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

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

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


Revision 1.2 - (hide annotations) (download) (as text)
Thu Aug 5 18:12:05 2010 UTC (9 years, 2 months ago) by pseudo
Branch: MAIN
CVS Tags: HEAD
Branch point for: gettext
Changes since 1.1: +1 -2 lines
File MIME type: text/x-chdr
Added new, full IPv6 support to eggdrop.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23