Implement channel exception list (mode 'e')

This allows a channel operator to define exception masks that allow users
to join the channel even when a "ban" would match and prevent them from
joining: the exception list (e) overrides the ban list (b).
This commit is contained in:
Alexander Barton 2012-01-21 19:59:57 +01:00
parent 33a165721b
commit f2fa1045e2
6 changed files with 85 additions and 18 deletions

View File

@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -87,6 +87,14 @@ Channel_GetListBans(CHANNEL *c)
}
GLOBAL struct list_head *
Channel_GetListExcepts(CHANNEL *c)
{
assert(c != NULL);
return &c->list_excepts;
}
GLOBAL struct list_head *
Channel_GetListInvites(CHANNEL *c)
{
@ -161,6 +169,7 @@ Free_Channel(CHANNEL *chan)
array_free(&chan->topic);
array_free(&chan->keyfile);
Lists_Free(&chan->list_bans);
Lists_Free(&chan->list_excepts);
Lists_Free(&chan->list_invites);
free(chan);
@ -788,6 +797,13 @@ Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count)
} /* Channel_SetMaxUsers */
/**
* Check if a client is allowed to send to a specific channel.
*
* @param Chan The channel to check.
* @param From The client that wants to send.
* @return true if the client is allowed to send, false otherwise.
*/
static bool
Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
{
@ -822,6 +838,9 @@ Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
if (strchr(Channel_Modes(Chan), 'm'))
return false;
if (Lists_Check(&Chan->list_excepts, From))
return true;
return !Lists_Check(&Chan->list_bans, From);
}
@ -1013,7 +1032,16 @@ GLOBAL bool
Channel_AddBan(CHANNEL *c, const char *mask )
{
struct list_head *h = Channel_GetListBans(c);
LogDebug("Adding \"%s\" to \"%s\" %s list", mask, Channel_Name(c), "ban");
LogDebug("Adding \"%s\" to \"%s\" ban list", mask, Channel_Name(c));
return Lists_Add(h, mask, false, NULL);
}
GLOBAL bool
Channel_AddExcept(CHANNEL *c, const char *mask )
{
struct list_head *h = Channel_GetListExcepts(c);
LogDebug("Adding \"%s\" to \"%s\" exception list", mask, Channel_Name(c));
return Lists_Add(h, mask, false, NULL);
}
@ -1022,7 +1050,7 @@ GLOBAL bool
Channel_AddInvite(CHANNEL *c, const char *mask, bool onlyonce)
{
struct list_head *h = Channel_GetListInvites(c);
LogDebug("Adding \"%s\" to \"%s\" %s list", mask, Channel_Name(c), "invite");
LogDebug("Adding \"%s\" to \"%s\" invite list", mask, Channel_Name(c));
return Lists_Add(h, mask, onlyonce, NULL);
}
@ -1063,6 +1091,19 @@ Channel_ShowBans( CLIENT *Client, CHANNEL *Channel )
}
GLOBAL bool
Channel_ShowExcepts( CLIENT *Client, CHANNEL *Channel )
{
struct list_head *h;
assert( Channel != NULL );
h = Channel_GetListExcepts(Channel);
return ShowChannelList(h, Client, Channel, RPL_EXCEPTLIST_MSG,
RPL_ENDOFEXCEPTLIST_MSG);
}
GLOBAL bool
Channel_ShowInvites( CLIENT *Client, CHANNEL *Channel )
{

View File

@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -38,6 +38,7 @@ typedef struct _CHANNEL
char key[CLIENT_PASS_LEN]; /* Channel key ("password", mode "k" ) */
unsigned long maxusers; /* Maximum number of members (mode "l") */
struct list_head list_bans; /* list head of banned users */
struct list_head list_excepts; /* list head of (ban) exception list */
struct list_head list_invites; /* list head of invited users */
array keyfile; /* Name of the channel key file */
} CHANNEL;
@ -58,6 +59,7 @@ typedef POINTER CL2CHAN;
#endif
GLOBAL struct list_head *Channel_GetListBans PARAMS((CHANNEL *c));
GLOBAL struct list_head *Channel_GetListExcepts PARAMS((CHANNEL *c));
GLOBAL struct list_head *Channel_GetListInvites PARAMS((CHANNEL *c));
GLOBAL void Channel_Init PARAMS(( void ));
@ -123,10 +125,13 @@ GLOBAL char *Channel_TopicWho PARAMS(( CHANNEL *Chan ));
GLOBAL unsigned int Channel_CreationTime PARAMS(( CHANNEL *Chan ));
#endif
GLOBAL bool Channel_AddInvite PARAMS((CHANNEL *c, const char *Mask, bool OnlyOnce ));
GLOBAL bool Channel_AddBan PARAMS((CHANNEL *c, const char *Mask ));
GLOBAL bool Channel_AddBan PARAMS((CHANNEL *c, const char *Mask));
GLOBAL bool Channel_AddExcept PARAMS((CHANNEL *c, const char *Mask));
GLOBAL bool Channel_AddInvite PARAMS((CHANNEL *c, const char *Mask,
bool OnlyOnce));
GLOBAL bool Channel_ShowBans PARAMS((CLIENT *client, CHANNEL *c));
GLOBAL bool Channel_ShowExcepts PARAMS((CLIENT *client, CHANNEL *c));
GLOBAL bool Channel_ShowInvites PARAMS((CLIENT *client, CHANNEL *c));
GLOBAL void Channel_LogServer PARAMS((const char *msg));

