]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * GLINE functionality | |
3 | */ | |
4 | ||
5 | #include "newsearch.h" | |
6 | ||
7 | #include <stdio.h> | |
8 | #include <stdlib.h> | |
9 | #include <string.h> | |
10 | #include <stdint.h> | |
11 | ||
12 | #include "../control/control.h" | |
13 | #include "../irc/irc.h" /* irc_send() */ | |
14 | #include "../lib/irc_string.h" /* IPtostr(), longtoduration(), durationtolong() */ | |
15 | #include "../lib/strlfunc.h" | |
16 | #include "../glines/glines.h" | |
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 */ | |
20 | extern nick *senderNSExtern; | |
21 | static const char *defaultreason = "You (%u) have been g-lined for violating our terms of service"; | |
22 | ||
23 | void *gline_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput); | |
24 | void gline_free(searchCtx *ctx, struct searchNode *thenode); | |
25 | ||
26 | struct gline_localdata { | |
27 | unsigned int marker; | |
28 | unsigned int duration; | |
29 | int count; | |
30 | char reason[NSMAX_REASON_LEN]; | |
31 | }; | |
32 | ||
33 | struct searchNode *gline_parse(searchCtx *ctx, int argc, char **argv) { | |
34 | struct gline_localdata *localdata; | |
35 | struct searchNode *thenode; | |
36 | ||
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 | } | |
41 | localdata->count = 0; | |
42 | if (ctx->searchcmd == reg_chansearch) | |
43 | localdata->marker = nextchanmarker(); | |
44 | else if (ctx->searchcmd == reg_nicksearch) | |
45 | localdata->marker = nextnickmarker(); | |
46 | else if (ctx->searchcmd == reg_whowassearch) | |
47 | localdata->marker = nextwhowasmarker(); | |
48 | else { | |
49 | free(localdata); | |
50 | parseError = "gline: invalid search type"; | |
51 | return NULL; | |
52 | } | |
53 | ||
54 | /* default duration, default reason */ | |
55 | if(argc == 0) { | |
56 | localdata->duration = NSGLINE_DURATION; | |
57 | strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason)); | |
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 | } | |
70 | ||
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; | |
82 | } | |
83 | } else { | |
84 | durationsn = argzerosn; | |
85 | durationp = argzerop; | |
86 | ||
87 | if (!(reasonsn=argtoconststr("gline", ctx, argv[1], &reasonp))) { | |
88 | durationsn->free(ctx, durationsn); | |
89 | free(localdata); | |
90 | return NULL; | |
91 | } | |
92 | } | |
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); | |
99 | } | |
100 | ||
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 | } | |
112 | } | |
113 | } | |
114 | ||
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 | } | |
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 | ||
130 | void *gline_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) { | |
131 | struct gline_localdata *localdata; | |
132 | nick *np; | |
133 | chanindex *cip; | |
134 | whowas *ww; | |
135 | ||
136 | localdata = thenode->localdata; | |
137 | ||
138 | if (ctx->searchcmd == reg_chansearch) { | |
139 | cip = (chanindex *)theinput; | |
140 | cip->marker = localdata->marker; | |
141 | if (cip->channel != NULL) | |
142 | localdata->count += cip->channel->users->totalusers; | |
143 | } | |
144 | else { | |
145 | np = (nick *)theinput; | |
146 | if (ctx->searchcmd == reg_nicksearch) | |
147 | np->marker = localdata->marker; | |
148 | else { | |
149 | ww = (whowas *)np->next; | |
150 | ww->marker = localdata->marker; | |
151 | } | |
152 | localdata->count++; | |
153 | } | |
154 | ||
155 | return (void *)1; | |
156 | } | |
157 | ||
158 | static int glineuser(glinebuf *gbuf, nick *np, struct gline_localdata *localdata, time_t ti) { | |
159 | char msgbuf[512]; | |
160 | if (!IsOper(np) && !IsService(np) && !IsXOper(np)) { | |
161 | nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np); | |
162 | glinebufaddbynick(gbuf, np, 0, "newsearch", msgbuf, getnettime() + localdata->duration, getnettime(), getnettime() + localdata->duration); | |
163 | return 1; | |
164 | } | |
165 | ||
166 | return 0; | |
167 | } | |
168 | ||
169 | void gline_free(searchCtx *ctx, struct searchNode *thenode) { | |
170 | struct gline_localdata *localdata; | |
171 | nick *np, *nnp; | |
172 | chanindex *cip, *ncip; | |
173 | whowas *ww; | |
174 | int i, j, hits, safe=0; | |
175 | time_t ti = time(NULL); | |
176 | glinebuf gbuf; | |
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 ... */ | |
182 | ctx->reply(senderNSExtern, "Warning: your pattern matches too many users (%d) - nothing done.", localdata->count); | |
183 | free(localdata); | |
184 | free(thenode); | |
185 | return; | |
186 | } | |
187 | ||
188 | glinebufinit(&gbuf, 0); | |
189 | ||
190 | if (ctx->searchcmd == reg_chansearch) { | |
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]))) { | |
200 | if(!glineuser(&gbuf, np, localdata, ti)) | |
201 | safe++; | |
202 | } | |
203 | } | |
204 | } | |
205 | } | |
206 | } | |
207 | } else if (ctx->searchcmd == reg_nicksearch) { | |
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) { | |
212 | if(!glineuser(&gbuf, np, localdata, ti)) | |
213 | safe++; | |
214 | } | |
215 | } | |
216 | } | |
217 | } else { | |
218 | for (i = whowasoffset; i < whowasoffset + whowasmax; i++) { | |
219 | ww = &whowasrecs[i % whowasmax]; | |
220 | ||
221 | if (ww->type == WHOWAS_UNUSED) | |
222 | continue; | |
223 | ||
224 | if (ww->marker == localdata->marker) { | |
225 | if(!glineuser(&gbuf, &ww->nick, localdata, ti)) | |
226 | safe++; | |
227 | } | |
228 | } | |
229 | } | |
230 | ||
231 | glinebufcounthits(&gbuf, &hits, NULL); | |
232 | glinebufcommit(&gbuf, 1); | |
233 | ||
234 | if (safe) | |
235 | ctx->reply(senderNSExtern, "Warning: your pattern matched privileged users (%d in total) - these have not been touched.", safe); | |
236 | /* notify opers of the action */ | |
237 | ctx->wall(NL_GLINES, "%s/%s glined %d %s via %s for %s [%d untouched].", senderNSExtern->nick, senderNSExtern->authname, (localdata->count - safe), | |
238 | (localdata->count - safe) != 1 ? "users" : "user", (ctx->searchcmd == reg_chansearch) ? "chansearch" : "nicksearch", longtoduration(localdata->duration, 1), safe); | |
239 | free(localdata); | |
240 | free(thenode); | |
241 | } |