Author: Kev <klmitch@mit.edu>
[ircu2.10.12-pk.git] / ircd / channel.c
index 9c4c31d8165368be8ef3313768bdb38a4f296b24..6c974c62eaee51ed27e8b3988a19b3b132c97811 100644 (file)
@@ -25,6 +25,7 @@
 #include "ircd.h"
 #include "ircd_alloc.h"
 #include "ircd_chattr.h"
+#include "ircd_log.h"
 #include "ircd_reply.h"
 #include "ircd_snprintf.h"
 #include "ircd_string.h"
@@ -2828,13 +2829,11 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all)
                           addbuf, remstr, addstr,
                           mbuf->mb_channel->creationtime);
 
-#ifdef OPATH
-    if (mbuf->mb_dest & MODEBUF_DEST_LOG) {
-      write_log(OPATH, "%Tu %#C OPMODE %H %s%s%s%s%s%s\n", TStime(),
-               mbuf->mb_source, mbuf->mb_channel, rembuf_i ? "-" : "", rembuf,
+    if (mbuf->mb_dest & MODEBUF_DEST_LOG)
+      log_write(LS_OPERMODE, L_INFO, LOG_NOSNOTICE,
+               "%#C OPMODE %H %s%s%s%s%s%s", mbuf->mb_source,
+               mbuf->mb_channel, rembuf_i ? "-" : "", rembuf,
                addbuf_i ? "+" : "", addbuf, remstr, addstr);
-    }
-#endif
 
     if (mbuf->mb_dest & MODEBUF_DEST_CHANNEL)
       sendcmdto_channel_butserv(app_source, CMD_MODE, mbuf->mb_channel,
@@ -3691,12 +3690,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 +3700,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 +3747,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 +3862,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));
+
+    t_mode |= state.add;
+  }
 
-    if (state.del & MODE_INVITEONLY) /* clear invites away if needed */
+  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) {
@@ -3947,46 +3942,56 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags)
 
   assert(0 != jbuf);
 
