Merge branch 'owner-mode' into devel
This commit is contained in:
commit
3ed02190ef
|
@ -390,6 +390,7 @@ channel {
|
|||
exemptchanops = "NT";
|
||||
use_halfop = yes;
|
||||
use_admin = yes;
|
||||
use_owner = yes;
|
||||
use_knock = yes;
|
||||
use_local_channels = yes;
|
||||
knock_delay = 5 minutes;
|
||||
|
|
|
@ -808,6 +808,16 @@ channel {
|
|||
*/
|
||||
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
|
||||
* is locked somehow (+ikl). If the channel is +p or you are banned
|
||||
* the knock will not be sent.
|
||||
|
|
|
@ -804,6 +804,16 @@ channel {
|
|||
*/
|
||||
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
|
||||
* is locked somehow (+ikl). If the channel is +p or you are banned
|
||||
* the knock will not be sent.
|
||||
|
|
|
@ -64,7 +64,7 @@ mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char
|
|||
return 0;
|
||||
}
|
||||
|
||||
if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!')
|
||||
if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!' || *parv[1] == '~')
|
||||
{
|
||||
parv[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],
|
||||
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);
|
||||
sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
|
||||
|
|
|
@ -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,
|
||||
parc - 2, parv + 2);
|
||||
#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 */
|
||||
if (!wasonchannel)
|
||||
|
@ -174,6 +191,26 @@ mo_omode(struct Client *client_p, struct Client *source_p, int parc, const char
|
|||
source_p->id);
|
||||
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)
|
||||
{
|
||||
/* Hack it so set_channel_mode() will accept */
|
||||
|
|
|
@ -154,13 +154,15 @@ typedef int (*ExtbanFunc)(const char *data, struct Client *client_p,
|
|||
#define ONLY_SERVERS 0x0020
|
||||
#define CHFL_HALFOP 0x0040
|
||||
#define CHFL_ADMIN 0x0080
|
||||
#define CHFL_OWNER 0x0200
|
||||
#define ONLY_OPERS 0x0100
|
||||
#define ALL_MEMBERS CHFL_PEON
|
||||
#define ONLY_CHANOPS (CHFL_ADMIN|CHFL_CHANOP|CHFL_HALFOP)
|
||||
#define ONLY_CHANOPSVOICED (CHFL_ADMIN|CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE)
|
||||
#define ONLY_CHANOPS (CHFL_OWNER|CHFL_ADMIN|CHFL_CHANOP|CHFL_HALFOP)
|
||||
#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_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_voiced(x) ((x) && (x)->flags & CHFL_VOICE)
|
||||
#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 int is_halfop(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_chanop_voiced(struct membership *msptr);
|
||||
extern int can_kick_deop(struct membership *source, struct membership *target);
|
||||
|
|
|
@ -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,
|
||||
int alevel, int parc, int *parn,
|
||||
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,
|
||||
int alevel, int parc, int *parn,
|
||||
const char **parv, int *errors, int dir, char c, long mode_type);
|
||||
|
|
|
@ -243,6 +243,7 @@ struct config_channel_entry
|
|||
int admin_on_channel_create;
|
||||
int use_halfop;
|
||||
int use_admin;
|
||||
int use_owner;
|
||||
int use_except;
|
||||
int use_invex;
|
||||
int use_knock;
|
||||
|
|
|
@ -544,7 +544,12 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
|
|||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if(*s == '!')
|
||||
if(*s == '~')
|
||||
{
|
||||
fl |= CHFL_OWNER;
|
||||
s++;
|
||||
}
|
||||
else if(*s == '!')
|
||||
{
|
||||
fl |= CHFL_ADMIN;
|
||||
s++;
|
||||
|
@ -584,7 +589,13 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
|
|||
|
||||
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++ = '!';
|
||||
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
|
||||
* I would love to hear it - Taros */
|
||||
|
||||
if(fl & CHFL_ADMIN)
|
||||
if(fl & CHFL_OWNER)
|
||||
{
|
||||
*mbuf++ = 'y';
|
||||
para[pargs++] = target_p->name;
|
||||
|
||||
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';
|
||||
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
|
||||
* I would love to hear it - Taros */
|
||||
|
||||
if(is_admin(msptr))
|
||||
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(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;
|
||||
lpara[count++] = msptr->client_p->name;
|
||||
|
|
|
@ -643,6 +643,12 @@ static struct InfoStruct info_table[] = {
|
|||
&ConfigChannel.use_admin,
|
||||
"Enable chanmode +a (admin)",
|
||||
},
|
||||
{
|
||||
"use_owner",
|
||||
OUTPUT_BOOLEAN_YN,
|
||||
&ConfigChannel.use_owner,
|
||||
"Enable chanmode +y (owner)",
|
||||
},
|
||||
{
|
||||
"use_except",
|
||||
OUTPUT_BOOLEAN_YN,
|
||||
|
|
|
@ -186,6 +186,12 @@ find_channel_status(struct membership *msptr, int combine)
|
|||
|
||||
p = buffer;
|
||||
|
||||
if(is_owner(msptr))
|
||||
{
|
||||
if(!combine)
|
||||
return "~";
|
||||
*p++ = '~';
|
||||
}
|
||||
if(is_admin(msptr))
|
||||
{
|
||||
if(!combine)
|
||||
|
@ -252,6 +258,24 @@ is_admin(struct membership *msptr)
|
|||
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()
|
||||
*
|
||||
* input - membership to check for ops
|
||||
|
@ -261,7 +285,7 @@ is_admin(struct membership *msptr)
|
|||
int
|
||||
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;
|
||||
else
|
||||
return 0;
|
||||
|
@ -276,7 +300,7 @@ is_any_op(struct membership *msptr)
|
|||
int
|
||||
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;
|
||||
else
|
||||
return 0;
|
||||
|
@ -291,14 +315,29 @@ is_chanop_voiced(struct membership *msptr)
|
|||
int
|
||||
can_kick_deop(struct membership *source, struct membership *target)
|
||||
{
|
||||
if(is_chanop(source) && !is_admin(target))
|
||||
return 1;
|
||||
else if(is_halfop(source) && !is_any_op(target))
|
||||
return 1;
|
||||
else if(is_admin(source))
|
||||
return 1;
|
||||
/*
|
||||
* 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;
|
||||
if(is_admin(source) && is_owner(target))
|
||||
return 0;
|
||||
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 0;
|
||||
}
|
||||
|
||||
/* add_user_to_channel()
|
||||
|
|
148
src/chmode.c
148
src/chmode.c
|
@ -92,6 +92,7 @@ construct_cflags_strings(void)
|
|||
!(chmode_table[i].set_func == chm_throttle) &&
|
||||
!(chmode_table[i].set_func == chm_key) &&
|
||||
!(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_op) &&
|
||||
!(chmode_table[i].set_func == chm_halfop) &&
|
||||
|
@ -131,6 +132,7 @@ construct_cflags_strings(void)
|
|||
/* Should we leave orphaned check here? -- dwr */
|
||||
if( !(chmode_table[i].set_func == chm_nosuch) &&
|
||||
!(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_halfop && !ConfigChannel.use_halfop))
|
||||
{
|
||||
|
@ -147,7 +149,8 @@ construct_cflag_param_string(void)
|
|||
{
|
||||
|
||||
*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_except ? "e" : "",
|
||||
ConfigChannel.use_forward ? "f" : "",
|
||||
|
@ -210,8 +213,10 @@ cflag_orphan(char c_)
|
|||
static int
|
||||
get_channel_access(struct Client *source_p, struct membership *msptr)
|
||||
{
|
||||
if(!MyClient(source_p) || is_admin(msptr))
|
||||
return CHFL_ADMIN;
|
||||
if(!MyClient(source_p) || is_owner(msptr))
|
||||
return CHFL_OWNER;
|
||||
else if(is_admin(msptr))
|
||||
return CHFL_ADMIN;
|
||||
else if(is_chanop(msptr))
|
||||
return CHFL_CHANOP;
|
||||
else if(is_halfop(msptr))
|
||||
|
@ -536,7 +541,7 @@ chm_simple(struct Client *source_p, struct Channel *chptr,
|
|||
struct Metadata *md;
|
||||
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))
|
||||
override = 1;
|
||||
|
@ -747,7 +752,7 @@ chm_staff(struct Client *source_p, struct Channel *chptr,
|
|||
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))
|
||||
override = 1;
|
||||
|
@ -879,8 +884,8 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
|
|||
*errors |= errorval;
|
||||
|
||||
/* non-ops cant see +eI lists.. */
|
||||
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && mode_type != CHFL_BAN &&
|
||||
mode_type != CHFL_QUIET)
|
||||
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && alevel != CHFL_OWNER &&
|
||||
mode_type != CHFL_BAN && mode_type != CHFL_QUIET)
|
||||
{
|
||||
if(IsOverride(source_p))
|
||||
{
|
||||
|
@ -913,7 +918,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
|
|||
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))
|
||||
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
|
||||
chm_admin(struct Client *source_p, struct Channel *chptr,
|
||||
int alevel, int parc, int *parn,
|
||||
|
@ -1019,7 +1133,7 @@ chm_admin(struct Client *source_p, struct Channel *chptr,
|
|||
return;
|
||||
}
|
||||
|
||||
if(alevel != CHFL_ADMIN)
|
||||
if(alevel != CHFL_ADMIN && alevel != CHFL_OWNER)
|
||||
{
|
||||
if(IsOverride(source_p))
|
||||
override = 1;
|
||||
|
@ -1122,7 +1236,7 @@ chm_op(struct Client *source_p, struct Channel *chptr,
|
|||
struct Client *targ_p;
|
||||
int override = 0;
|
||||
|
||||
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN)
|
||||
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_OWNER)
|
||||
{
|
||||
if(IsOverride(source_p))
|
||||
override = 1;
|
||||
|
@ -1235,7 +1349,7 @@ chm_halfop(struct Client *source_p, struct Channel *chptr,
|
|||
return;
|
||||
}
|
||||
|
||||
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN)
|
||||
if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_OWNER)
|
||||
{
|
||||
if(IsOverride(source_p))
|
||||
override = 1;
|
||||
|
@ -1339,7 +1453,7 @@ chm_voice(struct Client *source_p, struct Channel *chptr,
|
|||
struct Client *targ_p;
|
||||
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))
|
||||
override = 1;
|
||||
|
@ -1426,7 +1540,7 @@ chm_limit(struct Client *source_p, struct Channel *chptr,
|
|||
int limit;
|
||||
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))
|
||||
override = 1;
|
||||
|
@ -1493,7 +1607,7 @@ chm_throttle(struct Client *source_p, struct Channel *chptr,
|
|||
int joins = 0, timeslice = 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))
|
||||
override = 1;
|
||||
|
@ -1585,7 +1699,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr,
|
|||
}
|
||||
|
||||
#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))
|
||||
override = 1;
|
||||
|
@ -1690,7 +1804,7 @@ chm_key(struct Client *source_p, struct Channel *chptr,
|
|||
char *key;
|
||||
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))
|
||||
override = 1;
|
||||
|
@ -1894,7 +2008,7 @@ struct ChannelMode chmode_table[256] =
|
|||
{chm_voice, 0 }, /* v */
|
||||
{chm_nosuch, 0 }, /* w */
|
||||
{chm_nosuch, 0 }, /* x */
|
||||
{chm_nosuch, 0 }, /* y */
|
||||
{chm_owner, 0 }, /* y */
|
||||
{chm_simple, MODE_OPMODERATE }, /* z */
|
||||
|
||||
{chm_nosuch, 0 }, /* 0x7b */
|
||||
|
|
|
@ -2301,6 +2301,7 @@ static struct ConfEntry conf_channel_table[] =
|
|||
{ "admin_on_channel_create", CF_YESNO, NULL, 0, &ConfigChannel.admin_on_channel_create },
|
||||
{ "use_halfop", CF_YESNO, NULL, 0, &ConfigChannel.use_halfop },
|
||||
{ "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_invex", CF_YESNO, NULL, 0, &ConfigChannel.use_invex },
|
||||
{ "use_knock", CF_YESNO, NULL, 0, &ConfigChannel.use_knock },
|
||||
|
|
|
@ -771,6 +771,7 @@ set_default_conf(void)
|
|||
ConfigChannel.admin_on_channel_create = NO;
|
||||
ConfigChannel.use_halfop = YES;
|
||||
ConfigChannel.use_admin = YES;
|
||||
ConfigChannel.use_owner = YES;
|
||||
ConfigChannel.use_except = YES;
|
||||
ConfigChannel.use_invex = YES;
|
||||
ConfigChannel.use_knock = YES;
|
||||
|
|
|
@ -257,11 +257,13 @@ isupport_chanlimit(const void *ptr)
|
|||
static const char*
|
||||
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_halfop ? "h" : "",
|
||||
ConfigChannel.use_owner ? "~" : "",
|
||||
ConfigChannel.use_admin ? "!" : "",
|
||||
ConfigChannel.use_halfop ? "%" : "");
|
||||
return result;
|
||||
|
|
Loading…
Reference in New Issue