Automated merge with ssh://shadowircd/uranium/shadowircd/

This commit is contained in:
B.Greenham 2010-03-03 20:38:57 -05:00
commit 3b0e9fa20e
13 changed files with 393 additions and 92 deletions

View File

@ -4,8 +4,6 @@ Todo list for ShadowIRCd 6.0
* custom operstrings * custom operstrings
* norepeat cmode * norepeat cmode
* kicknorejoin (+J in inspircd chmode) * kicknorejoin (+J in inspircd chmode)
* operoverride umode (+p), steal this from ircd-seven
* immune cmode (+M), steal this from ircd-seven too
* Anything else we think of between now and release. :P * Anything else we think of between now and release. :P
Todo list for ShadowIRCd 6.1 Todo list for ShadowIRCd 6.1

View File

@ -231,7 +231,7 @@ privset "global_op" {
privset "admin" { privset "admin" {
extends = "global_op"; extends = "global_op";
privs = oper:admin, oper:die, oper:rehash, oper:spy; privs = oper:admin, oper:die, oper:rehash, oper:spy, oper:override;
}; };
operator "god" { operator "god" {

View File

@ -419,6 +419,9 @@ privset "local_op" {
* oper:xline: allows use of /quote xline/unxline * oper:xline: allows use of /quote xline/unxline
* oper:resv: allows /quote resv/unresv and cmode +LP * oper:resv: allows /quote resv/unresv and cmode +LP
* oper:operwall: allows the oper to send/receive operwalls * oper:operwall: allows the oper to send/receive operwalls
* oper:override: allows the oper to set umode +p on themself
* which grants the ability to have implicit
* operator access in all channels.
* oper:spy: allows 'operspy' features to see through +s * oper:spy: allows 'operspy' features to see through +s
* channels etc. see /quote help operspy * channels etc. see /quote help operspy
* oper:hidden: hides the oper from /stats p * oper:hidden: hides the oper from /stats p
@ -442,7 +445,7 @@ privset "global_op" {
privset "admin" { privset "admin" {
extends = "global_op"; extends = "global_op";
privs = oper:admin, oper:die, oper:rehash, oper:spy; privs = oper:admin, oper:die, oper:rehash, oper:spy, oper:override;
}; };
/* operator {}: defines ircd operators. (OLD O:) */ /* operator {}: defines ircd operators. (OLD O:) */

View File

@ -46,6 +46,7 @@ SRCS = \
force_user_invis.c \ force_user_invis.c \
hurt.c \ hurt.c \
ip_cloaking.c \ ip_cloaking.c \
make_override_immune.c \
sno_farconnect.c \ sno_farconnect.c \
sno_globalkline.c \ sno_globalkline.c \
sno_globaloper.c \ sno_globaloper.c \

View File

@ -0,0 +1,36 @@
#include "stdinc.h"
#include "modules.h"
#include "hook.h"
#include "client.h"
#include "ircd.h"
#include "send.h"
#include "numeric.h"
#include "chmode.h"
#include "s_newconf.h"
static void can_kick(hook_data_channel_approval *);
mapi_hfn_list_av1 nooperkick_hfnlist[] = {
{ "can_kick", (hookfn) can_kick },
{ NULL, NULL }
};
DECLARE_MODULE_AV1(chm_no_oper_kick, NULL, NULL, NULL, NULL, nooperkick_hfnlist, "$Revision$");
static void
can_kick(hook_data_channel_approval *data)
{
struct Client *source_p = data->client;
struct Client *target_p = data->target;
struct Channel *chptr = data->chptr;
if (target_p->umodes & UMODE_OVERRIDE && data->approved)
{
sendto_one_numeric(source_p, ERR_ISCHANSERVICE,
"%s %s :User is immune from kick.",
target_p->name, chptr->chname);
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Overriding KICK from %s on %s in %s (user is immune)",
source_p->name, target_p->name, chptr->chname);
data->approved = 0;
}
}

View File

@ -150,6 +150,7 @@ typedef int (*ExtbanFunc)(const char *data, struct Client *client_p,
#define ONLY_SERVERS 0x0020 #define ONLY_SERVERS 0x0020
#define CHFL_HALFOP 0x0040 #define CHFL_HALFOP 0x0040
#define CHFL_OWNER 0x0080 #define CHFL_OWNER 0x0080
#define ONLY_OPERS 0x0100
#define ALL_MEMBERS CHFL_PEON #define ALL_MEMBERS CHFL_PEON
#define ONLY_CHANOPS CHFL_CHANOP #define ONLY_CHANOPS CHFL_CHANOP
#define ONLY_CHANOPSVOICED (CHFL_CHANOP|CHFL_VOICE) #define ONLY_CHANOPSVOICED (CHFL_CHANOP|CHFL_VOICE)
@ -183,6 +184,7 @@ typedef int (*ExtbanFunc)(const char *data, struct Client *client_p,
#define MODE_NOCAPS 0x100000 /* Block messages in all capital letters */ #define MODE_NOCAPS 0x100000 /* Block messages in all capital letters */
#define MODE_NOREJOIN 0x200000 /* Block rejoin immediately after kick */ #define MODE_NOREJOIN 0x200000 /* Block rejoin immediately after kick */
#define MODE_NOREPEAT 0x400000 /* Block repeat messages */ #define MODE_NOREPEAT 0x400000 /* Block repeat messages */
#define MODE_NOOPERKICK 0x800000 /* disallow kicking opers */
#define CHFL_BAN 0x10000000 /* ban channel flag */ #define CHFL_BAN 0x10000000 /* ban channel flag */
#define CHFL_EXCEPTION 0x20000000 /* exception to ban channel flag */ #define CHFL_EXCEPTION 0x20000000 /* exception to ban channel flag */

View File

@ -48,6 +48,9 @@ extern void chm_simple(struct Client *source_p, struct Channel *chptr,
extern void chm_ban(struct Client *source_p, struct Channel *chptr, extern void chm_ban(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);
extern void chm_hidden(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);
extern void chm_staff(struct Client *source_p, struct Channel *chptr, extern void chm_staff(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);

View File

@ -67,9 +67,10 @@ static void remove_ban_list(struct Channel *chptr, struct Client *source_p,
rb_dlink_list * list, char c, int mems); rb_dlink_list * list, char c, int mems);
static char modebuf[MODEBUFLEN]; static char modebuf[MODEBUFLEN];
static char omodebuf[MODEBUFLEN];
static char parabuf[MODEBUFLEN]; static char parabuf[MODEBUFLEN];
static const char *para[MAXMODEPARAMS]; static const char *para[MAXMODEPARAMS];
static char *mbuf; static char *mbuf, *ombuf;
static int pargs; static int pargs;
/* /*
@ -122,6 +123,7 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char *
return 0; return 0;
mbuf = modebuf; mbuf = modebuf;
ombuf = omodebuf;
mode.key[0] = mode.forward[0] = '\0'; mode.key[0] = mode.forward[0] = '\0';
mode.mode = mode.limit = mode.join_num = mode.join_time = 0; mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
@ -190,7 +192,12 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char *
":%s MODE %s %s %s", ":%s MODE %s %s %s",
source_p->servptr->name, source_p->servptr->name,
chptr->chname, modebuf, parabuf); chptr->chname, modebuf, parabuf);
*modebuf = *parabuf = '\0'; if(*omodebuf != '\0')
sendto_channel_local(ONLY_OPERS, chptr,
":%s MODE %s %s %s",
source_p->servptr->name,
chptr->chname, modebuf, parabuf);
*omodebuf = *modebuf = *parabuf = '\0';
} }
if(!IsMember(source_p, chptr)) if(!IsMember(source_p, chptr))
@ -249,7 +256,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
if(*parv[2] == '&') if(*parv[2] == '&')
return 0; return 0;
modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0'; omodebuf[0] = modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0';
pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0; pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
/* Hide connecting server on netburst -- jilles */ /* Hide connecting server on netburst -- jilles */
@ -259,6 +266,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
fakesource_p = source_p; fakesource_p = source_p;
mbuf = modebuf; mbuf = modebuf;
ombuf = omodebuf;
newts = atol(parv[1]); newts = atol(parv[1]);
s = parv[3]; s = parv[3];
@ -457,7 +465,11 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s", sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s",
fakesource_p->name, chptr->chname, modebuf, parabuf); fakesource_p->name, chptr->chname, modebuf, parabuf);
*modebuf = *parabuf = '\0'; if(*omodebuf != '\0')
sendto_channel_local(ONLY_OPERS, chptr, ":%s MODE %s %s %s",
fakesource_p->name, chptr->chname, omodebuf, parabuf);
*omodebuf = *modebuf = *parabuf = '\0';
if(parv[3][0] != '0' && keep_new_modes) if(parv[3][0] != '0' && keep_new_modes)
modes = channel_modes(chptr, source_p); modes = channel_modes(chptr, source_p);
@ -469,6 +481,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
ptr_uid = buf_uid + mlen_uid; ptr_uid = buf_uid + mlen_uid;
mbuf = modebuf; mbuf = modebuf;
ombuf = omodebuf;
para[0] = para[1] = para[2] = para[3] = empty; para[0] = para[1] = para[2] = para[3] = empty;
pargs = 0; pargs = 0;
len_nick = len_uid = 0; len_nick = len_uid = 0;
@ -799,7 +812,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
static void static void
set_final_mode(struct Mode *mode, struct Mode *oldmode) set_final_mode(struct Mode *mode, struct Mode *oldmode)
{ {
int dir = MODE_QUERY; int dir = MODE_QUERY, odir = MODE_QUERY;
char *pbuf = parabuf; char *pbuf = parabuf;
int len; int len;
int i; int i;
@ -809,12 +822,25 @@ set_final_mode(struct Mode *mode, struct Mode *oldmode)
{ {
if((mode->mode & chmode_flags[i]) && !(oldmode->mode & chmode_flags[i])) if((mode->mode & chmode_flags[i]) && !(oldmode->mode & chmode_flags[i]))
{ {
if(dir != MODE_ADD) if (chmode_table[i].set_func == chm_hidden)
{ {
*mbuf++ = '+'; if(odir != MODE_ADD)
dir = MODE_ADD; {
*ombuf++ = '+';
odir = MODE_ADD;
}
*ombuf++ = i;
}
else
{
if(dir != MODE_ADD)
{
*mbuf++ = '+';
dir = MODE_ADD;
}
*mbuf++ = i;
} }
*mbuf++ = i;
} }
} }
@ -823,12 +849,24 @@ set_final_mode(struct Mode *mode, struct Mode *oldmode)
{ {
if((oldmode->mode & chmode_flags[i]) && !(mode->mode & chmode_flags[i])) if((oldmode->mode & chmode_flags[i]) && !(mode->mode & chmode_flags[i]))
{ {
if(dir != MODE_DEL) if(chmode_table[i].set_func == chm_hidden)
{ {
*mbuf++ = '-'; if(odir != MODE_DEL)
dir = MODE_DEL; {
*ombuf++ = '-';
odir = MODE_DEL;
}
*ombuf++ = i;
}
else
{
if(dir != MODE_DEL)
{
*mbuf++ = '-';
dir = MODE_DEL;
}
*mbuf++ = i;
} }
*mbuf++ = i;
} }
} }

View File

@ -173,6 +173,17 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
return 0; return 0;
} }
if (MyClient(source_p) && chptr->mode.mode & MODE_NOOPERKICK && IsOper(who))
{
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Overriding KICK from %s on %s in %s (channel is +M)",
source_p->name, who->name, chptr->chname);
sendto_one_numeric(source_p, ERR_ISCHANSERVICE,
"%s %s :Cannot kick IRC operators from that channel.",
who->name, chptr->chname);
return 0;
}
if(MyClient(source_p)) if(MyClient(source_p))
{ {
hook_data_channel_approval hookdata; hook_data_channel_approval hookdata;

View File

@ -105,6 +105,8 @@ m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *
/* setting topic */ /* setting topic */
if(parc > 2) if(parc > 2)
{ {
char topic_info[USERHOST_REPLYLEN];
msptr = find_channel_membership(chptr, source_p); msptr = find_channel_membership(chptr, source_p);
if(msptr == NULL) if(msptr == NULL)
@ -114,9 +116,20 @@ m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *
return 0; return 0;
} }
if((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || is_any_op(msptr) || IsOverride(source_p)) if(MyClient(source_p) && (chptr->mode.mode & MODE_TOPICLIMIT) && !is_chanop(msptr))
{ {
char topic_info[USERHOST_REPLYLEN]; if(IsOverride(source_p))
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"%s is overriding TOPIC on [%s]",
get_oper_name(source_p), chptr->chname);
else
{
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
me.name, source_p->name, parv[1]);
return 0;
}
}
if(ConfigChannel.host_in_topic) if(ConfigChannel.host_in_topic)
rb_sprintf(topic_info, "%s!%s@%s", rb_sprintf(topic_info, "%s!%s@%s",
@ -135,11 +148,7 @@ m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *
source_p->name, source_p->username, source_p->name, source_p->username,
source_p->host, chptr->chname, source_p->host, chptr->chname,
chptr->topic == NULL ? "" : chptr->topic); chptr->topic == NULL ? "" : chptr->topic);
}
else
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
get_id(&me, source_p),
get_id(source_p, source_p), name);
} }
else if(MyClient(source_p)) else if(MyClient(source_p))
{ {

View File

@ -1252,8 +1252,12 @@ channel_modes(struct Channel *chptr, struct Client *client_p)
*pbuf = '\0'; *pbuf = '\0';
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{
if(chmode_table[i].set_func == chm_hidden && !IsOper(client_p) && IsClient(client_p))
continue;
if(chptr->mode.mode & chmode_flags[i]) if(chptr->mode.mode & chmode_flags[i])
*mbuf++ = i; *mbuf++ = i;
}
if(chptr->mode.limit) if(chptr->mode.limit)
{ {

View File

@ -64,6 +64,7 @@ static int mode_count;
static int mode_limit; static int mode_limit;
static int mode_limit_simple; static int mode_limit_simple;
static int mask_pos; static int mask_pos;
static int no_override_deop;
char cflagsbuf[256]; char cflagsbuf[256];
char cflagsmyinfo[256]; char cflagsmyinfo[256];
@ -586,6 +587,59 @@ chm_orphaned(struct Client *source_p, struct Channel *chptr,
} }
} }
void
chm_hidden(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(!IsOper(source_p) && !IsServer(source_p))
{
if(!(*errors & SM_ERR_NOPRIVS))
sendto_one_numeric(source_p, ERR_NOPRIVILEGES, form_str(ERR_NOPRIVILEGES));
*errors |= SM_ERR_NOPRIVS;
return;
}
if(MyClient(source_p) && !IsOperAdmin(source_p))
{
if(!(*errors & SM_ERR_NOPRIVS))
sendto_one(source_p, form_str(ERR_NOPRIVS), me.name,
source_p->name, "cmodes");
*errors |= SM_ERR_NOPRIVS;
return;
}
if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE))
return;
/* setting + */
if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type))
{
chptr->mode.mode |= mode_type;
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].id = NULL;
mode_changes[mode_count].mems = ONLY_OPERS;
mode_changes[mode_count].override = 0;
mode_changes[mode_count++].arg = NULL;
}
else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type))
{
chptr->mode.mode &= ~mode_type;
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 = ONLY_OPERS;
mode_changes[mode_count].id = NULL;
mode_changes[mode_count].override = 0;
mode_changes[mode_count++].arg = NULL;
}
}
void void
chm_staff(struct Client *source_p, struct Channel *chptr, chm_staff(struct Client *source_p, struct Channel *chptr,
int alevel, int parc, int *parn, int alevel, int parc, int *parn,
@ -621,6 +675,7 @@ chm_staff(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 = 0;
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))
@ -632,6 +687,7 @@ chm_staff(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].caps = 0; mode_changes[mode_count].caps = 0;
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].override = 0;
mode_changes[mode_count].id = NULL; mode_changes[mode_count].id = NULL;
mode_changes[mode_count++].arg = NULL; mode_changes[mode_count++].arg = NULL;
} }
@ -652,6 +708,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
int rpl_endlist; int rpl_endlist;
int caps; int caps;
int mems; int mems;
int override = 0;
switch (mode_type) switch (mode_type)
{ {
@ -725,11 +782,22 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP && mode_type != CHFL_BAN && if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP && mode_type != CHFL_BAN &&
mode_type != CHFL_QUIET) mode_type != CHFL_QUIET)
{ {
if(!(*errors & SM_ERR_NOOPS)) if(IsOverride(source_p))
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), {
me.name, source_p->name, chptr->chname); sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
*errors |= SM_ERR_NOOPS; "%s is overriding modes on %s: (%s list)",
return; get_oper_name(source_p), chptr->chname,
mode_type == CHFL_INVEX ? "invex" : "exempt");
}
else
{
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;
}
} }
RB_DLINK_FOREACH(ptr, list->head) RB_DLINK_FOREACH(ptr, list->head)
@ -748,11 +816,17 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
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 > MAXMODEPARAMS)) if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
@ -804,6 +878,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].nocaps = 0;
mode_changes[mode_count].mems = mems; mode_changes[mode_count].mems = mems;
mode_changes[mode_count].id = NULL; mode_changes[mode_count].id = NULL;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].arg = mask; mode_changes[mode_count++].arg = mask;
} }
else if(dir == MODE_DEL) else if(dir == MODE_DEL)
@ -821,6 +896,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].nocaps = 0;
mode_changes[mode_count].mems = mems; mode_changes[mode_count].mems = mems;
mode_changes[mode_count].id = NULL; mode_changes[mode_count].id = NULL;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].arg = mask; mode_changes[mode_count++].arg = mask;
} }
} }
@ -833,6 +909,7 @@ chm_owner(struct Client *source_p, struct Channel *chptr,
struct membership *mstptr; struct membership *mstptr;
const char *ownernick; const char *ownernick;
struct Client *targ_p; struct Client *targ_p;
int override = 0;
if(!ConfigChannel.use_owner) if(!ConfigChannel.use_owner)
{ {
@ -845,11 +922,17 @@ chm_owner(struct Client *source_p, struct Channel *chptr,
if(alevel != CHFL_OWNER) if(alevel != CHFL_OWNER)
{ {
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((dir == MODE_QUERY) || (parc <= *parn)) if((dir == MODE_QUERY) || (parc <= *parn))
@ -887,7 +970,14 @@ chm_owner(struct Client *source_p, struct Channel *chptr,
if(dir == MODE_ADD) if(dir == MODE_ADD)
{ {
if(targ_p == source_p) if(targ_p == source_p)
return; {
no_override_deop = 1;
/* Don't reject modes from remote. It desyncs, and this is perfectly
* legitimate from a remote override oper.
if(!override)
return;
*/
}
mode_changes[mode_count].letter = c; mode_changes[mode_count].letter = c;
mode_changes[mode_count].dir = MODE_ADD; mode_changes[mode_count].dir = MODE_ADD;
@ -896,6 +986,7 @@ chm_owner(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name; mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p; mode_changes[mode_count++].client = targ_p;
mstptr->flags |= CHFL_OWNER; mstptr->flags |= CHFL_OWNER;
@ -916,6 +1007,7 @@ chm_owner(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name; mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p; mode_changes[mode_count++].client = targ_p;
mstptr->flags &= ~CHFL_OWNER; mstptr->flags &= ~CHFL_OWNER;
@ -930,14 +1022,21 @@ chm_op(struct Client *source_p, struct Channel *chptr,
struct membership *mstptr; struct membership *mstptr;
const char *opnick; const char *opnick;
struct Client *targ_p; struct Client *targ_p;
int override = 0;
if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER) if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER)
{ {
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((dir == MODE_QUERY) || (parc <= *parn)) if((dir == MODE_QUERY) || (parc <= *parn))
@ -975,7 +1074,14 @@ chm_op(struct Client *source_p, struct Channel *chptr,
if(dir == MODE_ADD) if(dir == MODE_ADD)
{ {
if(targ_p == source_p) if(targ_p == source_p)
return; {
no_override_deop = 1;
/* Don't reject modes from remote. It desyncs, and this is perfectly
* legitimate from a remote override oper.
if(!override)
return;
*/
}
mode_changes[mode_count].letter = c; mode_changes[mode_count].letter = c;
mode_changes[mode_count].dir = MODE_ADD; mode_changes[mode_count].dir = MODE_ADD;
@ -984,6 +1090,7 @@ chm_op(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name; mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p; mode_changes[mode_count++].client = targ_p;
mstptr->flags |= CHFL_CHANOP; mstptr->flags |= CHFL_CHANOP;
@ -1004,6 +1111,7 @@ chm_op(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name; mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p; mode_changes[mode_count++].client = targ_p;
mstptr->flags &= ~CHFL_CHANOP; mstptr->flags &= ~CHFL_CHANOP;
@ -1018,6 +1126,7 @@ chm_halfop(struct Client *source_p, struct Channel *chptr,
struct membership *mstptr; struct membership *mstptr;
const char *halfopnick; const char *halfopnick;
struct Client *targ_p; struct Client *targ_p;
int override = 0;
if(!ConfigChannel.use_halfop) if(!ConfigChannel.use_halfop)
{ {
@ -1030,11 +1139,17 @@ chm_halfop(struct Client *source_p, struct Channel *chptr,
if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER) if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER)
{ {
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((dir == MODE_QUERY) || (parc <= *parn)) if((dir == MODE_QUERY) || (parc <= *parn))
@ -1072,7 +1187,14 @@ chm_halfop(struct Client *source_p, struct Channel *chptr,
if(dir == MODE_ADD) if(dir == MODE_ADD)
{ {
if(targ_p == source_p) if(targ_p == source_p)
return; {
no_override_deop = 1;
/* Don't reject modes from remote. It desyncs, and this is perfectly
* legitimate from a remote override oper.
if(!override)
return;
*/
}
mode_changes[mode_count].letter = c; mode_changes[mode_count].letter = c;
mode_changes[mode_count].dir = MODE_ADD; mode_changes[mode_count].dir = MODE_ADD;
@ -1081,6 +1203,7 @@ chm_halfop(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name; mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p; mode_changes[mode_count++].client = targ_p;
mstptr->flags |= CHFL_HALFOP; mstptr->flags |= CHFL_HALFOP;
@ -1101,6 +1224,7 @@ chm_halfop(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name; mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p; mode_changes[mode_count++].client = targ_p;
mstptr->flags &= ~CHFL_HALFOP; mstptr->flags &= ~CHFL_HALFOP;
@ -1115,14 +1239,21 @@ chm_voice(struct Client *source_p, struct Channel *chptr,
struct membership *mstptr; struct membership *mstptr;
const char *opnick; const char *opnick;
struct Client *targ_p; struct Client *targ_p;
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((dir == MODE_QUERY) || parc <= *parn) if((dir == MODE_QUERY) || parc <= *parn)
@ -1166,6 +1297,7 @@ chm_voice(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name; mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p; mode_changes[mode_count++].client = targ_p;
mstptr->flags |= CHFL_VOICE; mstptr->flags |= CHFL_VOICE;
@ -1179,6 +1311,7 @@ chm_voice(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id; mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name; mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p; mode_changes[mode_count++].client = targ_p;
mstptr->flags &= ~CHFL_VOICE; mstptr->flags &= ~CHFL_VOICE;
@ -1193,14 +1326,20 @@ chm_limit(struct Client *source_p, struct Channel *chptr,
const char *lstr; const char *lstr;
static char limitstr[30]; static char limitstr[30];
int limit; int limit;
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(dir == MODE_QUERY) if(dir == MODE_QUERY)
@ -1225,6 +1364,7 @@ chm_limit(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 = limitstr; mode_changes[mode_count++].arg = limitstr;
chptr->mode.limit = limit; chptr->mode.limit = limit;
@ -1242,6 +1382,7 @@ chm_limit(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;
} }
} }
@ -1252,14 +1393,21 @@ chm_throttle(struct Client *source_p, struct Channel *chptr,
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 joins = 0, timeslice = 0; int joins = 0, timeslice = 0;
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(dir == MODE_QUERY) if(dir == MODE_QUERY)
@ -1281,6 +1429,7 @@ chm_throttle(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 = parv[(*parn)]; mode_changes[mode_count++].arg = parv[(*parn)];
(*parn)++; (*parn)++;
@ -1304,6 +1453,7 @@ chm_throttle(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;
} }
} }
@ -1316,6 +1466,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
struct Channel *targptr = NULL; struct Channel *targptr = NULL;
struct membership *msptr; struct membership *msptr;
const char *forward; const char *forward;
int override = 0;
/* if +f is disabled, ignore local attempts to set it */ /* if +f is disabled, ignore local attempts to set it */
if(!ConfigChannel.use_forward && MyClient(source_p) && if(!ConfigChannel.use_forward && MyClient(source_p) &&
@ -1338,11 +1489,16 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
#ifndef FORWARD_OPERONLY #ifndef FORWARD_OPERONLY
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;
}
} }
#else #else
if(!IsOper(source_p) && !IsServer(source_p)) if(!IsOper(source_p) && !IsServer(source_p))
@ -1388,9 +1544,14 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
if((msptr = find_channel_membership(targptr, source_p)) == NULL || if((msptr = find_channel_membership(targptr, source_p)) == NULL ||
is_any_op(msptr)) is_any_op(msptr))
{ {
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), if(IsOverride(source_p))
me.name, source_p->name, targptr->chname); override = 1;
return; else
{
sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
me.name, source_p->name, targptr->chname);
return;
}
} }
} }
@ -1402,6 +1563,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
mode_changes[mode_count].nocaps = 0; mode_changes[mode_count].nocaps = 0;
mode_changes[mode_count].mems = ConfigChannel.use_forward ? ALL_MEMBERS : ONLY_SERVERS; mode_changes[mode_count].mems = ConfigChannel.use_forward ? ALL_MEMBERS : ONLY_SERVERS;
mode_changes[mode_count].id = NULL; mode_changes[mode_count].id = NULL;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].arg = forward; mode_changes[mode_count++].arg = forward;
} }
else if(dir == MODE_DEL) else if(dir == MODE_DEL)
@ -1417,6 +1579,7 @@ chm_forward(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;
} }
} }
@ -1427,14 +1590,20 @@ chm_key(struct Client *source_p, struct Channel *chptr,
const char **parv, int *errors, int dir, char c, long mode_type) const char **parv, int *errors, int dir, char c, long mode_type)
{ {
char *key; char *key;
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(dir == MODE_QUERY) if(dir == MODE_QUERY)
@ -1465,6 +1634,7 @@ chm_key(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 = chptr->mode.key; mode_changes[mode_count++].arg = chptr->mode.key;
} }
else if(dir == MODE_DEL) else if(dir == MODE_DEL)
@ -1496,6 +1666,7 @@ chm_key(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 = "*"; mode_changes[mode_count++].arg = "*";
} }
} }
@ -1505,13 +1676,20 @@ chm_regonly(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(dir == MODE_QUERY) if(dir == MODE_QUERY)
@ -1535,6 +1713,7 @@ chm_regonly(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;
} }
@ -1619,7 +1798,7 @@ struct ChannelMode chmode_table[256] =
{chm_simple, MODE_NOREJOIN }, /* J */ {chm_simple, MODE_NOREJOIN }, /* J */
{chm_simple, MODE_NOREPEAT }, /* K */ {chm_simple, MODE_NOREPEAT }, /* K */
{chm_staff, MODE_EXLIMIT }, /* L */ {chm_staff, MODE_EXLIMIT }, /* L */
{chm_nosuch, 0 }, /* M */ {chm_hidden, MODE_NOOPERKICK }, /* M */
{chm_simple, MODE_NONICK }, /* N */ {chm_simple, MODE_NONICK }, /* N */
{chm_nosuch, 0 }, /* O */ {chm_nosuch, 0 }, /* O */
{chm_staff, MODE_PERMANENT }, /* P */ {chm_staff, MODE_PERMANENT }, /* P */
@ -1837,6 +2016,7 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
const char *ml = parv[0]; const char *ml = parv[0];
char c; char c;
struct Client *fakesource_p; struct Client *fakesource_p;
int flags_list[3] = { ALL_MEMBERS, ONLY_CHANOPS, ONLY_OPERS };
mask_pos = 0; mask_pos = 0;
mode_count = 0; mode_count = 0;
@ -1845,6 +2025,8 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
alevel = get_channel_access(source_p, msptr); alevel = get_channel_access(source_p, msptr);
no_override_deop = 0;
/* Hide connecting server on netburst -- jilles */ /* Hide connecting server on netburst -- jilles */
if (ConfigServerHide.flatten_links && IsServer(source_p) && !has_id(source_p) && !HasSentEob(source_p)) if (ConfigServerHide.flatten_links && IsServer(source_p) && !has_id(source_p) && !HasSentEob(source_p))
fakesource_p = &me; fakesource_p = &me;
@ -1884,18 +2066,22 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
source_p->name, source_p->username, source_p->name, source_p->username,
source_p->host, chptr->chname); source_p->host, chptr->chname);
for (override = 0; override < (IsOverride(source_p) ? 2 : 1); ++override) for (override = 0; override < (IsOverride(source_p) && alevel != CHFL_CHANOP ? 2 : 1); ++override)
{ {
int was_on_chan = 0; int was_on_chan = 0;
if(override) if(override)
{ {
if(msptr) if(msptr)
{
was_on_chan = 1; was_on_chan = 1;
msptr->flags |= CHFL_CHANOP;
}
else else
add_user_to_channel(chptr, source_p, 0); add_user_to_channel(chptr, source_p, CHFL_CHANOP);
} }
for(j = 0, flags = ALL_MEMBERS; j < 2; j++, flags = ONLY_CHANOPS) for(j = 0, flags = flags_list[0]; j < 3; j++, flags = flags_list[j])
{ {
cur_len = mlen; cur_len = mlen;
mbuf = modebuf + mlen; mbuf = modebuf + mlen;
@ -1970,8 +2156,13 @@ set_channel_mode(struct Client *client_p, struct Client *source_p,
} }
} }
if(override && !was_on_chan) if(override)
remove_user_from_channel(find_channel_membership(chptr, source_p)); {
if(!was_on_chan)
remove_user_from_channel(find_channel_membership(chptr, source_p));
else if (!no_override_deop)
msptr->flags &= ~CHFL_CHANOP;
}
} }
/* 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)

View File

@ -646,7 +646,12 @@ sendto_channel_local(int type, struct Channel *chptr, const char *pattern, ...)
if(IsIOError(target_p)) if(IsIOError(target_p))
continue; continue;
if(type && ((msptr->flags & type) == 0)) if(type == ONLY_OPERS)
{
if(!IsOper(target_p))
continue;
}
else if(type && ((msptr->flags & type) == 0))
continue; continue;
_send_linebuf(target_p, &linebuf); _send_linebuf(target_p, &linebuf);