]> jfr.im git - irc/quakenet/newserv.git/blame - versionscan/versionscan.c
Get rid of ALL WARNINGS!
[irc/quakenet/newserv.git] / versionscan / versionscan.c
CommitLineData
4ad1cf7a
CP
1#include "versionscan.h"
2
3CommandTree* versionscan_commands;
4nick* versionscan_nick;
5int versionscannext;
6int versionscan_mode;
7vspattern* vspatterns;
8vsauthdata* vsauths;
9vsstatistic* vsstats;
10unsigned long hcount=0;
11unsigned long wcount=0;
12unsigned long kcount=0;
13unsigned long gcount=0;
14
15//sendnoticetouser(versionscan_nick, np, "");
16
17void versionscan_addstat(char* reply) {
18 vsstatistic* v, *pv;
19
20 pv=0;
21 for (v=vsstats; v; v=v->next) {
22 if (!ircd_strcmp(v->reply, reply)) {
23 v->count++;
24 return;
25 }
26 pv=v;
27 }
28 if (!pv) {
29 vsstats=(vsstatistic*)malloc(sizeof(vsstatistic));
30 vsstats->reply=(char*)malloc(strlen(reply)+1);
31 strcpy(vsstats->reply, reply);
32 vsstats->count=1;
33 vsstats->next=0;
34 }
35 else {
36 pv->next=(vsstatistic*)malloc(sizeof(vsstatistic));
37 pv->next->reply=(char*)malloc(strlen(reply)+1);
38 strcpy(pv->next->reply, reply);
39 pv->next->count=1;
40 pv->next->next=0;
41 }
42}
43
44unsigned char versionscan_getlevelbyauth(char* auth) {
45 vsauthdata* v;
46
47 for (v=vsauths; v; v=v->next) {
48 if (!ircd_strcmp(v->account, auth)) {
49 return v->flags;
50 }
51 }
52 return 0;
53}
54
55vsauthdata* versionscan_getauthbyauth(char* auth) {
56 vsauthdata* v;
57
58 for (v=vsauths; v; v=v->next) {
59 if (!ircd_strcmp(v->account, auth)) {
60 return v;
61 }
62 }
63 return 0;
64}
65
66int IsVersionscanStaff(nick* np) {
67 unsigned char level;
68
69 if (!IsAccount(np)) {
70 return 0;
71 }
72 level=versionscan_getlevelbyauth(np->authname);
73 if (level & (VS_STAFF | VS_GLINE | VS_ADMIN)) {
74 return 1;
75 }
76 return 0;
77}
78
79int IsVersionscanGlineAccess(nick* np) {
80 unsigned char level;
81
82 if (!IsAccount(np)) {
83 return 0;
84 }
85 level=versionscan_getlevelbyauth(np->authname);
86 if (level & (VS_GLINE | VS_ADMIN)) {
87 return 1;
88 }
89 return 0;
90}
91
92int IsVersionscanAdmin(nick* np) {
93 unsigned char level;
94
95 if (!IsAccount(np)) {
96 return 0;
97 }
98 level=versionscan_getlevelbyauth(np->authname);
99 if (level & VS_ADMIN) {
100 return 1;
101 }
102 return 0;
103}
104
105const char* versionscan_flagstochar(unsigned char flags) {
106 static char outstring[50];
107 int pos=0;
108
109 outstring[pos++]='+';
110 if (flags & VS_ADMIN) { outstring[pos++]='a'; }
111 if (flags & VS_GLINE) { outstring[pos++]='g'; }
112 if (flags & VS_STAFF) { outstring[pos++]='s'; }
113 outstring[pos]='\0';
114
115 return outstring;
116}
117
118void versionscan_addpattern(char* pattern, char* data, unsigned char action) {
119 vspattern* v;
120
121 if (!vspatterns) {
122 vspatterns=(vspattern*)malloc(sizeof(vspattern));
123 strncpy(vspatterns->pattern, pattern, VSPATTERNLEN);
124 strncpy(vspatterns->data, data, VSDATALEN);
125 vspatterns->action=action;
126 vspatterns->next=0;
127 vspatterns->hitcount=0;
128 return;
129 }
130
131 for (v=vspatterns; v; v=v->next) {
132 if (!v->next) {
133 v->next=(vspattern*)malloc(sizeof(vspattern));
134 strncpy(v->next->pattern, pattern, VSPATTERNLEN);
135 strncpy(v->next->data, data, VSDATALEN);
136 v->next->action=action;
137 v->next->next=0;
138 v->next->hitcount=0;
139 return;
140 }
141 }
142}
143
144void versionscan_delpattern(char* pattern) {
145 vspattern* v, *pv;
146
147 pv=0;
148 for (v=vspatterns; v; v=v->next) {
149 if (!ircd_strcmp(v->pattern, pattern)) {
150 if (pv) {
151 pv->next=v->next;
152 free(v);
153 }
154 else {
155 vspatterns=v->next;
156 free(v);
157 }
158 return;
159 }
160 pv=v;
161 }
162}
163
164vspattern* versionscan_getpattern(char* pattern) {
165 vspattern* v;
166
167 for (v=vspatterns; v; v=v->next) {
168 if (!ircd_strcmp(v->pattern, pattern)) {
169 return v;
170 }
171 }
172 return 0;
173}
174
175int versionscan_whois(void* sender, int cargc, char** cargv) {
176 nick* np=(nick*)sender;
177 nick* target;
178 vsauthdata* v;
179
180 if (cargc < 1) {
181 sendnoticetouser(versionscan_nick, np, "Syntax: whois <nickname>");
182 return CMD_ERROR;
183 }
184 if (!(target=getnickbynick(cargv[0]))) {
185 sendnoticetouser(versionscan_nick, np, "No such nick.");
186 return CMD_ERROR;
187 }
188 if (!IsAccount(target)) {
189 sendnoticetouser(versionscan_nick, np, "%s is not authed with the network.", target->nick);
190 return CMD_ERROR;
191 }
192 if (!(v=versionscan_getauthbyauth(target->authname))) {
193 sendnoticetouser(versionscan_nick, np, "User %s is not in my database.", target->nick);
194 return CMD_ERROR;
195 }
196 sendnoticetouser(versionscan_nick, np, "%s is authed as %s, with flags: %s", target->nick, target->authname, versionscan_flagstochar(v->flags));
197
198 return CMD_OK;
199}
200
201int versionscan_showcommands(void* sender, int cargc, char** cargv) {
202 nick* np=(nick*)sender;
203 Command* cmdlist[150];
204 int i, j;
205
206 sendnoticetouser(versionscan_nick, np, "The following commands are registered at present:");
207 j=getcommandlist(versionscan_commands, cmdlist, 150);
208 for (i=0; i<j; i++) {
209 if (cmdlist[i]->level & (VS_STAFF | VS_GLINE | VS_ADMIN)) {
210 sendnoticetouser(versionscan_nick, np, "%s (%s)", cmdlist[i]->command->content, versionscan_flagstochar(cmdlist[i]->level));
211 }
212 else {
213 sendnoticetouser(versionscan_nick, np, "%s", cmdlist[i]->command->content);
214 }
215 }
216 sendnoticetouser(versionscan_nick, np, "End of list.");
217
218 return CMD_OK;
219}
220
221int versionscan_help(void* sender, int cargc, char** cargv) {
222 nick* np=(nick*)sender;
223
224 if (cargc < 1) {
225 sendnoticetouser(versionscan_nick, np, "Syntax: help <command>");
226 return CMD_ERROR;
227 }
228
229 if (!strcasecmp(cargv[0], "help")) {
230 sendnoticetouser(versionscan_nick, np, "Syntax: help <command>");
231 sendnoticetouser(versionscan_nick, np, "Gives help on commands.");
232 return CMD_OK;
233 }
234 if (!strcasecmp(cargv[0], "hello")) {
235 sendnoticetouser(versionscan_nick, np, "Syntax: hello");
236 sendnoticetouser(versionscan_nick, np, "Creates the first account on the bot.");
237 return CMD_OK;
238 }
239 if (!strcasecmp(cargv[0], "scan")) {
240 sendnoticetouser(versionscan_nick, np, "Syntax: scan <target>");
241 sendnoticetouser(versionscan_nick, np, "Sends a version request to the specified target, which may be a nick or a channel.");
242 return CMD_OK;
243 }
244 if (!strcasecmp(cargv[0], "broadcast")) {
245 sendnoticetouser(versionscan_nick, np, "Syntax: broadcast [-f]");
246 sendnoticetouser(versionscan_nick, np, "Send a network-wide CTCP version.");
247 return CMD_OK;
248 }
249 if (!strcasecmp(cargv[0], "changelev")) {
250 sendnoticetouser(versionscan_nick, np, "Syntax: changelev <nick> <level>");
251 sendnoticetouser(versionscan_nick, np, "Changes a user's privileges.");
252 sendnoticetouser(versionscan_nick, np, "+a -> admin access");
253 sendnoticetouser(versionscan_nick, np, "+g -> g-line access");
254 sendnoticetouser(versionscan_nick, np, "+s -> staff access");
255 return CMD_OK;
256 }
257 if (!strcasecmp(cargv[0], "mode")) {
258 sendnoticetouser(versionscan_nick, np, "Syntax: mode [<mode of operation>]");
259 sendnoticetouser(versionscan_nick, np, "Where <mode of operation> is one of:");
260 sendnoticetouser(versionscan_nick, np, "idle: do nothing");
261 sendnoticetouser(versionscan_nick, np, "scan: scan newly connecting users and those targeted by the 'scan' command");
262 sendnoticetouser(versionscan_nick, np, "stat: collect statistics after a network-wide CTCP version request");
263 return CMD_OK;
264 }
265 if (!strcasecmp(cargv[0], "showcommands")) {
266 sendnoticetouser(versionscan_nick, np, "Syntax: showcommands");
267 sendnoticetouser(versionscan_nick, np, "Displays registered commands.");
268 return CMD_OK;
269 }
270 if (!strcasecmp(cargv[0], "whois")) {
271 sendnoticetouser(versionscan_nick, np, "Syntax: whois <nickname>");
272 sendnoticetouser(versionscan_nick, np, "Display information about the specified user.");
273 return CMD_OK;
274 }
275 if (!strcasecmp(cargv[0], "statistics")) {
276 sendnoticetouser(versionscan_nick, np, "Syntax: statistics [<limit>]");
277 sendnoticetouser(versionscan_nick, np, "Display statistics of collected CTCP version replies.");
278 return CMD_OK;
279 }
280 if (!strcasecmp(cargv[0], "listpatterns")) {
281 sendnoticetouser(versionscan_nick, np, "Syntax: listpatterns");
282 sendnoticetouser(versionscan_nick, np, "Lists CTCP version reply patterns.");
283 return CMD_OK;
284 }
285 if (!strcasecmp(cargv[0], "addpattern")) {
286 sendnoticetouser(versionscan_nick, np, "Syntax: addpattern <pattern> <action> <data>");
287 sendnoticetouser(versionscan_nick, np, "Adds a CTCP version reply pattern, where action is one of the following:");
288 sendnoticetouser(versionscan_nick, np, "%d - warn", VS_WARN);
289 sendnoticetouser(versionscan_nick, np, "%d - kill", VS_KILL);
290 sendnoticetouser(versionscan_nick, np, "%d - g-line user@host", VS_GLUSER);
291 sendnoticetouser(versionscan_nick, np, "%d - g-line *@host", VS_GLHOST);
292 return CMD_OK;
293 }
294 if (!strcasecmp(cargv[0], "delpattern")) {
295 sendnoticetouser(versionscan_nick, np, "Syntax: delpattern <pattern>");
296 sendnoticetouser(versionscan_nick, np, "Deletes a CTCP version reply pattern.");
297 return CMD_OK;
298 }
299 if (!strcasecmp(cargv[0], "status")) {
300 sendnoticetouser(versionscan_nick, np, "Syntax: status");
301 sendnoticetouser(versionscan_nick, np, "Gives various bits of information about the bot.");
302 return CMD_OK;
303 }
304
305 return CMD_OK;
306}
307
308int versionscan_listpatterns(void* sender, int cargc, char** cargv) {
309 nick* np=(nick*)sender;
310 vspattern* v;
311
312 for (v=vspatterns; v; v=v->next) {
313 sendnoticetouser(versionscan_nick, np, "Pattern [%s]:", v->pattern);
314 sendnoticetouser(versionscan_nick, np, "Data: %s", v->data);
315 sendnoticetouser(versionscan_nick, np, "Action: %s", (v->action == VS_WARN)?"warn":(v->action == VS_KILL)?"kill":(v->action == VS_GLUSER)?"g-line user@host":"g-line *@host");
316 sendnoticetouser(versionscan_nick, np, "Hit count: %lu", v->hitcount);
317 }
318 sendnoticetouser(versionscan_nick, np, "End of list.");
319 return CMD_OK;
320}
321
322int versionscan_addpatterncmd(void* sender, int cargc, char** cargv) {
323 nick* np=(nick*)sender;
324 int action;
325
326 if (cargc < 3) {
327 sendnoticetouser(versionscan_nick, np, "Syntax: addpattern <pattern> <action> <data>");
328 return CMD_ERROR;
329 }
330
331 action=atoi(cargv[1]);
332 if ((action < VS_WARN) || (action > VS_GLHOST)) {
333 sendnoticetouser(versionscan_nick, np, "Action must be a number between 1 and 4.");
334 return CMD_ERROR;
335 }
336
337 if (versionscan_getpattern(cargv[0])) {
338 sendnoticetouser(versionscan_nick, np, "That pattern already exists.");
339 return CMD_ERROR;
340 }
341
342 if ((action > VS_KILL) && !IsVersionscanGlineAccess(np)) {
343 sendnoticetouser(versionscan_nick, np, "You are not allowed to add G-Lines.");
344 return CMD_ERROR;
345 }
346
347 versionscan_addpattern(cargv[0], cargv[2], (unsigned char)action);
348 sendnoticetouser(versionscan_nick, np, "Done.");
349 return CMD_OK;
350}
351
352int versionscan_delpatterncmd(void* sender, int cargc, char** cargv) {
353 nick* np=(nick*)sender;
354
355 if (cargc < 1) {
356 sendnoticetouser(versionscan_nick, np, "Syntax: delpattern <pattern>");
357 return CMD_ERROR;
358 }
359
360 if (!versionscan_getpattern(cargv[0])) {
361 sendnoticetouser(versionscan_nick, np, "That pattern does not exist.");
362 return CMD_ERROR;
363 }
364
365 versionscan_delpattern(cargv[0]);
366 sendnoticetouser(versionscan_nick, np, "Done.");
367 return CMD_OK;
368}
369
370int versionscan_status(void* sender, int cargc, char** cargv) {
371 nick* np=(nick*)sender;
372 vspattern* v;
373 int pcount=0; unsigned long chcount=0;
374
375 for (v=vspatterns; v; v=v->next) {
376 pcount++;
377 chcount+=v->hitcount;
378 }
379
380 sendnoticetouser(versionscan_nick, np, "Patterns: %d", pcount);
381 sendnoticetouser(versionscan_nick, np, "Users hit: %lu (%lu from current patterns)", hcount, chcount);
382 sendnoticetouser(versionscan_nick, np, "Warnings given: %lu", wcount);
383 sendnoticetouser(versionscan_nick, np, "Kills sent: %lu", kcount);
384 sendnoticetouser(versionscan_nick, np, "G-Lines set: %lu", gcount);
385 return CMD_OK;
386}
387
388int versionscan_hello(void* sender, int cargc, char** cargv) {
389 nick* np=(nick*)sender;
390
391 if (vsauths) {
392 sendnoticetouser(versionscan_nick, np, "The hello command cannot be used after the first user account has been created.");
393 return CMD_ERROR;
394 }
395
396 vsauths=(vsauthdata*)malloc(sizeof(vsauthdata));
397 strncpy(vsauths->account, np->authname, ACCOUNTLEN);
398 vsauths->flags=VS_STAFF | VS_GLINE | VS_ADMIN;
399
400/* ?! */
401/* vsauths->next; */
402
403 sendnoticetouser(versionscan_nick, np, "An account has been created for you with the following flags: %s.", versionscan_flagstochar(vsauths->flags));
404 return CMD_OK;
405}
406
407int versionscan_changelev(void* sender, int cargc, char** cargv) {
408 nick* np=(nick*)sender;
409 vsauthdata* v;
410 nick* target;
411 unsigned char flags=0;
412 int i; int plus=1;
413
414 if (cargc < 2) {
415 sendnoticetouser(versionscan_nick, np, "Syntax: changelev <nick> [+|-]<level>");
416 return CMD_ERROR;
417 }
418
419 if (!(target=getnickbynick(cargv[0]))) {
420 sendnoticetouser(versionscan_nick, np, "No such nick.");
421 return CMD_ERROR;
422 }
423
424 if (!IsAccount(target)) {
425 sendnoticetouser(versionscan_nick, np, "%s is not authed.", target->nick);
426 return CMD_ERROR;
427 }
428
429 if ((v=versionscan_getauthbyauth(target->authname))) {
430 i=0;
431 if ((cargv[1][0] == '+') || (cargv[1][0] =='-')) {
432 plus=(cargv[1][0] == '+')?1:0;
433 i++;
434 flags=v->flags;
435 }
436 for (; cargv[1][i]; i++) {
437 switch (cargv[1][i]) {
438 case 'a':
439 flags=(plus)?flags | VS_ADMIN:flags & (~VS_ADMIN);
440 break;
441 case 'g':
442 flags=(plus)?flags | VS_GLINE:flags & (~VS_GLINE);
443 break;
444 case 's':
445 flags=(plus)?flags | VS_STAFF:flags & (~VS_STAFF);
446 break;
447 default:
448 sendnoticetouser(versionscan_nick, np, "Invalid level '%c'.", cargv[1][i]);
449 return CMD_ERROR;
450 break;
451 }
452 }
453 if (!flags) {
454 vsauthdata* pv, *prevv;
455
456 prevv=0;
457 for (pv=vsauths; pv; pv++) {
458 if (pv == v) {
459 if (prevv) {
460 prevv->next=pv->next;
461 free(pv);
462 }
463 else {
464 vsauths=pv->next;
465 free(pv);
466 }
467 }
468 prevv=pv;
469 }
470 }
471 else {
472 v->flags=flags;
473 }
474 sendnoticetouser(versionscan_nick, np, "Done.");
475 return CMD_OK;
476 }
477 else {
478 i=0;
479 if ((cargv[1][0] == '+') || (cargv[1][0] =='-')) {
480 plus=(cargv[1][0] == '+')?1:0;
481 i++;
482 }
483 for (; cargv[1][i]; i++) {
484 switch (cargv[1][i]) {
485 case 'a':
486 flags=(plus)?flags | VS_ADMIN:flags & (~VS_ADMIN);
487 break;
488 case 'g':
489 flags=(plus)?flags | VS_GLINE:flags & (~VS_GLINE);
490 break;
491 case 's':
492 flags=(plus)?flags | VS_STAFF:flags & (~VS_STAFF);
493 break;
494 default:
495 sendnoticetouser(versionscan_nick, np, "Invalid level '%c'.", cargv[1][i]);
496 return CMD_ERROR;
497 break;
498 }
499 }
500 if (flags) {
501 for (v=vsauths; v; v=v->next) {
502 if (!v->next) {
503 v->next=(vsauthdata*)malloc(sizeof(vsauthdata));
504 strncpy(v->next->account, target->authname, ACCOUNTLEN);
505 v->next->flags=flags;
506 v->next->next=0;
507 sendnoticetouser(versionscan_nick, np, "Done.");
508 return CMD_OK;
509 }
510 }
511 sendnoticetouser(versionscan_nick, np, "Error adding user to database.");
512 }
513 else {
514 sendnoticetouser(versionscan_nick, np, "No level specified.");
515 }
516 }
517
518 return CMD_ERROR;
519}
520
521int versionscan_scan(void* sender, int cargc, char** cargv) {
522 nick* np=(nick*)sender;
523 nick* n;
524 channel* cp;
525
526 if (cargc < 1) {
527 sendnoticetouser(versionscan_nick, np, "Syntax: scan <target>");
528 return CMD_ERROR;
529 }
530
531 if (versionscan_mode != VS_SCAN) {
532 sendnoticetouser(versionscan_nick, np, "Scanning of users is currently disabled.");
533 return CMD_ERROR;
534 }
535
536 if (cargv[0][0] == '#') {
537 if ((cp=findchannel(cargv[0]))) {
538 sendmessagetochannel(versionscan_nick, cp, "\001VERSION\001");
539 sendnoticetouser(versionscan_nick, np, "Done.");
540 }
541 else {
542 sendnoticetouser(versionscan_nick, np, "No such channel.");
543 return CMD_ERROR;
544 }
545 }
546 else {
547 if ((n=getnickbynick(cargv[0]))) {
548 if (IsOper(n)) {
549 sendnoticetouser(versionscan_nick, np, "Cannot scan IRC Operators.");
550 return CMD_ERROR;
551 }
552 sendmessagetouser(versionscan_nick, n, "\001VERSION\001");
553 sendnoticetouser(versionscan_nick, np, "Done.");
554 }
555 else {
556 sendnoticetouser(versionscan_nick, np, "No such nick.");
557 return CMD_ERROR;
558 }
559 }
560 return CMD_OK;
561}
562
563int versionscan_modecmd(void* sender, int cargc, char** cargv) {
564 nick* np=(nick*)sender;
565 int oldmode=versionscan_mode;
566
567 if (cargc < 1) {
568 sendnoticetouser(versionscan_nick, np, "Currently running in %s mode.", (versionscan_mode == VS_SCAN)?"SCAN":(versionscan_mode == VS_STAT)?"STATISTICS":"IDLE");
569 return CMD_OK;
570 }
571
572 if (!ircd_strcmp(cargv[0], "idle")) {
573 versionscan_mode=VS_IDLE;
574 sendnoticetouser(versionscan_nick, np, "Now operating in IDLE mode.");
575 }
576 else if (!ircd_strcmp(cargv[0], "scan")) {
577 versionscan_mode=VS_SCAN;
578 sendnoticetouser(versionscan_nick, np, "Now operating in SCAN mode.");
579 }
580 else if (!ircd_strcmp(cargv[0], "stat")) {
581 versionscan_mode=VS_STAT;
582 sendnoticetouser(versionscan_nick, np, "Now operating in STATISTICS mode.");
583 }
584 else {
585 sendnoticetouser(versionscan_nick, np, "Invalid mode of operation.");
586 return CMD_ERROR;
587 }
588
589 if (oldmode == VS_STAT) {
590 vsstatistic* v, *nv;
591
592 for (v=vsstats; v;) {
593 nv=v->next;
594 free(v->reply);
595 free(v);
596 v=nv;
597 }
598 vsstats=0;
599 }
600
601 return CMD_OK;
602}
603
604int versionscan_statistics(void* sender, int cargc, char** cargv) {
605 nick* np=(nick*)sender;
606 vsstatistic* v;
607 long rlimit=0, limit=100;
608
609 if (versionscan_mode != VS_STAT) {
610 sendnoticetouser(versionscan_nick, np, "No statistics are available unless STATISTICS mode of operation is enabled.");
611 return CMD_OK;
612 }
613 if (cargc) {
614 limit=atoi(cargv[0]);
615 }
616 if ((limit < 1) || (limit > 500)) {
617 sendnoticetouser(versionscan_nick, np, "Invalid results limit. Valid values are 1-500.");
618 return CMD_ERROR;
619 }
620 sendnoticetouser(versionscan_nick, np, "Reply: [Count]:");
621 for (v=vsstats; (v && (rlimit < limit)); v=v->next) {
622 sendnoticetouser(versionscan_nick, np, "%s [%lu]", v->reply, v->count);
623 rlimit++;
624 }
625 sendnoticetouser(versionscan_nick, np, "End of list - %lu results returned.", rlimit);
626 return CMD_OK;
627}
628
629int versionscan_broadcast(void* sender, int cargc, char** cargv) {
630 nick* np=(nick*)sender;
631 int force=0;
632
633 if (cargc) {
634 if (strcmp(cargv[0], "-f")) {
635 sendnoticetouser(versionscan_nick, np, "Invalid flag.");
636 return CMD_ERROR;
637 }
638 force=1;
639 }
640
641 if (versionscan_mode != VS_STAT) {
642 if (!force) {
643 sendnoticetouser(versionscan_nick, np, "Statistics collection mode is not currently enabled. Use the 'mode' command to change current mode of operation.");
644 sendnoticetouser(versionscan_nick, np, "If you really wish to send a network-wide CTCP version whilst running in SCAN or IDLE mode, use the -f flag.");
645 return CMD_ERROR;
646 }
647 sendnoticetouser(versionscan_nick, np, "Forcing network-wide CTCP version.");
648 }
649
650 irc_send("%s P $* :\001VERSION\001\r\n", longtonumeric(versionscan_nick->numeric, 5));
651 sendnoticetouser(versionscan_nick, np, "Done.");
652
653 return CMD_OK;
654}
655
656void versionscan_newnick(int hooknum, void* arg) {
657 nick* np=(nick*)arg;
658
659 /* ignore opers or auth'd users, helps cut down on spam during a burst */
660 if (!(IsOper(np) || IsAccount(np)) && (versionscan_mode == VS_SCAN)) {
661 sendmessagetouser(versionscan_nick, np, "\001VERSION\001");
662 }
663}
664
665void versionscan_handler(nick* me, int type, void** args) {
666 nick* sender;
667 Command* cmd;
668 char* cargv[50];
669 int cargc;
670 vspattern* v;
671 char* p;
672 char **chargs = (char **)args;
673
674 switch (type) {
675 case LU_PRIVMSG:
676 case LU_SECUREMSG:
677 /* nick */
678 sender=args[0];
679
680 if (!strncmp("\001VERSION", args[1], 8)) {
681 sendnoticetouser(versionscan_nick, sender, "\001VERSION QuakeNet %s v%s.\001", VS_RNDESC, VS_VERSION);
682 return;
683 }
684
685 cargc=splitline((char*)args[1], cargv, 50, 0);
686
687 cmd=findcommandintree(versionscan_commands, cargv[0], 1);
688 if (!cmd) {
689 sendnoticetouser(versionscan_nick, sender, "Unknown command.");
690 return;
691 }
692
693/* if ((cmd->level & VS_AUTHED) && !IsAccount(sender)) {
694 sendnoticetouser(versionscan_nick, sender, "Sorry, you need to be authed to use this command.");
695 return;
696 }
697*/
698 if ((cmd->level & VS_OPER) && !IsOper(sender)) {
699 sendnoticetouser(versionscan_nick, sender, "Sorry, you need to be opered to use this command.");
700 return;
701 }
702/*
703 if (((cmd->level & VS_STAFF) && !IsVersionscanStaff(sender)) ||
704 ((cmd->level & VS_GLINE) && !IsVersionscanGlineAccess(sender)) ||
705 ((cmd->level & VS_ADMIN) && !IsVersionscanAdmin(sender))) {
706 sendnoticetouser(versionscan_nick, sender, "Sorry, you do not have access to this command.");
707 return;
708 }
709*/ /*
710 if ((cmd->level & VS_GLINE) && !IsVersionscanGlineAccess(sender)) {
711 sendnoticetouser(versionscan_nick, sender, "Sorry, you do not have access to this command.");
712 return;
713 }
714
715 if ((cmd->level & VS_ADMIN) && !IsVersionscanAdmin(sender)) {
716 sendnoticetouser(versionscan_nick, sender, "Sorry, you do not have access to this command.");
717 return;
718 }*/
719
720 if (cmd->maxparams < (cargc-1)) {
721 /* We need to do some rejoining */
722 rejoinline(cargv[cmd->maxparams], cargc-(cmd->maxparams));
723 cargc=(cmd->maxparams)+1;
724 }
725
726 (cmd->handler)((void*)sender, cargc-1, &(cargv[1]));
727 break;
728 case LU_PRIVNOTICE:
729 sender=args[0];
730
731 if (strncmp("\001VERSION", args[1], 8)) {
732 break;
733 }
734 if ((p=strchr(&chargs[1][8], '\001'))) {
735 *p++='\0';
736 }
737 if (versionscan_mode == VS_SCAN) {
738 if (IsOper(sender)) {
739 break;
740 }
741 for (v=vspatterns; v; v=v->next) {
742 if (match2strings(v->pattern, &chargs[1][8])) {
743 v->hitcount++;
744 hcount++;
745 switch (v->action) {
746 case VS_WARN:
747 sendnoticetouser(versionscan_nick, sender, v->data);
748 wcount++;
749 break;
750 case VS_KILL:
751 killuser(versionscan_nick, sender, v->data);
752 kcount++;
753 break;
754 case VS_GLUSER:
755 irc_send("%s GL * +*!%s@%s 3600 :%s\r\n", mynumeric->content, sender->ident, sender->host->name->content, v->data);
756 gcount++;
757 break;
758 case VS_GLHOST:
759 irc_send("%s GL * +*!*@%s 3600 :%s\r\n", mynumeric->content, sender->host->name->content, v->data);
760 gcount++;
761 break;
762 default:
763 /* oh dear, something's fucked */
764 break;
765 }
766 break;
767 }
768 }
769 }
770 else if (versionscan_mode == VS_STAT) {
771 versionscan_addstat(&chargs[1][8]);
772 }
773 break;
774 case LU_KILLED:
775 versionscan_nick=NULL;
776 scheduleoneshot(time(NULL)+1, &versionscan_createfakeuser, NULL);
777 break;
778 }
779}
780
781void versionscan_createfakeuser(void* arg) {
782 channel* cp;
783 char buf[200];
784
785 sprintf(buf, "%s v%s", VS_RNDESC, VS_VERSION);
786 versionscan_nick=registerlocaluser(VS_NICK, VS_IDENT, VS_HOST, buf, VS_AUTHNAME, UMODE_ACCOUNT | UMODE_DEAF | UMODE_OPER | UMODE_SERVICE, versionscan_handler);
787 if ((cp=findchannel(OPER_CHAN))) {
788 localjoinchannel(versionscan_nick, cp);
789 localgetops(versionscan_nick, cp);
790 } else {
791 localcreatechannel(versionscan_nick, OPER_CHAN);
792 }
793}
794
795void _init() {
796 vspatterns=0;
797 vsauths=0;
798 vsstats=0;
799 versionscan_mode=VS_IDLE;
800
801 versionscan_commands=newcommandtree();
802
803 addcommandtotree(versionscan_commands, "showcommands", 0, 0, versionscan_showcommands);
804 addcommandtotree(versionscan_commands, "help", VS_AUTHED | VS_STAFF, 1, versionscan_help);
805 addcommandtotree(versionscan_commands, "hello", VS_AUTHED | VS_OPER, 0, versionscan_hello);
806 addcommandtotree(versionscan_commands, "scan", VS_AUTHED | VS_STAFF, 1, versionscan_scan);
807 addcommandtotree(versionscan_commands, "changelev", VS_AUTHED | VS_OPER | VS_ADMIN, 2, versionscan_changelev);
808 addcommandtotree(versionscan_commands, "listpatterns", VS_AUTHED | VS_STAFF | VS_OPER, 0, versionscan_listpatterns);
809 addcommandtotree(versionscan_commands, "addpattern", VS_AUTHED | VS_STAFF | VS_OPER, 3, versionscan_addpatterncmd);
810 addcommandtotree(versionscan_commands, "delpattern", VS_AUTHED | VS_OPER | VS_ADMIN, 1, versionscan_delpatterncmd);
811 addcommandtotree(versionscan_commands, "status", VS_AUTHED | VS_OPER | VS_ADMIN, 0, versionscan_status);
812 addcommandtotree(versionscan_commands, "mode", VS_AUTHED | VS_OPER | VS_ADMIN, 1, versionscan_modecmd);
813 addcommandtotree(versionscan_commands, "statistics", VS_AUTHED | VS_OPER | VS_STAFF, 1, versionscan_statistics);
814 addcommandtotree(versionscan_commands, "broadcast", VS_AUTHED | VS_OPER | VS_ADMIN, 1, versionscan_broadcast);
815 addcommandtotree(versionscan_commands, "whois", VS_AUTHED | VS_STAFF, 1, versionscan_whois);
816
817 registerhook(HOOK_NICK_NEWNICK, &versionscan_newnick);
818
819 scheduleoneshot(time(NULL)+1, &versionscan_createfakeuser, NULL);
820}
821
822void _fini() {
823 void* p, *np;
824
825 deregisterhook(HOOK_NICK_NEWNICK, &versionscan_newnick);
826 if (versionscan_nick) {
827 deregisterlocaluser(versionscan_nick, "Module unloaded.");
828 versionscan_nick=NULL;
829 }
830
831 for (p=vspatterns; p;) {
832 np=((vspattern*)p)->next;
833 free(p);
834 p=np;
835 }
836 for (p=vsauths; p;) {
837 np=((vsauthdata*)p)->next;
838 free(p);
839 p=np;
840 }
841 for (p=vsstats; p;) {
842 np=((vsstatistic*)p)->next;
843 free(((vsstatistic*)p)->reply);
844 free(p);
845 p=np;
846 }
847}