View File

@ -161,7 +161,7 @@
#define USERMODES "acCiorRswx"
/** Supported channel modes. */
#define CHANMODES "biIklmnoOPRstvz"
#define CHANMODES "beiIklmnoOPRstvz"
/** Away message for users connected to linked servers. */
#define DEFAULT_AWAY_MSG "Away"

View File

@ -82,7 +82,7 @@ static bool
join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
const char *key)
{
bool is_invited, is_banned;
bool is_invited, is_banned, is_exception;;
const char *channel_modes;
/* Allow IRC operators to overwrite channel limits */
@ -90,9 +90,10 @@ join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
return true;
is_banned = Lists_Check(Channel_GetListBans(chan), Client);
is_exception = Lists_Check(Channel_GetListExcepts(chan), Client);
is_invited = Lists_Check(Channel_GetListInvites(chan), Client);
if (is_banned && !is_invited) {
if (is_banned && !is_invited && !is_exception) {
/* Client is banned from channel (and not on invite list) */
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG,
Client_ID(Client), channame);

View File

@ -662,6 +662,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
/* --- Channel lists --- */
case 'I': /* Invite lists */
case 'b': /* Ban lists */
case 'e': /* Channel exception lists */
if (Mode_Limit_Reached(Client, mode_arg_count++))
goto chan_exit;
if (arg_arg > mode_arg) {
@ -683,10 +684,17 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
Req->argv[arg_arg][0] = '\0';
arg_arg++;
} else {
if (*mode_ptr == 'I')
switch (*mode_ptr) {
case 'I':
Channel_ShowInvites(Origin, Channel);
else
break;
case 'b':
Channel_ShowBans(Origin, Channel);
break;
case 'e':
Channel_ShowExcepts(Origin, Channel);
break;
}
}
break;
default:
@ -836,7 +844,7 @@ IRC_AWAY( CLIENT *Client, REQUEST *Req )
/**
* Add entries to channel invite, ban and exception lists.
*
* @param what Can be 'I' for invite or 'b' for ban list.
* @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
* @param Prefix The originator of the command.
* @param Client The sender of the command.
* @param Channel The channel of which the list should be modified.
@ -853,7 +861,7 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
assert(Client != NULL);
assert(Channel != NULL);
assert(Pattern != NULL);
assert(what == 'I' || what == 'b');
assert(what == 'I' || what == 'b' || what == 'e');
mask = Lists_MakeMask(Pattern);
@ -864,6 +872,9 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
case 'b':
list = Channel_GetListBans(Channel);
break;
case 'e':
list = Channel_GetListExcepts(Channel);
break;
}
if (Lists_CheckDupeMask(list, mask))
@ -884,6 +895,10 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
if (!Channel_AddBan(Channel, mask))
return CONNECTED;
break;
case 'e':
if (!Channel_AddExcept(Channel, mask))
return CONNECTED;
break;
}
return Send_ListChange(true, what, Prefix, Client, Channel, mask);
}
@ -892,7 +907,7 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
/**
* Delete entries from channel invite, ban and exeption lists.
*
* @param what Can be 'I' for invite or 'b' for ban list.
* @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
* @param Prefix The originator of the command.
* @param Client The sender of the command.
* @param Channel The channel of which the list should be modified.
@ -909,7 +924,7 @@ Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
assert(Client != NULL);
assert(Channel != NULL);
assert(Pattern != NULL);
assert(what == 'I' || what == 'b');
assert(what == 'I' || what == 'b' || what == 'e');
mask = Lists_MakeMask(Pattern);
@ -920,6 +935,9 @@ Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
case 'b':
list = Channel_GetListBans(Channel);
break;
case 'e':
list = Channel_GetListExcepts(Channel);
break;
}
if (!Lists_CheckDupeMask(list, mask))
@ -931,7 +949,7 @@ Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
/**
* Send information about changed channel ban/invite lists to clients.
* Send information about changed channel invite/ban/exception lists to clients.
*
* @param IsAdd true if the list item has been added, false otherwise.
* @param ModeChar The mode to use (e. g. 'b' or 'I')

View File

@ -21,8 +21,8 @@
#define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)"
#define RPL_CREATED_MSG "003 %s :This server has been started %s"
#define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s"
#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=bI,k,l,imnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
#define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=bI:%d PENALTY :are supported on this server"
#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=beI,k,l,imnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
#define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d PENALTY :are supported on this server"
#define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d"
#define RPL_TRACEOPERATOR_MSG "204 %s Oper 2 :%s"
@ -75,6 +75,8 @@
#define RPL_INVITING_MSG "341 %s %s %s%s"
#define RPL_INVITELIST_MSG "346 %s %s %s"
#define RPL_ENDOFINVITELIST_MSG "347 %s %s :End of channel invite list"
#define RPL_EXCEPTLIST_MSG "348 %s %s %s"
#define RPL_ENDOFEXCEPTLIST_MSG "349 %s %s :End of channel exception list"
#define RPL_VERSION_MSG "351 %s %s-%s.%s %s :%s"
#define RPL_WHOREPLY_MSG "352 %s %s %s %s %s %s %s :%d %s"
#define RPL_NAMREPLY_MSG "353 %s %s %s :"