fix possible crash on user deletion
[srvx.git] / patches / srvx-bantypes.diff
1 diff -upr srvx-1.2rc3/src/chanserv.c Services/src/chanserv.c
2 --- src/chanserv.c      Sat Jan  4 07:16:40 2003
3 +++ src/chanserv.c      Mon Jul  7 18:18:27 2003
4 @@ -419,6 +419,8 @@ dict_t note_types;
5  static dict_t sChannels;
6  static dict_t plain_dnrs, mask_dnrs, handle_dnrs;
7  
8 +extern const char *hidden_host_suffix;
9 +
10  static struct
11  {
12      struct chanNode    *debug_channel;
13 @@ -2859,12 +2861,103 @@ bad_channel_ban(struct chanNode *channel
14      return 0;
15  }
16  
17 +#define i_isdigit(x) isdigit((int) (unsigned char) (x))\r
18 +\r
19 +int is_ipv4_address(const char *host)\r
20 +{\r
21 +    while (*host != '\0') {\r
22 +       if (*host != '.' && !i_isdigit(*host))\r
23 +       return 0;\r
24 +       host++;\r
25 +    }\r
26 +    return 1;\r
27 +}\r
28 +\r
29 +static char *get_domain_mask(char *host)\r
30 +{\r
31 +    char *ptr;\r
32 +\r
33 +    if (strchr(host, '.') == NULL) {\r
34 +       /* no dots - toplevel domain or IPv6 address */\r
35 +       ptr = strrchr(host, ':');\r
36 +       if (ptr != NULL) {\r
37 +          /* IPv6 address, ban the last 64k addresses */\r
38 +          if (ptr[1] != '\0') strcpy(ptr+1, "*");\r
39 +       }\r
40 +       return host;\r
41 +    }\r
42 +\r
43 +    if (is_ipv4_address(host)) {\r
44 +       /* it's an IP address, change last digit to * */\r
45 +       ptr = strrchr(host, '.');\r
46 +       if (ptr != NULL && i_isdigit(ptr[1]))\r
47 +           strcpy(ptr+1, "*");\r
48 +    } else {\r
49 +       /* if more than one dot, skip the first\r
50 +          (dyn123.blah.net -> *.blah.net) */\r
51 +          ptr = strchr(host, '.');\r
52 +          if (ptr != NULL && strchr(ptr+1, '.') != NULL) {\r
53 +             host = ptr-1;\r
54 +             host[0] = '*';\r
55 +          }\r
56 +    }\r
57 +    return host;\r
58 +}\r
59 +\r
60 +char *generate_ban_hostmask(struct userNode *user, const char banopt)\r
61 +{\r
62 +    char *nickname, *ident = "*", *hostname, *mask, *usemask;\r
63 +    int len;\r
64 +\r
65 +    /* figure out string parts */\r
66 +    if(IsHiddenHost(user) && user->handle_info && hidden_host_suffix) {\r
67 +       usemask = alloca(strlen(user->handle_info->handle) + strlen(hidden_host_suffix) + 2);\r
68 +       sprintf(usemask, "%s.%s", user->handle_info->handle, hidden_host_suffix);\r
69 +    } \r
70 +    else {\r
71 +       usemask = user->hostname;\r
72 +    } \r
73 +\r
74 +    if((banopt == 'f') || (banopt == 'h') || (banopt == 'i') || (banopt == 'j')) {\r
75 +       nickname = user->nick;\r
76 +    }\r
77 +    else {\r
78 +       nickname = "*";\r
79 +    }\r
80 +\r
81 +    if((banopt == 'd') || (banopt == 'e') || (banopt == 'i') || (banopt == 'j')) {\r
82 +        hostname = get_domain_mask(usemask);\r
83 +    } \r
84 +    else {\r
85 +      hostname = usemask;\r
86 +    }\r
87 +\r
88 +    if((banopt == 'a') || (banopt == 'f')) {\r
89 +       ident = user->ident;\r
90 +    }\r
91 +    else if((banopt == 'b') || (banopt == 'd') || (banopt == 'i')) {\r
92 +        ident = malloc(strlen(user->ident)+1);\r
93 +        sprintf(ident, "*%s", user->ident);\r
94 +    }\r
95 +    else {\r
96 +        ident = "*";\r
97 +    }\r
98 +\r
99 +    /* Put it all together. */\r
100 +    len = strlen(ident) + strlen(hostname) + strlen(nickname) + 3;\r
101 +    mask = malloc(len);\r
102 +    sprintf(mask, "%s!%s@%s", nickname, ident, hostname);\r
103 +\r
104 +    return mask;\r
105 +}\r
106 +
107  static int
108  eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, unsigned char *argv[], struct svccmd *cmd, int action)
109  {
110      struct userNode *victim, **victims;
111      unsigned int offset, n, victimCount = 0, duration = 0, present;
112 -    char *reason = CSMSG_KICK_REASON, *ban, *name;
113 +    char *reason = CSMSG_KICK_REASON, *ban, *name, banopt;
114 +    struct chanData *cData;
115  
116      offset = (action & ACTION_ADD_TIMED_BAN) ? 3 : 2;
117      REQUIRE_PARAMS(offset); (void)cmd;
118 @@ -2910,7 +3003,19 @@ eject_user(struct userNode *user, struct
119         victims = &victim;
120         victimCount = 1;
121  
122 -       ban = generate_hostmask(victim, GENMASK_STRICT_HOST|GENMASK_ANY_IDENT);
123 +    if(!(cData = channel->channel_info)) \r
124 +    {\r
125 +       banopt = 'c';\r
126 +    }\r
127 +\r
128 +    if(!(cData->options[optBanType])) {\r
129 +       banopt = 'c';\r
130 +    }\r
131 +    else {\r
132 +       banopt = cData->options[optBanType];\r
133 +    }\r
134 +
135 +    ban = generate_ban_hostmask(victim, banopt);
136         name = victim->nick;
137      }
138      else
139 @@ -5507,6 +5612,30 @@ static CHANNEL_OPTION_FUNC(opt_topicrefr
140      CHANNEL_MULTIPLE_OPTION("TopicRefresh ", "topic refresh", optTopicRefresh, -1);
141  }
142  
143 +static CHANNEL_OPTION_FUNC(opt_bantype)\r
144 +{\r
145 +    struct chanData *cData = channel->channel_info;\r
146 +\r
147 +    struct valueData values[] =\r
148 +    {\r
149 +       {"*!user@host", 'a'},\r
150 +       {"*!*user@host", 'b'},\r
151 +       {"*!*@host", 'c'},\r
152 +       {"*!*user@*.host", 'd'},\r
153 +       {"*!*@*.host", 'e'},\r
154 +       {"nick!user@host", 'f'},\r
155 +       {"nick!*@host", 'h'},\r
156 +       {"nick!*user@*.host", 'i'},\r
157 +       {"nick!*@*.host", 'j'},\r
158 +    };\r
159 +\r
160 +    if(!(cData->options[optBanType])) {\r
161 +        cData->options[optBanType] = values[2].value;\r
162 +     }\r
163 +\r
164 +     CHANNEL_MULTIPLE_OPTION("BanType ", "bantype", optBanType, -1);\r
165 +}
166 +
167  static struct svccmd_list set_shows_list;
168  
169  static void
170 @@ -6538,6 +6667,7 @@ chanserv_conf_read(void)
171              "DefaultTopic", "TopicMask", "Greeting", "UserGreeting", "Modes",
172              "PubCmd", "StrictOp", "AutoOp", "EnfModes", "EnfTopic", "Protect",
173              "Toys", "Setters", "TopicRefresh", "CtcpUsers", "CtcpReaction",
174 +            "BanType",
175              /* binary options */
176              "Voice", "UserInfo", "DynLimit", "TopicSnarf", "PeonInvite", "NoDelete",
177              /* delimiter */
178 @@ -7320,6 +7450,7 @@ init_chanserv(const char *nick)
179      DEFINE_CHANNEL_OPTION(ctcpusers);
180      DEFINE_CHANNEL_OPTION(ctcpreaction);
181      DEFINE_CHANNEL_OPTION(peoninvite);
182 +    DEFINE_CHANNEL_OPTION(bantype);
183  
184      /* Alias set topic to set defaulttopic for compatibility. */
185      modcmd_register(chanserv_module, "set topic", chan_opt_defaulttopic, 1, 0, NULL);
186 diff -upr srvx-1.2rc3/src/chanserv.h Services/src/chanserv.h
187 --- src/chanserv.h      Mon Oct 21 04:34:58 2002
188 +++ src/chanserv.h      Mon Jul  7 18:16:21 2003
189 @@ -51,10 +51,11 @@ enum opt
190      optTopicRefresh,
191      optCTCPUsers,
192      optCTCPReaction,
193 -    optMax
194 +    optMax,
195 +    optBanType
196  };
197  
198 -#define OPTION_STRING_SIZE     (optMax + 2)
199 +#define OPTION_STRING_SIZE     (optBanType + 2)
200  #define FLAGS_STRING_LENGTH    5
201  
202  /* Flags are stored in base64, so a length of 5 gives us
203 @@ -76,7 +77,7 @@ enum opt
204     will not work because FLAGS_STRING_LENGTH is 5. */
205  
206  #define CHANNEL_DEFAULT_FLAGS  (CHANNEL_INFO_LINES)
207 -#define CHANNEL_DEFAULT_OPTIONS        "lmoooanpcnat"
208 +#define CHANNEL_DEFAULT_OPTIONS        "lmoooanpcnatc"
209  
210  #define IsProtected(x)         ((x)->flags & CHANNEL_NODELETE)
211  #define IsSuspended(x)         ((x)->flags & CHANNEL_SUSPENDED)
212 diff -upr srvx-1.2rc3/src/chanserv.help Services/src/chanserv.help
213 --- src/chanserv.help   Wed Jan  1 00:45:40 2003
214 +++ src/chanserv.help   Mon Jul  7 17:51:47 2003
215 @@ -322,6 +322,7 @@
216          "DYNLIMIT:     Adjusts user limit (+l channel mode) to prevent join floods.",
217          "TOPICSNARF:   Topics set manually (by /TOPIC #channel ...) change default $C topic",
218          "PEONINVITE:   Indicates whether peons may use the $bINVITEME$b command.",
219 +        "BANTYPE:      Indicated what type of ban $C will set will case of a ban command.",
220          "$bIRCOP ONLY$b:",
221          "NODELETE:  Prevents channel deletion.",
222          "$uSee Also:$u set pubcmd, set strictop, set autoop, set enfmodes, set enftopic, set protect, set toys, set setters, set topicrefresh, set ctcpusers, set ctcpreaction");
223 @@ -440,6 +441,17 @@
224          "$b2$b  Short timed ban (defaults to 3 minutes) on disallowed CTCPs.",
225          "$b3$b  Long timed ban (defaults to 1 hour) on disallowed CTCPs.",
226          "$uSee Also:$u set, set ctcpusers");
227 +"SET BANTYPE" ("/msg $C SET <#channel> BANTYPE <value>",\r
228 +        "This settings control what banmask $C sets upon a ban command. Valid settings are:",\r
229 +        "$b0$b *!user@host",\r
230 +        "$b1$b *!*user@host",\r
231 +        "$b2$b *!*@host",\r
232 +        "$b3$b *!*user@*.host",\r
233 +        "$b4$b *!*@*.host",\r
234 +        "$b5$b nick!user@host",\r
235 +        "$b6$b nick!*@host",\r
236 +        "$b7$b nick!*user@*.host",\r
237 +        "$b8$b nick!*@*.host");
238  "SETINFO" ("/msg $C SETINFO <#channel> <info>",
239          "This command will set a user defined information message to be displayed when you join the channel. By setting the message to '*', you will clear your message.",
240          "$uSee Also:$u access");