/[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.1 - (hide annotations) (download) (as text)
Mon Jul 26 21:11:06 2010 UTC (9 years, 2 months ago) by simple
Branch: MAIN
Branch point for: eggheads
File MIME type: text/x-chdr
Initial revision

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     * $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