/[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.2.2 - (hide annotations) (download) (as text)
Wed Jan 12 13:54:00 2011 UTC (8 years, 6 months ago) by pseudo
Branch: gettext
Changes since 1.2.2.1: +5 -5 lines
File MIME type: text/x-chdr
Removed memcpy(), memset() and strftime() compatibility replacements.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23