]>
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" |
324b4e11 | 16 | #include "../glines/glines.h" |
4278cc14 IB |
17 | |
18 | /* used for *_free functions that need to warn users of certain things | |
19 | i.e. hitting too many users in a (kill) or (gline) - declared in newsearch.c */ | |
219d27f1 | 20 | extern nick *senderNSExtern; |
2ba836f2 | 21 | static const char *defaultreason = "You (%u) have been g-lined for violating our terms of service"; |
4278cc14 | 22 | |
c8be5183 CP |
23 | void *gline_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput); |
24 | void gline_free(searchCtx *ctx, struct searchNode *thenode); | |
4278cc14 IB |
25 | |
26 | struct gline_localdata { | |
27 | unsigned int marker; | |
f16cabe4 | 28 | unsigned int duration; |
4278cc14 | 29 | int count; |
96429168 | 30 | char reason[NSMAX_REASON_LEN]; |
4278cc14 IB |
31 | }; |
32 | ||
f33f3f52 | 33 | struct searchNode *gline_parse(searchCtx *ctx, int argc, char **argv) { |
4278cc14 IB |
34 | struct gline_localdata *localdata; |
35 | struct searchNode *thenode; | |
36 | ||
9ce4f0be IB |
37 | if (!(localdata = (struct gline_localdata *) malloc(sizeof(struct gline_localdata)))) { |
38 | parseError = "malloc: could not allocate memory for this search."; | |
39 | return NULL; | |
40 | } | |
4278cc14 | 41 | localdata->count = 0; |
a92bb8e1 | 42 | if (ctx->searchcmd == reg_chansearch) |
8e257015 | 43 | localdata->marker = nextchanmarker(); |
a92bb8e1 | 44 | else if (ctx->searchcmd == reg_nicksearch) |
8e257015 | 45 | localdata->marker = nextnickmarker(); |
0eb4cbd3 GB |
46 | else if (ctx->searchcmd == reg_whowassearch) |
47 | localdata->marker = nextwhowasmarker(); | |
a92bb8e1 | 48 | else { |
31686847 | 49 | free(localdata); |
a92bb8e1 P |
50 | parseError = "gline: invalid search type"; |
51 | return NULL; | |
52 | } | |
4278cc14 | 53 | |
31686847 CP |
54 | /* default duration, default reason */ |
55 | if(argc == 0) { | |
f16cabe4 | 56 | localdata->duration = NSGLINE_DURATION; |
2ba836f2 | 57 | strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason)); |
31686847 CP |
58 | } else if(argc > 2) { |
59 | free(localdata); | |
60 | parseError = "gline: invalid number of arguments"; | |
61 | return NULL; | |
62 | } else { | |
63 | char *argzerop, *reasonp, *durationp; | |
64 | struct searchNode *durationsn, *reasonsn, *argzerosn; | |
65 | ||
66 | if (!(argzerosn=argtoconststr("gline", ctx, argv[0], &argzerop))) { | |
67 | free(localdata); | |
68 | return NULL; | |
69 | } | |
96429168 | 70 | |
31686847 CP |
71 | if(argc == 1) { |
72 | durationp = reasonp = NULL; | |
73 | durationsn = reasonsn = NULL; | |
74 | ||
75 | /* if we have a space it's a reason */ | |
76 | if(strchr(argzerop, ' ')) { | |
77 | reasonsn = argzerosn; | |
78 | reasonp = argzerop; | |
79 | } else { | |
80 | durationsn = argzerosn; | |
81 | durationp = argzerop; | |
90323e03 | 82 | } |
31686847 CP |
83 | } else { |
84 | durationsn = argzerosn; | |
85 | durationp = argzerop; | |
90323e03 | 86 | |
31686847 CP |
87 | if (!(reasonsn=argtoconststr("gline", ctx, argv[1], &reasonp))) { |
88 | durationsn->free(ctx, durationsn); | |
89 | free(localdata); | |
90 | return NULL; | |
91 | } | |
96429168 | 92 | } |
31686847 CP |
93 | |
94 | if(!reasonp) { | |
95 | strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason)); | |
96 | } else { | |
97 | strlcpy(localdata->reason, reasonp, sizeof(localdata->reason)); | |
98 | reasonsn->free(ctx, reasonsn); | |
96429168 | 99 | } |
96429168 | 100 | |
31686847 CP |
101 | if(!durationp) { |
102 | localdata->duration = NSGLINE_DURATION; | |
103 | } else { | |
104 | localdata->duration = durationtolong(durationp); | |
105 | durationsn->free(ctx, durationsn); | |
106 | ||
107 | if (localdata->duration == 0) { | |
108 | parseError = "gline duration invalid."; | |
109 | free(localdata); | |
110 | return NULL; | |
111 | } | |
2ba836f2 | 112 | } |
f16cabe4 IB |
113 | } |
114 | ||
9ce4f0be IB |
115 | if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) { |
116 | /* couldn't malloc() memory for thenode, so free localdata to avoid leakage */ | |
117 | parseError = "malloc: could not allocate memory for this search."; | |
118 | free(localdata); | |
119 | return NULL; | |
120 | } | |
4278cc14 IB |
121 | |
122 | thenode->returntype = RETURNTYPE_BOOL; | |
123 | thenode->localdata = localdata; | |
124 | thenode->exe = gline_exe; | |
125 | thenode->free = gline_free; | |
126 | ||
127 | return thenode; | |
128 | } | |
129 | ||
c8be5183 | 130 | void *gline_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) { |
4278cc14 | 131 | struct gline_localdata *localdata; |
8e257015 IB |
132 | nick *np; |
133 | chanindex *cip; | |
0eb4cbd3 | 134 | whowas *ww; |
4278cc14 IB |
135 | |
136 | localdata = thenode->localdata; | |
137 | ||
a92bb8e1 | 138 | if (ctx->searchcmd == reg_chansearch) { |
8e257015 IB |
139 | cip = (chanindex *)theinput; |
140 | cip->marker = localdata->marker; | |
0371d169 GB |
141 | if (cip->channel != NULL) |
142 | localdata->count += cip->channel->users->totalusers; | |
8e257015 IB |
143 | } |
144 | else { | |
145 | np = (nick *)theinput; | |
0eb4cbd3 GB |
146 | if (ctx->searchcmd == reg_nicksearch) |
147 | np->marker = localdata->marker; | |
148 | else { | |
0495c1d1 | 149 | ww = (whowas *)np->next; |
0eb4cbd3 GB |
150 | ww->marker = localdata->marker; |
151 | } | |
8e257015 IB |
152 | localdata->count++; |
153 | } | |
4278cc14 | 154 | |
c7f7a584 | 155 | return (void *)1; |
4278cc14 IB |
156 | } |
157 | ||
324b4e11 | 158 | static int glineuser(glinebuf *gbuf, nick *np, struct gline_localdata *localdata, time_t ti) { |
90323e03 CP |
159 | char msgbuf[512]; |
160 | if (!IsOper(np) && !IsService(np) && !IsXOper(np)) { | |
161 | nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np); | |
324b4e11 | 162 | glinebufaddbynick(gbuf, np, 0, "newsearch", msgbuf, getnettime() + localdata->duration, getnettime(), getnettime() + localdata->duration); |
90323e03 CP |
163 | return 1; |
164 | } | |
165 | ||
166 | return 0; | |
167 | } | |
168 | ||
c8be5183 | 169 | void gline_free(searchCtx *ctx, struct searchNode *thenode) { |
4278cc14 IB |
170 | struct gline_localdata *localdata; |
171 | nick *np, *nnp; | |
8e257015 | 172 | chanindex *cip, *ncip; |
0eb4cbd3 | 173 | whowas *ww; |
324b4e11 | 174 | int i, j, hits, safe=0; |
aace33dc | 175 | time_t ti = time(NULL); |
324b4e11 | 176 | glinebuf gbuf; |
4278cc14 IB |
177 | |
178 | localdata = thenode->localdata; | |
179 | ||
180 | if (localdata->count > NSMAX_GLINE_LIMIT) { | |
181 | /* need to warn the user that they have just tried to twat half the network ... */ | |
0da2a4ae | 182 | ctx->reply(senderNSExtern, "Warning: your pattern matches too many users (%d) - nothing done.", localdata->count); |
4278cc14 IB |
183 | free(localdata); |
184 | free(thenode); | |
185 | return; | |
186 | } | |
187 | ||
324b4e11 GB |
188 | glinebufinit(&gbuf, 0); |
189 | ||
a92bb8e1 | 190 | if (ctx->searchcmd == reg_chansearch) { |
8e257015 IB |
191 | for (i=0;i<CHANNELHASHSIZE;i++) { |
192 | for (cip=chantable[i];cip;cip=ncip) { | |
193 | ncip = cip->next; | |
194 | if (cip != NULL && cip->channel != NULL && cip->marker == localdata->marker) { | |
195 | for (j=0;j<cip->channel->users->hashsize;j++) { | |
196 | if (cip->channel->users->content[j]==nouser) | |
197 | continue; | |
198 | ||
199 | if ((np=getnickbynumeric(cip->channel->users->content[j]))) { | |
324b4e11 | 200 | if(!glineuser(&gbuf, np, localdata, ti)) |
2ba836f2 | 201 | safe++; |
8e257015 IB |
202 | } |
203 | } | |
204 | } | |
205 | } | |
206 | } | |
0eb4cbd3 | 207 | } else if (ctx->searchcmd == reg_nicksearch) { |
8e257015 IB |
208 | for (i=0;i<NICKHASHSIZE;i++) { |
209 | for (np=nicktable[i];np;np=nnp) { | |
210 | nnp = np->next; | |
211 | if (np->marker == localdata->marker) { | |
324b4e11 | 212 | if(!glineuser(&gbuf, np, localdata, ti)) |
90323e03 | 213 | safe++; |
4278cc14 | 214 | } |
4278cc14 IB |
215 | } |
216 | } | |
0eb4cbd3 | 217 | } else { |
0495c1d1 GB |
218 | for (i = whowasoffset; i < whowasoffset + WW_MAXENTRIES; i++) { |
219 | ww = &whowasrecs[i % WW_MAXENTRIES]; | |
220 | ||
221 | if (ww->type == WHOWAS_UNUSED) | |
222 | continue; | |
223 | ||
0eb4cbd3 | 224 | if (ww->marker == localdata->marker) { |
0495c1d1 | 225 | if(!glineuser(&gbuf, &ww->nick, localdata, ti)) |
0eb4cbd3 GB |
226 | safe++; |
227 | } | |
228 | } | |
4278cc14 | 229 | } |
324b4e11 | 230 | |
33e09c2c | 231 | glinebufcounthits(&gbuf, &hits, NULL); |
324b4e11 GB |
232 | glinebufcommit(&gbuf, 1); |
233 | ||
4278cc14 | 234 | if (safe) |
0da2a4ae | 235 | ctx->reply(senderNSExtern, "Warning: your pattern matched privileged users (%d in total) - these have not been touched.", safe); |
f16cabe4 | 236 | /* notify opers of the action */ |
0da2a4ae | 237 | ctx->wall(NL_GLINES, "%s/%s glined %d %s via %s for %s [%d untouched].", senderNSExtern->nick, senderNSExtern->authname, (localdata->count - safe), |
a92bb8e1 | 238 | (localdata->count - safe) != 1 ? "users" : "user", (ctx->searchcmd == reg_chansearch) ? "chansearch" : "nicksearch", longtoduration(localdata->duration, 1), safe); |
4278cc14 IB |
239 | free(localdata); |
240 | free(thenode); | |
241 | } |