From b168d1cf9ec654e8a47b94c3c79c833ce650a721 Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Tue, 23 Jan 2007 02:23:35 +0000 Subject: [PATCH] Fix SF bug #1640796; add a test for it. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/branches/u2_10_12_branch@1759 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 7 +++++ ircd/channel.c | 64 +++++++++++++++++++++++-------------------- tests/bug-1640796.cmd | 35 +++++++++++++++++++++++ 3 files changed, 76 insertions(+), 30 deletions(-) create mode 100644 tests/bug-1640796.cmd diff --git a/ChangeLog b/ChangeLog index cd2a40d..e7c4ac0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2007-01-22 Michael Poole + + * ircd/channel.c (find_delayed_joins): New function. + (modebuf_flush): Handle +D-D and related cases. + (mode_parse_mode): It is too early to handle +D here, so don't. + (CheckDelayedJoins): Use find_delayed_joins(). + 2007-01-22 Michael Poole * tests: New subdirectory for test framework. diff --git a/ircd/channel.c b/ircd/channel.c index e591dda..355b99d 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -2049,6 +2049,20 @@ modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode, modebuf_flush_int(mbuf, 0); } +/** Check a channel for join-delayed members. + * @param[in] chan Channel to search. + * @return Non-zero if any members are join-delayed; false if none are. + */ +static int +find_delayed_joins(const struct Channel *chan) +{ + const struct Membership *memb; + for (memb = chan->members; memb; memb = memb->next_member) + if (IsDelayedJoin(memb)) + return 1; + return 0; +} + /** The exported binding for modebuf_flush() * * @param mbuf The mode buffer to flush. @@ -2058,19 +2072,22 @@ modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode, int modebuf_flush(struct ModeBuf *mbuf) { - struct Membership *memb; - - /* Check if MODE_WASDELJOINS should be set */ - if (!(mbuf->mb_channel->mode.mode & (MODE_DELJOINS | MODE_WASDELJOINS)) - && (mbuf->mb_rem & MODE_DELJOINS)) { - for (memb = mbuf->mb_channel->members; memb; memb = memb->next_member) { - if (IsDelayedJoin(memb)) { - mbuf->mb_channel->mode.mode |= MODE_WASDELJOINS; - mbuf->mb_add |= MODE_WASDELJOINS; - mbuf->mb_rem &= ~MODE_WASDELJOINS; - break; - } - } + /* Check if MODE_WASDELJOINS should be set: */ + /* Must be set if going -D and some clients are hidden */ + if ((mbuf->mb_rem & MODE_DELJOINS) + && !(mbuf->mb_channel->mode.mode & (MODE_DELJOINS | MODE_WASDELJOINS)) + && find_delayed_joins(mbuf->mb_channel)) { + mbuf->mb_channel->mode.mode |= MODE_WASDELJOINS; + mbuf->mb_add |= MODE_WASDELJOINS; + mbuf->mb_rem &= ~MODE_WASDELJOINS; + } + /* Must be cleared if +D is set */ + if ((mbuf->mb_add & MODE_DELJOINS) + && ((mbuf->mb_channel->mode.mode & (MODE_WASDELJOINS | MODE_WASDELJOINS)) + == (MODE_WASDELJOINS | MODE_WASDELJOINS))) { + mbuf->mb_channel->mode.mode &= ~MODE_WASDELJOINS; + mbuf->mb_add &= ~MODE_WASDELJOINS; + mbuf->mb_rem |= MODE_WASDELJOINS; } return modebuf_flush_int(mbuf, 1); @@ -3138,10 +3155,6 @@ mode_parse_mode(struct ParseState *state, int *flag_p) state->add &= ~MODE_SECRET; state->del |= MODE_SECRET; } - if (flag_p[0] & MODE_DELJOINS) { - state->add &= ~MODE_WASDELJOINS; - state->del |= MODE_WASDELJOINS; - } } else { state->add &= ~flag_p[0]; state->del |= flag_p[0]; @@ -3576,18 +3589,9 @@ void RevealDelayedJoin(struct Membership *member) void CheckDelayedJoins(struct Channel *chan) { - struct Membership *memb2; - - if (chan->mode.mode & MODE_WASDELJOINS) { - for (memb2=chan->members;memb2;memb2=memb2->next_member) - if (IsDelayedJoin(memb2)) - break; - - if (!memb2) { - /* clear +d */ - chan->mode.mode &= ~MODE_WASDELJOINS; - sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan, NULL, 0, - "%H -d", chan); - } + if ((chan->mode.mode & MODE_WASDELJOINS) && !find_delayed_joins(chan)) { + chan->mode.mode &= ~MODE_WASDELJOINS; + sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan, NULL, 0, + "%H -d", chan); } } diff --git a/tests/bug-1640796.cmd b/tests/bug-1640796.cmd new file mode 100644 index 0000000..8a3c0d8 --- /dev/null +++ b/tests/bug-1640796.cmd @@ -0,0 +1,35 @@ +define srv1 localhost:7601 +define srv1-name irc.example.net +define hidden-srv *.undernet.org +define channel #random-channel +define cl1-nick Ch4n0pm4n +define cl2-nick D00dm4n + +# Connect two clients. Join one to the test channel. +connect cl1 %cl1-nick% op3rm4n %srv1% :Some Chanop +connect cl2 %cl2-nick% d00dm4n %srv1% :Someone Else +:cl1 join %channel% +:cl1 mode %channel% +D +:cl1 expect %cl1-nick% mode %channel% \\+D + +# Now join the other client, and let the chanop remove -D. Both +# should see the channel become +d. +:cl2 wait cl1 +:cl2 join %channel% +:cl1 wait cl2 +:cl1 mode %channel% -D +:cl1 expect %cl1-nick% mode %channel% -D\\+d +:cl2 expect %cl1-nick% mode %channel% -D\\+d + +# Bug 1640796 is that if the chanop sends +D-D, the channel is +# improperly marked -d. (An empty mode change is also sent to other +# servers.) +:cl1 mode %channel% +D-D +:cl1 mode %channel% +:cl1 expect %srv1-name% 324 %cl1-nick% %channel% \\+.*d + +# Make sure that client 1 does see the -d when client 2 quits +:cl2 wait cl1 +:cl2 part %channel% leaving +:cl1 expect %hidden-srv% mode %channel% -d +:cl1 quit done -- 2.20.1