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