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 struct chanuserrec *get_chanrec(struct userrec *u, char *chname)
00030 {
00031 struct chanuserrec *ch;
00032
00033 for (ch = u->chanrec; ch; ch = ch->next)
00034 if (!irccmp(ch->channel, chname))
00035 return ch;
00036 return NULL;
00037 }
00038
00039 static struct chanuserrec *add_chanrec(struct userrec *u, char *chname)
00040 {
00041 struct chanuserrec *ch = NULL;
00042
00043 if (findchan_by_dname(chname)) {
00044 ch = malloc(sizeof(struct chanuserrec));
00045
00046 ch->next = u->chanrec;
00047 u->chanrec = ch;
00048 ch->info = NULL;
00049 ch->flags = 0;
00050 ch->flags_udef = 0;
00051 ch->laston = 0;
00052 strlcpy(ch->channel, chname, sizeof ch->channel);
00053 }
00054 return ch;
00055 }
00056
00057 static void add_chanrec_by_handle(struct userrec *bu, char *hand, char *chname)
00058 {
00059 struct userrec *u;
00060
00061 u = get_user_by_handle(bu, hand);
00062 if (!u)
00063 return;
00064 if (!get_chanrec(u, chname))
00065 add_chanrec(u, chname);
00066 }
00067
00068 static void get_handle_chaninfo(char *handle, char *chname, char *s)
00069 {
00070 struct userrec *u;
00071 struct chanuserrec *ch;
00072
00073 u = get_user_by_handle(userlist, handle);
00074 if (u == NULL) {
00075 s[0] = 0;
00076 return;
00077 }
00078 ch = get_chanrec(u, chname);
00079 if (ch == NULL) {
00080 s[0] = 0;
00081 return;
00082 }
00083 if (ch->info == NULL) {
00084 s[0] = 0;
00085 return;
00086 }
00087 strcpy(s, ch->info);
00088 return;
00089 }
00090
00091 static void set_handle_chaninfo(struct userrec *bu, char *handle,
00092 char *chname, char *info)
00093 {
00094 struct userrec *u;
00095 struct chanuserrec *ch;
00096 struct chanset_t *cst;
00097
00098 u = get_user_by_handle(bu, handle);
00099 if (!u)
00100 return;
00101 ch = get_chanrec(u, chname);
00102 if (!ch) {
00103 add_chanrec_by_handle(bu, handle, chname);
00104 ch = get_chanrec(u, chname);
00105 }
00106 if (info)
00107 if (strlen(info) > 80)
00108 info[80] = 0;
00109 if (ch->info != NULL)
00110 free(ch->info);
00111 if (info && info[0])
00112 ch->info = strdup(info);
00113 else
00114 ch->info = NULL;
00115 cst = findchan_by_dname(chname);
00116 }
00117
00118 static void del_chanrec(struct userrec *u, char *chname)
00119 {
00120 struct chanuserrec *ch = u->chanrec, *lst = NULL;
00121
00122 while (ch) {
00123 if (!irccmp(chname, ch->channel)) {
00124 if (lst == NULL)
00125 u->chanrec = ch->next;
00126 else
00127 lst->next = ch->next;
00128 if (ch->info != NULL)
00129 free(ch->info);
00130 free(ch);
00131 return;
00132 }
00133 lst = ch;
00134 ch = ch->next;
00135 }
00136 }
00137
00138 static void set_handle_laston(char *chan, struct userrec *u, time_t n)
00139 {
00140 struct chanuserrec *ch;
00141
00142 if (!u)
00143 return;
00144 touch_laston(u, chan, n);
00145 ch = get_chanrec(u, chan);
00146 if (!ch)
00147 return;
00148 ch->laston = n;
00149 }
00150
00151
00152
00153 static int u_sticky_mask(maskrec *u, char *uhost)
00154 {
00155 for (; u; u = u->next)
00156 if (!irccmp(u->mask, uhost))
00157 return (u->flags & MASKREC_STICKY);
00158 return 0;
00159 }
00160
00161
00162
00163 static int u_setsticky_mask(int type, struct chanset_t *chan, char *uhost,
00164 int sticky)
00165 {
00166 int j;
00167 maskrec *u;
00168 char *botcmd;
00169
00170 if (type == 'b') {
00171 if (chan) u = chan->bans;
00172 else u = global_bans;
00173 botcmd = "s";
00174 }
00175 else if (type == 'I') {
00176 if (chan) u = chan->invites;
00177 else u = global_invites;
00178 botcmd = "sInv";
00179 }
00180 else if (type == 'e') {
00181 if (chan) u = chan->exempts;
00182 else u = global_exempts;
00183 botcmd = "se";
00184 }
00185 else return(-1);
00186
00187 j = atoi(uhost);
00188 if (!j)
00189 j = (-1);
00190 while(u) {
00191 if (j >= 0)
00192 j--;
00193
00194 if (!j || ((j < 0) && !irccmp(u->mask, uhost))) {
00195 if (sticky > 0)
00196 u->flags |= MASKREC_STICKY;
00197 else if (!sticky)
00198 u->flags &= ~MASKREC_STICKY;
00199 else
00200 return 0;
00201 if (!j)
00202 strcpy(uhost, u->mask);
00203 return 1;
00204 }
00205
00206 u = u->next;
00207 }
00208 if (j >= 0)
00209 return -j;
00210
00211 return 0;
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221 static int u_equals_mask(maskrec *u, char *mask)
00222 {
00223 for (; u; u = u->next)
00224 if (!irccmp(u->mask, mask)) {
00225 if (u->flags & MASKREC_PERM)
00226 return 2;
00227 else
00228 return 1;
00229 }
00230 return 0;
00231 }
00232
00233 static int u_match_mask(maskrec *rec, char *mask)
00234 {
00235 for (; rec; rec = rec->next)
00236 if (wild_match(rec->mask, mask))
00237 return 1;
00238 return 0;
00239 }
00240
00241 static int u_delmask(char type, struct chanset_t *c, char *who, int doit)
00242 {
00243 int j, i = 0;
00244 maskrec **u = NULL, *t;
00245 char temp[256];
00246
00247 if (type == 'b')
00248 u = c ? &c->bans : &global_bans;
00249 if (type == 'e')
00250 u = c ? &c->exempts : &global_exempts;
00251 if (type == 'I')
00252 u = c ? &c->invites : &global_invites;
00253
00254 if (!strchr(who, '!') && (j = atoi(who))) {
00255 j--;
00256 for (; (*u) && j; u = &((*u)->next), j--);
00257 if (*u) {
00258 strlcpy(temp, (*u)->mask, sizeof temp);
00259 i = 1;
00260 } else
00261 return -j - 1;
00262 } else {
00263
00264 for (; *u && !i; u = &((*u)->next))
00265 if (!irccmp((*u)->mask, who)) {
00266 strlcpy(temp, who, sizeof temp);
00267 i = 1;
00268 break;
00269 }
00270 if (!*u)
00271 return 0;
00272 }
00273 if (i && doit) {
00274 if (lastdeletedmask)
00275 free(lastdeletedmask);
00276 lastdeletedmask = (*u)->mask;
00277 if ((*u)->desc)
00278 free((*u)->desc);
00279 if ((*u)->user)
00280 free((*u)->user);
00281 t = *u;
00282 *u = (*u)->next;
00283 free(t);
00284 }
00285 return i;
00286 }
00287
00288
00289
00290 static int u_addmask(char type, struct chanset_t *chan, char *who, char *from,
00291 char *note, time_t expire_time, int flags)
00292 {
00293 char host[1024], s[1024];
00294 maskrec *p = NULL, *l, **u = NULL;
00295 module_entry *me;
00296
00297 if (type == 'b')
00298 u = chan ? &chan->bans : &global_bans;
00299 if (type == 'e')
00300 u = chan ? &chan->exempts : &global_exempts;
00301 if (type == 'I')
00302 u = chan ? &chan->invites : &global_invites;
00303
00304 strlcpy(host, who, sizeof host);
00305
00306
00307 if ((strchr(host, '!') == NULL) && (strchr(host, '@') == NULL))
00308 strcat(host, "!*@*");
00309 else if (strchr(host, '@') == NULL)
00310 strcat(host, "@*");
00311 else if (strchr(host, '!') == NULL) {
00312 char *i = strchr(host, '@');
00313
00314 strcpy(s, i);
00315 *i = 0;
00316 strcat(host, "!*");
00317 strcat(host, s);
00318 }
00319 if ((me = module_find("server", 0, 0)) && me->funcs)
00320 simple_sprintf(s, "%s!%s", me->funcs[SERVER_BOTNAME],
00321 me->funcs[SERVER_BOTUSERHOST]);
00322 else
00323 s[0] = 0;
00324 if (s[0] && type == 'b' && wild_match(host, s)) {
00325 putlog(LOG_MISC, "*", _("Wanted to ban myself--deflected."));
00326 return 0;
00327 }
00328 if (expire_time == now)
00329 return 1;
00330
00331 for (l = *u; l; l = l->next)
00332 if (!irccmp(l->mask, host)) {
00333 p = l;
00334 break;
00335 }
00336
00337
00338 if (note[0] == '*') {
00339 flags |= MASKREC_STICKY;
00340 note++;
00341 }
00342 if ((expire_time == 0L) || (flags & MASKREC_PERM)) {
00343 flags |= MASKREC_PERM;
00344 expire_time = 0L;
00345 }
00346
00347 if (p == NULL) {
00348 p = malloc(sizeof(maskrec));
00349 p->next = *u;
00350 *u = p;
00351 } else {
00352 free(p->mask);
00353 free(p->user);
00354 free(p->desc);
00355 }
00356 p->expire = expire_time;
00357 p->added = now;
00358 p->lastactive = 0;
00359 p->flags = flags;
00360 p->mask = strdup(host);
00361 p->user = strdup(from);
00362 p->desc = strdup(note);
00363 return 1;
00364 }
00365
00366
00367
00368 static void display_ban(int idx, int number, maskrec *ban,
00369 struct chanset_t *chan, int show_inact)
00370 {
00371 char dates[81], s[41];
00372
00373 if (ban->added) {
00374 daysago(now, ban->added, s);
00375 sprintf(dates, "%s %s", _("Created"), s);
00376 if (ban->added < ban->lastactive) {
00377 strcat(dates, ", ");
00378 strcat(dates, _("last used"));
00379 strcat(dates, " ");
00380 daysago(now, ban->lastactive, s);
00381 strcat(dates, s);
00382 }
00383 } else
00384 dates[0] = 0;
00385 if (ban->flags & MASKREC_PERM)
00386 strcpy(s, "(perm)");
00387 else {
00388 char s1[41];
00389
00390 days(ban->expire, now, s1);
00391 sprintf(s, "(expires %s)", s1);
00392 }
00393 if (ban->flags & MASKREC_STICKY)
00394 strcat(s, " (sticky)");
00395 if (!chan || ischanban(chan, ban->mask)) {
00396 if (number >= 0) {
00397 dprintf(idx, " [%3d] %s %s\n", number, ban->mask, s);
00398 } else {
00399 dprintf(idx, "BAN: %s %s\n", ban->mask, s);
00400 }
00401 } else if (show_inact) {
00402 if (number >= 0) {
00403 dprintf(idx, "! [%3d] %s %s\n", number, ban->mask, s);
00404 } else {
00405 dprintf(idx, "BAN (%s): %s %s\n", _("inactive"), ban->mask, s);
00406 }
00407 } else
00408 return;
00409 dprintf(idx, " %s: %s\n", ban->user, ban->desc);
00410 if (dates[0])
00411 dprintf(idx, " %s\n", dates);
00412 }
00413
00414
00415
00416 static void display_exempt(int idx, int number, maskrec *exempt,
00417 struct chanset_t *chan, int show_inact)
00418 {
00419 char dates[81], s[41];
00420
00421 if (exempt->added) {
00422 daysago(now, exempt->added, s);
00423 sprintf(dates, "%s %s", _("Created"), s);
00424 if (exempt->added < exempt->lastactive) {
00425 strcat(dates, ", ");
00426 strcat(dates, _("last used"));
00427 strcat(dates, " ");
00428 daysago(now, exempt->lastactive, s);
00429 strcat(dates, s);
00430 }
00431 } else
00432 dates[0] = 0;
00433 if (exempt->flags & MASKREC_PERM)
00434 strcpy(s, "(perm)");
00435 else {
00436 char s1[41];
00437
00438 days(exempt->expire, now, s1);
00439 sprintf(s, "(expires %s)", s1);
00440 }
00441 if (exempt->flags & MASKREC_STICKY)
00442 strcat(s, " (sticky)");
00443 if (!chan || ischanexempt(chan, exempt->mask)) {
00444 if (number >= 0) {
00445 dprintf(idx, " [%3d] %s %s\n", number, exempt->mask, s);
00446 } else {
00447 dprintf(idx, "EXEMPT: %s %s\n", exempt->mask, s);
00448 }
00449 } else if (show_inact) {
00450 if (number >= 0) {
00451 dprintf(idx, "! [%3d] %s %s\n", number, exempt->mask, s);
00452 } else {
00453 dprintf(idx, "EXEMPT (%s): %s %s\n", _("inactive"), exempt->mask, s);
00454 }
00455 } else
00456 return;
00457 dprintf(idx, " %s: %s\n", exempt->user, exempt->desc);
00458 if (dates[0])
00459 dprintf(idx, " %s\n", dates);
00460 }
00461
00462
00463
00464 static void display_invite (int idx, int number, maskrec *invite,
00465 struct chanset_t *chan, int show_inact)
00466 {
00467 char dates[81], s[41];
00468
00469 if (invite->added) {
00470 daysago(now, invite->added, s);
00471 sprintf(dates, "%s %s", _("Created"), s);
00472 if (invite->added < invite->lastactive) {
00473 strcat(dates, ", ");
00474 strcat(dates, _("last used"));
00475 strcat(dates, " ");
00476 daysago(now, invite->lastactive, s);
00477 strcat(dates, s);
00478 }
00479 } else
00480 dates[0] = 0;
00481 if (invite->flags & MASKREC_PERM)
00482 strcpy(s, "(perm)");
00483 else {
00484 char s1[41];
00485
00486 days(invite->expire, now, s1);
00487 sprintf(s, "(expires %s)", s1);
00488 }
00489 if (invite->flags & MASKREC_STICKY)
00490 strcat(s, " (sticky)");
00491 if (!chan || ischaninvite(chan, invite->mask)) {
00492 if (number >= 0) {
00493 dprintf(idx, " [%3d] %s %s\n", number, invite->mask, s);
00494 } else {
00495 dprintf(idx, "INVITE: %s %s\n", invite->mask, s);
00496 }
00497 } else if (show_inact) {
00498 if (number >= 0) {
00499 dprintf(idx, "! [%3d] %s %s\n", number, invite->mask, s);
00500 } else {
00501 dprintf(idx, "INVITE (%s): %s %s\n", _("inactive"), invite->mask, s);
00502 }
00503 } else
00504 return;
00505 dprintf(idx, " %s: %s\n", invite->user, invite->desc);
00506 if (dates[0])
00507 dprintf(idx, " %s\n", dates);
00508 }
00509
00510 static void tell_bans(int idx, int show_inact, char *match)
00511 {
00512 char *p = NULL, *chname;
00513 int k = 1;
00514 struct chanset_t *chan = NULL;
00515 maskrec *u;
00516
00517
00518 if (match[0]) {
00519 p = strdup(match);
00520 chname = strtok(p, " ");
00521 if (chname && (strchr(CHANMETA, chname[0]))) {
00522 chan = findchan_by_dname(chname);
00523 if (!chan) {
00524 dprintf(idx, "%s.\n", _("No such channel defined"));
00525 return;
00526 }
00527 } else
00528 match = chname;
00529 if (p)
00530 free_null(p);
00531 }
00532
00533
00534 if (!chan && !(chan = findchan_by_dname(dcc[idx].u.chat->con_chan)) &&
00535 !(chan = chanset))
00536 chan = NULL;
00537
00538 if (chan && show_inact)
00539 dprintf(idx, "%s: (! = %s %s)\n", _("Global bans"),
00540 _("not active on"), chan->dname);
00541 else
00542 dprintf(idx, "%s:\n", _("Global bans"));
00543 for (u = global_bans; u; u = u->next) {
00544 if (match[0]) {
00545 if ((wild_match(match, u->mask)) ||
00546 (wild_match(match, u->desc)) ||
00547 (wild_match(match, u->user)))
00548 display_ban(idx, k, u, chan, 1);
00549 k++;
00550 } else
00551 display_ban(idx, k++, u, chan, show_inact);
00552 }
00553 if (chan) {
00554 if (show_inact)
00555 dprintf(idx, _("Channel bans for %s: (! = not active, * = not placed by bot)\n"),
00556 chan->dname);
00557 else
00558 dprintf(idx, _("Channel bans for %s: (* = not placed by bot)\n"),
00559 chan->dname);
00560 for (u = chan->bans; u; u = u->next) {
00561 if (match[0]) {
00562 if ((wild_match(match, u->mask)) ||
00563 (wild_match(match, u->desc)) ||
00564 (wild_match(match, u->user)))
00565 display_ban(idx, k, u, chan, 1);
00566 k++;
00567 } else
00568 display_ban(idx, k++, u, chan, show_inact);
00569 }
00570 if (chan->status & CHAN_ACTIVE) {
00571 masklist *b;
00572
00573 char buf[UHOSTLEN], *nick, *uhost, fill[UHOSTLEN * 2];
00574 int min, sec;
00575
00576 for (b = chan->channel.ban; b && b->mask[0]; b = b->next) {
00577 if ((!u_equals_mask(global_bans, b->mask)) &&
00578 (!u_equals_mask(chan->bans, b->mask))) {
00579 strlcpy(buf, b->who, sizeof buf);
00580 nick = strtok(buf, "!");
00581 uhost = strtok(NULL, "!");
00582 if (nick)
00583 sprintf(fill, "%s (%s!%s)", b->mask, nick, uhost);
00584 else
00585 sprintf(fill, "%s (server %s)", b->mask, uhost);
00586 if (b->timer != 0) {
00587 min = (now - b->timer) / 60;
00588 sec = (now - b->timer) - (min * 60);
00589 sprintf(buf, " (active %02d:%02d)", min, sec);
00590 strcat(fill, buf);
00591 }
00592 if ((!match[0]) || (wild_match(match, b->mask)))
00593 dprintf(idx, "* [%3d] %s\n", k, fill);
00594 k++;
00595 }
00596 }
00597 }
00598 }
00599 if (k == 1)
00600 dprintf(idx, _("(There are no bans, permanent or otherwise.)\n"));
00601 if ((!show_inact) && (!match[0]))
00602 dprintf(idx, _("Use .bans all to see the total list.\n"));
00603 }
00604
00605 static void tell_exempts(int idx, int show_inact, char *match)
00606 {
00607 char *p = NULL, *chname;
00608 int k = 1;
00609 struct chanset_t *chan = NULL;
00610 maskrec *u;
00611
00612
00613 if (match[0]) {
00614 p = strdup(match);
00615 chname = strtok(p, " ");
00616 if (chname && (strchr(CHANMETA, chname[0]))) {
00617 chan = findchan_by_dname(chname);
00618 if (!chan) {
00619 dprintf(idx, _("No such channel defined.\n"));
00620 return;
00621 }
00622 } else
00623 match = chname;
00624 if (p)
00625 free_null(p);
00626 }
00627
00628
00629 if (!chan && !(chan = findchan_by_dname(dcc[idx].u.chat->con_chan))
00630 && !(chan = chanset))
00631 chan = NULL;
00632
00633 if (chan && show_inact)
00634 dprintf(idx, "%s: (! = %s %s)\n", _("Global exempts"),
00635 _("not active on"), chan->dname);
00636 else
00637 dprintf(idx, _("Global exempts:\n"));
00638 for (u = global_exempts; u; u = u->next) {
00639 if (match[0]) {
00640 if ((wild_match(match, u->mask)) ||
00641 (wild_match(match, u->desc)) ||
00642 (wild_match(match, u->user)))
00643 display_exempt(idx, k, u, chan, 1);
00644 k++;
00645 } else
00646 display_exempt(idx, k++, u, chan, show_inact);
00647 }
00648 if (chan) {
00649 if (show_inact)
00650 dprintf(idx, "%s %s: (! = %s, * = %s)\n",
00651 _("Channel exempts for"), chan->dname,
00652 _("not active"),
00653 _("not placed by bot"));
00654 else
00655 dprintf(idx, "%s %s: (* = %s)\n",
00656 _("Channel exempts for"), chan->dname,
00657 _("not placed by bot"));
00658 for (u = chan->exempts; u; u = u->next) {
00659 if (match[0]) {
00660 if ((wild_match(match, u->mask)) ||
00661 (wild_match(match, u->desc)) ||
00662 (wild_match(match, u->user)))
00663 display_exempt(idx, k, u, chan, 1);
00664 k++;
00665 } else
00666 display_exempt(idx, k++, u, chan, show_inact);
00667 }
00668 if (chan->status & CHAN_ACTIVE) {
00669 masklist *e;
00670
00671 char buf[UHOSTLEN], *nick, *uhost, fill[UHOSTLEN * 2];
00672 int min, sec;
00673
00674 for (e = chan->channel.exempt; e && e->mask[0]; e = e->next) {
00675 if ((!u_equals_mask(global_exempts,e->mask)) &&
00676 (!u_equals_mask(chan->exempts, e->mask))) {
00677 strlcpy(buf, e->who, sizeof buf);
00678 nick = strtok(buf, "!");
00679 uhost = strtok(NULL, "!");
00680 if (nick)
00681 sprintf(fill, "%s (%s!%s)", e->mask, nick, uhost);
00682 else
00683 sprintf(fill, "%s (server %s)", e->mask, uhost);
00684 if (e->timer != 0) {
00685 min = (now - e->timer) / 60;
00686 sec = (now - e->timer) - (min * 60);
00687 sprintf(buf, " (active %02d:%02d)", min, sec);
00688 strcat(fill, buf);
00689 }
00690 if ((!match[0]) || (wild_match(match, e->mask)))
00691 dprintf(idx, "* [%3d] %s\n", k, fill);
00692 k++;
00693 }
00694 }
00695 }
00696 }
00697 if (k == 1)
00698 dprintf(idx, "(There are no ban exempts, permanent or otherwise.)\n");
00699 if ((!show_inact) && (!match[0]))
00700 dprintf(idx, "%s.\n", _("Use .exempts all to see the total list"));
00701 }
00702
00703 static void tell_invites(int idx, int show_inact, char *match)
00704 {
00705 char *p = NULL, *chname;
00706 int k = 1;
00707 struct chanset_t *chan = NULL;
00708 maskrec *u;
00709
00710
00711 if (match[0]) {
00712 p = strdup(match);
00713 chname = strtok(p, " ");
00714 if (chname && (strchr(CHANMETA, chname[0]))) {
00715 chan = findchan_by_dname(chname);
00716 if (!chan) {
00717 dprintf(idx, "%s.\n", _("No such channel defined"));
00718 return;
00719 }
00720 } else
00721 match = chname;
00722 if (p)
00723 free_null(p);
00724 }
00725
00726
00727 if (!chan && !(chan = findchan_by_dname(dcc[idx].u.chat->con_chan))
00728 && !(chan = chanset))
00729 chan = NULL;
00730
00731 if (chan && show_inact)
00732 dprintf(idx, "%s: (! = %s %s)\n", _("Global invites"),
00733 _("not active on"), chan->dname);
00734 else
00735 dprintf(idx, "%s:\n", _("Global invites"));
00736 for (u = global_invites; u; u = u->next) {
00737 if (match[0]) {
00738 if ((wild_match(match, u->mask)) ||
00739 (wild_match(match, u->desc)) ||
00740 (wild_match(match, u->user)))
00741 display_invite(idx, k, u, chan, 1);
00742 k++;
00743 } else
00744 display_invite(idx, k++, u, chan, show_inact);
00745 }
00746 if (chan) {
00747 if (show_inact)
00748 dprintf(idx, "%s %s: (! = %s, * = %s)\n",
00749 _("Channel invites for"), chan->dname,
00750 _("not active"),
00751 _("not placed by bot"));
00752 else
00753 dprintf(idx, "%s %s: (* = %s)\n",
00754 _("Channel invites for"), chan->dname,
00755 _("not placed by bot"));
00756 for (u = chan->invites; u; u = u->next) {
00757 if (match[0]) {
00758 if ((wild_match(match, u->mask)) ||
00759 (wild_match(match, u->desc)) ||
00760 (wild_match(match, u->user)))
00761 display_invite(idx, k, u, chan, 1);
00762 k++;
00763 } else
00764 display_invite(idx, k++, u, chan, show_inact);
00765 }
00766 if (chan->status & CHAN_ACTIVE) {
00767 masklist *i;
00768
00769 char buf[UHOSTLEN], *nick, *uhost, fill[UHOSTLEN * 2];
00770 int min, sec;
00771
00772 for (i = chan->channel.invite; i && i->mask[0]; i = i->next) {
00773 if ((!u_equals_mask(global_invites,i->mask)) &&
00774 (!u_equals_mask(chan->invites, i->mask))) {
00775 strlcpy(buf, i->who, sizeof buf);
00776 nick = strtok(buf, "!");
00777 uhost = strtok(NULL, "!");
00778 if (nick)
00779 sprintf(fill, "%s (%s!%s)", i->mask, nick, uhost);
00780 else
00781 sprintf(fill, "%s (server %s)", i->mask, uhost);
00782 if (i->timer != 0) {
00783 min = (now - i->timer) / 60;
00784 sec = (now - i->timer) - (min * 60);
00785 sprintf(buf, " (active %02d:%02d)", min, sec);
00786 strcat(fill, buf);
00787 }
00788 if ((!match[0]) || (wild_match(match, i->mask)))
00789 dprintf(idx, "* [%3d] %s\n", k, fill);
00790 k++;
00791 }
00792 }
00793 }
00794 }
00795 if (k == 1)
00796 dprintf(idx, "(There are no invites, permanent or otherwise.)\n");
00797 if ((!show_inact) && (!match[0]))
00798 dprintf(idx, "%s.\n", _("Use .invites all to see the total list"));
00799 }
00800
00801
00802 static int write_bans(FILE *f, int idx)
00803 {
00804 struct chanset_t *chan;
00805 maskrec *b;
00806 char *mask;
00807
00808 if (global_bans)
00809 if (fprintf(f, BAN_NAME " - -\n") == EOF)
00810 return 0;
00811 for (b = global_bans; b; b = b->next) {
00812 mask = str_escape(b->mask, ':', '\\');
00813 if (!mask ||
00814 fprintf(f, "- %s:%s%lu%s:+%lu:%lu:%s:%s\n", mask,
00815 (b->flags & MASKREC_PERM) ? "+" : "", b->expire,
00816 (b->flags & MASKREC_STICKY) ? "*" : "", b->added,
00817 b->lastactive, b->user ? b->user : myname,
00818 b->desc ? b->desc : "requested") == EOF) {
00819 if (mask)
00820 free(mask);
00821 return 0;
00822 }
00823 free(mask);
00824 }
00825 for (chan = chanset; chan; chan = chan->next)
00826 if (idx < 0) {
00827 struct flag_record fr = {FR_CHAN | FR_GLOBAL | FR_BOT, 0, 0, 0, 0, 0};
00828
00829 if (idx >= 0)
00830 get_user_flagrec(dcc[idx].user, &fr, chan->dname);
00831 }
00832 return 1;
00833 }
00834
00835
00836
00837 static int write_exempts(FILE *f, int idx)
00838 {
00839 struct chanset_t *chan;
00840 maskrec *e;
00841 char *mask;
00842
00843 if (global_exempts)
00844 if (fprintf(f, EXEMPT_NAME " - -\n") == EOF)
00845 return 0;
00846 for (e = global_exempts; e; e = e->next) {
00847 mask = str_escape(e->mask, ':', '\\');
00848 if (!mask ||
00849 fprintf(f, "%s %s:%s%lu%s:+%lu:%lu:%s:%s\n", "%", e->mask,
00850 (e->flags & MASKREC_PERM) ? "+" : "", e->expire,
00851 (e->flags & MASKREC_STICKY) ? "*" : "", e->added,
00852 e->lastactive, e->user ? e->user : myname,
00853 e->desc ? e->desc : "requested") == EOF) {
00854 if (mask)
00855 free(mask);
00856 return 0;
00857 }
00858 free(mask);
00859 }
00860 for (chan = chanset;chan;chan=chan->next)
00861 if (idx < 0) {
00862 struct flag_record fr = {FR_CHAN | FR_GLOBAL | FR_BOT, 0, 0, 0, 0, 0};
00863
00864 if (idx >= 0)
00865 get_user_flagrec(dcc[idx].user,&fr,chan->dname);
00866 }
00867 return 1;
00868 }
00869
00870
00871
00872 static int write_invites(FILE *f, int idx)
00873 {
00874 struct chanset_t *chan;
00875 maskrec *ir;
00876 char *mask;
00877
00878 if (global_invites)
00879 if (fprintf(f, INVITE_NAME " - -\n") == EOF)
00880 return 0;
00881 for (ir = global_invites; ir; ir = ir->next) {
00882 mask = str_escape(ir->mask, ':', '\\');
00883 if (!mask ||
00884 fprintf(f,"@ %s:%s%lu%s:+%lu:%lu:%s:%s\n",ir->mask,
00885 (ir->flags & MASKREC_PERM) ? "+" : "", ir->expire,
00886 (ir->flags & MASKREC_STICKY) ? "*" : "", ir->added,
00887 ir->lastactive, ir->user ? ir->user : myname,
00888 ir->desc ? ir->desc : "requested") == EOF) {
00889 if (mask)
00890 free(mask);
00891 return 0;
00892 }
00893 free(mask);
00894 }
00895 for (chan = chanset; chan; chan = chan->next)
00896 if (idx < 0) {
00897 struct flag_record fr = {FR_CHAN | FR_GLOBAL | FR_BOT, 0, 0, 0, 0, 0};
00898
00899 if (idx >= 0)
00900 get_user_flagrec(dcc[idx].user,&fr,chan->dname);
00901 }
00902 return 1;
00903 }
00904
00905 static void channels_writeuserfile(void)
00906 {
00907 char s[1024];
00908 FILE *f;
00909 int ret = 0;
00910
00911 simple_sprintf(s, "%s~new", userfile);
00912 f = fopen(s, "a");
00913 if (f) {
00914 ret = write_bans(f, -1);
00915 ret += write_exempts(f, -1);
00916 ret += write_invites(f, -1);
00917 fclose(f);
00918 }
00919 if (ret < 3)
00920 putlog(LOG_MISC, "*", _("ERROR writing user file."));
00921 write_channels();
00922 }
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934 static int expired_mask(struct chanset_t *chan, char *who)
00935 {
00936 char buf[UHOSTLEN], *nick, *uhost;
00937 struct userrec *u;
00938 memberlist *m, *m2;
00939
00940
00941 if (force_expire)
00942 return 1;
00943
00944 strlcpy(buf, who, sizeof buf);
00945 nick = strtok(buf, "!");
00946 uhost = strtok(NULL, "!");
00947
00948 if (!nick)
00949 return 1;
00950
00951 m = ismember(chan, nick);
00952 if (!m)
00953 for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next)
00954 if (!strcasecmp(uhost, m2->userhost)) {
00955 m = m2;
00956 break;
00957 }
00958
00959 if (!m || !chan_hasop(m) || !irccmp(m->nick, botname))
00960 return 1;
00961
00962
00963
00964
00965
00966 if (m->user)
00967 u = m->user;
00968 else {
00969 simple_sprintf(buf, "%s!%s", m->nick, m->userhost);
00970 u = get_user_by_host(buf);
00971 }
00972
00973 if (u && u->flags & USER_BOT)
00974 return 0;
00975 else
00976 return 1;
00977 }
00978
00979
00980
00981 static void check_expired_bans(void)
00982 {
00983 maskrec *u, *u2;
00984 struct chanset_t *chan;
00985 masklist *b;
00986
00987 for (u = global_bans; u; u = u2) {
00988 u2 = u->next;
00989 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
00990 putlog(LOG_MISC, "*", "%s %s (%s)", _("No longer banning"),
00991 u->mask, _("expired"));
00992 for (chan = chanset; chan; chan = chan->next)
00993 for (b = chan->channel.ban; b->mask[0]; b = b->next)
00994 if (!irccmp(b->mask, u->mask) &&
00995 expired_mask(chan, b->who) && b->timer != now) {
00996 add_mode(chan, '-', 'b', u->mask);
00997 b->timer = now;
00998 }
00999 u_delmask('b', NULL, u->mask, 1);
01000 }
01001 }
01002
01003 for (chan = chanset; chan; chan = chan->next) {
01004 for (u = chan->bans; u; u = u2) {
01005 u2 = u->next;
01006 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
01007 putlog(LOG_MISC, "*", "%s %s %s %s (%s)", _("No longer banning"),
01008 u->mask, _("on"), chan->dname, _("expired"));
01009 for (b = chan->channel.ban; b->mask[0]; b = b->next)
01010 if (!irccmp(b->mask, u->mask) &&
01011 expired_mask(chan, b->who) && b->timer != now) {
01012 add_mode(chan, '-', 'b', u->mask);
01013 b->timer = now;
01014 }
01015 u_delmask('b', chan, u->mask, 1);
01016 }
01017 }
01018 }
01019 }
01020
01021
01022
01023 static void check_expired_exempts(void)
01024 {
01025 maskrec *u, *u2;
01026 struct chanset_t *chan;
01027 masklist *b, *e;
01028 int match;
01029
01030 if (!use_exempts)
01031 return;
01032 for (u = global_exempts; u; u = u2) {
01033 u2 = u->next;
01034 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
01035 putlog(LOG_MISC, "*", "%s %s (%s)", _("No longer ban exempting"),
01036 u->mask, _("expired"));
01037 for (chan = chanset; chan; chan = chan->next) {
01038 match = 0;
01039 b = chan->channel.ban;
01040 while (b->mask[0] && !match) {
01041 if (wild_match(b->mask, u->mask) ||
01042 wild_match(u->mask, b->mask))
01043 match = 1;
01044 else
01045 b = b->next;
01046 }
01047 if (match)
01048 putlog(LOG_MISC, chan->dname,
01049 "Exempt not expired on channel %s. Ban still set!",
01050 chan->dname);
01051 else
01052 for (e = chan->channel.exempt; e->mask[0]; e = e->next)
01053 if (!irccmp(e->mask, u->mask) &&
01054 expired_mask(chan, e->who) && e->timer != now) {
01055 add_mode(chan, '-', 'e', u->mask);
01056 e->timer = now;
01057 }
01058 }
01059 u_delmask('e', NULL, u->mask,1);
01060 }
01061 }
01062
01063 for (chan = chanset; chan; chan = chan->next) {
01064 for (u = chan->exempts; u; u = u2) {
01065 u2 = u->next;
01066 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
01067 match=0;
01068 b = chan->channel.ban;
01069 while (b->mask[0] && !match) {
01070 if (wild_match(b->mask, u->mask) ||
01071 wild_match(u->mask, b->mask))
01072 match=1;
01073 else
01074 b = b->next;
01075 }
01076 if (match)
01077 putlog(LOG_MISC, chan->dname,
01078 "Exempt not expired on channel %s. Ban still set!",
01079 chan->dname);
01080 else {
01081 putlog(LOG_MISC, "*", "%s %s %s %s (%s)", _("No longer ban exempting"),
01082 u->mask, _("on"), chan->dname, _("expired"));
01083 for (e = chan->channel.exempt; e->mask[0]; e = e->next)
01084 if (!irccmp(e->mask, u->mask) &&
01085 expired_mask(chan, e->who) && e->timer != now) {
01086 add_mode(chan, '-', 'e', u->mask);
01087 e->timer = now;
01088 }
01089 u_delmask('e', chan, u->mask, 1);
01090 }
01091 }
01092 }
01093 }
01094 }
01095
01096
01097
01098 static void check_expired_invites(void)
01099 {
01100 maskrec *u, *u2;
01101 struct chanset_t *chan;
01102 masklist *b;
01103
01104 if (!use_invites)
01105 return;
01106 for (u = global_invites; u; u = u2) {
01107 u2 = u->next;
01108 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
01109 putlog(LOG_MISC, "*", "%s %s (%s)", _("No longer inviteing"),
01110 u->mask, _("expired"));
01111 for (chan = chanset; chan; chan = chan->next)
01112 if (!(chan->channel.mode & CHANINV))
01113 for (b = chan->channel.invite; b->mask[0]; b = b->next)
01114 if (!irccmp(b->mask, u->mask) &&
01115 expired_mask(chan, b->who) && b->timer != now) {
01116 add_mode(chan, '-', 'I', u->mask);
01117 b->timer = now;
01118 }
01119 u_delmask('I', NULL, u->mask,1);
01120 }
01121 }
01122
01123 for (chan = chanset; chan; chan = chan->next) {
01124 for (u = chan->invites; u; u = u2) {
01125 u2 = u->next;
01126 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
01127 putlog(LOG_MISC, "*", "%s %s %s %s (%s)", _("No longer inviteing"),
01128 u->mask, _("on"), chan->dname, _("expired"));
01129 if (!(chan->channel.mode & CHANINV))
01130 for (b = chan->channel.invite; b->mask[0]; b = b->next)
01131 if (!irccmp(b->mask, u->mask) &&
01132 expired_mask(chan, b->who) && b->timer != now) {
01133 add_mode(chan, '-', 'I', u->mask);
01134 b->timer = now;
01135 }
01136 u_delmask('I', chan, u->mask, 1);
01137 }
01138 }
01139 }
01140 }