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