]> jfr.im git - irc/quakenet/newserv.git/blob - newsearch/ns-kill.c
2c8a059ec1b1cb1c968dfef381b0697f1b6de846
[irc/quakenet/newserv.git] / newsearch / ns-kill.c
1 /*
2 * KILL functionality
3 */
4
5 #include "newsearch.h"
6
7 #include <stdio.h>
8 #include <stdlib.h>
9
10 #include "../control/control.h"
11 #include "../localuser/localuser.h" /* killuser() */
12 #include "../lib/irc_string.h" /* IPtostr() */
13 #include "../lib/strlfunc.h"
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 *kill_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
20 void kill_free(searchCtx *ctx, struct searchNode *thenode);
21 static const char *defaultreason = "You (%n) have been disconnected for violating our terms of service";
22
23 struct kill_localdata {
24 unsigned int marker;
25 int count;
26 int type;
27 char reason[NSMAX_REASON_LEN];
28 };
29
30 struct searchNode *kill_parse(searchCtx *ctx, int type, int argc, char **argv) {
31 struct kill_localdata *localdata;
32 struct searchNode *thenode;
33 int len;
34
35 if (!(localdata = (struct kill_localdata *) malloc(sizeof(struct kill_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 if (argc==1) {
47 char *p = argv[0];
48 if(*p == '\"')
49 p++;
50 len = strlcpy(localdata->reason, p, sizeof(localdata->reason));
51 if(len >= sizeof(localdata->reason)) {
52 localdata->reason[sizeof(localdata->reason)-1] = '\0';
53 } else {
54 localdata->reason[len-1] = '\0';
55 }
56 }
57 else
58 strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason));
59
60 if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
61 /* couldn't malloc() memory for thenode, so free localdata to avoid leakage */
62 parseError = "malloc: could not allocate memory for this search.";
63 free(localdata);
64 return NULL;
65 }
66
67 thenode->returntype = RETURNTYPE_BOOL;
68 thenode->localdata = localdata;
69 thenode->exe = kill_exe;
70 thenode->free = kill_free;
71
72 return thenode;
73 }
74
75 void *kill_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
76 struct kill_localdata *localdata;
77 nick *np;
78 chanindex *cip;
79
80 localdata = thenode->localdata;
81
82 if (localdata->type == SEARCHTYPE_CHANNEL) {
83 cip = (chanindex *)theinput;
84 cip->marker = localdata->marker;
85 localdata->count += cip->channel->users->totalusers;
86 }
87 else {
88 np = (nick *)theinput;
89 np->marker = localdata->marker;
90 localdata->count++;
91 }
92
93 return (void *)1;
94 }
95
96 void kill_free(searchCtx *ctx, struct searchNode *thenode) {
97 struct kill_localdata *localdata;
98 nick *np, *nnp;
99 chanindex *cip;
100 int i, j, safe=0;
101 unsigned int nickmarker;
102 char msgbuf[512];
103
104 localdata = thenode->localdata;
105
106 if (localdata->count > NSMAX_KILL_LIMIT) {
107 /* need to warn the user that they have just tried to twat half the network ... */
108 ctx->reply(senderNSExtern, "Warning: your pattern matches too many users (%d) - nothing done.", localdata->count);
109 free(localdata);
110 free(thenode);
111 return;
112 }
113
114 /* For channel searches, mark up all the nicks in the relevant channels first */
115 if (localdata->type == SEARCHTYPE_CHANNEL) {
116 nickmarker=nextnickmarker();
117 for (i=0;i<CHANNELHASHSIZE;i++) {
118 for (cip=chantable[i];cip;cip=cip->next) {
119 /* Skip empty and non-matching channels */
120 if (!cip->channel || cip->marker != localdata->marker)
121 continue;
122
123 for (j=0;j<cip->channel->users->hashsize;j++) {
124 if (cip->channel->users->content[j]==nouser)
125 continue;
126
127 if ((np=getnickbynumeric(cip->channel->users->content[j])))
128 np->marker=nickmarker;
129 }
130 }
131 }
132 } else {
133 /* For nick searches they're already marked, pick up the saved value */
134 nickmarker=localdata->marker;
135 }
136
137 /* Now do the actual kills */
138 for (i=0;i<NICKHASHSIZE;i++) {
139 for (np=nicktable[i];np;np=nnp) {
140 nnp = np->next;
141
142 if (np->marker != nickmarker)
143 continue;
144
145 if (IsOper(np) || IsService(np) || IsXOper(np)) {
146 safe++;
147 continue;
148 }
149
150 nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np);
151 killuser(NULL, np, "%s", msgbuf);
152 }
153 }
154
155 if (safe)
156 ctx->reply(senderNSExtern, "Warning: your pattern matched privileged users (%d in total) - these have not been touched.", safe);
157 /* notify opers of the action */
158 ctx->wall(NL_KICKKILLS, "%s/%s killed %d %s via %s [%d untouched].", senderNSExtern->nick, senderNSExtern->authname, (localdata->count - safe),
159 (localdata->count - safe) != 1 ? "users" : "user", (localdata->type == SEARCHTYPE_CHANNEL) ? "chansearch" : "nicksearch", safe);
160 free(localdata);
161 free(thenode);
162 }