]> jfr.im git - irc/rqf/shadowircd.git/blobdiff - src/chmode.c
Add full support for +a (owner) and +h (halfop) chmodes.
[irc/rqf/shadowircd.git] / src / chmode.c
index 7121e263db2c33aa4e8f2387d67b0e30734df8e9..7f78db94d920d6a1c231983d385b61290c9be027 100644 (file)
@@ -89,7 +89,9 @@ construct_noparam_modes(void)
                        !(chmode_table[i].set_func == chm_throttle) &&
                         !(chmode_table[i].set_func == chm_key) &&
                         !(chmode_table[i].set_func == chm_limit) &&
+                       !(chmode_table[i].set_func == chm_owner) &&
                         !(chmode_table[i].set_func == chm_op) &&
+                       !(chmode_table[i].set_func == chm_halfop) &&
                         !(chmode_table[i].set_func == chm_voice))
                {
                        chmode_flags[i] = chmode_table[i].mode_type;
@@ -175,8 +177,12 @@ find_cflag_slot(void)
 static int
 get_channel_access(struct Client *source_p, struct membership *msptr)
 {
-       if(!MyClient(source_p) || is_chanop(msptr))
+       if(!MyClient(source_p) || is_owner(msptr))
+               return CHFL_OWNER;
+       else if(is_chanop(msptr))
                return CHFL_CHANOP;
+       else if(is_halfop(msptr))
+               return CHFL_HALFOP;
 
        return CHFL_PEON;
 }
@@ -492,7 +498,7 @@ chm_simple(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)
 {
-       if(alevel != CHFL_CHANOP)
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
        {
                if(!(*errors & SM_ERR_NOOPS))
                        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
@@ -706,7 +712,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
                *errors |= errorval;
 
                /* non-ops cant see +eI lists.. */
-               if(alevel != CHFL_CHANOP && mode_type != CHFL_BAN &&
+               if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP && mode_type != CHFL_BAN &&
                                mode_type != CHFL_QUIET)
                {
                        if(!(*errors & SM_ERR_NOOPS))
@@ -730,7 +736,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
                return;
        }
 
-       if(alevel != CHFL_CHANOP)
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
        {
                if(!(*errors & SM_ERR_NOOPS))
                        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
@@ -809,6 +815,103 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
        }
 }
 
+void
+chm_owner(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)
+{
+       struct membership *mstptr;
+       const char *ownernick;
+       struct Client *targ_p;
+
+       if(!ConfigChannel.use_owner)
+       {
+               if(*errors & SM_ERR_UNKNOWN)
+                       return;
+               *errors |= SM_ERR_UNKNOWN;
+               sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name, source_p->name, c);
+               return;
+       }
+
+       if(alevel != CHFL_OWNER)
+       {
+               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) || (parc <= *parn))
+               return;
+
+       ownernick = parv[(*parn)];
+       (*parn)++;
+
+       /* empty nick */
+       if(EmptyString(ownernick))
+       {
+               sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), "*");
+               return;
+       }
+
+       if((targ_p = find_chasing(source_p, ownernick, NULL)) == NULL)
+       {
+               return;
+       }
+
+       mstptr = find_channel_membership(chptr, targ_p);
+
+       if(mstptr == NULL)
+       {
+               if(!(*errors & SM_ERR_NOTONCHANNEL) && MyClient(source_p))
+                       sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
+                                          form_str(ERR_USERNOTINCHANNEL), ownernick, chptr->chname);
+               *errors |= SM_ERR_NOTONCHANNEL;
+               return;
+       }
+
+       if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
+               return;
+
+       if(dir == MODE_ADD)
+       {
+               if(targ_p == source_p)
+                       return;
+
+               mode_changes[mode_count].letter = c;
+               mode_changes[mode_count].dir = MODE_ADD;
+               mode_changes[mode_count].caps = 0;
+               mode_changes[mode_count].nocaps = 0;
+               mode_changes[mode_count].mems = ALL_MEMBERS;
+               mode_changes[mode_count].id = targ_p->id;
+               mode_changes[mode_count].arg = targ_p->name;
+               mode_changes[mode_count++].client = targ_p;
+
+               mstptr->flags |= CHFL_OWNER;
+       }
+       else
+       {
+               if(MyClient(source_p) && IsService(targ_p))
+               {
+                       sendto_one(source_p, form_str(ERR_ISCHANSERVICE),
+                                  me.name, source_p->name, targ_p->name, chptr->chname);
+                       return;
+               }
+
+               mode_changes[mode_count].letter = c;
+               mode_changes[mode_count].dir = MODE_DEL;
+               mode_changes[mode_count].caps = 0;
+               mode_changes[mode_count].nocaps = 0;
+               mode_changes[mode_count].mems = ALL_MEMBERS;
+               mode_changes[mode_count].id = targ_p->id;
+               mode_changes[mode_count].arg = targ_p->name;
+               mode_changes[mode_count++].client = targ_p;
+
+               mstptr->flags &= ~CHFL_OWNER;
+       }
+}
+
 void
 chm_op(struct Client *source_p, struct Channel *chptr,
        int alevel, int parc, int *parn,
@@ -818,7 +921,7 @@ chm_op(struct Client *source_p, struct Channel *chptr,
        const char *opnick;
        struct Client *targ_p;
 
-       if(alevel != CHFL_CHANOP)
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER)
        {
                if(!(*errors & SM_ERR_NOOPS))
                        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
@@ -897,6 +1000,103 @@ chm_op(struct Client *source_p, struct Channel *chptr,
        }
 }
 
+void
+chm_halfop(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)
+{
+       struct membership *mstptr;
+       const char *halfopnick;
+       struct Client *targ_p;
+
+       if(!ConfigChannel.use_halfop)
+       {
+               if(*errors & SM_ERR_UNKNOWN)
+                       return;
+               *errors |= SM_ERR_UNKNOWN;
+               sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name, source_p->name, c);
+               return;
+       }
+
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
+       {
+               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) || (parc <= *parn))
+               return;
+
+       halfopnick = parv[(*parn)];
+       (*parn)++;
+
+       /* empty nick */
+       if(EmptyString(halfopnick))
+       {
+               sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), "*");
+               return;
+       }
+
+       if((targ_p = find_chasing(source_p, halfopnick, NULL)) == NULL)
+       {
+               return;
+       }
+
+       mstptr = find_channel_membership(chptr, targ_p);
+
+       if(mstptr == NULL)
+       {
+               if(!(*errors & SM_ERR_NOTONCHANNEL) && MyClient(source_p))
+                       sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
+                                          form_str(ERR_USERNOTINCHANNEL), halfopnick, chptr->chname);
+               *errors |= SM_ERR_NOTONCHANNEL;
+               return;
+       }
+
+       if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
+               return;
+
+       if(dir == MODE_ADD)
+       {
+               if(targ_p == source_p)
+                       return;
+
+               mode_changes[mode_count].letter = c;
+               mode_changes[mode_count].dir = MODE_ADD;
+               mode_changes[mode_count].caps = 0;
+               mode_changes[mode_count].nocaps = 0;
+               mode_changes[mode_count].mems = ALL_MEMBERS;
+               mode_changes[mode_count].id = targ_p->id;
+               mode_changes[mode_count].arg = targ_p->name;
+               mode_changes[mode_count++].client = targ_p;
+
+               mstptr->flags |= CHFL_HALFOP;
+       }
+       else
+       {
+               if(MyClient(source_p) && IsService(targ_p))
+               {
+                       sendto_one(source_p, form_str(ERR_ISCHANSERVICE),
+                                  me.name, source_p->name, targ_p->name, chptr->chname);
+                       return;
+               }
+
+               mode_changes[mode_count].letter = c;
+               mode_changes[mode_count].dir = MODE_DEL;
+               mode_changes[mode_count].caps = 0;
+               mode_changes[mode_count].nocaps = 0;
+               mode_changes[mode_count].mems = ALL_MEMBERS;
+               mode_changes[mode_count].id = targ_p->id;
+               mode_changes[mode_count].arg = targ_p->name;
+               mode_changes[mode_count++].client = targ_p;
+
+               mstptr->flags &= ~CHFL_HALFOP;
+       }
+}
+
 void
 chm_voice(struct Client *source_p, struct Channel *chptr,
          int alevel, int parc, int *parn,
@@ -906,7 +1106,7 @@ chm_voice(struct Client *source_p, struct Channel *chptr,
        const char *opnick;
        struct Client *targ_p;
 
-       if(alevel != CHFL_CHANOP)
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
        {
                if(!(*errors & SM_ERR_NOOPS))
                        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
@@ -984,7 +1184,7 @@ chm_limit(struct Client *source_p, struct Channel *chptr,
        static char limitstr[30];
        int limit;
 
-       if(alevel != CHFL_CHANOP)
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
        {
                if(!(*errors & SM_ERR_NOOPS))
                        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
@@ -1043,7 +1243,7 @@ chm_throttle(struct Client *source_p, struct Channel *chptr,
 {
        int joins = 0, timeslice = 0;
 
-       if(alevel != CHFL_CHANOP)
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
        {
                if(!(*errors & SM_ERR_NOOPS))
                        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
@@ -1126,7 +1326,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
        }
 
 #ifndef FORWARD_OPERONLY
-       if(alevel != CHFL_CHANOP)
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
        {
                if(!(*errors & SM_ERR_NOOPS))
                        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
@@ -1218,7 +1418,7 @@ chm_key(struct Client *source_p, struct Channel *chptr,
 {
        char *key;
 
-       if(alevel != CHFL_CHANOP)
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
        {
                if(!(*errors & SM_ERR_NOOPS))
                        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
@@ -1295,7 +1495,7 @@ 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)
 {
-       if(alevel != CHFL_CHANOP)
+       if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
        {
                if(!(*errors & SM_ERR_NOOPS))
                        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
@@ -1429,14 +1629,14 @@ struct ChannelMode chmode_table[256] =
   {chm_nosuch, 0 },
   {chm_nosuch, 0 },
   {chm_nosuch, 0 },
-  {chm_nosuch, 0 },                    /* a */
+  {chm_owner,  0 },                    /* a */
   {chm_ban,    CHFL_BAN },             /* b */
   {chm_simple, MODE_NOCOLOR },         /* c */
   {chm_nosuch, 0 },                    /* d */
   {chm_ban,    CHFL_EXCEPTION },       /* e */
   {chm_forward,        0 },                    /* f */
   {chm_simple, MODE_FREEINVITE },      /* g */
-  {chm_nosuch, 0 },                    /* h */
+  {chm_halfop, 0 },                    /* h */
   {chm_simple, MODE_INVITEONLY },      /* i */
   {chm_throttle, 0 },                  /* j */
   {chm_key,    0 },                    /* k */