]> jfr.im git - irc/rqf/shadowircd.git/blobdiff - src/chmode.c
chmode: Remove chm_regonly, a vestige from ratbox which doesn't apply to native chary...
[irc/rqf/shadowircd.git] / src / chmode.c
index dbf47f619f505707ce28b4fcaabd4722b3b7e4c9..d5fa3a315ddbc96eefac9216acd21498100a67cd 100644 (file)
@@ -43,6 +43,7 @@
 #include "chmode.h"
 #include "irc_dictionary.h"
 
+
 /* bitmasks for error returns, so we send once per call */
 #define SM_ERR_NOTS             0x00000001     /* No TS on channel */
 #define SM_ERR_NOOPS            0x00000002     /* No chan ops */
@@ -56,6 +57,7 @@
 #define SM_ERR_NOPRIVS          0x00000400
 #define SM_ERR_RPL_Q            0x00000800
 #define SM_ERR_RPL_F            0x00001000
+#define SM_ERR_MLOCK            0x00002000
 
 #define MAXMODES_SIMPLE 46 /* a-zA-Z except bqeIov */
 
@@ -68,11 +70,10 @@ static int no_override_deop;
 
 char cflagsbuf[256];
 char cflagsmyinfo[256];
+char cflagsparaminfo[256];
 
 int chmode_flags[256];
 
-struct module_modes ModuleModes;
-
 /* OPTIMIZE ME! -- dwr */
 void
 construct_cflags_strings(void)
@@ -103,27 +104,35 @@ construct_cflags_strings(void)
                        chmode_flags[i] = 0;
                }
                 
-               if(chmode_flags[i] == ModuleModes.MODE_DISFORWARD)
+               switch (chmode_flags[i])
                {
-                       if (ModuleModes.MODE_FORWARD)
+                   case MODE_EXLIMIT:
+                   case MODE_DISFORWARD:
+                       if(ConfigChannel.use_forward)
                        {
-                               *ptr++ = (char) i;
+                           *ptr++ = (char) i;
                        }
-               }
-               else if(chmode_flags[i] == ModuleModes.MODE_REGONLY)
-               {
-                       if (rb_dlink_list_length(&service_list))
+                       
+                       break;
+                   case MODE_REGONLY:
+                       if(rb_dlink_list_length(&service_list))
                        {
-                               *ptr++ = (char) i;
+                           *ptr++ = (char) i;
+                       }
+
+                       break;
+                   default:
+                       if(chmode_flags[i] != 0 && !(chmode_table[i].set_func == chm_orphaned))
+                       {
+                           *ptr++ = (char) i;
                        }
-               }
-               else if(chmode_flags[i] != ModuleModes.MODE_EXLIMIT && chmode_flags[i] != 0)
-               {
-                       *ptr++ = (char) i;
                }
                
                /* Should we leave orphaned check here? -- dwr */
-               if(!(chmode_table[i].set_func == chm_nosuch) && !(chmode_table[i].set_func == chm_orphaned))
+               if( !(chmode_table[i].set_func == chm_nosuch) && 
+                       !(chmode_table[i].set_func == chm_orphaned) && 
+                       !(chmode_table[i].set_func == chm_admin && !ConfigChannel.use_admin) && 
+                       !(chmode_table[i].set_func == chm_halfop && !ConfigChannel.use_halfop))
                {
                    *ptr2++ = (char) i;
                }
@@ -133,6 +142,21 @@ construct_cflags_strings(void)
        *ptr2++ = '\0';
 }
 
