1 /*
2 * userchan.c -- part of channels.mod
3 *
4 * $Id: userchan.c,v 1.44 (1.0.1) 2004/03/24 23:44:23 [Xp-AvR] Exp $
5 */
6
get_chanrec(struct userrec * u,char * chname)7 struct chanuserrec *get_chanrec(struct userrec *u, char *chname)
8 {
9 struct chanuserrec *ch;
10
11 for (ch = u->chanrec; ch; ch = ch->next)
12 if (!rfc_casecmp(ch->channel, chname))
13 return ch;
14 return NULL;
15 }
16
add_chanrec(struct userrec * u,char * chname)17 static struct chanuserrec *add_chanrec(struct userrec *u, char *chname)
18 {
19 struct chanuserrec *ch = NULL;
20
21 if (findchan_by_dname(chname)) {
22 ch = user_malloc(sizeof(struct chanuserrec));
23
24 ch->next = u->chanrec;
25 u->chanrec = ch;
26 ch->info = NULL;
27 ch->flags = 0;
28 ch->flags_udef = 0;
29 ch->laston = 0;
30 strncpy(ch->channel, chname, 81);
31 ch->channel[80] = 0;
32 if (!noshare && !(u->flags & USER_UNSHARED))
33 shareout(findchan_by_dname(chname), "+cr %s %s\n", u->handle, chname);
34 }
35 return ch;
36 }
37
add_chanrec_by_handle(struct userrec * bu,char * hand,char * chname)38 static void add_chanrec_by_handle(struct userrec *bu, char *hand, char *chname)
39 {
40 struct userrec *u;
41
42 u = get_user_by_handle(bu, hand);
43 if (!u)
44 return;
45 if (!get_chanrec(u, chname))
46 add_chanrec(u, chname);
47 }
48
get_handle_chaninfo(char * handle,char * chname,char * s)49 static void get_handle_chaninfo(char *handle, char *chname, char *s)
50 {
51 struct userrec *u;
52 struct chanuserrec *ch;
53
54 u = get_user_by_handle(userlist, handle);
55 if (u == NULL) {
56 s[0] = 0;
57 return;
58 }
59 ch = get_chanrec(u, chname);
60 if (ch == NULL) {
61 s[0] = 0;
62 return;
63 }
64 if (ch->info == NULL) {
65 s[0] = 0;
66 return;
67 }
68 strcpy(s, ch->info);
69 return;
70 }
71
set_handle_chaninfo(struct userrec * bu,char * handle,char * chname,char * info)72 static void set_handle_chaninfo(struct userrec *bu, char *handle,
73 char *chname, char *info)
74 {
75 struct userrec *u;
76 struct chanuserrec *ch;
77 struct chanset_t *cst;
78
79 u = get_user_by_handle(bu, handle);
80 if (!u)
81 return;
82 ch = get_chanrec(u, chname);
83 if (!ch) {
84 add_chanrec_by_handle(bu, handle, chname);
85 ch = get_chanrec(u, chname);
86 }
87 if (info) {
88 if (strlen(info) > 80)
89 info[80] = 0;
90 }
91 if (ch->info != NULL)
92 nfree(ch->info);
93 if (info && info[0]) {
94 ch->info = (char *) user_malloc(strlen(info) + 1);
95 strcpy(ch->info, info);
96 } else
97 ch->info = NULL;
98 cst = findchan_by_dname(chname);
99 if ((!noshare) && (bu == userlist) &&
100 !(u->flags & (USER_UNSHARED | USER_BOT)) && share_greet) {
101 shareout(cst, "chchinfo %s %s %s\n", handle, chname, info ? info : "");
102 }
103 }
104
del_chanrec(struct userrec * u,char * chname)105 static void del_chanrec(struct userrec *u, char *chname)
106 {
107 struct chanuserrec *ch = u->chanrec, *lst = NULL;
108
109 while (ch) {
110 if (!rfc_casecmp(chname, ch->channel)) {
111 if (lst == NULL)
112 u->chanrec = ch->next;
113 else
114 lst->next = ch->next;
115 if (ch->info != NULL)
116 nfree(ch->info);
117 nfree(ch);
118 if (!noshare && !(u->flags & USER_UNSHARED))
119 shareout(findchan_by_dname(chname), "-cr %s %s\n", u->handle, chname);
120 return;
121 }
122 lst = ch;
123 ch = ch->next;
124 }
125 }
126
set_handle_laston(char * chan,struct userrec * u,time_t n)127 static void set_handle_laston(char *chan, struct userrec *u, time_t n)
128 {
129 struct chanuserrec *ch;
130
131 if (!u)
132 return;
133 touch_laston(u, chan, n);
134 ch = get_chanrec(u, chan);
135 if (!ch)
136 return;
137 ch->laston = n;
138 }
139
140 /* Is this mask sticky? */
u_sticky_mask(maskrec * u,char * uhost)141 static int u_sticky_mask(maskrec *u, char *uhost)
142 {
143 for (; u; u = u->next)
144 if (!rfc_casecmp(u->mask, uhost))
145 return (u->flags & MASKREC_STICKY);
146 return 0;
147 }
148
149 /* Set sticky attribute for a mask. */
u_setsticky_mask(struct chanset_t * chan,maskrec * u,char * uhost,int sticky,char * botcmd)150 static int u_setsticky_mask(struct chanset_t *chan, maskrec *u, char *uhost,
151 int sticky, char *botcmd)
152 {
153 int j;
154
155 if (str_isdigit(uhost))
156 j = atoi(uhost);
157 else
158 j = -1;
159 while (u) {
160 if (j >= 0)
161 j--;
162
163 if (!j || ((j < 0) && !rfc_casecmp(u->mask, uhost))) {
164 if (sticky > 0)
165 u->flags |= MASKREC_STICKY;
166 else if (!sticky)
167 u->flags &= ~MASKREC_STICKY;
168 else
169 return 0;
170 if (!j)
171 strcpy(uhost, u->mask);
172
173 if (!noshare)
174 shareout(chan, "%s %s %d %s\n", botcmd, uhost, sticky,
175 (chan) ? chan->dname : "");
176 return 1;
177 }
178
179 u = u->next;
180 }
181 if (j >= 0)
182 return -j;
183
184 return 0;
185 }
186
187 /* Merge of u_equals_ban(), u_equals_exempt() and u_equals_invite(). */
u_equals_mask(maskrec * u,char * mask)188 static int u_equals_mask(maskrec *u, char *mask)
189 {
190 for (; u; u = u->next)
191 if (!rfc_casecmp(u->mask, mask)) {
192 if (u->flags & MASKREC_PERM)
193 return 2;
194 else
195 return 1;
196 }
197 return 0;
198 }
199
u_match_mask(maskrec * rec,char * mask)200 static int u_match_mask(maskrec *rec, char *mask)
201 {
202 for (; rec; rec = rec->next)
203 if (wild_match(rec->mask, mask))
204 return 1;
205 return 0;
206 }
207
u_delban(struct chanset_t * c,char * who,int doit)208 static int u_delban(struct chanset_t *c, char *who, int doit)
209 {
210 int j, i = 0;
211 maskrec *t;
212 maskrec **u = (c) ? &c->bans : &global_bans;
213 char temp[256];
214
215 if (!strchr(who, '!') && str_isdigit(who)) {
216 j = atoi(who);
217 j--;
218 for (; (*u) && j; u = &((*u)->next), j--);
219 if (*u) {
220 strncpyz(temp, (*u)->mask, sizeof temp);
221 i = 1;
222 } else
223 return -j - 1;
224 } else {
225 for (; *u && !i; u = &((*u)->next))
226 if (!rfc_casecmp((*u)->mask, who)) {
227 strncpyz(temp, who, sizeof temp);
228 i = 1;
229 break;
230 }
231 if (!*u)
232 return 0;
233 }
234 if (i && doit) {
235 if (!noshare) {
236 char *mask = str_escape(temp, ':', '\\');
237
238 if (mask) {
239 if (c)
240 shareout(c, "-bc %s %s\n", c->dname, mask);
241 else
242 shareout(NULL, "-b %s\n", mask);
243 nfree(mask);
244 }
245 }
246 if (lastdeletedmask)
247 nfree(lastdeletedmask);
248 lastdeletedmask = nmalloc(strlen((*u)->mask) + 1);
249 strcpy(lastdeletedmask, (*u)->mask);
250 nfree((*u)->mask);
251 if ((*u)->desc)
252 nfree((*u)->desc);
253 if ((*u)->user)
254 nfree((*u)->user);
255 t = *u;
256 *u = (*u)->next;
257 nfree(t);
258 }
259 return i;
260 }
261
u_delexempt(struct chanset_t * c,char * who,int doit)262 static int u_delexempt(struct chanset_t *c, char *who, int doit)
263 {
264 int j, i = 0;
265 maskrec *t, **u = c ? &(c->exempts) : &global_exempts;
266 char temp[256];
267
268 if (!strchr(who, '!') && str_isdigit(who)) {
269 j = atoi(who);
270 j--;
271 for (; (*u) && j; u = &((*u)->next), j--);
272 if (*u) {
273 strncpyz(temp, (*u)->mask, sizeof temp);
274 i = 1;
275 } else
276 return -j - 1;
277 } else {
278 for (; *u && !i; u = &((*u)->next))
279 if (!rfc_casecmp((*u)->mask, who)) {
280 strncpyz(temp, who, sizeof temp);
281 i = 1;
282 break;
283 }
284 if (!*u)
285 return 0;
286 }
287 if (i && doit) {
288 if (!noshare) {
289 char *mask = str_escape(temp, ':', '\\');
290
291 if (mask) {
292 if (c)
293 shareout(c, "-ec %s %s\n", c->dname, mask);
294 else
295 shareout(NULL, "-e %s\n", mask);
296 nfree(mask);
297 }
298 }
299 if (lastdeletedmask)
300 nfree(lastdeletedmask);
301 lastdeletedmask = nmalloc(strlen((*u)->mask) + 1);
302 strcpy(lastdeletedmask, (*u)->mask);
303 nfree((*u)->mask);
304 if ((*u)->desc)
305 nfree((*u)->desc);
306 if ((*u)->user)
307 nfree((*u)->user);
308 t = *u;
309 *u = (*u)->next;
310 nfree(t);
311 }
312 return i;
313 }
314
u_delinvite(struct chanset_t * c,char * who,int doit)315 static int u_delinvite(struct chanset_t *c, char *who, int doit)
316 {
317 int j, i = 0;
318 maskrec *t;
319 maskrec **u = c ? &(c->invites) : &global_invites;
320 char temp[256];
321
322 if (!strchr(who, '!') && str_isdigit(who)) {
323 j = atoi(who);
324 j--;
325 for (; (*u) && j; u = &((*u)->next), j--);
326 if (*u) {
327 strncpyz(temp, (*u)->mask, sizeof temp);
328 i = 1;
329 } else
330 return -j - 1;
331 } else {
332 for (; *u && !i; u = &((*u)->next))
333 if (!rfc_casecmp((*u)->mask, who)) {
334 strncpyz(temp, who, sizeof temp);
335 i = 1;
336 break;
337 }
338 if (!*u)
339 return 0;
340 }
341 if (i && doit) {
342 if (!noshare) {
343 char *mask = str_escape(temp, ':', '\\');
344
345 if (mask) {
346 if (c)
347 shareout(c, "-invc %s %s\n", c->dname, mask);
348 else
349 shareout(NULL, "-inv %s\n", mask);
350 nfree(mask);
351 }
352 }
353 if (lastdeletedmask)
354 nfree(lastdeletedmask);
355 lastdeletedmask = nmalloc(strlen((*u)->mask) + 1);
356 strcpy(lastdeletedmask, (*u)->mask);
357 nfree((*u)->mask);
358 if ((*u)->desc)
359 nfree((*u)->desc);
360 if ((*u)->user)
361 nfree((*u)->user);
362 t = *u;
363 *u = (*u)->next;
364 nfree(t);
365 }
366 return i;
367 }
368
369 /* Note: If first char of note is '*' it's a sticky ban. */
u_addban(struct chanset_t * chan,char * ban,char * from,char * note,time_t expire_time,int flags)370 static int u_addban(struct chanset_t *chan, char *ban, char *from, char *note,
371 time_t expire_time, int flags)
372 {
373 char host[1024], s[1024], myhost[1024], ident[21], nick[1024], *p0;
374 maskrec *p = NULL, *l, **u = chan ? &chan->bans : &global_bans;
375 module_entry *me;
376 struct userrec *ul;
377 struct list_type *q;
378 struct flag_record user, plus, minus;
379 int ok = 1, f = 0;
380
381 strcpy(host, ban);
382
383 /* Proper banning & ident check */
384 p0 = strchr(host, '@');
385 strcpy(myhost, &p0[1]);
386 p0 = strchr(host, '!');
387 strcpy(ident, &p0[1]);
388 ident[strlen(ident) - strlen(myhost) - 1] = 0;
389 strcpy(nick, host);
390 nick[strlen(p0) - strlen(ident) - strlen(myhost) - 1] = 0;
391 if (strlen(ident) > 10)
392 ident[10] = 0;
393 sprintf(host, "%s!%s@%s", nick, ident, myhost);
394 /* */
395
396 if ((strchr(host, '!') == NULL) && (strchr(host, '@') == NULL))
397 strcat(host, "!*@*");
398 else if (strchr(host, '@') == NULL)
399 strcat(host, "@*");
400 else if (strchr(host, '!') == NULL) {
401 char *i = strchr(host, '@');
402
403 strcpy(s, i);
404 *i = 0;
405 strcat(host, "!*");
406 strcat(host, s);
407 }
408
409 if ((me = module_find("server", 0, 0)) && me->funcs)
410 simple_sprintf(s, "%s!%s", me->funcs[SERVER_BOTNAME],
411 me->funcs[SERVER_BOTUSERHOST]);
412 else
413 simple_sprintf(s, "%s!%s@%s", origbotname, botuser, hostname);
414 if (wild_match(host, s)) {
415 putlog(LOG_MISC, "*", IRC_IBANNEDME);
416 return 0;
417 }
418
419 plus.match = FR_GLOBAL | FR_CHAN | FR_BOT;
420 break_down_flags("b", &plus, &minus);
421 f = (minus.global ||minus.udef_global || minus.chan || minus.udef_chan || minus.bot);
422 minus.match = plus.match ^ (FR_AND | FR_OR);
423 for (ul = userlist; ul; ul = ul->next) {
424 user.match = FR_GLOBAL | FR_CHAN | FR_BOT;
425 get_user_flagrec(ul, &user, NULL);
426 if (flagrec_eq(&plus, &user) && !(f && flagrec_eq(&minus, &user)))
427 ok = 1;
428 else
429 ok = 0;
430 if (ok) {
431 for (q = get_user(&USERENTRY_HOSTS, ul); q; q = q->next)
432 if (wild_match(q->extra, host)) {
433 debug2("(userchan.c->u_addban) ban %s matches to one of the bots: %s", host, q->extra);
434 return 0;
435 }
436 }
437 }
438
439 if (expire_time == now)
440 return 1;
441
442 for (l = *u; l; l = l->next)
443 if (!rfc_casecmp(l->mask, host)) {
444 p = l;
445 break;
446 }
447
448 if (note[0] == '*') {
449 flags |= MASKREC_STICKY;
450 note++;
451 }
452 if ((expire_time == 0L) || (flags & MASKREC_PERM)) {
453 flags |= MASKREC_PERM;
454 expire_time = 0L;
455 }
456
457 if (p == NULL) {
458 p = user_malloc(sizeof(maskrec));
459 p->next = *u;
460 *u = p;
461 } else {
462 nfree(p->mask);
463 nfree(p->user);
464 nfree(p->desc);
465 }
466 p->expire = expire_time;
467 p->added = now;
468 p->lastactive = 0;
469 p->flags = flags;
470 p->mask = user_malloc(strlen(host) + 1);
471 strcpy(p->mask, host);
472 p->user = user_malloc(strlen(from) + 1);
473 strcpy(p->user, from);
474 p->desc = user_malloc(strlen(note) + 1);
475 strcpy(p->desc, note);
476 if (!noshare) {
477 char *mask = str_escape(host, ':', '\\');
478
479 if (mask) {
480 if (strcmp(mask, "*!*@*") != 0) {
481 if (!chan)
482 shareout(NULL, "+b %s %lu %s%s %s %s\n", mask, expire_time - now,
483 (flags & MASKREC_STICKY) ? "s" : "",
484 (flags & MASKREC_PERM) ? "p" : "-", from, note);
485 else
486 shareout(chan, "+bc %s %lu %s %s%s %s %s\n", mask, expire_time - now,
487 chan->dname, (flags & MASKREC_STICKY) ? "s" : "",
488 (flags & MASKREC_PERM) ? "p" : "-", from, note);
489 }
490 nfree(mask);
491 }
492 }
493 return 1;
494 }
495
496 /* Note: If first char of note is '*' it's a sticky invite. */
u_addinvite(struct chanset_t * chan,char * invite,char * from,char * note,time_t expire_time,int flags)497 static int u_addinvite(struct chanset_t *chan, char *invite, char *from,
498 char *note, time_t expire_time, int flags)
499 {
500 char host[1024], s[1024], myhost[1024], ident[21], nick[1024], *p0;
501 maskrec *p = NULL, *l, **u = chan ? &chan->invites : &global_invites;
502 module_entry *me;
503
504 strcpy(host, invite);
505
506 /* Proper banning & ident check */
507 p0 = strchr(host, '@');
508 strcpy(myhost, &p0[1]);
509 p0 = strchr(host, '!');
510 strcpy(ident, &p0[1]);
511 ident[strlen(ident) - strlen(myhost) - 1] = 0;
512 strcpy(nick, host);
513 nick[strlen(p0) - strlen(ident) - strlen(myhost) - 1] = 0;
514 if (strlen(ident) > 10)
515 ident[10] = 0;
516 sprintf(host, "%s!%s@%s", nick, ident, myhost);
517 /* */
518
519 if ((strchr(host, '!') == NULL) && (strchr(host, '@') == NULL))
520 strcat(host, "!*@*");
521 else if (strchr(host, '@') == NULL)
522 strcat(host, "@*");
523 else if (strchr(host, '!') == NULL) {
524 char *i = strchr(host, '@');
525
526 strcpy(s, i);
527 *i = 0;
528 strcat(host, "!*");
529 strcat(host, s);
530 }
531 if ((me = module_find("server", 0, 0)) && me->funcs)
532 simple_sprintf(s, "%s!%s", me->funcs[SERVER_BOTNAME],
533 me->funcs[SERVER_BOTUSERHOST]);
534 else
535 simple_sprintf(s, "%s!%s@%s", origbotname, botuser, hostname);
536
537 for (l = *u; l; l = l->next)
538 if (!rfc_casecmp(l->mask, host)) {
539 p = l;
540 break;
541 }
542
543 if (note[0] == '*') {
544 flags |= MASKREC_STICKY;
545 note++;
546 }
547 if ((expire_time == 0L) || (flags & MASKREC_PERM)) {
548 flags |= MASKREC_PERM;
549 expire_time = 0L;
550 }
551
552 if (p == NULL) {
553 p = user_malloc(sizeof(maskrec));
554 p->next = *u;
555 *u = p;
556 } else {
557 nfree(p->mask);
558 nfree(p->user);
559 nfree(p->desc);
560 }
561 p->expire = expire_time;
562 p->added = now;
563 p->lastactive = 0;
564 p->flags = flags;
565 p->mask = user_malloc(strlen(host) + 1);
566 strcpy(p->mask, host);
567 p->user = user_malloc(strlen(from) + 1);
568 strcpy(p->user, from);
569 p->desc = user_malloc(strlen(note) + 1);
570 strcpy(p->desc, note);
571 if (!noshare) {
572 char *mask = str_escape(host, ':', '\\');
573
574 if (mask) {
575 if (!chan)
576 shareout(NULL, "+inv %s %lu %s%s %s %s\n", mask, expire_time - now,
577 (flags & MASKREC_STICKY) ? "s" : "",
578 (flags & MASKREC_PERM) ? "p" : "-", from, note);
579 else
580 shareout(chan, "+invc %s %lu %s %s%s %s %s\n", mask, expire_time - now,
581 chan->dname, (flags & MASKREC_STICKY) ? "s" : "",
582 (flags & MASKREC_PERM) ? "p" : "-", from, note);
583 nfree(mask);
584 }
585 }
586 return 1;
587 }
588
589 /* Note: If first char of note is '*' it's a sticky exempt. */
u_addexempt(struct chanset_t * chan,char * exempt,char * from,char * note,time_t expire_time,int flags)590 static int u_addexempt(struct chanset_t *chan, char *exempt, char *from,
591 char *note, time_t expire_time, int flags)
592 {
593 char host[1024], s[1024], myhost[1024], ident[21], nick[1024], *p0;
594 maskrec *p = NULL, *l, **u = chan ? &chan->exempts : &global_exempts;
595 module_entry *me;
596
597 strcpy(host, exempt);
598
599 /* Proper banning & ident check */
600 p0 = strchr(host, '@');
601 strcpy(myhost, &p0[1]);
602 p0 = strchr(host, '!');
603 strcpy(ident, &p0[1]);
604 ident[strlen(ident) - strlen(myhost) - 1] = 0;
605 strcpy(nick, host);
606 nick[strlen(p0) - strlen(ident) - strlen(myhost) - 1] = 0;
607 if (strlen(ident) > 10)
608 ident[10] = 0;
609 sprintf(host, "%s!%s@%s", nick, ident, myhost);
610 /* */
611
612 if ((strchr(host, '!') == NULL) && (strchr(host, '@') == NULL))
613 strcat(host, "!*@*");
614 else if (strchr(host, '@') == NULL)
615 strcat(host, "@*");
616 else if (strchr(host, '!') == NULL) {
617 char *i = strchr(host, '@');
618
619 strcpy(s, i);
620 *i = 0;
621 strcat(host, "!*");
622 strcat(host, s);
623 }
624 if ((me = module_find("server", 0, 0)) && me->funcs)
625 simple_sprintf(s, "%s!%s", me->funcs[SERVER_BOTNAME],
626 me->funcs[SERVER_BOTUSERHOST]);
627 else
628 simple_sprintf(s, "%s!%s@%s", origbotname, botuser, hostname);
629
630 for (l = *u; l; l = l->next)
631 if (!rfc_casecmp(l->mask, host)) {
632 p = l;
633 break;
634 }
635
636 if (note[0] == '*') {
637 flags |= MASKREC_STICKY;
638 note++;
639 }
640 if ((expire_time == 0L) || (flags & MASKREC_PERM)) {
641 flags |= MASKREC_PERM;
642 expire_time = 0L;
643 }
644
645 if (p == NULL) {
646 p = user_malloc(sizeof(maskrec));
647 p->next = *u;
648 *u = p;
649 } else {
650 nfree(p->mask);
651 nfree(p->user);
652 nfree(p->desc);
653 }
654 p->expire = expire_time;
655 p->added = now;
656 p->lastactive = 0;
657 p->flags = flags;
658 p->mask = user_malloc(strlen(host) + 1);
659 strcpy(p->mask, host);
660 p->user = user_malloc(strlen(from) + 1);
661 strcpy(p->user, from);
662 p->desc = user_malloc(strlen(note) + 1);
663 strcpy(p->desc, note);
664 if (!noshare) {
665 char *mask = str_escape(host, ':', '\\');
666
667 if (mask) {
668 if (!chan)
669 shareout(NULL, "+e %s %lu %s%s %s %s\n", mask, expire_time - now,
670 (flags & MASKREC_STICKY) ? "s" : "",
671 (flags & MASKREC_PERM) ? "p" : "-", from, note);
672 else
673 shareout(chan, "+ec %s %lu %s %s%s %s %s\n", mask, expire_time - now,
674 chan->dname, (flags & MASKREC_STICKY) ? "s" : "",
675 (flags & MASKREC_PERM) ? "p" : "-", from, note);
676 nfree(mask);
677 }
678 }
679 return 1;
680 }
681
682 /* Take host entry from ban list and display it ban-style. */
display_ban(int idx,int number,maskrec * ban,struct chanset_t * chan,int show_inact)683 static void display_ban(int idx, int number, maskrec *ban,
684 struct chanset_t *chan, int show_inact)
685 {
686 char dates[81], s[41];
687
688 if (ban->added) {
689 daysago(now, ban->added, s);
690 sprintf(dates, "%s %s", MODES_CREATED, s);
691 if (ban->added < ban->lastactive) {
692 strcat(dates, ", ");
693 strcat(dates, MODES_LASTUSED);
694 strcat(dates, " ");
695 daysago(now, ban->lastactive, s);
696 strcat(dates, s);
697 }
698 } else
699 dates[0] = 0;
700 if (ban->flags & MASKREC_PERM)
701 strcpy(s, "(expires: never)");
702 else {
703 char s1[41];
704
705 strftime(s1, 23, "%d.%m.%Y %H:%M:%S", localtime(&ban->expire));
706 sprintf(s, "(expires: %s)", s1);
707 }
708 if (ban->flags & MASKREC_STICKY)
709 strcat(s, " (sticky)");
710 if (!chan || ischanban(chan, ban->mask)) {
711 if (number >= 0)
712 dprintf(idx, " [%3d] %s %s\n", number, ban->mask, s);
713 else
714 dprintf(idx, "BAN: %s %s\n", ban->mask, s);
715 } else if (show_inact) {
716 if (number >= 0)
717 dprintf(idx, "! [%3d] %s %s\n", number, ban->mask, s);
718 else
719 dprintf(idx, "BAN (%s): %s %s\n", MODES_INACTIVE, ban->mask, s);
720 } else
721 return;
722 dprintf(idx, " %s: %s\n", ban->user, ban->desc);
723 if (dates[0])
724 dprintf(idx, " %s\n", dates);
725 }
726
727 /* Take host entry from exempt list and display it ban-style. */
display_exempt(int idx,int number,maskrec * exempt,struct chanset_t * chan,int show_inact)728 static void display_exempt(int idx, int number, maskrec *exempt,
729 struct chanset_t *chan, int show_inact)
730 {
731 char dates[81], s[41];
732
733 if (exempt->added) {
734 daysago(now, exempt->added, s);
735 sprintf(dates, "%s %s", MODES_CREATED, s);
736 if (exempt->added < exempt->lastactive) {
737 strcat(dates, ", ");
738 strcat(dates, MODES_LASTUSED);
739 strcat(dates, " ");
740 daysago(now, exempt->lastactive, s);
741 strcat(dates, s);
742 }
743 } else
744 dates[0] = 0;
745 if (exempt->flags & MASKREC_PERM)
746 strcpy(s, "(expires: never)");
747 else {
748 char s1[41];
749
750 strftime(s1, 23, "%d.%m.%Y %H:%M:%S", localtime(&exempt->expire));
751 sprintf(s, "(expires: %s)", s1);
752 }
753 if (exempt->flags & MASKREC_STICKY)
754 strcat(s, " (sticky)");
755 if (!chan || ischanexempt(chan, exempt->mask)) {
756 if (number >= 0)
757 dprintf(idx, " [%3d] %s %s\n", number, exempt->mask, s);
758 else
759 dprintf(idx, "EXEMPT: %s %s\n", exempt->mask, s);
760 } else if (show_inact) {
761 if (number >= 0)
762 dprintf(idx, "! [%3d] %s %s\n", number, exempt->mask, s);
763 else
764 dprintf(idx, "EXEMPT (%s): %s %s\n", MODES_INACTIVE, exempt->mask, s);
765 } else
766 return;
767 dprintf(idx, " %s: %s\n", exempt->user, exempt->desc);
768 if (dates[0])
769 dprintf(idx, " %s\n", dates);
770 }
771
772 /* Take host entry from invite list and display it ban-style. */
display_invite(int idx,int number,maskrec * invite,struct chanset_t * chan,int show_inact)773 static void display_invite(int idx, int number, maskrec *invite,
774 struct chanset_t *chan, int show_inact)
775 {
776 char dates[81], s[41];
777
778 if (invite->added) {
779 daysago(now, invite->added, s);
780 sprintf(dates, "%s %s", MODES_CREATED, s);
781 if (invite->added < invite->lastactive) {
782 strcat(dates, ", ");
783 strcat(dates, MODES_LASTUSED);
784 strcat(dates, " ");
785 daysago(now, invite->lastactive, s);
786 strcat(dates, s);
787 }
788 } else
789 dates[0] = 0;
790 if (invite->flags & MASKREC_PERM)
791 strcpy(s, "(expires: never)");
792 else {
793 char s1[41];
794
795 strftime(s1, 23, "%d.%m.%Y %H:%M:%S", localtime(&invite->expire));
796 sprintf(s, "(expires: %s)", s1);
797 }
798 if (invite->flags & MASKREC_STICKY)
799 strcat(s, " (sticky)");
800 if (!chan || ischaninvite(chan, invite->mask)) {
801 if (number >= 0)
802 dprintf(idx, " [%3d] %s %s\n", number, invite->mask, s);
803 else
804 dprintf(idx, "INVITE: %s %s\n", invite->mask, s);
805 } else if (show_inact) {
806 if (number >= 0)
807 dprintf(idx, "! [%3d] %s %s\n", number, invite->mask, s);
808 else
809 dprintf(idx, "INVITE (%s): %s %s\n", MODES_INACTIVE, invite->mask, s);
810 } else
811 return;
812 dprintf(idx, " %s: %s\n", invite->user, invite->desc);
813 if (dates[0])
814 dprintf(idx, " %s\n", dates);
815 }
816
tell_bans(int idx,int show_inact,char * match)817 static void tell_bans(int idx, int show_inact, char *match)
818 {
819 int k = 1;
820 char *chname;
821 struct chanset_t *chan = NULL;
822 maskrec *u;
823
824 if (match[0]) {
825 chname = newsplit(&match);
826 if (chname[0] && (strchr(CHANMETA, chname[0]))) {
827 chan = findchan_by_dname(chname);
828 if (!chan) {
829 dprintf(idx, "%s.\n", CHAN_NOSUCH);
830 return;
831 }
832 } else
833 match = chname;
834 }
835
836 if (!chan && !(chan = findchan_by_dname(dcc[idx].u.chat->con_chan)) &&
837 !(chan = chanset))
838 chan = NULL;
839
840 if (chan && show_inact)
841 dprintf(idx, "%s: (! = %s %s)\n", BANS_GLOBAL,
842 MODES_NOTACTIVE, chan->dname);
843 else
844 dprintf(idx, "%s:\n", BANS_GLOBAL);
845 for (u = global_bans; u; u = u->next) {
846 if (match[0]) {
847 if ((wild_match(match, u->mask)) ||
848 (wild_match(match, u->desc)) || (wild_match(match, u->user)))
849 display_ban(idx, k, u, chan, 1);
850 k++;
851 } else
852 display_ban(idx, k++, u, chan, show_inact);
853 }
854 if (chan) {
855 if (show_inact)
856 dprintf(idx, "%s %s: (! = %s, * = %s)\n",
857 BANS_BYCHANNEL, chan->dname, MODES_NOTACTIVE2, MODES_NOTBYBOT);
858 else
859 dprintf(idx, "%s %s: (* = %s)\n",
860 BANS_BYCHANNEL, chan->dname, MODES_NOTBYBOT);
861 for (u = chan->bans; u; u = u->next) {
862 if (match[0]) {
863 if ((wild_match(match, u->mask)) ||
864 (wild_match(match, u->desc)) || (wild_match(match, u->user)))
865 display_ban(idx, k, u, chan, 1);
866 k++;
867 } else
868 display_ban(idx, k++, u, chan, show_inact);
869 }
870 if (chan->status & CHAN_ACTIVE) {
871 masklist *b;
872 char s[UHOSTLEN], *s1, *s2, fill[256];
873 int min, sec;
874
875 for (b = chan->channel.ban; b && b->mask[0]; b = b->next) {
876 if ((!u_equals_mask(global_bans, b->mask)) &&
877 (!u_equals_mask(chan->bans, b->mask))) {
878 strcpy(s, b->who);
879 s2 = s;
880 s1 = splitnick(&s2);
881 if (s1[0])
882 sprintf(fill, "%s (%s!%s)", b->mask, s1, s2);
883 else
884 sprintf(fill, "%s (server %s)", b->mask, s2);
885 if (b->timer != 0) {
886 min = (now - b->timer) / 60;
887 sec = (now - b->timer) - (min * 60);
888 sprintf(s, " (active %02d:%02d)", min, sec);
889 strcat(fill, s);
890 }
891 if ((!match[0]) || (wild_match(match, b->mask)))
892 dprintf(idx, "* [%3d] %s\n", k, fill);
893 k++;
894 }
895 }
896 }
897 }
898 if (k == 1)
899 dprintf(idx, "(There are no bans, permanent or otherwise.)\n");
900 if ((!show_inact) && (!match[0]))
901 dprintf(idx, "%s.\n", BANS_USEBANSALL);
902 }
903
tell_exempts(int idx,int show_inact,char * match)904 static void tell_exempts(int idx, int show_inact, char *match)
905 {
906 int k = 1;
907 char *chname;
908 struct chanset_t *chan = NULL;
909 maskrec *u;
910
911 if (match[0]) {
912 chname = newsplit(&match);
913 if (chname[0] && strchr(CHANMETA, chname[0])) {
914 chan = findchan_by_dname(chname);
915 if (!chan) {
916 dprintf(idx, "%s.\n", CHAN_NOSUCH);
917 return;
918 }
919 } else
920 match = chname;
921 }
922
923 if (!chan && !(chan = findchan_by_dname(dcc[idx].u.chat->con_chan)) &&
924 !(chan = chanset))
925 chan = NULL;
926
927 if (chan && show_inact)
928 dprintf(idx, "%s: (! = %s %s)\n", EXEMPTS_GLOBAL,
929 MODES_NOTACTIVE, chan->dname);
930 else
931 dprintf(idx, "%s:\n", EXEMPTS_GLOBAL);
932 for (u = global_exempts; u; u = u->next) {
933 if (match[0]) {
934 if ((wild_match(match, u->mask)) ||
935 (wild_match(match, u->desc)) || (wild_match(match, u->user)))
936 display_exempt(idx, k, u, chan, 1);
937 k++;
938 } else
939 display_exempt(idx, k++, u, chan, show_inact);
940 }
941 if (chan) {
942 if (show_inact)
943 dprintf(idx, "%s %s: (! = %s, * = %s)\n", EXEMPTS_BYCHANNEL,
944 chan->dname, MODES_NOTACTIVE2, MODES_NOTBYBOT);
945 else
946 dprintf(idx, "%s %s: (* = %s)\n",
947 EXEMPTS_BYCHANNEL, chan->dname, MODES_NOTBYBOT);
948 for (u = chan->exempts; u; u = u->next) {
949 if (match[0]) {
950 if ((wild_match(match, u->mask)) ||
951 (wild_match(match, u->desc)) || (wild_match(match, u->user)))
952 display_exempt(idx, k, u, chan, 1);
953 k++;
954 } else
955 display_exempt(idx, k++, u, chan, show_inact);
956 }
957 if (chan->status & CHAN_ACTIVE) {
958 masklist *e;
959 char s[UHOSTLEN], *s1, *s2, fill[256];
960 int min, sec;
961
962 for (e = chan->channel.exempt; e && e->mask[0]; e = e->next) {
963 if ((!u_equals_mask(global_exempts, e->mask)) &&
964 (!u_equals_mask(chan->exempts, e->mask))) {
965 strcpy(s, e->who);
966 s2 = s;
967 s1 = splitnick(&s2);
968 if (s1[0])
969 sprintf(fill, "%s (%s!%s)", e->mask, s1, s2);
970 else
971 sprintf(fill, "%s (server %s)", e->mask, s2);
972 if (e->timer != 0) {
973 min = (now - e->timer) / 60;
974 sec = (now - e->timer) - (min * 60);
975 sprintf(s, " (active %02d:%02d)", min, sec);
976 strcat(fill, s);
977 }
978 if ((!match[0]) || (wild_match(match, e->mask)))
979 dprintf(idx, "* [%3d] %s\n", k, fill);
980 k++;
981 }
982 }
983 }
984 }
985 if (k == 1)
986 dprintf(idx, "(There are no ban exempts, permanent or otherwise.)\n");
987 if ((!show_inact) && (!match[0]))
988 dprintf(idx, "%s.\n", EXEMPTS_USEEXEMPTSALL);
989 }
990
tell_invites(int idx,int show_inact,char * match)991 static void tell_invites(int idx, int show_inact, char *match)
992 {
993 int k = 1;
994 char *chname;
995 struct chanset_t *chan = NULL;
996 maskrec *u;
997
998 if (match[0]) {
999 chname = newsplit(&match);
1000 if (chname[0] && strchr(CHANMETA, chname[0])) {
1001 chan = findchan_by_dname(chname);
1002 if (!chan) {
1003 dprintf(idx, "%s.\n", CHAN_NOSUCH);
1004 return;
1005 }
1006 } else
1007 match = chname;
1008 }
1009
1010 if (!chan && !(chan = findchan_by_dname(dcc[idx].u.chat->con_chan)) &&
1011 !(chan = chanset))
1012 chan = NULL;
1013
1014 if (chan && show_inact)
1015 dprintf(idx, "%s: (! = %s %s)\n", INVITES_GLOBAL,
1016 MODES_NOTACTIVE, chan->dname);
1017 else
1018 dprintf(idx, "%s:\n", INVITES_GLOBAL);
1019 for (u = global_invites; u; u = u->next) {
1020 if (match[0]) {
1021 if ((wild_match(match, u->mask)) ||
1022 (wild_match(match, u->desc)) || (wild_match(match, u->user)))
1023 display_invite(idx, k, u, chan, 1);
1024 k++;
1025 } else
1026 display_invite(idx, k++, u, chan, show_inact);
1027 }
1028 if (chan) {
1029 if (show_inact)
1030 dprintf(idx, "%s %s: (! = %s, * = %s)\n", INVITES_BYCHANNEL,
1031 chan->dname, MODES_NOTACTIVE2, MODES_NOTBYBOT);
1032 else
1033 dprintf(idx, "%s %s: (* = %s)\n",
1034 INVITES_BYCHANNEL, chan->dname, MODES_NOTBYBOT);
1035 for (u = chan->invites; u; u = u->next) {
1036 if (match[0]) {
1037 if ((wild_match(match, u->mask)) ||
1038 (wild_match(match, u->desc)) || (wild_match(match, u->user)))
1039 display_invite(idx, k, u, chan, 1);
1040 k++;
1041 } else
1042 display_invite(idx, k++, u, chan, show_inact);
1043 }
1044 if (chan->status & CHAN_ACTIVE) {
1045 masklist *i;
1046 char s[UHOSTLEN], *s1, *s2, fill[256];
1047 int min, sec;
1048
1049 for (i = chan->channel.invite; i && i->mask[0]; i = i->next) {
1050 if ((!u_equals_mask(global_invites, i->mask)) &&
1051 (!u_equals_mask(chan->invites, i->mask))) {
1052 strcpy(s, i->who);
1053 s2 = s;
1054 s1 = splitnick(&s2);
1055 if (s1[0])
1056 sprintf(fill, "%s (%s!%s)", i->mask, s1, s2);
1057 else
1058 sprintf(fill, "%s (server %s)", i->mask, s2);
1059 if (i->timer != 0) {
1060 min = (now - i->timer) / 60;
1061 sec = (now - i->timer) - (min * 60);
1062 sprintf(s, " (active %02d:%02d)", min, sec);
1063 strcat(fill, s);
1064 }
1065 if ((!match[0]) || (wild_match(match, i->mask)))
1066 dprintf(idx, "* [%3d] %s\n", k, fill);
1067 k++;
1068 }
1069 }
1070 }
1071 }
1072 if (k == 1)
1073 dprintf(idx, "(There are no invites, permanent or otherwise.)\n");
1074 if ((!show_inact) && (!match[0]))
1075 dprintf(idx, "%s.\n", INVITES_USEINVITESALL);
1076 }
1077
1078 /* Write the ban lists and the ignore list to a file. */
write_bans(FILE * f,int idx,char * key)1079 static int write_bans(FILE *f, int idx, char *key)
1080 {
1081 struct chanset_t *chan;
1082 maskrec *b;
1083 char *mask;
1084
1085 if (global_bans)
1086 if (efprintf(f, key, BAN_NAME " - -\n") == EOF)
1087 return 0;
1088 for (b = global_bans; b; b = b->next) {
1089 mask = str_escape(b->mask, ':', '\\');
1090 if (!mask ||
1091 efprintf(f, key, "- %s:%s%lu%s:+%lu:%lu:%s:%s\n", mask,
1092 (b->flags & MASKREC_PERM) ? "+" : "", b->expire,
1093 (b->flags & MASKREC_STICKY) ? "*" : "", b->added,
1094 b->lastactive, b->user ? b->user : botnetnick,
1095 b->desc ? b->desc : "requested") == EOF) {
1096 if (mask)
1097 nfree(mask);
1098 return 0;
1099 }
1100 nfree(mask);
1101 }
1102 for (chan = chanset; chan; chan = chan->next)
1103 if ((idx < 0) || (chan->status & CHAN_SHARED)) {
1104 struct flag_record fr = { FR_CHAN | FR_GLOBAL | FR_BOT, 0, 0, 0, 0, 0 };
1105
1106 if (idx >= 0)
1107 get_user_flagrec(dcc[idx].user, &fr, chan->dname);
1108 else
1109 fr.chan = BOT_SHARE;
1110 if ((fr.chan & BOT_SHARE) || (fr.bot & BOT_GLOBAL)) {
1111 if (efprintf(f, key, "::%s bans\n", chan->dname) == EOF)
1112 return 0;
1113 for (b = chan->bans; b; b = b->next) {
1114 mask = str_escape(b->mask, ':', '\\');
1115 if (!mask ||
1116 efprintf(f, key, "- %s:%s%lu%s:+%lu:%lu:%s:%s\n", mask,
1117 (b->flags & MASKREC_PERM) ? "+" : "", b->expire,
1118 (b->flags & MASKREC_STICKY) ? "*" : "", b->added,
1119 b->lastactive, b->user ? b->user : botnetnick,
1120 b->desc ? b->desc : "requested") == EOF) {
1121 if (mask)
1122 nfree(mask);
1123 return 0;
1124 }
1125 nfree(mask);
1126 }
1127 }
1128 }
1129 return 1;
1130 }
1131
1132 /* Write the exemptlists to a file. */
write_exempts(FILE * f,int idx,char * key)1133 static int write_exempts(FILE *f, int idx, char *key)
1134 {
1135 struct chanset_t *chan;
1136 maskrec *e;
1137 char *mask;
1138
1139 if (global_exempts)
1140 if (efprintf(f, key, EXEMPT_NAME " - -\n") == EOF) /* Daemus */
1141 return 0;
1142 for (e = global_exempts; e; e = e->next) {
1143 mask = str_escape(e->mask, ':', '\\');
1144 if (!mask ||
1145 efprintf(f, key, "%s %s:%s%lu%s:+%lu:%lu:%s:%s\n", "%", mask,
1146 (e->flags & MASKREC_PERM) ? "+" : "", e->expire,
1147 (e->flags & MASKREC_STICKY) ? "*" : "", e->added,
1148 e->lastactive, e->user ? e->user : botnetnick,
1149 e->desc ? e->desc : "requested") == EOF) {
1150 if (mask)
1151 nfree(mask);
1152 return 0;
1153 }
1154 nfree(mask);
1155 }
1156 for (chan = chanset; chan; chan = chan->next)
1157 if ((idx < 0) || (chan->status & CHAN_SHARED)) {
1158 struct flag_record fr = { FR_CHAN | FR_GLOBAL | FR_BOT, 0, 0, 0, 0, 0 };
1159
1160 if (idx >= 0)
1161 get_user_flagrec(dcc[idx].user, &fr, chan->dname);
1162 else
1163 fr.chan = BOT_SHARE;
1164 if ((fr.chan & BOT_SHARE) || (fr.bot & BOT_GLOBAL)) {
1165 if (efprintf(f, key, "&&%s exempts\n", chan->dname) == EOF)
1166 return 0;
1167 for (e = chan->exempts; e; e = e->next) {
1168 mask = str_escape(e->mask, ':', '\\');
1169 if (!mask ||
1170 efprintf(f, key, "%s %s:%s%lu%s:+%lu:%lu:%s:%s\n", "%", mask,
1171 (e->flags & MASKREC_PERM) ? "+" : "", e->expire,
1172 (e->flags & MASKREC_STICKY) ? "*" : "", e->added,
1173 e->lastactive, e->user ? e->user : botnetnick,
1174 e->desc ? e->desc : "requested") == EOF) {
1175 if (mask)
1176 nfree(mask);
1177 return 0;
1178 }
1179 nfree(mask);
1180 }
1181 }
1182 }
1183 return 1;
1184 }
1185
1186 /* Write the invitelists to a file. */
write_invites(FILE * f,int idx,char * key)1187 static int write_invites(FILE *f, int idx, char *key)
1188 {
1189 struct chanset_t *chan;
1190 maskrec *ir;
1191 char *mask;
1192
1193 if (global_invites)
1194 if (efprintf(f, key, INVITE_NAME " - -\n") == EOF)
1195 return 0;
1196 for (ir = global_invites; ir; ir = ir->next) {
1197 mask = str_escape(ir->mask, ':', '\\');
1198 if (!mask ||
1199 efprintf(f, key, "@ %s:%s%lu%s:+%lu:%lu:%s:%s\n", mask,
1200 (ir->flags & MASKREC_PERM) ? "+" : "", ir->expire,
1201 (ir->flags & MASKREC_STICKY) ? "*" : "", ir->added,
1202 ir->lastactive, ir->user ? ir->user : botnetnick,
1203 ir->desc ? ir->desc : "requested") == EOF) {
1204 if (mask)
1205 nfree(mask);
1206 return 0;
1207 }
1208 nfree(mask);
1209 }
1210 for (chan = chanset; chan; chan = chan->next)
1211 if ((idx < 0) || (chan->status & CHAN_SHARED)) {
1212 struct flag_record fr = { FR_CHAN | FR_GLOBAL | FR_BOT, 0, 0, 0, 0, 0 };
1213
1214 if (idx >= 0)
1215 get_user_flagrec(dcc[idx].user, &fr, chan->dname);
1216 else
1217 fr.chan = BOT_SHARE;
1218 if ((fr.chan & BOT_SHARE) || (fr.bot & BOT_GLOBAL)) {
1219 if (efprintf(f, key, "$$%s invites\n", chan->dname) == EOF)
1220 return 0;
1221 for (ir = chan->invites; ir; ir = ir->next) {
1222 mask = str_escape(ir->mask, ':', '\\');
1223 if (!mask ||
1224 efprintf(f, key, "@ %s:%s%lu%s:+%lu:%lu:%s:%s\n", mask,
1225 (ir->flags & MASKREC_PERM) ? "+" : "", ir->expire,
1226 (ir->flags & MASKREC_STICKY) ? "*" : "", ir->added,
1227 ir->lastactive, ir->user ? ir->user : botnetnick,
1228 ir->desc ? ir->desc : "requested") == EOF) {
1229 if (mask)
1230 nfree(mask);
1231 return 0;
1232 }
1233 nfree(mask);
1234 }
1235 }
1236 }
1237 return 1;
1238 }
1239
channels_writeuserfile(void)1240 static void channels_writeuserfile(void)
1241 {
1242 char s[1024], key[256] = "-DONTENCRYPTFILES-";
1243 FILE *f;
1244 int ret = 0;
1245
1246 simple_sprintf(s, "%s~new", userfile);
1247 f = fopen(s, "a");
1248 if (f) {
1249 if (!export_userfile)
1250 strcpy(key, userfileCryptKey);
1251 ret = write_bans(f, -1, key);
1252 ret += write_exempts(f, -1, key);
1253 ret += write_invites(f, -1, key);
1254 fclose(f);
1255 }
1256 if (ret < 3)
1257 putlog(LOG_MISC, "*", USERF_ERRWRITE);
1258 write_channels();
1259 }
1260
1261 /* Expire mask originally set by `who' on `chan'? */
expired_mask(struct chanset_t * chan,char * who)1262 static int expired_mask(struct chanset_t *chan, char *who)
1263 {
1264 memberlist *m, *m2;
1265 char buf[UHOSTLEN], *snick, *sfrom;
1266 struct userrec *u;
1267
1268 if (force_expire)
1269 return 1;
1270
1271 strcpy(buf, who);
1272 sfrom = buf;
1273 snick = splitnick(&sfrom);
1274
1275 if (!snick[0])
1276 return 1;
1277
1278 m = ismember(chan, snick);
1279 if (!m)
1280 for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next)
1281 if (!EvangelineStrcasecmp(sfrom, m2->userhost)) {
1282 m = m2;
1283 break;
1284 }
1285
1286 if (!m || !chan_hasop(m) || !rfc_casecmp(m->nick, botname))
1287 return 1;
1288
1289 if (m->user)
1290 u = m->user;
1291 else {
1292 simple_sprintf(buf, "%s!%s", m->nick, m->userhost);
1293 u = get_user_by_host(buf);
1294 }
1295 if (u && u->flags & USER_BOT)
1296 return 0;
1297 else
1298 return 1;
1299 }
1300
1301 /* Check for expired timed-bans. */
check_expired_bans(void)1302 static void check_expired_bans(void)
1303 {
1304 maskrec *u, *u2;
1305 struct chanset_t *chan;
1306 masklist *b;
1307
1308 for (u = global_bans; u; u = u2) {
1309 u2 = u->next;
1310 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
1311 putlog(LOG_MISC, "*", "%s %s (%s)", BANS_NOLONGER, u->mask, MISC_EXPIRED);
1312 for (chan = chanset; chan; chan = chan->next)
1313 for (b = chan->channel.ban; b->mask[0]; b = b->next)
1314 if (!rfc_casecmp(b->mask, u->mask) &&
1315 expired_mask(chan, b->who) && b->timer != now) {
1316 add_mode(chan, '-', 'b', u->mask);
1317 b->timer = now;
1318 }
1319 u_delban(NULL, u->mask, 1);
1320 }
1321 }
1322 for (chan = chanset; chan; chan = chan->next) {
1323 for (u = chan->bans; u; u = u2) {
1324 u2 = u->next;
1325 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
1326 putlog(LOG_MISC, "*", "%s %s %s %s (%s)", BANS_NOLONGER,
1327 u->mask, MISC_ONLOCALE, chan->dname, MISC_EXPIRED);
1328 for (b = chan->channel.ban; b->mask[0]; b = b->next)
1329 if (!rfc_casecmp(b->mask, u->mask) &&
1330 expired_mask(chan, b->who) && b->timer != now) {
1331 add_mode(chan, '-', 'b', u->mask);
1332 b->timer = now;
1333 }
1334 u_delban(chan, u->mask, 1);
1335 }
1336 }
1337 }
1338 }
1339
1340 /* Check for expired timed-exemptions */
check_expired_exempts(void)1341 static void check_expired_exempts(void)
1342 {
1343 maskrec *u, *u2;
1344 struct chanset_t *chan;
1345 masklist *b, *e;
1346 int match;
1347
1348 if (!use_exempts)
1349 return;
1350 for (u = global_exempts; u; u = u2) {
1351 u2 = u->next;
1352 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
1353 putlog(LOG_MISC, "*", "%s %s (%s)", EXEMPTS_NOLONGER,
1354 u->mask, MISC_EXPIRED);
1355 for (chan = chanset; chan; chan = chan->next) {
1356 match = 0;
1357 b = chan->channel.ban;
1358 while (b->mask[0] && !match) {
1359 if (wild_match(b->mask, u->mask) || wild_match(u->mask, b->mask))
1360 match = 1;
1361 else
1362 b = b->next;
1363 }
1364 if (match)
1365 putlog(LOG_MISC, chan->dname,
1366 "Exempt not expired on channel %s. Ban still set!",
1367 chan->dname);
1368 else
1369 for (e = chan->channel.exempt; e->mask[0]; e = e->next)
1370 if (!rfc_casecmp(e->mask, u->mask) &&
1371 expired_mask(chan, e->who) && e->timer != now) {
1372 add_mode(chan, '-', 'e', u->mask);
1373 e->timer = now;
1374 }
1375 }
1376 u_delexempt(NULL, u->mask, 1);
1377 }
1378 }
1379 for (chan = chanset; chan; chan = chan->next) {
1380 for (u = chan->exempts; u; u = u2) {
1381 u2 = u->next;
1382 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
1383 match = 0;
1384 b = chan->channel.ban;
1385 while (b->mask[0] && !match) {
1386 if (wild_match(b->mask, u->mask) || wild_match(u->mask, b->mask))
1387 match = 1;
1388 else
1389 b = b->next;
1390 }
1391 if (match)
1392 putlog(LOG_MISC, chan->dname,
1393 "Exempt not expired on channel %s. Ban still set!",
1394 chan->dname);
1395 else {
1396 putlog(LOG_MISC, "*", "%s %s %s %s (%s)", EXEMPTS_NOLONGER,
1397 u->mask, MISC_ONLOCALE, chan->dname, MISC_EXPIRED);
1398 for (e = chan->channel.exempt; e->mask[0]; e = e->next)
1399 if (!rfc_casecmp(e->mask, u->mask) &&
1400 expired_mask(chan, e->who) && e->timer != now) {
1401 add_mode(chan, '-', 'e', u->mask);
1402 e->timer = now;
1403 }
1404 u_delexempt(chan, u->mask, 1);
1405 }
1406 }
1407 }
1408 }
1409 }
1410
1411 /* Check for expired timed-invites. */
check_expired_invites(void)1412 static void check_expired_invites(void)
1413 {
1414 maskrec *u, *u2;
1415 struct chanset_t *chan;
1416 masklist *b;
1417
1418 if (!use_invites)
1419 return;
1420 for (u = global_invites; u; u = u2) {
1421 u2 = u->next;
1422 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
1423 putlog(LOG_MISC, "*", "%s %s (%s)", INVITES_NOLONGER,
1424 u->mask, MISC_EXPIRED);
1425 for (chan = chanset; chan; chan = chan->next)
1426 if (!(chan->channel.mode & CHANINV))
1427 for (b = chan->channel.invite; b->mask[0]; b = b->next)
1428 if (!rfc_casecmp(b->mask, u->mask) &&
1429 expired_mask(chan, b->who) && b->timer != now) {
1430 add_mode(chan, '-', 'I', u->mask);
1431 b->timer = now;
1432 }
1433 u_delinvite(NULL, u->mask, 1);
1434 }
1435 }
1436 for (chan = chanset; chan; chan = chan->next) {
1437 for (u = chan->invites; u; u = u2) {
1438 u2 = u->next;
1439 if (!(u->flags & MASKREC_PERM) && (now >= u->expire)) {
1440 putlog(LOG_MISC, "*", "%s %s %s %s (%s)", INVITES_NOLONGER,
1441 u->mask, MISC_ONLOCALE, chan->dname, MISC_EXPIRED);
1442 if (!(chan->channel.mode & CHANINV))
1443 for (b = chan->channel.invite; b->mask[0]; b = b->next)
1444 if (!rfc_casecmp(b->mask, u->mask) &&
1445 expired_mask(chan, b->who) && b->timer != now) {
1446 add_mode(chan, '-', 'I', u->mask);
1447 b->timer = now;
1448 }
1449 u_delinvite(chan, u->mask, 1);
1450 }
1451 }
1452 }
1453 }
1454