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