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

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

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


Revision 1.2.2.2 - (show 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 /*
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.2.2.1 2010/11/08 10:02:33 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
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", _("placed by"), 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, _("Currently ignoring:\n"));
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, "*", _("No longer ignoring %s (expired)"), (*u)->igmask);
226 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 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 }
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 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 }
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 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 }
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 putlog(LOG_MISC, "*", _("*** Malformed ignore line."));
475 }
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 strftime(s1, 11, "%Y-%m-%d", localtime(&li->laston));
503 else
504 strftime(s1, 6, "%H:%M", localtime(&li->laston));
505 }
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 strftime(s1, 11, "%Y-%m-%d", localtime(&ch->laston));
522 else
523 strftime(s1, 6, "%H:%M", localtime(&ch->laston));
524 }
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 dprintf(idx, _("Can't find anyone matching that.\n"));
553 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 dprintf(idx, _("*** Matching '%s':\n"), mtch);
574 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 dprintf(idx, _("(skipping first %d)\n"), start - 1);
580 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 dprintf(idx, _("Unknown flag specified for matching!!\n"));
591 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 dprintf(idx, _("(more than %d matches; list truncated)\n"), limit);
610 }
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 dprintf(idx, _("(more than %d matches; list truncated)\n"), limit);
620 }
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 dprintf(idx, _("(more than %d matches; list truncated)\n"), limit);
632 }
633 }
634 }
635 }
636 }
637
638 dprintf(idx, P_("--- Found one match.\n", "--- Found %d matches.\n", cnt), cnt);
639 }
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 snprintf(buf, sizeof buf, _("Old userfile. Use '%s' to convert"),
705 "tclsh scripts/weed <userfile> c");
706 fatal(buf, 0);
707 }
708 if (s[1] > '4')
709 fatal(_("Invalid userfile format."), 0);
710 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 putlog(LOG_MISC, "*", _("* Corrupt user record '%s'!"), code);
932 lasthand[0] = 0;
933 } else {
934 u = get_user_by_handle(bu, code);
935 if (u && !(u->flags & USER_UNSHARED)) {
936 putlog(LOG_MISC, "*", _("* Duplicate user record '%s'!"), code);
937 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 putlog(LOG_MISC, "*", _("* Corrupted password reset for '%s'"), code);
951 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 putlog(LOG_MISC, "*", _("Ignored masks for channel(s): %s"), ignored);
972 }
973 putlog(LOG_MISC, "*", _("Userfile loaded, unpacking..."));
974 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 putlog(LOG_MISC, "*", _("(!) I have a user record, but without +b"));
979 /* 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 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 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 putlog(LOG_BOTS, "*", _("(!) BUG: rejecting not connected bot %s!"),
1088 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