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:
Jilles Tjoelker 2012-06-19 00:33:29 +02:00
parent e4ce3b5409
commit f3b3ad0b07

View file

@ -199,6 +199,42 @@ get_channel_access(struct Client *source_p, struct membership *msptr)
return moduledata.approved; 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() /* add_id()
* *
* inputs - client, channel, id to add, type, forward * 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, int alevel, int parc, int *parn,
const char **parv, int *errors, int dir, char c, long mode_type) const char **parv, int *errors, int dir, char c, long mode_type)
{ {
if(alevel != CHFL_CHANOP) if(!allow_mode_change(source_p, chptr, alevel, errors, c))
{
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; return;
}
if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE)) if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE))
return; return;
@ -789,6 +819,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
*errors |= errorval; *errors |= errorval;
/* non-ops cant see +eI lists.. */ /* 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 && if(alevel != CHFL_CHANOP && mode_type != CHFL_BAN &&
mode_type != CHFL_QUIET) mode_type != CHFL_QUIET)
{ {
@ -816,14 +847,9 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
return; return;
} }
if(alevel != CHFL_CHANOP) if(!allow_mode_change(source_p, chptr, alevel, errors, c))
{
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; return;
}
if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS)) if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
return; return;
@ -969,14 +995,8 @@ chm_op(struct Client *source_p, struct Channel *chptr,
const char *opnick; const char *opnick;
struct Client *targ_p; struct Client *targ_p;
if(alevel != CHFL_CHANOP) if(!allow_mode_change(source_p, chptr, alevel, errors, c))
{
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; return;
}
if((dir == MODE_QUERY) || (parc <= *parn)) if((dir == MODE_QUERY) || (parc <= *parn))
return; return;
@ -1057,14 +1077,8 @@ chm_voice(struct Client *source_p, struct Channel *chptr,
const char *opnick; const char *opnick;
struct Client *targ_p; struct Client *targ_p;
if(alevel != CHFL_CHANOP) if(!allow_mode_change(source_p, chptr, alevel, errors, c))
{
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; return;
}
if((dir == MODE_QUERY) || parc <= *parn) if((dir == MODE_QUERY) || parc <= *parn)
return; return;
@ -1135,14 +1149,8 @@ chm_limit(struct Client *source_p, struct Channel *chptr,
static char limitstr[30]; static char limitstr[30];
int limit; int limit;
if(alevel != CHFL_CHANOP) if(!allow_mode_change(source_p, chptr, alevel, errors, c))
{
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; return;
}
if(dir == MODE_QUERY) if(dir == MODE_QUERY)
return; return;
@ -1194,14 +1202,8 @@ chm_throttle(struct Client *source_p, struct Channel *chptr,
{ {
int joins = 0, timeslice = 0; int joins = 0, timeslice = 0;
if(alevel != CHFL_CHANOP) if(!allow_mode_change(source_p, chptr, alevel, errors, c))
{
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; return;
}
if(dir == MODE_QUERY) if(dir == MODE_QUERY)
return; return;
@ -1275,14 +1277,8 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
} }
#ifndef FORWARD_OPERONLY #ifndef FORWARD_OPERONLY
if(alevel != CHFL_CHANOP) if(!allow_mode_change(source_p, chptr, alevel, errors, c))
{
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; return;
}
#else #else
if(!IsOper(source_p) && !IsServer(source_p)) if(!IsOper(source_p) && !IsServer(source_p))
{ {
@ -1342,14 +1338,8 @@ chm_key(struct Client *source_p, struct Channel *chptr,
{ {
char *key; char *key;
if(alevel != CHFL_CHANOP) if(!allow_mode_change(source_p, chptr, alevel, errors, c))
{
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; return;
}
if(dir == MODE_QUERY) if(dir == MODE_QUERY)
return; return;
@ -1741,19 +1731,6 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
dir = MODE_QUERY; dir = MODE_QUERY;
break; break;
default: 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, chmode_table[(unsigned char) c].set_func(fakesource_p, chptr, alevel,
parc, &parn, parv, parc, &parn, parv,
&errors, dir, c, &errors, dir, c,