Merge branch 'owner-mode' into devel

This commit is contained in:
Sam Dodrill 2013-09-28 20:39:55 -07:00
commit 3ed02190ef
15 changed files with 568 additions and 40 deletions

View File

@ -390,6 +390,7 @@ channel {
exemptchanops = "NT"; exemptchanops = "NT";
use_halfop = yes; use_halfop = yes;
use_admin = yes; use_admin = yes;
use_owner = yes;
use_knock = yes; use_knock = yes;
use_local_channels = yes; use_local_channels = yes;
knock_delay = 5 minutes; knock_delay = 5 minutes;

View File

@ -808,6 +808,16 @@ channel {
*/ */
use_admin = no; use_admin = no;
/* owner: Enable/disable channel mode +y, which adds owner,
* a channel status above admin that has op powers (kick, ban, mode, etc.)
* owners can only be kicked/deadmined by other owners, and may kick
* or deop anyone. Disabling this via rehash will cause things which
* are rather confusing to occur, it is highly recommended to restart
* if you wish to disable this option, though it may be enabled
* by rehash with no problems.
*/
use_owner = no;
/* knock: Allows users to request an invite to a channel that /* knock: Allows users to request an invite to a channel that
* is locked somehow (+ikl). If the channel is +p or you are banned * is locked somehow (+ikl). If the channel is +p or you are banned
* the knock will not be sent. * the knock will not be sent.

View File

@ -804,6 +804,16 @@ channel {
*/ */
use_admin = yes; use_admin = yes;
/* owner: Enable/disable channel mode +y, which adds owner,
* a channel status above admin that has op powers (kick, ban, mode, etc.)
* owners can only be kicked/deadmined by other owners, and may kick
* or deop anyone. Disabling this via rehash will cause things which
* are rather confusing to occur, it is highly recommended to restart
* if you wish to disable this option, though it may be enabled
* by rehash with no problems.
*/
use_owner = yes;
/* knock: Allows users to request an invite to a channel that /* knock: Allows users to request an invite to a channel that
* is locked somehow (+ikl). If the channel is +p or you are banned * is locked somehow (+ikl). If the channel is +p or you are banned
* the knock will not be sent. * the knock will not be sent.

View File

@ -64,7 +64,7 @@ mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char
return 0; return 0;
} }
if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!') if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!' || *parv[1] == '~')
{ {
parv[1]++; parv[1]++;
move_me = 1; move_me = 1;
@ -97,7 +97,19 @@ mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char
me.name, parv[1], me.name, parv[1],
source_p->name, source_p->username, source_p->host); source_p->name, source_p->username, source_p->host);
if(*parv[1] == '!' && ConfigChannel.use_admin) if(*parv[1] == '~' && ConfigChannel.use_owner)
{
add_user_to_channel(chptr, source_p, CHFL_OWNER);
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
":%s SJOIN %ld %s + :~%s",
me.id, (long) chptr->channelts, chptr->chname, source_p->id);
sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
source_p->name,
source_p->username, source_p->host, chptr->chname);
sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +y %s",
me.name, chptr->chname, source_p->name);
}
else if(*parv[1] == '!' && ConfigChannel.use_admin)
{ {
add_user_to_channel(chptr, source_p, CHFL_ADMIN); add_user_to_channel(chptr, source_p, CHFL_ADMIN);
sendto_server(client_p, chptr, CAP_TS6, NOCAPS, sendto_server(client_p, chptr, CAP_TS6, NOCAPS,

View File

@ -123,7 +123,24 @@ mo_omode(struct Client *client_p, struct Client *source_p, int parc, const char
set_channel_mode(client_p, source_p->servptr, chptr, msptr, set_channel_mode(client_p, source_p->servptr, chptr, msptr,
parc - 2, parv + 2); parc - 2, parv + 2);
#else #else
if (parc == 4 && !strcmp(parv[2], "+a") && !irccmp(parv[3], source_p->name)) if (parc == 4 && !strcmp(parv[2], "+y") && !irccmp(parv[3], source_p->name))
{
/* Ownering themselves */
if (!wasonchannel)
{
sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
return 0;
}
sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +y %s",
me.name, parv[1], source_p->name);
sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
":%s TMODE %ld %s +y %s",
me.id, (long) chptr->channelts, parv[1],
source_p->id);
msptr->flags |= CHFL_OWNER;
}
else if (parc == 4 && !strcmp(parv[2], "+a") && !irccmp(parv[3], source_p->name))
{ {
/* Admining themselves */ /* Admining themselves */
if (!wasonchannel) if (!wasonchannel)
@ -174,6 +191,26 @@ mo_omode(struct Client *client_p, struct Client *source_p, int parc, const char
source_p->id); source_p->id);
msptr->flags |= CHFL_HALFOP; msptr->flags |= CHFL_HALFOP;
} }
else if (ConfigChannel.use_owner)
{
/* I hope this is correct.
* -- Kabaka */
/* Hack it so set_channel_mode() will accept */
if (wasonchannel)
msptr->flags |= CHFL_OWNER;
else
{
add_user_to_channel(chptr, source_p, CHFL_CHANOP);
msptr = find_channel_membership(chptr, source_p);
}
set_channel_mode(client_p, source_p, chptr, msptr,
parc - 2, parv + 2);
if (wasonchannel)
msptr->flags &= ~CHFL_OWNER;
else
remove_user_from_channel(msptr);
}
else if (ConfigChannel.use_admin) else if (ConfigChannel.use_admin)
{ {
/* Hack it so set_channel_mode() will accept */ /* Hack it so set_channel_mode() will accept */

View File

@ -154,13 +154,15 @@ 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_ADMIN 0x0080 #define CHFL_ADMIN 0x0080
#define CHFL_OWNER 0x0200
#define ONLY_OPERS 0x0100 #define ONLY_OPERS 0x0100
#define ALL_MEMBERS CHFL_PEON #define ALL_MEMBERS CHFL_PEON
#define ONLY_CHANOPS (CHFL_ADMIN|CHFL_CHANOP|CHFL_HALFOP) #define ONLY_CHANOPS (CHFL_OWNER|CHFL_ADMIN|CHFL_CHANOP|CHFL_HALFOP)
#define ONLY_CHANOPSVOICED (CHFL_ADMIN|CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE) #define ONLY_CHANOPSVOICED (CHFL_OWNER|CHFL_ADMIN|CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE)
#define is_chmode_h(x) ((x) && (x)->flags & CHFL_HALFOP) /* does not check if halfop is enabled, should typically not be used */ #define is_chmode_h(x) ((x) && (x)->flags & CHFL_HALFOP) /* does not check if halfop is enabled, should typically not be used */
#define is_chmode_a(x) ((x) && (x)->flags & CHFL_ADMIN) /* does not check if admin is enabled, should typically not be used */ #define is_chmode_a(x) ((x) && (x)->flags & CHFL_ADMIN) /* does not check if admin is enabled, should typically not be used */
#define is_chmode_y(x) ((x) && (x)->flags & CHFL_OWNER) /* does not check if owner is enabled, should typically not be used */
#define is_chanop(x) ((x) && (x)->flags & CHFL_CHANOP) #define is_chanop(x) ((x) && (x)->flags & CHFL_CHANOP)
#define is_voiced(x) ((x) && (x)->flags & CHFL_VOICE) #define is_voiced(x) ((x) && (x)->flags & CHFL_VOICE)
#define can_send_banned(x) ((x) && (x)->flags & (CHFL_BANNED|CHFL_QUIETED)) #define can_send_banned(x) ((x) && (x)->flags & (CHFL_BANNED|CHFL_QUIETED))
@ -243,6 +245,7 @@ extern struct membership *find_channel_membership(struct Channel *, struct Clien
extern const char *find_channel_status(struct membership *msptr, int combine); extern const char *find_channel_status(struct membership *msptr, int combine);
extern int is_halfop(struct membership *msptr); extern int is_halfop(struct membership *msptr);
extern int is_admin(struct membership *msptr); extern int is_admin(struct membership *msptr);
extern int is_owner(struct membership *msptr);
extern int is_any_op(struct membership *msptr); extern int is_any_op(struct membership *msptr);
extern int is_chanop_voiced(struct membership *msptr); extern int is_chanop_voiced(struct membership *msptr);
extern int can_kick_deop(struct membership *source, struct membership *target); extern int can_kick_deop(struct membership *source, struct membership *target);

View File

@ -66,6 +66,9 @@ extern void chm_key(struct Client *source_p, struct Channel *chptr,
extern void chm_limit(struct Client *source_p, struct Channel *chptr, extern void chm_limit(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_owner(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_admin(struct Client *source_p, struct Channel *chptr, extern void chm_admin(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

@ -243,6 +243,7 @@ struct config_channel_entry
int admin_on_channel_create; int admin_on_channel_create;
int use_halfop; int use_halfop;
int use_admin; int use_admin;
int use_owner;
int use_except; int use_except;
int use_invex; int use_invex;
int use_knock; int use_knock;

View File

@ -544,7 +544,12 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
if(*s == '!') if(*s == '~')
{
fl |= CHFL_OWNER;
s++;
}
else if(*s == '!')
{ {
fl |= CHFL_ADMIN; fl |= CHFL_ADMIN;
s++; s++;
@ -584,7 +589,13 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
if(keep_new_modes) if(keep_new_modes)
{ {
if(fl & CHFL_ADMIN) if(fl & CHFL_OWNER)
{
*ptr_uid++ = '~';
len_nick++;
len_uid++;
}
else if(fl & CHFL_ADMIN)
{ {
*ptr_uid++ = '!'; *ptr_uid++ = '!';
len_nick++; len_nick++;
@ -630,7 +641,101 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
/* If anyone can think of a way to do this that doesn't make babies cry /* If anyone can think of a way to do this that doesn't make babies cry
* I would love to hear it - Taros */ * I would love to hear it - Taros */
if(fl & CHFL_OWNER)
{
*mbuf++ = 'y';
para[pargs++] = target_p->name;
if(fl & CHFL_ADMIN) if(fl & CHFL_ADMIN)
{
/* its possible the +y has filled up MAXMODEPARAMS, if so, start
* a new buffer
*/
if(pargs >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
fakesource_p->name, chptr->chname,
modebuf,
para[0], para[1], para[2], para[3]);
mbuf = modebuf;
*mbuf++ = '+';
para[0] = para[1] = para[2] = para[3] = NULL;
pargs = 0;
}
*mbuf++ = 'a';
para[pargs++] = target_p->name;
}
if(fl & CHFL_CHANOP)
{
/* its possible the +y has filled up MAXMODEPARAMS, if so, start
* a new buffer
*/
if(pargs >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
fakesource_p->name, chptr->chname,
modebuf,
para[0], para[1], para[2], para[3]);
mbuf = modebuf;
*mbuf++ = '+';
para[0] = para[1] = para[2] = para[3] = NULL;
pargs = 0;
}
*mbuf++ = 'o';
para[pargs++] = target_p->name;
}
if(fl & CHFL_HALFOP)
{
/* its possible the +y has filled up MAXMODEPARAMS, if so, start
* a new buffer
*/
if(pargs >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
fakesource_p->name, chptr->chname,
modebuf,
para[0], para[1], para[2], para[3]);
mbuf = modebuf;
*mbuf++ = '+';
para[0] = para[1] = para[2] = para[3] = NULL;
pargs = 0;
}
*mbuf++ = 'h';
para[pargs++] = target_p->name;
}
if(fl & CHFL_VOICE)
{
/* its possible the +y has filled up MAXMODEPARAMS, if so, start
* a new buffer
*/
if(pargs >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
fakesource_p->name, chptr->chname,
modebuf,
para[0], para[1], para[2], para[3]);
mbuf = modebuf;
*mbuf++ = '+';
para[0] = para[1] = para[2] = para[3] = NULL;
pargs = 0;
}
*mbuf++ = 'v';
para[pargs++] = target_p->name;
}
}
else if(fl & CHFL_ADMIN)
{ {
*mbuf++ = 'a'; *mbuf++ = 'a';
para[pargs++] = target_p->name; para[pargs++] = target_p->name;
@ -1026,7 +1131,190 @@ remove_our_modes(struct Channel *chptr, struct Client *source_p)
/* If anyone can think of a way to do this that doesn't make babies cry /* If anyone can think of a way to do this that doesn't make babies cry
* I would love to hear it - Taros */ * I would love to hear it - Taros */
if(is_owner(msptr))
{
msptr->flags &= ~CHFL_ADMIN;
lpara[count++] = msptr->client_p->name;
*mbuf++ = 'y';
/* Make sure it fits if +h, +o, or +v are involved */
if(is_admin(msptr)) if(is_admin(msptr))
{
if(count >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
source_p->name, chptr->chname,
lmodebuf, lpara[0], lpara[1],
lpara[2], lpara[3]);
/* preserve the initial '-' */
mbuf = lmodebuf;
*mbuf++ = '-';
count = 0;
for(i = 0; i < MAXMODEPARAMS; i++)
lpara[i] = NULL;
}
msptr->flags &= ~CHFL_ADMIN;
lpara[count++] = msptr->client_p->name;
*mbuf++ = 'a';
}
if(is_chanop(msptr))
{
if(count >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
source_p->name, chptr->chname,
lmodebuf, lpara[0], lpara[1],
lpara[2], lpara[3]);
/* preserve the initial '-' */
mbuf = lmodebuf;
*mbuf++ = '-';
count = 0;
for(i = 0; i < MAXMODEPARAMS; i++)
lpara[i] = NULL;
}
msptr->flags &= ~CHFL_CHANOP;
lpara[count++] = msptr->client_p->name;
*mbuf++ = 'o';
}
if(is_halfop(msptr))
{
if(count >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
source_p->name, chptr->chname,
lmodebuf, lpara[0], lpara[1],
lpara[2], lpara[3]);
/* preserve the initial '-' */
mbuf = lmodebuf;
*mbuf++ = '-';
count = 0;
for(i = 0; i < MAXMODEPARAMS; i++)
lpara[i] = NULL;
}
msptr->flags &= ~CHFL_HALFOP;
lpara[count++] = msptr->client_p->name;
*mbuf++ = 'h';
}
if(is_voiced(msptr))
{
if(count >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
source_p->name, chptr->chname,
lmodebuf, lpara[0], lpara[1],
lpara[2], lpara[3]);
/* preserve the initial '-' */
mbuf = lmodebuf;
*mbuf++ = '-';
count = 0;
for(i = 0; i < MAXMODEPARAMS; i++)
lpara[i] = NULL;
}
msptr->flags &= ~CHFL_VOICE;
lpara[count++] = msptr->client_p->name;
*mbuf++ = 'v';
}
else if(is_admin(msptr))
{
msptr->flags &= ~CHFL_ADMIN;
lpara[count++] = msptr->client_p->name;
*mbuf++ = 'a';
/* Make sure it fits if +h, +o, or +v are involved */
if(is_chanop(msptr))
{
if(count >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
source_p->name, chptr->chname,
lmodebuf, lpara[0], lpara[1],
lpara[2], lpara[3]);
/* preserve the initial '-' */
mbuf = lmodebuf;
*mbuf++ = '-';
count = 0;
for(i = 0; i < MAXMODEPARAMS; i++)
lpara[i] = NULL;
}
msptr->flags &= ~CHFL_CHANOP;
lpara[count++] = msptr->client_p->name;
*mbuf++ = 'o';
}
if(is_halfop(msptr))
{
if(count >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
source_p->name, chptr->chname,
lmodebuf, lpara[0], lpara[1],
lpara[2], lpara[3]);
/* preserve the initial '-' */
mbuf = lmodebuf;
*mbuf++ = '-';
count = 0;
for(i = 0; i < MAXMODEPARAMS; i++)
lpara[i] = NULL;
}
msptr->flags &= ~CHFL_HALFOP;
lpara[count++] = msptr->client_p->name;
*mbuf++ = 'h';
}
if(is_voiced(msptr))
{
if(count >= MAXMODEPARAMS)
{
*mbuf = '\0';
sendto_channel_local(ALL_MEMBERS, chptr,
":%s MODE %s %s %s %s %s %s",
source_p->name, chptr->chname,
lmodebuf, lpara[0], lpara[1],
lpara[2], lpara[3]);
/* preserve the initial '-' */
mbuf = lmodebuf;
*mbuf++ = '-';
count = 0;
for(i = 0; i < MAXMODEPARAMS; i++)
lpara[i] = NULL;
}
msptr->flags &= ~CHFL_VOICE;
lpara[count++] = msptr->client_p->name;
*mbuf++ = 'v';
}
}
}
else if(is_admin(msptr))
{ {
msptr->flags &= ~CHFL_ADMIN; msptr->flags &= ~CHFL_ADMIN;
lpara[count++] = msptr->client_p->name; lpara[count++] = msptr->client_p->name;

View File

@ -643,6 +643,12 @@ static struct InfoStruct info_table[] = {
&ConfigChannel.use_admin, &ConfigChannel.use_admin,
"Enable chanmode +a (admin)", "Enable chanmode +a (admin)",
}, },
{
"use_owner",
OUTPUT_BOOLEAN_YN,
&ConfigChannel.use_owner,
"Enable chanmode +y (owner)",
},
{ {
"use_except", "use_except",
OUTPUT_BOOLEAN_YN, OUTPUT_BOOLEAN_YN,

View File

@ -186,6 +186,12 @@ find_channel_status(struct membership *msptr, int combine)
p = buffer; p = buffer;
if(is_owner(msptr))
{
if(!combine)
return "~";
*p++ = '~';
}
if(is_admin(msptr)) if(is_admin(msptr))
{ {
if(!combine) if(!combine)
@ -252,6 +258,24 @@ is_admin(struct membership *msptr)
return 0; return 0;
} }
/* is_owner()
* input - membership to check for owner
* output - 1 if the user is an admin, 0 if the user is not or owner
* is disabled
* side effects -
*
*/
int
is_owner(struct membership *msptr)
{
if(!ConfigChannel.use_owner)
return 0;
if(is_chmode_y(msptr))
return 1;
else
return 0;
}
/* is_any_op() /* is_any_op()
* *
* input - membership to check for ops * input - membership to check for ops
@ -261,7 +285,7 @@ is_admin(struct membership *msptr)
int int
is_any_op(struct membership *msptr) is_any_op(struct membership *msptr)
{ {
if(is_chanop(msptr) || is_halfop(msptr) || is_admin(msptr)) if(is_chanop(msptr) || is_halfop(msptr) || is_admin(msptr) || is_owner(msptr))
return 1; return 1;
else else
return 0; return 0;
@ -276,7 +300,7 @@ is_any_op(struct membership *msptr)
int int
is_chanop_voiced(struct membership *msptr) is_chanop_voiced(struct membership *msptr)
{ {
if(is_chanop(msptr) || is_voiced(msptr) || is_halfop(msptr) || is_admin(msptr)) if(is_chanop(msptr) || is_voiced(msptr) || is_halfop(msptr) || is_admin(msptr) || is_owner(msptr))
return 1; return 1;
else else
return 0; return 0;
@ -291,14 +315,29 @@ is_chanop_voiced(struct membership *msptr)
int int
can_kick_deop(struct membership *source, struct membership *target) can_kick_deop(struct membership *source, struct membership *target)
{ {
if(is_chanop(source) && !is_admin(target)) /*
* Reworked the logic to match this:
* - owners can do what they want
* - admins cannot kick or deop owners
* - admins can kick or deop admins
* - ops cannot kick or deop admins
* - halfops cannot kick or deop anyone that has halfop or up
* -- Niichan
*/
if(is_owner(source))
return 1; return 1;
else if(is_halfop(source) && !is_any_op(target)) if(is_admin(source) && is_owner(target))
return 1; return 0;
else if(is_admin(source)) if(is_chanop(source) && is_owner(target))
return 0;
if(is_chanop(source) && is_admin(target))
return 0;
if(is_halfop(source) && is_any_op(target))
return 0;
return 1; return 1;
return 0;
} }
/* add_user_to_channel() /* add_user_to_channel()

View File

@ -92,6 +92,7 @@ construct_cflags_strings(void)
!(chmode_table[i].set_func == chm_throttle) && !(chmode_table[i].set_func == chm_throttle) &&
!(chmode_table[i].set_func == chm_key) && !(chmode_table[i].set_func == chm_key) &&
!(chmode_table[i].set_func == chm_limit) && !(chmode_table[i].set_func == chm_limit) &&
!(chmode_table[i].set_func == chm_owner) &&
!(chmode_table[i].set_func == chm_admin) && !(chmode_table[i].set_func == chm_admin) &&
!(chmode_table[i].set_func == chm_op) && !(chmode_table[i].set_func == chm_op) &&
!(chmode_table[i].set_func == chm_halfop) && !(chmode_table[i].set_func == chm_halfop) &&
@ -131,6 +132,7 @@ construct_cflags_strings(void)
/* Should we leave orphaned check here? -- dwr */ /* Should we leave orphaned check here? -- dwr */
if( !(chmode_table[i].set_func == chm_nosuch) && if( !(chmode_table[i].set_func == chm_nosuch) &&
!(chmode_table[i].set_func == chm_orphaned) && !(chmode_table[i].set_func == chm_orphaned) &&
!(chmode_table[i].set_func == chm_owner && !ConfigChannel.use_owner) &&
!(chmode_table[i].set_func == chm_admin && !ConfigChannel.use_admin) && !(chmode_table[i].set_func == chm_admin && !ConfigChannel.use_admin) &&
!(chmode_table[i].set_func == chm_halfop && !ConfigChannel.use_halfop)) !(chmode_table[i].set_func == chm_halfop && !ConfigChannel.use_halfop))
{ {
@ -147,7 +149,8 @@ construct_cflag_param_string(void)
{ {
*cflagsparaminfo = '\0'; *cflagsparaminfo = '\0';
rb_snprintf(cflagsparaminfo, sizeof cflagsparaminfo, "%sb%s%s%s%sklov%s%s", rb_snprintf(cflagsparaminfo, sizeof cflagsparaminfo, "%s%sb%s%s%s%sklov%s%s",
ConfigChannel.use_owner ? "y" : "",
ConfigChannel.use_admin ? "a" : "", ConfigChannel.use_admin ? "a" : "",
ConfigChannel.use_except ? "e" : "", ConfigChannel.use_except ? "e" : "",
ConfigChannel.use_forward ? "f" : "", ConfigChannel.use_forward ? "f" : "",
@ -210,7 +213,9 @@ cflag_orphan(char c_)
static int static int
get_channel_access(struct Client *source_p, struct membership *msptr) get_channel_access(struct Client *source_p, struct membership *msptr)
{ {
if(!MyClient(source_p) || is_admin(msptr)) if(!MyClient(source_p) || is_owner(msptr))
return CHFL_OWNER;
else if(is_admin(msptr))
return CHFL_ADMIN; return CHFL_ADMIN;
else if(is_chanop(msptr)) else if(is_chanop(msptr))
return CHFL_CHANOP; return CHFL_CHANOP;
@ -536,7 +541,7 @@ chm_simple(struct Client *source_p, struct Channel *chptr,
struct Metadata *md; struct Metadata *md;
struct DictionaryIter iter; struct DictionaryIter iter;
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER)
{ {
if (IsOverride(source_p)) if (IsOverride(source_p))
override = 1; override = 1;
@ -747,7 +752,7 @@ chm_staff(struct Client *source_p, struct Channel *chptr,
return; return;
} }
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER)
{ {
if (IsOverride(source_p)) if (IsOverride(source_p))
override = 1; override = 1;
@ -879,8 +884,8 @@ 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.. */
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && mode_type != CHFL_BAN && if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER &&
mode_type != CHFL_QUIET) mode_type != CHFL_BAN && mode_type != CHFL_QUIET)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
{ {
@ -913,7 +918,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
return; return;
} }
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
override = 1; override = 1;
@ -1000,6 +1005,115 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
} }
} }
void
chm_owner(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)
{
struct membership *mstptr;
const char *ownernick;
struct Client *targ_p;
int override = 0;
if(!ConfigChannel.use_owner)
{
if(*errors & SM_ERR_UNKNOWN)
return;
*errors |= SM_ERR_UNKNOWN;
sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name, source_p->name, c);
return;
}
if(alevel != CHFL_OWNER)
{
if(IsOverride(source_p))
override = 1;
else
{
if(!(*errors & SM_ERR_NOOPS))
sendto_one(source_p, ":%s 482 %s %s :You're not a channel owner", me.name, source_p->name, chptr->chname);
*errors |= SM_ERR_NOOPS;
return;
}
}
if((dir == MODE_QUERY) || (parc <= *parn))
return;
ownernick = parv[(*parn)];
(*parn)++;
/* empty nick */
if(EmptyString(ownernick))
{
sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), "*");
return;
}
if((targ_p = find_chasing(source_p, ownernick, NULL)) == NULL)
return;
mstptr = find_channel_membership(chptr, targ_p);
if(mstptr == NULL)
{
if(!(*errors & SM_ERR_NOTONCHANNEL) && MyClient(source_p))
sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
form_str(ERR_USERNOTINCHANNEL), ownernick, chptr->chname);
*errors |= SM_ERR_NOTONCHANNEL;
return;
}
if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
return;
if(dir == MODE_ADD)
{
if(targ_p == source_p)
{
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].dir = MODE_ADD;
mode_changes[mode_count].caps = 0;
mode_changes[mode_count].nocaps = 0;
mode_changes[mode_count].mems = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p;
mstptr->flags |= CHFL_OWNER;
}
else
{
if(MyClient(source_p) && IsService(targ_p))
{
sendto_one(source_p, form_str(ERR_ISCHANSERVICE),
me.name, source_p->name, targ_p->name, chptr->chname);
return;
}
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 = ALL_MEMBERS;
mode_changes[mode_count].id = targ_p->id;
mode_changes[mode_count].arg = targ_p->name;
mode_changes[mode_count].override = override;
mode_changes[mode_count++].client = targ_p;
mstptr->flags &= ~CHFL_OWNER;
}
}
void void
chm_admin(struct Client *source_p, struct Channel *chptr, chm_admin(struct Client *source_p, struct Channel *chptr,
int alevel, int parc, int *parn, int alevel, int parc, int *parn,
@ -1019,7 +1133,7 @@ chm_admin(struct Client *source_p, struct Channel *chptr,
return; return;
} }
if(alevel != CHFL_ADMIN) if(alevel != CHFL_ADMIN && alevel != CHFL_OWNER)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
override = 1; override = 1;
@ -1122,7 +1236,7 @@ chm_op(struct Client *source_p, struct Channel *chptr,
struct Client *targ_p; struct Client *targ_p;
int override = 0; int override = 0;
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_OWNER)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
override = 1; override = 1;
@ -1235,7 +1349,7 @@ chm_halfop(struct Client *source_p, struct Channel *chptr,
return; return;
} }
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_OWNER)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
override = 1; override = 1;
@ -1339,7 +1453,7 @@ chm_voice(struct Client *source_p, struct Channel *chptr,
struct Client *targ_p; struct Client *targ_p;
int override = 0; int override = 0;
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
override = 1; override = 1;
@ -1426,7 +1540,7 @@ chm_limit(struct Client *source_p, struct Channel *chptr,
int limit; int limit;
int override = 0; int override = 0;
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
override = 1; override = 1;
@ -1493,7 +1607,7 @@ chm_throttle(struct Client *source_p, struct Channel *chptr,
int joins = 0, timeslice = 0; int joins = 0, timeslice = 0;
int override = 0; int override = 0;
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
override = 1; override = 1;
@ -1585,7 +1699,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
} }
#ifndef FORWARD_OPERONLY #ifndef FORWARD_OPERONLY
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
override = 1; override = 1;
@ -1690,7 +1804,7 @@ chm_key(struct Client *source_p, struct Channel *chptr,
char *key; char *key;
int override = 0; int override = 0;
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP) if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER)
{ {
if(IsOverride(source_p)) if(IsOverride(source_p))
override = 1; override = 1;
@ -1894,7 +2008,7 @@ struct ChannelMode chmode_table[256] =
{chm_voice, 0 }, /* v */ {chm_voice, 0 }, /* v */
{chm_nosuch, 0 }, /* w */ {chm_nosuch, 0 }, /* w */
{chm_nosuch, 0 }, /* x */ {chm_nosuch, 0 }, /* x */
{chm_nosuch, 0 }, /* y */ {chm_owner, 0 }, /* y */
{chm_simple, MODE_OPMODERATE }, /* z */ {chm_simple, MODE_OPMODERATE }, /* z */
{chm_nosuch, 0 }, /* 0x7b */ {chm_nosuch, 0 }, /* 0x7b */

View File

@ -2301,6 +2301,7 @@ static struct ConfEntry conf_channel_table[] =
{ "admin_on_channel_create", CF_YESNO, NULL, 0, &ConfigChannel.admin_on_channel_create }, { "admin_on_channel_create", CF_YESNO, NULL, 0, &ConfigChannel.admin_on_channel_create },
{ "use_halfop", CF_YESNO, NULL, 0, &ConfigChannel.use_halfop }, { "use_halfop", CF_YESNO, NULL, 0, &ConfigChannel.use_halfop },
{ "use_admin", CF_YESNO, NULL, 0, &ConfigChannel.use_admin }, { "use_admin", CF_YESNO, NULL, 0, &ConfigChannel.use_admin },
{ "use_owner", CF_YESNO, NULL, 0, &ConfigChannel.use_owner },
{ "use_except", CF_YESNO, NULL, 0, &ConfigChannel.use_except }, { "use_except", CF_YESNO, NULL, 0, &ConfigChannel.use_except },
{ "use_invex", CF_YESNO, NULL, 0, &ConfigChannel.use_invex }, { "use_invex", CF_YESNO, NULL, 0, &ConfigChannel.use_invex },
{ "use_knock", CF_YESNO, NULL, 0, &ConfigChannel.use_knock }, { "use_knock", CF_YESNO, NULL, 0, &ConfigChannel.use_knock },

View File

@ -771,6 +771,7 @@ set_default_conf(void)
ConfigChannel.admin_on_channel_create = NO; ConfigChannel.admin_on_channel_create = NO;
ConfigChannel.use_halfop = YES; ConfigChannel.use_halfop = YES;
ConfigChannel.use_admin = YES; ConfigChannel.use_admin = YES;
ConfigChannel.use_owner = YES;
ConfigChannel.use_except = YES; ConfigChannel.use_except = YES;
ConfigChannel.use_invex = YES; ConfigChannel.use_invex = YES;
ConfigChannel.use_knock = YES; ConfigChannel.use_knock = YES;

View File

@ -257,11 +257,13 @@ isupport_chanlimit(const void *ptr)
static const char* static const char*
isupport_prefix(const void *ptr) isupport_prefix(const void *ptr)
{ {
static char result[11]; static char result[13];
rb_snprintf(result, sizeof result, "(%so%sv)%s@%s+", rb_snprintf(result, sizeof result, "(%s%so%sv)%s%s@%s+",
ConfigChannel.use_owner ? "y" : "",
ConfigChannel.use_admin ? "a" : "", ConfigChannel.use_admin ? "a" : "",
ConfigChannel.use_halfop ? "h" : "", ConfigChannel.use_halfop ? "h" : "",
ConfigChannel.use_owner ? "~" : "",
ConfigChannel.use_admin ? "!" : "", ConfigChannel.use_admin ? "!" : "",
ConfigChannel.use_halfop ? "%" : ""); ConfigChannel.use_halfop ? "%" : "");
return result; return result;