Browse Source

* Port [3161] to 1.2.13
* Fix cmd_chattr accepting invalid flags. (fixes #293)
* See 'help whois' as some flags are now user, bot, chan, global only.


svn: 3163

Bryan Drewery 19 years ago
parent
commit
778ab617b9
6 changed files with 90 additions and 77 deletions
  1. 2 0
      doc/UPDATES
  2. 20 31
      misc/help.txt
  3. 13 11
      src/cmds.c
  4. 18 14
      src/flags.c
  5. 33 21
      src/flags.h
  6. 4 0
      src/users.c

+ 2 - 0
doc/UPDATES

@@ -16,6 +16,8 @@ Lines prefixed with '-' were disabled before release and are not finished, or ar
 * Added cmd_umode (+m) to manually set bots' usermodes at will.
 * Added cmd_umode (+m) to manually set bots' usermodes at will.
 * Fix botnicks becoming lower case after being opped.
 * Fix botnicks becoming lower case after being opped.
 * Minor documentation change for cmd_newleaf. (fixes #291)
 * Minor documentation change for cmd_newleaf. (fixes #291)
+* Fix cmd_chattr accepting invalid flags. (fixes #293)
+* See 'help whois' as some flags are now user, bot, chan, global only.
 
 
 1.2.12 - http://wraith.shatow.net/milestone/1.2.12
 1.2.12 - http://wraith.shatow.net/milestone/1.2.12
 * Clearing a variable via 'set var -' now resets that variable to default settings. (implements #111)
 * Clearing a variable via 'set var -' now resets that variable to default settings. (implements #111)

+ 20 - 31
misc/help.txt

@@ -1833,42 +1833,31 @@ See also: whom
       $bFLAGS$b  - the list of flags for this user (see below)
       $bFLAGS$b  - the list of flags for this user (see below)
       $bLAST$b   - the time or date that the user was last on irc or the partyline
       $bLAST$b   - the time or date that the user was last on irc or the partyline
  
  
-   Valid global flags:
+   Valid flags:
+      $bd$b = deop (user cannot gain ops in any channel)
+      $bk$b = autokick (user is kicked and banned automatically)
+      $bo$b = op (user has op access to all of the bot's channels)
+      $bq$b = quiet (user cannot gain voice on any channel)
+      $bv$b = voice (user gets +v automatically from +y bots)
+ 
+   Valid user-only flags:
       $ba$b - admin (user has absolute control over botnet minus a few perm-owner only cmds)
       $ba$b - admin (user has absolute control over botnet minus a few perm-owner only cmds)
               Be careful who you give this to, only the perm-owner of the net should even have it.
               Be careful who you give this to, only the perm-owner of the net should even have it.
-      $bc$b - chat-bot (bot accepts DCC chat on irc)
-      $bd$b - deop (user cannot gain ops in any channel)
       $bi$b - hub access (user has hub DCC access)
       $bi$b - hub access (user has hub DCC access)
       $bj$b - leaf access (user has leaf DCC access)
       $bj$b - leaf access (user has leaf DCC access)
-      $bk$b - autokick (user is kicked and banned automatically)
-      $bl$b - limit-bot (bot sets limit in all channels, see '%dhelp chaninfo') [$bCPU INTENSIVE$b]
-      $bm$b - master (user has more access to the botnet cmds than a normal user)
-      $bn$b - owner (user has just about full access to bot)
-      $bo$b - op (user has op access to all of the bot's channels)
-      $bO$b - autoop (user is auto-opped in all channels)
-      $bp$b - party-line (user has access to the partyline)
-      $bq$b - quiet (user cannot gain voice on any channel)
-      $br$b - resolve (bot resolves clients in to match against userlist) [$bCPU INTENSIVE+$b]
+      $bm$b = master (user has more access to the botnet cmds than a normal user)
+      $bn$b = owner (user has just about full access to bot)
+      $bO$b = autoop (user is auto-opped in all channels)
+      $bx$b = flood-exempt (user is exempt from flood kicks)
+ 
+   Valid bot-only flags:
+      $bc$b = chat-bot (bot accepts DCC chat on irc)
+      $bl$b = limit-bot (bot sets limit in all channels, see '%dhelp chaninfo') [$bCPU INTENSIVE$b]
+      $br$b = resolve (bot resolves clients in to match against userlist) [$bCPU INTENSIVE+$b]
       $bu$b - update-bot (see doc/UPGRADING)
       $bu$b - update-bot (see doc/UPGRADING)
-      $bv$b - voice (user gets +v automatically from +y bots)
-      $bw$b - wasop-test (INTERNAL)
-      $bx$b - flood-exempt (user is exempt from flood kicks)
-      $by$b - voice-bot (bot gives out voices/auto-ops in chans) [$bCPU INTENSIVE$b]
- 
-   Users can also have flags specific to a channel:
- 
-      $bd$b - deop (user cannot gain ops on the channel)
-      $bk$b - autokick (user is kicked and banned automatically)
-      $bl$b - limit-bot (bot sets limit in the channel) [$bCPU INTENSIVE$b]
-      $bm$b - master (user is a channel master)
-      $bn$b - owner (user is a channel owner)
-      $bo$b - op (user has op access to the channel)
-      $bO$b - autoop (user is auto-opped in channel)
-      $bq$b - quiet (user cannot gain voice on the channel)
-      $br$b - resolve (bot resolves clients in channel to match against userlist) [$bCPU INTENSIVE+$b]
-      $bv$b - voice (user gets +v automatically)
-      $bw$b - wasop-test (INTERNAL)
-      $by$b - voice-bot (bot gives out voices/auto-ops in the channel) [$bCPU INTENSIVE$b]
+      $by$b = voice-bot (bot gives out voices/auto-ops in chans) [$bCPU INTENSIVE$b]
+ 
+   $bFlags followed by a '=' may also be used for a specific channel record.$b
  
  
    Hostmasks for the user are displayed on the following lines. If the user is
    Hostmasks for the user are displayed on the following lines. If the user is
    a bot, there will be a line below which says "ADDRESS:" and gives the bot's
    a bot, there will be a line below which says "ADDRESS:" and gives the bot's

+ 13 - 11
src/cmds.c

@@ -818,9 +818,9 @@ static void cmd_userlist(int idx, char *par)
   
   
   PRINT_USERS(1, 0, 0, "Bots");
   PRINT_USERS(1, 0, 0, "Bots");
   bt = tt;			/* we don't want to add these duplicates into the total */
   bt = tt;			/* we don't want to add these duplicates into the total */
-  PRINT_USERS(1, USER_CHANHUB, 0, "Chatbots");
-  PRINT_USERS(1, USER_DOVOICE, 0, "Voicebots");
-  PRINT_USERS(1, USER_DOLIMIT, 0, "Limitbots");
+  PRINT_USERS(1, BOT_CHANHUB, 0, "Chatbots");
+  PRINT_USERS(1, BOT_DOVOICE, 0, "Voicebots");
+  PRINT_USERS(1, BOT_DOLIMIT, 0, "Limitbots");
   tt = 0;
   tt = 0;
   PRINT_USERS(0, USER_ADMIN, 0, "Admins");
   PRINT_USERS(0, USER_ADMIN, 0, "Admins");
   PRINT_USERS(0, USER_OWNER, USER_ADMIN, "Owners");
   PRINT_USERS(0, USER_OWNER, USER_ADMIN, "Owners");
@@ -2326,6 +2326,9 @@ static void cmd_chattr(int idx, char *par)
   user.match = FR_GLOBAL;
   user.match = FR_GLOBAL;
   if (chan)
   if (chan)
     user.match |= FR_CHAN;
     user.match |= FR_CHAN;
+  if (u2->bot)
+    user.match |= FR_BOT;
+
   get_user_flagrec(dcc[idx].user, &user, chan ? chan->dname : 0);
   get_user_flagrec(dcc[idx].user, &user, chan ? chan->dname : 0);
   get_user_flagrec(u2, &ouser, chan ? chan->dname : 0);
   get_user_flagrec(u2, &ouser, chan ? chan->dname : 0);
   if (!chan && !glob_master(user)) {
   if (!chan && !glob_master(user)) {
@@ -2348,7 +2351,6 @@ static void cmd_chattr(int idx, char *par)
         free(tmpchg);
         free(tmpchg);
       return;
       return;
     }
     }
-  user.match &= -1;
 
 
   if (chg) {
   if (chg) {
     int okp = 1;
     int okp = 1;
@@ -2356,9 +2358,9 @@ static void cmd_chattr(int idx, char *par)
     pls.match = user.match;
     pls.match = user.match;
     break_down_flags(chg, &pls, &mns);
     break_down_flags(chg, &pls, &mns);
 
 
-    if ((pls.global & USER_UPDATEHUB) && (bot_hublevel(u2) == 999)) {
+    if ((pls.global & BOT_UPDATEHUB) && (bot_hublevel(u2) == 999)) {
       dprintf(idx, "Only a hub can be set as the updatehub.\n");
       dprintf(idx, "Only a hub can be set as the updatehub.\n");
-      pls.global &= ~(USER_UPDATEHUB);
+      pls.global &= ~(BOT_UPDATEHUB);
     }
     }
     
     
     /* strip out +p without +i or +j */
     /* strip out +p without +i or +j */
@@ -2375,9 +2377,9 @@ static void cmd_chattr(int idx, char *par)
         putlog(LOG_MISC, "*", "%s attempted to give %s hub connect access", dcc[idx].nick, u2->handle);
         putlog(LOG_MISC, "*", "%s attempted to give %s hub connect access", dcc[idx].nick, u2->handle);
       if (mns.global & USER_HUBA)
       if (mns.global & USER_HUBA)
         putlog(LOG_MISC, "*", "%s attempted to take away hub connect access from %s", dcc[idx].nick, u2->handle);
         putlog(LOG_MISC, "*", "%s attempted to take away hub connect access from %s", dcc[idx].nick, u2->handle);
-      if (pls.global & USER_UPDATEHUB)
+      if (pls.global & BOT_UPDATEHUB)
         putlog(LOG_MISC, "*", "%s attempted to make %s the updatehub", dcc[idx].nick, u2->handle);
         putlog(LOG_MISC, "*", "%s attempted to make %s the updatehub", dcc[idx].nick, u2->handle);
-      if (mns.global & USER_UPDATEHUB)
+      if (mns.global & BOT_UPDATEHUB)
         putlog(LOG_MISC, "*", "%s attempted to take away updatehub status from %s", dcc[idx].nick, u2->handle);
         putlog(LOG_MISC, "*", "%s attempted to take away updatehub status from %s", dcc[idx].nick, u2->handle);
       if (pls.global & USER_ADMIN)
       if (pls.global & USER_ADMIN)
         putlog(LOG_MISC, "*", "%s attempted to give %s admin access", dcc[idx].nick, u2->handle);
         putlog(LOG_MISC, "*", "%s attempted to give %s admin access", dcc[idx].nick, u2->handle);
@@ -2387,9 +2389,9 @@ static void cmd_chattr(int idx, char *par)
         putlog(LOG_MISC, "*", "%s attempted to give owner to %s", dcc[idx].nick, u2->handle);
         putlog(LOG_MISC, "*", "%s attempted to give owner to %s", dcc[idx].nick, u2->handle);
       if (mns.global & USER_OWNER)
       if (mns.global & USER_OWNER)
         putlog(LOG_MISC, "*", "%s attempted to take owner away from %s", dcc[idx].nick, u2->handle);
         putlog(LOG_MISC, "*", "%s attempted to take owner away from %s", dcc[idx].nick, u2->handle);
-      pls.global &=~(USER_HUBA | USER_ADMIN | USER_OWNER | USER_UPDATEHUB);
-      mns.global &=~(USER_HUBA | USER_ADMIN | USER_OWNER | USER_UPDATEHUB);
-      pls.chan &= ~(USER_ADMIN | USER_UPDATEHUB);
+      pls.global &=~(USER_HUBA | USER_ADMIN | USER_OWNER | BOT_UPDATEHUB);
+      mns.global &=~(USER_HUBA | USER_ADMIN | USER_OWNER | BOT_UPDATEHUB);
+      pls.chan &= ~(USER_ADMIN | BOT_UPDATEHUB);
     }
     }
     if (chan) {
     if (chan) {
       pls.chan &= ~(USER_HUBA | USER_CHUBA);
       pls.chan &= ~(USER_HUBA | USER_CHUBA);

+ 18 - 14
src/flags.c

@@ -43,8 +43,8 @@ sanity_check(flag_t atr, int bot)
   if (bot && (atr & (USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA)))
   if (bot && (atr & (USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA)))
     atr &= ~(USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA);
     atr &= ~(USER_PARTY | USER_MASTER | USER_OWNER | USER_ADMIN | USER_HUBA | USER_CHUBA);
 /* only bots should be there: */
 /* only bots should be there: */
-  if (!bot && (atr & (USER_DOLIMIT | USER_DOVOICE | USER_UPDATEHUB | USER_CHANHUB)))
-    atr &= ~(USER_DOLIMIT | USER_DOVOICE | USER_UPDATEHUB | USER_CHANHUB);
+  if (!bot && (atr & (BOT_DOLIMIT | BOT_DOVOICE | BOT_UPDATEHUB | BOT_CHANHUB)))
+    atr &= ~(BOT_DOLIMIT | BOT_DOVOICE | BOT_UPDATEHUB | BOT_CHANHUB);
   if (atr & USER_AUTOOP)
   if (atr & USER_AUTOOP)
     atr |= USER_OP;
     atr |= USER_OP;
   if ((atr & USER_OP) && (atr & USER_DEOP))
   if ((atr & USER_OP) && (atr & USER_DEOP))
@@ -78,11 +78,11 @@ flag_t
 chan_sanity_check(flag_t chatr, int bot)
 chan_sanity_check(flag_t chatr, int bot)
 {
 {
   /* these should only be global */
   /* these should only be global */
-  if (chatr & (USER_PARTY | USER_ADMIN | USER_HUBA | USER_CHUBA | USER_UPDATEHUB))
-    chatr &= ~(USER_PARTY | USER_ADMIN | USER_HUBA | USER_CHUBA | USER_UPDATEHUB);
+  if (chatr & (USER_PARTY | USER_ADMIN | USER_HUBA | USER_CHUBA | BOT_UPDATEHUB))
+    chatr &= ~(USER_PARTY | USER_ADMIN | USER_HUBA | USER_CHUBA | BOT_UPDATEHUB);
   /* these should only be set on bots */
   /* these should only be set on bots */
-  if (!bot && (chatr & (USER_DOLIMIT | USER_DOVOICE | USER_CHANHUB)))
-    chatr &= ~(USER_DOLIMIT | USER_DOVOICE | USER_CHANHUB);
+  if (!bot && (chatr & (BOT_DOLIMIT | BOT_DOVOICE | BOT_CHANHUB)))
+    chatr &= ~(BOT_DOLIMIT | BOT_DOVOICE | BOT_CHANHUB);
 
 
   if ((chatr & USER_OP) && (chatr & USER_DEOP))
   if ((chatr & USER_OP) && (chatr & USER_DEOP))
     chatr &= ~(USER_OP | USER_DEOP);
     chatr &= ~(USER_OP | USER_DEOP);
@@ -190,12 +190,16 @@ break_down_flags(const char *string, struct flag_record *plus, struct flag_recor
     }
     }
     string++;
     string++;
   }
   }
-  /*
-   * for (which = plus; which; which = (which == plus ? minus : 0)) {
-   * which->global &= USER_VALID;
-   * which->chan &= CHAN_VALID;
-   * }
-   */
+  for (which = plus; which; which = (which == plus ? minus : 0)) {
+    if (flags & FR_BOT) {
+      which->global &= BOT_VALID;
+      which->chan &= BOT_CHAN_VALID;
+    } else {    
+      which->global &= USER_VALID;
+      which->chan &= USER_CHAN_VALID;
+    }
+  }
+
   plus->match |= flags;
   plus->match |= flags;
   if (minus) {
   if (minus) {
     minus->match |= flags;
     minus->match |= flags;
@@ -500,7 +504,7 @@ chk_noflood(struct flag_record fr)
 int
 int
 isupdatehub()
 isupdatehub()
 {
 {
-  if (conf.bot->hub && conf.bot->u && (conf.bot->u->flags & USER_UPDATEHUB))
+  if (conf.bot->hub && conf.bot->u && (conf.bot->u->flags & BOT_UPDATEHUB))
     return 1;
     return 1;
   else
   else
     return 0;
     return 0;
@@ -509,7 +513,7 @@ isupdatehub()
 int
 int
 ischanhub()
 ischanhub()
 {
 {
-  if (!conf.bot->hub && conf.bot->u && (conf.bot->u->flags & USER_CHANHUB))
+  if (!conf.bot->hub && conf.bot->u && (conf.bot->u->flags & BOT_CHANHUB))
     return 1;
     return 1;
   else
   else
     return 0;
     return 0;

+ 33 - 21
src/flags.h

@@ -26,6 +26,7 @@ struct flag_record {
 
 
 #define FR_GLOBAL 0x00000001
 #define FR_GLOBAL 0x00000001
 #define FR_CHAN   0x00000002
 #define FR_CHAN   0x00000002
+#define FR_BOT    0x00000004
 #define FR_ANYWH  0x10000000
 #define FR_ANYWH  0x10000000
 #define FR_ANYCH  0x20000000
 #define FR_ANYCH  0x20000000
 #define FR_AND    0x40000000
 #define FR_AND    0x40000000
@@ -57,29 +58,39 @@ struct flag_record {
 #define DEFLAG_MDOP        6
 #define DEFLAG_MDOP        6
 #define DEFLAG_MOP	   7
 #define DEFLAG_MOP	   7
 
 
-#define USER_VALID (flag_t) 0xfffffffffffff
-#define CHAN_VALID (flag_t) 0xfffffffffffff
+
+#define USER_DEFAULT	0
 
 
 #define USER_ADMIN	FLAG[(int) 'a']
 #define USER_ADMIN	FLAG[(int) 'a']
-#define USER_CHANHUB	FLAG[(int) 'c']
-#define USER_DEOP	FLAG[(int) 'd']
 #define USER_HUBA	FLAG[(int) 'i']
 #define USER_HUBA	FLAG[(int) 'i']
 #define USER_CHUBA	FLAG[(int) 'j']
 #define USER_CHUBA	FLAG[(int) 'j']
-#define USER_KICK	FLAG[(int) 'k']
-#define USER_DOLIMIT	FLAG[(int) 'l']
+#define USER_PARTY	FLAG[(int) 'p']
 #define USER_MASTER	FLAG[(int) 'm']
 #define USER_MASTER	FLAG[(int) 'm']
 #define USER_OWNER	FLAG[(int) 'n']
 #define USER_OWNER	FLAG[(int) 'n']
-#define USER_OP		FLAG[(int) 'o']
+
 #define USER_AUTOOP	FLAG[(int) 'O']
 #define USER_AUTOOP	FLAG[(int) 'O']
-#define USER_PARTY	FLAG[(int) 'p']
+
+#define USER_DEOP	FLAG[(int) 'd']
+#define USER_KICK	FLAG[(int) 'k']
+#define USER_OP		FLAG[(int) 'o']
 #define USER_QUIET	FLAG[(int) 'q']
 #define USER_QUIET	FLAG[(int) 'q']
-#define USER_DORESOLV	FLAG[(int) 'r']
-#define USER_UPDATEHUB	FLAG[(int) 'u']
 #define USER_VOICE	FLAG[(int) 'v']
 #define USER_VOICE	FLAG[(int) 'v']
-#define USER_WASOPTEST	FLAG[(int) 'w']
 #define USER_NOFLOOD	FLAG[(int) 'x']
 #define USER_NOFLOOD	FLAG[(int) 'x']
-#define USER_DOVOICE	FLAG[(int) 'y']
-#define USER_DEFAULT	0
+#define USER_WASOPTEST	FLAG[(int) 'w']
+
+#define CHAN_VALID (flag_t) USER_DEOP|USER_KICK|USER_OP|USER_QUIET|USER_VOICE|USER_NOFLOOD|USER_WASOPTEST
+
+#define USER_CHAN_VALID (flag_t) CHAN_VALID|USER_AUTOOP|USER_MASTER|USER_OWNER
+#define USER_VALID (flag_t) USER_ADMIN|USER_HUBA|USER_CHUBA|USER_PARTY|USER_CHAN_VALID
+
+#define BOT_CHANHUB	FLAG[(int) 'c']
+#define BOT_UPDATEHUB	FLAG[(int) 'u']
+#define BOT_DORESOLV	FLAG[(int) 'r']
+#define BOT_DOLIMIT	FLAG[(int) 'l']
+#define BOT_DOVOICE	FLAG[(int) 'y']
+
+#define BOT_CHAN_VALID (flag_t) CHAN_VALID|BOT_CHANHUB|BOT_DOLIMIT|BOT_DOVOICE|BOT_DORESOLV
+#define BOT_VALID  (flag_t) BOT_CHAN_VALID|BOT_UPDATEHUB
 
 
 
 
 #define bot_hublevel(x) ( ( (x) && x->bot && (get_user(&USERENTRY_BOTADDR, x)) ) ? \
 #define bot_hublevel(x) ( ( (x) && x->bot && (get_user(&USERENTRY_BOTADDR, x)) ) ? \
@@ -109,19 +120,20 @@ struct flag_record {
 #define chan_quiet(x)                  ((x).chan & USER_QUIET)
 #define chan_quiet(x)                  ((x).chan & USER_QUIET)
 #define glob_quiet(x)                  ((x).global & USER_QUIET)
 #define glob_quiet(x)                  ((x).global & USER_QUIET)
 #define glob_party(x)                  ((x).global & USER_PARTY)
 #define glob_party(x)                  ((x).global & USER_PARTY)
-#define glob_hilite(x)                         ((x).global & USER_HIGHLITE)
+#define glob_hilite(x)                 ((x).global & USER_HIGHLITE)
 #define glob_admin(x)                  ((x).global & USER_ADMIN)
 #define glob_admin(x)                  ((x).global & USER_ADMIN)
 #define glob_huba(x)                   ((x).global & USER_HUBA)
 #define glob_huba(x)                   ((x).global & USER_HUBA)
 #define glob_chuba(x)                  ((x).global & USER_CHUBA)
 #define glob_chuba(x)                  ((x).global & USER_CHUBA)
-#define glob_dolimit(x)                        ((x).global & USER_DOLIMIT)
-#define chan_dolimit(x)                        ((x).chan & USER_DOLIMIT)
-#define glob_dovoice(x)                        ((x).global & USER_DOVOICE)
-#define chan_dovoice(x)                        ((x).chan & USER_DOVOICE)
 #define glob_noflood(x)                        ((x).global & USER_NOFLOOD)
 #define glob_noflood(x)                        ((x).global & USER_NOFLOOD)
 #define chan_noflood(x)                        ((x).chan & USER_NOFLOOD)
 #define chan_noflood(x)                        ((x).chan & USER_NOFLOOD)
-#define glob_chanhub(x)                        ((x).global & USER_CHANHUB)
-#define glob_doresolv(x)                        ((x).global & USER_DORESOLV)
-#define chan_doresolv(x)                        ((x).chan & USER_DORESOLV)
+
+#define glob_dolimit(x)                        ((x).global & BOT_DOLIMIT)
+#define chan_dolimit(x)                        ((x).chan & BOT_DOLIMIT)
+#define glob_dovoice(x)                        ((x).global & BOT_DOVOICE)
+#define chan_dovoice(x)                        ((x).chan & BOT_DOVOICE)
+#define glob_chanhub(x)                        ((x).global & BOT_CHANHUB)
+#define glob_doresolv(x)                        ((x).global & BOT_DORESOLV)
+#define chan_doresolv(x)                        ((x).chan & BOT_DORESOLV)
 
 
 void init_flags(void);
 void init_flags(void);
 void get_user_flagrec(struct userrec *, struct flag_record *, const char *);
 void get_user_flagrec(struct userrec *, struct flag_record *, const char *);

+ 4 - 0
src/users.c

@@ -671,6 +671,8 @@ int readuserfile(const char *file, struct userrec **ret)
 	    fl = newsplit(&s);
 	    fl = newsplit(&s);
 	    rmspace(s);
 	    rmspace(s);
 	    fr.match = FR_CHAN;
 	    fr.match = FR_CHAN;
+            if (u->bot)
+              fr.match |= FR_BOT;
 	    break_down_flags(fl, &fr, 0);
 	    break_down_flags(fl, &fr, 0);
 	    if (findchan_by_dname(chname)) {
 	    if (findchan_by_dname(chname)) {
 	      for (cr = u->chanrec; cr; cr = cr->next)
 	      for (cr = u->chanrec; cr; cr = cr->next)
@@ -850,6 +852,8 @@ int readuserfile(const char *file, struct userrec **ret)
 	      u = NULL;
 	      u = NULL;
 	    } else {
 	    } else {
 	      fr.match = FR_GLOBAL;
 	      fr.match = FR_GLOBAL;
+              if (isbot)
+                fr.match |= FR_BOT;
 	      break_down_flags(attr, &fr, 0);
 	      break_down_flags(attr, &fr, 0);
 	      strcpy(lasthand, code);
 	      strcpy(lasthand, code);
 	      cst = NULL;
 	      cst = NULL;