+void
+construct_cflag_param_string(void)
+{
+
+       *cflagsparaminfo = '\0';
+       rb_snprintf(cflagsparaminfo, sizeof cflagsparaminfo, "%sb%s%s%s%sklov%s%s",
+                       ConfigChannel.use_admin ? "a" : "",
+                       ConfigChannel.use_except ? "e" : "",
+                       ConfigChannel.use_forward ? "f" : "",
+                       ConfigChannel.use_halfop ? "h" : "",
+                       strcasecmp(ConfigChannel.disabledmodes, "j") ? "" : "j",
+                       strcasecmp(ConfigChannel.disabledmodes, "q") ? "" : "q",
+                       ConfigChannel.use_invex ? "I" : "");
+}
+
 /*
  * find_umode_slot
  *
@@ -216,7 +240,7 @@ add_id(struct Client *source_p, struct Channel *chptr, const char *banid,
         */
        if(MyClient(source_p))
        {
-               if((rb_dlink_list_length(&chptr->banlist) + rb_dlink_list_length(&chptr->exceptlist) + rb_dlink_list_length(&chptr->invexlist) + rb_dlink_list_length(&chptr->quietlist)) >= (chptr->mode.mode & ModuleModes.MODE_EXLIMIT ? ConfigChannel.max_bans_large : ConfigChannel.max_bans))
+               if((rb_dlink_list_length(&chptr->banlist) + rb_dlink_list_length(&chptr->exceptlist) + rb_dlink_list_length(&chptr->invexlist) + rb_dlink_list_length(&chptr->quietlist)) >= (chptr->mode.mode & MODE_EXLIMIT ? ConfigChannel.max_bans_large : ConfigChannel.max_bans))
                {
                        sendto_one(source_p, form_str(ERR_BANLISTFULL),
                                   me.name, source_p->name, chptr->chname, realban);
@@ -253,7 +277,7 @@ add_id(struct Client *source_p, struct Channel *chptr, const char *banid,
        rb_dlinkAdd(actualBan, &actualBan->node, list);
 
        /* invalidate the can_send() cache */
-       if(mode_type == CHFL_BAN || mode_type == ModuleModes.CHFL_QUIET || mode_type == CHFL_EXCEPTION)
+       if(mode_type == CHFL_BAN || mode_type == CHFL_QUIET || mode_type == CHFL_EXCEPTION)
                chptr->bants++;
 
        return 1;
@@ -284,7 +308,7 @@ del_id(struct Channel *chptr, const char *banid, rb_dlink_list * list, long mode
                        free_ban(banptr);
 
                        /* invalidate the can_send() cache */
-                       if(mode_type == CHFL_BAN || mode_type == ModuleModes.CHFL_QUIET || mode_type == CHFL_EXCEPTION)
+                       if(mode_type == CHFL_BAN || mode_type == CHFL_QUIET || mode_type == CHFL_EXCEPTION)
                                chptr->bants++;
 
                        return 1;
@@ -530,10 +554,10 @@ chm_simple(struct Client *source_p, struct Channel *chptr,
                return;
 
        /* setting + */
-       if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type) && !(chptr->mode_lock.off_mode & mode_type))
+       if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type))
        {
                /* if +f is disabled, ignore an attempt to set +QF locally */
-               if(!ModuleModes.MODE_FORWARD && MyClient(source_p) &&
+               if(!ConfigChannel.use_forward && MyClient(source_p) &&
                   (c == 'Q' || c == 'F'))
                        return;
 
@@ -581,7 +605,10 @@ chm_orphaned(struct Client *source_p, struct Channel *chptr,
           const char **parv, int *errors, int dir, char c, long mode_type)
 {
        if(MyClient(source_p))
+       {
+               sendto_one_numeric(source_p, 469, "Mode %c is disabled.", c);
                return;
+       }
         
        if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type))
        {
@@ -595,7 +622,7 @@ chm_orphaned(struct Client *source_p, struct Channel *chptr,
                mode_changes[mode_count].mems = ALL_MEMBERS;
                mode_changes[mode_count++].arg = NULL;
        }
-       else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type) && !(chptr->mode_lock.mode & mode_type))
+       else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type))
        {
                chptr->mode.mode &= ~mode_type;
 
@@ -633,6 +660,7 @@ chm_hidden(struct Client *source_p, struct Channel *chptr,
        if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE))
                return;
 
