Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Mon, 23 Oct 2000 21:44:48 +0000 (21:44 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Mon, 23 Oct 2000 21:44:48 +0000 (21:44 +0000)
Log message:

Fixed a couple of bugs in the new mode parser, in particular a bug in
mode_parse_limit that wiped out all modes when you did -l, and another
more minor bug having to do with presentation--i.e., if you did a +p
on a channel that was not +s, you would see "-s+p"

Some behavior may still be unexpected; for instance, "mode #test +ps" will
toggle the channel mode between +p and +s, because of the mutual
exclusivity, and if you do "mode #test -n+n" on a +n channel, you will get
"mode #test -n".  We may be able to solve this by removing the shortcut
test at the top of mode_parse_mode...

Testing done: I checked to see if the -iklmntp * behavior worked correctly,
and it did--note that "*" there will be properly treated as an error if the
channel key is, say, "foobar" ;)  I also checked to see that +p/+s worked
as I desired, and it does--which is how I know of the other behavior ;)

Testing needed: tell me what kind of behavior your prefer!

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@298 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
ircd/channel.c

index ea80cfc4537a81fd8929eea71950781a9d509e30..69883349f904962351451a6886ea00410a423ec7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2000-10-23  Kevin L. Mitchell  <klmitch@mit.edu>
+
+       * ircd/channel.c: add "add" and "del" elements to ParseState to
+       avoid not-too-pretty -p+s when +s is sufficient; fix a bug in
+       mode_parse_limit that caused it to clear all channel modes
+       prematurely; restructure mode_parse_mode to avoid calling
+       modebuf_mode too early (ties in with first mentioned change);
+       better logic for +p/+s mutual exclusivity; initialize "add" and
+       "del" elements in mode_parse; send simple modes down to
+       modebuf_mode after the loop in mode_parse
+
 2000-09-28  Greg Sikorski <gte@atomicrevs.demon.co.uk>
        * ircd/m_names.c: Fixed a non-lethal logic error that 
        triggers an assert() in find_member_link while debugging.
index 1c544bcd4d22c91909885e3765ba55e6b5f111a9..9c4c31d8165368be8ef3313768bdb38a4f296b24 100644 (file)
@@ -3186,6 +3186,8 @@ struct ParseState {
   unsigned int flags;
   unsigned int dir;
   unsigned int done;
+  unsigned int add;
+  unsigned int del;
   int args_used;
   int max_args;
   int numbans;
@@ -3260,7 +3262,7 @@ mode_parse_limit(struct ParseState *state, int *flag_p)
       state->chptr->mode.mode |= flag_p[0];
       state->chptr->mode.limit = t_limit;
     } else {
-      state->chptr->mode.mode &= flag_p[0];
+      state->chptr->mode.mode &= ~flag_p[0];
       state->chptr->mode.limit = 0;
     }
   }
