00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "services.h"
00016 #include "language.h"
00017
00018 Channel *chanlist[1024];
00019
00020 #define HASH(chan) ((chan)[1] ? ((chan)[1]&31)<<5 | ((chan)[2]&31) : 0)
00021
00022
00023
00024
00025 void chan_deluser(User * user, Channel * c)
00026 {
00027 struct c_userlist *u;
00028
00029 if (c->ci)
00030 update_cs_lastseen(user, c->ci);
00031
00032 for (u = c->users; u && u->user != user; u = u->next);
00033 if (!u)
00034 return;
00035
00036 if (u->ud) {
00037 if (u->ud->lastline)
00038 free(u->ud->lastline);
00039 free(u->ud);
00040 }
00041
00042 if (u->next)
00043 u->next->prev = u->prev;
00044 if (u->prev)
00045 u->prev->next = u->next;
00046 else
00047 c->users = u->next;
00048 free(u);
00049 c->usercount--;
00050
00051 if (s_BotServ && c->ci && c->ci->bi && c->usercount == BSMinUsers - 1) {
00052 anope_cmd_part(c->ci->bi->nick, c->name, NULL);
00053 }
00054
00055 if (!c->users)
00056 chan_delete(c);
00057 }
00058
00059
00060
00061
00062
00063
00064
00065 char *chan_get_modes(Channel * chan, int complete, int plus)
00066 {
00067 static char res[BUFSIZE];
00068 char *end = res;
00069
00070 if (chan->mode) {
00071 int n = 0;
00072 CBModeInfo *cbmi = cbmodeinfos;
00073
00074 do {
00075 if (chan->mode & cbmi->flag)
00076 *end++ = cbmi->mode;
00077 } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1);
00078
00079 if (complete) {
00080 cbmi = cbmodeinfos;
00081
00082 do {
00083 if (cbmi->getvalue && (chan->mode & cbmi->flag) &&
00084 (plus || !(cbmi->flags & CBM_MINUS_NO_ARG))) {
00085 char *value = cbmi->getvalue(chan);
00086
00087 if (value) {
00088 *end++ = ' ';
00089 while (*value)
00090 *end++ = *value++;
00091 }
00092 }
00093 } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1);
00094 }
00095 }
00096
00097 *end = 0;
00098
00099 return res;
00100 }
00101
00102
00103
00104
00105
00106 int chan_get_user_status(Channel * chan, User * user)
00107 {
00108 struct u_chanlist *uc;
00109
00110 for (uc = user->chans; uc; uc = uc->next)
00111 if (uc->chan == chan)
00112 return uc->status;
00113
00114 return 0;
00115 }
00116
00117
00118
00119
00120
00121 int chan_has_user_status(Channel * chan, User * user, int16 status)
00122 {
00123 struct u_chanlist *uc;
00124
00125 for (uc = user->chans; uc; uc = uc->next) {
00126 if (uc->chan == chan) {
00127 if (debug) {
00128 alog("debug: chan_has_user_status wanted %d the user is %d", status, uc->status);
00129 }
00130 return (uc->status & status);
00131 }
00132 }
00133 return 0;
00134 }
00135
00136
00137
00138
00139
00140 void chan_remove_user_status(Channel * chan, User * user, int16 status)
00141 {
00142 struct u_chanlist *uc;
00143
00144 if (debug >= 2)
00145 alog("debug: removing user status (%d) from %s for %s", status,
00146 user->nick, chan->name);
00147
00148 for (uc = user->chans; uc; uc = uc->next) {
00149 if (uc->chan == chan) {
00150 uc->status &= ~status;
00151 break;
00152 }
00153 }
00154 }
00155
00156
00157
00158 void chan_set_modes(const char *source, Channel * chan, int ac, char **av,
00159 int check)
00160 {
00161 int add = 1;
00162 char *modes = av[0], mode;
00163 CBMode *cbm;
00164 CMMode *cmm;
00165 CUMode *cum;
00166 unsigned char botmode = 0;
00167 BotInfo *bi;
00168 User *u, *user;
00169 int i, real_ac = ac;
00170 char **real_av = av;
00171
00172 if (debug)
00173 alog("debug: Changing modes for %s to %s", chan->name,
00174 merge_args(ac, av));
00175
00176 u = finduser(source);
00177 if (u && (chan_get_user_status(chan, u) & CUS_DEOPPED)) {
00178 char *s;
00179
00180 if (debug)
00181 alog("debug: Removing instead of setting due to DEOPPED flag");
00182
00183
00184 for (s = av[0]; *s; s++) {
00185 if (*s == '+')
00186 *s = '-';
00187 else if (*s == '-')
00188 *s = '+';
00189 }
00190
00191
00192 anope_cmd_mode(whosends(chan->ci), chan->name, merge_args(ac, av));
00193
00194 return;
00195 }
00196
00197 ac--;
00198
00199 while ((mode = *modes++)) {
00200
00201 switch (mode) {
00202 case '+':
00203 add = 1;
00204 continue;
00205 case '-':
00206 add = 0;
00207 continue;
00208 }
00209
00210 if (((int) mode) < 0) {
00211 if (debug)
00212 alog("Debug: Malformed mode detected on %s.", chan->name);
00213 continue;
00214 }
00215
00216 if ((cum = &cumodes[(int) mode])->status != 0) {
00217 if (ac == 0) {
00218 alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
00219 continue;
00220 }
00221 ac--;
00222 av++;
00223
00224 if ((cum->flags & CUF_PROTECT_BOTSERV) && !add) {
00225 if ((bi = findbot(*av))) {
00226 if (!botmode || botmode != mode) {
00227 anope_cmd_mode(bi->nick, chan->name, "+%c %s",
00228 mode, bi->nick);
00229 botmode = mode;
00230 continue;
00231 } else {
00232 botmode = mode;
00233 continue;
00234 }
00235 }
00236 } else {
00237 if ((bi = findbot(*av))) {
00238 continue;
00239 }
00240 }
00241
00242 if (!(user = finduser(*av))
00243 && !(UseTS6 && ircd->ts6 && (user = find_byuid(*av)))) {
00244 if (debug) {
00245 alog("debug: MODE %s %c%c for nonexistent user %s",
00246 chan->name, (add ? '+' : '-'), mode, *av);
00247 }
00248 continue;
00249 }
00250
00251 if (debug)
00252 alog("debug: Setting %c%c on %s for %s", (add ? '+' : '-'),
00253 mode, chan->name, user->nick);
00254
00255 if (add) {
00256 chan_set_user_status(chan, user, cum->status);
00257
00258 if (cum->status & CUS_OP)
00259 chan_remove_user_status(chan, user, CUS_DEOPPED);
00260 } else {
00261 chan_remove_user_status(chan, user, cum->status);
00262 }
00263
00264 } else if ((cbm = &cbmodes[(int) mode])->flag != 0) {
00265 if (check >= 0) {
00266 if (add)
00267 chan->mode |= cbm->flag;
00268 else
00269 chan->mode &= ~cbm->flag;
00270 }
00271
00272 if (cbm->setvalue) {
00273 if (add || !(cbm->flags & CBM_MINUS_NO_ARG)) {
00274 if (ac == 0) {
00275 alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
00276 continue;
00277 }
00278 ac--;
00279 av++;
00280 }
00281 cbm->setvalue(chan, add ? *av : NULL);
00282 }
00283
00284 if (check < 0) {
00285 if (add)
00286 chan->mode |= cbm->flag;
00287 else
00288 chan->mode &= ~cbm->flag;
00289 }
00290 } else if ((cmm = &cmmodes[(int) mode])->addmask) {
00291 if (ac == 0) {
00292 alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
00293 continue;
00294 }
00295
00296 ac--;
00297 av++;
00298 if (add)
00299 cmm->addmask(chan, *av);
00300 else
00301 cmm->delmask(chan, *av);
00302 }
00303 }
00304
00305 if (check > 0) {
00306 check_modes(chan);
00307
00308 if (check < 2) {
00309
00310
00311
00312 real_ac--;
00313 real_av++;
00314 for (i = 0; i < real_ac; i++) {
00315 if ((user = finduser(*real_av)) && is_on_chan(chan, user))
00316 chan_set_correct_modes(user, chan, 0);
00317 real_av++;
00318 }
00319 }
00320 }
00321 }
00322
00323
00324
00325
00326
00327 void chan_set_user_status(Channel * chan, User * user, int16 status)
00328 {
00329 struct u_chanlist *uc;
00330
00331 if (debug >= 2)
00332 alog("debug: setting user status (%d) on %s for %s", status,
00333 user->nick, chan->name);
00334
00335 if (HelpChannel && ircd->supporthelper && (status & CUS_OP)
00336 && (stricmp(chan->name, HelpChannel) == 0)
00337 && (!chan->ci || check_access(user, chan->ci, CA_AUTOOP))) {
00338 if (debug) {
00339 alog("debug: %s being given +h for having %d status in %s",
00340 user->nick, status, chan->name);
00341 }
00342 common_svsmode(user, "+h", NULL);
00343 }
00344
00345 for (uc = user->chans; uc; uc = uc->next) {
00346 if (uc->chan == chan) {
00347 uc->status |= status;
00348 break;
00349 }
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 Channel *findchan(const char *chan)
00360 {
00361 Channel *c;
00362
00363 if (!chan || !*chan) {
00364 if (debug) {
00365 alog("debug: findchan() called with NULL values");
00366 }
00367 return NULL;
00368 }
00369
00370 if (debug >= 3)
00371 alog("debug: findchan(%p)", chan);
00372 c = chanlist[HASH(chan)];
00373 while (c) {
00374 if (stricmp(c->name, chan) == 0)
00375 return c;
00376 c = c->next;
00377 }
00378 if (debug >= 3)
00379 alog("debug: findchan(%s) -> %p", chan, (void *) c);
00380 return NULL;
00381 }
00382
00383
00384
00385
00386
00387
00388
00389 static Channel *current;
00390 static int next_index;
00391
00392 Channel *firstchan(void)
00393 {
00394 next_index = 0;
00395 while (next_index < 1024 && current == NULL)
00396 current = chanlist[next_index++];
00397 if (debug >= 3)
00398 alog("debug: firstchan() returning %s",
00399 current ? current->name : "NULL (end of list)");
00400 return current;
00401 }
00402
00403 Channel *nextchan(void)
00404 {
00405 if (current)
00406 current = current->next;
00407 if (!current && next_index < 1024) {
00408 while (next_index < 1024 && current == NULL)
00409 current = chanlist[next_index++];
00410 }
00411 if (debug >= 3)
00412 alog("debug: nextchan() returning %s",
00413 current ? current->name : "NULL (end of list)");
00414 return current;
00415 }
00416
00417
00418
00419
00420
00421 void get_channel_stats(long *nrec, long *memuse)
00422 {
00423 long count = 0, mem = 0;
00424 Channel *chan;
00425 struct c_userlist *cu;
00426 BanData *bd;
00427 int i, j;
00428
00429 for (i = 0; i < 1024; i++) {
00430 for (chan = chanlist[i]; chan; chan = chan->next) {
00431 count++;
00432 mem += sizeof(*chan);
00433 if (chan->topic)
00434 mem += strlen(chan->topic) + 1;
00435 if (chan->key)
00436 mem += strlen(chan->key) + 1;
00437 if (ircd->fmode) {
00438 if (chan->flood)
00439 mem += strlen(chan->flood) + 1;
00440 }
00441 if (ircd->Lmode) {
00442 if (chan->redirect)
00443 mem += strlen(chan->redirect) + 1;
00444 }
00445 mem += sizeof(char *) * chan->bansize;
00446 for (j = 0; j < chan->bancount; j++) {
00447 if (chan->bans[j])
00448 mem += strlen(chan->bans[j]) + 1;
00449 }
00450 if (ircd->except) {
00451 mem += sizeof(char *) * chan->exceptsize;
00452 for (j = 0; j < chan->exceptcount; j++) {
00453 if (chan->excepts[j])
00454 mem += strlen(chan->excepts[j]) + 1;
00455 }
00456 }
00457 if (ircd->invitemode) {
00458 mem += sizeof(char *) * chan->invitesize;
00459 for (j = 0; j < chan->invitecount; j++) {
00460 if (chan->invite[j])
00461 mem += strlen(chan->invite[j]) + 1;
00462 }
00463 }
00464 for (cu = chan->users; cu; cu = cu->next) {
00465 mem += sizeof(*cu);
00466 if (cu->ud) {
00467 mem += sizeof(*cu->ud);
00468 if (cu->ud->lastline)
00469 mem += strlen(cu->ud->lastline) + 1;
00470 }
00471 }
00472 for (bd = chan->bd; bd; bd = bd->next) {
00473 if (bd->mask)
00474 mem += strlen(bd->mask) + 1;
00475 mem += sizeof(*bd);
00476 }
00477 }
00478 }
00479 *nrec = count;
00480 *memuse = mem;
00481 }
00482
00483
00484
00485
00486
00487 int is_on_chan(Channel * c, User * u)
00488 {
00489 struct u_chanlist *uc;
00490
00491 for (uc = u->chans; uc; uc = uc->next)
00492 if (uc->chan == c)
00493 return 1;
00494
00495 return 0;
00496 }
00497
00498
00499
00500
00501
00502
00503 User *nc_on_chan(Channel * c, NickCore * nc)
00504 {
00505 struct c_userlist *u;
00506
00507 if (!c || !nc)
00508 return NULL;
00509
00510 for (u = c->users; u; u = u->next) {
00511 if (u->user->na && u->user->na->nc == nc
00512 && nick_recognized(u->user))
00513 return u->user;
00514 }
00515 return NULL;
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 void do_join(const char *source, int ac, char **av)
00527 {
00528 User *user;
00529 Channel *chan;
00530 char *s, *t;
00531 struct u_chanlist *c, *nextc;
00532 char *channame;
00533
00534 if (UseTS6 && ircd->ts6) {
00535 user = find_byuid(source);
00536 if (!user)
00537 user = finduser(source);
00538 } else {
00539 user = finduser(source);
00540 }
00541 if (!user) {
00542 if (debug) {
00543 alog("debug: JOIN from nonexistent user %s: %s", source,
00544 merge_args(ac, av));
00545 }
00546 return;
00547 }
00548
00549 t = av[0];
00550 while (*(s = t)) {
00551 t = s + strcspn(s, ",");
00552 if (*t)
00553 *t++ = 0;
00554
00555 if (*s == '0') {
00556 c = user->chans;
00557 while (c) {
00558 nextc = c->next;
00559 channame = sstrdup(c->chan->name);
00560 send_event(EVENT_PART_CHANNEL, 3, EVENT_START, user->nick,
00561 channame);
00562 chan_deluser(user, c->chan);
00563 send_event(EVENT_PART_CHANNEL, 3, EVENT_STOP, user->nick,
00564 channame);
00565 free(channame);
00566 free(c);
00567 c = nextc;
00568 }
00569 user->chans = NULL;
00570 continue;
00571 }
00572
00573
00574 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START, source, s);
00575
00576
00577
00578
00579
00580 if (check_kick(user, s, time(NULL)))
00581 continue;
00582
00583 chan = findchan(s);
00584 chan = join_user_update(user, chan, s, time(NULL));
00585 chan_set_correct_modes(user, chan, 1);
00586
00587 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP, source, s);
00588 }
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 void do_kick(const char *source, int ac, char **av)
00600 {
00601 BotInfo *bi;
00602 ChannelInfo *ci;
00603 User *user;
00604 char *s, *t;
00605 struct u_chanlist *c;
00606
00607 t = av[1];
00608 while (*(s = t)) {
00609 t = s + strcspn(s, ",");
00610 if (*t)
00611 *t++ = 0;
00612
00613
00614
00615
00616
00617 if (s_BotServ && (bi = findbot(s)) && (ci = cs_findchan(av[0]))) {
00618 bot_join(ci);
00619 continue;
00620 }
00621
00622 if (UseTS6 && ircd->ts6) {
00623 user = find_byuid(s);
00624 if (!user) {
00625 user = finduser(s);
00626 }
00627 } else {
00628 user = finduser(s);
00629 }
00630 if (!user) {
00631 if (debug) {
00632 alog("debug: KICK for nonexistent user %s on %s: %s", s,
00633 av[0], merge_args(ac - 2, av + 2));
00634 }
00635 continue;
00636 }
00637 if (debug) {
00638 alog("debug: kicking %s from %s", user->nick, av[0]);
00639 }
00640 for (c = user->chans; c && stricmp(av[0], c->chan->name) != 0;
00641 c = c->next);
00642 if (c) {
00643 send_event(EVENT_CHAN_KICK, 2, user->nick, av[0]);
00644 chan_deluser(user, c->chan);
00645 if (c->next)
00646 c->next->prev = c->prev;
00647 if (c->prev)
00648 c->prev->next = c->next;
00649 else
00650 user->chans = c->next;
00651 free(c);
00652 }
00653 }
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663 void do_part(const char *source, int ac, char **av)
00664 {
00665 User *user;
00666 char *s, *t;
00667 struct u_chanlist *c;
00668 char *channame;
00669
00670 if (UseTS6 && ircd->ts6) {
00671 user = find_byuid(source);
00672 if (!user)
00673 user = finduser(source);
00674 } else {
00675 user = finduser(source);
00676 }
00677 if (!user) {
00678 if (debug) {
00679 alog("debug: PART from nonexistent user %s: %s", source,
00680 merge_args(ac, av));
00681 }
00682 return;
00683 }
00684 t = av[0];
00685 while (*(s = t)) {
00686 t = s + strcspn(s, ",");
00687 if (*t)
00688 *t++ = 0;
00689 if (debug)
00690 alog("debug: %s leaves %s", source, s);
00691 for (c = user->chans; c && stricmp(s, c->chan->name) != 0;
00692 c = c->next);
00693 if (c) {
00694 if (!c->chan) {
00695 alog("user: BUG parting %s: channel entry found but c->chan NULL", s);
00696 return;
00697 }
00698 channame = sstrdup(c->chan->name);
00699 send_event(EVENT_PART_CHANNEL, (ac >= 2 ? 4 : 3), EVENT_START,
00700 user->nick,
00701 channame, (ac >= 2 ? av[1] : ""));
00702
00703 chan_deluser(user, c->chan);
00704 if (c->next)
00705 c->next->prev = c->prev;
00706 if (c->prev)
00707 c->prev->next = c->next;
00708 else
00709 user->chans = c->next;
00710 free(c);
00711
00712 send_event(EVENT_PART_CHANNEL, (ac >= 2 ? 4 : 3), EVENT_STOP,
00713 user->nick,
00714 channame, (ac >= 2 ? av[1] : ""));
00715 free(channame);
00716 }
00717 }
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 void do_sjoin(const char *source, int ac, char **av)
00759 {
00760 Channel *c;
00761 User *user;
00762 Server *serv;
00763 struct c_userlist *cu;
00764 char *s = NULL;
00765 char *end, cubuf[7], *end2, *cumodes[6];
00766 int is_sqlined = 0;
00767 int ts = 0;
00768 int is_created = 0;
00769 int keep_their_modes = 1;
00770
00771 serv = findserver(servlist, source);
00772
00773 if (ircd->sjb64) {
00774 ts = base64dects(av[0]);
00775 } else {
00776 ts = strtoul(av[0], NULL, 10);
00777 }
00778 c = findchan(av[1]);
00779 if (c != NULL) {
00780 if (c->creation_time == 0 || ts == 0)
00781 c->creation_time = 0;
00782 else if (c->creation_time > ts) {
00783 c->creation_time = ts;
00784 for (cu = c->users; cu; cu = cu->next) {
00785
00786 cumodes[0] = "-ov";
00787 cumodes[1] = user->nick;
00788 cumodes[2] = user->nick;
00789 chan_set_modes(source, c, 3, cumodes, 2);
00790 }
00791 if (c->ci && c->ci->bi) {
00792
00793 anope_cmd_part(c->ci->bi->nick, c->name, "TS reop");
00794 bot_join(c->ci);
00795 }
00796
00797 } else if (c->creation_time < ts)
00798 keep_their_modes = 0;
00799 } else
00800 is_created = 1;
00801
00802
00803 if (ac >= 4) {
00804 if (ircd->chansqline) {
00805 if (!c)
00806 is_sqlined = check_chan_sqline(av[1]);
00807 }
00808
00809 cubuf[0] = '+';
00810 cumodes[0] = cubuf;
00811
00812
00813 s = av[ac - 1];
00814
00815 while (*s) {
00816 end = strchr(s, ' ');
00817 if (end)
00818 *end = 0;
00819
00820 end2 = cubuf + 1;
00821
00822
00823 if (ircd->sjoinbanchar) {
00824 if (*s == ircd->sjoinbanchar && keep_their_modes) {
00825 add_ban(c, myStrGetToken(s, ircd->sjoinbanchar, 1));
00826 if (!end)
00827 break;
00828 s = end + 1;
00829 continue;
00830 }
00831 }
00832 if (ircd->sjoinexchar) {
00833 if (*s == ircd->sjoinexchar && keep_their_modes) {
00834 add_exception(c,
00835 myStrGetToken(s, ircd->sjoinexchar, 1));
00836 if (!end)
00837 break;
00838 s = end + 1;
00839 continue;
00840 }
00841 }
00842
00843 if (ircd->sjoininvchar) {
00844 if (*s == ircd->sjoininvchar && keep_their_modes) {
00845 add_invite(c, myStrGetToken(s, ircd->sjoininvchar, 1));
00846 if (!end)
00847 break;
00848 s = end + 1;
00849 continue;
00850 }
00851 }
00852
00853 while (csmodes[(int) *s] != 0)
00854 *end2++ = csmodes[(int) *s++];
00855 *end2 = 0;
00856
00857
00858 if (UseTS6 && ircd->ts6) {
00859 user = find_byuid(s);
00860 if (!user)
00861 user = finduser(s);
00862 } else {
00863 user = finduser(s);
00864 }
00865
00866 if (!user) {
00867 if (debug) {
00868 alog("debug: SJOIN for nonexistent user %s on %s", s,
00869 av[1]);
00870 }
00871 return;
00872 }
00873
00874 if (is_sqlined && !is_oper(user)) {
00875 anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
00876 } else {
00877 if (!check_kick(user, av[1], ts)) {
00878 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START,
00879 user->nick, av[1]);
00880
00881
00882
00883
00884
00885
00886
00887 c = join_user_update(user, c, av[1], ts);
00888
00889
00890 if (end2 - cubuf > 1 && keep_their_modes) {
00891 int i;
00892
00893 for (i = 1; i < end2 - cubuf; i++)
00894 cumodes[i] = user->nick;
00895 chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
00896 cumodes, 2);
00897 }
00898
00899 if (c->ci && (!serv || is_sync(serv))
00900 && !c->topic_sync)
00901 restore_topic(c->name);
00902 chan_set_correct_modes(user, c, 1);
00903
00904 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP,
00905 user->nick, av[1]);
00906 }
00907 }
00908
00909 if (!end)
00910 break;
00911 s = end + 1;
00912 }
00913
00914 if (c && keep_their_modes) {
00915
00916 chan_set_modes(source, c, ac - 3, &av[2], 2);
00917 }
00918
00919
00920 } else if (ac == 3 && !ircd->ts6) {
00921 if (ircd->chansqline) {
00922 if (!c)
00923 is_sqlined = check_chan_sqline(av[1]);
00924 }
00925
00926 cubuf[0] = '+';
00927 cumodes[0] = cubuf;
00928
00929
00930 s = av[2];
00931
00932 while (*s) {
00933 end = strchr(s, ' ');
00934 if (end)
00935 *end = 0;
00936
00937 end2 = cubuf + 1;
00938
00939 while (csmodes[(int) *s] != 0)
00940 *end2++ = csmodes[(int) *s++];
00941 *end2 = 0;
00942
00943 if (UseTS6 && ircd->ts6) {
00944 user = find_byuid(s);
00945 if (!user)
00946 user = finduser(s);
00947 } else {
00948 user = finduser(s);
00949 }
00950
00951 if (!user) {
00952 if (debug) {
00953 alog("debug: SJOIN for nonexistent user %s on %s", s,
00954 av[1]);
00955 }
00956 return;
00957 }
00958
00959 if (is_sqlined && !is_oper(user)) {
00960 anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
00961 } else {
00962 if (!check_kick(user, av[1], ts)) {
00963 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START,
00964 user->nick, av[1]);
00965
00966
00967
00968
00969
00970
00971
00972 c = join_user_update(user, c, av[1], ts);
00973
00974
00975 if (end2 - cubuf > 1 && keep_their_modes) {
00976 int i;
00977
00978 for (i = 1; i < end2 - cubuf; i++)
00979 cumodes[i] = user->nick;
00980 chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
00981 cumodes, 2);
00982 }
00983
00984 chan_set_correct_modes(user, c, 1);
00985
00986 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP,
00987 user->nick, av[1]);
00988 }
00989 }
00990
00991 if (!end)
00992 break;
00993 s = end + 1;
00994 }
00995 } else if (ac == 3 && ircd->ts6) {
00996 if (ircd->chansqline) {
00997 if (!c)
00998 is_sqlined = check_chan_sqline(av[1]);
00999 }
01000
01001 cubuf[0] = '+';
01002 cumodes[0] = cubuf;
01003
01004
01005 s = sstrdup(source);
01006
01007 while (*s) {
01008 end = strchr(s, ' ');
01009 if (end)
01010 *end = 0;
01011
01012 end2 = cubuf + 1;
01013
01014 while (csmodes[(int) *s] != 0)
01015 *end2++ = csmodes[(int) *s++];
01016 *end2 = 0;
01017
01018 if (UseTS6 && ircd->ts6) {
01019 user = find_byuid(s);
01020 if (!user)
01021 user = finduser(s);
01022 } else {
01023 user = finduser(s);
01024 }
01025 if (!user) {
01026 if (debug) {
01027 alog("debug: SJOIN for nonexistent user %s on %s", s,
01028 av[1]);
01029 }
01030 free(s);
01031 return;
01032 }
01033
01034 if (is_sqlined && !is_oper(user)) {
01035 anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
01036 } else {
01037 if (!check_kick(user, av[1], ts)) {
01038 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START,
01039 user->nick, av[1]);
01040
01041
01042
01043
01044
01045
01046
01047 c = join_user_update(user, c, av[1], ts);
01048
01049
01050 if (end2 - cubuf > 1 && keep_their_modes) {
01051 int i;
01052
01053 for (i = 1; i < end2 - cubuf; i++)
01054 cumodes[i] = user->nick;
01055 chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
01056 cumodes, 2);
01057 }
01058
01059 chan_set_correct_modes(user, c, 1);
01060
01061 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP,
01062 user->nick, av[1]);
01063 }
01064 }
01065
01066 if (!end)
01067 break;
01068 s = end + 1;
01069 }
01070 free(s);
01071 } else if (ac == 2) {
01072 if (UseTS6 && ircd->ts6) {
01073 user = find_byuid(source);
01074 if (!user)
01075 user = finduser(s);
01076 } else {
01077 user = finduser(source);
01078 }
01079 if (!user) {
01080 if (debug) {
01081 alog("debug: SJOIN for nonexistent user %s on %s", source,
01082 av[1]);
01083 }
01084 return;
01085 }
01086
01087 if (check_kick(user, av[1], ts))
01088 return;
01089
01090 if (ircd->chansqline) {
01091 if (!c)
01092 is_sqlined = check_chan_sqline(av[1]);
01093 }
01094
01095 if (is_sqlined && !is_oper(user)) {
01096 anope_cmd_kick(s_OperServ, av[1], user->nick, "Q-Lined");
01097 } else {
01098 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START, user->nick,
01099 av[1]);
01100
01101 c = join_user_update(user, c, av[1], ts);
01102 if (is_created && c->ci)
01103 restore_topic(c->name);
01104 chan_set_correct_modes(user, c, 1);
01105
01106 send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP, user->nick,
01107 av[1]);
01108 }
01109 }
01110 }
01111
01112
01113
01114
01115
01116
01117 void do_cmode(const char *source, int ac, char **av)
01118 {
01119 Channel *chan;
01120 ChannelInfo *ci = NULL;
01121 int i;
01122 char *t;
01123
01124 if (ircdcap->tsmode) {
01125
01126
01127 if (uplink_capab & ircdcap->tsmode || UseTSMODE) {
01128 for (i = 0; i < strlen(av[1]); i++) {
01129 if (!isdigit(av[1][i]))
01130 break;
01131 }
01132 if (av[1][i] == '\0') {
01133
01134
01135 t = av[0];
01136 av[0] = av[1];
01137 av[1] = t;
01138 ac--;
01139 av++;
01140 } else {
01141 alog("TSMODE enabled but MODE has no valid TS");
01142 }
01143 }
01144 }
01145
01146
01147 if (UseTS6 && ircd->ts6) {
01148 if (isdigit(av[0][0])) {
01149 ac--;
01150 av++;
01151 }
01152 }
01153
01154 chan = findchan(av[0]);
01155 if (!chan) {
01156 ci = cs_findchan(av[0]);
01157 if (!(ci && (ci->flags & CI_VERBOTEN)))
01158 if (debug) {
01159 alog("debug: MODE %s for nonexistent channel %s",
01160 merge_args(ac - 1, av + 1), av[0]);
01161 }
01162 return;
01163 }
01164
01165
01166 if (strchr(source, '.') && !av[1][strcspn(av[1], "bovahq")]) {
01167 if (time(NULL) != chan->server_modetime) {
01168 chan->server_modecount = 0;
01169 chan->server_modetime = time(NULL);
01170 }
01171 chan->server_modecount++;
01172 }
01173
01174 ac--;
01175 av++;
01176