+
        /* setting + */
        if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type))
        {
@@ -646,6 +674,19 @@ chm_hidden(struct Client *source_p, struct Channel *chptr,
                mode_changes[mode_count].mems = ONLY_OPERS;
                mode_changes[mode_count].override = 0;
                mode_changes[mode_count++].arg = NULL;
+       
+               /* A little ugly */
+               sendto_wallops_flags(UMODE_WALLOP, &me, 
+                               "+%c set on [%s] by %s!%s@%s",
+                               c, chptr->chname, source_p->name, source_p->username, source_p->host);
+               ilog(L_MAIN, "+%c set on [%s] by %s",
+                               c, chptr->chname, get_oper_name(source_p));
+
+               if(*chptr->chname != '&')
+                       sendto_server(NULL, NULL, NOCAPS, NOCAPS, 
+                               ":%s WALLOPS :+%c set on [%s] by %s!%s@%s",
+                               me.name, c, chptr->chname, source_p->name, source_p->username,
+                               source_p->host);
        }
        else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type))
        {
@@ -659,6 +700,19 @@ chm_hidden(struct Client *source_p, struct Channel *chptr,
                mode_changes[mode_count].id = NULL;
                mode_changes[mode_count].override = 0;
                mode_changes[mode_count++].arg = NULL;
+               
+               /* A little ugly */
+               sendto_wallops_flags(UMODE_WALLOP, &me, 
+                               "+%c unset from [%s] by %s!%s@%s",
+                               c, chptr->chname, source_p->name, source_p->username, source_p->host);
+               ilog(L_MAIN, "+%c unset from [%s] by %s",
+                               c, chptr->chname, get_oper_name(source_p));
+
+               if(*chptr->chname != '&')
+                       sendto_server(NULL, NULL, NOCAPS, NOCAPS, 
+                               ":%s WALLOPS :+%c unset from [%s] by %s!%s@%s",
+                               me.name, c, chptr->chname, source_p->name, source_p->username,
+                               source_p->host);
        }
 }
 
@@ -748,17 +802,18 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
        int mems;
        int override = 0;
 
-       if(mode_type == CHFL_BAN)
+       switch (mode_type)
        {
+       case CHFL_BAN:
                list = &chptr->banlist;
                errorval = SM_ERR_RPL_B;
                rpl_list = RPL_BANLIST;
                rpl_endlist = RPL_ENDOFBANLIST;
                mems = ALL_MEMBERS;
                caps = 0;
-       }
-       else if(mode_type == CHFL_EXCEPTION)
-       {
+               break;
+
+       case CHFL_EXCEPTION:
                /* if +e is disabled, allow all but +e locally */
                if(!ConfigChannel.use_except && MyClient(source_p) &&
                   ((dir == MODE_ADD) && (parc > *parn)))
@@ -774,9 +829,9 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
                        mems = ONLY_CHANOPS;
                else
                        mems = ONLY_SERVERS;
-       }
-       else if(mode_type == CHFL_INVEX)
-       {
+               break;
+
+       case CHFL_INVEX:
                /* if +I is disabled, allow all but +I locally */
                if(!ConfigChannel.use_invex && MyClient(source_p) &&
                   (dir == MODE_ADD) && (parc > *parn))
@@ -792,20 +847,21 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
                        mems = ONLY_CHANOPS;
                else
                        mems = ONLY_SERVERS;
-       }
-       else if(mode_type == ModuleModes.CHFL_QUIET)
-       {
+               break;
+
+       case CHFL_QUIET:
                list = &chptr->quietlist;
                errorval = SM_ERR_RPL_Q;
                rpl_list = RPL_QUIETLIST;
                rpl_endlist = RPL_ENDOFQUIETLIST;
                mems = ALL_MEMBERS;
                caps = 0;
-       }
-       else
-       {
+               break;
+
+       default:
                sendto_realops_snomask(SNO_GENERAL, L_ALL, "chm_ban() called with unknown type!");
                return;
+               break;
        }
 
        if(dir == 0 || parc <= *parn)
