2007-07-16 17:30:04 +00:00
/* +------------------------------------+
* | Inspire Internet Relay Chat Daemon |
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*
2008-01-10 13:27:07 +00:00
* InspIRCd : ( C ) 2002 - 2008 InspIRCd Development Team
2007-07-16 17:30:04 +00:00
* See : http : //www.inspircd.org/wiki/index.php/Credits
*
* This program is free but copyrighted software ; see
* the file COPYING for details .
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2008-07-29 18:58:38 +00:00
/* $Core */
2007-10-22 19:53:23 +00:00
2007-07-16 17:30:04 +00:00
# include "inspircd.h"
2008-06-12 21:04:37 +00:00
# include <cstdarg>
2007-07-16 17:30:04 +00:00
# include "wildcard.h"
# include "mode.h"
2008-02-11 09:41:58 +00:00
Channel : : Channel ( InspIRCd * Instance , const std : : string & cname , time_t ts ) : ServerInstance ( Instance )
2007-07-16 17:30:04 +00:00
{
2008-04-06 20:10:33 +00:00
chan_hash : : iterator findchan = ServerInstance - > chanlist - > find ( cname ) ;
2008-01-06 12:29:31 +00:00
if ( findchan ! = Instance - > chanlist - > end ( ) )
2008-02-11 09:41:58 +00:00
throw CoreException ( " Cannot create duplicate channel " + cname ) ;
2008-01-06 12:29:31 +00:00
2008-02-11 09:41:58 +00:00
( * ( ServerInstance - > chanlist ) ) [ cname . c_str ( ) ] = this ;
2008-05-25 17:30:43 +00:00
this - > name . assign ( cname , 0 , ServerInstance - > Config - > Limits . ChanMax ) ;
2008-02-22 16:40:02 +00:00
this - > created = ts ? ts : ServerInstance - > Time ( ) ;
2008-01-06 02:36:05 +00:00
this - > age = this - > created ;
2008-07-20 14:30:00 +00:00
maxbans = topicset = 0 ;
2008-07-20 08:53:56 +00:00
modes . reset ( ) ;
2007-07-16 17:30:04 +00:00
}
2007-10-15 20:59:05 +00:00
void Channel : : SetMode ( char mode , bool mode_on )
2007-07-16 17:30:04 +00:00
{
modes [ mode - 65 ] = mode_on ;
if ( ! mode_on )
this - > SetModeParam ( mode , " " , false ) ;
}
2007-10-15 20:59:05 +00:00
void Channel : : SetModeParam ( char mode , const char * parameter , bool mode_on )
2007-07-16 17:30:04 +00:00
{
2008-06-12 21:04:37 +00:00
CustomModeList : : iterator n = custom_mode_params . find ( mode ) ;
2007-07-16 17:30:04 +00:00
if ( mode_on )
{
if ( n = = custom_mode_params . end ( ) )
custom_mode_params [ mode ] = strdup ( parameter ) ;
}
else
{
if ( n ! = custom_mode_params . end ( ) )
{
free ( n - > second ) ;
custom_mode_params . erase ( n ) ;
}
}
}
2007-10-15 20:59:05 +00:00
bool Channel : : IsModeSet ( char mode )
2007-07-16 17:30:04 +00:00
{
return modes [ mode - 65 ] ;
}
2007-10-15 20:59:05 +00:00
std : : string Channel : : GetModeParameter ( char mode )
2007-07-16 17:30:04 +00:00
{
2008-07-20 14:30:00 +00:00
CustomModeList : : iterator n = custom_mode_params . find ( mode ) ;
if ( n ! = custom_mode_params . end ( ) )
return n - > second ;
return " " ;
2007-07-16 17:30:04 +00:00
}
2007-10-15 20:59:05 +00:00
long Channel : : GetUserCounter ( )
2007-07-16 17:30:04 +00:00
{
return ( this - > internal_userlist . size ( ) ) ;
}
2007-10-15 20:59:05 +00:00
void Channel : : AddUser ( User * user )
2007-07-16 17:30:04 +00:00
{
internal_userlist [ user ] = user - > nick ;
}
2007-10-15 20:59:05 +00:00
unsigned long Channel : : DelUser ( User * user )
2007-07-16 17:30:04 +00:00
{
CUListIter a = internal_userlist . find ( user ) ;
2008-06-12 21:04:37 +00:00
2007-07-16 17:30:04 +00:00
if ( a ! = internal_userlist . end ( ) )
{
internal_userlist . erase ( a ) ;
/* And tidy any others... */
DelOppedUser ( user ) ;
DelHalfoppedUser ( user ) ;
DelVoicedUser ( user ) ;
}
2008-06-12 21:04:37 +00:00
2007-07-16 17:30:04 +00:00
return internal_userlist . size ( ) ;
}
2007-10-15 20:59:05 +00:00
bool Channel : : HasUser ( User * user )
2007-07-16 17:30:04 +00:00
{
return ( internal_userlist . find ( user ) ! = internal_userlist . end ( ) ) ;
}
2007-10-15 20:59:05 +00:00
void Channel : : AddOppedUser ( User * user )
2007-07-16 17:30:04 +00:00
{
internal_op_userlist [ user ] = user - > nick ;
}
2007-10-15 20:59:05 +00:00
void Channel : : DelOppedUser ( User * user )
2007-07-16 17:30:04 +00:00
{
CUListIter a = internal_op_userlist . find ( user ) ;
if ( a ! = internal_op_userlist . end ( ) )
{
internal_op_userlist . erase ( a ) ;
return ;
}
}
2007-10-15 20:59:05 +00:00
void Channel : : AddHalfoppedUser ( User * user )
2007-07-16 17:30:04 +00:00
{
internal_halfop_userlist [ user ] = user - > nick ;
}
2007-10-15 20:59:05 +00:00
void Channel : : DelHalfoppedUser ( User * user )
2007-07-16 17:30:04 +00:00
{
CUListIter a = internal_halfop_userlist . find ( user ) ;
if ( a ! = internal_halfop_userlist . end ( ) )
2008-06-12 21:04:37 +00:00
{
2007-07-16 17:30:04 +00:00
internal_halfop_userlist . erase ( a ) ;
}
}
2007-10-15 20:59:05 +00:00
void Channel : : AddVoicedUser ( User * user )
2007-07-16 17:30:04 +00:00
{
internal_voice_userlist [ user ] = user - > nick ;
}
2007-10-15 20:59:05 +00:00
void Channel : : DelVoicedUser ( User * user )
2007-07-16 17:30:04 +00:00
{
CUListIter a = internal_voice_userlist . find ( user ) ;
2008-06-12 21:04:37 +00:00
2007-07-16 17:30:04 +00:00
if ( a ! = internal_voice_userlist . end ( ) )
{
internal_voice_userlist . erase ( a ) ;
}
}
2007-10-15 20:59:05 +00:00
CUList * Channel : : GetUsers ( )
2007-07-16 17:30:04 +00:00
{
return & internal_userlist ;
}
2007-10-15 20:59:05 +00:00
CUList * Channel : : GetOppedUsers ( )
2007-07-16 17:30:04 +00:00
{
return & internal_op_userlist ;
}
2007-10-15 20:59:05 +00:00
CUList * Channel : : GetHalfoppedUsers ( )
2007-07-16 17:30:04 +00:00
{
return & internal_halfop_userlist ;
}
2007-10-15 20:59:05 +00:00
CUList * Channel : : GetVoicedUsers ( )
2007-07-16 17:30:04 +00:00
{
return & internal_voice_userlist ;
}
2007-10-15 20:59:05 +00:00
void Channel : : SetDefaultModes ( )
2007-07-16 17:30:04 +00:00
{
2008-04-07 23:48:26 +00:00
ServerInstance - > Logs - > Log ( " CHANNELS " , DEBUG , " SetDefaultModes %s " , ServerInstance - > Config - > DefaultModes ) ;
2007-07-16 17:30:04 +00:00
irc : : spacesepstream list ( ServerInstance - > Config - > DefaultModes ) ;
2007-08-23 18:06:26 +00:00
std : : string modeseq ;
2007-07-16 17:30:04 +00:00
std : : string parameter ;
2007-08-23 18:06:26 +00:00
list . GetToken ( modeseq ) ;
2007-07-16 17:30:04 +00:00
for ( std : : string : : iterator n = modeseq . begin ( ) ; n ! = modeseq . end ( ) ; + + n )
{
ModeHandler * mode = ServerInstance - > Modes - > FindMode ( * n , MODETYPE_CHANNEL ) ;
if ( mode )
{
if ( mode - > GetNumParams ( true ) )
2007-08-23 18:06:26 +00:00
list . GetToken ( parameter ) ;
2007-07-16 17:30:04 +00:00
else
parameter . clear ( ) ;
2007-08-28 13:40:21 +00:00
mode - > OnModeChange ( ServerInstance - > FakeClient , ServerInstance - > FakeClient , this , parameter , true ) ;
2007-07-16 17:30:04 +00:00
}
}
}
2008-06-12 21:04:37 +00:00
/*
2007-07-16 17:30:04 +00:00
* add a channel to a user , creating the record for it if needed and linking
2008-06-12 21:04:37 +00:00
* it to the user record
2007-07-16 17:30:04 +00:00
*/
2007-11-09 21:51:48 +00:00
Channel * Channel : : JoinUser ( InspIRCd * Instance , User * user , const char * cn , bool override , const char * key , bool bursting , time_t TS )
2007-07-16 17:30:04 +00:00
{
if ( ! user | | ! cn )
return NULL ;
char cname [ MAXBUF ] ;
int MOD_RESULT = 0 ;
std : : string privs ;
2007-10-15 20:59:05 +00:00
Channel * Ptr ;
2007-07-16 17:30:04 +00:00
2007-08-05 19:51:57 +00:00
/*
* We don ' t restrict the number of channels that remote users or users that are override - joining may be in .
* We restrict local users to MaxChans channels .
* We restrict local operators to OperMaxChans channels .
* This is a lot more logical than how it was formerly . - - w00t
*/
if ( IS_LOCAL ( user ) & & ! override )
{
2008-07-21 17:11:02 +00:00
// Checking MyClass exists because we *may* get here with NULL, not 100% sure.
if ( user - > MyClass & & user - > MyClass - > GetMaxChans ( ) )
2007-08-05 19:51:57 +00:00
{
2008-07-21 17:11:02 +00:00
if ( user - > chans . size ( ) > = user - > MyClass - > GetMaxChans ( ) )
2007-08-05 19:51:57 +00:00
{
2008-07-13 19:01:17 +00:00
user - > WriteNumeric ( ERR_TOOMANYCHANNELS , " %s %s :You are on too many channels " , user - > nick . c_str ( ) , cn ) ;
2007-08-05 19:51:57 +00:00
return NULL ;
}
}
else
{
2007-08-19 20:14:05 +00:00
if ( IS_OPER ( user ) )
2007-08-05 19:51:57 +00:00
{
2007-08-19 20:14:05 +00:00
if ( user - > chans . size ( ) > = Instance - > Config - > OperMaxChans )
{
2008-07-13 19:01:17 +00:00
user - > WriteNumeric ( ERR_TOOMANYCHANNELS , " %s %s :You are on too many channels " , user - > nick . c_str ( ) , cn ) ;
2007-08-19 20:14:05 +00:00
return NULL ;
}
}
else
{
if ( user - > chans . size ( ) > = Instance - > Config - > MaxChans )
{
2008-07-13 19:01:17 +00:00
user - > WriteNumeric ( ERR_TOOMANYCHANNELS , " %s %s :You are on too many channels " , user - > nick . c_str ( ) , cn ) ;
2007-08-19 20:14:05 +00:00
return NULL ;
}
2007-08-05 19:51:57 +00:00
}
}
}
2008-05-25 17:30:43 +00:00
strlcpy ( cname , cn , Instance - > Config - > Limits . ChanMax ) ;
2007-08-05 19:51:57 +00:00
Ptr = Instance - > FindChan ( cname ) ;
2007-07-16 17:30:04 +00:00
if ( ! Ptr )
{
2007-07-23 17:22:10 +00:00
/*
* Fix : desync bug was here , don ' t set @ on remote users - spanningtree handles their permissions . bug # 358. - - w00t
*/
if ( ! IS_LOCAL ( user ) )
{
if ( ! TS )
2008-05-18 23:15:53 +00:00
Instance - > Logs - > Log ( " CHANNEL " , DEBUG , " *** BUG *** Channel::JoinUser called for REMOTE user '%s' on channel '%s' but no TS given! " , user - > nick . c_str ( ) , cn ) ;
2007-07-23 17:22:10 +00:00
}
else
{
privs = " @ " ;
}
2007-07-16 17:30:04 +00:00
if ( IS_LOCAL ( user ) & & override = = false )
{
MOD_RESULT = 0 ;
2008-04-16 00:36:20 +00:00
FOREACH_RESULT_I ( Instance , I_OnUserPreJoin , OnUserPreJoin ( user , NULL , cname , privs , key ? key : " " ) ) ;
2007-07-16 17:30:04 +00:00
if ( MOD_RESULT = = 1 )
return NULL ;
}
2008-01-06 02:36:05 +00:00
Ptr = new Channel ( Instance , cname , TS ) ;
2007-07-16 17:30:04 +00:00
}
else
{
/* Already on the channel */
if ( Ptr - > HasUser ( user ) )
return NULL ;
/*
* remote users are allowed us to bypass channel modes
* and bans ( used by servers )
*/
if ( IS_LOCAL ( user ) & & override = = false )
{
MOD_RESULT = 0 ;
2008-04-16 00:36:20 +00:00
FOREACH_RESULT_I ( Instance , I_OnUserPreJoin , OnUserPreJoin ( user , Ptr , cname , privs , key ? key : " " ) ) ;
2007-07-16 17:30:04 +00:00
if ( MOD_RESULT = = 1 )
{
return NULL ;
}
else if ( MOD_RESULT = = 0 )
{
2008-07-20 14:30:00 +00:00
std : : string ckey = Ptr - > GetModeParameter ( ' k ' ) ;
if ( ! ckey . empty ( ) )
2007-07-16 17:30:04 +00:00
{
MOD_RESULT = 0 ;
2008-07-20 14:30:00 +00:00
FOREACH_RESULT_I ( Instance , I_OnCheckKey , OnCheckKey ( user , Ptr , key ? key : " " ) ) ;
2007-07-16 17:30:04 +00:00
if ( ! MOD_RESULT )
{
2008-07-20 14:30:00 +00:00
if ( ( ! key ) | | ckey ! = key )
2007-07-16 17:30:04 +00:00
{
2008-07-13 19:01:17 +00:00
user - > WriteNumeric ( ERR_BADCHANNELKEY , " %s %s :Cannot join channel (Incorrect channel key) " , user - > nick . c_str ( ) , Ptr - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
return NULL ;
}
}
}
2007-07-23 18:06:57 +00:00
if ( Ptr - > IsModeSet ( ' i ' ) )
2007-07-16 17:30:04 +00:00
{
MOD_RESULT = 0 ;
FOREACH_RESULT_I ( Instance , I_OnCheckInvite , OnCheckInvite ( user , Ptr ) ) ;
if ( ! MOD_RESULT )
{
2008-05-19 21:16:42 +00:00
if ( ! user - > IsInvited ( Ptr - > name . c_str ( ) ) )
2007-07-16 17:30:04 +00:00
{
2008-07-13 19:01:17 +00:00
user - > WriteNumeric ( ERR_INVITEONLYCHAN , " %s %s :Cannot join channel (Invite only) " , user - > nick . c_str ( ) , Ptr - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
return NULL ;
}
}
2008-05-19 21:16:42 +00:00
user - > RemoveInvite ( Ptr - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
}
2008-07-20 14:30:00 +00:00
std : : string limit = Ptr - > GetModeParameter ( ' l ' ) ;
if ( ! limit . empty ( ) )
2007-07-16 17:30:04 +00:00
{
MOD_RESULT = 0 ;
2008-07-20 14:30:00 +00:00
FOREACH_RESULT_I ( Instance , I_OnCheckLimit , OnCheckLimit ( user , Ptr ) ) ;
2007-07-16 17:30:04 +00:00
if ( ! MOD_RESULT )
{
2008-07-20 14:30:00 +00:00
long llimit = atol ( limit . c_str ( ) ) ;
if ( Ptr - > GetUserCounter ( ) > = llimit )
2007-07-16 17:30:04 +00:00
{
2008-07-13 19:01:17 +00:00
user - > WriteNumeric ( ERR_CHANNELISFULL , " %s %s :Cannot join channel (Channel is full) " , user - > nick . c_str ( ) , Ptr - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
return NULL ;
}
}
}
2008-07-20 14:30:00 +00:00
2007-07-16 17:30:04 +00:00
if ( Ptr - > bans . size ( ) )
{
if ( Ptr - > IsBanned ( user ) )
{
2008-07-13 19:01:17 +00:00
user - > WriteNumeric ( ERR_BANNEDFROMCHAN , " %s %s :Cannot join channel (You're banned) " , user - > nick . c_str ( ) , Ptr - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
return NULL ;
}
}
}
}
}
2008-01-06 02:24:26 +00:00
/* As spotted by jilles, dont bother to set this on remote users */
2008-04-07 23:48:26 +00:00
if ( IS_LOCAL ( user ) & & Ptr - > GetUserCounter ( ) = = 0 )
2008-01-06 02:24:26 +00:00
Ptr - > SetDefaultModes ( ) ;
2007-11-09 21:51:48 +00:00
return Channel : : ForceChan ( Instance , Ptr , user , privs , bursting ) ;
2007-07-16 17:30:04 +00:00
}
2007-11-09 21:51:48 +00:00
Channel * Channel : : ForceChan ( InspIRCd * Instance , Channel * Ptr , User * user , const std : : string & privs , bool bursting )
2008-07-20 14:30:00 +00:00
{
2007-07-16 17:30:04 +00:00
std : : string nick = user - > nick ;
bool silent = false ;
Ptr - > AddUser ( user ) ;
/* Just in case they have no permissions */
user - > chans [ Ptr ] = 0 ;
for ( std : : string : : const_iterator x = privs . begin ( ) ; x ! = privs . end ( ) ; x + + )
{
const char status = * x ;
ModeHandler * mh = Instance - > Modes - > FindPrefix ( status ) ;
if ( mh )
{
2008-02-02 23:24:19 +00:00
/* Set, and make sure that the mode handler knows this mode was now set */
2007-07-16 17:30:04 +00:00
Ptr - > SetPrefix ( user , status , mh - > GetPrefixRank ( ) , true ) ;
2007-08-28 13:40:21 +00:00
mh - > OnModeChange ( Instance - > FakeClient , Instance - > FakeClient , Ptr , nick , true ) ;
2007-07-16 17:30:04 +00:00
switch ( mh - > GetPrefix ( ) )
{
2008-02-02 23:24:19 +00:00
/* These logic ops are SAFE IN THIS CASE because if the entry doesnt exist,
* addressing operator [ ] creates it . If they do exist , it points to it .
* At all other times where we dont want to create an item if it doesnt exist , we
2007-07-16 17:30:04 +00:00
* must stick to : : find ( ) .
*/
case ' @ ' :
user - > chans [ Ptr ] | = UCMODE_OP ;
break ;
case ' % ' :
user - > chans [ Ptr ] | = UCMODE_HOP ;
break ;
case ' + ' :
user - > chans [ Ptr ] | = UCMODE_VOICE ;
break ;
}
}
}
2007-11-09 21:51:48 +00:00
FOREACH_MOD_I ( Instance , I_OnUserJoin , OnUserJoin ( user , Ptr , bursting , silent ) ) ;
2007-07-16 17:30:04 +00:00
if ( ! silent )
2008-05-19 21:16:42 +00:00
Ptr - > WriteChannel ( user , " JOIN :%s " , Ptr - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
/* Theyre not the first ones in here, make sure everyone else sees the modes we gave the user */
std : : string ms = Instance - > Modes - > ModeString ( user , Ptr ) ;
if ( ( Ptr - > GetUserCounter ( ) > 1 ) & & ( ms . length ( ) ) )
2008-05-19 21:16:42 +00:00
Ptr - > WriteAllExceptSender ( user , true , 0 , " MODE %s +%s " , Ptr - > name . c_str ( ) , ms . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
/* Major improvement by Brain - we dont need to be calculating all this pointlessly for remote users */
if ( IS_LOCAL ( user ) )
{
if ( Ptr - > topicset )
{
2008-07-13 19:01:17 +00:00
user - > WriteNumeric ( RPL_TOPIC , " %s %s :%s " , user - > nick . c_str ( ) , Ptr - > name . c_str ( ) , Ptr - > topic . c_str ( ) ) ;
user - > WriteNumeric ( RPL_TOPICTIME , " %s %s %s %lu " , user - > nick . c_str ( ) , Ptr - > name . c_str ( ) , Ptr - > setby . c_str ( ) , ( unsigned long ) Ptr - > topicset ) ;
2007-07-16 17:30:04 +00:00
}
Ptr - > UserList ( user ) ;
}
FOREACH_MOD_I ( Instance , I_OnPostJoin , OnPostJoin ( user , Ptr ) ) ;
return Ptr ;
}
2007-10-15 20:59:05 +00:00
bool Channel : : IsBanned ( User * user )
2007-07-16 17:30:04 +00:00
{
char mask [ MAXBUF ] ;
int MOD_RESULT = 0 ;
FOREACH_RESULT ( I_OnCheckBan , OnCheckBan ( user , this ) ) ;
2008-04-10 20:48:46 +00:00
if ( MOD_RESULT = = - 1 )
return true ;
else if ( MOD_RESULT = = 0 )
2007-07-16 17:30:04 +00:00
{
2008-05-18 23:15:53 +00:00
snprintf ( mask , MAXBUF , " %s!%s@%s " , user - > nick . c_str ( ) , user - > ident . c_str ( ) , user - > GetIPString ( ) ) ;
2007-07-16 17:30:04 +00:00
for ( BanList : : iterator i = this - > bans . begin ( ) ; i ! = this - > bans . end ( ) ; i + + )
{
/* This allows CIDR ban matching
2008-06-12 21:04:37 +00:00
*
2007-07-16 17:30:04 +00:00
* Full masked host Full unmasked host IP with / without CIDR
*/
if ( ( match ( user - > GetFullHost ( ) , i - > data ) ) | | ( match ( user - > GetFullRealHost ( ) , i - > data ) ) | | ( match ( mask , i - > data , true ) ) )
{
return true ;
}
}
}
return false ;
}
2008-07-12 20:38:14 +00:00
bool Channel : : IsExtBanned ( const std : : string & str , char type )
{
2008-07-12 20:53:19 +00:00
int MOD_RESULT = 0 ;
FOREACH_RESULT ( I_OnCheckStringExtBan , OnCheckStringExtBan ( str , this , type ) ) ;
if ( MOD_RESULT = = - 1 )
return true ;
else if ( MOD_RESULT = = 0 )
{
2008-07-12 20:38:14 +00:00
for ( BanList : : iterator i = this - > bans . begin ( ) ; i ! = this - > bans . end ( ) ; i + + )
{
if ( i - > data [ 0 ] ! = type | | i - > data [ 1 ] ! = ' : ' )
continue ;
// Iterate past char and : to get to the mask without doing a data copy(!)
std : : string maskptr = i - > data . substr ( 2 ) ;
2008-07-12 21:14:33 +00:00
ServerInstance - > Logs - > Log ( " EXTBANS " , DEBUG , " Checking %s against %s, type is %c " , str . c_str ( ) , maskptr . c_str ( ) , type ) ;
2008-07-12 20:38:14 +00:00
if ( match ( str , maskptr ) )
return true ;
}
2008-07-12 20:53:19 +00:00
}
2008-07-12 20:38:14 +00:00
return false ;
}
2008-04-04 21:43:21 +00:00
bool Channel : : IsExtBanned ( User * user , char type )
{
2008-07-11 21:26:27 +00:00
int MOD_RESULT = 0 ;
2008-07-12 20:53:19 +00:00
FOREACH_RESULT ( I_OnCheckExtBan , OnCheckExtBan ( user , this , type ) ) ;
2008-04-04 21:43:21 +00:00
2008-07-11 21:26:27 +00:00
if ( MOD_RESULT = = - 1 )
return true ;
else if ( MOD_RESULT = = 0 )
2008-04-04 21:43:21 +00:00
{
2008-07-12 20:53:19 +00:00
char mask [ MAXBUF ] ;
2008-07-11 21:26:27 +00:00
snprintf ( mask , MAXBUF , " %s!%s@%s " , user - > nick . c_str ( ) , user - > ident . c_str ( ) , user - > GetIPString ( ) ) ;
2008-04-04 21:43:21 +00:00
2008-07-12 20:53:19 +00:00
// XXX: we should probably hook cloaked hosts in here somehow too..
if ( this - > IsExtBanned ( mask , type ) )
return true ;
2008-07-11 21:26:27 +00:00
2008-07-12 20:53:19 +00:00
if ( this - > IsExtBanned ( user - > GetFullHost ( ) , type ) )
return true ;
2008-07-11 21:26:27 +00:00
2008-07-12 20:53:19 +00:00
if ( this - > IsExtBanned ( user - > GetFullRealHost ( ) , type ) )
return true ;
2008-04-04 21:43:21 +00:00
}
return false ;
}
2007-10-15 20:59:05 +00:00
/* Channel::PartUser
2007-07-16 17:30:04 +00:00
* remove a channel from a users record , and return the number of users left .
2007-10-15 20:59:05 +00:00
* Therefore , if this function returns 0 the caller should delete the Channel .
2008-07-11 14:44:17 +00:00
*
* XXX : bleh , string copy of reason , fixme ! - - w00t
2007-07-16 17:30:04 +00:00
*/
2008-07-11 21:15:02 +00:00
long Channel : : PartUser ( User * user , std : : string & reason )
2007-07-16 17:30:04 +00:00
{
bool silent = false ;
if ( ! user )
return this - > GetUserCounter ( ) ;
UCListIter i = user - > chans . find ( this ) ;
if ( i ! = user - > chans . end ( ) )
{
2008-07-11 21:15:02 +00:00
FOREACH_MOD ( I_OnUserPart , OnUserPart ( user , this , reason , silent ) ) ;
2007-07-16 17:30:04 +00:00
if ( ! silent )
2008-07-16 11:58:28 +00:00
this - > WriteChannel ( user , " PART %s%s%s " , this - > name . c_str ( ) , reason . empty ( ) ? " " : " : " , reason . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
user - > chans . erase ( i ) ;
this - > RemoveAllPrefixes ( user ) ;
}
if ( ! this - > DelUser ( user ) ) /* if there are no users left on the channel... */
{
chan_hash : : iterator iter = ServerInstance - > chanlist - > find ( this - > name ) ;
/* kill the record */
if ( iter ! = ServerInstance - > chanlist - > end ( ) )
{
2008-01-06 14:43:42 +00:00
int MOD_RESULT = 0 ;
FOREACH_RESULT_I ( ServerInstance , I_OnChannelPreDelete , OnChannelPreDelete ( this ) ) ;
if ( MOD_RESULT = = 1 )
return 1 ; // delete halted by module
FOREACH_MOD ( I_OnChannelDelete , OnChannelDelete ( this ) ) ;
2007-07-16 17:30:04 +00:00
ServerInstance - > chanlist - > erase ( iter ) ;
}
return 0 ;
}
return this - > GetUserCounter ( ) ;
}
2008-04-07 22:00:49 +00:00
long Channel : : ServerKickUser ( User * user , const char * reason , bool triggerevents , const char * servername )
2007-07-16 17:30:04 +00:00
{
bool silent = false ;
if ( ! user | | ! reason )
return this - > GetUserCounter ( ) ;
if ( IS_LOCAL ( user ) )
{
if ( ! this - > HasUser ( user ) )
{
/* Not on channel */
return this - > GetUserCounter ( ) ;
}
}
2008-04-07 22:03:12 +00:00
if ( servername = = NULL | | * ServerInstance - > Config - > HideWhoisServer )
2008-04-07 22:00:49 +00:00
servername = ServerInstance - > Config - > ServerName ;
2007-07-16 17:30:04 +00:00
if ( triggerevents )
{
FOREACH_MOD ( I_OnUserKick , OnUserKick ( NULL , user , this , reason , silent ) ) ;
}
UCListIter i = user - > chans . find ( this ) ;
if ( i ! = user - > chans . end ( ) )
{
if ( ! silent )
2008-05-19 21:16:42 +00:00
this - > WriteChannelWithServ ( servername , " KICK %s %s :%s " , this - > name . c_str ( ) , user - > nick . c_str ( ) , reason ) ;
2007-07-16 17:30:04 +00:00
user - > chans . erase ( i ) ;
this - > RemoveAllPrefixes ( user ) ;
}
if ( ! this - > DelUser ( user ) )
{
chan_hash : : iterator iter = ServerInstance - > chanlist - > find ( this - > name ) ;
/* kill the record */
if ( iter ! = ServerInstance - > chanlist - > end ( ) )
{
2008-01-06 14:43:42 +00:00
int MOD_RESULT = 0 ;
FOREACH_RESULT_I ( ServerInstance , I_OnChannelPreDelete , OnChannelPreDelete ( this ) ) ;
if ( MOD_RESULT = = 1 )
return 1 ; // delete halted by module
FOREACH_MOD ( I_OnChannelDelete , OnChannelDelete ( this ) ) ;
2007-07-16 17:30:04 +00:00
ServerInstance - > chanlist - > erase ( iter ) ;
}
return 0 ;
}
return this - > GetUserCounter ( ) ;
}
2007-10-15 20:59:05 +00:00
long Channel : : KickUser ( User * src , User * user , const char * reason )
2007-07-16 17:30:04 +00:00
{
bool silent = false ;
if ( ! src | | ! user | | ! reason )
return this - > GetUserCounter ( ) ;
if ( IS_LOCAL ( src ) )
{
if ( ! this - > HasUser ( user ) )
{
2008-07-13 19:05:31 +00:00
src - > WriteNumeric ( ERR_USERNOTINCHANNEL , " %s %s %s :They are not on that channel " , src - > nick . c_str ( ) , user - > nick . c_str ( ) , this - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
return this - > GetUserCounter ( ) ;
}
if ( ( ServerInstance - > ULine ( user - > server ) ) & & ( ! ServerInstance - > ULine ( src - > server ) ) )
{
2008-07-13 19:05:31 +00:00
src - > WriteNumeric ( ERR_CHANOPRIVSNEEDED , " %s %s :Only a u-line may kick a u-line from a channel. " , src - > nick . c_str ( ) , this - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
return this - > GetUserCounter ( ) ;
}
int MOD_RESULT = 0 ;
if ( ! ServerInstance - > ULine ( src - > server ) )
{
MOD_RESULT = 0 ;
FOREACH_RESULT ( I_OnUserPreKick , OnUserPreKick ( src , user , this , reason ) ) ;
if ( MOD_RESULT = = 1 )
return this - > GetUserCounter ( ) ;
}
/* Set to -1 by OnUserPreKick if explicit allow was set */
if ( MOD_RESULT ! = - 1 )
{
FOREACH_RESULT ( I_OnAccessCheck , OnAccessCheck ( src , user , this , AC_KICK ) ) ;
if ( ( MOD_RESULT = = ACR_DENY ) & & ( ! ServerInstance - > ULine ( src - > server ) ) )
return this - > GetUserCounter ( ) ;
2008-06-12 21:04:37 +00:00
2007-07-16 17:30:04 +00:00
if ( ( MOD_RESULT = = ACR_DEFAULT ) | | ( ! ServerInstance - > ULine ( src - > server ) ) )
{
int them = this - > GetStatus ( src ) ;
int us = this - > GetStatus ( user ) ;
if ( ( them < STATUS_HOP ) | | ( them < us ) )
{
2008-07-13 19:05:31 +00:00
src - > WriteNumeric ( ERR_CHANOPRIVSNEEDED , " %s %s :You must be a channel %soperator " , src - > nick . c_str ( ) , this - > name . c_str ( ) , them = = STATUS_HOP ? " " : " half- " ) ;
2007-07-16 17:30:04 +00:00
return this - > GetUserCounter ( ) ;
}
}
}
}
FOREACH_MOD ( I_OnUserKick , OnUserKick ( src , user , this , reason , silent ) ) ;
UCListIter i = user - > chans . find ( this ) ;
if ( i ! = user - > chans . end ( ) )
{
/* zap it from the channel list of the user */
if ( ! silent )
2008-05-19 21:16:42 +00:00
this - > WriteChannel ( src , " KICK %s %s :%s " , this - > name . c_str ( ) , user - > nick . c_str ( ) , reason ) ;
2007-07-16 17:30:04 +00:00
user - > chans . erase ( i ) ;
this - > RemoveAllPrefixes ( user ) ;
}
if ( ! this - > DelUser ( user ) )
/* if there are no users left on the channel */
{
2008-05-19 21:16:42 +00:00
chan_hash : : iterator iter = ServerInstance - > chanlist - > find ( this - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
/* kill the record */
if ( iter ! = ServerInstance - > chanlist - > end ( ) )
{
2008-01-06 14:43:42 +00:00
int MOD_RESULT = 0 ;
FOREACH_RESULT_I ( ServerInstance , I_OnChannelPreDelete , OnChannelPreDelete ( this ) ) ;
if ( MOD_RESULT = = 1 )
return 1 ; // delete halted by module
FOREACH_MOD ( I_OnChannelDelete , OnChannelDelete ( this ) ) ;
2007-07-16 17:30:04 +00:00
ServerInstance - > chanlist - > erase ( iter ) ;
}
return 0 ;
}
return this - > GetUserCounter ( ) ;
}
2008-02-13 18:22:19 +00:00
void Channel : : WriteChannel ( User * user , const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
char textbuffer [ MAXBUF ] ;
va_list argsPtr ;
if ( ! user | | ! text )
return ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer , MAXBUF , text , argsPtr ) ;
va_end ( argsPtr ) ;
this - > WriteChannel ( user , std : : string ( textbuffer ) ) ;
}
2007-10-15 20:59:05 +00:00
void Channel : : WriteChannel ( User * user , const std : : string & text )
2007-07-16 17:30:04 +00:00
{
CUList * ulist = this - > GetUsers ( ) ;
char tb [ MAXBUF ] ;
if ( ! user )
return ;
2008-05-19 21:16:42 +00:00
snprintf ( tb , MAXBUF , " :%s %s " , user - > GetFullHost ( ) . c_str ( ) , text . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
std : : string out = tb ;
for ( CUList : : iterator i = ulist - > begin ( ) ; i ! = ulist - > end ( ) ; i + + )
{
if ( IS_LOCAL ( i - > first ) )
i - > first - > Write ( out ) ;
}
}
2007-10-15 20:59:05 +00:00
void Channel : : WriteChannelWithServ ( const char * ServName , const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
char textbuffer [ MAXBUF ] ;
va_list argsPtr ;
if ( ! text )
return ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer , MAXBUF , text , argsPtr ) ;
va_end ( argsPtr ) ;
this - > WriteChannelWithServ ( ServName , std : : string ( textbuffer ) ) ;
}
2007-10-15 20:59:05 +00:00
void Channel : : WriteChannelWithServ ( const char * ServName , const std : : string & text )
2007-07-16 17:30:04 +00:00
{
CUList * ulist = this - > GetUsers ( ) ;
char tb [ MAXBUF ] ;
2008-05-19 21:16:42 +00:00
snprintf ( tb , MAXBUF , " :%s %s " , ServName ? ServName : ServerInstance - > Config - > ServerName , text . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
std : : string out = tb ;
for ( CUList : : iterator i = ulist - > begin ( ) ; i ! = ulist - > end ( ) ; i + + )
{
if ( IS_LOCAL ( i - > first ) )
i - > first - > Write ( out ) ;
}
}
/* write formatted text from a source user to all users on a channel except
* for the sender ( for privmsg etc ) */
2008-02-13 18:22:19 +00:00
void Channel : : WriteAllExceptSender ( User * user , bool serversource , char status , const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
char textbuffer [ MAXBUF ] ;
va_list argsPtr ;
if ( ! text )
return ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer , MAXBUF , text , argsPtr ) ;
va_end ( argsPtr ) ;
this - > WriteAllExceptSender ( user , serversource , status , std : : string ( textbuffer ) ) ;
}
2008-02-13 18:22:19 +00:00
void Channel : : WriteAllExcept ( User * user , bool serversource , char status , CUList & except_list , const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
char textbuffer [ MAXBUF ] ;
va_list argsPtr ;
if ( ! text )
return ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer , MAXBUF , text , argsPtr ) ;
va_end ( argsPtr ) ;
this - > WriteAllExcept ( user , serversource , status , except_list , std : : string ( textbuffer ) ) ;
}
2007-10-15 20:59:05 +00:00
void Channel : : WriteAllExcept ( User * user , bool serversource , char status , CUList & except_list , const std : : string & text )
2007-07-16 17:30:04 +00:00
{
2008-04-04 18:50:09 +00:00
CUList * ulist = this - > GetUsers ( ) ;
2007-07-16 17:30:04 +00:00
char tb [ MAXBUF ] ;
2008-05-19 21:16:42 +00:00
snprintf ( tb , MAXBUF , " :%s %s " , user - > GetFullHost ( ) . c_str ( ) , text . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
std : : string out = tb ;
for ( CUList : : iterator i = ulist - > begin ( ) ; i ! = ulist - > end ( ) ; i + + )
{
if ( ( IS_LOCAL ( i - > first ) ) & & ( except_list . find ( i - > first ) = = except_list . end ( ) ) )
{
2008-04-04 18:50:09 +00:00
/* User doesnt have the status we're after */
if ( status & & ! strchr ( this - > GetAllPrefixChars ( i - > first ) , status ) )
continue ;
2007-07-16 17:30:04 +00:00
if ( serversource )
i - > first - > WriteServ ( text ) ;
else
i - > first - > Write ( out ) ;
}
}
}
2007-10-15 20:59:05 +00:00
void Channel : : WriteAllExceptSender ( User * user , bool serversource , char status , const std : : string & text )
2007-07-16 17:30:04 +00:00
{
CUList except_list ;
except_list [ user ] = user - > nick ;
this - > WriteAllExcept ( user , serversource , status , except_list , std : : string ( text ) ) ;
}
/*
* return a count of the users on a specific channel accounting for
* invisible users who won ' t increase the count . e . g . for / LIST
*/
2007-10-15 20:59:05 +00:00
int Channel : : CountInvisible ( )
2007-07-16 17:30:04 +00:00
{
int count = 0 ;
CUList * ulist = this - > GetUsers ( ) ;
for ( CUList : : iterator i = ulist - > begin ( ) ; i ! = ulist - > end ( ) ; i + + )
{
if ( ! ( i - > first - > IsModeSet ( ' i ' ) ) )
count + + ;
}
return count ;
}
2007-10-15 20:59:05 +00:00
char * Channel : : ChanModes ( bool showkey )
2007-07-16 17:30:04 +00:00
{
static char scratch [ MAXBUF ] ;
static char sparam [ MAXBUF ] ;
char * offset = scratch ;
std : : string extparam ;
* scratch = ' \0 ' ;
* sparam = ' \0 ' ;
2007-10-15 20:59:05 +00:00
/* This was still iterating up to 190, Channel::modes is only 64 elements -- Om */
2007-07-16 17:30:04 +00:00
for ( int n = 0 ; n < 64 ; n + + )
{
if ( this - > modes [ n ] )
{
* offset + + = n + 65 ;
extparam . clear ( ) ;
switch ( n )
{
case CM_KEY :
2008-07-20 14:30:00 +00:00
// Unfortunately this must be special-cased, as we definitely don't want to always display key.
if ( showkey )
{
extparam = this - > GetModeParameter ( ' k ' ) ;
}
else
{
extparam = " <key> " ;
}
break ;
2007-07-16 17:30:04 +00:00
case CM_NOEXTERNAL :
case CM_TOPICLOCK :
case CM_INVITEONLY :
case CM_MODERATED :
case CM_SECRET :
case CM_PRIVATE :
/* We know these have no parameters */
break ;
default :
extparam = this - > GetModeParameter ( n + 65 ) ;
break ;
}
if ( ! extparam . empty ( ) )
{
charlcat ( sparam , ' ' , MAXBUF ) ;
strlcat ( sparam , extparam . c_str ( ) , MAXBUF ) ;
}
}
}
/* Null terminate scratch */
* offset = ' \0 ' ;
strlcat ( scratch , sparam , MAXBUF ) ;
return scratch ;
}
/* compile a userlist of a channel into a string, each nick seperated by
* spaces and op , voice etc status shown as @ and + , and send it to ' user '
*/
2007-10-15 20:59:05 +00:00
void Channel : : UserList ( User * user , CUList * ulist )
2007-07-16 17:30:04 +00:00
{
char list [ MAXBUF ] ;
size_t dlen , curlen ;
int MOD_RESULT = 0 ;
2008-03-21 16:17:03 +00:00
bool call_modules = true ;
2007-07-16 17:30:04 +00:00
if ( ! IS_LOCAL ( user ) )
return ;
FOREACH_RESULT ( I_OnUserList , OnUserList ( user , this , ulist ) ) ;
if ( MOD_RESULT = = 1 )
2008-03-21 16:17:03 +00:00
call_modules = false ;
2007-11-10 16:19:46 +00:00
if ( MOD_RESULT ! = - 1 )
{
if ( ( this - > IsModeSet ( ' s ' ) ) & & ( ! this - > HasUser ( user ) ) )
{
2008-07-13 19:05:31 +00:00
user - > WriteNumeric ( ERR_NOSUCHNICK , " %s %s :No such nick/channel " , user - > nick . c_str ( ) , this - > name . c_str ( ) ) ;
2007-11-10 16:19:46 +00:00
return ;
}
}
2007-07-16 17:30:04 +00:00
2008-05-19 21:16:42 +00:00
dlen = curlen = snprintf ( list , MAXBUF , " %s %c %s : " , user - > nick . c_str ( ) , this - > IsModeSet ( ' s ' ) ? ' @ ' : this - > IsModeSet ( ' p ' ) ? ' * ' : ' = ' , this - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
int numusers = 0 ;
char * ptr = list + dlen ;
if ( ! ulist )
ulist = this - > GetUsers ( ) ;
/* Improvement by Brain - this doesnt change in value, so why was it inside
* the loop ?
*/
bool has_user = this - > HasUser ( user ) ;
for ( CUList : : iterator i = ulist - > begin ( ) ; i ! = ulist - > end ( ) ; i + + )
{
2007-07-23 18:06:57 +00:00
if ( ( ! has_user ) & & ( i - > first - > IsModeSet ( ' i ' ) ) )
2007-07-16 17:30:04 +00:00
{
/*
* user is + i , and source not on the channel , does not show
* nick in NAMES list
*/
continue ;
}
if ( i - > first - > Visibility & & ! i - > first - > Visibility - > VisibleTo ( user ) )
continue ;
2008-03-21 15:54:15 +00:00
std : : string prefixlist = this - > GetPrefixChar ( i - > first ) ;
std : : string nick = i - > first - > nick ;
2008-03-21 16:17:03 +00:00
if ( call_modules )
{
FOREACH_MOD ( I_OnNamesListItem , OnNamesListItem ( user , i - > first , this , prefixlist , nick ) ) ;
2008-06-12 21:04:37 +00:00
2008-03-21 16:17:03 +00:00
/* Nick was nuked, a module wants us to skip it */
if ( nick . empty ( ) )
continue ;
}
2008-06-12 21:04:37 +00:00
2008-03-30 02:39:38 +00:00
size_t ptrlen = 0 ;
2007-07-16 17:30:04 +00:00
2008-05-25 17:30:43 +00:00
if ( curlen + prefixlist . length ( ) + nick . length ( ) + 1 > 480 )
2007-07-16 17:30:04 +00:00
{
/* list overflowed into multiple numerics */
user - > WriteServ ( std : : string ( list ) ) ;
/* reset our lengths */
2008-05-19 21:16:42 +00:00
dlen = curlen = snprintf ( list , MAXBUF , " %s %c %s : " , user - > nick . c_str ( ) , this - > IsModeSet ( ' s ' ) ? ' @ ' : this - > IsModeSet ( ' p ' ) ? ' * ' : ' = ' , this - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
ptr = list + dlen ;
ptrlen = 0 ;
numusers = 0 ;
}
2008-03-30 02:39:38 +00:00
ptrlen = snprintf ( ptr , MAXBUF , " %s%s " , prefixlist . c_str ( ) , nick . c_str ( ) ) ;
curlen + = ptrlen ;
ptr + = ptrlen ;
numusers + + ;
2007-07-16 17:30:04 +00:00
}
/* if whats left in the list isnt empty, send it */
if ( numusers )
{
2008-07-13 19:05:31 +00:00
user - > WriteNumeric ( RPL_NAMREPLY , std : : string ( list ) ) ;
2007-07-16 17:30:04 +00:00
}
2008-07-13 19:05:31 +00:00
user - > WriteNumeric ( RPL_ENDOFNAMES , " %s %s :End of /NAMES list. " , user - > nick . c_str ( ) , this - > name . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
}
2007-10-15 20:59:05 +00:00
long Channel : : GetMaxBans ( )
2007-07-16 17:30:04 +00:00
{
/* Return the cached value if there is one */
if ( this - > maxbans )
return this - > maxbans ;
/* If there isnt one, we have to do some O(n) hax to find it the first time. (ick) */
for ( std : : map < std : : string , int > : : iterator n = ServerInstance - > Config - > maxbans . begin ( ) ; n ! = ServerInstance - > Config - > maxbans . end ( ) ; n + + )
{
2008-05-18 17:51:36 +00:00
if ( match ( this - > name , n - > first ) )
2007-07-16 17:30:04 +00:00
{
this - > maxbans = n - > second ;
return n - > second ;
}
}
/* Screw it, just return the default of 64 */
this - > maxbans = 64 ;
return this - > maxbans ;
}
2007-10-15 20:59:05 +00:00
void Channel : : ResetMaxBans ( )
2007-07-16 17:30:04 +00:00
{
this - > maxbans = 0 ;
}
/* returns the status character for a given user on a channel, e.g. @ for op,
* % for halfop etc . If the user has several modes set , the highest mode
* the user has must be returned .
*/
2007-10-15 20:59:05 +00:00
const char * Channel : : GetPrefixChar ( User * user )
2007-07-16 17:30:04 +00:00
{
static char pf [ 2 ] = { 0 , 0 } ;
2008-06-12 21:04:37 +00:00
2007-07-16 17:30:04 +00:00
prefixlist : : iterator n = prefixes . find ( user ) ;
if ( n ! = prefixes . end ( ) )
{
if ( n - > second . size ( ) )
{
/* If the user has any prefixes, their highest prefix
* will always be at the head of the list , as the list is
* sorted in rank order highest first ( see SetPrefix ( )
* for reasons why )
*/
* pf = n - > second . begin ( ) - > first ;
return pf ;
}
}
* pf = 0 ;
return pf ;
}
2008-04-01 13:53:27 +00:00
2007-10-15 20:59:05 +00:00
const char * Channel : : GetAllPrefixChars ( User * user )
2007-07-16 17:30:04 +00:00
{
static char prefix [ MAXBUF ] ;
int ctr = 0 ;
* prefix = 0 ;
prefixlist : : iterator n = prefixes . find ( user ) ;
if ( n ! = prefixes . end ( ) )
{
for ( std : : vector < prefixtype > : : iterator x = n - > second . begin ( ) ; x ! = n - > second . end ( ) ; x + + )
{
prefix [ ctr + + ] = x - > first ;
}
}
prefix [ ctr ] = 0 ;
return prefix ;
}
2007-10-15 20:59:05 +00:00
unsigned int Channel : : GetPrefixValue ( User * user )
2007-07-16 17:30:04 +00:00
{
prefixlist : : iterator n = prefixes . find ( user ) ;
if ( n ! = prefixes . end ( ) )
{
if ( n - > second . size ( ) )
return n - > second . begin ( ) - > second ;
}
return 0 ;
}
2007-10-15 20:59:05 +00:00
int Channel : : GetStatusFlags ( User * user )
2007-07-16 17:30:04 +00:00
{
UCListIter i = user - > chans . find ( this ) ;
if ( i ! = user - > chans . end ( ) )
{
return i - > second ;
}
return 0 ;
}
2007-10-15 20:59:05 +00:00
int Channel : : GetStatus ( User * user )
2007-07-16 17:30:04 +00:00
{
if ( ServerInstance - > ULine ( user - > server ) )
return STATUS_OP ;
UCListIter i = user - > chans . find ( this ) ;
if ( i ! = user - > chans . end ( ) )
{
if ( ( i - > second & UCMODE_OP ) > 0 )
{
return STATUS_OP ;
}
if ( ( i - > second & UCMODE_HOP ) > 0 )
{
return STATUS_HOP ;
}
if ( ( i - > second & UCMODE_VOICE ) > 0 )
{
return STATUS_VOICE ;
}
return STATUS_NORMAL ;
}
return STATUS_NORMAL ;
}
2007-10-15 20:59:05 +00:00
void Channel : : SetPrefix ( User * user , char prefix , unsigned int prefix_value , bool adding )
2007-07-16 17:30:04 +00:00
{
prefixlist : : iterator n = prefixes . find ( user ) ;
prefixtype pfx = std : : make_pair ( prefix , prefix_value ) ;
if ( adding )
{
if ( n ! = prefixes . end ( ) )
{
if ( std : : find ( n - > second . begin ( ) , n - > second . end ( ) , pfx ) = = n - > second . end ( ) )
{
n - > second . push_back ( pfx ) ;
/* We must keep prefixes in rank order, largest first.
* This is for two reasons , firstly because x - chat * ass - u - me ' s * this
* state , and secondly it turns out to be a benefit to us later .
* See above in GetPrefix ( ) .
*/
std : : sort ( n - > second . begin ( ) , n - > second . end ( ) , ModeParser : : PrefixComparison ) ;
}
}
else
{
pfxcontainer one ;
one . push_back ( pfx ) ;
2007-10-15 20:59:05 +00:00
prefixes . insert ( std : : make_pair < User * , pfxcontainer > ( user , one ) ) ;
2007-07-16 17:30:04 +00:00
}
}
else
{
if ( n ! = prefixes . end ( ) )
{
pfxcontainer : : iterator x = std : : find ( n - > second . begin ( ) , n - > second . end ( ) , pfx ) ;
if ( x ! = n - > second . end ( ) )
n - > second . erase ( x ) ;
}
}
}
2007-10-15 20:59:05 +00:00
void Channel : : RemoveAllPrefixes ( User * user )
2007-07-16 17:30:04 +00:00
{
prefixlist : : iterator n = prefixes . find ( user ) ;
if ( n ! = prefixes . end ( ) )
{
prefixes . erase ( n ) ;
}
}