From f3b3ad0b07251e703e526f494c18f9e4286e1bd3 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Tue, 19 Jun 2012 00:33:29 +0200 Subject: [PATCH] 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. --- src/chmode.c | 115 +++++++++++++++++++++------------------------------ 1 file changed, 46 insertions(+), 69 deletions(-) diff --git a/src/chmode.c b/src/chmode.c index 3a6379de..4188f1d3 100644 --- a/src/chmode.c +++ b/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,