chmode: Allow mode queries on mlocked modes.
Check mlock at the same point where chanops are checked (except for querying a +e/+I list) and abstract this check into a function. In particular, /mode #channel f is now again allowed if +f is mlocked.
This commit is contained in:
parent
e4ce3b5409
commit
f3b3ad0b07
1 changed files with 46 additions and 69 deletions
115
src/chmode.c
115
src/chmode.c
|
@ -199,6 +199,42 @@ get_channel_access(struct Client *source_p, struct membership *msptr)
|
|||
return moduledata.approved;
|
||||
}
|
||||
|
||||
/* allow_mode_change()
|
||||
*
|
||||
* Checks if mlock and chanops permit a mode change.
|
||||
*
|
||||
* inputs - client, channel, access level, errors pointer, mode char
|
||||
* outputs - 0 on failure, 1 on success
|
||||
* side effects - error message sent on failure
|
||||
*/
|
||||
static int
|
||||
allow_mode_change(struct Client *source_p, struct Channel *chptr, int alevel,
|
||||
int *errors, char c)
|
||||
{
|
||||
/* 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;
|
||||
return 0;
|
||||
}
|
||||
if(alevel != CHFL_CHANOP)
|
||||
{
|
||||
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 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* add_id()
|
||||
*
|
||||
* inputs - client, channel, id to add, type, forward
|
||||
|
@ -576,14 +612,8 @@ 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(!(*errors & SM_ERR_NOOPS))
|
||||
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
|
||||
me.name, source_p->name, chptr->chname);
|
||||
*errors |= SM_ERR_NOOPS;
|
||||
if(!allow_mode_change(source_p, chptr, alevel, errors, c))
|
||||
return;
|
||||
}
|
||||
|
||||
if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE))
|
||||
return;
|
||||
|
@ -789,6 +819,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
|
|||
*errors |= errorval;
|
||||
|
||||
/* non-ops cant see +eI lists.. */
|
||||
/* note that this is still permitted if +e/+I are mlocked. */
|
||||
if(alevel != CHFL_CHANOP && mode_type != CHFL_BAN &&
|
||||
mode_type != CHFL_QUIET)
|
||||
{
|
||||
|
@ -816,14 +847,9 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
|
|||
return;
|
||||
}
|
||||
|
||||
if(alevel != CHFL_CHANOP)
|
||||
{
|
||||
if(!(*errors & SM_ERR_NOOPS))
|
||||
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
|
||||
me.name, source_p->name, chptr->chname);
|
||||
*errors |= SM_ERR_NOOPS;
|
||||
if(!allow_mode_change(source_p, chptr, alevel, errors, c))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
|
||||
return;
|
||||
|
@ -969,14 +995,8 @@ chm_op(struct Client *source_p, struct Channel *chptr,
|
|||
const char *opnick;
|
||||
struct Client *targ_p;
|
||||
|
||||
if(alevel != CHFL_CHANOP)
|
||||
{
|
||||
if(!(*errors & SM_ERR_NOOPS))
|
||||
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
|
||||
me.name, source_p->name, chptr->chname);
|
||||
*errors |= SM_ERR_NOOPS;
|
||||
if(!allow_mode_change(source_p, chptr, alevel, errors, c))
|
||||
return;
|
||||
}
|
||||
|
||||
if((dir == MODE_QUERY) || (parc <= *parn))
|
||||
return;
|
||||
|
@ -1057,14 +1077,8 @@ chm_voice(struct Client *source_p, struct Channel *chptr,
|
|||
const char *opnick;
|
||||
struct Client *targ_p;
|
||||
|
||||
if(alevel != CHFL_CHANOP)
|
||||
{
|
||||
if(!(*errors & SM_ERR_NOOPS))
|
||||
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
|
||||
me.name, source_p->name, chptr->chname);
|
||||
*errors |= SM_ERR_NOOPS;
|
||||
if(!allow_mode_change(source_p, chptr, alevel, errors, c))
|
||||
return;
|
||||
}
|
||||
|
||||
if((dir == MODE_QUERY) || parc <= *parn)
|
||||
return;
|
||||
|
@ -1135,14 +1149,8 @@ chm_limit(struct Client *source_p, struct Channel *chptr,
|
|||
static char limitstr[30];
|
||||
int limit;
|
||||
|
||||
if(alevel != CHFL_CHANOP)
|
||||
{
|
||||
if(!(*errors & SM_ERR_NOOPS))
|
||||
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
|
||||
me.name, source_p->name, chptr->chname);
|
||||
*errors |= SM_ERR_NOOPS;
|
||||
if(!allow_mode_change(source_p, chptr, alevel, errors, c))
|
||||
return;
|
||||
}
|
||||
|
||||
if(dir == MODE_QUERY)
|
||||
return;
|
||||
|
@ -1194,14 +1202,8 @@ chm_throttle(struct Client *source_p, struct Channel *chptr,
|
|||
{
|
||||
int joins = 0, timeslice = 0;
|
||||
|
||||
if(alevel != CHFL_CHANOP)
|
||||
{
|
||||
if(!(*errors & SM_ERR_NOOPS))
|
||||
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
|
||||
me.name, source_p->name, chptr->chname);
|
||||
*errors |= SM_ERR_NOOPS;
|
||||
if(!allow_mode_change(source_p, chptr, alevel, errors, c))
|
||||
return;
|
||||
}
|
||||
|
||||
if(dir == MODE_QUERY)
|
||||
return;
|
||||
|
@ -1275,14 +1277,8 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
|
|||
}
|
||||
|
||||
#ifndef FORWARD_OPERONLY
|
||||
if(alevel != CHFL_CHANOP)
|
||||
{
|
||||
if(!(*errors & SM_ERR_NOOPS))
|
||||
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
|
||||
me.name, source_p->name, chptr->chname);
|
||||
*errors |= SM_ERR_NOOPS;
|
||||
if(!allow_mode_change(source_p, chptr, alevel, errors, c))
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if(!IsOper(source_p) && !IsServer(source_p))
|
||||
{
|
||||
|
@ -1342,14 +1338,8 @@ chm_key(struct Client *source_p, struct Channel *chptr,
|
|||
{
|
||||
char *key;
|
||||
|
||||
if(alevel != CHFL_CHANOP)
|
||||
{
|
||||
if(!(*errors & SM_ERR_NOOPS))
|
||||
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
|
||||
me.name, source_p->name, chptr->chname);
|
||||
*errors |= SM_ERR_NOOPS;
|
||||
if(!allow_mode_change(source_p, chptr, alevel, errors, c))
|
||||
return;
|
||||
}
|
||||
|
||||
if(dir == MODE_QUERY)
|
||||
return;
|
||||
|
@ -1741,19 +1731,6 @@ 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,
|
||||
|
|
Loading…
Reference in a new issue