]>
Commit | Line | Data |
---|---|---|
4278cc14 IB |
1 | /* |
2 | * GLINE functionality | |
3 | */ | |
4 | ||
5 | #include "newsearch.h" | |
6 | ||
7 | #include <stdio.h> | |
8 | #include <stdlib.h> | |
96429168 | 9 | #include <string.h> |
8bab42e7 | 10 | #include <stdint.h> |
4278cc14 | 11 | |
0da2a4ae | 12 | #include "../control/control.h" |
4278cc14 | 13 | #include "../irc/irc.h" /* irc_send() */ |
f16cabe4 | 14 | #include "../lib/irc_string.h" /* IPtostr(), longtoduration(), durationtolong() */ |
2ba836f2 | 15 | #include "../lib/strlfunc.h" |
f22229e9 | 16 | #include "../core/schedule.h" |
324b4e11 | 17 | #include "../glines/glines.h" |
4278cc14 IB |
18 | |
19 | /* used for *_free functions that need to warn users of certain things | |
20 | i.e. hitting too many users in a (kill) or (gline) - declared in newsearch.c */ | |
219d27f1 | 21 | extern nick *senderNSExtern; |
2ba836f2 | 22 | static const char *defaultreason = "You (%u) have been g-lined for violating our terms of service"; |
f22229e9 GB |
23 | static int defaultmindelay = 15; |
24 | static int defaultvariance = 15; | |
4278cc14 | 25 | |
c8be5183 CP |
26 | void *gline_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput); |
27 | void gline_free(searchCtx *ctx, struct searchNode *thenode); | |
4278cc14 IB |
28 | |
29 | struct gline_localdata { | |
30 | unsigned int marker; | |
f16cabe4 | 31 | unsigned int duration; |
4278cc14 | 32 | int count; |
96429168 | 33 | char reason[NSMAX_REASON_LEN]; |
f22229e9 GB |
34 | int mindelay; |
35 | int maxdelay; | |
4278cc14 IB |
36 | }; |
37 | ||
f22229e9 | 38 | struct searchNode *common_gline_parse(searchCtx *ctx, int argc, char **argv, int withdelay) { |
4278cc14 IB |
39 | struct gline_localdata *localdata; |
40 | struct searchNode *thenode; | |
41 | ||
9ce4f0be IB |
42 | if (!(localdata = (struct gline_localdata *) malloc(sizeof(struct gline_localdata)))) { |
43 | parseError = "malloc: could not allocate memory for this search."; | |
44 | return NULL; | |
45 | } | |
4278cc14 | 46 | localdata->count = 0; |
a92bb8e1 | 47 | if (ctx->searchcmd == reg_chansearch) |
8e257015 | 48 | localdata->marker = nextchanmarker(); |
a92bb8e1 | 49 | else if (ctx->searchcmd == reg_nicksearch) |
8e257015 | 50 | localdata->marker = nextnickmarker(); |
0eb4cbd3 GB |
51 | else if (ctx->searchcmd == reg_whowassearch) |
52 | localdata->marker = nextwhowasmarker(); | |
a92bb8e1 | 53 | else { |
31686847 | 54 | free(localdata); |
a92bb8e1 P |
55 | parseError = "gline: invalid search type"; |
56 | return NULL; | |
57 | } | |
4278cc14 | 58 | |
31686847 CP |
59 | /* default duration, default reason */ |
60 | if(argc == 0) { | |
f16cabe4 | 61 | localdata->duration = NSGLINE_DURATION; |
2ba836f2 | 62 | strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason)); |
f22229e9 | 63 | } else if(argc > (withdelay ? 4 : 2)) { |
31686847 CP |
64 | free(localdata); |
65 | parseError = "gline: invalid number of arguments"; | |
66 | return NULL; | |
67 | } else { | |
f22229e9 GB |
68 | char *argzerop, *reasonp, *durationp, *mindelayp, *maxdelayp; |
69 | struct searchNode *durationsn, *reasonsn, *mindelaysn, *maxdelaysn, *argzerosn; | |
31686847 CP |
70 | |
71 | if (!(argzerosn=argtoconststr("gline", ctx, argv[0], &argzerop))) { | |
72 | free(localdata); | |
73 | return NULL; | |
74 | } | |
96429168 | 75 | |
31686847 | 76 | if(argc == 1) { |
f22229e9 GB |
77 | durationp = reasonp = mindelayp = maxdelayp = NULL; |
78 | durationsn = reasonsn = mindelaysn = maxdelaysn = NULL; | |
31686847 CP |
79 | |
80 | /* if we have a space it's a reason */ | |
81 | if(strchr(argzerop, ' ')) { | |
82 | reasonsn = argzerosn; | |
83 | reasonp = argzerop; | |
84 | } else { | |
85 | durationsn = argzerosn; | |
86 | durationp = argzerop; | |
90323e03 | 87 | } |
31686847 CP |
88 | } else { |
89 | durationsn = argzerosn; | |
90 | durationp = argzerop; | |
90323e03 | 91 | |
31686847 CP |
92 | if (!(reasonsn=argtoconststr("gline", ctx, argv[1], &reasonp))) { |
93 | durationsn->free(ctx, durationsn); | |
94 | free(localdata); | |
95 | return NULL; | |
f22229e9 GB |
96 | } |
97 | ||
98 | if (withdelay) { | |
99 | mindelayp = maxdelayp = NULL; | |
100 | mindelaysn = maxdelaysn = NULL; | |
101 | ||
102 | if (argc > 2 && !(mindelaysn=argtoconststr("gline", ctx, argv[2], &mindelayp))) { | |
103 | mindelaysn->free(ctx, mindelaysn); | |
104 | free(localdata); | |
105 | return NULL; | |
106 | } | |
107 | ||
108 | if (argc > 3 && !(maxdelaysn=argtoconststr("gline", ctx, argv[3], &maxdelayp))) { | |
109 | maxdelaysn->free(ctx, maxdelaysn); | |
110 | free(localdata); | |
111 | return NULL; | |
112 | } | |
113 | } | |
96429168 | 114 | } |
31686847 CP |
115 | |
116 | if(!reasonp) { | |
117 | strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason)); | |
118 | } else { | |
119 | strlcpy(localdata->reason, reasonp, sizeof(localdata->reason)); | |
120 | reasonsn->free(ctx, reasonsn); | |
96429168 | 121 | } |
96429168 | 122 | |
31686847 CP |
123 | if(!durationp) { |
124 | localdata->duration = NSGLINE_DURATION; | |
125 | } else { | |
126 | localdata->duration = durationtolong(durationp); | |
127 | durationsn->free(ctx, durationsn); | |
128 | ||
129 | if (localdata->duration == 0) { | |
130 | parseError = "gline duration invalid."; | |
131 | free(localdata); | |
132 | return NULL; | |
133 | } | |
2ba836f2 | 134 | } |
f22229e9 GB |
135 | |
136 | if (withdelay) { | |
137 | if(!mindelayp) { | |
138 | localdata->mindelay = defaultmindelay; | |
139 | } else { | |
140 | localdata->mindelay = durationtolong(mindelayp); | |
141 | mindelaysn->free(ctx, mindelaysn); | |
142 | ||
143 | if (localdata->mindelay == 0) { | |
144 | parseError = "gline mindelay invalid."; | |
145 | free(localdata); | |
146 | return NULL; | |
147 | } | |
148 | } | |
149 | ||
150 | if(!maxdelayp) { | |
151 | localdata->maxdelay = localdata->mindelay + defaultvariance; | |
152 | } else { | |
153 | localdata->maxdelay = durationtolong(maxdelayp); | |
154 | maxdelaysn->free(ctx, maxdelaysn); | |
155 | ||
156 | if (localdata->maxdelay == 0) { | |
157 | parseError = "gline maxdelay invalid."; | |
158 | free(localdata); | |
159 | return NULL; | |
160 | } | |
161 | } | |
162 | } else { | |
163 | localdata->mindelay = 0; | |
164 | localdata->maxdelay = 0; | |
165 | } | |
166 | ||
167 | if (localdata->mindelay < 0 || localdata->maxdelay < localdata->mindelay) { | |
168 | parseError = "gline delay invalid."; | |
169 | free(localdata); | |
170 | return NULL; | |
171 | } | |
f16cabe4 IB |
172 | } |
173 | ||
9ce4f0be IB |
174 | if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) { |
175 | /* couldn't malloc() memory for thenode, so free localdata to avoid leakage */ | |
176 | parseError = "malloc: could not allocate memory for this search."; | |
177 | free(localdata); | |
178 | return NULL; | |
179 | } | |
4278cc14 IB |
180 | |
181 | thenode->returntype = RETURNTYPE_BOOL; | |
182 | thenode->localdata = localdata; | |
183 | thenode->exe = gline_exe; | |
184 | thenode->free = gline_free; | |
185 | ||
186 | return thenode; | |
187 | } | |
188 | ||
f22229e9 GB |
189 | struct searchNode *gline_parse(searchCtx *ctx, int argc, char **argv) { |
190 | return common_gline_parse(ctx, argc, argv, 0); | |
191 | } | |
192 | ||
193 | struct searchNode *delaygline_parse(searchCtx *ctx, int argc, char **argv) { | |
194 | return common_gline_parse(ctx, argc, argv, 1); | |
195 | } | |
196 | ||
c8be5183 | 197 | void *gline_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) { |
4278cc14 | 198 | struct gline_localdata *localdata; |
8e257015 IB |
199 | nick *np; |
200 | chanindex *cip; | |
0eb4cbd3 | 201 | whowas *ww; |
4278cc14 IB |
202 | |
203 | localdata = thenode->localdata; | |
204 | ||
a92bb8e1 | 205 | if (ctx->searchcmd == reg_chansearch) { |
8e257015 IB |
206 | cip = (chanindex *)theinput; |
207 | cip->marker = localdata->marker; | |
0371d169 GB |
208 | if (cip->channel != NULL) |
209 | localdata->count += cip->channel->users->totalusers; | |
8e257015 IB |
210 | } |
211 | else { | |
212 | np = (nick *)theinput; | |
0eb4cbd3 GB |
213 | if (ctx->searchcmd == reg_nicksearch) |
214 | np->marker = localdata->marker; | |
215 | else { | |
0495c1d1 | 216 | ww = (whowas *)np->next; |
0eb4cbd3 GB |
217 | ww->marker = localdata->marker; |
218 | } | |
8e257015 IB |
219 | localdata->count++; |
220 | } | |
4278cc14 | 221 | |
c7f7a584 | 222 | return (void *)1; |
4278cc14 IB |
223 | } |
224 | ||
324b4e11 | 225 | static int glineuser(glinebuf *gbuf, nick *np, struct gline_localdata *localdata, time_t ti) { |
90323e03 CP |
226 | char msgbuf[512]; |
227 | if (!IsOper(np) && !IsService(np) && !IsXOper(np)) { | |
228 | nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np); | |
324b4e11 | 229 | glinebufaddbynick(gbuf, np, 0, "newsearch", msgbuf, getnettime() + localdata->duration, getnettime(), getnettime() + localdata->duration); |
90323e03 CP |
230 | return 1; |
231 | } | |
232 | ||
233 | return 0; | |
234 | } | |
235 | ||
f22229e9 GB |
236 | static void commitglines(void *arg) { |
237 | glinebuf *gbuf = (glinebuf *)arg; | |
238 | glinebufcommit(gbuf, 1); | |
239 | free(gbuf); | |
240 | } | |
241 | ||
c8be5183 | 242 | void gline_free(searchCtx *ctx, struct searchNode *thenode) { |
4278cc14 IB |
243 | struct gline_localdata *localdata; |
244 | nick *np, *nnp; | |
8e257015 | 245 | chanindex *cip, *ncip; |
0eb4cbd3 | 246 | whowas *ww; |
f22229e9 | 247 | int i, j, hits, safe=0, delay; |
aace33dc | 248 | time_t ti = time(NULL); |
f22229e9 | 249 | glinebuf *gbuf; |
4278cc14 IB |
250 | |
251 | localdata = thenode->localdata; | |
252 | ||
253 | if (localdata->count > NSMAX_GLINE_LIMIT) { | |
254 | /* need to warn the user that they have just tried to twat half the network ... */ | |
0da2a4ae | 255 | ctx->reply(senderNSExtern, "Warning: your pattern matches too many users (%d) - nothing done.", localdata->count); |
4278cc14 IB |
256 | free(localdata); |
257 | free(thenode); | |
258 | return; | |
259 | } | |
260 | ||
f22229e9 GB |
261 | gbuf = malloc(sizeof(glinebuf)); |
262 | glinebufinit(gbuf, 0); | |
324b4e11 | 263 | |
a92bb8e1 | 264 | if (ctx->searchcmd == reg_chansearch) { |
8e257015 IB |
265 | for (i=0;i<CHANNELHASHSIZE;i++) { |
266 | for (cip=chantable[i];cip;cip=ncip) { | |
267 | ncip = cip->next; | |
268 | if (cip != NULL && cip->channel != NULL && cip->marker == localdata->marker) { | |
269 | for (j=0;j<cip->channel->users->hashsize;j++) { | |
270 | if (cip->channel->users->content[j]==nouser) | |
271 | continue; | |
272 | ||
273 | if ((np=getnickbynumeric(cip->channel->users->content[j]))) { | |
f22229e9 | 274 | if(!glineuser(gbuf, np, localdata, ti)) |
2ba836f2 | 275 | safe++; |
8e257015 IB |
276 | } |
277 | } | |
278 | } | |
279 | } | |
280 | } | |
0eb4cbd3 | 281 | } else if (ctx->searchcmd == reg_nicksearch) { |
8e257015 IB |
282 | for (i=0;i<NICKHASHSIZE;i++) { |
283 | for (np=nicktable[i];np;np=nnp) { | |
284 | nnp = np->next; | |
285 | if (np->marker == localdata->marker) { | |
f22229e9 | 286 | if(!glineuser(gbuf, np, localdata, ti)) |
90323e03 | 287 | safe++; |
4278cc14 | 288 | } |
4278cc14 IB |
289 | } |
290 | } | |
0eb4cbd3 | 291 | } else { |
291fdf5f CP |
292 | for (i = whowasoffset; i < whowasoffset + whowasmax; i++) { |
293 | ww = &whowasrecs[i % whowasmax]; | |
0495c1d1 GB |
294 | |
295 | if (ww->type == WHOWAS_UNUSED) | |
296 | continue; | |
297 | ||
0eb4cbd3 | 298 | if (ww->marker == localdata->marker) { |
f22229e9 | 299 | if(!glineuser(gbuf, &ww->nick, localdata, ti)) |
0eb4cbd3 GB |
300 | safe++; |
301 | } | |
302 | } | |
4278cc14 | 303 | } |
324b4e11 | 304 | |
f22229e9 GB |
305 | glinebufcounthits(gbuf, &hits, NULL); |
306 | ||
307 | delay = (rand() % (localdata->maxdelay + 1 - localdata->mindelay)) + localdata->mindelay; | |
308 | ||
309 | if (delay > 0) { | |
310 | scheduleoneshot(time(NULL) + delay, commitglines, gbuf); | |
311 | } else { | |
312 | commitglines(gbuf); | |
313 | } | |
324b4e11 | 314 | |
4278cc14 | 315 | if (safe) |
0da2a4ae | 316 | ctx->reply(senderNSExtern, "Warning: your pattern matched privileged users (%d in total) - these have not been touched.", safe); |
f16cabe4 | 317 | /* notify opers of the action */ |
0da2a4ae | 318 | ctx->wall(NL_GLINES, "%s/%s glined %d %s via %s for %s [%d untouched].", senderNSExtern->nick, senderNSExtern->authname, (localdata->count - safe), |
a92bb8e1 | 319 | (localdata->count - safe) != 1 ? "users" : "user", (ctx->searchcmd == reg_chansearch) ? "chansearch" : "nicksearch", longtoduration(localdata->duration, 1), safe); |
4278cc14 IB |
320 | free(localdata); |
321 | free(thenode); | |
322 | } |