@@ -816,7 +872,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
 
                /* non-ops cant see +eI lists.. */
                if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && mode_type != CHFL_BAN &&
-                               mode_type != ModuleModes.CHFL_QUIET)
+                               mode_type != CHFL_QUIET)
                {
                        if(IsOverride(source_p))
                        {
@@ -1503,7 +1559,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
        int override = 0;
 
        /* if +f is disabled, ignore local attempts to set it */
-       if(!ModuleModes.MODE_FORWARD && MyClient(source_p) &&
+       if(!ConfigChannel.use_forward && MyClient(source_p) &&
           (dir == MODE_ADD) && (parc > *parn))
                return;
 
@@ -1573,7 +1629,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
                                           form_str(ERR_NOSUCHCHANNEL), forward);
                        return;
                }
-               if(MyClient(source_p) && !(targptr->mode.mode & ModuleModes.MODE_FREETARGET))
+               if(MyClient(source_p) && !(targptr->mode.mode & MODE_FREETARGET))
                {
                        if((msptr = find_channel_membership(targptr, source_p)) == NULL ||
                                !is_any_op(msptr))
@@ -1595,7 +1651,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
                mode_changes[mode_count].dir = MODE_ADD;
                mode_changes[mode_count].caps = 0;
                mode_changes[mode_count].nocaps = 0;
-               mode_changes[mode_count].mems = ModuleModes.MODE_FORWARD ? ALL_MEMBERS : ONLY_SERVERS;
+               mode_changes[mode_count].mems = ConfigChannel.use_forward ? ALL_MEMBERS : ONLY_SERVERS;
                mode_changes[mode_count].id = NULL;
                mode_changes[mode_count].override = override;
                mode_changes[mode_count++].arg = forward;
@@ -1705,56 +1761,7 @@ chm_key(struct Client *source_p, struct Channel *chptr,
        }
 }
 
-void
-chm_regonly(struct Client *source_p, struct Channel *chptr,
-           int alevel, int parc, int *parn,
-           const char **parv, int *errors, int dir, char c, long mode_type)
-{
-       int override = 0;
-
-       if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP)
-       {
-               if(IsOverride(source_p))
-                       override = 1;
-               else
-               {
-                       if(!(*errors & SM_ERR_NOOPS))
-                               sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
-                                               me.name, source_p->name, chptr->chname);
-                       *errors |= SM_ERR_NOOPS;
-                       return;
-               }
-       }
-
-       if(dir == MODE_QUERY)
-               return;
-
-       if(((dir == MODE_ADD) && (chptr->mode.mode & mode_type)) ||
-          ((dir == MODE_DEL) && !(chptr->mode.mode & mode_type)))
-               return;
-
-       if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE))
-               return;
-
-       if(dir == MODE_ADD)
-               chptr->mode.mode |= mode_type;
-       else
-               chptr->mode.mode &= ~mode_type;
-
-       mode_changes[mode_count].letter = c;
-       mode_changes[mode_count].dir = dir;
-       mode_changes[mode_count].caps = CAP_SERVICE;
-       mode_changes[mode_count].nocaps = 0;
-       mode_changes[mode_count].mems = ALL_MEMBERS;
-       mode_changes[mode_count].id = NULL;
-       mode_changes[mode_count].override = override;
-       mode_changes[mode_count++].arg = NULL;
-}
-
 /* *INDENT-OFF* */