-  if (chan) {
-    if (jbuf->jb_type == JOINBUF_TYPE_PART ||
-       jbuf->jb_type == JOINBUF_TYPE_PARTALL) {
-      /* Send notification to channel */
-      if (!(flags & CHFL_ZOMBIE))
-       sendcmdto_channel_butserv(jbuf->jb_source, CMD_PART, chan,
-                                 (flags & CHFL_BANNED || !jbuf->jb_comment) ?
-                                 ":%H" : "%H :%s", chan, jbuf->jb_comment);
-      else if (MyUser(jbuf->jb_source))
-       sendcmdto_one(jbuf->jb_source, CMD_PART, jbuf->jb_source,
-                     (flags & CHFL_BANNED || !jbuf->jb_comment) ?
-                     ":%H" : "%H :%s", chan, jbuf->jb_comment);
-      /* XXX: Shouldn't we send a PART here anyway? */
-      /* to users on the channel?  Why?  From their POV, the user isn't on
-       * the channel anymore anyway.  We don't send to servers until below,
-       * when we gang all the channel parts together.  Note that this is
-       * exactly the same logic, albeit somewhat more concise, as was in
-       * the original m_part.c */
-
-      if (jbuf->jb_type == JOINBUF_TYPE_PARTALL ||
-         IsLocalChannel(chan->chname)) /* got to remove user here */
-       remove_user_from_channel(jbuf->jb_source, chan);
-    } else {
-      /* Add user to channel */
-      add_user_to_channel(chan, jbuf->jb_source, flags);
+  if (!chan) {
+    if (jbuf->jb_type == JOINBUF_TYPE_JOIN)
+      sendcmdto_serv_butone(jbuf->jb_source, CMD_JOIN, jbuf->jb_connect, "0");
 
-      /* Send the notification to the channel */
-      sendcmdto_channel_butserv(jbuf->jb_source, CMD_JOIN, chan, ":%H", chan);
+    return;
+  }
 
-      /* send an op, too, if needed */
-      if (!MyUser(jbuf->jb_source) && jbuf->jb_type == JOINBUF_TYPE_CREATE &&
-         !IsModelessChannel(chan->chname))
-       sendcmdto_channel_butserv(jbuf->jb_source, CMD_MODE, chan, "%H +o %C",
-                                 chan, jbuf->jb_source);
-    }
+  if (jbuf->jb_type == JOINBUF_TYPE_PART ||
+      jbuf->jb_type == JOINBUF_TYPE_PARTALL) {
+    /* Send notification to channel */
+    if (!(flags & CHFL_ZOMBIE))
+      sendcmdto_channel_butserv(jbuf->jb_source, CMD_PART, chan,
+                               (flags & CHFL_BANNED || !jbuf->jb_comment) ?
+                               ":%H" : "%H :%s", chan, jbuf->jb_comment);
+    else if (MyUser(jbuf->jb_source))
+      sendcmdto_one(jbuf->jb_source, CMD_PART, jbuf->jb_source,
+                   (flags & CHFL_BANNED || !jbuf->jb_comment) ?
+                   ":%H" : "%H :%s", chan, jbuf->jb_comment);
+    /* XXX: Shouldn't we send a PART here anyway? */
+    /* to users on the channel?  Why?  From their POV, the user isn't on
+     * the channel anymore anyway.  We don't send to servers until below,
+     * when we gang all the channel parts together.  Note that this is
+     * exactly the same logic, albeit somewhat more concise, as was in
+     * the original m_part.c */
+
+    if (jbuf->jb_type == JOINBUF_TYPE_PARTALL ||
+       IsLocalChannel(chan->chname)) /* got to remove user here */
+      remove_user_from_channel(jbuf->jb_source, chan);
+  } else {
+    /* Add user to channel */
+    add_user_to_channel(chan, jbuf->jb_source, flags);
+
+    /* send notification to all servers */
+    if (jbuf->jb_type != JOINBUF_TYPE_CREATE && !IsLocalChannel(chan->chname))
+      sendcmdto_serv_butone(jbuf->jb_source, CMD_JOIN, jbuf->jb_connect,
+                           "%H %Tu", chan, chan->creationtime);
+
+    /* Send the notification to the channel */
+    sendcmdto_channel_butserv(jbuf->jb_source, CMD_JOIN, chan, ":%H", chan);
 
-    if (jbuf->jb_type == JOINBUF_TYPE_PARTALL || IsLocalChannel(chan->chname))
-      return; /* don't send to remote */
+    /* send an op, too, if needed */
+    if (!MyUser(jbuf->jb_source) && jbuf->jb_type == JOINBUF_TYPE_CREATE &&
+       !IsModelessChannel(chan->chname))
+      sendcmdto_channel_butserv(jbuf->jb_source, CMD_MODE, chan, "%H +o %C",
+                               chan, jbuf->jb_source);
   }
 
+  if (jbuf->jb_type == JOINBUF_TYPE_PARTALL || IsLocalChannel(chan->chname))
+    return; /* don't send to remote */
+
   /* figure out if channel name will cause buffer to be overflowed */
   len = chan ? strlen(chan->chname) + 1 : 2;
   if (jbuf->jb_strlen + len > IRC_BUFSIZE)
@@ -4011,7 +4016,8 @@ joinbuf_flush(struct JoinBuf *jbuf)
   int chanlist_i = 0;
   int i;
 
-  if (!jbuf->jb_count || jbuf->jb_type == JOINBUF_TYPE_PARTALL)
+  if (!jbuf->jb_count || jbuf->jb_type == JOINBUF_TYPE_PARTALL ||
+      jbuf->jb_type == JOINBUF_TYPE_JOIN)
     return 0; /* no joins to process */
 
   for (i = 0; i < jbuf->jb_count; i++) { /* build channel list */
@@ -4026,18 +4032,12 @@ joinbuf_flush(struct JoinBuf *jbuf)
   }
 
   jbuf->jb_count = 0; /* reset base counters */
-  jbuf->jb_strlen = ((jbuf->jb_type == JOINBUF_TYPE_JOIN ||
-                     jbuf->jb_type == JOINBUF_TYPE_PART ?
+  jbuf->jb_strlen = ((jbuf->jb_type == JOINBUF_TYPE_PART ?
                      STARTJOINLEN : STARTCREATELEN) +
                     (jbuf->jb_comment ? strlen(jbuf->jb_comment) + 2 : 0));
 
   /* and send the appropriate command */
   switch (jbuf->jb_type) {
-  case JOINBUF_TYPE_JOIN:
-    sendcmdto_serv_butone(jbuf->jb_source, CMD_JOIN, jbuf->jb_connect,
-                         "%s", chanlist);
-    break;
-
   case JOINBUF_TYPE_CREATE:
     sendcmdto_serv_butone(jbuf->jb_source, CMD_CREATE, jbuf->jb_connect,
                          "%s %Tu", chanlist, jbuf->jb_create);