@@ -3689,8 +3691,10 @@ mode_process_clients(struct ParseState *state)
 static void
 mode_parse_mode(struct ParseState *state, int *flag_p)
 {
-  if ((state->dir == MODE_ADD &&  (flag_p[0] & state->chptr->mode.mode)) ||
-      (state->dir == MODE_DEL && !(flag_p[0] & state->chptr->mode.mode)))
+  if ((state->dir == MODE_ADD &&  ((flag_p[0] & state->chptr->mode.mode) ||
+                                  (flag_p[0] & state->del))) ||
+      (state->dir == MODE_DEL && !((flag_p[0] & state->chptr->mode.mode) ||
+                                  (flag_p[0] & state->add))))
     return; /* no change */
 
   /* If they're not an oper, they can't change modes */
@@ -3702,36 +3706,32 @@ mode_parse_mode(struct ParseState *state, int *flag_p)
   if (!state->mbuf)
     return;
 
-  modebuf_mode(state->mbuf, state->dir | flag_p[0]);
-
-  /* make +p and +s mutually exclusive */
-  if (state->dir == MODE_ADD && flag_p[0] & (MODE_SECRET | MODE_PRIVATE)) {
-    if (flag_p[0] == MODE_SECRET && (state->chptr->mode.mode & MODE_PRIVATE))
-      modebuf_mode(state->mbuf, MODE_DEL | MODE_PRIVATE);
-    else if (flag_p[0] == MODE_PRIVATE &&
-            (state->chptr->mode.mode & MODE_SECRET))
-      modebuf_mode(state->mbuf, MODE_DEL | MODE_SECRET);
+  if (state->dir == MODE_ADD) {
+    if (state->del & flag_p[0]) /* if we're adding a deleted mode, ignore */
+      state->del &= ~flag_p[0];
+    else
+      state->add |= flag_p[0]; /* otherwise add it */
+  } else {
+    if (state->add & flag_p[0]) /* if we're deleting an added mode, ignore */
+      state->add &= ~flag_p[0];
+    else
+      state->del |= flag_p[0]; /* otherwise delete it */
   }
 
-  if (state->flags & MODE_PARSE_SET) { /* set the flags */
-    if (state->dir == MODE_ADD) { /* add the mode to the channel */
-      state->chptr->mode.mode |= flag_p[0];
-
-      /* make +p and +s mutually exclusive */
-      if (state->dir == MODE_ADD && flag_p[0] & (MODE_SECRET | MODE_PRIVATE)) {
-       if (flag_p[0] == MODE_PRIVATE)
-         state->chptr->mode.mode &= ~MODE_SECRET;
-       else
-         state->chptr->mode.mode &= ~MODE_PRIVATE;
-      }
-    } else /* remove the mode from the channel */
-      state->chptr->mode.mode &= ~flag_p[0];
+  /* make +p and +s mutually exclusive */
+  if (state->dir == MODE_ADD && (flag_p[0] & MODE_SECRET)) {
+    if (state->add & MODE_PRIVATE) /* deal with added modes first */
+      state->add &= ~MODE_PRIVATE;
+    if (state->chptr->mode.mode & MODE_PRIVATE) /* then channel modes */
+      state->del |= MODE_PRIVATE;
+  } else if (state->dir == MODE_ADD && (flag_p[0] & MODE_PRIVATE)) {
+    if (state->add & MODE_SECRET) /* deal with added modes first */
+      state->add &= ~MODE_SECRET;
+    if (state->chptr->mode.mode & MODE_SECRET) /* then channel modes */
+      state->del |= MODE_SECRET;
   }
 
-  /* Clear out invite structures if we're removing invites */
-  if (state->flags & MODE_PARSE_SET && state->dir == MODE_DEL &&
-      flag_p[0] == MODE_INVITEONLY)
-    mode_invite_clear(state->chptr);
+  assert(0 == (state->add & state->del));
 }
 
 /*
@@ -3779,6 +3779,8 @@ mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr,
   state.flags = flags;
   state.dir = MODE_ADD;
   state.done = 0;
+  state.add = 0;
+  state.del = 0;
   state.args_used = 0;
   state.max_args = MAXMODEPARAMS;
   state.numbans = 0;
@@ -3873,6 +3875,19 @@ mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr,
   if (!state.mbuf || state.flags & (MODE_PARSE_NOTOPER | MODE_PARSE_NOTMEMBER))
     return state.args_used; /* tell our parent how many args we gobbled */
 
+  if (state.add) /* add any modes to be added... */
+    modebuf_mode(state.mbuf, MODE_ADD | state.add);
+  if (state.del) /* delete any modes to be deleted... */
+    modebuf_mode(state.mbuf, MODE_DEL | state.del);
+
+  if (state.flags & MODE_PARSE_SET) { /* set the channel modes */
+    state.chptr->mode.mode |= state.add;
+    state.chptr->mode.mode &= ~state.del;
+
+    if (state.del & MODE_INVITEONLY) /* clear invites away if needed */
+      mode_invite_clear(state.chptr);
+  }
+
   if (state.flags & MODE_PARSE_WIPEOUT) {
     if (state.chptr->mode.limit && !(state.done & DONE_LIMIT))
       modebuf_mode_uint(state.mbuf, MODE_DEL | MODE_LIMIT,