/[cvs]/eggdrop1.4/src/users.c
ViewVC logotype

Contents of /eggdrop1.4/src/users.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.18 - (show annotations) (download) (as text)
Sun Feb 6 18:37:44 2000 UTC (19 years, 6 months ago) by per
Branch: MAIN
CVS Tags: eggdrop104030RC2, eggdrop10403RC1, eggdrop10404, eggdrop10403, HEAD
Changes since 1.17: +4 -1 lines
File MIME type: text/x-chdr
eugene, malformed_ban, staticadduser, securityfix and bothost patch

1 /*
2 * users.c -- handles:
3 * testing and enforcing ignores
4 * adding and removing ignores
5 * listing ignores
6 * auto-linking bots
7 * sending and receiving a userfile from a bot
8 * listing users ('.whois' and '.match')
9 * reading the user file
10 *
11 * dprintf'ized, 9nov1995
12 *
13 * $Id: users.c,v 1.17 2000/01/17 16:14:45 per Exp $
14 */
15 /*
16 * Copyright (C) 1997 Robey Pointer
17 * Copyright (C) 1999, 2000 Eggheads
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 */
33
34 #include "main.h"
35 #include "users.h"
36 #include "chan.h"
37 #include "modules.h"
38 #include "tandem.h"
39 char natip[121] = "";
40
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 char spaces[33] = " ";
44 char spaces2[33] = " ";
45
46 extern struct dcc_t *dcc;
47 extern struct userrec *userlist, *lastuser;
48 extern struct chanset_t *chanset;
49 extern int dcc_total, noshare, use_silence;
50 extern char botnetnick[];
51 extern Tcl_Interp *interp;
52 extern time_t now;
53
54 char userfile[121] = ""; /* where the user records are stored */
55 int ignore_time = 10; /* how many minutes will ignores last? */
56 int gban_total = 0; /* Total number of global bans */
57 int gexempt_total = 0; /* Total number of global exempts */
58 int ginvite_total = 0; /* Total number of global invites */
59
60 /* is this nick!user@host being ignored? */
61 int match_ignore(char *uhost)
62 {
63 struct igrec *ir;
64
65 for (ir = global_ign; ir; ir = ir->next)
66 if (wild_match(ir->igmask, uhost))
67 return 1;
68 return 0;
69 }
70
71 int equals_ignore(char *uhost)
72 {
73 struct igrec *u = global_ign;
74
75 for (; u; u = u->next)
76 if (!rfc_casecmp(u->igmask, uhost)) {
77 if (u->flags & IGREC_PERM)
78 return 2;
79 else
80 return 1;
81 }
82 return 0;
83 }
84
85 int delignore(char *ign)
86 {
87 int i, j;
88 struct igrec **u;
89 struct igrec *t;
90
91 Context;
92
93 i = 0;
94 if (!strchr(ign, '!') && (j = atoi(ign))) {
95 for (u = &global_ign, j--; *u && j; u = &((*u)->next), j--);
96 if (*u) {
97 strcpy(ign, (*u)->igmask);
98 i = 1;
99 }
100 } else {
101 /* find the matching host, if there is one */
102 for (u = &global_ign; *u && !i; u = &((*u)->next))
103 if (!rfc_casecmp(ign, (*u)->igmask)) {
104 i = 1;
105 break;
106 }
107 }
108 if (i) {
109 if (!noshare)
110 shareout(NULL, "-i %s\n", ign);
111 nfree((*u)->igmask);
112 if ((*u)->msg)
113 nfree((*u)->msg);
114 if ((*u)->user)
115 nfree((*u)->user);
116 t = *u;
117 *u = (*u)->next;
118 nfree(t);
119 }
120 return i;
121 }
122
123 void addignore(char *ign, char *from, char *mnote, time_t expire_time)
124 {
125 struct igrec *p;
126
127 if (equals_ignore(ign))
128 delignore(ign); /* remove old ignore */
129 p = user_malloc(sizeof(struct igrec));
130
131 p->next = global_ign;
132 global_ign = p;
133 p->expire = expire_time;
134 p->added = now;
135 p->flags = expire_time ? 0 : IGREC_PERM;
136 p->igmask = user_malloc(strlen(ign) + 1);
137 strcpy(p->igmask, ign);
138 p->user = user_malloc(strlen(from) + 1);
139 strcpy(p->user, from);
140 p->msg = user_malloc(strlen(mnote) + 1);
141 strcpy(p->msg, mnote);
142 if (!noshare)
143 shareout(NULL, "+i %s %lu %c %s %s\n", ign, expire_time - now,
144 (p->flags & IGREC_PERM) ? 'p' : '-', from, mnote);
145 }
146
147 /* take host entry from ignore list and display it ignore-style */
148 void display_ignore(int idx, int number, struct igrec *ignore)
149 {
150 char dates[81], s[41];
151
152 if (ignore->added) {
153 daysago(now, ignore->added, s);
154 sprintf(dates, "Started %s", s);
155 } else
156 dates[0] = 0;
157 if (ignore->flags & IGREC_PERM)
158 strcpy(s, "(perm)");
159 else {
160 char s1[41];
161
162 days(ignore->expire, now, s1);
163 sprintf(s, "(expires %s)", s1);
164 }
165 if (number >= 0)
166 dprintf(idx, " [%3d] %s %s\n", number, ignore->igmask, s);
167 else
168 dprintf(idx, "IGNORE: %s %s\n", ignore->igmask, s);
169 if (ignore->msg && ignore->msg[0])
170 dprintf(idx, " %s: %s\n", ignore->user, ignore->msg);
171 else
172 dprintf(idx, " %s %s\n", MODES_PLACEDBY, ignore->user);
173 if (dates[0])
174 dprintf(idx, " %s\n", dates);
175 }
176
177 /* list the ignores and how long they've been active */
178 void tell_ignores(int idx, char *match)
179 {
180 struct igrec *u = global_ign;
181 int k = 1;
182
183 if (u == NULL) {
184 dprintf(idx, "No ignores.\n");
185 return;
186 }
187 dprintf(idx, "%s:\n", IGN_CURRENT);
188 for (; u; u = u->next) {
189 if (match[0]) {
190 if (wild_match(match, u->igmask) ||
191 wild_match(match, u->msg) ||
192 wild_match(match, u->user))
193 display_ignore(idx, k, u);
194 k++;
195 } else
196 display_ignore(idx, k++, u);
197 }
198 }
199
200 /* check for expired timed-ignores */
201 void check_expired_ignores()
202 {
203 struct igrec **u = &global_ign;
204
205 if (!*u)
206 return;
207 while (*u) {
208 if (!((*u)->flags & IGREC_PERM) && (now >= (*u)->expire)) {
209 putlog(LOG_MISC, "*", "%s %s (%s)", IGN_NOLONGER, (*u)->igmask,
210 MISC_EXPIRED);
211 if (use_silence) {
212 char *p;
213
214 /* possibly an ircu silence was added for this user */
215 p = strchr((*u)->igmask, '!');
216 if (p == NULL)
217 p = (*u)->igmask;
218 else
219 p++;
220 dprintf(DP_SERVER, "SILENCE -%s\n", p);
221 }
222 delignore((*u)->igmask);
223 } else {
224 u = &((*u)->next);
225 }
226 }
227 }
228
229 /* Channel mask loaded from user file. This function is
230 * add(ban|invite|exempt)_fully merged into one. <cybah>
231 */
232 static void addmask_fully(struct chanset_t *chan, maskrec **m, maskrec **global,
233 char *mask, char *from,
234 char *note, time_t expire_time, int flags,
235 time_t added, time_t last)
236 {
237 maskrec *p = user_malloc(sizeof(maskrec));
238 maskrec **u = (chan) ? m : global;
239
240 p->next = *u;
241 *u = p;
242 p->expire = expire_time;
243 p->added = added;
244 p->lastactive = last;
245 p->flags = flags;
246 p->mask = user_malloc(strlen(mask) + 1);
247 strcpy(p->mask, mask);
248 p->user = user_malloc(strlen(from) + 1);
249 strcpy(p->user, from);
250 p->desc = user_malloc(strlen(note) + 1);
251 strcpy(p->desc, note);
252 }
253
254 static void restore_chanban(struct chanset_t *chan, char *host)
255 {
256 char *expi, *add, *last, *user, *desc;
257 int flags = 0;
258
259 expi = strchr(host, ':');
260 if (expi) {
261 *expi = 0;
262 expi++;
263 if (*expi == '+') {
264 flags |= MASKREC_PERM;
265 expi++;
266 }
267 add = strchr(expi, ':');
268 if (add) {
269 if (add[-1] == '*') {
270 flags |= MASKREC_STICKY;
271 add[-1] = 0;
272 } else
273 *add = 0;
274 add++;
275 if (*add == '+') {
276 last = strchr(add, ':');
277 if (last) {
278 *last = 0;
279 last++;
280 user = strchr(last, ':');
281 if (user) {
282 *user = 0;
283 user++;
284 desc = strchr(user, ':');
285 if (desc) {
286 *desc = 0;
287 desc++;
288 addmask_fully(chan, &chan->bans, &global_bans, host, user,
289 desc, atoi(expi), flags, atoi(add), atoi(last));
290 return;
291 }
292 }
293 }
294 } else {
295 desc = strchr(add, ':');
296 if (desc) {
297 *desc = 0;
298 desc++;
299 addmask_fully(chan, &chan->bans, &global_bans, host, add, desc,
300 atoi(expi), flags, now, 0);
301 return;
302 }
303 }
304 }
305 }
306 putlog(LOG_MISC, "*", "*** Malformed banline for %s.",
307 chan ? chan->name : "global_bans");
308 }
309
310 static void restore_chanexempt (struct chanset_t * chan, char * host)
311 {
312 char * expi, * add, * last, * user, * desc;
313 int flags = 0;
314
315 expi = strchr(host,':');
316 if (expi) {
317 *expi = 0;
318 expi++;
319 if (*expi == '+') {
320 flags |= MASKREC_PERM;
321 expi++;
322 }
323 add = strchr(expi,':');
324 if (add) {
325 if (add[-1]=='*') {
326 flags |= MASKREC_STICKY;
327 add[-1] = 0;
328 } else
329 *add = 0;
330 add++;
331 if (*add == '+') {
332 last = strchr(add,':');
333 if (last) {
334 *last = 0;
335 last++;
336 user = strchr(last,':');
337 if (user) {
338 *user = 0;
339 user++;
340 desc = strchr(user,':');
341 if (desc) {
342 *desc = 0;
343 desc++;
344 addmask_fully(chan, &chan->exempts, &global_exempts, host,user,desc,atoi(expi),flags,
345 atoi(add), atoi(last));
346 return;
347 }
348 }
349 }
350 } else {
351 desc = strchr(add,':');
352
353 if (desc) {
354 *desc = 0;
355 desc++;
356 addmask_fully(chan, &chan->exempts, &global_exempts, host,add,desc,atoi(expi),flags,
357 now, 0);
358 return;
359 }
360 }
361 }
362 }
363 putlog(LOG_MISC,"*","*** Malformed exemptline for %s.",
364 chan?chan->name:"global_exempts");
365 }
366
367 static void restore_chaninvite (struct chanset_t * chan, char * host)
368 {
369 char * expi, * add, * last, * user, * desc;
370 int flags = 0;
371
372 expi = strchr(host,':');
373 if (expi) {
374 *expi = 0;
375 expi++;
376 if (*expi == '+') {
377 flags |= MASKREC_PERM;
378 expi++;
379 }
380 add = strchr(expi,':');
381 if (add) {
382 if (add[-1]=='*') {
383 flags |= MASKREC_STICKY;
384 add[-1] = 0;
385 } else
386 *add = 0;
387 add++;
388 if (*add == '+') {
389 last = strchr(add,':');
390 if (last) {
391 *last = 0;
392 last++;
393 user = strchr(last,':');
394 if (user) {
395 *user = 0;
396 user++;
397 desc = strchr(user,':');
398 if (desc) {
399 *desc = 0;
400 desc++;
401 addmask_fully(chan, &chan->invites, &global_invites, host, user,
402 desc, atoi(expi), flags, atoi(add), atoi(last));
403 return;
404 }
405 }
406 }
407 } else {
408 desc = strchr(add,':');
409
410 if (desc) {
411 *desc = 0;
412 desc++;
413 addmask_fully(chan, &chan->invites, &global_invites, host, add,
414 desc,atoi(expi),flags, now, 0);
415 return;
416 }
417 }
418 }
419 }
420 putlog(LOG_MISC,"*","*** Malformed inviteline for %s.",
421 chan?chan->name:"global_invites");
422 }
423
424 static void restore_ignore(char *host)
425 {
426 char *expi, *user, *added, *desc;
427 int flags = 0;
428 struct igrec *p;
429
430 expi = strchr(host, ':');
431 if (expi) {
432 *expi = 0;
433 expi++;
434 if (*expi == '+') {
435 flags |= IGREC_PERM;
436 expi++;
437 }
438 user = strchr(expi, ':');
439 if (user) {
440 *user = 0;
441 user++;
442 added = strchr(user, ':');
443 if (added) {
444 *added = 0;
445 added++;
446 desc = strchr(added, ':');
447 if (desc) {
448 *desc = 0;
449 desc++;
450 } else
451 desc = NULL;
452 } else {
453 added = "0";
454 desc = NULL;
455 }
456 p = user_malloc(sizeof(struct igrec));
457
458 p->next = global_ign;
459 global_ign = p;
460 p->expire = atoi(expi);
461 p->added = atoi(added);
462 p->flags = flags;
463 p->igmask = user_malloc(strlen(host) + 1);
464 strcpy(p->igmask, host);
465 p->user = user_malloc(strlen(user) + 1);
466 strcpy(p->user, user);
467 if (desc) {
468 p->msg = user_malloc(strlen(desc) + 1);
469 strcpy(p->msg, desc);
470 } else
471 p->msg = NULL;
472 return;
473 }
474 }
475 putlog(LOG_MISC, "*", "*** Malformed ignore line.");
476 }
477
478 void tell_user(int idx, struct userrec *u, int master)
479 {
480 char s[81], s1[81];
481 int n, l = HANDLEN - strlen(u->handle);
482 time_t now2;
483 struct chanuserrec *ch;
484 struct user_entry *ue;
485 struct laston_info *li;
486 struct flag_record fr =
487 {FR_GLOBAL, 0, 0, 0, 0, 0};
488
489 Context;
490 fr.global = u->flags;
491
492 fr.udef_global = u->flags_udef;
493 build_flags(s, &fr, NULL);
494 Tcl_SetVar(interp, "user", u->handle, 0);
495 n = 0;
496 if (Tcl_VarEval(interp, "notes ", "$user", NULL) == TCL_OK)
497 n = atoi(interp->result);
498 li = get_user(&USERENTRY_LASTON, u);
499 if (!li || !li->laston)
500 strcpy(s1, "never");
501 else {
502 now2 = now - li->laston;
503 strcpy(s1, ctime(&li->laston));
504 if (now2 > 86400) {
505 s1[7] = 0;
506 strcpy(&s1[11], &s1[4]);
507 strcpy(s1, &s1[8]);
508 } else {
509 s1[16] = 0;
510 strcpy(s1, &s1[11]);
511 }
512 }
513 Context;
514 spaces[l] = 0;
515 dprintf(idx, "%s%s %-5s%5d %-15s %s (%-10.10s)\n", u->handle, spaces,
516 get_user(&USERENTRY_PASS, u) ? "yes" : "no", n, s, s1,
517 (li && li->lastonplace) ? li->lastonplace : "nowhere");
518 spaces[l] = ' ';
519 /* channel flags? */
520 Context;
521 ch = u->chanrec;
522 while (ch != NULL) {
523 fr.match = FR_CHAN | FR_GLOBAL;
524 get_user_flagrec(dcc[idx].user, &fr, ch->channel);
525 if (glob_op(fr) || chan_op(fr)) {
526 if (ch->laston == 0L)
527 strcpy(s1, "never");
528 else {
529 now2 = now - (ch->laston);
530 strcpy(s1, ctime(&(ch->laston)));
531 if (now2 > 86400) {
532 s1[7] = 0;
533 strcpy(&s1[11], &s1[4]);
534 strcpy(s1, &s1[8]);
535 } else {
536 s1[16] = 0;
537 strcpy(s1, &s1[11]);
538 }
539 }
540 fr.match = FR_CHAN;
541 fr.chan = ch->flags;
542 fr.udef_chan = ch->flags_udef;
543 build_flags(s, &fr, NULL);
544 spaces[HANDLEN - 9] = 0;
545 dprintf(idx, "%s %-18s %-15s %s\n", spaces, ch->channel, s, s1);
546 spaces[HANDLEN - 9] = ' ';
547 if (ch->info != NULL)
548 dprintf(idx, " INFO: %s\n", ch->info);
549 }
550 ch = ch->next;
551 }
552 /* user-defined extra fields */
553 Context;
554 for (ue = u->entries; ue; ue = ue->next)
555 if (!ue->name && ue->type->display)
556 ue->type->display(idx, ue);
557 }
558
559 /* show user by ident */
560 void tell_user_ident(int idx, char *id, int master)
561 {
562 struct userrec *u;
563
564 u = get_user_by_handle(userlist, id);
565 if (u == NULL)
566 u = get_user_by_host(id);
567 if (u == NULL) {
568 dprintf(idx, "%s.\n", USERF_NOMATCH);
569 return;
570 }
571 spaces[HANDLEN - 6] = 0;
572 dprintf(idx, "HANDLE%s PASS NOTES FLAGS LAST\n", spaces);
573 spaces[HANDLEN - 6] = ' ';
574 tell_user(idx, u, master);
575 }
576
577 /* match string:
578 * wildcard to match nickname or hostmasks
579 * +attr to find all with attr */
580 void tell_users_match(int idx, char *mtch, int start, int limit,
581 int master, char *chname)
582 {
583 struct userrec *u = userlist;
584 int fnd = 0, cnt, nomns = 0, flags = 0;
585 struct list_type *q;
586 struct flag_record user, pls, mns;
587
588 Context;
589 dprintf(idx, "*** %s '%s':\n", MISC_MATCHING, mtch);
590 cnt = 0;
591 spaces[HANDLEN - 6] = 0;
592 dprintf(idx, "HANDLE%s PASS NOTES FLAGS LAST\n", spaces);
593 spaces[HANDLEN - 6] = ' ';
594 if (start > 1)
595 dprintf(idx, "(%s %d)\n", MISC_SKIPPING, start - 1);
596 if (strchr("+-&|", *mtch)) {
597 user.match = pls.match = FR_GLOBAL | FR_BOT | FR_CHAN;
598 break_down_flags(mtch, &pls, &mns);
599 mns.match = pls.match ^ (FR_AND | FR_OR);
600 if (!mns.global && !mns.udef_global && !mns.chan && !mns.udef_chan &&
601 !mns.bot) {
602 nomns = 1;
603 if (!pls.global && !pls.udef_global && !pls.chan && !pls.udef_chan &&
604 !pls.bot) {
605 /* happy now BB you weenie :P */
606 dprintf(idx, "Unknown flag specified for matching!!\n");
607 return;
608 }
609 }
610 if (!chname || !chname[0])
611 chname = dcc[idx].u.chat->con_chan;
612 flags = 1;
613 }
614 while (u != NULL) {
615 if (flags) {
616 get_user_flagrec(u, &user, chname);
617 if (flagrec_eq(&pls, &user)) {
618 if (nomns || !flagrec_eq(&mns, &user)) {
619 cnt++;
620 if ((cnt <= limit) && (cnt >= start))
621 tell_user(idx, u, master);
622 if (cnt == limit + 1)
623 dprintf(idx, MISC_TRUNCATED, limit);
624 }
625 }
626 } else if (wild_match(mtch, u->handle)) {
627 cnt++;
628 if ((cnt <= limit) && (cnt >= start))
629 tell_user(idx, u, master);
630 if (cnt == limit + 1)
631 dprintf(idx, MISC_TRUNCATED, limit);
632 } else {
633 fnd = 0;
634 for (q = get_user(&USERENTRY_HOSTS, u); q; q = q->next) {
635 if ((wild_match(mtch, q->extra)) && (!fnd)) {
636 cnt++;
637 fnd = 1;
638 if ((cnt <= limit) && (cnt >= start)) {
639 tell_user(idx, u, master);
640 }
641 if (cnt == limit + 1)
642 dprintf(idx, MISC_TRUNCATED, limit);
643 }
644 }
645 }
646 u = u->next;
647 }
648 dprintf(idx, MISC_FOUNDMATCH, cnt, cnt == 1 ? "" : "es");
649 }
650
651 /*
652 * tagged lines in the user file:
653 * * OLD:
654 * # (comment)
655 * ; (comment)
656 * - hostmask(s)
657 * + email
658 * * dcc directory
659 * = comment
660 * : info line
661 * . xtra (Tcl)
662 * ! channel-specific
663 * !! global laston
664 * :: channel-specific bans
665 * NEW:
666 * *ban global bans
667 * *ignore global ignores
668 * ::#chan channel bans
669 * - entries in each
670 * <handle> begin user entry
671 * --KEY INFO - info on each
672 * NEWER:
673 * % exemptmask(s)
674 * @ Invitemask(s)
675 * *exempt global exempts
676 * *Invite global Invites
677 * && channel-specific exempts
678 * &&#chan channel exempts
679 * $$ channel-specific Invites
680 * $$#chan channel Invites
681 */
682
683 int noxtra = 0;
684 int readuserfile(char *file, struct userrec **ret)
685 {
686 char *p, buf[512], lasthand[512], *attr, *pass, *code, s1[512], *s;
687 FILE *f;
688 struct userrec *bu, *u = NULL;
689 struct chanset_t *cst = NULL;
690 int i;
691 char ignored[512];
692 struct flag_record fr;
693 struct chanuserrec *cr;
694
695 Context;
696 bu = (*ret);
697 ignored[0] = 0;
698 if (bu == userlist) {
699 clear_chanlist();
700 lastuser = NULL;
701 global_bans = NULL;
702 global_ign = NULL;
703 global_exempts = NULL;
704 global_invites = NULL;
705 }
706 lasthand[0] = 0;
707 f = fopen(file, "r");
708 if (f == NULL)
709 return 0;
710 noshare = noxtra = 1;
711 Context;
712 /* read opening comment */
713 s = buf;
714 fgets(s, 180, f);
715 if (s[1] < '4') {
716 fatal(USERF_OLDFMT, 0);
717 }
718 if (s[1] > '4')
719 fatal(USERF_INVALID, 0);
720 gban_total = 0;
721 gexempt_total = 0;
722 ginvite_total = 0;
723 while (!feof(f)) {
724 s = buf;
725 fgets(s, 511, f);
726 if (!feof(f)) {
727 if ((s[0] != '#') && (s[0] != ';') && (s[0])) {
728 code = newsplit(&s);
729 rmspace(s);
730 if (!strcmp(code, "-")) {
731 if (lasthand[0]) {
732 if (u) { /* only break it down if there a real users */
733 p = strchr(s, ',');
734 while (p != NULL) {
735 splitc(s1, s, ',');
736 rmspace(s1);
737 if (s1[0])
738 set_user(&USERENTRY_HOSTS, u, s1);
739 p = strchr(s, ',');
740 }
741 }
742 /* channel bans are never stacked with , */
743 if (s[0]) {
744 if (lasthand[0] && (strchr(CHANMETA, lasthand[0]) != NULL))
745 restore_chanban(cst, s);
746 else if (lasthand[0] == '*') {
747 if (lasthand[1] == 'i') {
748 restore_ignore(s);
749 } else {
750 restore_chanban(NULL, s);
751 gban_total++;
752 }
753 } else if (lasthand[0]) {
754 set_user(&USERENTRY_HOSTS, u, s);
755 }
756 }
757 }
758 } else if (strcmp(code, "%") == 0) { /* exemptmasks */
759 if (lasthand[0]) {
760 if (s[0]) {
761 if ((lasthand[0] == '#') || (lasthand[0] == '+')) {
762 restore_chanexempt(cst,s);
763 }
764 else if (lasthand[0] == '*') {
765 if (lasthand[1] == 'e') {
766 restore_chanexempt(NULL, s);
767 gexempt_total++;
768 }
769 }
770 }
771 }
772 } else if (strcmp(code, "@") == 0) { /* Invitemasks */
773 if (lasthand[0]) {
774 if (s[0]) {
775 if ((lasthand[0] == '#') || (lasthand[0] == '+')) {
776 restore_chaninvite(cst,s);
777 }
778 else if (lasthand[0] == '*') {
779 if (lasthand[1] == 'I') {
780 restore_chaninvite(NULL, s);
781 ginvite_total++;
782 }
783 }
784 }
785 }
786 } else if (!strcmp(code, "!")) {
787 /* ! #chan laston flags [info] */
788 char *chname, *st, *fl;
789
790 if (u) {
791 chname = newsplit(&s);
792 st = newsplit(&s);
793 fl = newsplit(&s);
794 rmspace(s);
795 fr.match = FR_CHAN;
796 break_down_flags(fl, &fr, 0);
797 if (findchan(chname)) {
798 for (cr = u->chanrec; cr; cr = cr->next)
799 if (!rfc_casecmp(cr->channel, chname))
800 break;
801 if (!cr) {
802 cr = (struct chanuserrec *)
803 user_malloc(sizeof(struct chanuserrec));
804
805 cr->next = u->chanrec;
806 u->chanrec = cr;
807 strncpy(cr->channel, chname, 80);
808 cr->channel[80] = 0;
809 cr->laston = atoi(st);
810 cr->flags = fr.chan;
811 cr->flags_udef = fr.udef_chan;
812 if (s[0]) {
813 cr->info = (char *) user_malloc(strlen(s) + 1);
814 strcpy(cr->info, s);
815 } else
816 cr->info = NULL;
817 }
818 }
819 }
820 } else if (!strncmp(code, "::", 2)) {
821 /* channel-specific bans */
822 strcpy(lasthand, &code[2]);
823 u = NULL;
824 if (!findchan(lasthand)) {
825 strcpy(s1, lasthand);
826 strcat(s1, " ");
827 if (strstr(ignored, s1) == NULL) {
828 strcat(ignored, lasthand);
829 strcat(ignored, " ");
830 }
831 lasthand[0] = 0;
832 u = 0;
833 } else {
834 /* Remove all bans for this channel to avoid dupes */
835 /* NOTE only remove bans for when getting a userfile
836 * from another bot & that channel is shared */
837 cst = findchan(lasthand);
838 if ((*ret == userlist) || channel_shared(cst)) {
839 clear_masks(cst->bans);
840 cst->bans = NULL;
841 } else {
842 /* otherwise ignore any bans for this channel */
843 cst = NULL;
844 lasthand[0] = 0;
845 }
846 }
847 } else if (strncmp(code, "&&", 2) == 0) {
848 /* channel-specific exempts */
849 strcpy(lasthand, &code[2]);
850 u = NULL;
851 if (!findchan(lasthand)) {
852 strcpy(s1, lasthand);
853 strcat(s1, " ");
854 if (strstr(ignored, s1) == NULL) {
855 strcat(ignored, lasthand);
856 strcat(ignored, " ");
857 }
858 lasthand[0] = 0;
859 u = 0;
860 } else {
861 /* Remove all exempts for this channel to avoid dupes */
862 /* NOTE only remove exempts for when getting a userfile
863 * from another bot & that channel is shared */
864 cst = findchan(lasthand);
865 if ((*ret == userlist) || channel_shared(cst)) {
866 clear_masks(cst->exempts);
867 cst->exempts = NULL;
868 } else {
869 /* otherwise ignore any exempts for this channel */
870 cst = NULL;
871 lasthand[0] = 0;
872 }
873 }
874 } else if (strncmp(code, "$$", 2) == 0) {
875 /* channel-specific invites */
876 strcpy(lasthand, &code[2]);
877 u = NULL;
878 if (!findchan(lasthand)) {
879 strcpy(s1, lasthand);
880 strcat(s1, " ");
881 if (strstr(ignored, s1) == NULL) {
882 strcat(ignored, lasthand);
883 strcat(ignored, " ");
884 }
885 lasthand[0] = 0;
886 u = 0;
887 } else {
888 /* Remove all invites for this channel to avoid dupes */
889 /* NOTE only remove invites for when getting a userfile
890 * from another bot & that channel is shared */
891 cst = findchan(lasthand);
892 if ((*ret == userlist) || channel_shared(cst)) {
893 clear_masks(cst->invites);
894 cst->invites = NULL;
895 } else {
896 /* otherwise ignore any invites for this channel */
897 cst = NULL;
898 lasthand[0] = 0;
899 }
900 }
901 } else if (!strncmp(code, "--", 2)) {
902 /* new format storage */
903 struct user_entry *ue;
904 int ok = 0;
905
906 Context;
907 if (u) {
908 ue = u->entries;
909 for (; ue && !ok; ue = ue->next)
910 if (ue->name && !strcasecmp(code + 2, ue->name)) {
911 struct list_type *list;
912
913 list = user_malloc(sizeof(struct list_type));
914
915 list->next = NULL;
916 list->extra = user_malloc(strlen(s) + 1);
917 strcpy(list->extra, s);
918 list_append((&ue->u.list), list);
919 ok = 1;
920 }
921 if (!ok) {
922 ue = user_malloc(sizeof(struct user_entry));
923
924 ue->name = user_malloc(strlen(code + 1));
925 ue->type = NULL;
926 strcpy(ue->name, code + 2);
927 ue->u.list = user_malloc(sizeof(struct list_type));
928
929 ue->u.list->next = NULL;
930 ue->u.list->extra = user_malloc(strlen(s) + 1);
931 strcpy(ue->u.list->extra, s);
932 list_insert((&u->entries), ue);
933 }
934 }
935 } else if (!rfc_casecmp(code, BAN_NAME)) {
936 strcpy(lasthand, code);
937 u = NULL;
938 } else if (!rfc_casecmp(code, IGNORE_NAME)) {
939 strcpy(lasthand, code);
940 u = NULL;
941 } else if (!rfc_casecmp(code, EXEMPT_NAME)) {
942 strcpy(lasthand, code);
943 u = NULL;
944 } else if (!rfc_casecmp(code, INVITE_NAME)) {
945 strcpy(lasthand, code);
946 u = NULL;
947 } else if (code[0] == '*') {
948 lasthand[0] = 0;
949 u = NULL;
950 } else {
951 pass = newsplit(&s);
952 attr = newsplit(&s);
953 rmspace(s);
954 if (!attr[0] || !pass[0]) {
955 putlog(LOG_MISC, "*", "* %s '%s'!", USERF_CORRUPT, code);
956 lasthand[0] = 0;
957 } else {
958 u = get_user_by_handle(bu, code);
959 if (u && !(u->flags & USER_UNSHARED)) {
960 putlog(LOG_MISC, "*", "* %s '%s'!", USERF_DUPE, code);
961 lasthand[0] = 0;
962 u = NULL;
963 } else if (u) {
964 lasthand[0] = 0;
965 u = NULL;
966 } else {
967 fr.match = FR_GLOBAL;
968 break_down_flags(attr, &fr, 0);
969 strcpy(lasthand, code);
970 cst = NULL;
971 if (strlen(code) > HANDLEN)
972 code[HANDLEN] = 0;
973 if (strlen(pass) > 20) {
974 putlog(LOG_MISC, "*", "* %s '%s'", USERF_BROKEPASS, code);
975 strcpy(pass, "-");
976 }
977 bu = adduser(bu, code, 0, pass,
978 sanity_check(fr.global &USER_VALID));
979
980 u = get_user_by_handle(bu, code);
981 for (i = 0; i < dcc_total; i++)
982 if (!strcasecmp(code, dcc[i].nick))
983 dcc[i].user = u;
984 u->flags_udef = fr.udef_global;
985 /* if s starts with '/' it's got file info */
986 }
987 }
988 }
989 }
990 }
991 }
992 Context;
993 fclose(f);
994 (*ret) = bu;
995 if (ignored[0]) {
996 putlog(LOG_MISC, "*", "%s %s", USERF_IGNBANS, ignored);
997 }
998 putlog(LOG_MISC, "*", "Userfile loaded, unpacking...");
999 Context;
1000 for (u = bu; u; u = u->next) {
1001 struct user_entry *e;
1002
1003 if (!(u->flags & USER_BOT) && !strcasecmp (u->handle, botnetnick)) {
1004 putlog(LOG_MISC, "*", "(!) I have an user record, but without +b");
1005 /* u->flags |= USER_BOT; */
1006 }
1007
1008 for (e = u->entries; e; e = e->next)
1009 if (e->name) {
1010 struct user_entry_type *uet = find_entry_type(e->name);
1011
1012 if (uet) {
1013 e->type = uet;
1014 uet->unpack(u, e);
1015 nfree(e->name);
1016 e->name = NULL;
1017 }
1018 }
1019 }
1020 noshare = noxtra = 0;
1021 Context;
1022 /* process the user data *now* */
1023 return 1;
1024 }
1025
1026 /* New methodology - cycle through list 3 times
1027 * 1st time scan for +sh bots and link if none connected
1028 * 2nd time scan for +h bots
1029 * 3rd time scan for +a/+h bots */
1030 void autolink_cycle(char *start)
1031 {
1032 struct userrec *u = userlist, *autc = NULL;
1033 static int cycle = 0;
1034 int got_hub = 0, got_alt = 0, got_shared = 0, linked, ready = 0, i,
1035 bfl;
1036
1037 Context;
1038 /* don't start a new cycle if some links are still pending */
1039 if (!start) {
1040 for (i = 0; i < dcc_total; i++) {
1041 if (dcc[i].type == &DCC_BOT_NEW)
1042 return;
1043 if (dcc[i].type == &DCC_FORK_BOT)
1044 return;
1045 }
1046 }
1047 if (!start) {
1048 ready = 1;
1049 cycle = 0;
1050 } /* new run through the user list */
1051 while (u && !autc) {
1052 while (u && !autc) {
1053 if (u->flags & USER_BOT) {
1054 bfl = bot_flags(u);
1055 if (bfl & (BOT_HUB | BOT_ALT)) {
1056 linked = 0;
1057 for (i = 0; i < dcc_total; i++) {
1058 if (dcc[i].user == u) {
1059 if (dcc[i].type == &DCC_BOT)
1060 linked = 1;
1061 if (dcc[i].type == &DCC_BOT_NEW)
1062 linked = 1;
1063 if (dcc[i].type == &DCC_FORK_BOT)
1064 linked = 1;
1065 }
1066 }
1067 if ((bfl & BOT_HUB) && (bfl & BOT_SHARE)) {
1068 if (linked)
1069 got_shared = 1;
1070 else if ((cycle == 0) && ready && !autc)
1071 autc = u;
1072 } else if ((bfl & BOT_HUB) && cycle > 0) {
1073 if (linked)
1074 got_hub = 1;
1075 else if ((cycle == 1) && ready && !autc)
1076 autc = u;
1077 } else if ((bfl & BOT_ALT) && (cycle == 2)) {
1078 if (linked)
1079 got_alt = 1;
1080 else if (!in_chain(u->handle) && ready && !autc)
1081 autc = u;
1082 }
1083 /* did we make it where we're supposed to start? yay! */
1084 if (!ready)
1085 if (!strcasecmp(u->handle, start)) {
1086 ready = 1;
1087 autc = NULL;
1088 /* if starting point is a +h bot, must be in 2nd cycle */
1089 if ((bfl & BOT_HUB) && !(bfl & BOT_SHARE)) {
1090 cycle = 1;
1091 }
1092 /* if starting point is a +a bot, must be in 3rd cycle */
1093 if (bfl & BOT_ALT) {
1094 cycle = 2;
1095 }
1096 }
1097 }
1098 if ((cycle == 0) && (bfl & BOT_REJECT) && in_chain(u->handle)) {
1099 /* get rid of nasty reject bot */
1100 int i;
1101
1102 i = nextbot(u->handle);
1103 if ((i >= 0) && !strcasecmp(dcc[i].nick, u->handle)) {
1104 char *p = MISC_REJECTED;
1105
1106 /* we're directly connected to the offending bot?! (shudder!) */
1107 putlog(LOG_BOTS, "*", "%s %s", BOT_REJECTING, dcc[i].nick);
1108 chatout("*** %s bot %s\n", p, dcc[i].nick);
1109 botnet_send_unlinked(i, dcc[i].nick, p);
1110 dprintf(i, "bye\n");
1111 killsock(dcc[i].sock);
1112 lostdcc(i);
1113 } else if (i < 0) {
1114 /* The bot is not connected, but listed in our tandem list! */
1115 putlog(LOG_BOTS, "*", "(!) BUG: rejecting not connected bot %s!",
1116 u->handle);
1117 rembot(u->handle);
1118 }
1119 }
1120 }
1121 u = u->next;
1122 }
1123 if (!autc) {
1124 if ((cycle == 0) && !got_shared) {
1125 cycle++;
1126 u = userlist;
1127 } else if ((cycle == 1) && !(got_shared || got_hub)) {
1128 cycle++;
1129 u = userlist;
1130 }
1131 }
1132 }
1133 if (got_shared && (cycle == 0))
1134 autc = NULL;
1135 else if ((got_shared || got_hub) && (cycle == 1))
1136 autc = NULL;
1137 else if ((got_shared || got_hub || got_alt) && (cycle == 2))
1138 autc = NULL;
1139 if (autc)
1140 botlink("", -3, autc->handle); /* try autoconnect */
1141 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23