Pārlūkot izejas kodu

Merge branch 'master' into 39-dynamic-roles

* master:
  Add back bot check in voicing. Lost in f6892d18a
  Reduce duplicate logic.
  Handle auto-op in check_expired_chanstuff.
  Consolidate some chk_autoop() logic.
  Fix backwards logic for applying invites in -dynamicinvites channels.
  Fix bot not auto-opping after just connecting.
  do_op: Don't try (and fail) to op right away with a delay.
  add_mode: Pass memberlist pointer if possible
Bryan Drewery 10 gadi atpakaļ
vecāks
revīzija
7448e9cecb

+ 3 - 0
doc/UPDATES.md

@@ -19,6 +19,9 @@
   * Fix binary compat issue causing ptrace permission errors on Linux 3.4+
   * Fix ban/exempt/invite masking not working with 10-char idents.
   * Fallback to ISON if the server falsely claims to support MONITOR.
+  * Fix bot not auto-opping after just connecting.
+  * Fix invites not being applied in -dynamicinvites channels when +i is set.
+  * Fix not handling auto-op in minutely channel rechecks.
 
 # 1.4.6
   * Disable demo TCL support by default to prevent confusion during build.

+ 2 - 2
src/flags.cc

@@ -476,9 +476,9 @@ real_chk_op(const struct flag_record fr, const struct chanset_t *chan, bool botb
 }
 
 int
