Initial support for 'noisy' oper-override of channel modes, using omode-type code. Supports simple modes at present.

This commit is contained in:
JD Horelick 2010-03-02 19:54:59 -05:00
parent 08e35f665f
commit eccd1c58d2
2 changed files with 103 additions and 75 deletions

View File

@ -114,6 +114,7 @@ struct ChModeChange
int caps; int caps;
int nocaps; int nocaps;
int mems; int mems;
int override;
struct Client *client; struct Client *client;
}; };

View File

@ -498,13 +498,21 @@ 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)
{ {
int override = 0;
if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP)
{ {
if(!(*errors & SM_ERR_NOOPS)) if (IsOverride(source_p))
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), override = 1;
me.name, source_p->name, chptr->chname); else
*errors |= SM_ERR_NOOPS; {
return; 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(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE)) if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE))
@ -526,6 +534,7 @@ chm_simple(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].nocaps = 0;
mode_changes[mode_count].id = NULL; mode_changes[mode_count].id = NULL;
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].arg = NULL; mode_changes[mode_count++].arg = NULL;
} }
else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type))
@ -538,6 +547,7 @@ chm_simple(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].nocaps = 0;
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = NULL; mode_changes[mode_count].id = NULL;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].arg = NULL; mode_changes[mode_count++].arg = NULL;
} }
} }
@ -1813,12 +1823,13 @@ void
set_channel_mode(struct Client *client_p, struct Client *source_p, set_channel_mode(struct Client *client_p, struct Client *source_p,
struct Channel *chptr, struct membership *msptr, int parc, const char *parv[]) struct Channel *chptr, struct membership *msptr, int parc, const char *parv[])
{ {
static char cmdbuf[BUFSIZE];
static char modebuf[BUFSIZE]; static char modebuf[BUFSIZE];
static char parabuf[BUFSIZE]; static char parabuf[BUFSIZE];
char *mbuf; char *mbuf;
char *pbuf; char *pbuf;
int cur_len, mlen, paralen, paracount, arglen, len; int cur_len, mlen, paralen, paracount, arglen, len;
int i, j, flags; int i, j, flags, override;
int dir = MODE_ADD; int dir = MODE_ADD;
int parn = 1; int parn = 1;
int errors = 0; int errors = 0;
@ -1867,87 +1878,103 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
return; return;
if(IsServer(source_p)) if(IsServer(source_p))
mlen = rb_sprintf(modebuf, ":%s MODE %s ", fakesource_p->name, chptr->chname); rb_sprintf(cmdbuf, ":%s MODE %s ", fakesource_p->name, chptr->chname);
else else
mlen = rb_sprintf(modebuf, ":%s!%s@%s MODE %s ", rb_sprintf(cmdbuf, ":%s!%s@%s MODE %s ",
source_p->name, source_p->username, source_p->name, source_p->username,
source_p->host, chptr->chname); source_p->host, chptr->chname);
for(j = 0, flags = ALL_MEMBERS; j < 2; j++, flags = ONLY_CHANOPS) for (override = 0; override < (IsOverride(source_p) ? 2 : 1); ++override)
{ {
cur_len = mlen; int was_on_chan = 0;
mbuf = modebuf + mlen; if(override)
pbuf = parabuf;
parabuf[0] = '\0';
paracount = paralen = 0;
dir = MODE_QUERY;
for(i = 0; i < mode_count; i++)
{ {
if(mode_changes[i].letter == 0 || mode_changes[i].mems != flags) if(msptr)
continue; was_on_chan = 1;
if(mode_changes[i].arg != NULL)
{
arglen = strlen(mode_changes[i].arg);
if(arglen > MODEBUFLEN - 5)
continue;
}
else else
arglen = 0; add_user_to_channel(chptr, source_p, 0);
/* if we're creeping over MAXMODEPARAMSSERV, or over
* bufsize (4 == +/-,modechar,two spaces) send now.
*/
if(mode_changes[i].arg != NULL &&
((paracount == MAXMODEPARAMSSERV) ||
((cur_len + paralen + arglen + 4) > (BUFSIZE - 3))))
{
*mbuf = '\0';
if(cur_len > mlen)
sendto_channel_local(flags, chptr, "%s %s", modebuf,
parabuf);
else
continue;
paracount = paralen = 0;
cur_len = mlen;
mbuf = modebuf + mlen;
pbuf = parabuf;
parabuf[0] = '\0';
dir = MODE_QUERY;
}
if(dir != mode_changes[i].dir)
{
*mbuf++ = (mode_changes[i].dir == MODE_ADD) ? '+' : '-';
cur_len++;
dir = mode_changes[i].dir;
}
*mbuf++ = mode_changes[i].letter;
cur_len++;
if(mode_changes[i].arg != NULL)
{
paracount++;
len = rb_sprintf(pbuf, "%s ", mode_changes[i].arg);
pbuf += len;
paralen += len;
}
} }
if(paralen && parabuf[paralen - 1] == ' ') for(j = 0, flags = ALL_MEMBERS; j < 2; j++, flags = ONLY_CHANOPS)
parabuf[paralen - 1] = '\0'; {
cur_len = mlen;
mbuf = modebuf + mlen;
pbuf = parabuf;
parabuf[0] = '\0';
paracount = paralen = 0;
dir = MODE_QUERY;
*mbuf = '\0'; for(i = 0; i < mode_count; i++)
if(cur_len > mlen) {
sendto_channel_local(flags, chptr, "%s %s", modebuf, parabuf); if(mode_changes[i].letter == 0 || mode_changes[i].mems != flags)
if(mode_changes[i].override != override)
continue;
if(mode_changes[i].arg != NULL)
{
arglen = strlen(mode_changes[i].arg);
if(arglen > MODEBUFLEN - 5)
continue;
}
else
arglen = 0;
/* if we're creeping over MAXMODEPARAMSSERV, or over
* bufsize (4 == +/-,modechar,two spaces) send now.
*/
if(mode_changes[i].arg != NULL &&
((paracount == MAXMODEPARAMSSERV) ||
((cur_len + paralen + arglen + 4) > (BUFSIZE - 3))))
{
*mbuf = '\0';
if(cur_len > mlen)
{
sendto_channel_local(flags, chptr, "%s%s %s",
cmdbuf, modebuf, parabuf);
if(override)
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"%s is overriding modes on %s: %s %s",
get_oper_name(source_p), chptr->chname,
modebuf, parabuf);
}
else
continue;
paracount = paralen = 0;
cur_len = mlen;
mbuf = modebuf + mlen;
pbuf = parabuf;
parabuf[0] = '\0';
dir = MODE_QUERY;
}
if(dir != mode_changes[i].dir)
{
*mbuf++ = (mode_changes[i].dir == MODE_ADD) ? '+' : '-';
cur_len++;
dir = mode_changes[i].dir;
}
*mbuf++ = mode_changes[i].letter;
cur_len++;
if(mode_changes[i].arg != NULL)
{
paracount++;
len = rb_sprintf(pbuf, "%s ", mode_changes[i].arg);
pbuf += len;
paralen += len;
}
}
if(override && !was_on_chan)
remove_user_from_channel(find_channel_membership(chptr, source_p));
} }
/* only propagate modes originating locally, or if we're hubbing */ /* only propagate modes originating locally, or if we're hubbing */
if(MyClient(source_p) || rb_dlink_list_length(&serv_list) > 1) if(MyClient(source_p) || rb_dlink_list_length(&serv_list) > 1)
send_cap_mode_changes(client_p, source_p, chptr, mode_changes, mode_count); send_cap_mode_changes(client_p, source_p, chptr, mode_changes, mode_count);
}
} }