2007-07-16 17:30:04 +00:00
/* +------------------------------------+
* | Inspire Internet Relay Chat Daemon |
* + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*
2010-01-11 03:07:32 +00:00
* InspIRCd : ( C ) 2002 - 2010 InspIRCd Development Team
2009-03-15 12:42:35 +00:00
* See : http : //wiki.inspircd.org/Credits
2007-07-16 17:30:04 +00:00
*
* This program is free but copyrighted software ; see
* the file COPYING for details .
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
# include "inspircd.h"
# include <stdarg.h>
# include "socketengine.h"
# include "xline.h"
2007-11-04 13:44:26 +00:00
# include "bancache.h"
2007-07-16 17:30:04 +00:00
# include "commands/cmd_whowas.h"
2009-10-16 17:01:49 +00:00
typedef unsigned int uniq_id_t ;
class sent
2008-04-02 17:08:09 +00:00
{
2009-10-16 17:01:49 +00:00
uniq_id_t uniq_id ;
uniq_id_t * array ;
void init ( )
{
if ( ! array )
array = new uniq_id_t [ ServerInstance - > SE - > GetMaxFds ( ) ] ;
memset ( array , 0 , ServerInstance - > SE - > GetMaxFds ( ) * sizeof ( uniq_id_t ) ) ;
uniq_id + + ;
}
public :
sent ( ) : uniq_id ( static_cast < uniq_id_t > ( - 1 ) ) , array ( NULL ) { }
inline uniq_id_t operator + + ( )
{
if ( + + uniq_id = = 0 )
init ( ) ;
return uniq_id ;
}
inline uniq_id_t & operator [ ] ( int i )
{
return array [ i ] ;
}
~ sent ( )
{
2009-10-19 04:09:38 +00:00
delete [ ] array ;
2009-10-16 17:01:49 +00:00
}
} ;
static sent already_sent ;
2007-07-16 17:30:04 +00:00
2007-10-15 20:59:05 +00:00
std : : string User : : ProcessNoticeMasks ( const char * sm )
2007-07-16 17:30:04 +00:00
{
bool adding = true , oldadding = false ;
const char * c = sm ;
std : : string output ;
while ( c & & * c )
{
switch ( * c )
{
case ' + ' :
adding = true ;
break ;
case ' - ' :
adding = false ;
break ;
case ' * ' :
for ( unsigned char d = ' A ' ; d < = ' z ' ; d + + )
{
if ( ServerInstance - > SNO - > IsEnabled ( d ) )
{
if ( ( ! IsNoticeMaskSet ( d ) & & adding ) | | ( IsNoticeMaskSet ( d ) & & ! adding ) )
{
if ( ( oldadding ! = adding ) | | ( ! output . length ( ) ) )
output + = ( adding ? ' + ' : ' - ' ) ;
this - > SetNoticeMask ( d , adding ) ;
output + = d ;
}
}
oldadding = adding ;
}
break ;
default :
if ( ( * c > = ' A ' ) & & ( * c < = ' z ' ) & & ( ServerInstance - > SNO - > IsEnabled ( * c ) ) )
{
if ( ( ! IsNoticeMaskSet ( * c ) & & adding ) | | ( IsNoticeMaskSet ( * c ) & & ! adding ) )
{
if ( ( oldadding ! = adding ) | | ( ! output . length ( ) ) )
output + = ( adding ? ' + ' : ' - ' ) ;
this - > SetNoticeMask ( * c , adding ) ;
output + = * c ;
}
}
2008-02-26 20:31:01 +00:00
else
2008-07-13 19:19:15 +00:00
this - > WriteNumeric ( ERR_UNKNOWNSNOMASK , " %s %c :is unknown snomask char to me " , this - > nick . c_str ( ) , * c ) ;
2008-02-26 20:31:01 +00:00
2007-07-16 17:30:04 +00:00
oldadding = adding ;
break ;
}
2010-01-04 17:04:08 +00:00
c + + ;
2007-07-16 17:30:04 +00:00
}
2008-11-02 19:46:09 +00:00
std : : string s = this - > FormatNoticeMasks ( ) ;
if ( s . length ( ) = = 0 )
{
this - > modes [ UM_SNOMASK ] = false ;
}
2007-07-16 17:30:04 +00:00
return output ;
}
2009-10-21 23:45:08 +00:00
void LocalUser : : StartDNSLookup ( )
2007-07-16 17:30:04 +00:00
{
try
{
2008-08-06 11:59:17 +00:00
bool cached = false ;
2008-10-28 23:20:28 +00:00
const char * sip = this - > GetIPString ( ) ;
2008-08-31 01:05:00 +00:00
UserResolver * res_reverse ;
2007-07-16 17:30:04 +00:00
2009-09-01 15:07:36 +00:00
QueryType resolvtype = this - > client_sa . sa . sa_family = = AF_INET6 ? DNS_QUERY_PTR6 : DNS_QUERY_PTR4 ;
2009-09-26 14:13:13 +00:00
res_reverse = new UserResolver ( this , sip , resolvtype , cached ) ;
2007-07-16 17:30:04 +00:00
2009-09-13 20:31:54 +00:00
ServerInstance - > AddResolver ( res_reverse , cached ) ;
2007-07-16 17:30:04 +00:00
}
catch ( CoreException & e )
{
2008-02-09 13:06:02 +00:00
ServerInstance - > Logs - > Log ( " USERS " , DEBUG , " Error in resolver: %s " , e . GetReason ( ) ) ;
2007-07-16 17:30:04 +00:00
}
}
2007-10-15 20:59:05 +00:00
bool User : : IsNoticeMaskSet ( unsigned char sm )
2007-07-16 17:30:04 +00:00
{
2008-08-25 15:49:39 +00:00
if ( ! isalpha ( sm ) )
return false ;
2007-07-16 17:30:04 +00:00
return ( snomasks [ sm - 65 ] ) ;
}
2007-10-15 20:59:05 +00:00
void User : : SetNoticeMask ( unsigned char sm , bool value )
2007-07-16 17:30:04 +00:00
{
2008-08-25 15:49:39 +00:00
if ( ! isalpha ( sm ) )
return ;
2007-07-16 17:30:04 +00:00
snomasks [ sm - 65 ] = value ;
}
2007-10-15 20:59:05 +00:00
const char * User : : FormatNoticeMasks ( )
2007-07-16 17:30:04 +00:00
{
static char data [ MAXBUF ] ;
int offset = 0 ;
for ( int n = 0 ; n < 64 ; n + + )
{
if ( snomasks [ n ] )
data [ offset + + ] = n + 65 ;
}
data [ offset ] = 0 ;
return data ;
}
2007-10-15 20:59:05 +00:00
bool User : : IsModeSet ( unsigned char m )
2007-07-16 17:30:04 +00:00
{
2008-08-25 15:49:39 +00:00
if ( ! isalpha ( m ) )
return false ;
2007-07-16 17:30:04 +00:00
return ( modes [ m - 65 ] ) ;
}
2007-10-15 20:59:05 +00:00
void User : : SetMode ( unsigned char m , bool value )
2007-07-16 17:30:04 +00:00
{
2008-08-25 15:49:39 +00:00
if ( ! isalpha ( m ) )
return ;
2007-07-16 17:30:04 +00:00
modes [ m - 65 ] = value ;
}
2008-08-31 13:00:12 +00:00
const char * User : : FormatModes ( bool showparameters )
2007-07-16 17:30:04 +00:00
{
static char data [ MAXBUF ] ;
2008-08-31 13:00:12 +00:00
std : : string params ;
2007-07-16 17:30:04 +00:00
int offset = 0 ;
2008-08-31 13:00:12 +00:00
for ( unsigned char n = 0 ; n < 64 ; n + + )
2007-07-16 17:30:04 +00:00
{
if ( modes [ n ] )
2008-08-31 13:00:12 +00:00
{
data [ offset + + ] = n + 65 ;
ModeHandler * mh = ServerInstance - > Modes - > FindMode ( n + 65 , MODETYPE_USER ) ;
if ( showparameters & & mh & & mh - > GetNumParams ( true ) )
{
std : : string p = mh - > GetUserParameter ( this ) ;
if ( p . length ( ) )
params . append ( " " ) . append ( p ) ;
}
}
2007-07-16 17:30:04 +00:00
}
data [ offset ] = 0 ;
2008-08-31 13:00:12 +00:00
strlcat ( data , params . c_str ( ) , MAXBUF ) ;
2007-07-16 17:30:04 +00:00
return data ;
}
2009-10-25 15:21:45 +00:00
User : : User ( const std : : string & uid , const std : : string & sid , int type )
: uuid ( uid ) , server ( sid ) , usertype ( type )
2007-07-16 17:30:04 +00:00
{
2008-02-22 16:40:02 +00:00
age = ServerInstance - > Time ( ) ;
2009-10-23 22:47:39 +00:00
signon = idle_lastmsg = 0 ;
registered = 0 ;
2009-10-17 02:43:07 +00:00
quietquit = quitting = exempt = dns_done = false ;
2009-10-21 23:45:08 +00:00
client_sa . sa . sa_family = AF_UNSPEC ;
2007-08-27 13:36:11 +00:00
2009-10-21 23:44:48 +00:00
ServerInstance - > Logs - > Log ( " USERS " , DEBUG , " New UUID for user: %s " , uuid . c_str ( ) ) ;
2007-08-27 13:54:15 +00:00
2009-09-26 14:13:13 +00:00
user_hash : : iterator finduuid = ServerInstance - > Users - > uuidlist - > find ( uuid ) ;
if ( finduuid = = ServerInstance - > Users - > uuidlist - > end ( ) )
( * ServerInstance - > Users - > uuidlist ) [ uuid ] = this ;
2007-08-27 11:43:12 +00:00
else
2007-10-15 20:59:05 +00:00
throw CoreException ( " Duplicate UUID " + std : : string ( uuid ) + " in User constructor " ) ;
2007-07-16 17:30:04 +00:00
}
2009-11-01 21:53:47 +00:00
LocalUser : : LocalUser ( int myfd , irc : : sockets : : sockaddrs * client , irc : : sockets : : sockaddrs * servaddr )
2009-11-06 22:37:36 +00:00
: User ( ServerInstance - > GetUID ( ) , ServerInstance - > Config - > ServerName , USERTYPE_LOCAL ) , eh ( this )
2009-10-21 23:44:48 +00:00
{
2009-10-21 23:45:08 +00:00
bytes_in = bytes_out = cmds_in = cmds_out = 0 ;
server_sa . sa . sa_family = AF_UNSPEC ;
2009-11-11 19:52:03 +00:00
CommandFloodPenalty = 0 ;
2009-10-21 23:45:32 +00:00
lastping = nping = 0 ;
2009-11-06 22:37:36 +00:00
eh . SetFd ( myfd ) ;
2009-11-01 21:53:47 +00:00
memcpy ( & client_sa , client , sizeof ( irc : : sockets : : sockaddrs ) ) ;
memcpy ( & server_sa , servaddr , sizeof ( irc : : sockets : : sockaddrs ) ) ;
2009-10-21 23:44:48 +00:00
}
2007-10-15 20:59:05 +00:00
User : : ~ User ( )
2007-07-16 17:30:04 +00:00
{
2009-10-23 22:47:39 +00:00
if ( ServerInstance - > Users - > uuidlist - > find ( uuid ) ! = ServerInstance - > Users - > uuidlist - > end ( ) )
2010-01-19 15:16:33 +00:00
ServerInstance - > Logs - > Log ( " USERS " , DEFAULT , " User destructor for %s called without cull " , uuid . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
}
2008-05-18 23:15:53 +00:00
const std : : string & User : : MakeHost ( )
2007-07-16 17:30:04 +00:00
{
2008-05-18 23:15:53 +00:00
if ( ! this - > cached_makehost . empty ( ) )
2007-07-16 17:30:04 +00:00
return this - > cached_makehost ;
char nhost [ MAXBUF ] ;
/* This is much faster than snprintf */
char * t = nhost ;
2008-05-18 23:15:53 +00:00
for ( const char * n = ident . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t + + = ' @ ' ;
2008-05-19 19:12:43 +00:00
for ( const char * n = host . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t = 0 ;
2008-05-18 23:15:53 +00:00
this - > cached_makehost . assign ( nhost ) ;
2007-07-16 17:30:04 +00:00
return this - > cached_makehost ;
}
2008-05-18 23:15:53 +00:00
const std : : string & User : : MakeHostIP ( )
2007-07-16 17:30:04 +00:00
{
2008-05-18 23:15:53 +00:00
if ( ! this - > cached_hostip . empty ( ) )
2007-07-16 17:30:04 +00:00
return this - > cached_hostip ;
char ihost [ MAXBUF ] ;
/* This is much faster than snprintf */
char * t = ihost ;
2008-05-18 23:15:53 +00:00
for ( const char * n = ident . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t + + = ' @ ' ;
for ( const char * n = this - > GetIPString ( ) ; * n ; n + + )
* t + + = * n ;
* t = 0 ;
2008-05-18 23:15:53 +00:00
this - > cached_hostip = ihost ;
2007-07-16 17:30:04 +00:00
return this - > cached_hostip ;
}
2009-10-23 22:47:39 +00:00
const std : : string & User : : GetFullHost ( )
2007-07-16 17:30:04 +00:00
{
2008-05-18 23:15:53 +00:00
if ( ! this - > cached_fullhost . empty ( ) )
2007-07-16 17:30:04 +00:00
return this - > cached_fullhost ;
char result [ MAXBUF ] ;
char * t = result ;
2008-05-18 23:15:53 +00:00
for ( const char * n = nick . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t + + = ' ! ' ;
2008-05-18 23:15:53 +00:00
for ( const char * n = ident . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t + + = ' @ ' ;
2008-05-18 23:15:53 +00:00
for ( const char * n = dhost . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t = 0 ;
2008-05-18 23:15:53 +00:00
this - > cached_fullhost = result ;
2007-07-16 17:30:04 +00:00
return this - > cached_fullhost ;
}
2007-10-15 20:59:05 +00:00
char * User : : MakeWildHost ( )
2007-07-16 17:30:04 +00:00
{
static char nresult [ MAXBUF ] ;
char * t = nresult ;
* t + + = ' * ' ; * t + + = ' ! ' ;
* t + + = ' * ' ; * t + + = ' @ ' ;
2008-05-18 23:15:53 +00:00
for ( const char * n = dhost . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t = 0 ;
return nresult ;
}
2009-10-23 22:47:39 +00:00
const std : : string & User : : GetFullRealHost ( )
2007-07-16 17:30:04 +00:00
{
2008-05-18 23:15:53 +00:00
if ( ! this - > cached_fullrealhost . empty ( ) )
2007-07-16 17:30:04 +00:00
return this - > cached_fullrealhost ;
char fresult [ MAXBUF ] ;
char * t = fresult ;
2008-05-18 23:15:53 +00:00
for ( const char * n = nick . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t + + = ' ! ' ;
2008-05-18 23:15:53 +00:00
for ( const char * n = ident . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t + + = ' @ ' ;
2008-05-19 19:12:43 +00:00
for ( const char * n = host . c_str ( ) ; * n ; n + + )
2007-07-16 17:30:04 +00:00
* t + + = * n ;
* t = 0 ;
2008-05-18 23:15:53 +00:00
this - > cached_fullrealhost = fresult ;
2007-07-16 17:30:04 +00:00
return this - > cached_fullrealhost ;
}
2009-10-21 23:45:32 +00:00
bool LocalUser : : IsInvited ( const irc : : string & channel )
2007-07-16 17:30:04 +00:00
{
2008-11-01 23:02:23 +00:00
time_t now = ServerInstance - > Time ( ) ;
2008-02-08 23:35:39 +00:00
InvitedList : : iterator safei ;
for ( InvitedList : : iterator i = invites . begin ( ) ; i ! = invites . end ( ) ; + + i )
2007-07-16 17:30:04 +00:00
{
2008-02-08 23:35:39 +00:00
if ( channel = = i - > first )
2007-07-16 17:30:04 +00:00
{
2008-02-08 23:35:39 +00:00
if ( i - > second ! = 0 & & now > i - > second )
{
/* Expired invite, remove it. */
safei = i ;
- - i ;
invites . erase ( safei ) ;
continue ;
}
2007-07-16 17:30:04 +00:00
return true ;
}
}
return false ;
}
2009-10-21 23:45:32 +00:00
InvitedList * LocalUser : : GetInviteList ( )
2007-07-16 17:30:04 +00:00
{
2008-11-01 23:02:23 +00:00
time_t now = ServerInstance - > Time ( ) ;
2008-02-08 23:35:39 +00:00
/* Weed out expired invites here. */
InvitedList : : iterator safei ;
for ( InvitedList : : iterator i = invites . begin ( ) ; i ! = invites . end ( ) ; + + i )
{
if ( i - > second ! = 0 & & now > i - > second )
{
/* Expired invite, remove it. */
safei = i ;
- - i ;
invites . erase ( safei ) ;
}
}
2007-07-16 17:30:04 +00:00
return & invites ;
}
2009-10-21 23:45:32 +00:00
void LocalUser : : InviteTo ( const irc : : string & channel , time_t invtimeout )
2007-07-16 17:30:04 +00:00
{
2008-11-01 23:02:23 +00:00
time_t now = ServerInstance - > Time ( ) ;
2008-02-11 09:41:58 +00:00
if ( invtimeout ! = 0 & & now > invtimeout ) return ; /* Don't add invites that are expired from the get-go. */
2008-02-08 23:35:39 +00:00
for ( InvitedList : : iterator i = invites . begin ( ) ; i ! = invites . end ( ) ; + + i )
{
if ( channel = = i - > first )
{
2008-02-11 09:41:58 +00:00
if ( i - > second ! = 0 & & invtimeout > i - > second )
2008-02-08 23:35:39 +00:00
{
2008-02-11 09:41:58 +00:00
i - > second = invtimeout ;
2008-02-08 23:35:39 +00:00
}
2008-08-07 19:17:17 +00:00
return ;
2008-02-08 23:35:39 +00:00
}
}
2008-02-11 09:41:58 +00:00
invites . push_back ( std : : make_pair ( channel , invtimeout ) ) ;
2007-07-16 17:30:04 +00:00
}
2009-10-21 23:45:32 +00:00
void LocalUser : : RemoveInvite ( const irc : : string & channel )
2007-07-16 17:30:04 +00:00
{
for ( InvitedList : : iterator i = invites . begin ( ) ; i ! = invites . end ( ) ; i + + )
{
2008-02-08 23:35:39 +00:00
if ( channel = = i - > first )
2007-07-16 17:30:04 +00:00
{
invites . erase ( i ) ;
return ;
}
}
}
2009-10-21 23:45:32 +00:00
bool User : : HasModePermission ( unsigned char , ModeType )
2008-03-23 20:43:35 +00:00
{
2009-10-21 23:45:32 +00:00
return true ;
}
2008-03-23 20:43:35 +00:00
2009-10-21 23:45:32 +00:00
bool LocalUser : : HasModePermission ( unsigned char mode , ModeType type )
{
2008-03-23 20:43:35 +00:00
if ( ! IS_OPER ( this ) )
return false ;
2008-09-13 15:47:01 +00:00
if ( mode < ' A ' | | mode > ( ' A ' + 64 ) ) return false ;
2008-03-23 21:12:36 +00:00
2009-10-21 23:46:05 +00:00
return ( ( type = = MODETYPE_USER ? oper - > AllowedUserModes : oper - > AllowedChanModes ) ) [ ( mode - ' A ' ) ] ;
2009-02-14 21:14:36 +00:00
2008-03-23 20:43:35 +00:00
}
2009-10-21 23:45:32 +00:00
/*
* users on remote servers can completely bypass all permissions based checks .
* This prevents desyncs when one server has different type / class tags to another .
* That having been said , this does open things up to the possibility of source changes
* allowing remote kills , etc - but if they have access to the src , they most likely have
* access to the conf - so it ' s an end to a means either way .
*/
bool User : : HasPermission ( const std : : string & )
2007-07-16 17:30:04 +00:00
{
2009-10-21 23:45:32 +00:00
return true ;
}
2007-07-16 17:30:04 +00:00
2009-10-21 23:45:32 +00:00
bool LocalUser : : HasPermission ( const std : : string & command )
{
2007-07-16 17:30:04 +00:00
// are they even an oper at all?
2007-10-15 22:33:18 +00:00
if ( ! IS_OPER ( this ) )
2007-07-16 17:30:04 +00:00
{
2007-10-15 22:33:18 +00:00
return false ;
}
2009-10-21 23:46:05 +00:00
if ( oper - > AllowedOperCommands . find ( command ) ! = oper - > AllowedOperCommands . end ( ) )
2007-11-11 15:44:43 +00:00
return true ;
2009-10-21 23:46:05 +00:00
else if ( oper - > AllowedOperCommands . find ( " * " ) ! = oper - > AllowedOperCommands . end ( ) )
2007-11-11 15:44:43 +00:00
return true ;
2007-10-15 22:33:18 +00:00
2007-07-16 17:30:04 +00:00
return false ;
}
2008-10-18 16:52:48 +00:00
bool User : : HasPrivPermission ( const std : : string & privstr , bool noisy )
2008-10-18 16:52:44 +00:00
{
2009-10-21 23:45:32 +00:00
return true ;
}
2008-10-18 16:52:48 +00:00
2009-10-21 23:45:32 +00:00
bool LocalUser : : HasPrivPermission ( const std : : string & privstr , bool noisy )
{
2008-10-18 16:52:48 +00:00
if ( ! IS_OPER ( this ) )
{
if ( noisy )
this - > WriteServ ( " NOTICE %s :You are not an oper " , this - > nick . c_str ( ) ) ;
return false ;
}
2009-10-21 23:46:05 +00:00
if ( oper - > AllowedPrivs . find ( privstr ) ! = oper - > AllowedPrivs . end ( ) )
2008-10-18 16:52:48 +00:00
{
return true ;
}
2009-10-21 23:46:05 +00:00
else if ( oper - > AllowedPrivs . find ( " * " ) ! = oper - > AllowedPrivs . end ( ) )
2008-10-18 16:52:48 +00:00
{
return true ;
}
if ( noisy )
2009-10-21 23:45:44 +00:00
this - > WriteServ ( " NOTICE %s :Oper type %s does not have access to priv %s " , this - > nick . c_str ( ) , oper - > NameStr ( ) , privstr . c_str ( ) ) ;
2008-10-18 16:52:48 +00:00
return false ;
2008-10-18 16:52:44 +00:00
}
2009-11-06 22:37:36 +00:00
void UserIOHandler : : OnDataReady ( )
2009-10-21 23:45:08 +00:00
{
2009-11-06 22:37:36 +00:00
if ( user - > quitting )
2009-09-21 13:26:31 +00:00
return ;
2007-07-16 17:30:04 +00:00
2009-11-06 22:37:36 +00:00
if ( recvq . length ( ) > user - > MyClass - > GetRecvqMax ( ) & & ! user - > HasPrivPermission ( " users/flood/increased-buffers " ) )
2007-07-16 17:30:04 +00:00
{
2009-11-06 22:37:36 +00:00
ServerInstance - > Users - > QuitUser ( user , " RecvQ exceeded " ) ;
2009-09-21 13:26:31 +00:00
ServerInstance - > SNO - > WriteToSnoMask ( ' a ' , " User %s RecvQ of %lu exceeds connect class maximum of %lu " ,
2009-11-06 22:37:36 +00:00
user - > nick . c_str ( ) , ( unsigned long ) recvq . length ( ) , user - > MyClass - > GetRecvqMax ( ) ) ;
2007-07-16 17:30:04 +00:00
}
2009-09-26 16:41:07 +00:00
unsigned long sendqmax = ULONG_MAX ;
2009-11-06 22:37:36 +00:00
if ( ! user - > HasPrivPermission ( " users/flood/increased-buffers " ) )
sendqmax = user - > MyClass - > GetSendqSoftMax ( ) ;
2009-11-11 19:52:03 +00:00
unsigned long penaltymax = ULONG_MAX ;
if ( ! user - > HasPrivPermission ( " users/flood/no-fakelag " ) )
penaltymax = user - > MyClass - > GetPenaltyThreshold ( ) * 1000 ;
2008-05-07 21:53:30 +00:00
2009-11-11 19:52:03 +00:00
while ( user - > CommandFloodPenalty < penaltymax & & getSendQSize ( ) < sendqmax )
2007-07-16 17:30:04 +00:00
{
2009-09-21 13:26:31 +00:00
std : : string line ;
line . reserve ( MAXBUF ) ;
std : : string : : size_type qpos = 0 ;
while ( qpos < recvq . length ( ) )
2007-07-16 17:30:04 +00:00
{
2009-09-21 13:26:31 +00:00
char c = recvq [ qpos + + ] ;
switch ( c )
2007-07-16 17:30:04 +00:00
{
2009-09-21 13:26:31 +00:00
case ' \0 ' :
c = ' ' ;
break ;
case ' \r ' :
continue ;
case ' \n ' :
goto eol_found ;
2007-07-16 17:30:04 +00:00
}
2009-09-21 13:26:31 +00:00
if ( line . length ( ) < MAXBUF - 2 )
line . push_back ( c ) ;
2007-07-16 17:30:04 +00:00
}
2009-09-21 13:26:31 +00:00
// if we got here, the recvq ran out before we found a newline
return ;
eol_found :
// just found a newline. Terminate the string, and pull it out of recvq
recvq = recvq . substr ( qpos ) ;
2007-07-16 17:30:04 +00:00
2009-09-21 13:26:31 +00:00
// TODO should this be moved to when it was inserted in recvq?
ServerInstance - > stats - > statsRecv + = qpos ;
2009-11-06 22:37:36 +00:00
user - > bytes_in + = qpos ;
user - > cmds_in + + ;
2009-09-21 13:26:31 +00:00
2009-11-06 22:37:36 +00:00
ServerInstance - > Parser - > ProcessBuffer ( line , user ) ;
if ( user - > quitting )
2009-10-19 21:10:10 +00:00
return ;
2007-07-16 17:30:04 +00:00
}
2009-09-26 16:41:07 +00:00
// Add pseudo-penalty so that we continue processing after sendq recedes
2009-11-11 19:52:03 +00:00
if ( user - > CommandFloodPenalty = = 0 & & getSendQSize ( ) > = sendqmax )
user - > CommandFloodPenalty + + ;
if ( user - > CommandFloodPenalty > = penaltymax & & ! user - > MyClass - > fakelag )
ServerInstance - > Users - > QuitUser ( user , " Excess Flood " ) ;
2007-07-16 17:30:04 +00:00
}
2009-11-06 22:37:36 +00:00
void UserIOHandler : : AddWriteBuf ( const std : : string & data )
2007-07-16 17:30:04 +00:00
{
2009-11-06 22:37:36 +00:00
if ( ! user - > quitting & & getSendQSize ( ) + data . length ( ) > user - > MyClass - > GetSendqHardMax ( ) & &
! user - > HasPrivPermission ( " users/flood/increased-buffers " ) )
2007-07-16 17:30:04 +00:00
{
/*
2009-09-27 00:22:29 +00:00
* Quit the user FIRST , because otherwise we could recurse
* here and hit the same limit .
2007-07-16 17:30:04 +00:00
*/
2009-11-06 22:37:36 +00:00
ServerInstance - > Users - > QuitUser ( user , " SendQ exceeded " ) ;
2009-09-27 00:22:29 +00:00
ServerInstance - > SNO - > WriteToSnoMask ( ' a ' , " User %s SendQ exceeds connect class maximum of %lu " ,
2009-11-06 22:37:36 +00:00
user - > nick . c_str ( ) , user - > MyClass - > GetSendqHardMax ( ) ) ;
2007-07-16 17:30:04 +00:00
return ;
}
2009-03-18 10:28:10 +00:00
// We still want to append data to the sendq of a quitting user,
// e.g. their ERROR message that says 'closing link'
2009-09-21 13:26:31 +00:00
WriteData ( data ) ;
2007-07-16 17:30:04 +00:00
}
2009-11-06 22:37:36 +00:00
void UserIOHandler : : OnError ( BufferedSocketError )
2007-07-16 17:30:04 +00:00
{
2009-11-06 22:37:36 +00:00
ServerInstance - > Users - > QuitUser ( user , getError ( ) ) ;
2009-09-21 13:26:31 +00:00
}
2007-08-23 22:06:04 +00:00
2009-10-17 18:52:39 +00:00
CullResult User : : cull ( )
2009-09-21 13:26:31 +00:00
{
if ( ! quitting )
ServerInstance - > Users - > QuitUser ( this , " Culled without QuitUser " ) ;
2009-09-30 17:12:08 +00:00
PurgeEmptyChannels ( ) ;
this - > InvalidateCache ( ) ;
2009-11-01 21:53:47 +00:00
if ( client_sa . sa . sa_family ! = AF_UNSPEC )
ServerInstance - > Users - > RemoveCloneCounts ( this ) ;
2009-10-17 18:52:39 +00:00
return Extensible : : cull ( ) ;
2007-07-16 17:30:04 +00:00
}
2009-10-21 23:45:08 +00:00
CullResult LocalUser : : cull ( )
{
std : : vector < LocalUser * > : : iterator x = find ( ServerInstance - > Users - > local_users . begin ( ) , ServerInstance - > Users - > local_users . end ( ) , this ) ;
if ( x ! = ServerInstance - > Users - > local_users . end ( ) )
ServerInstance - > Users - > local_users . erase ( x ) ;
else
ServerInstance - > Logs - > Log ( " USERS " , DEBUG , " Failed to remove user from vector " ) ;
2009-11-06 22:37:36 +00:00
eh . cull ( ) ;
2009-10-21 23:45:08 +00:00
return User : : cull ( ) ;
}
2009-10-23 22:47:39 +00:00
CullResult FakeUser : : cull ( )
{
// Fake users don't quit, they just get culled.
quitting = true ;
2010-01-30 18:02:25 +00:00
ServerInstance - > Users - > clientlist - > erase ( nick ) ;
ServerInstance - > Users - > uuidlist - > erase ( uuid ) ;
2009-10-23 22:47:39 +00:00
return User : : cull ( ) ;
}
2009-10-21 23:45:44 +00:00
void User : : Oper ( OperInfo * info )
2007-07-16 17:30:04 +00:00
{
2008-08-27 19:28:35 +00:00
if ( this - > IsModeSet ( ' o ' ) )
2008-08-27 19:47:33 +00:00
this - > UnOper ( ) ;
2008-08-27 19:23:17 +00:00
this - > modes [ UM_OPERATOR ] = 1 ;
2009-10-21 23:45:44 +00:00
this - > oper = info ;
2008-08-27 19:23:17 +00:00
this - > WriteServ ( " MODE %s :+o " , this - > nick . c_str ( ) ) ;
2009-10-21 23:45:44 +00:00
FOREACH_MOD ( I_OnOper , OnOper ( this , info - > name ) ) ;
2008-08-27 19:23:17 +00:00
2009-10-21 23:45:44 +00:00
std : : string opername ;
if ( info - > oper_block )
opername = info - > oper_block - > getString ( " name " ) ;
2008-08-27 19:23:17 +00:00
2009-10-23 19:07:40 +00:00
if ( IS_LOCAL ( this ) )
{
LocalUser * l = IS_LOCAL ( this ) ;
std : : string vhost = oper - > getConfig ( " vhost " ) ;
if ( ! vhost . empty ( ) )
l - > ChangeDisplayedHost ( vhost . c_str ( ) ) ;
std : : string opClass = oper - > getConfig ( " class " ) ;
if ( ! opClass . empty ( ) )
l - > SetClass ( opClass ) ;
}
2009-10-21 23:45:44 +00:00
ServerInstance - > SNO - > WriteToSnoMask ( ' o ' , " %s (%s@%s) is now an IRC operator of type %s (using oper '%s') " ,
2009-10-23 19:07:40 +00:00
nick . c_str ( ) , ident . c_str ( ) , host . c_str ( ) , oper - > NameStr ( ) , opername . c_str ( ) ) ;
this - > WriteNumeric ( 381 , " %s :You are now %s %s " , nick . c_str ( ) , strchr ( " aeiouAEIOU " , oper - > name [ 0 ] ) ? " an " : " a " , oper - > NameStr ( ) ) ;
2009-10-21 23:45:44 +00:00
2009-10-23 19:07:40 +00:00
ServerInstance - > Logs - > Log ( " OPER " , DEFAULT , " %s!%s@%s opered as type: %s " , this - > nick . c_str ( ) , this - > ident . c_str ( ) , this - > host . c_str ( ) , oper - > NameStr ( ) ) ;
2008-08-27 19:23:17 +00:00
ServerInstance - > Users - > all_opers . push_back ( this ) ;
2009-10-21 23:46:05 +00:00
// Expand permissions from config for faster lookup
2009-10-21 23:45:32 +00:00
if ( IS_LOCAL ( this ) )
2009-10-21 23:46:05 +00:00
oper - > init ( ) ;
2009-10-21 23:45:32 +00:00
2009-10-23 19:07:40 +00:00
FOREACH_MOD ( I_OnPostOper , OnPostOper ( this , oper - > name , opername ) ) ;
2009-10-21 23:45:32 +00:00
}
2009-10-21 23:46:05 +00:00
void OperInfo : : init ( )
2009-10-21 23:45:32 +00:00
{
2009-10-21 23:46:05 +00:00
AllowedOperCommands . clear ( ) ;
AllowedPrivs . clear ( ) ;
2009-10-21 23:45:44 +00:00
AllowedUserModes . reset ( ) ;
AllowedChanModes . reset ( ) ;
2009-10-21 23:46:05 +00:00
AllowedUserModes [ ' o ' - ' A ' ] = true ; // Call me paranoid if you want.
2009-10-21 23:45:44 +00:00
2009-10-21 23:46:05 +00:00
for ( std : : vector < reference < ConfigTag > > : : iterator iter = class_blocks . begin ( ) ; iter ! = class_blocks . end ( ) ; + + iter )
2009-08-03 21:44:10 +00:00
{
2009-10-21 23:45:44 +00:00
ConfigTag * tag = * iter ;
std : : string mycmd , mypriv ;
/* Process commands */
irc : : spacesepstream CommandList ( tag - > getString ( " commands " ) ) ;
while ( CommandList . GetToken ( mycmd ) )
2008-08-27 19:23:17 +00:00
{
2009-10-21 23:46:05 +00:00
AllowedOperCommands . insert ( mycmd ) ;
2009-10-21 23:45:44 +00:00
}
2009-08-03 21:44:10 +00:00
2009-10-21 23:45:44 +00:00
irc : : spacesepstream PrivList ( tag - > getString ( " privs " ) ) ;
while ( PrivList . GetToken ( mypriv ) )
{
2009-10-21 23:46:05 +00:00
AllowedPrivs . insert ( mypriv ) ;
2009-10-21 23:45:44 +00:00
}
2008-10-18 16:52:48 +00:00
2009-10-21 23:45:44 +00:00
for ( unsigned char * c = ( unsigned char * ) tag - > getString ( " usermodes " ) . c_str ( ) ; * c ; + + c )
{
if ( * c = = ' * ' )
{
this - > AllowedUserModes . set ( ) ;
}
else
{
this - > AllowedUserModes [ * c - ' A ' ] = true ;
}
}
2009-08-03 21:44:10 +00:00
2009-10-21 23:45:44 +00:00
for ( unsigned char * c = ( unsigned char * ) tag - > getString ( " chanmodes " ) . c_str ( ) ; * c ; + + c )
{
if ( * c = = ' * ' )
{
this - > AllowedChanModes . set ( ) ;
}
else
{
this - > AllowedChanModes [ * c - ' A ' ] = true ;
2007-11-11 15:44:43 +00:00
}
}
2007-07-16 17:30:04 +00:00
}
}
2007-10-15 20:59:05 +00:00
void User : : UnOper ( )
2007-07-16 17:30:04 +00:00
{
2009-10-21 23:45:32 +00:00
if ( ! IS_OPER ( this ) )
return ;
2008-08-27 21:37:28 +00:00
2009-10-21 23:45:32 +00:00
/*
* unset their oper type ( what IS_OPER checks ) .
* note , order is important - this must come before modes as - o attempts
* to call UnOper . - - w00t
*/
2009-10-21 23:45:44 +00:00
oper = NULL ;
2009-01-03 17:25:10 +00:00
2008-02-26 20:46:21 +00:00
2009-10-21 23:45:32 +00:00
/* Remove all oper only modes from the user when the deoper - Bug #466*/
std : : string moderemove ( " - " ) ;
2008-02-26 20:46:21 +00:00
2009-10-21 23:45:32 +00:00
for ( unsigned char letter = ' A ' ; letter < = ' z ' ; letter + + )
{
ModeHandler * mh = ServerInstance - > Modes - > FindMode ( letter , MODETYPE_USER ) ;
if ( mh & & mh - > NeedsOper ( ) )
moderemove + = letter ;
}
2009-01-03 17:25:10 +00:00
2008-05-04 21:37:36 +00:00
2009-10-21 23:45:32 +00:00
std : : vector < std : : string > parameters ;
parameters . push_back ( this - > nick ) ;
parameters . push_back ( moderemove ) ;
2009-01-03 17:25:10 +00:00
2009-10-21 23:45:32 +00:00
ServerInstance - > Parser - > CallHandler ( " MODE " , parameters , this ) ;
2007-11-11 15:44:43 +00:00
2009-10-21 23:45:32 +00:00
/* remove the user from the oper list. Will remove multiple entries as a safeguard against bug #404 */
ServerInstance - > Users - > all_opers . remove ( this ) ;
2008-03-23 21:36:16 +00:00
2009-10-21 23:45:32 +00:00
this - > modes [ UM_OPERATOR ] = 0 ;
}
2008-10-18 16:52:48 +00:00
2007-07-16 17:30:04 +00:00
/* adds or updates an entry in the whowas list */
2007-10-15 20:59:05 +00:00
void User : : AddToWhoWas ( )
2007-07-16 17:30:04 +00:00
{
2009-09-03 21:06:44 +00:00
Module * whowas = ServerInstance - > Modules - > Find ( " cmd_whowas.so " ) ;
if ( whowas )
2007-07-16 17:30:04 +00:00
{
2009-09-03 21:06:44 +00:00
WhowasRequest req ( NULL , whowas , WhowasRequest : : WHOWAS_ADD ) ;
req . user = this ;
req . Send ( ) ;
2007-07-16 17:30:04 +00:00
}
}
/*
* Check class restrictions
*/
2009-10-21 23:45:32 +00:00
void LocalUser : : CheckClass ( )
2007-07-16 17:30:04 +00:00
{
2007-10-23 23:25:49 +00:00
ConnectClass * a = this - > MyClass ;
2007-07-16 17:30:04 +00:00
2009-10-21 23:45:32 +00:00
if ( ! a )
{
ServerInstance - > Users - > QuitUser ( this , " Access denied by configuration " ) ;
}
else if ( a - > type = = CC_DENY )
2007-07-16 17:30:04 +00:00
{
2008-04-09 15:34:54 +00:00
ServerInstance - > Users - > QuitUser ( this , " Unauthorised connection " ) ;
2007-07-16 17:30:04 +00:00
return ;
}
2008-01-13 03:37:25 +00:00
else if ( ( a - > GetMaxLocal ( ) ) & & ( ServerInstance - > Users - > LocalCloneCount ( this ) > a - > GetMaxLocal ( ) ) )
2007-07-16 17:30:04 +00:00
{
2008-04-09 15:34:54 +00:00
ServerInstance - > Users - > QuitUser ( this , " No more connections allowed from your host via this connect class (local) " ) ;
2009-04-16 15:51:05 +00:00
ServerInstance - > SNO - > WriteToSnoMask ( ' a ' , " WARNING: maximum LOCAL connections (%ld) exceeded for IP %s " , a - > GetMaxLocal ( ) , this - > GetIPString ( ) ) ;
2007-07-16 17:30:04 +00:00
return ;
}
2008-01-13 03:37:25 +00:00
else if ( ( a - > GetMaxGlobal ( ) ) & & ( ServerInstance - > Users - > GlobalCloneCount ( this ) > a - > GetMaxGlobal ( ) ) )
2007-07-16 17:30:04 +00:00
{
2008-04-09 15:34:54 +00:00
ServerInstance - > Users - > QuitUser ( this , " No more connections allowed from your host via this connect class (global) " ) ;
2009-04-16 15:51:05 +00:00
ServerInstance - > SNO - > WriteToSnoMask ( ' a ' , " WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s " , a - > GetMaxGlobal ( ) , this - > GetIPString ( ) ) ;
2007-07-16 17:30:04 +00:00
return ;
}
2007-08-06 19:55:09 +00:00
this - > nping = ServerInstance - > Time ( ) + a - > GetPingTime ( ) + ServerInstance - > Config - > dns_timeout ;
2007-07-16 17:30:04 +00:00
}
2008-09-29 08:13:49 +00:00
bool User : : CheckLines ( bool doZline )
2008-04-12 15:48:01 +00:00
{
2008-09-29 08:13:49 +00:00
const char * check [ ] = { " G " , " K " , ( doZline ) ? " Z " : NULL , NULL } ;
2009-02-14 21:14:36 +00:00
2008-04-12 15:48:01 +00:00
if ( ! this - > exempt )
{
for ( int n = 0 ; check [ n ] ; + + n )
{
XLine * r = ServerInstance - > XLines - > MatchesLine ( check [ n ] , this ) ;
if ( r )
{
r - > Apply ( this ) ;
2008-07-12 09:43:58 +00:00
return true ;
2008-04-12 15:48:01 +00:00
}
}
}
2008-07-12 09:43:58 +00:00
return false ;
2008-04-12 15:48:01 +00:00
}
2009-10-21 23:44:58 +00:00
void LocalUser : : FullConnect ( )
2007-07-16 17:30:04 +00:00
{
ServerInstance - > stats - > statsConnects + + ;
this - > idle_lastmsg = ServerInstance - > Time ( ) ;
/*
2007-10-15 20:59:05 +00:00
* You may be thinking " wtf, we checked this in User::AddClient! " - and yes , we did , BUT .
2007-07-16 17:30:04 +00:00
* At the time AddClient is called , we don ' t have a resolved host , by here we probably do - which
* may put the user into a totally seperate class with different restrictions ! so we * must * check again .
* Don ' t remove this ! - - w00t
*/
2007-10-23 23:25:49 +00:00
this - > SetClass ( ) ;
2009-02-14 21:14:36 +00:00
2007-07-16 17:30:04 +00:00
/* Check the password, if one is required by the user's connect class.
* This CANNOT be in CheckClass ( ) , because that is called prior to PASS as well !
*/
2009-10-21 23:45:32 +00:00
if ( ! MyClass - > pass . empty ( ) )
2007-07-16 17:30:04 +00:00
{
2009-10-17 02:43:07 +00:00
if ( ServerInstance - > PassCompare ( this , MyClass - > pass . c_str ( ) , password . c_str ( ) , MyClass - > hash . c_str ( ) ) )
{
ServerInstance - > Users - > QuitUser ( this , " Invalid password " ) ;
return ;
}
2007-07-16 17:30:04 +00:00
}
2010-01-31 03:42:20 +00:00
CheckClass ( ) ;
CheckLines ( ) ;
2007-10-25 15:25:32 +00:00
2010-01-31 03:42:20 +00:00
if ( quitting )
2008-07-12 09:43:58 +00:00
return ;
2007-07-16 17:30:04 +00:00
2009-10-03 01:52:59 +00:00
this - > WriteServ ( " NOTICE Auth :Welcome to \002 %s \002 ! " , ServerInstance - > Config - > Network . c_str ( ) ) ;
this - > WriteNumeric ( RPL_WELCOME , " %s :Welcome to the %s IRC Network %s!%s@%s " , this - > nick . c_str ( ) , ServerInstance - > Config - > Network . c_str ( ) , this - > nick . c_str ( ) , this - > ident . c_str ( ) , this - > host . c_str ( ) ) ;
this - > WriteNumeric ( RPL_YOURHOSTIS , " %s :Your host is %s, running version InspIRCd-2.0 " , this - > nick . c_str ( ) , ServerInstance - > Config - > ServerName . c_str ( ) ) ;
2008-07-13 19:19:15 +00:00
this - > WriteNumeric ( RPL_SERVERCREATED , " %s :This server was created %s %s " , this - > nick . c_str ( ) , __TIME__ , __DATE__ ) ;
2009-10-03 01:52:59 +00:00
this - > WriteNumeric ( RPL_SERVERVERSION , " %s %s InspIRCd-2.0 %s %s %s " , this - > nick . c_str ( ) , ServerInstance - > Config - > ServerName . c_str ( ) , ServerInstance - > Modes - > UserModeList ( ) . c_str ( ) , ServerInstance - > Modes - > ChannelModeList ( ) . c_str ( ) , ServerInstance - > Modes - > ParaModeList ( ) . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
ServerInstance - > Config - > Send005 ( this ) ;
2008-07-13 19:19:15 +00:00
this - > WriteNumeric ( RPL_YOURUUID , " %s %s :your unique ID " , this - > nick . c_str ( ) , this - > uuid . c_str ( ) ) ;
2007-08-27 00:12:59 +00:00
2007-07-16 17:30:04 +00:00
/* Now registered */
2008-02-02 20:55:16 +00:00
if ( ServerInstance - > Users - > unregistered_count )
ServerInstance - > Users - > unregistered_count - - ;
2007-07-16 17:30:04 +00:00
2010-01-19 04:43:19 +00:00
/* Trigger MOTD and LUSERS output, give modules a chance too */
2009-09-02 00:49:36 +00:00
ModResult MOD_RESULT ;
2010-01-19 04:43:19 +00:00
std : : string command ( " MOTD " ) ;
2008-06-06 15:28:24 +00:00
std : : vector < std : : string > parameters ;
2010-01-19 04:43:19 +00:00
FIRST_MOD_RESULT ( OnPreCommand , MOD_RESULT , ( command , parameters , this , true , command ) ) ;
if ( ! MOD_RESULT )
ServerInstance - > CallCommandHandler ( command , parameters , this ) ;
MOD_RESULT = MOD_RES_PASSTHRU ;
command = " LUSERS " ;
FIRST_MOD_RESULT ( OnPreCommand , MOD_RESULT , ( command , parameters , this , true , command ) ) ;
2007-07-16 17:30:04 +00:00
if ( ! MOD_RESULT )
2008-06-06 15:28:24 +00:00
ServerInstance - > CallCommandHandler ( command , parameters , this ) ;
2007-07-16 17:30:04 +00:00
/*
2007-10-16 10:21:11 +00:00
* We don ' t set REG_ALL until triggering OnUserConnect , so some module events don ' t spew out stuff
* for a user that doesn ' t exist yet .
2007-07-16 17:30:04 +00:00
*/
FOREACH_MOD ( I_OnUserConnect , OnUserConnect ( this ) ) ;
this - > registered = REG_ALL ;
FOREACH_MOD ( I_OnPostConnect , OnPostConnect ( this ) ) ;
2009-09-01 15:07:27 +00:00
ServerInstance - > SNO - > WriteToSnoMask ( ' c ' , " Client connecting on port %d: %s!%s@%s [%s] [%s] " ,
this - > GetServerPort ( ) , this - > nick . c_str ( ) , this - > ident . c_str ( ) , this - > host . c_str ( ) , this - > GetIPString ( ) , this - > fullname . c_str ( ) ) ;
2008-02-09 13:06:02 +00:00
ServerInstance - > Logs - > Log ( " BANCACHE " , DEBUG , " BanCache: Adding NEGATIVE hit for %s " , this - > GetIPString ( ) ) ;
2007-11-04 23:15:26 +00:00
ServerInstance - > BanCache - > AddHit ( this - > GetIPString ( ) , " " , " " ) ;
2007-07-16 17:30:04 +00:00
}
2007-10-15 20:59:05 +00:00
void User : : InvalidateCache ( )
2007-07-16 17:30:04 +00:00
{
/* Invalidate cache */
2008-05-18 23:15:53 +00:00
cached_fullhost . clear ( ) ;
cached_hostip . clear ( ) ;
cached_makehost . clear ( ) ;
cached_fullrealhost . clear ( ) ;
2007-07-16 17:30:04 +00:00
}
2010-01-30 18:40:51 +00:00
bool User : : ChangeNick ( const std : : string & newnick , bool force )
2007-07-16 17:30:04 +00:00
{
2009-09-02 00:49:36 +00:00
ModResult MOD_RESULT ;
2007-07-16 17:30:04 +00:00
2010-01-30 18:40:51 +00:00
if ( force )
ServerInstance - > NICKForced . set ( this , 1 ) ;
2009-09-26 14:13:13 +00:00
FIRST_MOD_RESULT ( OnUserPreNick , MOD_RESULT , ( this , newnick ) ) ;
2009-10-11 18:03:17 +00:00
ServerInstance - > NICKForced . set ( this , 0 ) ;
2009-02-04 12:50:19 +00:00
2009-09-02 00:49:36 +00:00
if ( MOD_RESULT = = MOD_RES_DENY )
2008-04-07 22:00:49 +00:00
{
ServerInstance - > stats - > statsCollisions + + ;
return false ;
}
2008-02-09 13:06:02 +00:00
2010-01-30 18:40:51 +00:00
if ( assign ( newnick ) = = assign ( nick ) )
2007-07-16 17:30:04 +00:00
{
2010-01-30 18:40:51 +00:00
// case change, don't need to check Q:lines and such
// and, if it's identical including case, we can leave right now
if ( newnick = = nick )
return true ;
2007-07-16 17:30:04 +00:00
}
2010-01-30 18:40:51 +00:00
else
{
/*
* Don ' t check Q : Lines if it ' s a server - enforced change , just on the off - chance some fucking * moron *
* tries to Q : Line SIDs , also , this means we just get our way period , as it really should be .
* Thanks Kein for finding this . - - w00t
*
* Also don ' t check Q : Lines for remote nickchanges , they should have our Q : Lines anyway to enforce themselves .
* - - w00t
*/
if ( ! IS_LOCAL ( this ) )
{
XLine * mq = ServerInstance - > XLines - > MatchesLine ( " Q " , newnick ) ;
if ( mq )
{
if ( this - > registered = = REG_ALL )
{
ServerInstance - > SNO - > WriteGlobalSno ( ' a ' , " Q-Lined nickname %s from %s!%s@%s: %s " ,
newnick . c_str ( ) , this - > nick . c_str ( ) , this - > ident . c_str ( ) , this - > host . c_str ( ) , mq - > reason . c_str ( ) ) ;
}
this - > WriteNumeric ( 432 , " %s %s :Invalid nickname: %s " , this - > nick . c_str ( ) , newnick . c_str ( ) , mq - > reason . c_str ( ) ) ;
return false ;
}
2008-02-09 13:06:02 +00:00
2010-01-30 18:40:51 +00:00
if ( ServerInstance - > Config - > RestrictBannedUsers )
{
for ( UCListIter i = this - > chans . begin ( ) ; i ! = this - > chans . end ( ) ; i + + )
{
Channel * chan = * i ;
if ( chan - > GetPrefixValue ( this ) < VOICE_VALUE & & chan - > IsBanned ( this ) )
{
this - > WriteNumeric ( 404 , " %s %s :Cannot send to channel (you're banned) " , this - > nick . c_str ( ) , chan - > name . c_str ( ) ) ;
return false ;
}
}
}
}
/*
* Uh oh . . if the nickname is in use , and it ' s not in use by the person using it ( doh ) - -
* then we have a potential collide . Check whether someone else is camping on the nick
* ( i . e . connect - > send NICK , don ' t send USER . ) If they are camping , force - change the
* camper to their UID , and allow the incoming nick change .
*
* If the guy using the nick is already using it , tell the incoming nick change to gtfo ,
* because the nick is already ( rightfully ) in use . - - w00t
*/
User * InUse = ServerInstance - > FindNickOnly ( newnick ) ;
if ( InUse & & ( InUse ! = this ) )
{
if ( InUse - > registered ! = REG_ALL )
{
/* force the camper to their UUID, and ask them to re-send a NICK. */
InUse - > WriteTo ( InUse , " NICK %s " , InUse - > uuid . c_str ( ) ) ;
InUse - > WriteNumeric ( 433 , " %s %s :Nickname overruled. " , InUse - > nick . c_str ( ) , InUse - > nick . c_str ( ) ) ;
2010-01-30 18:56:39 +00:00
ServerInstance - > Users - > clientlist - > erase ( InUse - > nick ) ;
( * ( ServerInstance - > Users - > clientlist ) ) [ InUse - > uuid ] = InUse ;
InUse - > nick = InUse - > uuid ;
2010-01-30 18:40:51 +00:00
InUse - > InvalidateCache ( ) ;
InUse - > registered & = ~ REG_NICK ;
}
else
{
/* No camping, tell the incoming user to stop trying to change nick ;p */
this - > WriteNumeric ( 433 , " %s %s :Nickname is already in use. " , this - > registered > = REG_NICK ? this - > nick . c_str ( ) : " * " , newnick . c_str ( ) ) ;
2010-01-30 18:56:39 +00:00
return false ;
2010-01-30 18:40:51 +00:00
}
}
}
if ( this - > registered = = REG_ALL )
this - > WriteCommon ( " NICK %s " , newnick . c_str ( ) ) ;
std : : string oldnick = nick ;
nick = newnick ;
2010-01-30 18:56:39 +00:00
2010-01-30 18:40:51 +00:00
InvalidateCache ( ) ;
2010-01-30 18:56:39 +00:00
ServerInstance - > Users - > clientlist - > erase ( oldnick ) ;
( * ( ServerInstance - > Users - > clientlist ) ) [ newnick ] = this ;
2010-01-30 18:40:51 +00:00
FOREACH_MOD ( I_OnUserPostNick , OnUserPostNick ( this , oldnick ) ) ;
return true ;
2007-07-16 17:30:04 +00:00
}
2009-10-21 23:45:08 +00:00
int LocalUser : : GetServerPort ( )
2007-07-16 17:30:04 +00:00
{
2009-09-01 15:07:36 +00:00
switch ( this - > server_sa . sa . sa_family )
2007-07-16 17:30:04 +00:00
{
case AF_INET6 :
2009-09-01 15:07:52 +00:00
return htons ( this - > server_sa . in6 . sin6_port ) ;
2007-07-16 17:30:04 +00:00
case AF_INET :
2009-09-01 15:07:52 +00:00
return htons ( this - > server_sa . in4 . sin_port ) ;
2007-07-16 17:30:04 +00:00
}
return 0 ;
}
2009-09-01 15:07:52 +00:00
const char * User : : GetIPString ( )
{
int port ;
if ( cachedip . empty ( ) )
2007-07-16 17:30:04 +00:00
{
2009-10-22 21:49:39 +00:00
irc : : sockets : : satoap ( client_sa , cachedip , port ) ;
2009-09-01 15:07:52 +00:00
/* IP addresses starting with a : on irc are a Bad Thing (tm) */
if ( cachedip . c_str ( ) [ 0 ] = = ' : ' )
cachedip . insert ( 0 , 1 , ' 0 ' ) ;
2007-07-16 17:30:04 +00:00
}
2009-02-14 21:14:36 +00:00
2009-09-01 15:07:52 +00:00
return cachedip . c_str ( ) ;
2007-07-16 17:30:04 +00:00
}
2009-10-24 20:04:05 +00:00
irc : : sockets : : cidr_mask User : : GetCIDRMask ( )
2009-10-22 21:49:39 +00:00
{
int range = 0 ;
switch ( client_sa . sa . sa_family )
{
case AF_INET6 :
range = ServerInstance - > Config - > c_ipv6_range ;
break ;
case AF_INET :
range = ServerInstance - > Config - > c_ipv4_range ;
break ;
}
2009-10-24 20:04:05 +00:00
return irc : : sockets : : cidr_mask ( client_sa , range ) ;
2009-10-22 21:49:39 +00:00
}
2009-09-01 15:07:36 +00:00
bool User : : SetClientIP ( const char * sip )
{
this - > cachedip = " " ;
2009-10-22 21:49:39 +00:00
return irc : : sockets : : aptosa ( sip , 0 , client_sa ) ;
2009-09-01 15:07:36 +00:00
}
2009-09-21 13:26:31 +00:00
static std : : string wide_newline ( " \r \n " ) ;
2009-09-02 00:45:29 +00:00
void User : : Write ( const std : : string & text )
2009-10-21 23:45:08 +00:00
{
}
void User : : Write ( const char * text , . . . )
{
}
void LocalUser : : Write ( const std : : string & text )
2007-07-16 17:30:04 +00:00
{
2009-11-06 22:37:36 +00:00
if ( ! ServerInstance - > SE - > BoundsCheckFd ( & eh ) )
2007-07-16 17:30:04 +00:00
return ;
2009-09-21 13:26:31 +00:00
if ( text . length ( ) > MAXBUF - 2 )
2007-07-16 17:30:04 +00:00
{
2009-09-21 13:26:31 +00:00
// this should happen rarely or never. Crop the string at 512 and try again.
std : : string try_again = text . substr ( 0 , MAXBUF - 2 ) ;
Write ( try_again ) ;
return ;
2007-07-16 17:30:04 +00:00
}
2009-09-21 13:26:31 +00:00
2009-11-03 22:45:50 +00:00
ServerInstance - > Logs - > Log ( " USEROUTPUT " , DEBUG , " C[%s] O %s " , uuid . c_str ( ) , text . c_str ( ) ) ;
2009-09-21 13:26:31 +00:00
2009-11-06 22:37:36 +00:00
eh . AddWriteBuf ( text ) ;
eh . AddWriteBuf ( wide_newline ) ;
2009-09-21 13:26:31 +00:00
2009-09-02 00:45:29 +00:00
ServerInstance - > stats - > statsSent + = text . length ( ) + 2 ;
2009-09-21 13:26:31 +00:00
this - > bytes_out + = text . length ( ) + 2 ;
this - > cmds_out + + ;
2007-07-16 17:30:04 +00:00
}
/** Write()
*/
2009-10-21 23:45:08 +00:00
void LocalUser : : Write ( const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
va_list argsPtr ;
char textbuffer [ MAXBUF ] ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer , MAXBUF , text , argsPtr ) ;
va_end ( argsPtr ) ;
this - > Write ( std : : string ( textbuffer ) ) ;
}
2007-10-15 20:59:05 +00:00
void User : : WriteServ ( const std : : string & text )
2007-07-16 17:30:04 +00:00
{
2009-10-03 01:52:59 +00:00
this - > Write ( " :%s %s " , ServerInstance - > Config - > ServerName . c_str ( ) , text . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
}
/** WriteServ()
* Same as Write ( ) , except ` text ' is prefixed with ` : server . name ' .
*/
2007-10-15 20:59:05 +00:00
void User : : WriteServ ( const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
va_list argsPtr ;
char textbuffer [ MAXBUF ] ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer , MAXBUF , text , argsPtr ) ;
va_end ( argsPtr ) ;
this - > WriteServ ( std : : string ( textbuffer ) ) ;
}
2008-03-22 11:45:57 +00:00
void User : : WriteNumeric ( unsigned int numeric , const char * text , . . . )
{
va_list argsPtr ;
char textbuffer [ MAXBUF ] ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer , MAXBUF , text , argsPtr ) ;
va_end ( argsPtr ) ;
this - > WriteNumeric ( numeric , std : : string ( textbuffer ) ) ;
}
void User : : WriteNumeric ( unsigned int numeric , const std : : string & text )
{
char textbuffer [ MAXBUF ] ;
2009-09-02 00:49:36 +00:00
ModResult MOD_RESULT ;
2008-03-22 11:45:57 +00:00
2009-09-26 14:13:13 +00:00
FIRST_MOD_RESULT ( OnNumeric , MOD_RESULT , ( this , numeric , text ) ) ;
2008-03-22 11:45:57 +00:00
2009-09-02 00:49:36 +00:00
if ( MOD_RESULT = = MOD_RES_DENY )
2008-03-22 11:45:57 +00:00
return ;
2009-10-03 01:52:59 +00:00
snprintf ( textbuffer , MAXBUF , " :%s %03u %s " , ServerInstance - > Config - > ServerName . c_str ( ) , numeric , text . c_str ( ) ) ;
2008-03-22 11:45:57 +00:00
this - > Write ( std : : string ( textbuffer ) ) ;
}
2007-10-15 20:59:05 +00:00
void User : : WriteFrom ( User * user , const std : : string & text )
2007-07-16 17:30:04 +00:00
{
char tb [ MAXBUF ] ;
2008-05-18 23:15:53 +00:00
snprintf ( tb , MAXBUF , " :%s %s " , user - > GetFullHost ( ) . c_str ( ) , text . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
this - > Write ( std : : string ( tb ) ) ;
}
/* write text from an originating user to originating user */
2007-10-15 20:59:05 +00:00
void User : : WriteFrom ( User * user , const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
va_list argsPtr ;
char textbuffer [ MAXBUF ] ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer , MAXBUF , text , argsPtr ) ;
va_end ( argsPtr ) ;
this - > WriteFrom ( user , std : : string ( textbuffer ) ) ;
}
/* write text to an destination user from a source user (e.g. user privmsg) */
2007-10-15 20:59:05 +00:00
void User : : WriteTo ( User * dest , const char * data , . . . )
2007-07-16 17:30:04 +00:00
{
char textbuffer [ MAXBUF ] ;
va_list argsPtr ;
va_start ( argsPtr , data ) ;
vsnprintf ( textbuffer , MAXBUF , data , argsPtr ) ;
va_end ( argsPtr ) ;
this - > WriteTo ( dest , std : : string ( textbuffer ) ) ;
}
2007-10-15 20:59:05 +00:00
void User : : WriteTo ( User * dest , const std : : string & data )
2007-07-16 17:30:04 +00:00
{
dest - > WriteFrom ( this , data ) ;
}
2007-10-15 20:59:05 +00:00
void User : : WriteCommon ( const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
char textbuffer [ MAXBUF ] ;
va_list argsPtr ;
2009-10-12 13:20:47 +00:00
if ( this - > registered ! = REG_ALL | | quitting )
2007-07-16 17:30:04 +00:00
return ;
2009-10-05 23:27:46 +00:00
int len = snprintf ( textbuffer , MAXBUF , " :%s " , this - > GetFullHost ( ) . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
va_start ( argsPtr , text ) ;
2009-10-05 23:27:46 +00:00
vsnprintf ( textbuffer + len , MAXBUF - len , text , argsPtr ) ;
2007-07-16 17:30:04 +00:00
va_end ( argsPtr ) ;
2009-10-05 23:27:46 +00:00
this - > WriteCommonRaw ( std : : string ( textbuffer ) , true ) ;
2007-07-16 17:30:04 +00:00
}
2009-10-05 23:27:46 +00:00
void User : : WriteCommonExcept ( const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
2009-10-05 23:27:46 +00:00
char textbuffer [ MAXBUF ] ;
va_list argsPtr ;
2007-07-16 17:30:04 +00:00
2009-10-12 13:20:47 +00:00
if ( this - > registered ! = REG_ALL | | quitting )
2008-02-09 13:06:02 +00:00
return ;
2007-07-16 17:30:04 +00:00
2009-10-05 23:27:46 +00:00
int len = snprintf ( textbuffer , MAXBUF , " :%s " , this - > GetFullHost ( ) . c_str ( ) ) ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer + len , MAXBUF - len , text , argsPtr ) ;
va_end ( argsPtr ) ;
this - > WriteCommonRaw ( std : : string ( textbuffer ) , false ) ;
}
void User : : WriteCommonRaw ( const std : : string & line , bool include_self )
{
2009-10-12 13:20:47 +00:00
if ( this - > registered ! = REG_ALL | | quitting )
2009-10-05 23:27:46 +00:00
return ;
2007-07-16 17:30:04 +00:00
2009-10-16 17:01:49 +00:00
uniq_id_t uniq_id = + + already_sent ;
2009-10-05 23:27:46 +00:00
UserChanList include_c ( chans ) ;
std : : map < User * , bool > exceptions ;
2008-04-02 17:08:09 +00:00
2009-10-05 23:27:46 +00:00
exceptions [ this ] = include_self ;
2007-07-16 17:30:04 +00:00
2009-10-05 23:27:46 +00:00
FOREACH_MOD ( I_OnBuildNeighborList , OnBuildNeighborList ( this , include_c , exceptions ) ) ;
for ( std : : map < User * , bool > : : iterator i = exceptions . begin ( ) ; i ! = exceptions . end ( ) ; + + i )
2008-02-09 13:06:02 +00:00
{
2009-10-25 15:21:45 +00:00
LocalUser * u = IS_LOCAL ( i - > first ) ;
if ( u & & ! u - > quitting )
2009-10-05 23:27:46 +00:00
{
2009-10-25 15:21:45 +00:00
already_sent [ u - > GetFd ( ) ] = uniq_id ;
2009-10-05 23:27:46 +00:00
if ( i - > second )
u - > Write ( line ) ;
}
}
for ( UCListIter v = include_c . begin ( ) ; v ! = include_c . end ( ) ; + + v )
{
Channel * c = * v ;
const UserMembList * ulist = c - > GetUsers ( ) ;
2009-09-13 20:30:47 +00:00
for ( UserMembList : : const_iterator i = ulist - > begin ( ) ; i ! = ulist - > end ( ) ; i + + )
2007-07-16 17:30:04 +00:00
{
2009-10-25 15:21:45 +00:00
LocalUser * u = IS_LOCAL ( i - > first ) ;
if ( u & & ! u - > quitting & & already_sent [ u - > GetFd ( ) ] ! = uniq_id )
2007-07-16 17:30:04 +00:00
{
2009-10-25 15:21:45 +00:00
already_sent [ u - > GetFd ( ) ] = uniq_id ;
2009-10-05 23:27:46 +00:00
u - > Write ( line ) ;
2007-07-16 17:30:04 +00:00
}
}
}
}
2007-10-15 20:59:05 +00:00
void User : : WriteCommonQuit ( const std : : string & normal_text , const std : : string & oper_text )
2007-07-16 17:30:04 +00:00
{
2008-07-02 14:22:48 +00:00
char tb1 [ MAXBUF ] ;
char tb2 [ MAXBUF ] ;
2007-07-16 17:30:04 +00:00
if ( this - > registered ! = REG_ALL )
return ;
2009-10-16 17:01:49 +00:00
uniq_id_t uniq_id = + + already_sent ;
2008-04-02 17:08:09 +00:00
2008-07-02 14:22:48 +00:00
snprintf ( tb1 , MAXBUF , " :%s QUIT :%s " , this - > GetFullHost ( ) . c_str ( ) , normal_text . c_str ( ) ) ;
snprintf ( tb2 , MAXBUF , " :%s QUIT :%s " , this - > GetFullHost ( ) . c_str ( ) , oper_text . c_str ( ) ) ;
std : : string out1 = tb1 ;
std : : string out2 = tb2 ;
2007-07-16 17:30:04 +00:00
2009-10-05 23:27:46 +00:00
UserChanList include_c ( chans ) ;
std : : map < User * , bool > exceptions ;
FOREACH_MOD ( I_OnBuildNeighborList , OnBuildNeighborList ( this , include_c , exceptions ) ) ;
for ( std : : map < User * , bool > : : iterator i = exceptions . begin ( ) ; i ! = exceptions . end ( ) ; + + i )
2007-07-16 17:30:04 +00:00
{
2009-10-25 15:21:45 +00:00
LocalUser * u = IS_LOCAL ( i - > first ) ;
if ( u & & ! u - > quitting )
2007-07-16 17:30:04 +00:00
{
2009-10-25 15:21:45 +00:00
already_sent [ u - > GetFd ( ) ] = uniq_id ;
2009-10-05 23:27:46 +00:00
if ( i - > second )
2009-10-01 14:40:17 +00:00
u - > Write ( IS_OPER ( u ) ? out2 : out1 ) ;
2007-07-16 17:30:04 +00:00
}
}
2009-10-05 23:27:46 +00:00
for ( UCListIter v = include_c . begin ( ) ; v ! = include_c . end ( ) ; + + v )
2007-07-16 17:30:04 +00:00
{
2009-09-13 20:30:47 +00:00
const UserMembList * ulist = ( * v ) - > GetUsers ( ) ;
for ( UserMembList : : const_iterator i = ulist - > begin ( ) ; i ! = ulist - > end ( ) ; i + + )
2007-07-16 17:30:04 +00:00
{
2009-10-25 15:21:45 +00:00
LocalUser * u = IS_LOCAL ( i - > first ) ;
if ( u & & ! u - > quitting & & ( already_sent [ u - > GetFd ( ) ] ! = uniq_id ) )
2007-07-16 17:30:04 +00:00
{
2009-10-25 15:21:45 +00:00
already_sent [ u - > GetFd ( ) ] = uniq_id ;
2009-10-05 23:27:46 +00:00
u - > Write ( IS_OPER ( u ) ? out2 : out1 ) ;
2007-07-16 17:30:04 +00:00
}
}
}
}
2009-10-21 23:44:48 +00:00
void LocalUser : : SendText ( const std : : string & line )
{
Write ( line ) ;
}
void RemoteUser : : SendText ( const std : : string & line )
{
ServerInstance - > PI - > PushToClient ( this , line ) ;
}
void FakeUser : : SendText ( const std : : string & line )
2007-07-16 17:30:04 +00:00
{
}
2009-10-20 04:40:27 +00:00
void User : : SendText ( const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
va_list argsPtr ;
2009-10-20 04:40:27 +00:00
char line [ MAXBUF ] ;
2007-07-16 17:30:04 +00:00
va_start ( argsPtr , text ) ;
2009-10-20 04:40:27 +00:00
vsnprintf ( line , MAXBUF , text , argsPtr ) ;
2007-07-16 17:30:04 +00:00
va_end ( argsPtr ) ;
2009-10-20 04:40:27 +00:00
SendText ( std : : string ( line ) ) ;
}
void User : : SendText ( const std : : string & LinePrefix , std : : stringstream & TextStream )
{
char line [ MAXBUF ] ;
int start_pos = LinePrefix . length ( ) ;
int pos = start_pos ;
memcpy ( line , LinePrefix . data ( ) , pos ) ;
std : : string Word ;
while ( TextStream > > Word )
{
int len = Word . length ( ) ;
if ( pos + len + 12 > MAXBUF )
{
line [ pos ] = ' \0 ' ;
SendText ( std : : string ( line ) ) ;
pos = start_pos ;
}
line [ pos ] = ' ' ;
memcpy ( line + pos + 1 , Word . data ( ) , len ) ;
pos + = len + 1 ;
}
line [ pos ] = ' \0 ' ;
SendText ( std : : string ( line ) ) ;
2007-07-16 17:30:04 +00:00
}
/* return 0 or 1 depending if users u and u2 share one or more common channels
* ( used by QUIT , NICK etc which arent channel specific notices )
*
* The old algorithm in 1.0 for this was relatively inefficient , iterating over
* the first users channels then the second users channels within the outer loop ,
* therefore it was a maximum of x * y iterations ( upon returning 0 and checking
* all possible iterations ) . However this new function instead checks against the
2007-10-15 20:59:05 +00:00
* channel ' s userlist in the inner loop which is a std : : map < User * , User * >
2007-07-16 17:30:04 +00:00
* and saves us time as we already know what pointer value we are after .
* Don ' t quote me on the maths as i am not a mathematician or computer scientist ,
* but i believe this algorithm is now x + ( log y ) maximum iterations instead .
*/
2007-10-15 20:59:05 +00:00
bool User : : SharesChannelWith ( User * other )
2007-07-16 17:30:04 +00:00
{
if ( ( ! other ) | | ( this - > registered ! = REG_ALL ) | | ( other - > registered ! = REG_ALL ) )
return false ;
/* Outer loop */
for ( UCListIter i = this - > chans . begin ( ) ; i ! = this - > chans . end ( ) ; i + + )
{
/* Eliminate the inner loop (which used to be ~equal in size to the outer loop)
* by replacing it with a map : : find which * should * be more efficient
*/
2009-09-13 20:30:47 +00:00
if ( ( * i ) - > HasUser ( other ) )
2007-07-16 17:30:04 +00:00
return true ;
}
return false ;
}
2007-10-15 20:59:05 +00:00
bool User : : ChangeName ( const char * gecos )
2007-07-16 17:30:04 +00:00
{
2008-05-18 23:15:53 +00:00
if ( ! this - > fullname . compare ( gecos ) )
2007-07-16 17:30:04 +00:00
return true ;
if ( IS_LOCAL ( this ) )
{
2009-09-02 00:49:36 +00:00
ModResult MOD_RESULT ;
2009-10-21 23:45:19 +00:00
FIRST_MOD_RESULT ( OnChangeLocalUserGECOS , MOD_RESULT , ( IS_LOCAL ( this ) , gecos ) ) ;
2009-09-02 00:49:36 +00:00
if ( MOD_RESULT = = MOD_RES_DENY )
2007-07-16 17:30:04 +00:00
return false ;
FOREACH_MOD ( I_OnChangeName , OnChangeName ( this , gecos ) ) ;
}
2008-05-25 17:30:43 +00:00
this - > fullname . assign ( gecos , 0 , ServerInstance - > Config - > Limits . MaxGecos ) ;
2007-07-16 17:30:04 +00:00
return true ;
}
2009-09-02 00:45:16 +00:00
void User : : DoHostCycle ( const std : : string & quitline )
{
char buffer [ MAXBUF ] ;
2009-10-05 23:27:46 +00:00
if ( ! ServerInstance - > Config - > CycleHosts )
2009-09-02 00:45:16 +00:00
return ;
2009-10-16 17:01:49 +00:00
uniq_id_t silent_id = + + already_sent ;
uniq_id_t seen_id = + + already_sent ;
2009-09-02 00:45:16 +00:00
2009-10-05 23:27:46 +00:00
UserChanList include_c ( chans ) ;
std : : map < User * , bool > exceptions ;
FOREACH_MOD ( I_OnBuildNeighborList , OnBuildNeighborList ( this , include_c , exceptions ) ) ;
for ( std : : map < User * , bool > : : iterator i = exceptions . begin ( ) ; i ! = exceptions . end ( ) ; + + i )
{
2009-10-25 15:21:45 +00:00
LocalUser * u = IS_LOCAL ( i - > first ) ;
if ( u & & ! u - > quitting )
2009-10-05 23:27:46 +00:00
{
if ( i - > second )
2009-10-12 18:13:01 +00:00
{
2009-10-25 15:21:45 +00:00
already_sent [ u - > GetFd ( ) ] = seen_id ;
2009-10-05 23:27:46 +00:00
u - > Write ( quitline ) ;
2009-10-12 18:13:01 +00:00
}
else
{
2009-10-25 15:21:45 +00:00
already_sent [ u - > GetFd ( ) ] = silent_id ;
2009-10-12 18:13:01 +00:00
}
2009-10-05 23:27:46 +00:00
}
}
for ( UCListIter v = include_c . begin ( ) ; v ! = include_c . end ( ) ; + + v )
2009-09-02 00:45:16 +00:00
{
2009-09-13 20:30:47 +00:00
Channel * c = * v ;
2009-09-02 00:45:16 +00:00
snprintf ( buffer , MAXBUF , " :%s JOIN %s " , GetFullHost ( ) . c_str ( ) , c - > name . c_str ( ) ) ;
std : : string joinline ( buffer ) ;
2009-10-24 03:29:58 +00:00
Membership * memb = c - > GetUser ( this ) ;
std : : string modeline = memb - > modes ;
2009-09-02 00:45:16 +00:00
if ( modeline . length ( ) > 0 )
{
2009-10-24 03:29:58 +00:00
for ( unsigned int i = 0 ; i < memb - > modes . length ( ) ; i + + )
modeline . append ( " " ) . append ( nick ) ;
2009-09-02 00:45:16 +00:00
snprintf ( buffer , MAXBUF , " :%s MODE %s +%s " , GetFullHost ( ) . c_str ( ) , c - > name . c_str ( ) , modeline . c_str ( ) ) ;
modeline = buffer ;
}
2009-09-13 20:30:47 +00:00
const UserMembList * ulist = c - > GetUsers ( ) ;
for ( UserMembList : : const_iterator i = ulist - > begin ( ) ; i ! = ulist - > end ( ) ; i + + )
2009-09-02 00:45:16 +00:00
{
2009-10-25 15:21:45 +00:00
LocalUser * u = IS_LOCAL ( i - > first ) ;
if ( u = = NULL | | u = = this )
2009-09-02 00:45:16 +00:00
continue ;
2009-10-25 15:21:45 +00:00
if ( already_sent [ u - > GetFd ( ) ] = = silent_id )
2009-10-12 18:13:01 +00:00
continue ;
2009-09-02 00:45:16 +00:00
2009-10-25 15:21:45 +00:00
if ( already_sent [ u - > GetFd ( ) ] ! = seen_id )
2009-09-02 00:45:16 +00:00
{
u - > Write ( quitline ) ;
2009-10-25 15:21:45 +00:00
already_sent [ u - > GetFd ( ) ] = seen_id ;
2009-09-02 00:45:16 +00:00
}
u - > Write ( joinline ) ;
if ( modeline . length ( ) > 0 )
u - > Write ( modeline ) ;
}
}
}
2008-02-11 09:41:58 +00:00
bool User : : ChangeDisplayedHost ( const char * shost )
2007-07-16 17:30:04 +00:00
{
2008-05-23 05:15:49 +00:00
if ( dhost = = shost )
2007-07-16 17:30:04 +00:00
return true ;
if ( IS_LOCAL ( this ) )
{
2009-09-02 00:49:36 +00:00
ModResult MOD_RESULT ;
2009-10-21 23:45:19 +00:00
FIRST_MOD_RESULT ( OnChangeLocalUserHost , MOD_RESULT , ( IS_LOCAL ( this ) , shost ) ) ;
2009-09-02 00:49:36 +00:00
if ( MOD_RESULT = = MOD_RES_DENY )
2007-07-16 17:30:04 +00:00
return false ;
}
2008-02-09 13:06:02 +00:00
2008-10-25 12:21:14 +00:00
FOREACH_MOD ( I_OnChangeHost , OnChangeHost ( this , shost ) ) ;
2009-09-02 00:45:16 +00:00
std : : string quitstr = " : " + GetFullHost ( ) + " QUIT :Changing host " ;
2007-07-16 17:30:04 +00:00
2007-10-15 20:59:05 +00:00
/* Fix by Om: User::dhost is 65 long, this was truncating some long hosts */
2008-05-18 23:15:53 +00:00
this - > dhost . assign ( shost , 0 , 64 ) ;
2007-07-16 17:30:04 +00:00
this - > InvalidateCache ( ) ;
2009-09-02 00:45:16 +00:00
this - > DoHostCycle ( quitstr ) ;
2007-07-16 17:30:04 +00:00
if ( IS_LOCAL ( this ) )
2008-07-13 19:24:38 +00:00
this - > WriteNumeric ( RPL_YOURDISPLAYEDHOST , " %s %s :is now your displayed host " , this - > nick . c_str ( ) , this - > dhost . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
return true ;
}
2007-10-15 20:59:05 +00:00
bool User : : ChangeIdent ( const char * newident )
2007-07-16 17:30:04 +00:00
{
2008-10-02 22:27:03 +00:00
if ( this - > ident = = newident )
2007-07-16 17:30:04 +00:00
return true ;
2009-09-02 00:52:12 +00:00
FOREACH_MOD ( I_OnChangeIdent , OnChangeIdent ( this , newident ) ) ;
2009-09-02 00:45:16 +00:00
std : : string quitstr = " : " + GetFullHost ( ) + " QUIT :Changing ident " ;
2007-07-16 17:30:04 +00:00
2008-05-25 17:30:43 +00:00
this - > ident . assign ( newident , 0 , ServerInstance - > Config - > Limits . IdentMax + 1 ) ;
2007-07-16 17:30:04 +00:00
this - > InvalidateCache ( ) ;
2009-09-02 00:45:16 +00:00
this - > DoHostCycle ( quitstr ) ;
2007-07-16 17:30:04 +00:00
return true ;
}
2008-02-13 18:22:19 +00:00
void User : : SendAll ( const char * command , const char * text , . . . )
2007-07-16 17:30:04 +00:00
{
char textbuffer [ MAXBUF ] ;
2008-07-02 14:22:48 +00:00
char formatbuffer [ MAXBUF ] ;
2007-07-16 17:30:04 +00:00
va_list argsPtr ;
va_start ( argsPtr , text ) ;
vsnprintf ( textbuffer , MAXBUF , text , argsPtr ) ;
va_end ( argsPtr ) ;
2008-07-02 14:22:48 +00:00
snprintf ( formatbuffer , MAXBUF , " :%s %s $* :%s " , this - > GetFullHost ( ) . c_str ( ) , command , textbuffer ) ;
std : : string fmt = formatbuffer ;
2007-07-16 17:30:04 +00:00
2009-10-21 23:44:48 +00:00
for ( std : : vector < LocalUser * > : : const_iterator i = ServerInstance - > Users - > local_users . begin ( ) ; i ! = ServerInstance - > Users - > local_users . end ( ) ; i + + )
2007-07-16 17:30:04 +00:00
{
2008-07-02 14:22:48 +00:00
( * i ) - > Write ( fmt ) ;
2007-07-16 17:30:04 +00:00
}
}
2009-09-18 17:07:13 +00:00
std : : string User : : ChannelList ( User * source , bool spy )
2007-07-16 17:30:04 +00:00
{
2008-02-09 13:06:02 +00:00
std : : string list ;
for ( UCListIter i = this - > chans . begin ( ) ; i ! = this - > chans . end ( ) ; i + + )
2007-07-16 17:30:04 +00:00
{
2009-09-13 20:30:47 +00:00
Channel * c = * i ;
2009-09-18 17:07:13 +00:00
/* If the target is the sender, neither +p nor +s is set, or
* the channel contains the user , it is not a spy channel
2008-02-09 13:06:02 +00:00
*/
2009-09-18 17:07:13 +00:00
if ( spy ! = ( source = = this | | ! ( c - > IsModeSet ( ' p ' ) | | c - > IsModeSet ( ' s ' ) ) | | c - > HasUser ( source ) ) )
2009-09-13 20:30:47 +00:00
list . append ( c - > GetPrefixChar ( this ) ) . append ( c - > name ) . append ( " " ) ;
2007-07-16 17:30:04 +00:00
}
2008-02-09 13:06:02 +00:00
return list ;
2007-07-16 17:30:04 +00:00
}
2007-10-15 20:59:05 +00:00
void User : : SplitChanList ( User * dest , const std : : string & cl )
2007-07-16 17:30:04 +00:00
{
std : : string line ;
std : : ostringstream prefix ;
std : : string : : size_type start , pos , length ;
2008-02-09 13:06:02 +00:00
prefix < < this - > nick < < " " < < dest - > nick < < " : " ;
line = prefix . str ( ) ;
2009-10-03 01:52:59 +00:00
int namelen = ServerInstance - > Config - > ServerName . length ( ) + 6 ;
2008-02-09 13:06:02 +00:00
for ( start = 0 ; ( pos = cl . find ( ' ' , start ) ) ! = std : : string : : npos ; start = pos + 1 )
2007-07-16 17:30:04 +00:00
{
2008-02-09 13:06:02 +00:00
length = ( pos = = std : : string : : npos ) ? cl . length ( ) : pos ;
2007-07-16 17:30:04 +00:00
2008-02-09 13:06:02 +00:00
if ( line . length ( ) + namelen + length - start > 510 )
2007-07-16 17:30:04 +00:00
{
2008-02-09 13:06:02 +00:00
ServerInstance - > SendWhoisLine ( this , dest , 319 , " %s " , line . c_str ( ) ) ;
line = prefix . str ( ) ;
2007-07-16 17:30:04 +00:00
}
2008-02-09 13:06:02 +00:00
if ( pos = = std : : string : : npos )
2007-07-16 17:30:04 +00:00
{
2008-02-09 13:06:02 +00:00
line . append ( cl . substr ( start , length - start ) ) ;
break ;
}
else
{
line . append ( cl . substr ( start , length - start + 1 ) ) ;
2007-07-16 17:30:04 +00:00
}
}
2008-02-09 13:06:02 +00:00
if ( line . length ( ) )
2007-07-16 17:30:04 +00:00
{
2008-02-09 13:06:02 +00:00
ServerInstance - > SendWhoisLine ( this , dest , 319 , " %s " , line . c_str ( ) ) ;
2007-07-16 17:30:04 +00:00
}
}
2007-10-23 23:25:49 +00:00
/*
* Sets a user ' s connection class .
* If the class name is provided , it will be used . Otherwise , the class will be guessed using host / ip / ident / etc .
2007-07-16 17:30:04 +00:00
* NOTE : If the < ALLOW > or < DENY > tag specifies an ip , and this user resolves ,
* then their ip will be taken as ' priority ' anyway , so for example ,
* < connect allow = " 127.0.0.1 " > will match joe ! bloggs @ localhost
*/
2009-10-21 23:45:32 +00:00
void LocalUser : : SetClass ( const std : : string & explicit_name )
2007-07-16 17:30:04 +00:00
{
2007-10-23 23:31:40 +00:00
ConnectClass * found = NULL ;
2008-05-18 23:15:53 +00:00
ServerInstance - > Logs - > Log ( " CONNECTCLASS " , DEBUG , " Setting connect class for UID %s " , this - > uuid . c_str ( ) ) ;
2008-05-18 17:25:29 +00:00
2007-08-19 19:23:53 +00:00
if ( ! explicit_name . empty ( ) )
2007-07-16 17:30:04 +00:00
{
2007-08-19 19:23:53 +00:00
for ( ClassVector : : iterator i = ServerInstance - > Config - > Classes . begin ( ) ; i ! = ServerInstance - > Config - > Classes . end ( ) ; i + + )
2007-07-16 17:30:04 +00:00
{
2007-10-24 15:48:00 +00:00
ConnectClass * c = * i ;
2009-08-12 18:03:52 +00:00
if ( explicit_name = = c - > name )
2007-10-23 23:07:24 +00:00
{
2008-05-18 17:25:29 +00:00
ServerInstance - > Logs - > Log ( " CONNECTCLASS " , DEBUG , " Explicitly set to %s " , explicit_name . c_str ( ) ) ;
2007-10-24 15:48:00 +00:00
found = c ;
2007-10-23 23:07:24 +00:00
}
2007-08-19 19:23:53 +00:00
}
}
else
{
for ( ClassVector : : iterator i = ServerInstance - > Config - > Classes . begin ( ) ; i ! = ServerInstance - > Config - > Classes . end ( ) ; i + + )
{
2007-10-24 15:48:00 +00:00
ConnectClass * c = * i ;
2009-08-12 18:03:52 +00:00
if ( c - > type = = CC_ALLOW )
2008-05-18 17:41:04 +00:00
{
2009-08-12 18:03:52 +00:00
ServerInstance - > Logs - > Log ( " CONNECTCLASS " , DEBUG , " ALLOW %s %d %s " , c - > host . c_str ( ) , c - > GetPort ( ) , c - > GetName ( ) . c_str ( ) ) ;
2008-05-18 17:41:04 +00:00
}
2010-01-31 03:42:20 +00:00
else if ( c - > type = = CC_DENY )
2008-05-18 17:41:04 +00:00
{
ServerInstance - > Logs - > Log ( " CONNECTCLASS " , DEBUG , " DENY %s %d %s " , c - > GetHost ( ) . c_str ( ) , c - > GetPort ( ) , c - > GetName ( ) . c_str ( ) ) ;
}
2010-01-31 03:42:20 +00:00
else
{
continue ;
}
2008-05-18 17:41:04 +00:00
2008-05-18 17:16:55 +00:00
/* check if host matches.. */
2009-08-01 21:22:50 +00:00
if ( c - > GetHost ( ) . length ( ) & & ! InspIRCd : : MatchCIDR ( this - > GetIPString ( ) , c - > GetHost ( ) , NULL ) & &
2008-08-21 20:56:16 +00:00
! InspIRCd : : MatchCIDR ( this - > host , c - > GetHost ( ) , NULL ) )
2007-07-16 17:30:04 +00:00
{
2008-05-18 17:25:29 +00:00
ServerInstance - > Logs - > Log ( " CONNECTCLASS " , DEBUG , " No host match (for %s) " , c - > GetHost ( ) . c_str ( ) ) ;
2008-05-18 17:16:55 +00:00
continue ;
}
/*
* deny change if change will take class over the limit check it HERE , not after we found a matching class ,
* because we should attempt to find another class if this one doesn ' t match us . - - w00t
*/
2009-09-30 21:55:21 +00:00
if ( c - > limit & & ( c - > GetReferenceCount ( ) > = c - > limit ) )
2008-05-18 17:16:55 +00:00
{
2008-05-18 17:25:29 +00:00
ServerInstance - > Logs - > Log ( " CONNECTCLASS " , DEBUG , " OOPS: Connect class limit (%lu) hit, denying " , c - > limit ) ;
2008-05-18 17:16:55 +00:00
continue ;
}
/* if it requires a port ... */
if ( c - > GetPort ( ) )
{
2008-05-18 17:41:04 +00:00
ServerInstance - > Logs - > Log ( " CONNECTCLASS " , DEBUG , " Requires port (%d) " , c - > GetPort ( ) ) ;
2008-05-18 17:25:29 +00:00
2008-05-18 17:16:55 +00:00
/* and our port doesn't match, fail. */
2009-09-01 15:07:27 +00:00
if ( this - > GetServerPort ( ) ! = c - > GetPort ( ) )
2007-10-23 23:07:24 +00:00
{
2009-09-01 15:07:27 +00:00
ServerInstance - > Logs - > Log ( " CONNECTCLASS " , DEBUG , " Port match failed (%d) " , this - > GetServerPort ( ) ) ;
2008-05-18 17:16:55 +00:00
continue ;
2007-10-23 23:07:24 +00:00
}
2007-07-16 17:30:04 +00:00
}
2008-05-18 17:16:55 +00:00
2008-05-18 18:23:30 +00:00
/* we stop at the first class that meets ALL critera. */
2008-05-18 17:16:55 +00:00
found = c ;
2008-05-18 18:23:30 +00:00
break ;
2007-07-16 17:30:04 +00:00
}
}
2007-10-23 23:07:24 +00:00
2008-05-18 17:16:55 +00:00
/*
* Okay , assuming we found a class that matches . . switch us into that class , keeping refcounts up to date .
*/
2007-10-23 23:31:40 +00:00
if ( found )
{
2009-09-30 21:55:21 +00:00
MyClass = found ;
2007-10-23 23:31:40 +00:00
}
2007-10-23 23:25:49 +00:00
}
/* looks up a users password for their connection class (<ALLOW>/<DENY> tags)
* NOTE : If the < ALLOW > or < DENY > tag specifies an ip , and this user resolves ,
* then their ip will be taken as ' priority ' anyway , so for example ,
* < connect allow = " 127.0.0.1 " > will match joe ! bloggs @ localhost
*/
2009-10-21 23:45:32 +00:00
ConnectClass * LocalUser : : GetClass ( )
{
return MyClass ;
}
2007-10-23 23:25:49 +00:00
ConnectClass * User : : GetClass ( )
{
2009-10-21 23:45:32 +00:00
return NULL ;
2007-07-16 17:30:04 +00:00
}
2007-10-15 20:59:05 +00:00
void User : : PurgeEmptyChannels ( )
2007-07-16 17:30:04 +00:00
{
// firstly decrement the count on each channel
for ( UCListIter f = this - > chans . begin ( ) ; f ! = this - > chans . end ( ) ; f + + )
{
2009-09-13 20:30:47 +00:00
Channel * c = * f ;
2009-10-18 02:57:46 +00:00
c - > DelUser ( this ) ;
2007-07-16 17:30:04 +00:00
}
this - > UnOper ( ) ;
}
2009-10-23 22:47:39 +00:00
const std : : string & FakeUser : : GetFullHost ( )
2009-05-13 17:43:35 +00:00
{
2009-10-05 14:06:03 +00:00
if ( ! ServerInstance - > Config - > HideWhoisServer . empty ( ) )
2009-05-13 17:43:35 +00:00
return ServerInstance - > Config - > HideWhoisServer ;
2009-10-23 22:47:39 +00:00
return server ;
2009-05-13 17:43:35 +00:00
}
2009-10-23 22:47:39 +00:00
const std : : string & FakeUser : : GetFullRealHost ( )
2009-05-13 17:43:35 +00:00
{
2009-10-03 01:52:59 +00:00
if ( ! ServerInstance - > Config - > HideWhoisServer . empty ( ) )
2009-05-13 17:43:35 +00:00
return ServerInstance - > Config - > HideWhoisServer ;
2009-10-23 22:47:39 +00:00
return server ;
2009-05-13 17:43:35 +00:00
}
2009-10-17 02:40:16 +00:00
ConnectClass : : ConnectClass ( ConfigTag * tag , char t , const std : : string & mask )
2009-11-11 19:52:03 +00:00
: config ( tag ) , type ( t ) , fakelag ( true ) , name ( " unnamed " ) , registration_timeout ( 0 ) , host ( mask ) ,
pingtime ( 0 ) , pass ( " " ) , hash ( " " ) , softsendqmax ( 0 ) , hardsendqmax ( 0 ) , recvqmax ( 0 ) ,
penaltythreshold ( 0 ) , commandrate ( 0 ) , maxlocal ( 0 ) , maxglobal ( 0 ) , maxchans ( 0 ) , port ( 0 ) , limit ( 0 )
2009-08-12 18:03:52 +00:00
{
}
2009-10-17 02:40:16 +00:00
ConnectClass : : ConnectClass ( ConfigTag * tag , char t , const std : : string & mask , const ConnectClass & parent )
2009-11-11 19:52:03 +00:00
: config ( tag ) , type ( t ) , fakelag ( parent . fakelag ) , name ( " unnamed " ) ,
registration_timeout ( parent . registration_timeout ) , host ( mask ) , pingtime ( parent . pingtime ) ,
pass ( parent . pass ) , hash ( parent . hash ) , softsendqmax ( parent . softsendqmax ) ,
hardsendqmax ( parent . hardsendqmax ) , recvqmax ( parent . recvqmax ) ,
penaltythreshold ( parent . penaltythreshold ) , commandrate ( parent . commandrate ) ,
maxlocal ( parent . maxlocal ) , maxglobal ( parent . maxglobal ) , maxchans ( parent . maxchans ) ,
2009-09-30 21:55:21 +00:00
port ( parent . port ) , limit ( parent . limit )
2009-08-12 18:03:52 +00:00
{
}
void ConnectClass : : Update ( const ConnectClass * src )
{
name = src - > name ;
registration_timeout = src - > registration_timeout ;
host = src - > host ;
pingtime = src - > pingtime ;
pass = src - > pass ;
hash = src - > hash ;
2009-09-26 16:41:07 +00:00
softsendqmax = src - > softsendqmax ;
hardsendqmax = src - > hardsendqmax ;
2009-08-12 18:03:52 +00:00
recvqmax = src - > recvqmax ;
2009-10-19 18:32:11 +00:00
penaltythreshold = src - > penaltythreshold ;
2009-08-12 18:03:52 +00:00
maxlocal = src - > maxlocal ;
maxglobal = src - > maxglobal ;
limit = src - > limit ;
}