00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "services.h"
00015 #include "language.h"
00016
00017 Channel *chanlist[1024];
00018
00019 #define HASH(chan) ((chan)[1] ? ((chan)[1]&31)<<5 | ((chan)[2]&31) : 0)
00020
00021
00022
00023
00024 void chan_deluser(User * user, Channel * c)
00025 {
00026 struct c_userlist *u;
00027
00028 if (c->ci)
00029 update_cs_lastseen(user, c->ci);
00030
00031 for (u = c->users; u && u->user != user; u = u->next);
00032 if (!u)
00033 return;
00034
00035 if (u->ud) {
00036 if (u->ud->lastline)
00037 free(u->ud->lastline);
00038 free(u->ud);
00039 }
00040
00041 if (u->next)
00042 u->next->prev = u->prev;
00043 if (u->prev)
00044 u->prev->next = u->next;
00045 else
00046 c->users = u->next;
00047 free(u);
00048 c->usercount--;
00049
00050 if (s_BotServ && c->ci && c->ci->bi && c->usercount == BSMinUsers - 1) {
00051 anope_cmd_part(c->ci->bi->nick, c->name, NULL);
00052 }
00053
00054
00055 if (anope_get_permchan_mode() && c->mode & anope_get_permchan_mode())
00056 return;
00057
00058 if (!c->users)
00059 chan_delete(c);
00060 }
00061
00062
00063
00064
00065
00066
00067
00068 char *chan_get_modes(Channel * chan, int complete, int plus)
00069 {
00070 static char res[BUFSIZE];
00071 char *end = res;
00072
00073 if (chan->mode) {
00074 int n = 0;
00075 CBModeInfo *cbmi = cbmodeinfos;
00076
00077 do {
00078 if (chan->mode & cbmi->flag)
00079 *end++ = cbmi->mode;
00080 } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
00081
00082 if (complete) {
00083 cbmi = cbmodeinfos;
00084
00085 do {
00086 if (cbmi->getvalue && (chan->mode & cbmi->flag) &&
00087 (plus || !(cbmi->flags & CBM_MINUS_NO_ARG))) {
00088 char *value = cbmi->getvalue(chan);
00089
00090 if (value) {
00091 *end++ = ' ';
00092 while (*value)
00093 *end++ = *value++;
00094 }
00095 }
00096 } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
00097 }
00098 }
00099
00100 *end = 0;
00101
00102 return res;
00103 }
00104
00105
00106
00107
00108
00109 int chan_get_user_status(Channel * chan, User * user)
00110 {
00111 struct u_chanlist *uc;
00112
00113 for (uc = user->chans; uc; uc = uc->next)
00114 if (uc->chan == chan)
00115 return uc->status;
00116
00117 return 0;
00118 }
00119
00120
00121
00122
00123
00124 int chan_has_user_status(Channel * chan, User * user, int16 status)
00125 {
00126 struct u_chanlist *uc;
00127
00128 for (uc = user->chans; uc; uc = uc->next) {
00129 if (uc->chan == chan) {
00130 if (debug) {
00131 alog("debug: chan_has_user_status wanted %d the user is %d", status, uc->status);
00132 }
00133 return (uc->status & status);
00134 }
00135 }
00136 return 0;
00137 }
00138
00139
00140
00141
00142
00143 void chan_remove_user_status(Channel * chan, User * user, int16 status)
00144 {
00145 struct u_chanlist *uc;
00146
00147 if (debug >= 2)
00148 alog("debug: removing user status (%d) from %s for %s", status,
00149 user->nick, chan->name);
00150
00151 for (uc = user->chans; uc; uc = uc->next) {
00152 if (uc->chan == chan) {
00153 uc->status &= ~status;
00154 break;
00155 }
00156 }
00157 }
00158
00159
00160
00161 void chan_set_modes(const char *source, Channel * chan, int ac, char **av,
00162 int check)
00163 {
00164 int add = 1;
00165 char *modes = av[0], mode;
00166 CBMode *cbm;
00167 CMMode *cmm;
00168 CUMode *cum;
00169 unsigned char botmode = 0;
00170 BotInfo *bi;
00171 User *u, *user;
00172 int i, real_ac = ac;
00173 char **real_av = av;
00174
00175 if (debug)
00176 alog("debug: Changing modes for %s to %s", chan->name,
00177 merge_args(ac, av));
00178
00179 if (UseTS6 && ircd->ts6) {
00180 u = find_byuid(source);
00181 if (!u) u = finduser(source);
00182 } else
00183 u = finduser(source);
00184
00185 if (u && (chan_get_user_status(chan, u) & CUS_DEOPPED)) {
00186 char *s;
00187
00188 if (debug)
00189 alog("debug: Removing instead of setting due to DEOPPED flag");
00190
00191
00192 for (s = av[0]; *s; s++) {
00193 if (*s == '+')
00194 *s = '-';
00195 else if (*s == '-')
00196 *s = '+';
00197 }
00198
00199
00200 anope_cmd_mode(whosends(chan->ci), chan->name, merge_args(ac, av));
00201
00202 return;
00203 }
00204
00205 ac--;
00206
00207 while ((mode = *modes++)) {
00208
00209 switch (mode) {
00210 case '+':
00211 add = 1;
00212 continue;
00213 case '-':
00214 add = 0;
00215 continue;
00216 }
00217
00218 if (((int) mode) < 0) {
00219 if (debug)
00220 alog("Debug: Malformed mode detected on %s.", chan->name);
00221 continue;
00222 }
00223
00224 if ((cum = &cumodes[(int) mode])->status != 0) {
00225 if (ac == 0) {
00226 alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
00227 continue;
00228 }
00229 ac--;
00230 av++;
00231
00232 if ((cum->flags & CUF_PROTECT_BOTSERV) && !add) {
00233 if ((bi = findbot(*av))) {
00234 if (!botmode || botmode != mode) {
00235 anope_cmd_mode(bi->nick, chan->name, "+%c %s",
00236 mode, bi->nick);
00237 botmode = mode;
00238 continue;
00239 } else {
00240 botmode = mode;
00241 continue;
00242 }
00243 }
00244 } else {
00245 if ((bi = findbot(*av))) {
00246 continue;
00247 }
00248 }
00249
00250 if (UseTS6 && ircd->ts6) {
00251 user = find_byuid(*av);
00252 if (!user) user = finduser(*av);
00253 } else
00254 user = finduser(*av);
00255 if (!user) {
00256 if (debug)
00257 alog("debug: MODE %s %c%c for nonexistent user %s",
00258 chan->name, (add ? '+' : '-'), mode, *av);
00259 continue;
00260 }
00261
00262 if (debug)
00263 alog("debug: Setting %c%c on %s for %s", (add ? '+' : '-'),
00264 mode, chan->name, user->nick);
00265
00266 if (add) {
00267 chan_set_user_status(chan, user, cum->status);
00268
00269 if (cum->status & CUS_OP || cum->status & CUS_HALFOP)
00270 chan_remove_user_status(chan, user, CUS_DEOPPED);
00271 } else {
00272 chan_remove_user_status(chan, user, cum->status);
00273 }
00274
00275 } else if ((cbm = &cbmodes[(int) mode])->flag != 0) {
00276 if (check >= 0) {
00277 if (add)
00278 chan->mode |= cbm->flag;
00279 else
00280 chan->mode &= ~cbm->flag;
00281 }
00282
00283 if (cbm->setvalue) {
00284 if (add || !(cbm->flags & CBM_MINUS_NO_ARG)) {
00285 if (ac == 0) {
00286 alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
00287 continue;
00288 }
00289 ac--;
00290 av++;
00291 }
00292 cbm->setvalue(chan, add ? *av : NULL);
00293 }
00294
00295 if (check < 0) {
00296 if (add)
00297 chan->mode |= cbm->flag;
00298 else
00299 chan->mode &= ~cbm->flag;
00300 }
00301 } else if ((cmm = &cmmodes[(int) mode])->addmask) {
00302 if (ac == 0) {
00303 alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
00304 continue;
00305 }
00306
00307 ac--;
00308 av++;
00309 if (add)
00310 cmm->addmask(chan, *av);
00311 else
00312 cmm->delmask(chan, *av);
00313 }
00314 }
00315
00316
00317
00318 if (UseTS6 && ircd->ts6) {
00319 user = find_byuid(source);
00320 if (!user) user = finduser(source);
00321 } else
00322 user = finduser(source);
00323
00324 if ((user && is_ulined(user->server->name)) || is_ulined((char *)source))
00325 return;
00326
00327 if (check > 0) {
00328 check_modes(chan);
00329
00330 if ((check < 2) || (check == 3)) {
00331
00332
00333
00334 real_ac--;
00335 real_av++;
00336 for (i = 0; i < real_ac; i++) {
00337 if (UseTS6 && ircd->ts6) {
00338 user = find_byuid(*real_av);
00339 if (!user) user = finduser(*real_av);
00340 } else
00341 user = finduser(*real_av);
00342
00343 if (!user && UseTS6 && ircd->ts6) user = find_byuid(*real_av);
00344 if (user && is_on_chan(chan, user)) {
00345 if (check < 2)
00346 chan_set_correct_modes(user, chan, 0);
00347 else if ((chan->ci->flags) && (chan->ci->flags & CI_SECUREOPS))
00348 chan_set_correct_modes(user, chan, 0);
00349 }
00350 real_av++;
00351 }
00352 }
00353 }
00354 }
00355
00356
00357
00358
00359
00360 void chan_set_user_status(Channel * chan, User * user, int16 status)
00361 {
00362 struct u_chanlist *uc;
00363
00364 if (debug >= 2)
00365 alog("debug: setting user status (%d) on %s for %s", status,
00366 user->nick, chan->name);
00367
00368 if (HelpChannel && ircd->supporthelper && (status & CUS_OP)
00369 && (stricmp(chan->name, HelpChannel) == 0)
00370 && (!chan->ci || check_access(user, chan->ci, CA_AUTOOP))) {
00371 if (debug) {
00372 alog("debug: %s being given +h for having %d status in %s",
00373 user->nick, status, chan->name);
00374 }
00375 common_svsmode(user, "+h", NULL);
00376 }
00377
00378 for (uc = user->chans; uc; uc = uc->next) {
00379 if (uc->chan == chan) {
00380 uc->status |= status;
00381 break;
00382 }
00383 }
00384 }
00385
00386
00387
00388
00389
00390
00391
00392 Channel *findchan(const char *chan)
00393 {
00394 Channel *c;
00395
00396 if (!chan || !*chan) {
00397 if (debug) {
00398 alog("debug: findchan() called with NULL values");
00399 }
00400 return NULL;
00401 }
00402
00403 if (debug >= 3)
00404 alog("debug: findchan(%p)", chan);
00405 c = chanlist[HASH(chan)];
00406 while (c) {
00407 if (stricmp(c->name, chan) == 0) {
00408 if (debug >= 3)
00409 alog("debug: findchan(%s) -> %p", chan, (void *) c);
00410 return c;
00411 }
00412 c = c->next;
00413 }
00414 if (debug >= 3)
00415 alog("debug: findchan(%s) -> %p", chan, (void *) c);
00416 return NULL;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425 static Channel *current;
00426 static int next_index;
00427
00428 Channel *firstchan(void)
00429 {
00430 next_index = 0;
00431 while (next_index < 1024 && current == NULL)
00432 current = chanlist[next_index++];
00433 if (debug >= 3)
00434 alog("debug: firstchan() returning %s",
00435 current ? current->name : "NULL (end of list)");
00436 return current;
00437 }
00438
00439 Channel *nextchan(void)
00440 {
00441 if (current)
00442 current = current->next;
00443 if (!current && next_index < 1024) {
00444 while (next_index < 1024 && current == NULL)
00445 current = chanlist[next_index++];
00446 }
00447 if (debug >= 3)
00448 alog("debug: nextchan() returning %s",
00449 current ? current->name : "NULL (end of list)");
00450 return current;
00451 }
00452
00453
00454
00455
00456
00457 void get_channel_stats(long *nrec, long *memuse)
00458 {
00459 long count = 0, mem = 0;
00460 Channel *chan;
00461 struct c_userlist *cu;
00462 BanData *bd;
00463 int i;
00464
00465 for (i = 0; i < 1024; i++) {
00466 for (chan = chanlist[i]; chan; chan = chan->next) {
00467 count++;
00468 mem += sizeof(*chan);
00469 if (chan->topic)
00470 mem += strlen(chan->topic) + 1;
00471 if (chan->key)
00472 mem += strlen(chan->key) + 1;
00473 if (ircd->fmode) {
00474 if (chan->flood)
00475 mem += strlen(chan->flood) + 1;
00476 }
00477 if (ircd->Lmode) {
00478 if (chan->redirect)
00479 mem += strlen(chan->redirect) + 1;
00480 }
00481 if (ircd->jmode) {
00482 if (chan->throttle)
00483 mem += strlen(chan->throttle) + 1;
00484 }
00485 mem += get_memuse(chan->bans);
00486 if (ircd->except) {
00487 mem += get_memuse(chan->excepts);
00488 }
00489 if (ircd->invitemode) {
00490 mem += get_memuse(chan->invites);
00491 }
00492 for (cu = chan->users; cu; cu = cu->next) {
00493 mem += sizeof(*cu);
00494 if (cu->ud) {
00495 mem += sizeof(*cu->ud);
00496 if (cu->ud->lastline)
00497 mem += strlen(cu->ud->lastline) + 1;
00498 }
00499 }
00500 for (bd = chan->bd; bd; bd = bd->next) {
00501 if (bd->mask)
00502 mem += strlen(bd->mask) + 1;
00503 mem += sizeof(*bd);
00504 }
00505 }
00506 }
00507 *nrec = count;
00508 *memuse = mem;
00509 }
00510
00511
00512
00513
00514
00515 int is_on_chan(Channel * c, User * u)
00516 {
00517 struct u_chanlist *uc;
00518
00519 for (uc = u->chans; uc; uc = uc->next)
00520 if (uc->chan == c)
00521 return 1;
00522
00523 return 0;
00524 }
00525
00526
00527
00528
00529
00530
00531 User *nc_on_chan(Channel * c, NickCore * nc)
00532 {
00533 struct c_userlist *u;
00534
00535 if (!c || !nc)
00536 return NULL;
00537
00538 for (u = c->users; u; u = u->next) {
00539 if (u->user->na && u->user->na->nc == nc
00540 && nick_recognized(u->user))
00541 return u->user;
00542 }
00543 return NULL;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 void do_join(const char *source, int ac, char **av)
00555 {
00556 User *user;
00557 Channel *chan;
00558 char *s, *t;
00559 struct u_chanlist *c, *nextc;
00560 char *channame;
00561 time_t ts = time(NULL);
00562
00563 if (UseTS6 && ircd->ts6) {
00564 user = find_byuid(source);
00565 if (!user)
00566 user = finduser(source);
00567 } else {
00568 user = finduser(source);
00569 }
00570 if (!user) {
00571 if (debug) {
00572 alog("debug: JOIN from nonexistent user %s: %s", source,
00573 merge_args(ac, av));
00574 }
00575 return;
00576 }
00577
00578 t = av[0];
00579 while (*(s = t)) {
00580 t = s + strcspn(s, ",");
00581 if (*t)
00582 *t++ = 0;
00583
00584 if (*s == '0') {
00585 c = user->chans;
00586 while (c) {
00587 nextc = c->next;
00588 channame = sstrdup(c->chan->name);
00589 send_event(EVENT_PART_CHANNEL, 3, EVENT_START, user->nick,
00590 channame);
00591 chan_deluser(user, c->chan);
00592 send_event(EVENT_PART_CHANNEL, 3, EVENT_STOP, user->nick,
00593 channame);
00594 free(channame);
00595 free(c);
00596 c = nextc;
00597 }
00598 user->chans = NULL;
00599 continue;
00600 }
00601
00602
00603 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START, source, s);
00604
00605
00606
00607
00608
00609 if (check_kick(user, s, ts))
00610 continue;
00611
00612 if (ac == 2) {
00613 ts = strtoul(av[1], NULL, 10);
00614 if (debug) {
00615 alog("debug: recieved a new TS for JOIN: %ld",
00616 (long int) ts);
00617 }
00618 }
00619
00620 chan = findchan(s);
00621 chan = join_user_update(user, chan, s, ts);
00622 chan_set_correct_modes(user, chan, 1);
00623
00624 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP, source, s);
00625 }
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 void do_kick(const char *source, int ac, char **av)
00637 {
00638 BotInfo *bi;
00639 ChannelInfo *ci;
00640 User *user;
00641 char *s, *t;
00642 struct u_chanlist *c;
00643 Uid *uid;
00644
00645 t = av[1];
00646 while (*(s = t)) {
00647 t = s + strcspn(s, ",");
00648 if (*t)
00649 *t++ = 0;
00650
00651 if (ircd->ts6 && UseTS6)
00652 {
00653 uid = find_nickuid(s);
00654 if (uid)
00655 s = uid->nick;
00656 }
00657
00658
00659
00660
00661
00662 if (s_BotServ && (bi = findbot(s)) && (ci = cs_findchan(av[0]))) {
00663 bot_join(ci);
00664 continue;
00665 }
00666
00667 if (UseTS6 && ircd->ts6) {
00668 user = find_byuid(s);
00669 if (!user) {
00670 user = finduser(s);
00671 }
00672 } else {
00673 user = finduser(s);
00674 }
00675 if (!user) {
00676 if (debug) {
00677 alog("debug: KICK for nonexistent user %s on %s: %s", s,
00678 av[0], merge_args(ac - 2, av + 2));
00679 }
00680 continue;
00681 }
00682 if (debug) {
00683 alog("debug: kicking %s from %s", user->nick, av[0]);
00684 }
00685 for (c = user->chans; c && stricmp(av[0], c->chan->name) != 0;
00686 c = c->next);
00687 if (c) {
00688 send_event(EVENT_CHAN_KICK, 2, user->nick, av[0]);
00689 chan_deluser(user, c->chan);
00690 if (c->next)
00691 c->next->prev = c->prev;
00692 if (c->prev)
00693 c->prev->next = c->next;
00694 else
00695 user->chans = c->next;
00696 free(c);
00697 }
00698 }
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708 void do_part(const char *source, int ac, char **av)
00709 {
00710 User *user;
00711 char *s, *t;
00712 struct u_chanlist *c;
00713 char *channame;
00714
00715 if (UseTS6 && ircd->ts6) {
00716 user = find_byuid(source);
00717 if (!user)
00718 user = finduser(source);
00719 } else {
00720 user = finduser(source);
00721 }
00722 if (!user) {
00723 if (debug) {
00724 alog("debug: PART from nonexistent user %s: %s", source,
00725 merge_args(ac, av));
00726 }
00727 return;
00728 }
00729 t = av[0];
00730 while (*(s = t)) {
00731 t = s + strcspn(s, ",");
00732 if (*t)
00733 *t++ = 0;
00734 if (debug)
00735 alog("debug: %s leaves %s", source, s);
00736 for (c = user->chans; c && stricmp(s, c->chan->name) != 0;
00737 c = c->next);
00738 if (c) {
00739 if (!c->chan) {
00740 alog("user: BUG parting %s: channel entry found but c->chan NULL", s);
00741 return;
00742 }
00743 channame = sstrdup(c->chan->name);
00744 send_event(EVENT_PART_CHANNEL, (ac >= 2 ? 4 : 3), EVENT_START,
00745 user->nick, channame, (ac >= 2 ? av[1] : ""));
00746
00747 chan_deluser(user, c->chan);
00748 if (c->next)
00749 c->next->prev = c->prev;
00750 if (c->prev)
00751 c->prev->next = c->next;
00752 else
00753 user->chans = c->next;
00754 free(c);
00755
00756 send_event(EVENT_PART_CHANNEL, (ac >= 2 ? 4 : 3), EVENT_STOP,
00757 user->nick, channame, (ac >= 2 ? av[1] : ""));
00758 free(channame);
00759 }
00760 }
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 void do_sjoin(const char *source, int ac, char **av)
00802 {
00803 Channel *c;
00804 User *user;
00805 Server *serv = NULL;
00806 struct c_userlist *cu;
00807 char *s = NULL;
00808 char *end, cubuf[7], *end2, *cumodes[6], *buf;
00809 int is_sqlined = 0;
00810 int ts = 0;
00811 int is_created = 0;
00812 int keep_their_modes = 1;
00813
00814 if (UseTS6 && ircd->ts6)
00815 serv = findserver_uid(servlist, source);
00816 if (!serv)
00817 serv = findserver(servlist, source);
00818
00819 if (ircd->sjb64) {
00820 ts = base64dects(av[0]);
00821 } else {
00822 ts = strtoul(av[0], NULL, 10);
00823 }
00824 c = findchan(av[1]);
00825 if (c != NULL) {
00826 if (c->creation_time == 0 || ts == 0)
00827 c->creation_time = 0;
00828 else if (c->creation_time > ts) {
00829 c->creation_time = ts;
00830 for (cu = c->users; cu; cu = cu->next) {
00831
00832 cumodes[0] = "-ov";
00833 cumodes[1] = cu->user->nick;
00834 cumodes[2] = cu->user->nick;
00835 chan_set_modes(source, c, 3, cumodes, 2);
00836 }
00837 if (c->ci)
00838 {
00839 if (c->ci->bi)
00840 {
00841
00842 anope_cmd_part(c->ci->bi->nick, c->name, "TS reop");
00843 bot_join(c->ci);
00844 }
00845
00846 if (ircd->chanreg && ircd->regmode)
00847 {
00848 c->mode |= ircd->regmode;
00849 anope_cmd_mode(whosends(c->ci), c->name, "+r");
00850 }
00851 }
00852
00853 } else if (c->creation_time < ts)
00854 keep_their_modes = 0;
00855 } else
00856 is_created = 1;
00857
00858
00859 if (ac >= 4) {
00860 if (ircd->chansqline) {
00861 if (!c)
00862 is_sqlined = check_chan_sqline(av[1]);
00863 }
00864
00865 cubuf[0] = '+';
00866 cumodes[0] = cubuf;
00867
00868
00869 s = av[ac - 1];
00870
00871 while (*s) {
00872 end = strchr(s, ' ');
00873 if (end)
00874 *end = 0;
00875
00876 end2 = cubuf + 1;
00877
00878
00879 if (ircd->sjoinbanchar) {
00880 if (*s == ircd->sjoinbanchar && keep_their_modes) {
00881 buf = myStrGetToken(s, ircd->sjoinbanchar, 1);
00882 add_ban(c, buf);
00883 if (buf)
00884 free(buf);
00885 if (!end)
00886 break;
00887 s = end + 1;
00888 continue;
00889 }
00890 }
00891 if (ircd->sjoinexchar) {
00892 if (*s == ircd->sjoinexchar && keep_their_modes) {
00893 buf = myStrGetToken(s, ircd->sjoinexchar, 1);
00894 add_exception(c, buf);
00895 if (buf)
00896 free(buf);
00897 if (!end)
00898 break;
00899 s = end + 1;
00900 continue;
00901 }
00902 }
00903
00904 if (ircd->sjoininvchar) {
00905 if (*s == ircd->sjoininvchar && keep_their_modes) {
00906 buf = myStrGetToken(s, ircd->sjoininvchar, 1);
00907 add_invite(c, buf);
00908 if (buf)
00909 free(buf);
00910 if (!end)
00911 break;
00912 s = end + 1;
00913 continue;
00914 }
00915 }
00916
00917 while (csmodes[(int) *s] != 0)
00918 *end2++ = csmodes[(int) *s++];
00919 *end2 = 0;
00920
00921
00922 if (UseTS6 && ircd->ts6) {
00923 user = find_byuid(s);
00924 if (!user)
00925 user = finduser(s);
00926 } else {
00927 user = finduser(s);
00928 }
00929
00930 if (!user) {
00931 if (debug) {
00932 alog("debug: SJOIN for nonexistent user %s on %s", s,
00933 av[1]);
00934 }
00935 return;
00936 }
00937
00938 if (is_sqlined && !is_oper(user)) {
00939 anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
00940 } else {
00941 if (!check_kick(user, av[1], ts)) {
00942 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START,
00943 user->nick, av[1]);
00944
00945
00946
00947
00948
00949
00950
00951 c = join_user_update(user, c, av[1], ts);
00952
00953
00954 if (end2 - cubuf > 1 && keep_their_modes) {
00955 int i;
00956
00957 for (i = 1; i < end2 - cubuf; i++)
00958 cumodes[i] = user->nick;
00959 chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
00960 cumodes, 2);
00961 }
00962
00963 if (c->ci && (!serv || is_sync(serv))
00964 && !c->topic_sync)
00965 restore_topic(c->name);
00966 chan_set_correct_modes(user, c, 1);
00967
00968 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP,
00969 user->nick, av[1]);
00970 }
00971 }
00972
00973 if (!end)
00974 break;
00975 s = end + 1;
00976 }
00977
00978 if (c && keep_their_modes) {
00979
00980 chan_set_modes(source, c, ac - 3, &av[2], 2);
00981 }
00982
00983
00984 } else if (ac == 3 && !ircd->ts6) {
00985 if (ircd->chansqline) {
00986 if (!c)
00987 is_sqlined = check_chan_sqline(av[1]);
00988 }
00989
00990 cubuf[0] = '+';
00991 cumodes[0] = cubuf;
00992
00993
00994 s = av[2];
00995
00996 while (*s) {
00997 end = strchr(s, ' ');
00998 if (end)
00999 *end = 0;
01000
01001 end2 = cubuf + 1;
01002
01003 while (csmodes[(int) *s] != 0)
01004 *end2++ = csmodes[(int) *s++];
01005 *end2 = 0;
01006
01007 if (UseTS6 && ircd->ts6) {
01008 user = find_byuid(s);
01009 if (!user)
01010 user = finduser(s);
01011 } else {
01012 user = finduser(s);
01013 }
01014
01015 if (!user) {
01016 if (debug) {
01017 alog("debug: SJOIN for nonexistent user %s on %s", s,
01018 av[1]);
01019 }
01020 return;
01021 }
01022
01023 if (is_sqlined && !is_oper(user)) {
01024 anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
01025 } else {
01026 if (!check_kick(user, av[1], ts)) {
01027 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START,
01028 user->nick, av[1]);
01029
01030
01031
01032
01033
01034
01035
01036 c = join_user_update(user, c, av[1], ts);
01037
01038
01039 if (end2 - cubuf > 1 && keep_their_modes) {
01040 int i;
01041
01042 for (i = 1; i < end2 - cubuf; i++)
01043 cumodes[i] = user->nick;
01044 chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
01045 cumodes, 2);
01046 }
01047
01048 chan_set_correct_modes(user, c, 1);
01049
01050 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP,
01051 user->nick, av[1]);
01052 }
01053 }
01054
01055 if (!end)
01056 break;
01057 s = end + 1;
01058 }
01059 } else if (ac == 3 && ircd->ts6) {
01060 if (ircd->chansqline) {
01061 if (!c)
01062 is_sqlined = check_chan_sqline(av[1]);
01063 }
01064
01065 cubuf[0] = '+';
01066 cumodes[0] = cubuf;
01067
01068
01069 s = sstrdup(source);
01070
01071 while (*s) {
01072 end = strchr(s, ' ');
01073 if (end)
01074 *end = 0;
01075
01076 end2 = cubuf + 1;
01077
01078 while (csmodes[(int) *s] != 0)
01079 *end2++ = csmodes[(int) *s++];
01080 *end2 = 0;
01081
01082 if (UseTS6 && ircd->ts6) {
01083 user = find_byuid(s);
01084 if (!user)
01085 user = finduser(s);
01086 } else {
01087 user = finduser(s);
01088 }
01089 if (!user) {
01090 if (debug) {
01091 alog("debug: SJOIN for nonexistent user %s on %s", s,
01092 av[1]);
01093 }
01094 free(s);
01095 return;
01096 }
01097
01098 if (is_sqlined && !is_oper(user)) {
01099 anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
01100 } else {
01101 if (!check_kick(user, av[1], ts)) {
01102 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START,
01103 user->nick, av[1]);
01104
01105
01106
01107
01108
01109
01110
01111 c = join_user_update(user, c, av[1], ts);
01112
01113
01114 if (end2 - cubuf > 1 && keep_their_modes) {
01115 int i;
01116
01117 for (i = 1; i < end2 - cubuf; i++)
01118 cumodes[i] = user->nick;
01119 chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
01120 cumodes, 2);
01121 }
01122
01123 chan_set_correct_modes(user, c, 1);
01124
01125 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP,
01126 user->nick, av[1]);
01127 }
01128 }
01129
01130 if (!end)
01131 break;
01132 s = end + 1;
01133 }
01134 free(s);
01135 } else if (ac == 2) {
01136 if (UseTS6 && ircd->ts6) {
01137 user = find_byuid(source);
01138 if (!user)
01139 user = finduser(source);
01140 } else {
01141 user = finduser(source);
01142 }
01143 if (!user) {
01144 if (debug) {
01145 alog("debug: SJOIN for nonexistent user %s on %s", source,
01146 av[1]);
01147 }
01148 return;
01149 }
01150
01151 if (check_kick(user, av[1], ts))
01152 return;
01153
01154 if (ircd->chansqline) {
01155 if (!c)
01156 is_sqlined = check_chan_sqline(av[1]);
01157 }
01158
01159 if (is_sqlined && !is_oper(user)) {
01160 anope_cmd_kick(s_OperServ, av[1], user->nick, "Q-Lined");
01161 } else {
01162 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START, user->nick,
01163 av[1]);
01164
01165 c = join_user_update(user, c, av[1], ts);
01166 if (is_created && c->ci)
01167 restore_topic(c->name);
01168 chan_set_correct_modes(user, c, 1);
01169
01170 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP, user->nick,
01171 av[1]);
01172 }
01173 }
01174 }
01175
01176
01177
01178
01179
01180
01181 void do_cmode(const char *source, int ac, char **av)
01182 {
01183 Channel *chan;
01184 ChannelInfo *ci = NULL;
01185 int i;
01186 char *t;
01187
01188 if (ircdcap->tsmode) {
01189
01190
01191 if (uplink_capab & ircdcap->tsmode || UseTSMODE) {
01192 for (i = 0; i < strlen(av[1]); i++) {
01193 if (!isdigit(av[1][i]))
01194 break;
01195 }
01196 if (av[1][i] == '\0') {
01197
01198
01199 t = av[0];
01200 av[0] = av[1];
01201 av[1] = t;
01202 ac--;
01203 av++;
01204 } else {
01205 alog("TSMODE enabled but MODE has no valid TS");
01206 }
01207 }
01208 }
01209
01210
01211 if (UseTS6 && ircd->ts6) {
01212 if (isdigit(av[0][0])) {
01213 ac--;
01214 av++;
01215 }
01216 }
01217
01218 chan = findchan(av[0]);
01219 if (!chan) {
01220 if (debug) {
01221 ci = cs_findchan(av[0]);
01222 if (!(ci && (ci->flags & CI_VERBOTEN)))
01223 alog("debug: MODE %s for nonexistent channel %s",
01224 merge_args(ac - 1, av + 1), av[0]);
01225 }
01226 return;
01227 }
01228
01229
01230 if (strchr(source, '.') && !av[1][strcspn(av[1], "bovahq")]) {
01231 if (time(NULL) != chan->server_modetime) {
01232 chan->server_modecount = 0;
01233 chan->server_modetime = time(NULL);
01234 }
01235 chan->server_modecount++;
01236 }
01237
01238 ac--;
01239 av++;
01240 chan_set_modes(source, chan, ac, av, 1);
01241 }
01242
01243
01244
01245
01246
01247 void do_topic(const char *source, int ac, char **av)
01248 {
01249 Channel *c = findchan(av[0]);
01250 ChannelInfo *ci;
01251 int ts;
01252 time_t topic_time;
01253 char *topicsetter;
01254
01255 if (ircd->sjb64) {
01256 ts = base64dects(av[2]);
01257 if (debug) {
01258 alog("debug: encoded TOPIC TS %s converted to %d", av[2], ts);
01259 }
01260 } else {
01261 ts = strtoul(av[2], NULL, 10);
01262 }
01263
01264 topic_time = ts;
01265
01266 if (!c) {
01267 if (debug) {
01268 alog("debug: TOPIC %s for nonexistent channel %s",
01269 merge_args(ac - 1, av + 1), av[0]);
01270 }
01271 return;
01272 }
01273
01274
01275 c->topic_sync = 1;
01276
01277 ci = c->ci;
01278
01279
01280
01281
01282 topicsetter = myStrGetToken(av[1], '!', 0);
01283
01284
01285
01286
01287
01288
01289 if ((ac > 3) && *av[3] && ci && ci->last_topic
01290 && (strcmp(av[3], ci->last_topic) == 0)
01291 && (strcmp(topicsetter, ci->last_topic_setter) == 0)) {
01292
01293 if (c->topic)
01294 free(c->topic);
01295 c->topic = sstrdup(av[3]);
01296 strscpy(c->topic_setter, topicsetter, sizeof(c->topic_setter));
01297 c->topic_time = topic_time;
01298
01299 free(topicsetter);
01300 return;
01301 }
01302
01303 if (check_topiclock(c, topic_time)) {
01304 free(topicsetter);
01305 return;
01306 }
01307
01308 if (c->topic) {
01309 free(c->topic);
01310 c->topic = NULL;
01311 }
01312 if (ac > 3 && *av[3]) {
01313 c->topic = sstrdup(av[3]);
01314 }
01315
01316 strscpy(c->topic_setter, topicsetter, sizeof(c->topic_setter));
01317 c->topic_time = topic_time;
01318 free(topicsetter);
01319
01320 record_topic(av[0]);
01321
01322
01323 if (serv_uplink && is_sync(serv_uplink)) {
01324 if (ci && ci->last_topic) {
01325 send_event(EVENT_TOPIC_UPDATED, 2, av[0], ci->last_topic);
01326 } else {
01327 send_event(EVENT_TOPIC_UPDATED, 2, av[0], "");
01328 }
01329 }
01330 }
01331
01332
01333
01334
01335
01336 void add_ban(Channel * chan, char *mask)
01337 {
01338 Entry *ban;
01339
01340 if (!chan || !mask) {
01341 if (debug) {
01342 alog("debug: add_ban called with NULL values");
01343 }
01344 return;
01345 }
01346
01347
01348
01349 if (!chan->bans)
01350 chan->bans = list_create();
01351 ban = entry_add(chan->bans, mask);
01352
01353 if (!ban)
01354 fatal("Creating new ban entry failed");
01355
01356
01357
01358 if (s_BotServ && BSSmartJoin && chan->ci && chan->ci->bi
01359 && chan->usercount >= BSMinUsers) {
01360 BotInfo *bi = chan->ci->bi;
01361
01362 if (entry_match(ban, bi->nick, bi->user, bi->host, 0)) {
01363 anope_cmd_mode(bi->nick, chan->name, "-b %s", mask);
01364 entry_delete(chan->bans, ban);
01365 return;
01366 }
01367 }
01368
01369 if (debug)
01370 alog("debug: Added ban %s to channel %s", mask, chan->name);
01371 }
01372
01373
01374
01375 void add_exception(Channel * chan, char *mask)
01376 {
01377 Entry *exception;
01378
01379 if (!chan || !mask) {
01380 if (debug)
01381 alog("debug: add_exception called with NULL values");
01382 return;
01383 }
01384
01385
01386
01387 if (!chan->excepts)
01388 chan->excepts = list_create();
01389 exception = entry_add(chan->excepts, mask);
01390
01391 if (!exception)
01392 fatal("Creating new exception entry failed");
01393
01394 if (debug)
01395 alog("debug: Added except %s to channel %s", mask, chan->name);
01396 }
01397
01398
01399
01400 void add_invite(Channel * chan, char *mask)
01401 {
01402 Entry *invite;
01403
01404 if (!chan || !mask) {
01405 if (debug)
01406 alog("debug: add_invite called with NULL values");
01407 return;
01408 }
01409
01410
01411
01412 if (!chan->invites)
01413 chan->invites = list_create();
01414 invite = entry_add(chan->invites, mask);
01415
01416 if (!invite)
01417 fatal("Creating new exception entry failed");
01418
01419 if (debug)
01420 alog("debug: Added invite %s to channel %s", mask, chan->name);
01421 }
01422
01423
01424
01434 void chan_set_correct_modes(User * user, Channel * c, int give_modes)
01435 {
01436 char *tmp;
01437 char modebuf[BUFSIZE];
01438 char userbuf[BUFSIZE];
01439 int status;
01440 int add_modes = 0;
01441 int rem_modes = 0;
01442 ChannelInfo *ci;
01443
01444 if (!c || !(ci = c->ci))
01445 return;
01446
01447 if ((ci->flags & CI_VERBOTEN) || (*(c->name) == '+'))
01448 return;
01449
01450 status = chan_get_user_status(c, user);
01451
01452 if (debug)
01453 alog("debug: Setting correct user modes for %s on %s (current status: %d, %sgiving modes)", user->nick, c->name, status, (give_modes ? "" : "not "));
01454
01455
01456
01457
01458
01459
01460 if (give_modes && (get_ignore(user->nick) == NULL)
01461 && (!user->na || !(user->na->nc->flags & NI_AUTOOP))) {
01462 if (ircd->owner && is_founder(user, ci))
01463 add_modes |= CUS_OWNER;
01464 else if ((ircd->protect || ircd->admin)
01465 && check_access(user, ci, CA_AUTOPROTECT))
01466 add_modes |= CUS_PROTECT;
01467 if (check_access(user, ci, CA_AUTOOP))
01468 add_modes |= CUS_OP;
01469 else if (ircd->halfop && check_access(user, ci, CA_AUTOHALFOP))
01470 add_modes |= CUS_HALFOP;
01471 else if (check_access(user, ci, CA_AUTOVOICE))
01472 add_modes |= CUS_VOICE;
01473 }
01474
01475
01476
01477
01478
01479
01480
01481 if (((ci->flags & CI_SECUREOPS) || (c->usercount == 1 && is_sync(user->server))
01482 || check_access(user, ci, CA_AUTODEOP))
01483 && !is_ulined(user->server->name)) {
01484 if (ircd->owner && (status & CUS_OWNER) && !is_founder(user, ci))
01485 rem_modes |= CUS_OWNER;
01486 if ((ircd->protect || ircd->admin) && (status & CUS_PROTECT)
01487 && !check_access(user, ci, CA_AUTOPROTECT)
01488 && !check_access(user, ci, CA_PROTECTME))
01489 rem_modes |= CUS_PROTECT;
01490 if ((status & CUS_OP) && !check_access(user, ci, CA_AUTOOP)
01491 && !check_access(user, ci, CA_OPDEOPME))
01492 rem_modes |= CUS_OP;
01493 if (ircd->halfop && (status & CUS_HALFOP)
01494 && !check_access(user, ci, CA_AUTOHALFOP)
01495 && !check_access(user, ci, CA_HALFOPME))
01496 rem_modes |= CUS_HALFOP;
01497 }
01498
01499
01500 if (!add_modes && !rem_modes)
01501 return;
01502
01503
01504
01505
01506 strcpy(modebuf, "");
01507 strcpy(userbuf, "");
01508 if (add_modes > 0) {
01509 strcat(modebuf, "+");
01510 if ((add_modes & CUS_OWNER) && !(status & CUS_OWNER)) {
01511 tmp = stripModePrefix(ircd->ownerset);
01512 strcat(modebuf, tmp);
01513 free(tmp);
01514 strcat(userbuf, " ");
01515 strcat(userbuf, GET_USER(user));
01516 } else {
01517 add_modes &= ~CUS_OWNER;
01518 }
01519 if ((add_modes & CUS_PROTECT) && !(status & CUS_PROTECT)) {
01520 tmp = stripModePrefix(ircd->adminset);
01521 strcat(modebuf, tmp);
01522 free(tmp);
01523 strcat(userbuf, " ");
01524 strcat(userbuf, GET_USER(user));
01525 } else {
01526 add_modes &= ~CUS_PROTECT;
01527 }
01528 if ((add_modes & CUS_OP) && !(status & CUS_OP)) {
01529 strcat(modebuf, "o");
01530 strcat(userbuf, " ");
01531 strcat(userbuf, GET_USER(user));
01532 rem_modes |= CUS_DEOPPED;
01533 } else {
01534 add_modes &= ~CUS_OP;
01535 }
01536 if ((add_modes & CUS_HALFOP) && !(status & CUS_HALFOP)) {
01537 strcat(modebuf, "h");
01538 strcat(userbuf, " ");
01539 strcat(userbuf, GET_USER(user));
01540
01541 rem_modes |= CUS_DEOPPED;
01542 } else {
01543 add_modes &= ~CUS_HALFOP;
01544 }
01545 if ((add_modes & CUS_VOICE) && !(status & CUS_VOICE)) {
01546 strcat(modebuf, "v");
01547 strcat(userbuf, " ");
01548 strcat(userbuf, GET_USER(user));
01549 } else {
01550 add_modes &= ~CUS_VOICE;
01551 }
01552 }
01553 if (rem_modes > 0) {
01554 strcat(modebuf, "-");
01555 if (rem_modes & CUS_OWNER) {
01556 tmp = stripModePrefix(ircd->ownerset);
01557 strcat(modebuf, tmp);
01558 free(tmp);
01559 strcat(userbuf, " ");
01560 strcat(userbuf, GET_USER(user));
01561 }
01562 if (rem_modes & CUS_PROTECT) {
01563 tmp = stripModePrefix(ircd->adminset);
01564 strcat(modebuf, tmp);
01565 free(tmp);
01566 strcat(userbuf, " ");
01567 strcat(userbuf, GET_USER(user));
01568 }
01569 if (rem_modes & CUS_OP) {
01570 strcat(modebuf, "o");
01571 strcat(userbuf, " ");
01572 strcat(userbuf, GET_USER(user));
01573
01574 if (!(add_modes & CUS_HALFOP) && !(status & CUS_HALFOP))
01575 add_modes |= CUS_DEOPPED;
01576 }
01577 if (rem_modes & CUS_HALFOP) {
01578 strcat(modebuf, "h");
01579 strcat(userbuf, " ");
01580 strcat(userbuf, GET_USER(user));
01581
01582 if (!(add_modes & CUS_OP) && !(status & CUS_OP))
01583 add_modes |= CUS_DEOPPED;
01584 }
01585 }
01586
01587
01588
01589
01590 if (!add_modes && !rem_modes)
01591 return;
01592
01593 anope_cmd_mode(whosends(ci), c->name, "%s%s", modebuf, userbuf);
01594 if (add_modes > 0)
01595 chan_set_user_status(c, user, add_modes);
01596 if (rem_modes > 0)
01597 chan_remove_user_status(c, user, rem_modes);
01598 }
01599
01600
01601
01602
01603
01604
01605
01606
01607 void chan_adduser2(User * user, Channel * c)
01608 {
01609 struct c_userlist *u;
01610
01611 u = scalloc(sizeof(struct c_userlist), 1);
01612 u->next = c->users;
01613 if (c->users)
01614 c->users->prev = u;
01615 c->users = u;
01616 u->user = user;
01617 c->usercount++;
01618
01619 if (get_ignore(user->nick) == NULL) {
01620 if (c->ci && (check_access(user, c->ci, CA_MEMO))
01621 && (c->ci->memos.memocount > 0)) {
01622 if (c->ci->memos.memocount == 1) {
01623 notice_lang(s_MemoServ, user, MEMO_X_ONE_NOTICE,
01624 c->ci->memos.memocount, c->ci->name);
01625 } else {
01626 notice_lang(s_MemoServ, user, MEMO_X_MANY_NOTICE,
01627 c->ci->memos.memocount, c->ci->name);
01628 }
01629 }
01630
01631
01632 if (c->ci && c->ci->entry_message && is_sync(user->server))
01633 notice_user(whosends(c->ci), user, "[%s] %s", c->name,
01634 c->ci->entry_message);
01635 }
01636
01643 if (s_BotServ && c->ci && c->ci->bi) {
01644 if (c->usercount == BSMinUsers)
01645 bot_join(c->ci);
01646 if (c->usercount >= BSMinUsers && (c->ci->botflags & BS_GREET)
01647 && user->na && user->na->nc->greet
01648 && check_access(user, c->ci, CA_GREET)) {
01649
01650
01651
01652
01653 if (is_sync(user->server)) {
01654 anope_cmd_privmsg(c->ci->bi->nick, c->name, "[%s] %s",
01655 user->na->nick, user->na->nc->greet);
01656 c->ci->bi->lastmsg = time(NULL);
01657 }
01658 }
01659 }
01660 }
01661
01662
01663
01664
01665
01666
01667
01668 Channel *chan_create(char *chan, time_t ts)
01669 {
01670 Channel *c;
01671 Channel **list;
01672
01673 if (debug)
01674 alog("debug: Creating channel %s", chan);
01675
01676 c = scalloc(sizeof(Channel), 1);
01677 strscpy(c->name, chan, sizeof(c->name));
01678 list = &chanlist[HASH(c->name)];
01679 c->next = *list;
01680 if (*list)
01681 (*list)->prev = c;
01682 *list = c;
01683 c->creation_time = ts;
01684
01685 c->ci = cs_findchan(chan);
01686 if (c->ci)
01687 c->ci->c = c;
01688
01689 if (c->ci) {
01690 check_modes(c);
01691 stick_all(c->ci);
01692 }
01693
01694 if (serv_uplink && is_sync(serv_uplink) && (!(c->topic_sync))) {
01695 restore_topic(chan);
01696 }
01697
01698 return c;
01699 }
01700
01701
01702
01703
01704
01705 void chan_delete(Channel * c)
01706 {
01707 BanData *bd, *next;
01708
01709 if (debug)
01710 alog("debug: Deleting channel %s", c->name);
01711
01712 for (bd = c->bd; bd; bd = next) {
01713 if (bd->mask)
01714 free(bd->mask);
01715 next = bd->next;
01716 free(bd);
01717 }
01718
01719 if (c->ci)
01720 c->ci->c = NULL;
01721
01722 if (c->topic)
01723 free(c->topic);
01724
01725 if (c->key)
01726 free(c->key);
01727 if (ircd->fmode) {
01728 if (c->flood)
01729 free(c->flood);
01730 }
01731 if (ircd->Lmode) {
01732 if (c->redirect)
01733 free(c->redirect);
01734 }
01735 if (ircd->jmode) {
01736 if (c->throttle)
01737 free (c->throttle);
01738 }
01739
01740 if (c->bans && c->bans->count) {
01741 while (c->bans->entries) {
01742 entry_delete(c->bans, c->bans->entries);
01743 }
01744 }
01745
01746 if (ircd->except) {
01747 if (c->excepts && c->excepts->count) {
01748 while (c->excepts->entries) {
01749 entry_delete(c->excepts, c->excepts->entries);
01750 }
01751 }
01752 }
01753
01754 if (ircd->invitemode) {
01755 if (c->invites && c->invites->count) {
01756 while (c->invites->entries) {
01757 entry_delete(c->invites, c->invites->entries);
01758 }
01759 }
01760 }
01761
01762 if (c->next)
01763 c->next->prev = c->prev;
01764 if (c->prev)
01765 c->prev->next = c->next;
01766 else
01767 chanlist[HASH(c->name)] = c->next;
01768
01769 free(c);
01770 }
01771
01772
01773
01774 void del_ban(Channel * chan, char *mask)
01775 {
01776 AutoKick *akick;
01777 Entry *ban;
01778
01779
01780 if (!mask || !chan->bans || (chan->bans->count == 0))
01781 return;
01782
01783 ban = elist_find_mask(chan->bans, mask);
01784
01785 if (ban) {
01786 entry_delete(chan->bans, ban);
01787
01788 if (debug)
01789 alog("debug: Deleted ban %s from channel %s", mask,
01790 chan->name);
01791 }
01792
01793 if (chan->ci && (akick = is_stuck(chan->ci, mask)))
01794 stick_mask(chan->ci, akick);
01795 }
01796
01797
01798
01799 void del_exception(Channel * chan, char *mask)
01800 {
01801 Entry *exception;
01802
01803
01804 if (!mask || !chan->excepts || (chan->excepts->count == 0))
01805 return;
01806
01807 exception = elist_find_mask(chan->excepts, mask);
01808
01809 if (exception) {
01810 entry_delete(chan->excepts, exception);
01811
01812 if (debug)
01813 alog("debug: Deleted except %s to channel %s", mask,
01814 chan->name);
01815 }
01816 }
01817
01818
01819
01820 void del_invite(Channel * chan, char *mask)
01821 {
01822 Entry *invite;
01823
01824
01825 if (!mask || !chan->invites || (chan->invites->count == 0)) {
01826 return;
01827 }
01828
01829 invite = elist_find_mask(chan->invites, mask);
01830
01831 if (invite) {
01832 entry_delete(chan->invites, invite);
01833
01834 if (debug)
01835 alog("debug: Deleted invite %s to channel %s", mask,
01836 chan->name);
01837 }
01838 }
01839
01840
01841
01842
01843 char *get_flood(Channel * chan)
01844 {
01845 return chan->flood;
01846 }
01847
01848
01849
01850 char *get_throttle(Channel * chan)
01851 {
01852 return chan->throttle;
01853 }
01854
01855
01856
01857 char *get_key(Channel * chan)
01858 {
01859 return chan->key;
01860 }
01861
01862
01863
01864 char *get_limit(Channel * chan)
01865 {
01866 static char limit[16];
01867
01868 if (chan->limit == 0)
01869 return NULL;
01870
01871 snprintf(limit, sizeof(limit), "%lu", (unsigned long int) chan->limit);
01872 return limit;
01873 }
01874
01875
01876
01877 char *get_redirect(Channel * chan)
01878 {
01879 return chan->redirect;
01880 }
01881
01882
01883
01884
01885
01886 char *get_unkwn(Channel * chan)
01887 {
01888 return NULL;
01889 }
01890
01891
01892
01893 Channel *join_user_update(User * user, Channel * chan, char *name,
01894 time_t chants)
01895 {
01896 struct u_chanlist *c;
01897
01898
01899 if (!chan)
01900 chan = chan_create(name, chants);
01901 else
01902 {
01903
01904 if (chan->creation_time > chants && chants != 0)
01905 {
01906 struct c_userlist *cu;
01907 char *modes[6];
01908
01909 chan->creation_time = chants;
01910 for (cu = chan->users; cu; cu = cu->next)
01911 {
01912
01913 modes[0] = "-ov";
01914 modes[1] = cu->user->nick;
01915 modes[2] = cu->user->nick;
01916 chan_set_modes(s_OperServ, chan, 3, modes, 2);
01917 }
01918 if (chan->ci)
01919 {
01920 if (chan->ci->bi)
01921 {
01922
01923 anope_cmd_part(chan->ci->bi->nick, chan->name, "TS reop");
01924 bot_join(chan->ci);
01925 }
01926
01927 if (ircd->chanreg && ircd->regmode)
01928 {
01929 chan->mode |= ircd->regmode;
01930 anope_cmd_mode(whosends(chan->ci), chan->name, "+r");
01931 }
01932 }
01933
01934 }
01935
01936 }
01937
01938 if (debug)
01939 alog("debug: %s joins %s", user->nick, chan->name);
01940
01941 c = scalloc(sizeof(*c), 1);
01942 c->next = user->chans;
01943 if (user->chans)
01944 user->chans->prev = c;
01945 user->chans = c;
01946 c->chan = chan;
01947
01948 chan_adduser2(user, chan);
01949
01950 return chan;
01951 }
01952
01953
01954
01955 void set_flood(Channel * chan, char *value)
01956 {
01957 if (chan->flood)
01958 free(chan->flood);
01959 chan->flood = value ? sstrdup(value) : NULL;
01960
01961 if (debug)
01962 alog("debug: Flood mode for channel %s set to %s", chan->name,
01963 chan->flood ? chan->flood : "no flood settings");
01964 }
01965
01966
01967
01968 void chan_set_throttle(Channel * chan, char *value)
01969 {
01970 if (chan->throttle)
01971 free(chan->throttle);
01972 chan->throttle = value ? sstrdup(value) : NULL;
01973
01974 if (debug)
01975 alog("debug: Throttle mode for channel %s set to %s", chan->name,
01976 chan->throttle ? chan->throttle : "none");
01977 }
01978
01979
01980
01981 void chan_set_key(Channel * chan, char *value)
01982 {
01983 if (chan->key)
01984 free(chan->key);
01985 chan->key = value ? sstrdup(value) : NULL;
01986
01987 if (debug)
01988 alog("debug: Key of channel %s set to %s", chan->name,
01989 chan->key ? chan->key : "no key");
01990 }
01991
01992
01993
01994 void set_limit(Channel * chan, char *value)
01995 {
01996 chan->limit = value ? strtoul(value, NULL, 10) : 0;
01997
01998 if (debug)
01999 alog("debug: Limit of channel %s set to %u", chan->name,
02000 chan->limit);
02001 }
02002
02003
02004
02005 void set_redirect(Channel * chan, char *value)
02006 {
02007 if (chan->redirect)
02008 free(chan->redirect);
02009 chan->redirect = value ? sstrdup(value) : NULL;
02010
02011 if (debug)
02012 alog("debug: Redirect of channel %s set to %s", chan->name,
02013 chan->redirect ? chan->redirect : "no redirect");
02014 }
02015
02016
02017
02018
02019
02020 void set_unkwn(Channel *chan, char *value)
02021 {
02022
02023 }
02024
02025
02026
02027 void do_mass_mode(char *modes)
02028 {
02029 int ac;
02030 char **av;
02031 Channel *c;
02032 char *myModes;
02033
02034 if (!modes) {
02035 return;
02036 }
02037
02038
02039 myModes = sstrdup(modes);
02040 ac = split_buf(myModes, &av, 1);
02041
02042 for (c = firstchan(); c; c = nextchan()) {
02043 if (c->bouncy_modes) {
02044 free(av);
02045 free(myModes);
02046 return;
02047 } else {
02048 anope_cmd_mode(s_OperServ, c->name, "%s", modes);
02049 chan_set_modes(s_OperServ, c, ac, av, 1);
02050 }
02051 }
02052 free(av);
02053 free(myModes);
02054 }
02055
02056
02057
02058 void restore_unsynced_topics(void)
02059 {
02060 Channel *c;
02061
02062 for (c = firstchan(); c; c = nextchan()) {
02063 if (!(c->topic_sync))
02064 restore_topic(c->name);
02065 }
02066 }
02067
02068
02069
02076 Entry *entry_create(char *mask)
02077 {
02078 Entry *entry;
02079 char *nick = NULL, *user, *host, *cidrhost;
02080 uint32 ip, cidr;
02081
02082 entry = scalloc(1, sizeof(Entry));
02083 entry->type = ENTRYTYPE_NONE;
02084 entry->prev = NULL;
02085 entry->next = NULL;
02086 entry->nick = NULL;
02087 entry->user = NULL;
02088 entry->host = NULL;
02089 entry->mask = sstrdup(mask);
02090
02091 host = strchr(mask, '@');
02092 if (host) {
02093 *host++ = '\0';
02094
02095 if (str_is_pure_wildcard(mask))
02096 user = NULL;
02097 else {
02098
02099
02100 user = strchr(mask, '!');
02101 if (user) {
02102 *user++ = '\0';
02103
02104 if (str_is_pure_wildcard(mask))
02105 nick = NULL;
02106 else
02107 nick = mask;
02108 } else {
02109 nick = NULL;
02110 user = mask;
02111 }
02112 }
02113 } else {
02114
02115
02116
02117 user = NULL;
02118 host = mask;
02119 }
02120
02121 if (nick) {
02122 entry->nick = sstrdup(nick);
02123
02124 if (str_is_wildcard(nick))
02125 entry->type |= ENTRYTYPE_NICK_WILD;
02126 else
02127 entry->type |= ENTRYTYPE_NICK;
02128 }
02129
02130 if (user) {
02131 entry->user = sstrdup(user);
02132
02133 if (str_is_wildcard(user))
02134 entry->type |= ENTRYTYPE_USER_WILD;
02135 else
02136 entry->type |= ENTRYTYPE_USER;
02137 }
02138
02139
02140 if (*host && !str_is_pure_wildcard(host)) {
02141 if (ircd->cidrchanbei && str_is_cidr(host, &ip, &cidr, &cidrhost)) {
02142 entry->cidr_ip = ip;
02143 entry->cidr_mask = cidr;
02144 entry->type |= ENTRYTYPE_CIDR4;
02145 host = cidrhost;
02146 } else if (ircd->cidrchanbei && strchr(host, '/')) {
02147
02148
02149
02150
02151
02152
02153
02154
02155 entry->type = ENTRYTYPE_NONE;
02156 } else {
02157 entry->host = sstrdup(host);
02158 if (str_is_wildcard(host))
02159 entry->type |= ENTRYTYPE_HOST_WILD;
02160 else
02161 entry->type |= ENTRYTYPE_HOST;
02162 }
02163 }
02164 free(mask);
02165
02166 return entry;
02167 }
02168
02169
02176 Entry *entry_add(EList * list, char *mask)
02177 {
02178 Entry *e;
02179 char *hostmask;
02180
02181 hostmask = sstrdup(mask);
02182 e = entry_create(hostmask);
02183
02184 if (!e)
02185 return NULL;
02186
02187 e->next = list->entries;
02188 e->prev = NULL;
02189
02190 if (list->entries)
02191 list->entries->prev = e;
02192 list->entries = e;
02193 list->count++;
02194
02195 return e;
02196 }
02197
02198
02204 void entry_delete(EList * list, Entry * e)
02205 {
02206 if (!list || !e)
02207 return;
02208
02209 if (e->next)
02210 e->next->prev = e->prev;
02211 if (e->prev)
02212 e->prev->next = e->next;
02213
02214 if (list->entries == e)
02215 list->entries = e->next;
02216
02217 if (e->nick)
02218 free(e->nick);
02219 if (e->user)
02220 free(e->user);
02221 if (e->host)
02222 free(e->host);
02223 free(e->mask);
02224 free(e);
02225
02226 list->count--;
02227 }
02228
02229
02234 EList *list_create()
02235 {
02236 EList *list;
02237
02238 list = scalloc(1, sizeof(EList));
02239 list->entries = NULL;
02240 list->count = 0;
02241
02242 return list;
02243 }
02244
02245
02255 int entry_match(Entry * e, char *nick, char *user, char *host, uint32 ip)
02256 {
02257
02258 if (!e || e->type == ENTRYTYPE_NONE)
02259 return 0;
02260
02261 if (ircd->cidrchanbei && (e->type & ENTRYTYPE_CIDR4) &&
02262 (!ip || (ip && ((ip & e->cidr_mask) != e->cidr_ip))))
02263 return 0;
02264 if ((e->type & ENTRYTYPE_NICK)
02265 && (!nick || stricmp(e->nick, nick) != 0))
02266 return 0;
02267 if ((e->type & ENTRYTYPE_USER)
02268 && (!user || stricmp(e->user, user) != 0))
02269 return 0;
02270 if ((e->type & ENTRYTYPE_HOST)
02271 && (!host || stricmp(e->host, host) != 0))
02272 return 0;
02273 if ((e->type & ENTRYTYPE_NICK_WILD)
02274 && !match_wild_nocase(e->nick, nick))
02275 return 0;
02276 if ((e->type & ENTRYTYPE_USER_WILD)
02277 && !match_wild_nocase(e->user, user))
02278 return 0;
02279 if ((e->type & ENTRYTYPE_HOST_WILD)
02280 && !match_wild_nocase(e->host, host))
02281 return 0;
02282
02283 return 1;
02284 }
02285
02293 int entry_match_mask(Entry * e, char *mask, uint32 ip)
02294 {
02295 char *hostmask, *nick, *user, *host;
02296 int res;
02297
02298 hostmask = sstrdup(mask);
02299
02300 host = strchr(hostmask, '@');
02301 if (host) {
02302 *host++ = '\0';
02303 user = strchr(hostmask, '!');
02304 if (user) {
02305 *user++ = '\0';
02306 nick = hostmask;
02307 } else {
02308 nick = NULL;
02309 user = hostmask;
02310 }
02311 } else {
02312 nick = NULL;
02313 user = NULL;
02314 host = hostmask;
02315 }
02316
02317 res = entry_match(e, nick, user, host, ip);
02318
02319
02320 free(hostmask);
02321
02322 return res;
02323 }
02324
02334 Entry *elist_match(EList * list, char *nick, char *user, char *host,
02335 uint32 ip)
02336 {
02337 Entry *e;
02338
02339 if (!list || !list->entries)
02340 return NULL;
02341
02342 for (e = list->entries; e; e = e->next) {
02343 if (entry_match(e, nick, user, host, ip))
02344 return e;
02345 }
02346
02347
02348 return NULL;
02349 }
02350
02358 Entry *elist_match_mask(EList * list, char *mask, uint32 ip)
02359 {
02360 char *hostmask, *nick, *user, *host;
02361 Entry *res;
02362
02363 if (!list || !list->entries || !mask)
02364 return NULL;
02365
02366 hostmask = sstrdup(mask);
02367
02368 host = strchr(hostmask, '@');
02369 if (host) {
02370 *host++ = '\0';
02371 user = strchr(hostmask, '!');
02372 if (user) {
02373 *user++ = '\0';
02374 nick = hostmask;
02375 } else {
02376 nick = NULL;
02377 user = hostmask;
02378 }
02379 } else {
02380 nick = NULL;
02381 user = NULL;
02382 host = hostmask;
02383 }
02384
02385 res = elist_match(list, nick, user, host, ip);
02386
02387
02388 free(hostmask);
02389
02390 return res;
02391 }
02392
02400 static Entry *_elist_match_user(EList * list, User * u, boolean full)
02401 {
02402 Entry *res = NULL;
02403 char *host;
02404 uint32 ip = 0;
02405
02406 if (!list || !list->entries || !u)
02407 return NULL;
02408
02409 if (u->hostip == NULL) {
02410 host = host_resolve(u->host);
02411
02412
02413 if (host) {
02414 u->hostip = sstrdup(host);
02415 }
02416 } else {
02417 host = sstrdup(u->hostip);
02418 }
02419
02420
02421 if (host)
02422 ip = str_is_ip(host);
02423
02424
02425 if (full)
02426 res = elist_match(list, u->nick, u->username, u->host, ip);
02427 if (!res)
02428 res = elist_match(list, u->nick, u->vident, u->vhost, 0);
02429 if (!res)
02430 res = elist_match(list, u->nick, u->username, u->chost, 0);
02431
02432 if (host)
02433 free(host);
02434
02435 return res;
02436 }
02437
02438 Entry *elist_match_user(EList *list, User *u)
02439 {
02440 return _elist_match_user(list, u, false);
02441 }
02442
02443 Entry *elist_match_user_full(EList *list, User *u, boolean full)
02444 {
02445 return _elist_match_user(list, u, full);
02446 }
02447
02454 Entry *elist_find_mask(EList * list, char *mask)
02455 {
02456 Entry *e;
02457
02458 if (!list || !list->entries || !mask)
02459 return NULL;
02460
02461 for (e = list->entries; e; e = e->next) {
02462 if (!stricmp(e->mask, mask))
02463 return e;
02464 }
02465
02466 return NULL;
02467 }
02468
02474 long get_memuse(EList * list)
02475 {
02476 Entry *e;
02477 long mem = 0;
02478
02479 if (!list)
02480 return 0;
02481
02482 mem += sizeof(EList *);
02483 mem += sizeof(Entry *) * list->count;
02484 if (list->entries) {
02485 for (e = list->entries; e; e = e->next) {
02486 if (e->nick)
02487 mem += strlen(e->nick) + 1;
02488 if (e->user)
02489 mem += strlen(e->user) + 1;
02490 if (e->host)
02491 mem += strlen(e->host) + 1;
02492 if (e->mask)
02493 mem += strlen(e->mask) + 1;
02494 }
02495 }
02496
02497 return mem;
02498 }
02499
02500