00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "main.h"
00035 #include "users.h"
00036 #include "chan.h"
00037 #include "modules.h"
00038 #include "tandem.h"
00039 char natip[121] = "";
00040
00041 #include <netinet/in.h>
00042 #include <arpa/inet.h>
00043
00044 extern struct dcc_t *dcc;
00045 extern struct userrec *userlist, *lastuser;
00046 extern struct chanset_t *chanset;
00047 extern int dcc_total, noshare;
00048 extern char botnetnick[];
00049 extern Tcl_Interp *interp;
00050 extern time_t now;
00051
00052 char userfile[121] = "";
00053 int ignore_time = 10;
00054
00055
00056 int match_ignore(char *uhost)
00057 {
00058 struct igrec *ir;
00059
00060 for (ir = global_ign; ir; ir = ir->next)
00061 if (match_useraddr(ir->igmask, uhost))
00062 return 1;
00063 return 0;
00064 }
00065
00066 int equals_ignore(char *uhost)
00067 {
00068 struct igrec *u = global_ign;
00069
00070 for (; u; u = u->next)
00071 if (!rfc_casecmp(u->igmask, uhost)) {
00072 if (u->flags & IGREC_PERM)
00073 return 2;
00074 else
00075 return 1;
00076 }
00077 return 0;
00078 }
00079
00080 int delignore(char *ign)
00081 {
00082 int i, j;
00083 struct igrec **u;
00084 struct igrec *t;
00085 char temp[256];
00086
00087 i = 0;
00088 if (!strchr(ign, '!') && (j = atoi(ign))) {
00089 for (u = &global_ign, j--; *u && j; u = &((*u)->next), j--);
00090 if (*u) {
00091 strncpyz(temp, (*u)->igmask, sizeof temp);
00092 i = 1;
00093 }
00094 } else {
00095
00096 for (u = &global_ign; *u && !i; u = &((*u)->next))
00097 if (!rfc_casecmp(ign, (*u)->igmask)) {
00098 strncpyz(temp, ign, sizeof temp);
00099 i = 1;
00100 break;
00101 }
00102 }
00103 if (i) {
00104 if (!noshare) {
00105 char *mask = str_escape(temp, ':', '\\');
00106
00107 if (mask) {
00108 shareout(NULL, "-i %s\n", mask);
00109 nfree(mask);
00110 }
00111 }
00112 nfree((*u)->igmask);
00113 if ((*u)->msg)
00114 nfree((*u)->msg);
00115 if ((*u)->user)
00116 nfree((*u)->user);
00117 t = *u;
00118 *u = (*u)->next;
00119 nfree(t);
00120 }
00121 return i;
00122 }
00123
00124 void addignore(char *ign, char *from, char *mnote, time_t expire_time)
00125 {
00126 struct igrec *p = NULL, *l;
00127
00128 for (l = global_ign; l; l = l->next)
00129 if (!rfc_casecmp(l->igmask, ign)) {
00130 p = l;
00131 break;
00132 }
00133
00134 if (p == NULL) {
00135 p = user_malloc(sizeof(struct igrec));
00136 p->next = global_ign;
00137 global_ign = p;
00138 } else {
00139 nfree(p->igmask);
00140 nfree(p->user);
00141 nfree(p->msg);
00142 }
00143
00144 p->expire = expire_time;
00145 p->added = now;
00146 p->flags = expire_time ? 0 : IGREC_PERM;
00147 p->igmask = user_malloc(strlen(ign) + 1);
00148 strcpy(p->igmask, ign);
00149 p->user = user_malloc(strlen(from) + 1);
00150 strcpy(p->user, from);
00151 p->msg = user_malloc(strlen(mnote) + 1);
00152 strcpy(p->msg, mnote);
00153 if (!noshare) {
00154 char *mask = str_escape(ign, ':', '\\');
00155
00156 if (mask) {
00157 shareout(NULL, "+i %s %li %c %s %s\n", mask, expire_time - now,
00158 (p->flags & IGREC_PERM) ? 'p' : '-', from, mnote);
00159 nfree(mask);
00160 }
00161 }
00162 }
00163
00164
00165 void display_ignore(int idx, int number, struct igrec *ignore)
00166 {
00167 char dates[81], s[41];
00168
00169 if (ignore->added) {
00170 daysago(now, ignore->added, s);
00171 sprintf(dates, "Started %s", s);
00172 } else
00173 dates[0] = 0;
00174 if (ignore->flags & IGREC_PERM)
00175 strcpy(s, "(perm)");
00176 else {
00177 char s1[41];
00178
00179 days(ignore->expire, now, s1);
00180 sprintf(s, "(expires %s)", s1);
00181 }
00182 if (number >= 0)
00183 dprintf(idx, " [%3d] %s %s\n", number, ignore->igmask, s);
00184 else
00185 dprintf(idx, "IGNORE: %s %s\n", ignore->igmask, s);
00186 if (ignore->msg && ignore->msg[0])
00187 dprintf(idx, " %s: %s\n", ignore->user, ignore->msg);
00188 else
00189 dprintf(idx, " %s %s\n", MODES_PLACEDBY, ignore->user);
00190 if (dates[0])
00191 dprintf(idx, " %s\n", dates);
00192 }
00193
00194
00195 void tell_ignores(int idx, char *match)
00196 {
00197 struct igrec *u = global_ign;
00198 int k = 1;
00199
00200 if (u == NULL) {
00201 dprintf(idx, "No ignores.\n");
00202 return;
00203 }
00204 dprintf(idx, "%s:\n", IGN_CURRENT);
00205 for (; u; u = u->next) {
00206 if (match[0]) {
00207 if (cmp_usermasks(match, u->igmask) ||
00208 wild_match(match, u->msg) || wild_match(match, u->user))
00209 display_ignore(idx, k, u);
00210 k++;
00211 } else
00212 display_ignore(idx, k++, u);
00213 }
00214 }
00215
00216
00217 void check_expired_ignores()
00218 {
00219 struct igrec **u = &global_ign;
00220
00221 if (!*u)
00222 return;
00223
00224 while (*u) {
00225 if (!((*u)->flags & IGREC_PERM) && (now >= (*u)->expire)) {
00226 putlog(LOG_MISC, "*", "%s %s (%s)", IGN_NOLONGER, (*u)->igmask,
00227 MISC_EXPIRED);
00228 delignore((*u)->igmask);
00229 } else
00230 u = &((*u)->next);
00231 }
00232 }
00233
00234
00235
00236
00237 static void addmask_fully(struct chanset_t *chan, maskrec ** m,
00238 maskrec ** global, char *mask, char *from, char *note,
00239 time_t expire_time, int flags, time_t added,
00240 time_t last)
00241 {
00242 maskrec *p = user_malloc(sizeof(maskrec));
00243 maskrec **u = (chan) ? m : global;
00244
00245 p->next = *u;
00246 *u = p;
00247 p->expire = expire_time;
00248 p->added = added;
00249 p->lastactive = last;
00250 p->flags = flags;
00251 p->mask = user_malloc(strlen(mask) + 1);
00252 strcpy(p->mask, mask);
00253 p->user = user_malloc(strlen(from) + 1);
00254 strcpy(p->user, from);
00255 p->desc = user_malloc(strlen(note) + 1);
00256 strcpy(p->desc, note);
00257 }
00258
00259 static void restore_chanban(struct chanset_t *chan, char *host)
00260 {
00261 char *expi, *add, *last, *user, *desc;
00262 int flags = 0;
00263
00264 expi = strchr_unescape(host, ':', '\\');
00265 if (expi) {
00266 if (*expi == '+') {
00267 flags |= MASKREC_PERM;
00268 expi++;
00269 }
00270 add = strchr(expi, ':');
00271 if (add) {
00272 if (add[-1] == '*') {
00273 flags |= MASKREC_STICKY;
00274 add[-1] = 0;
00275 } else
00276 *add = 0;
00277 add++;
00278 if (*add == '+') {
00279 last = strchr(add, ':');
00280 if (last) {
00281 *last = 0;
00282 last++;
00283 user = strchr(last, ':');
00284 if (user) {
00285 *user = 0;
00286 user++;
00287 desc = strchr(user, ':');
00288 if (desc) {
00289 *desc = 0;
00290 desc++;
00291 addmask_fully(chan, &chan->bans, &global_bans, host, user,
00292 desc, atoi(expi), flags, atoi(add), atoi(last));
00293 return;
00294 }
00295 }
00296 }
00297 } else {
00298 desc = strchr(add, ':');
00299 if (desc) {
00300 *desc = 0;
00301 desc++;
00302 addmask_fully(chan, &chan->bans, &global_bans, host, add, desc,
00303 atoi(expi), flags, now, 0);
00304 return;
00305 }
00306 }
00307 }
00308 }
00309 putlog(LOG_MISC, "*", "*** Malformed banline for %s.",
00310 chan ? chan->dname : "global_bans");
00311 }
00312
00313 static void restore_chanexempt(struct chanset_t *chan, char *host)
00314 {
00315 char *expi, *add, *last, *user, *desc;
00316 int flags = 0;
00317
00318 expi = strchr_unescape(host, ':', '\\');
00319 if (expi) {
00320 if (*expi == '+') {
00321 flags |= MASKREC_PERM;
00322 expi++;
00323 }
00324 add = strchr(expi, ':');
00325 if (add) {
00326 if (add[-1] == '*') {
00327 flags |= MASKREC_STICKY;
00328 add[-1] = 0;
00329 } else
00330 *add = 0;
00331 add++;
00332 if (*add == '+') {
00333 last = strchr(add, ':');
00334 if (last) {
00335 *last = 0;
00336 last++;
00337 user = strchr(last, ':');
00338 if (user) {
00339 *user = 0;
00340 user++;
00341 desc = strchr(user, ':');
00342 if (desc) {
00343 *desc = 0;
00344 desc++;
00345 addmask_fully(chan, &chan->exempts, &global_exempts, host, user,
00346 desc, atoi(expi), flags, atoi(add), atoi(last));
00347 return;
00348 }
00349 }
00350 }
00351 } else {
00352 desc = strchr(add, ':');
00353 if (desc) {
00354 *desc = 0;
00355 desc++;
00356 addmask_fully(chan, &chan->exempts, &global_exempts, host, add,
00357 desc, atoi(expi), flags, now, 0);
00358 return;
00359 }
00360 }
00361 }
00362 }
00363 putlog(LOG_MISC, "*", "*** Malformed exemptline for %s.",
00364 chan ? chan->dname : "global_exempts");
00365 }
00366
00367 static void restore_chaninvite(struct chanset_t *chan, char *host)
00368 {
00369 char *expi, *add, *last, *user, *desc;
00370 int flags = 0;
00371
00372 expi = strchr_unescape(host, ':', '\\');
00373 if (expi) {
00374 if (*expi == '+') {
00375 flags |= MASKREC_PERM;
00376 expi++;
00377 }
00378 add = strchr(expi, ':');
00379 if (add) {
00380 if (add[-1] == '*') {
00381 flags |= MASKREC_STICKY;
00382 add[-1] = 0;
00383 } else
00384 *add = 0;
00385 add++;
00386 if (*add == '+') {
00387 last = strchr(add, ':');
00388 if (last) {
00389 *last = 0;
00390 last++;
00391 user = strchr(last, ':');
00392 if (user) {
00393 *user = 0;
00394 user++;
00395 desc = strchr(user, ':');
00396 if (desc) {
00397 *desc = 0;
00398 desc++;
00399 addmask_fully(chan, &chan->invites, &global_invites, host, user,
00400 desc, atoi(expi), flags, atoi(add), atoi(last));
00401 return;
00402 }
00403 }
00404 }
00405 } else {
00406 desc = strchr(add, ':');
00407 if (desc) {
00408 *desc = 0;
00409 desc++;
00410 addmask_fully(chan, &chan->invites, &global_invites, host, add,
00411 desc, atoi(expi), flags, now, 0);
00412 return;
00413 }
00414 }
00415 }
00416 }
00417 putlog(LOG_MISC, "*", "*** Malformed inviteline for %s.",
00418 chan ? chan->dname : "global_invites");
00419 }
00420
00421 static void restore_ignore(char *host)
00422 {
00423 char *expi, *user, *added, *desc;
00424 int flags = 0;
00425 struct igrec *p;
00426
00427 expi = strchr_unescape(host, ':', '\\');
00428 if (expi) {
00429 if (*expi == '+') {
00430 flags |= IGREC_PERM;
00431 expi++;
00432 }
00433 user = strchr(expi, ':');
00434 if (user) {
00435 *user = 0;
00436 user++;
00437 added = strchr(user, ':');
00438 if (added) {
00439 *added = 0;
00440 added++;
00441 desc = strchr(added, ':');
00442 if (desc) {
00443 *desc = 0;
00444 desc++;
00445 } else
00446 desc = NULL;
00447 } else {
00448 added = "0";
00449 desc = NULL;
00450 }
00451 p = user_malloc(sizeof(struct igrec));
00452
00453 p->next = global_ign;
00454 global_ign = p;
00455 p->expire = atoi(expi);
00456 p->added = atoi(added);
00457 p->flags = flags;
00458 p->igmask = user_malloc(strlen(host) + 1);
00459 strcpy(p->igmask, host);
00460 p->user = user_malloc(strlen(user) + 1);
00461 strcpy(p->user, user);
00462 if (desc) {
00463 p->msg = user_malloc(strlen(desc) + 1);
00464 strcpy(p->msg, desc);
00465 } else
00466 p->msg = NULL;
00467 return;
00468 }
00469 }
00470 putlog(LOG_MISC, "*", "*** Malformed ignore line.");
00471 }
00472
00473 void tell_user(int idx, struct userrec *u, int master)
00474 {
00475 char s[81], s1[81], format[81];
00476 int n = 0;
00477 time_t now2;
00478 struct chanuserrec *ch;
00479 struct user_entry *ue;
00480 struct laston_info *li;
00481 struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0, 0 };
00482
00483 fr.global = u->flags;
00484
00485 fr.udef_global = u->flags_udef;
00486 build_flags(s, &fr, NULL);
00487 if (module_find("notes", 0, 0)) {
00488 Tcl_SetVar(interp, "_user", u->handle, 0);
00489 if (Tcl_VarEval(interp, "notes ", "$_user", NULL) == TCL_OK)
00490 n = tcl_resultint();
00491 }
00492 li = get_user(&USERENTRY_LASTON, u);
00493 if (!li || !li->laston)
00494 strcpy(s1, "never");
00495 else {
00496 now2 = now - li->laston;
00497 if (now2 >= 86400)
00498 egg_strftime(s1, 11, "%Y-%m-%d", localtime(&li->laston));
00499 else
00500 egg_strftime(s1, 6, "%H:%M", localtime(&li->laston));
00501 }
00502 egg_snprintf(format, sizeof format, "%%-%us %%-5s%%5d %%-15s %%s (%%s)\n",
00503 HANDLEN);
00504 dprintf(idx, format, u->handle,
00505 get_user(&USERENTRY_PASS, u) ? "yes" : "no", n, s, s1,
00506 (li && li->lastonplace) ? li->lastonplace : "nowhere");
00507
00508 for (ch = u->chanrec; ch; ch = ch->next) {
00509 fr.match = FR_CHAN | FR_GLOBAL;
00510 get_user_flagrec(dcc[idx].user, &fr, ch->channel);
00511 if (glob_op(fr) || chan_op(fr)) {
00512 if (ch->laston == 0L)
00513 strcpy(s1, "never");
00514 else {
00515 now2 = now - (ch->laston);
00516 if (now2 >= 86400)
00517 egg_strftime(s1, 11, "%Y-%m-%d", localtime(&ch->laston));
00518 else
00519 egg_strftime(s1, 6, "%H:%M", localtime(&ch->laston));
00520 }
00521 fr.match = FR_CHAN;
00522 fr.chan = ch->flags;
00523 fr.udef_chan = ch->flags_udef;
00524 build_flags(s, &fr, NULL);
00525 egg_snprintf(format, sizeof format, "%%%us %%-18s %%-15s %%s\n",
00526 HANDLEN - 9);
00527 dprintf(idx, format, " ", ch->channel, s, s1);
00528 if (ch->info != NULL)
00529 dprintf(idx, " INFO: %s\n", ch->info);
00530 }
00531 }
00532
00533 for (ue = u->entries; ue; ue = ue->next)
00534 if (!ue->name && ue->type->display)
00535 ue->type->display(idx, ue);
00536 }
00537
00538
00539 void tell_user_ident(int idx, char *id, int master)
00540 {
00541 char format[81];
00542 struct userrec *u;
00543
00544 u = get_user_by_handle(userlist, id);
00545 if (u == NULL)
00546 u = get_user_by_host(id);
00547 if (u == NULL) {
00548 dprintf(idx, "%s.\n", USERF_NOMATCH);
00549 return;
00550 }
00551 egg_snprintf(format, sizeof format,
00552 "%%-%us PASS NOTES FLAGS LAST\n", HANDLEN);
00553 dprintf(idx, format, "HANDLE");
00554 tell_user(idx, u, master);
00555 }
00556
00557
00558
00559
00560 void tell_users_match(int idx, char *mtch, int start, int limit,
00561 int master, char *chname)
00562 {
00563 char format[81];
00564 struct userrec *u;
00565 int fnd = 0, cnt, nomns = 0, flags = 0;
00566 struct list_type *q;
00567 struct flag_record user, pls, mns;
00568
00569 dprintf(idx, "*** %s '%s':\n", MISC_MATCHING, mtch);
00570 cnt = 0;
00571 egg_snprintf(format, sizeof format,
00572 "%%-%us PASS NOTES FLAGS LAST\n", HANDLEN);
00573 dprintf(idx, format, "HANDLE");
00574 if (start > 1)
00575 dprintf(idx, "(%s %d)\n", MISC_SKIPPING, start - 1);
00576 if (strchr("+-&|", *mtch)) {
00577 user.match = pls.match = FR_GLOBAL | FR_BOT | FR_CHAN;
00578 break_down_flags(mtch, &pls, &mns);
00579 mns.match = pls.match ^ (FR_AND | FR_OR);
00580 if (!mns.global && !mns.udef_global && !mns.chan && !mns.udef_chan &&
00581 !mns.bot) {
00582 nomns = 1;
00583 if (!pls.global && !pls.udef_global && !pls.chan && !pls.udef_chan &&
00584 !pls.bot) {
00585
00586 dprintf(idx, "Unknown flag specified for matching!!\n");
00587 return;
00588 }
00589 }
00590 if (!chname || !chname[0])
00591 chname = dcc[idx].u.chat->con_chan;
00592 flags = 1;
00593 }
00594
00595 for (u = userlist; u; u = u->next) {
00596 if (flags) {
00597 get_user_flagrec(u, &user, chname);
00598 if (flagrec_eq(&pls, &user)) {
00599 if (nomns || !flagrec_eq(&mns, &user)) {
00600 cnt++;
00601 if ((cnt <= limit) && (cnt >= start)) {
00602 tell_user(idx, u, master);
00603 }
00604 if (cnt == limit + 1) {
00605 dprintf(idx, MISC_TRUNCATED, limit);
00606 }
00607 }
00608 }
00609 } else if (wild_match(mtch, u->handle)) {
00610 cnt++;
00611 if ((cnt <= limit) && (cnt >= start)) {
00612 tell_user(idx, u, master);
00613 }
00614 if (cnt == limit + 1) {
00615 dprintf(idx, MISC_TRUNCATED, limit);
00616 }
00617 } else {
00618 fnd = 0;
00619 for (q = get_user(&USERENTRY_HOSTS, u); q; q = q->next) {
00620 if (wild_match(mtch, q->extra) && !fnd) {
00621 cnt++;
00622 fnd = 1;
00623 if ((cnt <= limit) && (cnt >= start)) {
00624 tell_user(idx, u, master);
00625 }
00626 if (cnt == limit + 1) {
00627 dprintf(idx, MISC_TRUNCATED, limit);
00628 }
00629 }
00630 }
00631 }
00632 }
00633
00634 dprintf(idx, MISC_FOUNDMATCH, cnt, cnt == 1 ? "" : MISC_MATCH_PLURAL);
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 int noxtra = 0;
00670 int readuserfile(char *file, struct userrec **ret)
00671 {
00672 char *p, buf[512], lasthand[512], *attr, *pass, *code, s1[512], *s;
00673 FILE *f;
00674 struct userrec *bu, *u = NULL;
00675 struct chanset_t *cst = NULL;
00676 int i;
00677 char ignored[LOGLINEMAX];
00678 struct flag_record fr;
00679 struct chanuserrec *cr;
00680
00681 bu = (*ret);
00682 ignored[0] = 0;
00683 if (bu == userlist) {
00684 clear_chanlist();
00685 lastuser = NULL;
00686 global_bans = NULL;
00687 global_ign = NULL;
00688 global_exempts = NULL;
00689 global_invites = NULL;
00690 }
00691 lasthand[0] = 0;
00692 f = fopen(file, "r");
00693 if (f == NULL)
00694 return 0;
00695 noshare = noxtra = 1;
00696
00697 s = buf;
00698 fgets(s, 180, f);
00699 if (s[1] < '4') {
00700 fatal(USERF_OLDFMT, 0);
00701 }
00702 if (s[1] > '4')
00703 fatal(USERF_INVALID, 0);
00704 while (!feof(f)) {
00705 s = buf;
00706 fgets(s, 511, f);
00707 if (!feof(f)) {
00708 if (s[0] != '#' && s[0] != ';' && s[0]) {
00709 code = newsplit(&s);
00710 rmspace(s);
00711 if (!strcmp(code, "-")) {
00712 if (!lasthand[0])
00713 continue;
00714 if (u) {
00715 p = strchr(s, ',');
00716 while (p != NULL) {
00717 splitc(s1, s, ',');
00718 rmspace(s1);
00719 if (s1[0])
00720 set_user(&USERENTRY_HOSTS, u, s1);
00721 p = strchr(s, ',');
00722 }
00723 }
00724
00725 if (s[0]) {
00726 if (lasthand[0] && strchr(CHANMETA, lasthand[0]) != NULL)
00727 restore_chanban(cst, s);
00728 else if (lasthand[0] == '*') {
00729 if (lasthand[1] == 'i')
00730 restore_ignore(s);
00731 else
00732 restore_chanban(NULL, s);
00733 } else if (lasthand[0])
00734 set_user(&USERENTRY_HOSTS, u, s);
00735 }
00736 } else if (!strcmp(code, "%")) {
00737 if (!lasthand[0])
00738 continue;
00739 if (s[0]) {
00740 if (lasthand[0] == '#' || lasthand[0] == '+')
00741 restore_chanexempt(cst, s);
00742 else if (lasthand[0] == '*')
00743 if (lasthand[1] == 'e')
00744 restore_chanexempt(NULL, s);
00745 }
00746 } else if (!strcmp(code, "@")) {
00747 if (!lasthand[0])
00748 continue;
00749 if (s[0]) {
00750 if (lasthand[0] == '#' || lasthand[0] == '+')
00751 restore_chaninvite(cst, s);
00752 else if (lasthand[0] == '*')
00753 if (lasthand[1] == 'I')
00754 restore_chaninvite(NULL, s);
00755 }
00756 } else if (!strcmp(code, "!")) {
00757
00758 char *chname, *st, *fl;
00759
00760 if (u) {
00761 chname = newsplit(&s);
00762 st = newsplit(&s);
00763 fl = newsplit(&s);
00764 rmspace(s);
00765 fr.match = FR_CHAN;
00766 break_down_flags(fl, &fr, 0);
00767 if (findchan_by_dname(chname)) {
00768 for (cr = u->chanrec; cr; cr = cr->next)
00769 if (!rfc_casecmp(cr->channel, chname))
00770 break;
00771 if (!cr) {
00772 cr = (struct chanuserrec *)
00773 user_malloc(sizeof(struct chanuserrec));
00774
00775 cr->next = u->chanrec;
00776 u->chanrec = cr;
00777 strncpyz(cr->channel, chname, 80);
00778 cr->laston = atoi(st);
00779 cr->flags = fr.chan;
00780 cr->flags_udef = fr.udef_chan;
00781 if (s[0]) {
00782 cr->info = (char *) user_malloc(strlen(s) + 1);
00783 strcpy(cr->info, s);
00784 } else
00785 cr->info = NULL;
00786 }
00787 }
00788 }
00789 } else if (!strncmp(code, "::", 2)) {
00790
00791 strcpy(lasthand, &code[2]);
00792 u = NULL;
00793 if (!findchan_by_dname(lasthand)) {
00794 strcpy(s1, lasthand);
00795 strcat(s1, " ");
00796 if (strstr(ignored, s1) == NULL) {
00797 strncat(ignored, lasthand,
00798 sizeof(ignored) - 1 - strlen(ignored));
00799 strncat(ignored, " ",
00800 sizeof(ignored) - 1 - strlen(ignored));
00801 }
00802 lasthand[0] = 0;
00803 } else {
00804
00805
00806
00807 cst = findchan_by_dname(lasthand);
00808 if ((*ret == userlist) || channel_shared(cst)) {
00809 clear_masks(cst->bans);
00810 cst->bans = NULL;
00811 } else {
00812
00813 cst = NULL;
00814 lasthand[0] = 0;
00815 }
00816 }
00817 } else if (!strncmp(code, "&&", 2)) {
00818
00819 strcpy(lasthand, &code[2]);
00820 u = NULL;
00821 if (!findchan_by_dname(lasthand)) {
00822 strcpy(s1, lasthand);
00823 strcat(s1, " ");
00824 if (strstr(ignored, s1) == NULL) {
00825 strncat(ignored, lasthand,
00826 sizeof(ignored) - 1 - strlen(ignored));
00827 strncat(ignored, " ",
00828 sizeof(ignored) - 1 - strlen(ignored));
00829 }
00830 lasthand[0] = 0;
00831 } else {
00832
00833
00834
00835 cst = findchan_by_dname(lasthand);
00836 if ((*ret == userlist) || channel_shared(cst)) {
00837 clear_masks(cst->exempts);
00838 cst->exempts = NULL;
00839 } else {
00840
00841 cst = NULL;
00842 lasthand[0] = 0;
00843 }
00844 }
00845 } else if (!strncmp(code, "$$", 2)) {
00846
00847 strcpy(lasthand, &code[2]);
00848 u = NULL;
00849 if (!findchan_by_dname(lasthand)) {
00850 strcpy(s1, lasthand);
00851 strcat(s1, " ");
00852 if (strstr(ignored, s1) == NULL) {
00853 strncat(ignored, lasthand,
00854 sizeof(ignored) - 1 - strlen(ignored));
00855 strncat(ignored, " ",
00856 sizeof(ignored) - 1 - strlen(ignored));
00857 }
00858 lasthand[0] = 0;
00859 } else {
00860
00861
00862
00863 cst = findchan_by_dname(lasthand);
00864 if ((*ret == userlist) || channel_shared(cst)) {
00865 clear_masks(cst->invites);
00866 cst->invites = NULL;
00867 } else {
00868
00869 cst = NULL;
00870 lasthand[0] = 0;
00871 }
00872 }
00873 } else if (!strncmp(code, "--", 2)) {
00874 if (u) {
00875
00876 struct user_entry *ue;
00877 int ok = 0;
00878
00879 for (ue = u->entries; ue && !ok; ue = ue->next)
00880 if (ue->name && !egg_strcasecmp(code + 2, ue->name)) {
00881 struct list_type *list;
00882
00883 list = user_malloc(sizeof(struct list_type));
00884
00885 list->next = NULL;
00886 list->extra = user_malloc(strlen(s) + 1);
00887 strcpy(list->extra, s);
00888 egg_list_append((&ue->u.list), list);
00889 ok = 1;
00890 }
00891 if (!ok) {
00892 ue = user_malloc(sizeof(struct user_entry));
00893
00894 ue->name = user_malloc(strlen(code + 1));
00895 ue->type = NULL;
00896 strcpy(ue->name, code + 2);
00897 ue->u.list = user_malloc(sizeof(struct list_type));
00898
00899 ue->u.list->next = NULL;
00900 ue->u.list->extra = user_malloc(strlen(s) + 1);
00901 strcpy(ue->u.list->extra, s);
00902 list_insert((&u->entries), ue);
00903 }
00904 }
00905 } else if (!rfc_casecmp(code, BAN_NAME)) {
00906 strcpy(lasthand, code);
00907 u = NULL;
00908 } else if (!rfc_casecmp(code, IGNORE_NAME)) {
00909 strcpy(lasthand, code);
00910 u = NULL;
00911 } else if (!rfc_casecmp(code, EXEMPT_NAME)) {
00912 strcpy(lasthand, code);
00913 u = NULL;
00914 } else if (!rfc_casecmp(code, INVITE_NAME)) {
00915 strcpy(lasthand, code);
00916 u = NULL;
00917 } else if (code[0] == '*') {
00918 lasthand[0] = 0;
00919 u = NULL;
00920 } else {
00921 pass = newsplit(&s);
00922 attr = newsplit(&s);
00923 rmspace(s);
00924 if (!attr[0] || !pass[0]) {
00925 putlog(LOG_MISC, "*", "* %s '%s'!", USERF_CORRUPT, code);
00926 lasthand[0] = 0;
00927 } else {
00928 u = get_user_by_handle(bu, code);
00929 if (u && !(u->flags & USER_UNSHARED)) {
00930 putlog(LOG_MISC, "*", "* %s '%s'!", USERF_DUPE, code);
00931 lasthand[0] = 0;
00932 u = NULL;
00933 } else if (u) {
00934 lasthand[0] = 0;
00935 u = NULL;
00936 } else {
00937 fr.match = FR_GLOBAL;
00938 break_down_flags(attr, &fr, 0);
00939 strcpy(lasthand, code);
00940 cst = NULL;
00941 if (strlen(code) > HANDLEN)
00942 code[HANDLEN] = 0;
00943 if (strlen(pass) > 20) {
00944 putlog(LOG_MISC, "*", "* %s '%s'", USERF_BROKEPASS, code);
00945 strcpy(pass, "-");
00946 }
00947 bu = adduser(bu, code, 0, pass,
00948 sanity_check(fr.global &USER_VALID));
00949
00950 u = get_user_by_handle(bu, code);
00951 for (i = 0; i < dcc_total; i++)
00952 if (!egg_strcasecmp(code, dcc[i].nick))
00953 dcc[i].user = u;
00954 u->flags_udef = fr.udef_global;
00955
00956 }
00957 }
00958 }
00959 }
00960 }
00961 }
00962 fclose(f);
00963 (*ret) = bu;
00964 if (ignored[0]) {
00965 putlog(LOG_MISC, "*", "%s %s", USERF_IGNBANS, ignored);
00966 }
00967 putlog(LOG_MISC, "*", "Userfile loaded, unpacking...");
00968 for (u = bu; u; u = u->next) {
00969 struct user_entry *e;
00970
00971 if (!(u->flags & USER_BOT) && !egg_strcasecmp(u->handle, botnetnick)) {
00972 putlog(LOG_MISC, "*", "(!) I have a user record, but without +b");
00973
00974 }
00975
00976 for (e = u->entries; e; e = e->next)
00977 if (e->name) {
00978 struct user_entry_type *uet = find_entry_type(e->name);
00979
00980 if (uet) {
00981 e->type = uet;
00982 uet->unpack(u, e);
00983 nfree(e->name);
00984 e->name = NULL;
00985 }
00986 }
00987 }
00988 noshare = noxtra = 0;
00989
00990 return 1;
00991 }
00992
00993
00994
00995
00996
00997 void autolink_cycle(char *start)
00998 {
00999 struct userrec *u = userlist, *autc = NULL;
01000 static int cycle = 0;
01001 int got_hub = 0, got_alt = 0, got_shared = 0, linked, ready = 0, i, bfl;
01002
01003
01004 if (!start) {
01005 for (i = 0; i < dcc_total; i++) {
01006 if (dcc[i].type == &DCC_BOT_NEW)
01007 return;
01008 if (dcc[i].type == &DCC_FORK_BOT)
01009 return;
01010 if ((dcc[i].type == &DCC_DNSWAIT) &&
01011 (dcc[i].u.dns && (dcc[i].u.dns->type == &DCC_FORK_BOT)))
01012 return;
01013 }
01014 }
01015 if (!start) {
01016 ready = 1;
01017 cycle = 0;
01018 }
01019 while (u && !autc) {
01020 while (u && !autc) {
01021 if (u->flags & USER_BOT && strcmp(u->handle, botnetnick)) {
01022 bfl = bot_flags(u);
01023 if (bfl & (BOT_HUB | BOT_ALT)) {
01024 linked = 0;
01025 for (i = 0; i < dcc_total; i++) {
01026 if (dcc[i].user == u) {
01027 if (dcc[i].type == &DCC_BOT)
01028 linked = 1;
01029 if (dcc[i].type == &DCC_BOT_NEW)
01030 linked = 1;
01031 if (dcc[i].type == &DCC_FORK_BOT)
01032 linked = 1;
01033 }
01034 }
01035 if ((bfl & BOT_HUB) && (bfl & BOT_SHARE)) {
01036 if (linked)
01037 got_shared = 1;
01038 else if (!cycle && ready && !autc)
01039 autc = u;
01040 } else if ((bfl & BOT_HUB) && cycle > 0) {
01041 if (linked)
01042 got_hub = 1;
01043 else if ((cycle == 1) && ready && !autc)
01044 autc = u;
01045 } else if ((bfl & BOT_ALT) && (cycle == 2)) {
01046 if (linked)
01047 got_alt = 1;
01048 else if (!in_chain(u->handle) && ready && !autc)
01049 autc = u;
01050 }
01051
01052 if (!ready)
01053 if (!egg_strcasecmp(u->handle, start)) {
01054 ready = 1;
01055 autc = NULL;
01056
01057 if ((bfl & BOT_HUB) && !(bfl & BOT_SHARE)) {
01058 cycle = 1;
01059 }
01060
01061 if (bfl & BOT_ALT) {
01062 cycle = 2;
01063 }
01064 }
01065 }
01066 if (!cycle && (bfl & BOT_REJECT) && in_chain(u->handle)) {
01067
01068 int i;
01069
01070 i = nextbot(u->handle);
01071 if ((i >= 0) && !egg_strcasecmp(dcc[i].nick, u->handle)) {
01072 char *p = MISC_REJECTED;
01073
01074
01075 putlog(LOG_BOTS, "*", "%s %s", BOT_REJECTING, dcc[i].nick);
01076 chatout("*** %s bot %s\n", p, dcc[i].nick);
01077 botnet_send_unlinked(i, dcc[i].nick, p);
01078 dprintf(i, "bye %s\n", BOT_REJECTING);
01079 killsock(dcc[i].sock);
01080 lostdcc(i);
01081 } else if ((i < 0) && egg_strcasecmp(botnetnick, u->handle)) {
01082
01083 putlog(LOG_BOTS, "*", "(!) BUG: rejecting not connected bot %s!",
01084 u->handle);
01085 rembot(u->handle);
01086 }
01087 }
01088 }
01089 u = u->next;
01090 }
01091 if (!autc) {
01092 if (!cycle && !got_shared) {
01093 cycle++;
01094 u = userlist;
01095 } else if ((cycle == 1) && !(got_shared || got_hub)) {
01096 cycle++;
01097 u = userlist;
01098 }
01099 }
01100 }
01101 if (got_shared && !cycle)
01102 autc = NULL;
01103 else if ((got_shared || got_hub) && (cycle == 1))
01104 autc = NULL;
01105 else if ((got_shared || got_hub || got_alt) && (cycle == 2))
01106 autc = NULL;
01107 if (autc)
01108 botlink("", -3, autc->handle);
01109 }