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

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

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


Revision 1.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Mon Jul 26 21:11:06 2010 UTC (8 years, 9 months ago) by simple
Branch: eggheads
CVS Tags: v1
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Imported Eggdrop 1.6.20

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23