]> jfr.im git - irc/quakenet/newserv.git/blob - newsearch/ns-gline.c
trusts: Don't check clone limits for ::.
[irc/quakenet/newserv.git] / newsearch / ns-gline.c
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 {
47 free(localdata);
48 parseError = "gline: invalid search type";
49 return NULL;
50 }
51
52 /* default duration, default reason */
53 if(argc == 0) {
54 localdata->duration = NSGLINE_DURATION;
55 strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason));
56 } else if(argc > 2) {
57 free(localdata);
58 parseError = "gline: invalid number of arguments";
59 return NULL;
60 } else {
61 char *argzerop, *reasonp, *durationp;
62 struct searchNode *durationsn, *reasonsn, *argzerosn;
63
64 if (!(argzerosn=argtoconststr("gline", ctx, argv[0], &argzerop))) {
65 free(localdata);
66 return NULL;
67 }
68
69 if(argc == 1) {
70 durationp = reasonp = NULL;
71 durationsn = reasonsn = NULL;
72
73 /* if we have a space it's a reason */
74 if(strchr(argzerop, ' ')) {
75 reasonsn = argzerosn;
76 reasonp = argzerop;
77 } else {
78 durationsn = argzerosn;
79 durationp = argzerop;
80 }
81 } else {
82 durationsn = argzerosn;
83 durationp = argzerop;
84
85 if (!(reasonsn=argtoconststr("gline", ctx, argv[1], &reasonp))) {
86 durationsn->free(ctx, durationsn);
87 free(localdata);
88 return NULL;
89 }
90 }
91
92 if(!reasonp) {
93 strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason));
94 } else {
95 strlcpy(localdata->reason, reasonp, sizeof(localdata->reason));
96 reasonsn->free(ctx, reasonsn);
97 }
98
99 if(!durationp) {
100 localdata->duration = NSGLINE_DURATION;
101 } else {
102 localdata->duration = durationtolong(durationp);
103 durationsn->free(ctx, durationsn);
104
105 if (localdata->duration == 0) {
106 parseError = "gline duration invalid.";
107 free(localdata);
108 return NULL;
109 }
110 }
111 }
112
113 if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
114 /* couldn't malloc() memory for thenode, so free localdata to avoid leakage */
115 parseError = "malloc: could not allocate memory for this search.";
116 free(localdata);
117 return NULL;
118 }
119
120 thenode->returntype = RETURNTYPE_BOOL;
121 thenode->localdata = localdata;
122 thenode->exe = gline_exe;
123 thenode->free = gline_free;
124
125 return thenode;
126 }
127
128 void *gline_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
129 struct gline_localdata *localdata;
130 nick *np;
131 chanindex *cip;
132
133 localdata = thenode->localdata;
134
135 if (ctx->searchcmd == reg_chansearch) {
136 cip = (chanindex *)theinput;
137 cip->marker = localdata->marker;
138 if (cip->channel != NULL)
139 localdata->count += cip->channel->users->totalusers;
140 }
141 else {
142 np = (nick *)theinput;
143 np->marker = localdata->marker;
144 localdata->count++;
145 }
146
147 return (void *)1;
148 }
149
150 static int glineuser(glinebuf *gbuf, nick *np, struct gline_localdata *localdata, time_t ti) {
151 char msgbuf[512];
152 if (!IsOper(np) && !IsService(np) && !IsXOper(np)) {
153 nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np);
154 glinebufaddbynick(gbuf, np, 0, "newsearch", msgbuf, getnettime() + localdata->duration, getnettime(), getnettime() + localdata->duration);
155 return 1;
156 }
157
158 return 0;
159 }
160
161 void gline_free(searchCtx *ctx, struct searchNode *thenode) {
162 struct gline_localdata *localdata;
163 nick *np, *nnp;
164 chanindex *cip, *ncip;
165 int i, j, hits, safe=0;
166 time_t ti = time(NULL);
167 glinebuf gbuf;
168
169 localdata = thenode->localdata;
170
171 if (localdata->count > NSMAX_GLINE_LIMIT) {
172 /* need to warn the user that they have just tried to twat half the network ... */
173 ctx->reply(senderNSExtern, "Warning: your pattern matches too many users (%d) - nothing done.", localdata->count);
174 free(localdata);
175 free(thenode);
176 return;
177 }
178
179 glinebufinit(&gbuf, 0);
180
181 if (ctx->searchcmd == reg_chansearch) {
182 for (i=0;i<CHANNELHASHSIZE;i++) {
183 for (cip=chantable[i];cip;cip=ncip) {
184 ncip = cip->next;
185 if (cip != NULL && cip->channel != NULL && cip->marker == localdata->marker) {
186 for (j=0;j<cip->channel->users->hashsize;j++) {
187 if (cip->channel->users->content[j]==nouser)
188 continue;
189
190 if ((np=getnickbynumeric(cip->channel->users->content[j]))) {
191 if(!glineuser(&gbuf, np, localdata, ti))
192 safe++;
193 }
194 }
195 }
196 }
197 }
198 }
199 else {
200 for (i=0;i<NICKHASHSIZE;i++) {
201 for (np=nicktable[i];np;np=nnp) {
202 nnp = np->next;
203 if (np->marker == localdata->marker) {
204 if(!glineuser(&gbuf, np, localdata, ti))
205 safe++;
206 }
207 }
208 }
209 }
210
211 glinebufcounthits(&gbuf, &hits, NULL);
212 glinebufcommit(&gbuf, 1);
213
214 if (safe)
215 ctx->reply(senderNSExtern, "Warning: your pattern matched privileged users (%d in total) - these have not been touched.", safe);
216 /* notify opers of the action */
217 ctx->wall(NL_GLINES, "%s/%s glined %d %s via %s for %s [%d untouched].", senderNSExtern->nick, senderNSExtern->authname, (localdata->count - safe),
218 (localdata->count - safe) != 1 ? "users" : "user", (ctx->searchcmd == reg_chansearch) ? "chansearch" : "nicksearch", longtoduration(localdata->duration, 1), safe);
219 free(localdata);
220 free(thenode);
221 }