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