summaryrefslogtreecommitdiff
path: root/src/channels.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/channels.c')
-rw-r--r--src/channels.c214
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");
}