Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Tue, 24 Oct 2000 21:05:00 +0000 (21:05 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Tue, 24 Oct 2000 21:05:00 +0000 (21:05 +0000)
Log message:

* ircd/channel.c: ok, now last mode rules; mode +ps will always
result in +s (and won't send a mode if the channel is already +s);
mode +sp will always result in +p; -n+n on a +n channel results in
no mode change; -n+n on a -n channel results in a +n mode change;
etc.

Status: stable; I don't expect there will be any more problems besides bugs

Testing done: Simple modes conform to the behavior I expect, i.e., last
  mode takes precedence.  No empty mode commands are forwarded to remote
  servers.  +p and +s are mutually exclusive.  No unset modes are removed.

Testing needed: Brute force check it and report any problems; I'm
  particularly concerned with BURSTs and server MODEs, though reports on
  OPMODE and user MODEs will also need to be considered.  It should work.

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

ChangeLog
ircd/channel.c

index 69883349f904962351451a6886ea00410a423ec7..62c40e7be2d64dbf68ee4ed502b8df55e1db8174 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2000-10-24  Kevin L. Mitchell  <klmitch@mit.edu>
+
+       * ircd/channel.c: ok, now last mode rules; mode +ps will always
+       result in +s (and won't send a mode if the channel is already +s);
+       mode +sp will always result in +p; -n+n on a +n channel results in
+       no mode change; -n+n on a -n channel results in a +n mode change;
+       etc.
+
 2000-10-23  Kevin L. Mitchell  <klmitch@mit.edu>
 
        * ircd/channel.c: add "add" and "del" elements to ParseState to
index 9c4c31d8165368be8ef3313768bdb38a4f296b24..fcb4661f4284ba3d4384bcbe900775b4a2baa3e4 100644 (file)
@@ -3691,12 +3691,6 @@ 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) ||
-                                  (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 */
   if (state->flags & (MODE_PARSE_NOTOPER | MODE_PARSE_NOTMEMBER)) {
     send_notoper(state);
@@ -3707,31 +3701,24 @@ mode_parse_mode(struct ParseState *state, int *flag_p)
     return;
 
   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 */
-  }
+    state->add |= flag_p[0];
+    state->del &= ~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 */
+    if (flag_p[0] & MODE_SECRET) {
       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 */
+    } else if (flag_p[0] & MODE_PRIVATE) {
       state->add &= ~MODE_SECRET;
-    if (state->chptr->mode.mode & MODE_SECRET) /* then channel modes */
       state->del |= MODE_SECRET;
+    }
+  } else {
+    state->add &= ~flag_p[0];
+    state->del |= flag_p[0];
   }
 
   assert(0 == (state->add & state->del));
+  assert((MODE_SECRET | MODE_PRIVATE) !=
+        (state->add & (MODE_SECRET | MODE_PRIVATE)));
 }
 
 /*
@@ -3761,6 +3748,7 @@ mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr,
   };
   int i;
   int *flag_p;
+  unsigned int t_mode;
   char *modestr;
   struct ParseState state;
 
@@ -3875,17 +3863,25 @@ 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);
+  t_mode = state.chptr->mode.mode;
 
-  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 & t_mode) { /* delete any modes to be deleted... */
+    modebuf_mode(state.mbuf, MODE_DEL | (state.del & t_mode));
+
+    t_mode &= ~state.del;
+  }
+  if (state.add & ~t_mode) { /* add any modes to be added... */
+    modebuf_mode(state.mbuf, MODE_ADD | (state.add & ~t_mode));
 
-    if (state.del & MODE_INVITEONLY) /* clear invites away if needed */
+    t_mode |= state.add;
+  }
+
+  if (state.flags & MODE_PARSE_SET) { /* set the channel modes */
+    if ((state.chptr->mode.mode & MODE_INVITEONLY) &&
+       !(t_mode & MODE_INVITEONLY))
       mode_invite_clear(state.chptr);
+
+    state.chptr->mode.mode = t_mode;
   }
 
   if (state.flags & MODE_PARSE_WIPEOUT) {