diff options
Diffstat (limited to 'src/channels.c')
-rw-r--r-- | src/channels.c | 214 |
1 files changed, 205 insertions, 9 deletions
diff --git a/src/channels.c b/src/channels.c index ebee50403..2b871853d 100644 --- a/src/channels.c +++ b/src/channels.c @@ -21,11 +21,13 @@ Channel *chanlist[1024]; void add_ban(Channel * chan, char *mask); void add_exception(Channel * chan, char *mask); +void add_invite(Channel * chan, char *mask); void chan_adduser2(User * user, Channel * c); Channel *chan_create(char *chan); void chan_delete(Channel * c); void del_ban(Channel * chan, char *mask); void del_exception(Channel * chan, char *mask); +void del_invite(Channel * chan, char *mask); char *get_flood(Channel * chan); char *get_key(Channel * chan); char *get_limit(Channel * chan); @@ -390,6 +392,13 @@ void get_channel_stats(long *nrec, long *memuse) mem += strlen(chan->excepts[j]) + 1; } } + if (ircd->invitemode) { + mem += sizeof(char *) * chan->invitesize; + for (j = 0; j < chan->invitecount; j++) { + if (chan->invite[j]) + mem += strlen(chan->invite[j]) + 1; + } + } for (cu = chan->users; cu; cu = cu->next) { mem += sizeof(*cu); if (cu->ud) { @@ -618,22 +627,48 @@ void do_part(const char *source, int ac, char **av) av[0] = timestamp av[1] = user + ============================================================ + + Unreal SJOIN + + On Connect there is + SJOIN !11LkOb #ircops +nt :@Trystan + + av[0] = time stamp (base64) + av[1] = channel + av[2] = modes + av[3] = users + bans + + On Channel Creation or a User joins an existing + Luna.NomadIrc.Net SJOIN !11LkW9 #akill :@Trystan + Luna.NomadIrc.Net SJOIN !11LkW9 #akill :Trystan` + + av[0] = time stamp (base64) + av[1] = channel + av[2] = users + */ void do_sjoin(const char *source, int ac, char **av) { Channel *c; User *user; + char *s, *end, cubuf[ircd->max_symbols + 2], *end2, + *cumodes[ircd->max_symbols + 1]; + int is_sqlined = 0; + int ts = 0; + + if (ircd->sjb64) { + ts = base64dects(av[0]); + } else { + ts = strtoul(av[0], NULL, 10); + } /* Double check to avoid unknown modes that need parameters */ if (ac >= 4 && ac <= 6) { - char *s, *end, cubuf[ircd->max_symbols + 2], *end2, - *cumodes[ircd->max_symbols + 1]; - c = findchan(av[1]); - if (ircd->chansqline) { if (!c) is_sqlined = check_chan_sqline(av[1]); @@ -651,6 +686,26 @@ void do_sjoin(const char *source, int ac, char **av) *end = 0; end2 = cubuf + 1; + +#ifdef SJOINBANNCHAR + if (*s == SJOINBANNCHAR) { + add_ban(c, myStrGetToken(s, SJOINBANNCHAR, 1)); + if (!end) + break; + s = end + 1; + continue; + } +#endif +#ifdef SJOINEXCEPTIONCHAR + if (*s == SJOINEXCEPTIONCHAR) { + add_exception(c, myStrGetToken(s, SJOINEXCEPTIONCHAR, 1)); + if (!end) + break; + s = end + 1; + continue; + } +#endif + while (csmodes[(int) *s] != 0) *end2++ = csmodes[(int) *s++]; *end2 = 0; @@ -693,10 +748,75 @@ void do_sjoin(const char *source, int ac, char **av) if (c) { /* Set the timestamp */ - c->creation_time = strtoul(av[0], NULL, 10); + c->creation_time = ts; /* We now update the channel mode. */ chan_set_modes(source, c, ac - 3, &av[2], 1); } + + /* Unreal just had to be different */ + } else if (ac == 3) { + c = findchan(av[1]); + if (ircd->chansqline) { + if (!c) + is_sqlined = check_chan_sqline(av[1]); + } + + cubuf[0] = '+'; + cumodes[0] = cubuf; + + /* We make all the users join */ + s = av[2]; /* Users are always the last element */ + + while (*s) { + end = strchr(s, ' '); + if (end) + *end = 0; + + end2 = cubuf + 1; + + while (csmodes[(int) *s] != 0) + *end2++ = csmodes[(int) *s++]; + *end2 = 0; + + user = finduser(s); + if (!user) { + alog("user: SJOIN for nonexistent user %s on %s", s, + av[1]); + return; + } + + if (is_sqlined && !is_oper(user)) { + anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined"); + } else { + if (!check_kick(user, av[1])) { + /* Make the user join; if the channel does not exist it + * will be created there. This ensures that the channel + * is not created to be immediately destroyed, and + * that the locked key or topic is not shown to anyone + * who joins the channel when empty. + */ + c = join_user_update(user, c, av[1]); + + /* We update user mode on the channel */ + if (end2 - cubuf > 1) { + int i; + + for (i = 1; i < end2 - cubuf; i++) + cumodes[i] = user->nick; + chan_set_modes(source, c, 1 + (end2 - cubuf - 1), + cumodes, 1); + } + } + } + + if (!end) + break; + s = end + 1; + } + + if (c) { + c->creation_time = ts; + } } else if (ac == 2) { user = finduser(source); if (!user) { @@ -718,7 +838,7 @@ void do_sjoin(const char *source, int ac, char **av) anope_cmd_kick(s_OperServ, av[1], user->nick, "Q-Lined"); } else { c = join_user_update(user, c, av[1]); - c->creation_time = strtoul(av[0], NULL, 10); + c->creation_time = ts; } } } @@ -786,7 +906,16 @@ void do_cmode(const char *source, int ac, char **av) void do_topic(const char *source, int ac, char **av) { Channel *c = findchan(av[0]); - time_t topic_time = strtoul(av[2], NULL, 10); + int ts; + time_t topic_time; + + if (ircd->sjb64) { + ts = base64dects(av[0]); + } else { + ts = strtoul(av[0], NULL, 10); + } + + topic_time = ts; if (!c) { alog("channel: TOPIC %s for nonexistent channel %s", @@ -856,6 +985,21 @@ void add_exception(Channel * chan, char *mask) /*************************************************************************/ +void add_invite(Channel * chan, char *mask) +{ + if (chan->invitecount >= chan->invitesize) { + chan->invitesize += 8; + chan->invite = + srealloc(chan->invite, sizeof(char *) * chan->invitesize); + } + chan->invite[chan->invitecount++] = sstrdup(mask); + + if (debug) + alog("debug: Added invite %s to channel %s", mask, chan->name); +} + +/*************************************************************************/ + /* Add/remove a user to/from a channel, creating or deleting the channel as * necessary. If creating the channel, restore mode lock and topic as * necessary. Also check for auto-opping and auto-voicing. @@ -1012,13 +1156,25 @@ void chan_delete(Channel * c) if (c->excepts[i]) free(c->excepts[i]); else - alog("channel: BUG freeing %s: exceps[%d] is NULL!", + alog("channel: BUG freeing %s: excepts[%d] is NULL!", c->name, i); } if (c->exceptsize) free(c->excepts); } + if (ircd->invitemode) { + for (i = 0; i < c->invitecount; ++i) { + if (c->invite[i]) + free(c->invite[i]); + else + alog("channel: BUG freeing %s: invite[%d] is NULL!", + c->name, i); + } + if (c->invitesize) + free(c->invite); + } + if (c->next) c->next->prev = c->prev; if (c->prev) @@ -1037,6 +1193,11 @@ void del_ban(Channel * chan, char *mask) int i = 0; AutoKick *akick; + /* Sanity check as it seems some IRCD will just send -b without a mask */ + if (!mask) { + return; + } + while (i < chan->bancount && strcmp(*s, mask) != 0) { i++; s++; @@ -1063,6 +1224,11 @@ void del_exception(Channel * chan, char *mask) int i; int reset = 0; + /* Sanity check as it seems some IRCD will just send -e without a mask */ + if (!mask) { + return; + } + for (i = 0; i < chan->exceptcount; i++) { if ((!reset) && (stricmp(chan->excepts[i], mask) == 0)) { free(chan->excepts[i]); @@ -1082,6 +1248,36 @@ void del_exception(Channel * chan, char *mask) /*************************************************************************/ +void del_invite(Channel * chan, char *mask) +{ + int i; + int reset = 0; + + /* Sanity check as it seems some IRCD will just send -I without a mask */ + if (!mask) { + return; + } + + for (i = 0; i < chan->invitecount; i++) { + if ((!reset) && (stricmp(chan->invite[i], mask) == 0)) { + free(chan->invite[i]); + reset = 1; + } + if (reset) + chan->invite[i] = + (i == chan->invitecount) ? NULL : chan->invite[i + 1]; + } + + if (reset) + chan->invitecount--; + + if (debug) + alog("debug: Deleted invite %s to channel %s", mask, chan->name); +} + + +/*************************************************************************/ + char *get_flood(Channel * chan) { return chan->flood; @@ -1148,7 +1344,7 @@ void set_flood(Channel * chan, char *value) chan->flood = value ? sstrdup(value) : NULL; if (debug) - alog("debug: Flood of channel %s set to %s", chan->name, + alog("debug: Flood mode for channel %s set to %s", chan->name, chan->flood ? chan->flood : "no flood settings"); } |