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