summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/channels.c87
-rw-r--r--src/chanserv.c11
-rw-r--r--src/core/cs_akick.c4
-rw-r--r--src/core/cs_topic.c2
-rw-r--r--src/core/os_set.c4
-rw-r--r--src/init.c1
-rw-r--r--src/modules/cs_appendtopic.c2
-rw-r--r--src/protocol/charybdis.c11
-rw-r--r--src/protocol/hybrid.c2
-rw-r--r--src/protocol/plexus2.c2
-rw-r--r--src/protocol/plexus3.c2
-rw-r--r--src/protocol/ptlink.c2
-rw-r--r--src/protocol/ratbox.c2
-rw-r--r--src/protocol/shadowircd.c2
14 files changed, 70 insertions, 64 deletions
diff --git a/src/channels.c b/src/channels.c
index e93ea8401..d3615b335 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -575,11 +575,13 @@ void do_join(const char *source, int ac, char **av)
/* Make sure check_kick comes before chan_adduser, so banned users
* don't get to see things like channel keys. */
- if (check_kick(user, s))
+ /* If channel already exists, check_kick() will use correct TS.
+ * Otherwise, we lose. */
+ if (check_kick(user, s, time(NULL)))
continue;
chan = findchan(s);
- chan = join_user_update(user, chan, s);
+ chan = join_user_update(user, chan, s, time(NULL));
chan_set_correct_modes(user, chan, 1);
send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP, source, s);
@@ -756,11 +758,13 @@ void do_sjoin(const char *source, int ac, char **av)
Channel *c;
User *user;
Server *serv;
+ struct c_userlist *cu;
char *s = NULL;
char *end, cubuf[7], *end2, *cumodes[6];
int is_sqlined = 0;
int ts = 0;
int is_created = 0;
+ int keep_their_modes = 1;
serv = findserver(servlist, source);
@@ -769,10 +773,32 @@ void do_sjoin(const char *source, int ac, char **av)
} else {
ts = strtoul(av[0], NULL, 10);
}
+ c = findchan(av[1]);
+ if (c != NULL) {
+ if (c->creation_time == 0 || ts == 0)
+ c->creation_time = 0;
+ else if (c->creation_time > ts) {
+ c->creation_time = ts;
+ for (cu = c->users; cu; cu = cu->next) {
+ /* XXX */
+ cumodes[0] = "-ov";
+ cumodes[1] = user->nick;
+ cumodes[2] = user->nick;
+ chan_set_modes(source, c, 3, cumodes, 2);
+ }
+ if (c->ci && c->ci->bi) {
+ /* This is ugly, but it always works */
+ anope_cmd_part(c->ci->bi->nick, c->name, "TS reop");
+ bot_join(c->ci);
+ }
+ /* XXX simple modes and bans */
+ } else if (c->creation_time < ts)
+ keep_their_modes = 0;
+ } else
+ is_created = 1;
/* Double check to avoid unknown modes that need parameters */
if (ac >= 4) {
- c = findchan(av[1]);
if (ircd->chansqline) {
if (!c)
is_sqlined = check_chan_sqline(av[1]);
@@ -793,7 +819,7 @@ void do_sjoin(const char *source, int ac, char **av)
if (ircd->sjoinbanchar) {
- if (*s == ircd->sjoinbanchar) {
+ if (*s == ircd->sjoinbanchar && keep_their_modes) {
add_ban(c, myStrGetToken(s, ircd->sjoinbanchar, 1));
if (!end)
break;
@@ -802,7 +828,7 @@ void do_sjoin(const char *source, int ac, char **av)
}
}
if (ircd->sjoinexchar) {
- if (*s == ircd->sjoinexchar) {
+ if (*s == ircd->sjoinexchar && keep_their_modes) {
add_exception(c,
myStrGetToken(s, ircd->sjoinexchar, 1));
if (!end)
@@ -813,7 +839,7 @@ void do_sjoin(const char *source, int ac, char **av)
}
if (ircd->sjoininvchar) {
- if (*s == ircd->sjoininvchar) {
+ if (*s == ircd->sjoininvchar && keep_their_modes) {
add_invite(c, myStrGetToken(s, ircd->sjoininvchar, 1));
if (!end)
break;
@@ -846,7 +872,7 @@ void do_sjoin(const char *source, int ac, char **av)
if (is_sqlined && !is_oper(user)) {
anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
} else {
- if (!check_kick(user, av[1])) {
+ if (!check_kick(user, av[1], ts)) {
send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START,
user->nick, av[1]);
@@ -856,10 +882,10 @@ void do_sjoin(const char *source, int ac, char **av)
* 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]);
+ c = join_user_update(user, c, av[1], ts);
/* We update user mode on the channel */
- if (end2 - cubuf > 1) {
+ if (end2 - cubuf > 1 && keep_their_modes) {
int i;
for (i = 1; i < end2 - cubuf; i++)
@@ -883,16 +909,13 @@ void do_sjoin(const char *source, int ac, char **av)
s = end + 1;
}
- if (c) {
- /* Set the timestamp */
- c->creation_time = ts;
+ if (c && keep_their_modes) {
/* We now update the channel mode. */
chan_set_modes(source, c, ac - 3, &av[2], 2);
}
/* Unreal just had to be different */
} else if (ac == 3 && !ircd->ts6) {
- c = findchan(av[1]);
if (ircd->chansqline) {
if (!c)
is_sqlined = check_chan_sqline(av[1]);
@@ -934,7 +957,7 @@ void do_sjoin(const char *source, int ac, char **av)
if (is_sqlined && !is_oper(user)) {
anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
} else {
- if (!check_kick(user, av[1])) {
+ if (!check_kick(user, av[1], ts)) {
send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START,
user->nick, av[1]);
@@ -944,10 +967,10 @@ void do_sjoin(const char *source, int ac, char **av)
* 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]);
+ c = join_user_update(user, c, av[1], ts);
/* We update user mode on the channel */
- if (end2 - cubuf > 1) {
+ if (end2 - cubuf > 1 && keep_their_modes) {
int i;
for (i = 1; i < end2 - cubuf; i++)
@@ -967,12 +990,7 @@ void do_sjoin(const char *source, int ac, char **av)
break;
s = end + 1;
}
-
- if (c) {
- c->creation_time = ts;
- }
} else if (ac == 3 && ircd->ts6) {
- c = findchan(av[1]);
if (ircd->chansqline) {
if (!c)
is_sqlined = check_chan_sqline(av[1]);
@@ -1014,7 +1032,7 @@ void do_sjoin(const char *source, int ac, char **av)
if (is_sqlined && !is_oper(user)) {
anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
} else {
- if (!check_kick(user, av[1])) {
+ if (!check_kick(user, av[1], ts)) {
send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START,
user->nick, av[1]);
@@ -1024,10 +1042,10 @@ void do_sjoin(const char *source, int ac, char **av)
* 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]);
+ c = join_user_update(user, c, av[1], ts);
/* We update user mode on the channel */
- if (end2 - cubuf > 1) {
+ if (end2 - cubuf > 1 && keep_their_modes) {
int i;
for (i = 1; i < end2 - cubuf; i++)
@@ -1047,10 +1065,6 @@ void do_sjoin(const char *source, int ac, char **av)
break;
s = end + 1;
}
-
- if (c) {
- c->creation_time = ts;
- }
free(s);
} else if (ac == 2) {
if (UseTS6 && ircd->ts6) {
@@ -1068,12 +1082,9 @@ void do_sjoin(const char *source, int ac, char **av)
return;
}
- if (check_kick(user, av[1]))
+ if (check_kick(user, av[1], ts))
return;
- c = findchan(av[1]);
- if (!c)
- is_created = 1;
if (ircd->chansqline) {
if (!c)
is_sqlined = check_chan_sqline(av[1]);
@@ -1085,8 +1096,7 @@ void do_sjoin(const char *source, int ac, char **av)
send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START, user->nick,
av[1]);
- c = join_user_update(user, c, av[1]);
- c->creation_time = ts;
+ c = join_user_update(user, c, av[1], ts);
if (is_created && c->ci)
restore_topic(c->name);
chan_set_correct_modes(user, c, 1);
@@ -1559,7 +1569,7 @@ void chan_adduser2(User * user, Channel * c)
chan_adduser, but splitted to make it more efficient to use for
SJOINs). */
-Channel *chan_create(char *chan)
+Channel *chan_create(char *chan, time_t ts)
{
Channel *c;
Channel **list;
@@ -1574,7 +1584,7 @@ Channel *chan_create(char *chan)
if (*list)
(*list)->prev = c;
*list = c;
- c->creation_time = time(NULL);
+ c->creation_time = ts;
/* Store ChannelInfo pointer in channel record */
c->ci = cs_findchan(chan);
if (c->ci)
@@ -1798,13 +1808,14 @@ char *get_redirect(Channel * chan)
/*************************************************************************/
-Channel *join_user_update(User * user, Channel * chan, char *name)
+Channel *join_user_update(User * user, Channel * chan, char *name,
+ time_t chants)
{
struct u_chanlist *c;
/* If it's a new channel, so we need to create it first. */
if (!chan)
- chan = chan_create(name);
+ chan = chan_create(name, chants);
if (debug)
alog("debug: %s joins %s", user->nick, chan->name);
diff --git a/src/chanserv.c b/src/chanserv.c
index 547f337ce..f439369e9 100644
--- a/src/chanserv.c
+++ b/src/chanserv.c
@@ -1466,10 +1466,10 @@ static void timeout_leave(Timeout * to)
* else, kickban the user with an appropriate message (could be either
* AKICK or restricted access) and return 1. Note that this is called
* _before_ the user is added to internal channel lists (so do_kick() is
- * not called).
+ * not called). The channel TS must be given for a new channel.
*/
-int check_kick(User * user, char *chan)
+int check_kick(User * user, char *chan, time_t chants)
{
ChannelInfo *ci = cs_findchan(chan);
Channel *c;
@@ -1563,8 +1563,7 @@ int check_kick(User * user, char *chan)
* c may be NULL even if it exists */
if ((!(c = findchan(chan)) || c->usercount == 0)
&& !(ci->flags & CI_INHABIT)) {
- anope_cmd_join(s_ChanServ, chan,
- (c ? c->creation_time : time(NULL)));
+ anope_cmd_join(s_ChanServ, chan, (c ? c->creation_time : chants));
t = add_timeout(CSInhabit, timeout_leave, 0);
t->data = sstrdup(chan);
ci->flags |= CI_INHABIT;
@@ -1646,7 +1645,7 @@ void restore_topic(char *chan)
}
if (ircd->join2set) {
if (whosends(ci) == s_ChanServ) {
- anope_cmd_join(s_ChanServ, chan, time(NULL));
+ anope_cmd_join(s_ChanServ, chan, c->creation_time);
anope_cmd_mode(NULL, chan, "+o %s", s_ChanServ);
}
}
@@ -1708,7 +1707,7 @@ int check_topiclock(Channel * c, time_t topic_time)
if (ircd->join2set) {
if (whosends(ci) == s_ChanServ) {
- anope_cmd_join(s_ChanServ, c->name, time(NULL));
+ anope_cmd_join(s_ChanServ, c->name, c->creation_time);
anope_cmd_mode(NULL, c->name, "+o %s", s_ChanServ);
}
}
diff --git a/src/core/cs_akick.c b/src/core/cs_akick.c
index 4108f58e3..39eb6d25c 100644
--- a/src/core/cs_akick.c
+++ b/src/core/cs_akick.c
@@ -284,7 +284,7 @@ int do_akick(User * u)
cu = c->users;
while (cu) {
next = cu->next;
- if (check_kick(cu->user, c->name)) {
+ if (check_kick(cu->user, c->name, c->creation_time)) {
argv[0] = sstrdup(c->name);
argv[1] = sstrdup(cu->user->nick);
if (akick->reason)
@@ -553,7 +553,7 @@ int do_akick(User * u)
while (cu) {
next = cu->next;
- if (check_kick(cu->user, c->name)) {
+ if (check_kick(cu->user, c->name, c->creation_time)) {
argv[0] = sstrdup(c->name);
argv[1] = sstrdup(cu->user->nick);
argv[2] = sstrdup(CSAutokickReason);
diff --git a/src/core/cs_topic.c b/src/core/cs_topic.c
index c4af5fc5b..fe2a0b27d 100644
--- a/src/core/cs_topic.c
+++ b/src/core/cs_topic.c
@@ -103,7 +103,7 @@ int do_cs_topic(User * u)
s_ChanServ, u->nick, u->username, u->host, c->name);
if (ircd->join2set) {
if (whosends(ci) == s_ChanServ) {
- anope_cmd_join(s_ChanServ, c->name, time(NULL));
+ anope_cmd_join(s_ChanServ, c->name, c->creation_time);
anope_cmd_mode(NULL, c->name, "+o %s", s_ChanServ);
}
}
diff --git a/src/core/os_set.c b/src/core/os_set.c
index 240b60a5f..860270dfb 100644
--- a/src/core/os_set.c
+++ b/src/core/os_set.c
@@ -97,6 +97,7 @@ int do_set(User * u)
char *option = strtok(NULL, " ");
char *setting = strtok(NULL, " ");
int index;
+ Channel *c;
if (!option) {
syntax_error(s_OperServ, u, "SET", OPER_SET_SYNTAX);
@@ -185,7 +186,8 @@ int do_set(User * u)
*/
if (LogChannel && (stricmp(setting, "on") == 0)) {
if (ircd->join2msg) {
- anope_cmd_join(s_GlobalNoticer, LogChannel, time(NULL));
+ c = findchan(LogChannel);
+ anope_cmd_join(s_GlobalNoticer, LogChannel, c ? c->creation_time : time(NULL));
}
logchan = 1;
alog("Now sending log messages to %s", LogChannel);
diff --git a/src/init.c b/src/init.c
index bfdc26600..e40297765 100644
--- a/src/init.c
+++ b/src/init.c
@@ -761,6 +761,7 @@ int init_secondary(int ac, char **av)
/* And hybrid needs Global joined in the logchan */
if (logchan && ircd->join2msg) {
+ /* XXX might desync */
anope_cmd_join(s_GlobalNoticer, LogChannel, time(NULL));
}
diff --git a/src/modules/cs_appendtopic.c b/src/modules/cs_appendtopic.c
index 0967462c9..df68d0e91 100644
--- a/src/modules/cs_appendtopic.c
+++ b/src/modules/cs_appendtopic.c
@@ -147,7 +147,7 @@ int my_cs_appendtopic(User * u)
s_ChanServ, u->nick, u->username, u->host, c->name);
if (ircd->join2set) {
if (whosends(ci) == s_ChanServ) {
- anope_cmd_join(s_ChanServ, c->name, time(NULL));
+ anope_cmd_join(s_ChanServ, c->name, c->creation_time);
anope_cmd_mode(NULL, c->name, "+o %s", s_ChanServ);
}
}
diff --git a/src/protocol/charybdis.c b/src/protocol/charybdis.c
index d559e0941..317753945 100644
--- a/src/protocol/charybdis.c
+++ b/src/protocol/charybdis.c
@@ -907,16 +907,9 @@ void charybdis_cmd_unsqline(char *user)
void charybdis_cmd_join(char *user, char *channel, time_t chantime)
{
Uid *ud;
- time_t tstosend;
-
- /* Working around anope's TS brokenness, also making sure
- * to *never* send an SJOIN with TS zero -- jilles */
- if (chantime == 0 || chantime == time(NULL))
- tstosend = 0x7FFFFFFF;
- else
- tstosend = chantime;
+
ud = find_uid(user);
- send_cmd(NULL, "SJOIN %ld %s + :%s", (long int) tstosend,
+ send_cmd(NULL, "SJOIN %ld %s + :%s", (long int) chantime,
channel, (UseTS6 ? (ud ? ud->uid : user) : user));
}
diff --git a/src/protocol/hybrid.c b/src/protocol/hybrid.c
index 1f23a918c..0ceceb017 100644
--- a/src/protocol/hybrid.c
+++ b/src/protocol/hybrid.c
@@ -714,7 +714,7 @@ void hybrid_cmd_unsqline(char *user)
void hybrid_cmd_join(char *user, char *channel, time_t chantime)
{
- send_cmd(NULL, "SJOIN %ld %s + :%s", (long int) time(NULL), channel,
+ send_cmd(NULL, "SJOIN %ld %s + :%s", (long int) chantime, channel,
user);
}
diff --git a/src/protocol/plexus2.c b/src/protocol/plexus2.c
index 91d33c78d..4b6e19f37 100644
--- a/src/protocol/plexus2.c
+++ b/src/protocol/plexus2.c
@@ -866,7 +866,7 @@ plexus_cmd_unsqline (char *user)
void
plexus_cmd_join (char *user, char *channel, time_t chantime)
{
- send_cmd (ServerName, "SJOIN %ld %s + :%s", (long int) time (NULL), channel,
+ send_cmd (ServerName, "SJOIN %ld %s + :%s", (long int) chantime, channel,
user);
}
diff --git a/src/protocol/plexus3.c b/src/protocol/plexus3.c
index aa5a42c99..c2ac6a934 100644
--- a/src/protocol/plexus3.c
+++ b/src/protocol/plexus3.c
@@ -843,7 +843,7 @@ plexus_cmd_unsqline (char *user)
void
plexus_cmd_join (char *user, char *channel, time_t chantime)
{
- send_cmd (ServerName, "SJOIN %ld %s + :%s", (long int) time (NULL), channel,
+ send_cmd (ServerName, "SJOIN %ld %s + :%s", (long int) chantime, channel,
user);
}
diff --git a/src/protocol/ptlink.c b/src/protocol/ptlink.c
index 81b085fad..cdab41385 100644
--- a/src/protocol/ptlink.c
+++ b/src/protocol/ptlink.c
@@ -723,7 +723,7 @@ void ptlink_cmd_unsqline(char *user)
void ptlink_cmd_join(char *user, char *channel, time_t chantime)
{
- send_cmd(ServerName, "SJOIN %ld %s + :%s", (long int) time(NULL),
+ send_cmd(ServerName, "SJOIN %ld %s + :%s", (long int) chantime,
channel, user);
}
diff --git a/src/protocol/ratbox.c b/src/protocol/ratbox.c
index 4f6e6267d..bd42a56c3 100644
--- a/src/protocol/ratbox.c
+++ b/src/protocol/ratbox.c
@@ -854,7 +854,7 @@ void ratbox_cmd_join(char *user, char *channel, time_t chantime)
Uid *ud;
ud = find_uid(user);
- send_cmd(NULL, "SJOIN %ld %s + :%s", (long int) time(NULL),
+ send_cmd(NULL, "SJOIN %ld %s + :%s", (long int) chantime,
channel, (UseTS6 ? (ud ? ud->uid : user) : user));
}
diff --git a/src/protocol/shadowircd.c b/src/protocol/shadowircd.c
index 54757c98b..fe887db7f 100644
--- a/src/protocol/shadowircd.c
+++ b/src/protocol/shadowircd.c
@@ -888,7 +888,7 @@ void shadowircd_cmd_join(char *user, char *channel, time_t chantime)
Uid *ud;
ud = find_uid(user);
- send_cmd(NULL, "SJOIN %ld %s + :%s", (long int) time(NULL),
+ send_cmd(NULL, "SJOIN %ld %s + :%s", (long int) chantime,
channel, (ud ? ud->uid : user));
}