Explorar el Código

* Copied private() check to has_op() for irc.mod
* Fixed some MODE +o conditions where cookies were not used
* Added cmd_mop <#chan>
* Misc code fixes
* Added commented out original egg queue code


svn: 293

Bryan Drewery hace 22 años
padre
commit
efef2c5e0a
Se han modificado 4 ficheros con 375 adiciones y 79 borrados
  1. 45 61
      src/mod/irc.mod/cmdsirc.c
  2. 5 10
      src/mod/irc.mod/irc.c
  3. 2 1
      src/mod/irc.mod/irc.h
  4. 323 7
      src/mod/irc.mod/mode.c

+ 45 - 61
src/mod/irc.mod/cmdsirc.c

@@ -33,7 +33,11 @@ static struct chanset_t *get_channel(int idx, char *chname)
 static int has_op(int idx, struct chanset_t *chan)
 {
   get_user_flagrec(dcc[idx].user, &user, chan->dname);
-  if (chan_op(user) || (glob_op(user) && !chan_deop(user)))
+  if (private(user, chan, PRIV_OP)) {
+    dprintf(idx, "No such channel.\n");
+    return 0;
+  }
+  if (chk_op(user, chan))
     return 1;
   dprintf(idx, "You are not a channel op on %s.\n", chan->dname);
   return 0;
@@ -77,11 +81,6 @@ static void cmd_act(struct userrec *u, int idx, char *par)
 
   get_user_flagrec(dcc[idx].user, &user, chan->dname);
 
-  if (private(user, chan, PRIV_OP)) {
-    dprintf(idx, "No such channel.\n");
-    return;
-  }
-
   m = ismember(chan, botname);
   if (!m) {
     dprintf(idx, "Cannot say to %s: I'm not on that channel.\n", chan->dname);
@@ -132,10 +131,6 @@ static void cmd_say(struct userrec *u, int idx, char *par)
 
   get_user_flagrec(dcc[idx].user, &user, chan->dname);
 
-  if (private(user, chan, PRIV_OP)) {
-    dprintf(idx, "No such channel.\n");
-    return;
-  }
   m = ismember(chan, botname);
   if (!m) {
     dprintf(idx, "Cannot say to %s: I'm not on that channel.\n", chan->dname);
@@ -408,28 +403,6 @@ static void cmd_devoice(struct userrec *u, int idx, char *par)
   }
 
 }
-void do_op(char *nick, struct chanset_t *chan, int force)
-{
-  memberlist *m;
-
-  m = ismember(chan, nick);
-
-  if (!m) return;
-
-//  if (chan_hasop(m)) return;  
-
-  if (!force && chan_hasop(m)) 
-    return; 
-
-  if (channel_fastop(chan)) {
-    add_mode(chan, '+', 'o', nick);
-  } else {
-    char *tmp = nmalloc(strlen(chan->name) + 200);
-    makeopline(chan, nick, tmp);
-    dprintf(DP_MODE, tmp);
-    nfree(tmp);
-  }
-}
 
 static void cmd_op(struct userrec *u, int idx, char *par)
 {
@@ -594,9 +567,10 @@ Context;
   chanbots = nmalloc(chan->channel.members * sizeof(memberlist *));
   bzero(chanbots, chan->channel.members * sizeof(memberlist *));
 
-Context;
+ContextNote("!mdop!");
   for (m = chan->channel.member; m; m = m->next)
     if (m->flags & CHANOP) {
+      ContextNote(m->nick);
       if (!m->user)
 	targets[targetcount++] = m;
       else if (((m->user->flags & (USER_BOT | USER_OP)) == (USER_BOT | USER_OP))
@@ -988,11 +962,6 @@ static void cmd_getkey(struct userrec *u, int idx, char *par)
 
   get_user_flagrec(dcc[idx].user, &user, chan->dname);
 
-  if (private(user, chan, PRIV_OP)) {
-    dprintf(idx, "No such channel.\n");
-    return;
-  }
-
   if (!glob_op(user) && !chan_op(user)) {
     dprintf(idx, "You do not have access for %s\n");
     return;
@@ -1012,6 +981,43 @@ static void cmd_getkey(struct userrec *u, int idx, char *par)
   dprintf(idx, "\n");
 }
 
+static void cmd_mop(struct userrec *u, int idx, char *par)
+{
+  struct chanset_t *chan;
+  memberlist *m;
+  int found = 0;
+
+  if (par[0] && (strchr(CHANMETA, par[0]) != NULL)) {
+    char *chname = newsplit(&par);
+    chan = get_channel(idx, chname);
+  } else
+    chan = get_channel(idx, "");
+
+  if (!chan || !has_op(idx, chan))
+    return;
+
+  putlog(LOG_CMDS, "*", "#%s# (%s) mop %s", dcc[idx].nick, chan->dname, par);
+
+  get_user_flagrec(dcc[idx].user, &user, chan->dname);
+
+  for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
+    if (!m->user) {
+      char s[256];
+      sprintf(s, STR("%s!%s"), m->nick, m->userhost);
+      m->user = get_user_by_host(s);
+    }
+    get_user_flagrec(m->user, &victim, chan->dname);
+    if (!chan_hasop(m) && !glob_bot(victim) && chk_op(victim, chan)) {
+      found++;
+      dprintf(idx, "Gave op to %s on %s\n", m->nick, chan->dname);
+      do_op(m->nick, chan, 0);
+    }
+  }
+  if (!found)
+    dprintf(idx, "No one to op on %s\n", chan->dname);
+}
+
+
 static void cmd_find(struct userrec *u, int idx, char *par)
 {
   struct chanset_t *chan;
@@ -1174,11 +1180,6 @@ static void cmd_channel(struct userrec *u, int idx, char *par)
 
   get_user_flagrec(dcc[idx].user, &user, chan->dname);
 
-  if (private(user, chan, PRIV_OP)) {
-    dprintf(idx, "No such channel.\n");
-    return;
-  }
-
   putlog(LOG_CMDS, "*", "#%s# (%s) channel", dcc[idx].nick, chan->dname);
   strncpyz(s, getchanmode(chan), sizeof s);
   if (channel_pending(chan)) {
@@ -1335,11 +1336,6 @@ static void cmd_topic(struct userrec *u, int idx, char *par)
 
   get_user_flagrec(dcc[idx].user, &user, chan->dname);
 
-  if (private(user, chan, PRIV_OP)) {
-    dprintf(idx, "No such channel.\n");
-    return;
-  }
-
   if (!channel_active(chan)) {
     dprintf(idx, "I'm not on %s right now!\n", chan->dname);
     return;
@@ -1373,10 +1369,6 @@ static void cmd_resetbans(struct userrec *u, int idx, char *par)
 
   get_user_flagrec(dcc[idx].user, &user, chan->dname);
 
-  if (private(user, chan, PRIV_OP)) {
-    dprintf(idx, "No such channel.\n");
-    return;
-  }
   putlog(LOG_CMDS, "*", "#%s# (%s) resetbans", dcc[idx].nick, chan->dname);
   dprintf(idx, "Resetting bans on %s...\n", chan->dname);
   resetbans(chan);
@@ -1393,11 +1385,6 @@ static void cmd_resetexempts(struct userrec *u, int idx, char *par)
 
   get_user_flagrec(dcc[idx].user, &user, chan->dname);
 
-
-  if (private(user, chan, PRIV_OP)) {
-    dprintf(idx, "No such channel.\n");
-    return;
-  }
   putlog(LOG_CMDS, "*", "#%s# (%s) resetexempts", dcc[idx].nick, chan->dname);
   dprintf(idx, "Resetting exempts on %s...\n", chan->dname);
   resetexempts(chan);
@@ -1413,10 +1400,6 @@ static void cmd_resetinvites(struct userrec *u, int idx, char *par)
     return;
   get_user_flagrec(dcc[idx].user, &user, chan->dname);
 
-  if (private(user, chan, PRIV_OP)) {
-    dprintf(idx, "No such channel.\n");
-    return;
-  }
   putlog(LOG_CMDS, "*", "#%s# (%s) resetinvites", dcc[idx].nick, chan->dname);
   dprintf(idx, "Resetting resetinvites on %s...\n", chan->dname);
   resetinvites(chan);
@@ -1636,6 +1619,7 @@ static cmd_t irc_dcc[] =
   {"kick",		"o|o",	 (Function) cmd_kick,		NULL},
   {"kickban",		"o|o",	 (Function) cmd_kickban,	NULL},
   {"mdop",              "n|n",	 (Function) cmd_mdop,		NULL},
+  {"mop",		"n|m",	 (Function) cmd_mop,		NULL},
   {"msg",		"o",	 (Function) cmd_msg,		NULL},
   {"op",		"o|o",	 (Function) cmd_op,		NULL},
   {"reset",		"m|m",	 (Function) cmd_reset,		NULL},

+ 5 - 10
src/mod/irc.mod/irc.c

@@ -297,15 +297,10 @@ Context;
       putlog(LOG_GETIN, "*", STR("opreq from %s/%s on %s - I'm getting userlist right now"), botnick, nick, chan->dname);
       return;
     }
-    if (channel_fastop(chan) || channel_take(chan) || 0) {
-      add_mode(chan, '+', 'o', nick);
-    } else {
-      tmp = nmalloc(strlen(chan->dname) + 200);
-      makeopline(chan, nick, tmp);
-      dprintf(DP_MODE, tmp);
-      mem->flags |= SENTOP;
-      nfree(tmp);
-    }
+
+    do_op(nick, chan, 1);
+    mem->flags |= SENTOP;
+
     putlog(LOG_GETIN, "*", STR("opreq from %s/%s on %s - Opped"), botnick, nick, chan->dname);
   } else if (what[0] == 'i') {
 Context;
@@ -1408,7 +1403,7 @@ static void flush_modes()
 	m->flags &= ~FULL_DELAY;
         if (chan_sentop(m)) {
           m->flags &= ~SENTOP;
-          add_mode(chan, '+', 'o', m->nick);
+          do_op(m->nick, chan, 0);
         }
         if (chan_sentvoice(m)) {
           m->flags &= ~SENTVOICE;

+ 2 - 1
src/mod/irc.mod/irc.h

@@ -32,7 +32,8 @@ static void flush_mode(struct chanset_t *, int);
 				       (chan)->invites, global_invites, 'I')
 
 static void detect_autokick(char *, char *, struct chanset_t *, char *);
-static int target_priority(struct chanset_t *, memberlist *, int);
+/* static int target_priority(struct chanset_t *, memberlist *, int); */
+static void do_op(char *, struct chanset_t *, int);
 static void request_op(struct chanset_t *);
 static void request_in(struct chanset_t *);
 static void reset_chan_info(struct chanset_t *);

+ 323 - 7
src/mod/irc.mod/mode.c

@@ -21,6 +21,27 @@ static int reversing = 0;
 
 static struct flag_record user   = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
 static struct flag_record victim = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
+
+static void do_op(char *nick, struct chanset_t *chan, int force)
+{
+  memberlist *m = ismember(chan, nick);
+
+  if (!m) return;
+
+  if (!force && chan_hasop(m))
+    return;
+
+  if (channel_fastop(chan) || channel_take(chan)) {
+    add_mode(chan, '+', 'o', nick);
+  } else {
+    char *tmp = nmalloc(strlen(chan->name) + 200);
+    makeopline(chan, nick, tmp);
+    dprintf(DP_MODE, tmp);
+    nfree(tmp);
+  }
+}
+#define NEW_ADDMODE 1
+#ifdef NEW_ADDMODE
 void dequeue_op_deop(struct chanset_t * chan);
 
 static void flush_mode(struct chanset_t *chan, int pri)
@@ -428,7 +449,301 @@ putlog(LOG_DEBUG, "@", "add_mode for %s, %c%c %s", chan->dname, plus, mode, op);
   if (modes < 1)
     flush_mode(chan, NORMAL);		/* Full buffer! Flush modes. */
 }
+#else /* OLD SHIT */
+
+static void flush_mode(struct chanset_t *chan, int pri)
+{
+  char *p, out[512], post[512];
+  size_t postsize = sizeof(post);
+  int i, plus = 2;              /* 0 = '-', 1 = '+', 2 = none */
+putlog(LOG_DEBUG, "@", "DEBUG: flushing modes for %s", chan->dname);
+  p = out;
+  post[0] = 0, postsize--;
+
+  if (chan->mns[0]) {
+    *p++ = '-', plus = 0;
+    for (i = 0; i < strlen(chan->mns); i++)
+      *p++ = chan->mns[i];
+    chan->mns[0] = 0;
+  }
+
+  if (chan->pls[0]) {
+    *p++ = '+', plus = 1;
+    for (i = 0; i < strlen(chan->pls); i++)
+      *p++ = chan->pls[i];
+    chan->pls[0] = 0;
+  }
+
+  chan->bytes = 0;
+  chan->compat = 0;
 
+  /* +k or +l ? */
+  if (chan->key && !chan->rmkey) {
+    if (plus != 1) {
+      *p++ = '+', plus = 1;
+    }
+    *p++ = 'k';
+
+    postsize -= egg_strcatn(post, chan->key, sizeof(post));
+    postsize -= egg_strcatn(post, " ", sizeof(post));
+
+    nfree(chan->key), chan->key = NULL;
+  }
+
+  /* max +l is signed 2^32 on IRCnet at least... so makesure we've got at least
+   * a 13 char buffer for '-2147483647 \0'. We'll be overwriting the existing
+   * terminating null in 'post', so makesure postsize >= 12.
+   */
+  if (chan->limit != 0 && postsize >= 12) {
+    if (plus != 1) {
+      *p++ = '+', plus = 1;
+    }
+    *p++ = 'l';
+
+    /* 'sizeof(post) - 1' is used because we want to overwrite the old null */
+    postsize -=
+      sprintf(&post[(sizeof(post) - 1) - postsize], "%d ", chan->limit);
+
+    chan->limit = 0;
+  }
+
+  /* -k ? */
+  if (chan->rmkey) {
+    if (plus) {
+      *p++ = '-', plus = 0;
+    }
+    *p++ = 'k';
+
+    postsize -= egg_strcatn(post, chan->rmkey, sizeof(post));
+    postsize -= egg_strcatn(post, " ", sizeof(post));
+
+    nfree(chan->rmkey), chan->rmkey = NULL;
+  }
+
+  /* Do -{b,e,I} before +{b,e,I} to avoid the server ignoring overlaps */
+  for (i = 0; i < modesperline; i++) {
+    if ((chan->cmode[i].type & MINUS) && postsize > strlen(chan->cmode[i].op)) {
+      if (plus) {
+        *p++ = '-', plus = 0;
+      }
+
+      *p++ = ((chan->cmode[i].type & BAN) ? 'b' :
+              ((chan->cmode[i].type & CHOP) ? 'o' :
+              ((chan->cmode[i].type & EXEMPT) ? 'e' :
+              ((chan->cmode[i].type & INVITE) ? 'I' : 'v'))));
+
+      postsize -= egg_strcatn(post, chan->cmode[i].op, sizeof(post));
+      postsize -= egg_strcatn(post, " ", sizeof(post));
+
+      nfree(chan->cmode[i].op), chan->cmode[i].op = NULL;
+      chan->cmode[i].type = 0;
+    }
+  }
+
+  /* now do all the + modes... */
+  for (i = 0; i < modesperline; i++) {
+    if ((chan->cmode[i].type & PLUS) && postsize > strlen(chan->cmode[i].op)) {
+      if (plus != 1) {
+        *p++ = '+', plus = 1;
+      }
+
+      *p++ = ((chan->cmode[i].type & BAN) ? 'b' :
+              ((chan->cmode[i].type & CHOP) ? 'o' :
+              ((chan->cmode[i].type & EXEMPT) ? 'e' :
+              ((chan->cmode[i].type & INVITE) ? 'I' : 'v'))));
+
+      postsize -= egg_strcatn(post, chan->cmode[i].op, sizeof(post));
+      postsize -= egg_strcatn(post, " ", sizeof(post));
+
+      nfree(chan->cmode[i].op), chan->cmode[i].op = NULL;
+      chan->cmode[i].type = 0;
+    }
+  }
+
+  /* remember to terminate the buffer ('out')... */
+  *p = 0;
+
+  if (post[0]) {
+    /* remove the trailing space... */
+    size_t index = (sizeof(post) - 1) - postsize;
+
+    if (index > 0 && post[index - 1] == ' ')
+      post[index - 1] = 0;
+
+    egg_strcatn(out, " ", sizeof(out));
+    egg_strcatn(out, post, sizeof(out));
+  }
+  if (out[0]) {
+    if (pri == QUICK)
+      dprintf(DP_MODE, "MODE %s %s\n", chan->name, out);
+    else
+      dprintf(DP_SERVER, "MODE %s %s\n", chan->name, out);
+  }
+}
+
+/* Queue a channel mode change
+ */
+static void real_add_mode(struct chanset_t *chan,
+                          char plus, char mode, char *op)
+{
+  int i, type, modes, l;
+  masklist *m;
+  memberlist *mx;
+  char s[21];
+
+  /* Some IRCds do not allow halfops to set certian modes. The modes halfops
+   * are not allowed to set can be changed in chan.h. */
+  if (!me_op(chan))
+    return;
+putlog(LOG_DEBUG, "@", "add_mode for %s, %c%c %s", chan->dname, plus, mode, op);
+
+  if (mode == 'o' || mode == 'h' || mode == 'v') {
+    mx = ismember(chan, op);
+    if (!mx)
+      return;
+    if (plus == '-' && mode == 'o') {
+      if (chan_sentdeop(mx) || !chan_hasop(mx))
+        return;
+      mx->flags |= SENTDEOP;
+    }
+    if (plus == '+' && mode == 'o') {
+      if (chan_sentop(mx) || chan_hasop(mx))
+        return;
+      mx->flags |= SENTOP;
+    }
+    if (plus == '-' && mode == 'v') {
+      if (chan_sentdevoice(mx) || !chan_hasvoice(mx))
+        return;
+      mx->flags |= SENTDEVOICE;
+    }
+    if (plus == '+' && mode == 'v') {
+      if (chan_sentvoice(mx) || chan_hasvoice(mx))
+        return;
+      mx->flags |= SENTVOICE;
+    }
+  }
+
+  if (chan->compat == 0) {
+    if (mode == 'e' || mode == 'I')
+      chan->compat = 2;
+    else
+      chan->compat = 1;
+  } else if (mode == 'e' || mode == 'I') {
+    if (prevent_mixing && chan->compat == 1)
+      flush_mode(chan, NORMAL);
+  } else if (prevent_mixing && chan->compat == 2)
+    flush_mode(chan, NORMAL);
+
+  if (mode == 'o' || mode == 'b' || mode == 'v' || mode == 'e' || mode == 'I') {
+    type = (plus == '+' ? PLUS : MINUS) | (mode == 'o' ? CHOP : (mode == 'b' ? 
+            BAN : (mode == 'v' ? VOICE : (mode == 'e' ? EXEMPT : INVITE))));
+    /*
+     * FIXME: Some networks remove overlapped bans,
+     *        IRCnet does not (poptix/drummer)
+     *
+     * Note:  On IRCnet ischanXXX() should be used, otherwise isXXXed().
+     */
+    if ((plus == '-' && ((mode == 'b' && !ischanban(chan, op)) ||
+        (mode == 'e' && !ischanexempt(chan, op)) ||
+        (mode == 'I' && !ischaninvite(chan, op)))) || (plus == '+' &&
+        ((mode == 'b' && ischanban(chan, op)) ||
+        (mode == 'e' && ischanexempt(chan, op)) ||
+        (mode == 'I' && ischaninvite(chan, op)))))
+      return;
+
+    /* If there are already max_bans bans, max_exempts exemptions,
+     * max_invites invitations or max_modes +b/+e/+I modes on the
+     * channel, don't try to add one more.
+     */
+    if (plus == '+' && (mode == 'b' || mode == 'e' || mode == 'I')) {
+      int bans = 0, exempts = 0, invites = 0;
+
+      for (m = chan->channel.ban; m && m->mask[0]; m = m->next)
+        bans++;
+      if ((mode == 'b') && (bans >= max_bans))
+        return;
+
+      for (m = chan->channel.exempt; m && m->mask[0]; m = m->next)
+        exempts++;
+      if ((mode == 'e') && (exempts >= max_exempts))
+        return;
+
+      for (m = chan->channel.invite; m && m->mask[0]; m = m->next)
+        invites++;
+      if ((mode == 'I') && (invites >= max_invites))
+        return;
+
+      if (bans + exempts + invites >= max_modes)
+        return;
+    }
+
+    /* op-type mode change */
+    for (i = 0; i < modesperline; i++)
+      if (chan->cmode[i].type == type && chan->cmode[i].op != NULL &&
+          !rfc_casecmp(chan->cmode[i].op, op))
+        return;                 /* Already in there :- duplicate */
+    l = strlen(op) + 1;
+    if (chan->bytes + l > mode_buf_len)
+      flush_mode(chan, NORMAL);
+    for (i = 0; i < modesperline; i++)
+      if (chan->cmode[i].type == 0) {
+        chan->cmode[i].type = type;
+        chan->cmode[i].op = (char *) channel_malloc(l);
+        chan->bytes += l;       /* Add 1 for safety */
+        strcpy(chan->cmode[i].op, op);
+        break;
+      }
+  }
+
+  /* +k ? store key */
+  else if (plus == '+' && mode == 'k') {
+    if (chan->key)
+      nfree(chan->key);
+    chan->key = (char *) channel_malloc(strlen(op) + 1);
+    if (chan->key)
+      strcpy(chan->key, op);
+  }
+  /* -k ? store removed key */
+  else if (plus == '-' && mode == 'k') {
+    if (chan->rmkey)
+      nfree(chan->rmkey);
+    chan->rmkey = (char *) channel_malloc(strlen(op) + 1);
+    if (chan->rmkey)
+      strcpy(chan->rmkey, op);
+  }
+  /* +l ? store limit */
+  else if (plus == '+' && mode == 'l')
+    chan->limit = atoi(op);
+  else {
+    /* Typical mode changes */
+    if (plus == '+')
+      strcpy(s, chan->pls);
+    else
+      strcpy(s, chan->mns);
+    if (!strchr(s, mode)) {
+      if (plus == '+') {
+        chan->pls[strlen(chan->pls) + 1] = 0;
+        chan->pls[strlen(chan->pls)] = mode;
+      } else {
+        chan->mns[strlen(chan->mns) + 1] = 0;
+        chan->mns[strlen(chan->mns)] = mode;
+      }
+    }
+  }
+  modes = modesperline;         /* Check for full buffer. */
+  for (i = 0; i < modesperline; i++)
+    if (chan->cmode[i].type)
+      modes--;
+  if (include_lk && chan->limit)
+    modes--;
+  if (include_lk && chan->rmkey)
+    modes--;
+  if (include_lk && chan->key)
+    modes--;
+  if (modes < 1)
+    flush_mode(chan, NORMAL);   /* Full buffer! Flush modes. */
+}
+#endif /* NEW_ADDMODE */
 
 /*
  *    Mode parsing functions
@@ -500,11 +815,12 @@ static void got_op(struct chanset_t *chan, char *nick, char *from,
 	   nick[0]) {
     /* Channis is +bitch, and the opper isn't a global master or a bot */
     /* deop if they are +d or it is +bitch */
-    if (chk_deop(victim, chan) ||
-        (channel_bitch(chan) && !chk_op(victim, chan))		/* chk_op covers +private */
-       ) {
-      if (target_priority(chan, m, 1))
+    if ( chk_deop(victim, chan) ||
+        (channel_bitch(chan) && !chk_op(victim, chan)) ) {	/* chk_op covers +private */
+      /* if (target_priority(chan, m, 1)) */
+//        dprintf(DP_MODE, "MODE %s -o %s\n", chan->dname, who);
         add_mode(chan, '-', 'o', who);
+flush_mode(chan, QUICK);
     } else if (reversing) {
       add_mode(chan, '-', 'o', who);
     }
@@ -592,7 +908,7 @@ static void got_deop(struct chanset_t *chan, char *nick, char *from,
 	((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) ||
 	 !channel_bitch(chan)))
       /* Then we'll bless the victim */
-      add_mode(chan, '+', 'o', who);
+      do_op(who, chan, 0);
   }
 
   if (!nick[0])
@@ -660,8 +976,8 @@ static void got_ban(struct chanset_t *chan, char *nick, char *from, char *who)
 	  get_user_flagrec(u, &victim, chan->dname);
           if (chk_op(victim, chan) && !chan_master(user) && !glob_master(user) && 
              !glob_bot(user) && !isexempted(chan, s1)) {
-            if (target_priority(chan, m, 0))
-              add_mode(chan, '-', 'b', who);
+            /* if (target_priority(chan, m, 0)) */
+            add_mode(chan, '-', 'b', who);
             return;
 	  }
 	}