-chk_autoop(struct userrec *user, const struct flag_record fr, const struct chanset_t *chan)
+chk_autoop(memberlist *m, const struct flag_record fr, const struct chanset_t *chan)
 {
-  if (glob_bot(fr) || !chan || u_pass_match(user, "-"))
+  if (glob_bot(fr) || !chan || !m->user || u_pass_match(m->user, "-"))
     return 0;
   if (!channel_take(chan) && !privchan(fr, chan, PRIV_OP) && chk_op(fr, chan) && !chk_deop(fr, chan)) {
     if (channel_autoop(chan) || chan_autoop(fr) || glob_autoop(fr))

+ 1 - 1
src/flags.h

@@ -175,7 +175,7 @@ char geticon(int);
 int privchan(const struct flag_record, const struct chanset_t *, int);
 #define chk_op(fr, chan) real_chk_op(fr, chan, 1)
 int real_chk_op(const struct flag_record, const struct chanset_t *, bool);
-int chk_autoop(struct userrec *, const struct flag_record, const struct chanset_t *);
+int chk_autoop(memberlist *, const struct flag_record, const struct chanset_t *);
 #define chk_deop(fr, chan) real_chk_deop(fr, chan, 1)
 int real_chk_deop(const struct flag_record, const struct chanset_t *, bool);
 #define chk_voice(fr, chan) (\

+ 8 - 8
src/mod/irc.mod/chan.cc

@@ -447,7 +447,7 @@ static void priority_do(struct chanset_t * chan, bool opsonly, int action, bool
             if ((action == PRIO_DEOP) && !chan_sentdeop(m)) {
               ++actions;
               ++sent;
-              add_mode(chan, '-', 'o', m->nick);
+              add_mode(chan, '-', 'o', m);
               if (!floodless && (actions >= ct || (n == 1 && sent > 20))) {
                 if (flush)
                   flush_mode(chan, QUICK);
@@ -894,7 +894,7 @@ static void refresh_ban_kick(struct chanset_t* chan, memberlist *m, const char *
     for (maskrec* b = cycle ? chan->bans : global_bans; b; b = b->next) {
       if (wild_match(b->mask, user) || match_cidr(b->mask, user)) {
         if ((chan->role & ROLE_DEOP) && chan_hasop(m))
-  	  add_mode(chan, '-', 'o', m->nick);	/* Guess it can't hurt.	*/
+          add_mode(chan, '-', 'o', m);	/* Guess it can't hurt.	*/
 	check_exemptlist(chan, user);
 	do_mask(chan, chan->channel.ban, b->mask, 'b');
 	b->lastactive = now;
@@ -1039,7 +1039,7 @@ static void recheck_invites(struct chanset_t *chan)
        * only) or invite is sticky.
        */
       if (!isinvited(chan, ir->mask) && ((!channel_dynamicinvites(chan) &&
-          !(chan->channel.mode & CHANINV)) || ir->flags & MASKREC_STICKY))
+          (chan->channel.mode & CHANINV)) || ir->flags & MASKREC_STICKY))
 	add_mode(chan, '+', 'I', ir->mask);
 	/* do_mask(chan, chan->channel.invite, ir->mask, 'I');*/
     }
@@ -1222,19 +1222,19 @@ static void check_this_member(struct chanset_t *chan, char *nick, struct flag_re
       (chk_deop(*fr, chan) ||
        (!loading && userlist && chan_bitch(chan) && !chk_op(*fr, chan)) ) ) {
     /* if (target_priority(chan, m, 1)) */
-      add_mode(chan, '-', 'o', m->nick);
-  } else if (!chan_hasop(m) && (chan->role & ROLE_OP) && chk_autoop(m->user, *fr, chan)) {
+      add_mode(chan, '-', 'o', m);
+  } else if (!chan_hasop(m) && (chan->role & ROLE_OP) && chk_autoop(m, *fr, chan)) {
     do_op(m, chan, 1, 0);
   }
   if (dovoice(chan)) {
     if (chan_hasvoice(m) && !chan_hasop(m)) {
       /* devoice +q users .. */
       if (chk_devoice(*fr) || (channel_voicebitch(chan) && !chk_voice(*fr, chan)))
-        add_mode(chan, '-', 'v', m->nick);
+        add_mode(chan, '-', 'v', m);
     } else if (!chan_hasvoice(m) && !chan_hasop(m)) {
       /* voice +v users */
       if (chk_voice(*fr, chan)) {
-        add_mode(chan, '+', 'v', m->nick);
+        add_mode(chan, '+', 'v', m);
         if (m->flags & EVOICE)
           m->flags &= ~EVOICE;
       }
@@ -2887,7 +2887,7 @@ static int gotjoin(char *from, char *chname)
           /* Autoop */
           if (!chan_hasop(m) && 
                (op || 
-               ((chan->role & ROLE_OP) && chk_autoop(m->user, fr, chan)))) {
+               ((chan->role & ROLE_OP) && chk_autoop(m, fr, chan)))) {
             do_op(m, chan, 1, 0);
           }
 

+ 5 - 5
src/mod/irc.mod/cmdsirc.cc

@@ -305,8 +305,8 @@ static void cmd_kickban(int idx, char *par)
       dprintf(idx, "%s is permanently exempted!\n", nick);
       return;
     }
-    if (m->flags & CHANOP)
-      add_mode(chan, '-', 'o', m->nick);
+    if (chan_hasop(m))
+      add_mode(chan, '-', 'o', m);
     check_exemptlist(chan, s);
     switch (bantype) {
       case '@':
@@ -396,7 +396,7 @@ static void cmd_voice(int idx, char *par)
       dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
       return;
     }
-    add_mode(chan, '+', 'v', nick);
+    add_mode(chan, '+', 'v', m);
     dprintf(idx, "Gave voice to %s on %s\n", nick, chan->dname);
     next:;
     if (!all)
@@ -459,7 +459,7 @@ static void cmd_devoice(int idx, char *par)
     return;
   }
 
-  add_mode(chan, '-', 'v', nick);
+  add_mode(chan, '-', 'v', m);
   dprintf(idx, "Devoiced %s on %s\n", nick, chan->dname);
   next:;
   if (!all)
@@ -1041,7 +1041,7 @@ static void cmd_deop(int idx, char *par)
       if (all) goto next;  
       return;
     }
-    add_mode(chan, '-', 'o', nick);
+    add_mode(chan, '-', 'o', m);
     dprintf(idx, "Deopped %s on %s.\n", nick, chan->dname);
     next:;
     if (!all)

+ 22 - 17
src/mod/irc.mod/irc.cc

@@ -212,7 +212,7 @@ void set_devoice(struct chanset_t *chan, memberlist* m) {
 const char* punish_flooder(struct chanset_t* chan, memberlist* m, const char *reason) {
   if (channel_voice(chan) && chan->voice_moderate) {
     if (!chan_sentdevoice(m)) {
-      add_mode(chan, '-', 'v', m->nick);
+      add_mode(chan, '-', 'v', m);
       m->flags |= SENTDEVOICE;
       set_devoice(chan, m);
       return "devoicing";
@@ -1584,26 +1584,31 @@ check_expired_chanstuff(struct chanset_t *chan)
       }
 
       if (im_opped) {
-        if (dovoice(chan) && !loading) {      /* autovoice of +v users if bot is +y */
-          if (!chan_hasop(m) && !chan_hasvoice(m) && !chan_sentvoice(m)) {
+        if ((chan->role & (ROLE_OP|ROLE_VOICE)) && !loading && !chan_hasop(m)) {      /* autovoice of +v users if bot is +y */
+          get_user_flagrec(m->user, &fr, chan->dname, chan);
+
+          /* Autoop */
+          if ((chan->role & ROLE_OP) && !chan_sentop(m) && chk_autoop(m, fr, chan)) {
+            do_op(m, chan, 0, 0);
+          }
+
+          /* +v or +voice */
+          if ((chan->role & ROLE_VOICE) && !chan_hasvoice(m) && !chan_sentvoice(m)) {
             member_getuser(m, 1);
 
             if (m->user) {
-              get_user_flagrec(m->user, &fr, chan->dname, chan);
-              if (!glob_bot(fr)) {
-                if (!(m->flags & EVOICE) &&
-                    (
-                     /* +voice: Voice all clients who are not flag:+q. If the chan is +voicebitch, only op flag:+v clients */
-                     (channel_voice(chan) && !chk_devoice(fr) && (!channel_voicebitch(chan) || (channel_voicebitch(chan) && chk_voice(fr, chan)))) ||
-                     /* Or, if the channel is -voice but they still qualify to be voiced */
-                     (!channel_voice(chan) && !privchan(fr, chan, PRIV_VOICE) && chk_voice(fr, chan))
-                    )
-                   ) {
-                  add_mode(chan, '+', 'v', m->nick);
-                }
+              if (!(m->flags & EVOICE) &&
+                  (
+                   /* +voice: Voice all clients who are not flag:+q. If the chan is +voicebitch, only op flag:+v clients */
+                   (channel_voice(chan) && !chk_devoice(fr) && (!channel_voicebitch(chan) || (channel_voicebitch(chan) && chk_voice(fr, chan)))) ||
+                   /* Or, if the channel is -voice but they still qualify to be voiced */
+                   (!channel_voice(chan) && !privchan(fr, chan, PRIV_VOICE) && chk_voice(fr, chan))
+                  )
+                 ) {
+                add_mode(chan, '+', 'v', m);
               }
             } else if (!m->user && channel_voice(chan) && !channel_voicebitch(chan) && voice_ok(m, chan)) {
-              add_mode(chan, '+', 'v', m->nick);
+              add_mode(chan, '+', 'v', m);
             }
           }
         }
@@ -1698,7 +1703,7 @@ flush_modes()
         }
         if (chan_sentvoice(m)) {
           m->flags &= ~SENTVOICE;
-          add_mode(chan, '+', 'v', m->nick);
+          add_mode(chan, '+', 'v', m);
         }
       }
     }

+ 12 - 3
src/mod/irc.mod/irc.h

@@ -120,9 +120,18 @@ void join_chan(struct chanset_t* chan, int idx = DP_MODE);
 
 int check_bind_authc(char *, Auth *, char *, char *);
 void notice_invite(struct chanset_t *, char *, char *, char *, bool);
-void real_add_mode(struct chanset_t *, const char, const char, const char *, bool);
-#define add_mode(chan, pls, mode, nick) real_add_mode(chan, pls, mode, nick, 0)
-#define add_cookie(chan, nick) real_add_mode(chan, '+', 'o', nick, 1)
+void real_add_mode(struct chanset_t *, const char, const char, const char *, bool, memberlist *);
+inline void add_mode(struct chanset_t *chan, const char plus, const char mode,
+    const char *op)
+{
+  real_add_mode(chan, plus, mode, op, 0, NULL);
+}
+inline void add_mode(struct chanset_t *chan, const char plus, const char mode,
+    memberlist *m)
+{
+  real_add_mode(chan, plus, mode, m->nick, 0, m);
+}
+#define add_cookie(chan, member) real_add_mode(chan, '+', 'o', member->nick, 1, member)
 /* Check if I am a chanop. Returns boolean 1 or 0.
  */
 inline bool me_op(const struct chanset_t *chan)

+ 17 - 14
src/mod/irc.mod/mode.cc

@@ -101,12 +101,16 @@ do_op(memberlist *m, struct chanset_t *chan, bool delay, bool force)
   if (delay) {
     m->delay = now + chan->auto_delay;
     m->flags |= SENTOP;
+    return 1;
   }
 
   if (channel_fastop(chan) || channel_take(chan) || cookies_disabled) {
-    add_mode(chan, '+', 'o', m->nick);
+    add_mode(chan, '+', 'o', m);
   } else if (!connect_bursting) {
-    add_cookie(chan, m->nick);
+    add_cookie(chan, m);
+  } else {
+    /* Failed to give the mode, so requeue it. */
+    do_op(m, chan, 1, 0);
   }
   return 1;
 }
@@ -332,15 +336,14 @@ flush_mode(struct chanset_t *chan, int pri)
 /* Queue a channel mode change
  */
 void
-real_add_mode(struct chanset_t *chan, const char plus, const char mode, const char *op, bool cookie)
+real_add_mode(struct chanset_t *chan, const char plus, const char mode, const char *op, bool cookie, memberlist *mx)
 {
   if (!me_op(chan))
     return;
 
-  memberlist *mx = NULL;
-
   if (mode == 'o' || mode == 'v') {
-    mx = ismember(chan, op);
+    if (!mx)
+      mx = ismember(chan, op);
     if (!mx)
       return;
     if (plus == '-' && mode == 'o') {
@@ -599,7 +602,7 @@ got_op(struct chanset_t *chan, memberlist *m, memberlist *mv)
         m->flags |= SENTDEOP;
 #endif
       if (num == 5) {
-        add_mode(chan, '-', 'o', m->nick);
+        add_mode(chan, '-', 'o', m);
       } else if (bitch && num == 6) {
         len = simple_snprintf(outbuf, sizeof(outbuf), "KICK %s %s :%s\r\n", chan->name, mv->nick, response(RES_BITCHOPPED));
         mv->flags |= SENTKICK;
@@ -607,7 +610,7 @@ got_op(struct chanset_t *chan, memberlist *m, memberlist *mv)
         len = simple_snprintf(outbuf, sizeof(outbuf), "KICK %s %s :%s\r\n", chan->name, m->nick, response(RES_BITCHOP));
         m->flags |= SENTKICK;
       } else
-        add_mode(chan, '-', 'o', mv->nick);
+        add_mode(chan, '-', 'o', mv);
 
       if (len)
         dprintf_real(DP_MODE_NEXT, outbuf, len, sizeof(outbuf));
@@ -615,13 +618,13 @@ got_op(struct chanset_t *chan, memberlist *m, memberlist *mv)
 
 
   } else if (reversing && !me_opped)
-    add_mode(chan, '-', 'o', mv->nick);
+    add_mode(chan, '-', 'o', mv);
 
   /* server op */
   if (!m && meop && !me_opped) {
     if (chk_deop(victim, chan) || (chan_bitch(chan) && !chk_op(victim, chan))) {
       mv->flags |= FAKEOP;
-      add_mode(chan, '-', 'o', mv->nick);
+      add_mode(chan, '-', 'o', mv);
     } 
   }
   mv->flags |= WASOP;
@@ -1470,9 +1473,9 @@ gotmode(char *from, char *msg)
                 mv->flags |= CHANVOICE;
                 if (channel_active(chan) && dovoice(chan)) {
                   if (dv || chk_devoice(victim) || (channel_voicebitch(chan) && !chk_voice(victim, chan))) {
-                    add_mode(chan, '-', 'v', mparam);
+                    add_mode(chan, '-', 'v', mv);
                   } else if (reversing) {
-                    add_mode(chan, '-', 'v', mparam);
+                    add_mode(chan, '-', 'v', mv);
                   }
                 }
               } else if (msign == '-') {
@@ -1481,9 +1484,9 @@ gotmode(char *from, char *msg)
                 if (channel_active(chan) && dovoice(chan) && !chan_hasop(mv)) {
                   /* revoice +v users */
                   if (chk_voice(victim, chan)) {
-                    add_mode(chan, '+', 'v', mparam);
+                    add_mode(chan, '+', 'v', mv);
                   } else if (reversing) {
-                    add_mode(chan, '+', 'v', mparam);
+                    add_mode(chan, '+', 'v', mv);
                     /* if they arent +v|v and VOICER is m+ then EVOICE them */
                   } else {
                     if (!match_my_nick(nick) && channel_voice(chan) &&