-/* Only RFC and ircd-ratbox modes are held in this table
- * All other modes are added via loading modules in shadowircd/modes
- * Such is documented in the comments for each mode, ex: C - NOCTCP. */
 struct ChannelMode chmode_table[256] =
 {
   {chm_nosuch,  0 },                   /* 0x00 */
@@ -1825,24 +1832,24 @@ struct ChannelMode chmode_table[256] =
   {chm_nosuch, 0 },                    /* @ */
   {chm_nosuch, 0 },                    /* A */
   {chm_nosuch, 0 },                    /* B */
-  {chm_nosuch, 0 },                    /* C - MODE_NOCTCP */
-  {chm_nosuch, 0 },                    /* D - MODE_NOACTION */
-  {chm_nosuch, 0 },                    /* E - MODE_NOKICK */
-  {chm_nosuch, 0 },                    /* F - MODE_FREETARGET */
-  {chm_nosuch, 0 },                    /* G - MODE_NOCAPS */
+  {chm_simple, MODE_NOCTCP },          /* C */
+  {chm_simple, MODE_NOACTION },        /* D */
+  {chm_simple, MODE_NOKICK },          /* E */
+  {chm_simple, MODE_FREETARGET },      /* F */
+  {chm_simple, MODE_NOCAPS },          /* G */
   {chm_nosuch, 0 },                    /* H */
   {chm_ban,    CHFL_INVEX },           /* I */
-  {chm_nosuch, 0 },                    /* J - MODE_NOREJOIN */
-  {chm_nosuch, 0 },                    /* K - MODE_NOREPEAT */
-  {chm_nosuch, 0 },                    /* L - MODE_EXLIMIT */
-  {chm_nosuch, 0 },                    /* M - MODE_NOOPERKICK */
-  {chm_nosuch, 0 },                    /* N - MODE_NONICK */
+  {chm_simple, MODE_NOREJOIN },        /* J */
+  {chm_simple, MODE_NOREPEAT },        /* K */
+  {chm_staff,  MODE_EXLIMIT },         /* L */
+  {chm_hidden, MODE_NOOPERKICK },      /* M */
+  {chm_simple, MODE_NONICK },          /* N */
   {chm_nosuch, 0 },                    /* O */
-  {chm_nosuch, 0 },                    /* P - MODE_PERMANENT */
-  {chm_nosuch, 0 },                    /* Q - MODE_DISFORWARD */
+  {chm_staff,  MODE_PERMANENT },       /* P */
+  {chm_simple, MODE_DISFORWARD },      /* Q */
   {chm_nosuch, 0 },                    /* R */
   {chm_nosuch, 0 },                    /* S */
-  {chm_nosuch, 0 },                    /* T - MODE_NONOTICE */
+  {chm_simple, MODE_NONOTICE },        /* T */
   {chm_nosuch, 0 },                    /* U */
   {chm_nosuch, 0 },                    /* V */
   {chm_nosuch, 0 },                    /* W */
@@ -1857,22 +1864,22 @@ struct ChannelMode chmode_table[256] =
   {chm_nosuch, 0 },
   {chm_admin,  0 },                    /* a */
   {chm_ban,    CHFL_BAN },             /* b */
-  {chm_nosuch, 0 },                    /* c - MODE_NOCOLOR */
+  {chm_simple, MODE_NOCOLOR },         /* c */
   {chm_nosuch, 0 },                    /* d */
   {chm_ban,    CHFL_EXCEPTION },       /* e */
-  {chm_nosuch, 0 },                    /* f - MODE_FORWARD */
-  {chm_nosuch, 0 },                    /* g - MODE_FREEINVITE */
+  {chm_forward,        0 },                    /* f */
+  {chm_simple, MODE_FREEINVITE },      /* g */
   {chm_halfop, 0 },                    /* h */
   {chm_simple, MODE_INVITEONLY },      /* i */
-  {chm_nosuch, 0 },                    /* j - MODE_THROTTLE */
+  {chm_throttle, 0 },                  /* j */
   {chm_key,    0 },                    /* k */
   {chm_limit,  0 },                    /* l */
   {chm_simple, MODE_MODERATED },       /* m */
   {chm_simple, MODE_NOPRIVMSGS },      /* n */
   {chm_op,     0 },                    /* o */
   {chm_simple, MODE_PRIVATE },         /* p */
-  {chm_nosuch, 0 },                    /* q - CHFL_QUIET */
-  {chm_nosuch, 0 },                    /* r - MODE_REGONLY */
+  {chm_ban,    CHFL_QUIET },           /* q */
+  {chm_simple, MODE_REGONLY },         /* r */
   {chm_simple, MODE_SECRET },          /* s */
   {chm_simple, MODE_TOPICLIMIT },      /* t */
   {chm_nosuch, 0 },                    /* u */
@@ -1880,7 +1887,7 @@ struct ChannelMode chmode_table[256] =
   {chm_nosuch, 0 },                    /* w */
   {chm_nosuch, 0 },                    /* x */
   {chm_nosuch, 0 },                    /* y */
-  {chm_nosuch, 0 },                    /* z - MODE_OPMODERATE */
+  {chm_simple, MODE_OPMODERATE },      /* z */
 
   {chm_nosuch,  0 },                   /* 0x7b */
   {chm_nosuch,  0 },                   /* 0x7c */
@@ -2084,6 +2091,19 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
                        dir = MODE_QUERY;
                        break;
                default:
+                       /* If this mode char is locked, don't allow local users to change it. */
+                       if (MyClient(source_p) && chptr->mode_lock && strchr(chptr->mode_lock, c))
+                       {
+                               if (!(errors & SM_ERR_MLOCK))
+                                       sendto_one_numeric(source_p,
+                                                       ERR_MLOCKRESTRICTED,
+                                                       form_str(ERR_MLOCKRESTRICTED),
+                                                       chptr->chname,
+                                                       c,
+                                                       chptr->mode_lock);
+                               errors |= SM_ERR_MLOCK;
+                               continue;
+                       }
                        chmode_table[(unsigned char) c].set_func(fakesource_p, chptr, alevel,
                                       parc, &parn, parv,
                                       &errors, dir, c,
@@ -2240,41 +2260,15 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
  */
 void
 set_channel_mlock(struct Client *client_p, struct Client *source_p,
-                 struct Channel *chptr, int parc, const char *parv[])
+                 struct Channel *chptr, const char *newmlock, int propagate)
 {
-       int dir = MODE_ADD;
-       const char *ml = parv[0];
-       char c;
+       rb_free(chptr->mode_lock);
+       chptr->mode_lock = newmlock ? rb_strdup(newmlock) : NULL;
 
-       memset(&chptr->mode_lock, '\0', sizeof(struct Mode));
-
-       for(; (c = *ml) != 0; ml++)
+       if (propagate)
        {
-               switch (c)
-               {
-               case '+':
-                       dir = MODE_ADD;
-                       break;
-               case '-':
-                       dir = MODE_DEL;
-                       break;
-               default:
-                       if (chmode_table[(unsigned char) c].set_func == chm_simple)
-                               switch(dir)
-                               {
-                               case MODE_ADD:
-                                       chptr->mode_lock.mode |= chmode_table[(unsigned char) c].mode_type;
-                                       chptr->mode_lock.off_mode &= ~chmode_table[(unsigned char) c].mode_type;
-                                       break;
-                               case MODE_DEL:
-                                       chptr->mode_lock.off_mode |= chmode_table[(unsigned char) c].mode_type;
-                                       chptr->mode_lock.mode &= ~chmode_table[(unsigned char) c].mode_type;
-                                       break;
-                               }
-                       break;
-               }
+               sendto_server(client_p, NULL, CAP_TS6 | CAP_MLOCK, NOCAPS, ":%s MLOCK %ld %s :%s",
+                             source_p->id, (long) chptr->channelts, chptr->chname,
+                             chptr->mode_lock ? chptr->mode_lock : "");
        }
-
-       sendto_server(client_p, NULL, CAP_TS6 | CAP_MLOCK, NOCAPS, ":%s MLOCK %ld %s %s",
-                     source_p->id, (long) chptr->channelts, chptr->chname, channel_mlock(chptr, &me));
 }