2002-07-14 14:32:45 +00:00
< ? php
2007-06-09 11:11:20 +00:00
/**
2005-04-09 12:26:45 +00:00
*
* @ package phpBB3
2007-06-09 11:11:20 +00:00
* @ copyright ( c ) 2005 phpBB Group
2011-12-31 13:32:52 +00:00
* @ license http :// opensource . org / licenses / gpl - 2.0 . php GNU General Public License v2
2005-04-09 12:26:45 +00:00
*
*/
2013-09-10 14:01:09 +02:00
namespace phpbb ;
2005-04-09 12:26:45 +00:00
/**
* Session class
2006-06-13 21:06:29 +00:00
* @ package phpBB3
2005-04-09 12:26:45 +00:00
*/
2013-09-10 14:01:09 +02:00
class session
2002-10-20 19:19:07 +00:00
{
2005-07-04 16:54:34 +00:00
var $cookie_data = array ();
2006-06-11 18:13:52 +00:00
var $page = array ();
var $data = array ();
2002-10-04 13:09:10 +00:00
var $browser = '' ;
2006-12-10 17:44:45 +00:00
var $forwarded_for = '' ;
2006-04-29 13:14:33 +00:00
var $host = '' ;
2006-06-11 18:13:52 +00:00
var $session_id = '' ;
2002-10-21 14:10:45 +00:00
var $ip = '' ;
2006-06-11 18:13:52 +00:00
var $load = 0 ;
2005-07-04 16:54:34 +00:00
var $time_now = 0 ;
2006-06-11 18:13:52 +00:00
var $update_session_page = true ;
2005-07-04 16:54:34 +00:00
2006-03-01 21:48:02 +00:00
/**
* Extract current session page
2006-06-11 18:13:52 +00:00
*
* @ param string $root_path current root path ( phpbb_root_path )
2006-03-01 21:48:02 +00:00
*/
2010-03-06 04:41:49 +01:00
static function extract_current_page ( $root_path )
2006-03-01 21:48:02 +00:00
{
2013-09-17 11:41:46 -05:00
global $request , $symfony_request , $phpbb_filesystem ;
2011-07-13 19:20:16 +02:00
2006-03-01 21:48:02 +00:00
$page_array = array ();
// First of all, get the request uri...
2013-09-17 11:41:46 -05:00
$script_name = $symfony_request -> getScriptName ();
$args = explode ( '&' , $symfony_request -> getQueryString ());
2006-03-01 21:48:02 +00:00
// If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support...
if ( ! $script_name )
{
2011-08-18 23:38:39 +02:00
$script_name = htmlspecialchars_decode ( $request -> server ( 'REQUEST_URI' ));
2007-07-20 17:55:35 +00:00
$script_name = (( $pos = strpos ( $script_name , '?' )) !== false ) ? substr ( $script_name , 0 , $pos ) : $script_name ;
2006-06-11 18:13:52 +00:00
$page_array [ 'failover' ] = 1 ;
2006-03-01 21:48:02 +00:00
}
// Replace backslashes and doubled slashes (could happen on some proxy setups)
$script_name = str_replace ( array ( '\\' , '//' ), '/' , $script_name );
// Now, remove the sid and let us get a clean query string...
2007-09-22 18:21:58 +00:00
$use_args = array ();
// Since some browser do not encode correctly we need to do this with some "special" characters...
// " -> %22, ' => %27, < -> %3C, > -> %3E
$find = array ( '"' , " ' " , '<' , '>' );
$replace = array ( '%22' , '%27' , '%3C' , '%3E' );
2006-03-01 21:48:02 +00:00
foreach ( $args as $key => $argument )
{
2008-05-04 14:44:48 +00:00
if ( strpos ( $argument , 'sid=' ) === 0 )
2006-03-01 21:48:02 +00:00
{
2007-09-22 18:21:58 +00:00
continue ;
2006-03-01 21:48:02 +00:00
}
2007-09-22 18:21:58 +00:00
2008-09-05 12:46:58 +00:00
$use_args [] = str_replace ( $find , $replace , $argument );
2006-03-01 21:48:02 +00:00
}
2007-09-22 18:21:58 +00:00
unset ( $args );
2006-03-01 21:48:02 +00:00
2006-06-01 13:47:42 +00:00
// The following examples given are for an request uri of {path to the phpbb directory}/adm/index.php?i=10&b=2
2006-03-01 21:48:02 +00:00
// The current query string
2007-09-22 18:21:58 +00:00
$query_string = trim ( implode ( '&' , $use_args ));
2006-03-01 21:48:02 +00:00
// basenamed page name (for example: index.php)
2010-03-07 10:00:15 -07:00
$page_name = ( substr ( $script_name , - 1 , 1 ) == '/' ) ? '' : basename ( $script_name );
2006-10-12 15:20:33 +00:00
$page_name = urlencode ( htmlspecialchars ( $page_name ));
2006-03-01 21:48:02 +00:00
2013-09-17 22:00:06 -05:00
$symfony_request_path = $phpbb_filesystem -> clean_path ( $symfony_request -> getPathInfo ());
if ( $symfony_request_path !== '/' )
{
$page_name .= $symfony_request_path ;
}
2006-03-01 21:48:02 +00:00
// current directory within the phpBB root (for example: adm)
2006-06-24 13:27:04 +00:00
$root_dirs = explode ( '/' , str_replace ( '\\' , '/' , phpbb_realpath ( $root_path )));
$page_dirs = explode ( '/' , str_replace ( '\\' , '/' , phpbb_realpath ( './' )));
2006-06-01 13:47:42 +00:00
$intersection = array_intersect_assoc ( $root_dirs , $page_dirs );
$root_dirs = array_diff_assoc ( $root_dirs , $intersection );
$page_dirs = array_diff_assoc ( $page_dirs , $intersection );
$page_dir = str_repeat ( '../' , sizeof ( $root_dirs )) . implode ( '/' , $page_dirs );
2006-06-06 20:53:46 +00:00
if ( $page_dir && substr ( $page_dir , - 1 , 1 ) == '/' )
2006-06-01 13:47:42 +00:00
{
$page_dir = substr ( $page_dir , 0 , - 1 );
}
2006-03-01 21:48:02 +00:00
2006-06-01 13:47:42 +00:00
// Current page from phpBB root (for example: adm/index.php?i=10&b=2)
2013-09-17 11:41:46 -05:00
$page = (( $page_dir ) ? $page_dir . '/' : '' ) . $page_name ;
if ( $query_string )
{
$page .= '?' . $query_string ;
}
2006-03-01 21:48:02 +00:00
2007-05-04 12:30:21 +00:00
// The script path from the webroot to the current directory (for example: /phpBB3/adm/) : always prefixed with / and ends in /
2013-09-17 11:41:46 -05:00
$script_path = $symfony_request -> getBasePath ();
2006-03-01 21:48:02 +00:00
2007-05-04 12:30:21 +00:00
// The script path from the webroot to the phpBB root (for example: /phpBB3/)
2006-06-01 13:47:42 +00:00
$script_dirs = explode ( '/' , $script_path );
array_splice ( $script_dirs , - sizeof ( $page_dirs ));
2007-01-26 16:09:51 +00:00
$root_script_path = implode ( '/' , $script_dirs ) . ( sizeof ( $root_dirs ) ? '/' . implode ( '/' , $root_dirs ) : '' );
2006-03-01 21:48:02 +00:00
// We are on the base level (phpBB root == webroot), lets adjust the variables a bit...
if ( ! $root_script_path )
{
2006-05-28 15:42:06 +00:00
$root_script_path = ( $page_dir ) ? str_replace ( $page_dir , '' , $script_path ) : $script_path ;
2006-03-01 21:48:02 +00:00
}
2006-06-06 20:53:46 +00:00
$script_path .= ( substr ( $script_path , - 1 , 1 ) == '/' ) ? '' : '/' ;
$root_script_path .= ( substr ( $root_script_path , - 1 , 1 ) == '/' ) ? '' : '/' ;
2006-03-01 21:48:02 +00:00
$page_array += array (
2006-06-22 15:14:03 +00:00
'page_name' => $page_name ,
'page_dir' => $page_dir ,
2006-03-01 21:48:02 +00:00
'query_string' => $query_string ,
2006-06-22 15:14:03 +00:00
'script_path' => str_replace ( ' ' , '%20' , htmlspecialchars ( $script_path )),
'root_script_path' => str_replace ( ' ' , '%20' , htmlspecialchars ( $root_script_path )),
2006-03-01 21:48:02 +00:00
2008-03-17 16:25:07 +00:00
'page' => $page ,
2010-03-11 16:08:19 +01:00
'forum' => request_var ( 'f' , 0 ),
2006-03-01 21:48:02 +00:00
);
return $page_array ;
}
2008-09-15 18:41:27 +00:00
/**
* Get valid hostname / port . HTTP_HOST is used , SERVER_NAME if HTTP_HOST not present .
*/
function extract_current_hostname ()
{
2011-07-13 19:20:16 +02:00
global $config , $request ;
2008-09-15 18:41:27 +00:00
// Get hostname
2011-08-18 23:38:39 +02:00
$host = htmlspecialchars_decode ( $request -> header ( 'Host' , $request -> server ( 'SERVER_NAME' )));
2008-09-15 18:41:27 +00:00
// Should be a string and lowered
$host = ( string ) strtolower ( $host );
// If host is equal the cookie domain or the server name (if config is set), then we assume it is valid
if (( isset ( $config [ 'cookie_domain' ]) && $host === $config [ 'cookie_domain' ]) || ( isset ( $config [ 'server_name' ]) && $host === $config [ 'server_name' ]))
{
return $host ;
}
// Is the host actually a IP? If so, we use the IP... (IPv4)
if ( long2ip ( ip2long ( $host )) === $host )
{
return $host ;
}
// Now return the hostname (this also removes any port definition). The http:// is prepended to construct a valid URL, hosts never have a scheme assigned
$host = @ parse_url ( 'http://' . $host );
$host = ( ! empty ( $host [ 'host' ])) ? $host [ 'host' ] : '' ;
// Remove any portions not removed by parse_url (#)
$host = str_replace ( '#' , '' , $host );
// If, by any means, the host is now empty, we will use a "best approach" way to guess one
if ( empty ( $host ))
{
if ( ! empty ( $config [ 'server_name' ]))
{
$host = $config [ 'server_name' ];
}
else if ( ! empty ( $config [ 'cookie_domain' ]))
{
2008-09-16 11:41:00 +00:00
$host = ( strpos ( $config [ 'cookie_domain' ], '.' ) === 0 ) ? substr ( $config [ 'cookie_domain' ], 1 ) : $config [ 'cookie_domain' ];
2008-09-15 18:41:27 +00:00
}
else
{
// Set to OS hostname or localhost
2009-09-22 15:09:09 +00:00
$host = ( function_exists ( 'php_uname' )) ? php_uname ( 'n' ) : 'localhost' ;
2008-09-15 18:41:27 +00:00
}
}
// It may be still no valid host, but for sure only a hostname (we may further expand on the cookie domain... if set)
return $host ;
}
2005-07-04 16:54:34 +00:00
/**
* Start session management
*
* This is where all session activity begins . We gather various pieces of
* information from the client and server . We test to see if a session already
2007-07-15 20:53:27 +00:00
* exists . If it does , fine and dandy . If it doesn 't we' ll go on to create a
2005-07-04 16:54:34 +00:00
* new one ... pretty logical heh ? We also examine the system load ( if we ' re
* running on a system which makes such information readily available ) and
* halt if it ' s above an admin definable limit .
*
2006-06-11 18:13:52 +00:00
* @ param bool $update_session_page if true the session page gets updated .
* This can be set to circumvent certain scripts to update the users last visited page .
2005-07-04 16:54:34 +00:00
*/
2006-08-12 13:14:39 +00:00
function session_begin ( $update_session_page = true )
2002-07-14 14:32:45 +00:00
{
2007-07-10 15:14:25 +00:00
global $phpEx , $SID , $_SID , $_EXTRA_URL , $db , $config , $phpbb_root_path ;
2013-06-21 18:04:11 -04:00
global $request , $phpbb_container ;
2002-07-14 14:32:45 +00:00
2006-11-24 14:59:26 +00:00
// Give us some basic information
2006-06-11 18:13:52 +00:00
$this -> time_now = time ();
$this -> cookie_data = array ( 'u' => 0 , 'k' => '' );
$this -> update_session_page = $update_session_page ;
2011-08-18 23:38:39 +02:00
$this -> browser = $request -> header ( 'User-Agent' );
$this -> referer = $request -> header ( 'Referer' );
$this -> forwarded_for = $request -> header ( 'X-Forwarded-For' );
2008-06-09 17:05:52 +00:00
2008-09-15 18:41:27 +00:00
$this -> host = $this -> extract_current_hostname ();
2006-06-11 18:13:52 +00:00
$this -> page = $this -> extract_current_page ( $phpbb_root_path );
2006-01-25 21:01:52 +00:00
2006-12-10 17:44:45 +00:00
// if the forwarded for header shall be checked we have to validate its contents
if ( $config [ 'forwarded_for_check' ])
{
2011-03-17 01:29:10 +01:00
$this -> forwarded_for = preg_replace ( '# {2,}#' , ' ' , str_replace ( ',' , ' ' , $this -> forwarded_for ));
2006-12-10 17:44:45 +00:00
// split the list of IPs
2009-08-20 08:37:06 +00:00
$ips = explode ( ' ' , $this -> forwarded_for );
2006-12-10 17:44:45 +00:00
foreach ( $ips as $ip )
{
// check IPv4 first, the IPv6 is hopefully only going to be used very seldomly
2007-09-21 15:00:40 +00:00
if ( ! empty ( $ip ) && ! preg_match ( get_preg_expression ( 'ipv4' ), $ip ) && ! preg_match ( get_preg_expression ( 'ipv6' ), $ip ))
2006-12-10 17:44:45 +00:00
{
2007-02-25 22:09:53 +00:00
// contains invalid data, don't use the forwarded for header
$this -> forwarded_for = '' ;
break ;
2006-12-10 17:44:45 +00:00
}
}
}
2008-02-04 12:10:25 +00:00
else
{
$this -> forwarded_for = '' ;
}
2006-12-10 17:44:45 +00:00
2013-09-10 14:01:09 +02:00
if ( $request -> is_set ( $config [ 'cookie_name' ] . '_sid' , \phpbb\request\request_interface :: COOKIE ) || $request -> is_set ( $config [ 'cookie_name' ] . '_u' , \phpbb\request\request_interface :: COOKIE ))
2002-07-14 14:32:45 +00:00
{
2006-10-01 11:10:15 +00:00
$this -> cookie_data [ 'u' ] = request_var ( $config [ 'cookie_name' ] . '_u' , 0 , false , true );
$this -> cookie_data [ 'k' ] = request_var ( $config [ 'cookie_name' ] . '_k' , '' , false , true );
$this -> session_id = request_var ( $config [ 'cookie_name' ] . '_sid' , '' , false , true );
2006-06-06 20:53:46 +00:00
2003-01-20 05:12:38 +00:00
$SID = ( defined ( 'NEED_SID' )) ? '?sid=' . $this -> session_id : '?sid=' ;
2006-06-06 20:53:46 +00:00
$_SID = ( defined ( 'NEED_SID' )) ? $this -> session_id : '' ;
2006-08-07 10:42:22 +00:00
if ( empty ( $this -> session_id ))
{
$this -> session_id = $_SID = request_var ( 'sid' , '' );
$SID = '?sid=' . $this -> session_id ;
$this -> cookie_data = array ( 'u' => 0 , 'k' => '' );
}
2002-07-14 14:32:45 +00:00
}
else
{
2006-06-06 20:53:46 +00:00
$this -> session_id = $_SID = request_var ( 'sid' , '' );
2002-08-06 16:56:14 +00:00
$SID = '?sid=' . $this -> session_id ;
2002-07-14 14:32:45 +00:00
}
2006-06-11 18:13:52 +00:00
2007-07-10 15:14:25 +00:00
$_EXTRA_URL = array ();
2005-07-05 14:43:58 +00:00
// Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests
// it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip.
2011-08-18 23:38:39 +02:00
$this -> ip = htmlspecialchars_decode ( $request -> server ( 'REMOTE_ADDR' ));
2011-03-17 01:29:10 +01:00
$this -> ip = preg_replace ( '# {2,}#' , ' ' , str_replace ( ',' , ' ' , $this -> ip ));
2009-08-20 08:43:10 +00:00
// split the list of IPs
2011-04-19 13:46:00 +02:00
$ips = explode ( ' ' , trim ( $this -> ip ));
2009-08-20 08:43:10 +00:00
// Default IP if REMOTE_ADDR is invalid
$this -> ip = '127.0.0.1' ;
foreach ( $ips as $ip )
{
2010-07-22 00:59:12 +02:00
if ( function_exists ( 'phpbb_ip_normalise' ))
{
// Normalise IP address
$ip = phpbb_ip_normalise ( $ip );
if ( empty ( $ip ))
{
// IP address is invalid.
break ;
}
// IP address is valid.
$this -> ip = $ip ;
// Skip legacy code.
continue ;
}
2011-04-19 13:53:09 +02:00
if ( preg_match ( get_preg_expression ( 'ipv4' ), $ip ))
2009-08-20 08:43:10 +00:00
{
2011-04-19 13:53:09 +02:00
$this -> ip = $ip ;
2009-08-20 08:43:10 +00:00
}
2011-04-19 13:53:09 +02:00
else if ( preg_match ( get_preg_expression ( 'ipv6' ), $ip ))
2010-07-23 12:48:01 +02:00
{
2011-04-19 13:53:09 +02:00
// Quick check for IPv4-mapped address in IPv6
if ( stripos ( $ip , '::ffff:' ) === 0 )
2010-07-23 12:48:01 +02:00
{
2011-04-19 13:53:09 +02:00
$ipv4 = substr ( $ip , 7 );
if ( preg_match ( get_preg_expression ( 'ipv4' ), $ipv4 ))
{
$ip = $ipv4 ;
}
2010-07-23 12:48:01 +02:00
}
2011-04-19 13:53:09 +02:00
$this -> ip = $ip ;
}
else
{
// We want to use the last valid address in the chain
// Leave foreach loop when address is invalid
break ;
}
2009-08-20 08:43:10 +00:00
}
2006-05-12 20:52:58 +00:00
$this -> load = false ;
2002-07-14 14:32:45 +00:00
// Load limit check (if applicable)
2007-05-02 16:19:35 +00:00
if ( $config [ 'limit_load' ] || $config [ 'limit_search_load' ])
2002-07-14 14:32:45 +00:00
{
2008-04-20 05:13:34 +00:00
if (( function_exists ( 'sys_getloadavg' ) && $load = sys_getloadavg ()) || ( $load = explode ( ' ' , @ file_get_contents ( '/proc/loadavg' ))))
2002-07-14 14:32:45 +00:00
{
2008-04-20 05:13:34 +00:00
$this -> load = array_slice ( $load , 0 , 1 );
2006-08-02 15:53:19 +00:00
$this -> load = floatval ( $this -> load [ 0 ]);
2002-07-14 14:32:45 +00:00
}
2006-04-29 01:18:57 +00:00
else
{
set_config ( 'limit_load' , '0' );
2007-05-02 16:19:35 +00:00
set_config ( 'limit_search_load' , '0' );
2006-04-29 01:18:57 +00:00
}
2002-07-14 14:32:45 +00:00
}
2006-04-21 22:41:05 +00:00
2012-05-29 14:54:04 +02:00
// if no session id is set, redirect to index.php
2012-05-29 20:36:52 -04:00
$session_id = $request -> variable ( 'sid' , '' );
if ( defined ( 'NEED_SID' ) && ( empty ( $session_id ) || $this -> session_id !== $session_id ))
2012-05-29 14:54:04 +02:00
{
2013-02-11 15:29:12 +05:30
send_status_line ( 401 , 'Unauthorized' );
2012-05-29 14:54:04 +02:00
redirect ( append_sid ( " { $phpbb_root_path } index. $phpEx " ));
}
// if session id is set
if ( ! empty ( $this -> session_id ))
2002-07-14 14:32:45 +00:00
{
2005-01-15 18:50:22 +00:00
$sql = ' SELECT u .* , s .*
FROM ' . SESSIONS_TABLE . ' s , ' . USERS_TABLE . " u
2003-08-24 18:16:53 +00:00
WHERE s . session_id = '" . $db->sql_escape($this->session_id) . "'
2005-01-15 18:50:22 +00:00
AND u . user_id = s . session_user_id " ;
2002-07-14 14:32:45 +00:00
$result = $db -> sql_query ( $sql );
2002-10-20 19:19:07 +00:00
$this -> data = $db -> sql_fetchrow ( $result );
2002-08-06 16:56:14 +00:00
$db -> sql_freeresult ( $result );
2002-07-14 14:32:45 +00:00
// Did the session exist in the DB?
2002-11-01 12:23:08 +00:00
if ( isset ( $this -> data [ 'user_id' ]))
2002-07-14 14:32:45 +00:00
{
2005-07-04 16:54:34 +00:00
// Validate IP length according to admin ... enforces an IP
// check on bots if admin requires this
2005-10-02 16:57:33 +00:00
// $quadcheck = ($config['ip_check_bot'] && $this->data['user_type'] & USER_BOT) ? 4 : $config['ip_check'];
2007-05-13 16:15:20 +00:00
if ( strpos ( $this -> ip , ':' ) !== false && strpos ( $this -> data [ 'session_ip' ], ':' ) !== false )
{
$s_ip = short_ipv6 ( $this -> data [ 'session_ip' ], $config [ 'ip_check' ]);
$u_ip = short_ipv6 ( $this -> ip , $config [ 'ip_check' ]);
}
else
{
$s_ip = implode ( '.' , array_slice ( explode ( '.' , $this -> data [ 'session_ip' ]), 0 , $config [ 'ip_check' ]));
$u_ip = implode ( '.' , array_slice ( explode ( '.' , $this -> ip ), 0 , $config [ 'ip_check' ]));
}
2002-10-04 13:09:10 +00:00
2008-01-29 14:23:02 +00:00
$s_browser = ( $config [ 'browser_check' ]) ? trim ( strtolower ( substr ( $this -> data [ 'session_browser' ], 0 , 149 ))) : '' ;
$u_browser = ( $config [ 'browser_check' ]) ? trim ( strtolower ( substr ( $this -> browser , 0 , 149 ))) : '' ;
2003-03-24 19:03:32 +00:00
2006-12-10 20:13:46 +00:00
$s_forwarded_for = ( $config [ 'forwarded_for_check' ]) ? substr ( $this -> data [ 'session_forwarded_for' ], 0 , 254 ) : '' ;
2006-12-10 17:44:45 +00:00
$u_forwarded_for = ( $config [ 'forwarded_for_check' ]) ? substr ( $this -> forwarded_for , 0 , 254 ) : '' ;
2008-05-18 20:06:15 +00:00
2008-05-15 13:29:14 +00:00
// referer checks
2008-05-18 20:06:15 +00:00
// The @ before $config['referer_validation'] suppresses notices present while running the updater
$check_referer_path = ( @ $config [ 'referer_validation' ] == REFERER_VALIDATE_PATH );
2008-05-15 13:29:14 +00:00
$referer_valid = true ;
2008-05-18 20:06:15 +00:00
2008-05-16 12:34:39 +00:00
// we assume HEAD and TRACE to be foul play and thus only whitelist GET
2011-07-16 15:09:33 +02:00
if ( @ $config [ 'referer_validation' ] && strtolower ( $request -> server ( 'REQUEST_METHOD' )) !== 'get' )
2008-05-15 13:29:14 +00:00
{
$referer_valid = $this -> validate_referer ( $check_referer_path );
}
2006-12-10 17:44:45 +00:00
2008-05-15 13:29:14 +00:00
if ( $u_ip === $s_ip && $s_browser === $u_browser && $s_forwarded_for === $u_forwarded_for && $referer_valid )
2002-07-14 14:32:45 +00:00
{
2006-04-06 17:15:45 +00:00
$session_expired = false ;
2006-04-21 22:41:05 +00:00
// Check whether the session is still valid if we have one
2006-06-11 18:13:52 +00:00
$method = basename ( trim ( $config [ 'auth_method' ]));
2006-04-21 22:41:05 +00:00
2013-06-21 18:04:11 -04:00
$provider = $phpbb_container -> get ( 'auth.provider.' . $method );
2013-07-11 14:54:00 -04:00
2013-09-10 14:01:09 +02:00
if ( ! ( $provider instanceof \phpbb\auth\provider\provider_interface ))
2013-07-11 14:54:00 -04:00
{
2013-09-10 14:01:09 +02:00
throw new \RuntimeException ( $provider . ' must implement \phpbb\auth\provider\provider_interface' );
2013-07-11 14:54:00 -04:00
}
2013-06-21 18:04:11 -04:00
$ret = $provider -> validate_session ( $this -> data );
if ( $ret !== null && ! $ret )
2002-07-14 14:32:45 +00:00
{
2013-06-21 18:04:11 -04:00
$session_expired = true ;
2006-04-06 17:15:45 +00:00
}
2006-04-21 22:41:05 +00:00
if ( ! $session_expired )
2006-04-06 17:15:45 +00:00
{
2006-04-21 22:41:05 +00:00
// Check the session length timeframe if autologin is not enabled.
// Else check the autologin length... and also removing those having autologin enabled but no longer allowed board-wide.
if ( ! $this -> data [ 'session_autologin' ])
{
if ( $this -> data [ 'session_time' ] < $this -> time_now - ( $config [ 'session_length' ] + 60 ))
{
$session_expired = true ;
}
}
else if ( ! $config [ 'allow_autologin' ] || ( $config [ 'max_autologin_time' ] && $this -> data [ 'session_time' ] < $this -> time_now - ( 86400 * ( int ) $config [ 'max_autologin_time' ]) + 60 ))
{
$session_expired = true ;
}
2006-04-06 17:15:45 +00:00
}
if ( ! $session_expired )
{
// Only update session DB a minute or so after last update or if page changes
2006-06-11 18:13:52 +00:00
if ( $this -> time_now - $this -> data [ 'session_time' ] > 60 || ( $this -> update_session_page && $this -> data [ 'session_page' ] != $this -> page [ 'page' ]))
2006-04-06 17:15:45 +00:00
{
2006-06-11 18:13:52 +00:00
$sql_ary = array ( 'session_time' => $this -> time_now );
if ( $this -> update_session_page )
{
$sql_ary [ 'session_page' ] = substr ( $this -> page [ 'page' ], 0 , 199 );
2008-03-17 16:25:07 +00:00
$sql_ary [ 'session_forum_id' ] = $this -> page [ 'forum' ];
2006-06-11 18:13:52 +00:00
}
2008-03-27 16:17:54 +00:00
$db -> sql_return_on_error ( true );
2010-06-28 17:16:44 +02:00
$this -> update_session ( $sql_ary );
2008-03-27 16:17:54 +00:00
$db -> sql_return_on_error ( false );
// If the database is not yet updated, there will be an error due to the session_forum_id
// @todo REMOVE for 3.0.2
if ( $result === false )
{
unset ( $sql_ary [ 'session_forum_id' ]);
2010-06-28 17:16:44 +02:00
$this -> update_session ( $sql_ary );
2008-03-27 16:17:54 +00:00
}
2009-06-20 18:45:16 +00:00
if ( $this -> data [ 'user_id' ] != ANONYMOUS && ! empty ( $config [ 'new_member_post_limit' ]) && $this -> data [ 'user_new' ] && $config [ 'new_member_post_limit' ] <= $this -> data [ 'user_posts' ])
{
$this -> leave_newly_registered ();
}
2006-04-06 17:15:45 +00:00
}
$this -> data [ 'is_registered' ] = ( $this -> data [ 'user_id' ] != ANONYMOUS && ( $this -> data [ 'user_type' ] == USER_NORMAL || $this -> data [ 'user_type' ] == USER_FOUNDER )) ? true : false ;
$this -> data [ 'is_bot' ] = ( ! $this -> data [ 'is_registered' ] && $this -> data [ 'user_id' ] != ANONYMOUS ) ? true : false ;
2007-07-13 11:58:12 +00:00
$this -> data [ 'user_lang' ] = basename ( $this -> data [ 'user_lang' ]);
2007-07-15 20:53:27 +00:00
2006-04-06 17:15:45 +00:00
return true ;
2002-07-14 14:32:45 +00:00
}
2006-04-06 17:15:45 +00:00
}
else
{
// Added logging temporarly to help debug bugs...
2012-11-10 10:45:02 -06:00
if ( defined ( 'DEBUG' ) && $this -> data [ 'user_id' ] != ANONYMOUS )
2006-10-03 18:35:59 +00:00
{
2008-05-15 13:29:14 +00:00
if ( $referer_valid )
{
add_log ( 'critical' , 'LOG_IP_BROWSER_FORWARDED_CHECK' , $u_ip , $s_ip , $u_browser , $s_browser , htmlspecialchars ( $u_forwarded_for ), htmlspecialchars ( $s_forwarded_for ));
}
else
{
add_log ( 'critical' , 'LOG_REFERER_INVALID' , $this -> referer );
}
2006-10-03 18:35:59 +00:00
}
2002-07-14 14:32:45 +00:00
}
}
}
2005-07-04 16:54:34 +00:00
// If we reach here then no (valid) session exists. So we'll create a new one
return $this -> session_create ();
2002-07-14 14:32:45 +00:00
}
2007-07-15 20:53:27 +00:00
2005-07-04 16:54:34 +00:00
/**
* Create a new session
*
* If upon trying to start a session we discover there is nothing existing we
* jump here . Additionally this method is called directly during login to regenerate
* the session for the specific user . In this method we carry out a number of tasks ;
* garbage collection , ( search ) bot checking , banned user comparison . Basically
* though this method will result in a new session for a specific user .
*/
function session_create ( $user_id = false , $set_admin = false , $persist_login = false , $viewonline = true )
2002-07-14 14:32:45 +00:00
{
2013-06-21 18:04:11 -04:00
global $SID , $_SID , $db , $config , $cache , $phpbb_root_path , $phpEx , $phpbb_container ;
2002-07-14 14:32:45 +00:00
2005-07-04 16:54:34 +00:00
$this -> data = array ();
2006-06-11 18:13:52 +00:00
2006-05-18 18:18:32 +00:00
/* Garbage collection ... remove old sessions updating user information
2005-07-04 16:54:34 +00:00
// if necessary. It means (potentially) 11 queries but only infrequently
if ( $this -> time_now > $config [ 'session_last_gc' ] + $config [ 'session_gc' ])
{
$this -> session_gc ();
2006-05-18 18:18:32 +00:00
} */
2006-06-11 18:13:52 +00:00
2005-07-04 16:54:34 +00:00
// Do we allow autologin on this board? No? Then override anything
// that may be requested here
if ( ! $config [ 'allow_autologin' ])
{
$this -> cookie_data [ 'k' ] = $persist_login = false ;
}
2002-07-14 14:32:45 +00:00
2005-07-04 16:54:34 +00:00
/**
* Here we do a bot check , oh er saucy ! No , not that kind of bot
* check . We loop through the list of bots defined by the admin and
* see if we have any useragent and / or IP matches . If we do , this is a
* bot , act accordingly
2007-07-15 20:53:27 +00:00
*/
2005-07-04 16:54:34 +00:00
$bot = false ;
2006-11-12 15:35:43 +00:00
$active_bots = $cache -> obtain_bots ();
2005-10-02 16:57:33 +00:00
2005-05-05 16:55:05 +00:00
foreach ( $active_bots as $row )
2003-10-15 17:43:07 +00:00
{
2007-10-04 12:03:05 +00:00
if ( $row [ 'bot_agent' ] && preg_match ( '#' . str_replace ( '\*' , '.*?' , preg_quote ( $row [ 'bot_agent' ], '#' )) . '#i' , $this -> browser ))
2003-10-15 17:43:07 +00:00
{
$bot = $row [ 'user_id' ];
}
2006-06-11 18:13:52 +00:00
2006-03-25 12:35:23 +00:00
// If ip is supplied, we will make sure the ip is matching too...
if ( $row [ 'bot_ip' ] && ( $bot || ! $row [ 'bot_agent' ]))
2003-10-15 17:43:07 +00:00
{
2006-03-25 12:35:23 +00:00
// Set bot to false, then we only have to set it to true if it is matching
$bot = false ;
2003-10-15 17:43:07 +00:00
foreach ( explode ( ',' , $row [ 'bot_ip' ]) as $bot_ip )
{
2009-03-16 16:34:16 +00:00
$bot_ip = trim ( $bot_ip );
if ( ! $bot_ip )
{
continue ;
}
2003-10-15 17:43:07 +00:00
if ( strpos ( $this -> ip , $bot_ip ) === 0 )
{
2005-07-04 16:54:34 +00:00
$bot = ( int ) $row [ 'user_id' ];
2003-10-15 17:43:07 +00:00
break ;
}
}
}
2002-07-14 14:32:45 +00:00
2003-10-15 17:43:07 +00:00
if ( $bot )
2002-10-17 02:50:50 +00:00
{
2003-10-15 17:43:07 +00:00
break ;
2002-10-17 02:50:50 +00:00
}
2002-07-14 14:32:45 +00:00
}
2006-04-21 22:41:05 +00:00
2006-06-11 18:13:52 +00:00
$method = basename ( trim ( $config [ 'auth_method' ]));
2006-04-21 22:41:05 +00:00
2013-06-21 18:04:11 -04:00
$provider = $phpbb_container -> get ( 'auth.provider.' . $method );
$this -> data = $provider -> autologin ();
2006-04-21 22:41:05 +00:00
2013-06-21 18:04:11 -04:00
if ( sizeof ( $this -> data ))
{
$this -> cookie_data [ 'k' ] = '' ;
$this -> cookie_data [ 'u' ] = $this -> data [ 'user_id' ];
2006-04-21 22:41:05 +00:00
}
2005-07-04 16:54:34 +00:00
// If we're presented with an autologin key we'll join against it.
// Else if we've been passed a user_id we'll grab data based on that
2006-04-21 22:41:05 +00:00
if ( isset ( $this -> cookie_data [ 'k' ]) && $this -> cookie_data [ 'k' ] && $this -> cookie_data [ 'u' ] && ! sizeof ( $this -> data ))
2002-10-04 13:09:10 +00:00
{
2007-07-15 20:53:27 +00:00
$sql = ' SELECT u .*
2005-07-04 16:54:34 +00:00
FROM ' . USERS_TABLE . ' u , ' . SESSIONS_KEYS_TABLE . ' k
2005-07-05 14:43:58 +00:00
WHERE u . user_id = ' . (int) $this->cookie_data[' u '] . '
2006-10-03 18:35:59 +00:00
AND u . user_type IN ( ' . USER_NORMAL . ' , ' . USER_FOUNDER . " )
2005-07-04 16:54:34 +00:00
AND k . user_id = u . user_id
2005-11-03 20:53:47 +00:00
AND k . key_id = '" . $db->sql_escape(md5($this->cookie_data[' k '])) . "' " ;
2005-07-04 16:54:34 +00:00
$result = $db -> sql_query ( $sql );
$this -> data = $db -> sql_fetchrow ( $result );
$db -> sql_freeresult ( $result );
2007-06-20 14:24:02 +00:00
$bot = false ;
2005-07-04 16:54:34 +00:00
}
2006-04-21 22:41:05 +00:00
else if ( $user_id !== false && ! sizeof ( $this -> data ))
2002-07-14 14:32:45 +00:00
{
2005-07-04 16:54:34 +00:00
$this -> cookie_data [ 'k' ] = '' ;
$this -> cookie_data [ 'u' ] = $user_id ;
2005-01-02 19:06:45 +00:00
2005-01-15 18:50:22 +00:00
$sql = ' SELECT *
FROM ' . USERS_TABLE . '
2005-07-05 14:43:58 +00:00
WHERE user_id = ' . (int) $this->cookie_data[' u '] . '
2006-10-03 18:35:59 +00:00
AND user_type IN ( ' . USER_NORMAL . ' , ' . USER_FOUNDER . ' ) ' ;
2005-01-02 19:06:45 +00:00
$result = $db -> sql_query ( $sql );
$this -> data = $db -> sql_fetchrow ( $result );
$db -> sql_freeresult ( $result );
2007-06-20 14:24:02 +00:00
$bot = false ;
2002-07-14 14:32:45 +00:00
}
2007-07-15 20:53:27 +00:00
2011-01-19 03:08:27 +01:00
// Bot user, if they have a SID in the Request URI we need to get rid of it
// otherwise they'll index this page with the SID, duplicate content oh my!
if ( $bot && isset ( $_GET [ 'sid' ]))
{
2011-01-19 03:47:51 +01:00
send_status_line ( 301 , 'Moved Permanently' );
2011-01-19 03:08:27 +01:00
redirect ( build_url ( array ( 'sid' )));
}
2007-01-21 18:33:45 +00:00
// If no data was returned one or more of the following occurred:
2005-07-04 16:54:34 +00:00
// Key didn't match one in the DB
// User does not exist
// User is inactive
// User is bot
2005-07-28 11:50:27 +00:00
if ( ! sizeof ( $this -> data ) || ! is_array ( $this -> data ))
2003-10-15 17:43:07 +00:00
{
2005-07-04 16:54:34 +00:00
$this -> cookie_data [ 'k' ] = '' ;
$this -> cookie_data [ 'u' ] = ( $bot ) ? $bot : ANONYMOUS ;
2003-10-15 17:43:07 +00:00
2006-09-13 16:08:36 +00:00
if ( ! $bot )
{
$sql = ' SELECT *
FROM ' . USERS_TABLE . '
WHERE user_id = ' . (int) $this->cookie_data[' u ' ];
}
else
{
// We give bots always the same session if it is not yet expired.
$sql = ' SELECT u .* , s .*
FROM ' . USERS_TABLE . ' u
LEFT JOIN ' . SESSIONS_TABLE . ' s ON ( s . session_user_id = u . user_id )
WHERE u . user_id = ' . ( int ) $bot ;
}
2003-10-15 17:43:07 +00:00
$result = $db -> sql_query ( $sql );
2005-07-04 16:54:34 +00:00
$this -> data = $db -> sql_fetchrow ( $result );
2003-10-15 17:43:07 +00:00
$db -> sql_freeresult ( $result );
}
2006-07-06 16:46:53 +00:00
if ( $this -> data [ 'user_id' ] != ANONYMOUS && ! $bot )
2006-03-17 12:51:32 +00:00
{
$this -> data [ 'session_last_visit' ] = ( isset ( $this -> data [ 'session_time' ]) && $this -> data [ 'session_time' ]) ? $this -> data [ 'session_time' ] : (( $this -> data [ 'user_lastvisit' ]) ? $this -> data [ 'user_lastvisit' ] : time ());
}
else
{
2006-04-06 17:15:45 +00:00
$this -> data [ 'session_last_visit' ] = $this -> time_now ;
2006-03-17 12:51:32 +00:00
}
2003-04-09 22:41:25 +00:00
2006-10-10 13:59:02 +00:00
// Force user id to be integer...
$this -> data [ 'user_id' ] = ( int ) $this -> data [ 'user_id' ];
2005-07-04 16:54:34 +00:00
// At this stage we should have a filled data array, defined cookie u and k data.
// data array should contain recent session info if we're a real user and a recent
// session exists in which case session_id will also be set
2004-08-02 14:32:04 +00:00
2005-07-04 16:54:34 +00:00
// Is user banned? Are they excluded? Won't return on ban, exists within method
if ( $this -> data [ 'user_type' ] != USER_FOUNDER )
{
2006-12-10 17:44:45 +00:00
if ( ! $config [ 'forwarded_for_check' ])
{
$this -> check_ban ( $this -> data [ 'user_id' ], $this -> ip );
}
else
{
2009-08-20 08:37:06 +00:00
$ips = explode ( ' ' , $this -> forwarded_for );
2006-12-10 17:44:45 +00:00
$ips [] = $this -> ip ;
$this -> check_ban ( $this -> data [ 'user_id' ], $ips );
}
2003-01-07 18:39:24 +00:00
}
2006-06-11 18:13:52 +00:00
2006-10-03 18:35:59 +00:00
$this -> data [ 'is_registered' ] = ( ! $bot && $this -> data [ 'user_id' ] != ANONYMOUS && ( $this -> data [ 'user_type' ] == USER_NORMAL || $this -> data [ 'user_type' ] == USER_FOUNDER )) ? true : false ;
2005-04-10 18:07:12 +00:00
$this -> data [ 'is_bot' ] = ( $bot ) ? true : false ;
2006-04-06 17:15:45 +00:00
2006-09-13 16:08:36 +00:00
// If our friend is a bot, we re-assign a previously assigned session
2006-10-10 13:59:02 +00:00
if ( $this -> data [ 'is_bot' ] && $bot == $this -> data [ 'user_id' ] && $this -> data [ 'session_id' ])
2006-09-13 16:08:36 +00:00
{
2006-12-10 17:44:45 +00:00
// Only assign the current session if the ip, browser and forwarded_for match...
2007-05-13 16:15:20 +00:00
if ( strpos ( $this -> ip , ':' ) !== false && strpos ( $this -> data [ 'session_ip' ], ':' ) !== false )
{
$s_ip = short_ipv6 ( $this -> data [ 'session_ip' ], $config [ 'ip_check' ]);
$u_ip = short_ipv6 ( $this -> ip , $config [ 'ip_check' ]);
}
else
{
$s_ip = implode ( '.' , array_slice ( explode ( '.' , $this -> data [ 'session_ip' ]), 0 , $config [ 'ip_check' ]));
$u_ip = implode ( '.' , array_slice ( explode ( '.' , $this -> ip ), 0 , $config [ 'ip_check' ]));
}
2006-09-13 16:08:36 +00:00
2008-01-29 14:23:02 +00:00
$s_browser = ( $config [ 'browser_check' ]) ? trim ( strtolower ( substr ( $this -> data [ 'session_browser' ], 0 , 149 ))) : '' ;
$u_browser = ( $config [ 'browser_check' ]) ? trim ( strtolower ( substr ( $this -> browser , 0 , 149 ))) : '' ;
2006-09-13 16:08:36 +00:00
2006-12-10 17:44:45 +00:00
$s_forwarded_for = ( $config [ 'forwarded_for_check' ]) ? substr ( $this -> data [ 'session_forwarded_for' ], 0 , 254 ) : '' ;
$u_forwarded_for = ( $config [ 'forwarded_for_check' ]) ? substr ( $this -> forwarded_for , 0 , 254 ) : '' ;
if ( $u_ip === $s_ip && $s_browser === $u_browser && $s_forwarded_for === $u_forwarded_for )
2006-09-13 16:08:36 +00:00
{
$this -> session_id = $this -> data [ 'session_id' ];
// Only update session DB a minute or so after last update or if page changes
if ( $this -> time_now - $this -> data [ 'session_time' ] > 60 || ( $this -> update_session_page && $this -> data [ 'session_page' ] != $this -> page [ 'page' ]))
{
2006-11-15 15:35:50 +00:00
$this -> data [ 'session_time' ] = $this -> data [ 'session_last_visit' ] = $this -> time_now ;
2006-09-13 16:08:36 +00:00
$sql_ary = array ( 'session_time' => $this -> time_now , 'session_last_visit' => $this -> time_now , 'session_admin' => 0 );
if ( $this -> update_session_page )
{
$sql_ary [ 'session_page' ] = substr ( $this -> page [ 'page' ], 0 , 199 );
2008-03-17 16:25:07 +00:00
$sql_ary [ 'session_forum_id' ] = $this -> page [ 'forum' ];
2006-09-13 16:08:36 +00:00
}
2010-06-28 17:16:44 +02:00
$this -> update_session ( $sql_ary );
2006-11-15 15:35:50 +00:00
// Update the last visit time
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_lastvisit = ' . (int) $this->data[' session_time '] . '
WHERE user_id = ' . (int) $this->data[' user_id ' ];
$db -> sql_query ( $sql );
2006-09-13 16:08:36 +00:00
}
$SID = '?sid=' ;
$_SID = '' ;
return true ;
}
else
{
// If the ip and browser does not match make sure we only have one bot assigned to one session
$db -> sql_query ( 'DELETE FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . $this -> data [ 'user_id' ]);
}
}
2006-04-06 17:15:45 +00:00
$session_autologin = (( $this -> cookie_data [ 'k' ] || $persist_login ) && $this -> data [ 'is_registered' ]) ? true : false ;
2006-10-03 18:35:59 +00:00
$set_admin = ( $set_admin && $this -> data [ 'is_registered' ]) ? true : false ;
2006-04-06 17:15:45 +00:00
2002-07-14 14:32:45 +00:00
// Create or update the session
2004-09-01 15:47:46 +00:00
$sql_ary = array (
2005-07-04 16:54:34 +00:00
'session_user_id' => ( int ) $this -> data [ 'user_id' ],
'session_start' => ( int ) $this -> time_now ,
2004-09-01 15:47:46 +00:00
'session_last_visit' => ( int ) $this -> data [ 'session_last_visit' ],
2005-07-04 16:54:34 +00:00
'session_time' => ( int ) $this -> time_now ,
2008-01-29 14:23:02 +00:00
'session_browser' => ( string ) trim ( substr ( $this -> browser , 0 , 149 )),
2006-12-10 17:44:45 +00:00
'session_forwarded_for' => ( string ) $this -> forwarded_for ,
2004-09-02 20:54:09 +00:00
'session_ip' => ( string ) $this -> ip ,
2006-04-06 17:15:45 +00:00
'session_autologin' => ( $session_autologin ) ? 1 : 0 ,
2005-08-18 12:58:23 +00:00
'session_admin' => ( $set_admin ) ? 1 : 0 ,
'session_viewonline' => ( $viewonline ) ? 1 : 0 ,
2004-09-01 15:47:46 +00:00
);
2006-06-11 18:13:52 +00:00
if ( $this -> update_session_page )
{
$sql_ary [ 'session_page' ] = ( string ) substr ( $this -> page [ 'page' ], 0 , 199 );
2008-03-17 16:25:07 +00:00
$sql_ary [ 'session_forum_id' ] = $this -> page [ 'forum' ];
2006-06-11 18:13:52 +00:00
}
2005-07-04 16:54:34 +00:00
$db -> sql_return_on_error ( true );
2006-08-10 13:33:06 +00:00
$sql = ' DELETE
FROM ' . SESSIONS_TABLE . '
WHERE session_id = \ '' . $db -> sql_escape ( $this -> session_id ) . ' \ '
AND session_user_id = ' . ANONYMOUS ;
2005-12-28 17:35:20 +00:00
2007-03-01 10:29:46 +00:00
if ( ! defined ( 'IN_ERROR_HANDLER' ) && ( ! $this -> session_id || ! $db -> sql_query ( $sql ) || ! $db -> sql_affectedrows ()))
2002-07-14 14:32:45 +00:00
{
2005-07-04 16:54:34 +00:00
// Limit new sessions in 1 minute period (if required)
2007-07-28 09:19:29 +00:00
if ( empty ( $this -> data [ 'session_time' ]) && $config [ 'active_sessions' ])
2005-07-04 16:54:34 +00:00
{
2008-03-18 11:11:16 +00:00
// $db->sql_return_on_error(false);
2008-03-18 10:14:37 +00:00
2006-06-11 18:13:52 +00:00
$sql = ' SELECT COUNT ( session_id ) AS sessions
2005-07-04 16:54:34 +00:00
FROM ' . SESSIONS_TABLE . '
WHERE session_time >= ' . ( $this -> time_now - 60 );
$result = $db -> sql_query ( $sql );
$row = $db -> sql_fetchrow ( $result );
$db -> sql_freeresult ( $result );
2006-06-11 18:13:52 +00:00
2005-07-04 16:54:34 +00:00
if (( int ) $row [ 'sessions' ] > ( int ) $config [ 'active_sessions' ])
{
2010-09-11 21:55:11 +02:00
send_status_line ( 503 , 'Service Unavailable' );
2005-07-04 16:54:34 +00:00
trigger_error ( 'BOARD_UNAVAILABLE' );
}
}
2006-08-10 13:33:06 +00:00
}
2006-06-11 18:13:52 +00:00
2008-03-18 10:14:37 +00:00
// Since we re-create the session id here, the inserted row must be unique. Therefore, we display potential errors.
2008-03-18 11:11:16 +00:00
// Commented out because it will not allow forums to update correctly
// $db->sql_return_on_error(false);
2008-03-18 10:14:37 +00:00
2009-03-28 18:34:09 +00:00
// Something quite important: session_page always holds the *last* page visited, except for the *first* visit.
// We are not able to simply have an empty session_page btw, therefore we need to tell phpBB how to detect this special case.
// If the session id is empty, we have a completely new one and will set an "identifier" here. This identifier is able to be checked later.
if ( empty ( $this -> data [ 'session_id' ]))
{
// This is a temporary variable, only set for the very first visit
$this -> data [ 'session_created' ] = true ;
}
2006-08-10 13:33:06 +00:00
$this -> session_id = $this -> data [ 'session_id' ] = md5 ( unique_id ());
2002-07-14 14:32:45 +00:00
2006-08-10 13:33:06 +00:00
$sql_ary [ 'session_id' ] = ( string ) $this -> session_id ;
$sql_ary [ 'session_page' ] = ( string ) substr ( $this -> page [ 'page' ], 0 , 199 );
2008-03-17 16:25:07 +00:00
$sql_ary [ 'session_forum_id' ] = $this -> page [ 'forum' ];
2006-08-10 13:33:06 +00:00
$sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db -> sql_build_array ( 'INSERT' , $sql_ary );
$db -> sql_query ( $sql );
2004-09-01 15:47:46 +00:00
2008-03-18 11:11:16 +00:00
$db -> sql_return_on_error ( false );
2005-07-04 16:54:34 +00:00
// Regenerate autologin/persistent login key
2006-04-06 17:15:45 +00:00
if ( $session_autologin )
2005-07-04 16:54:34 +00:00
{
$this -> set_login_key ();
}
2006-06-11 18:13:52 +00:00
2007-06-15 17:19:27 +00:00
// refresh data
2006-08-07 10:42:22 +00:00
$SID = '?sid=' . $this -> session_id ;
$_SID = $this -> session_id ;
2007-06-15 17:19:27 +00:00
$this -> data = array_merge ( $this -> data , $sql_ary );
2006-06-11 18:13:52 +00:00
2003-10-15 17:43:07 +00:00
if ( ! $bot )
{
2005-07-17 14:51:57 +00:00
$cookie_expire = $this -> time_now + (( $config [ 'max_autologin_time' ]) ? 86400 * ( int ) $config [ 'max_autologin_time' ] : 31536000 );
2006-06-11 18:13:52 +00:00
2005-07-17 14:51:57 +00:00
$this -> set_cookie ( 'u' , $this -> cookie_data [ 'u' ], $cookie_expire );
$this -> set_cookie ( 'k' , $this -> cookie_data [ 'k' ], $cookie_expire );
2005-12-15 18:25:01 +00:00
$this -> set_cookie ( 'sid' , $this -> session_id , $cookie_expire );
2002-07-14 14:32:45 +00:00
2005-07-05 01:01:31 +00:00
unset ( $cookie_expire );
2008-01-29 15:49:15 +00:00
2007-10-03 15:05:54 +00:00
$sql = ' SELECT COUNT ( session_id ) AS sessions
FROM ' . SESSIONS_TABLE . '
2007-10-04 12:03:05 +00:00
WHERE session_user_id = ' . (int) $this->data[' user_id '] . '
2008-01-28 15:20:47 +00:00
AND session_time >= ' . (int) ($this->time_now - (max($config[' session_length '], $config[' form_token_lifetime ' ])));
2007-10-03 15:05:54 +00:00
$result = $db -> sql_query ( $sql );
$row = $db -> sql_fetchrow ( $result );
$db -> sql_freeresult ( $result );
if (( int ) $row [ 'sessions' ] <= 1 || empty ( $this -> data [ 'user_form_salt' ]))
{
$this -> data [ 'user_form_salt' ] = unique_id ();
// Update the form key
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_form_salt = \ '' . $db -> sql_escape ( $this -> data [ 'user_form_salt' ]) . ' \ '
WHERE user_id = ' . (int) $this->data[' user_id ' ];
$db -> sql_query ( $sql );
}
2003-10-15 17:43:07 +00:00
}
2006-09-13 16:08:36 +00:00
else
{
2006-12-10 17:44:45 +00:00
$this -> data [ 'session_time' ] = $this -> data [ 'session_last_visit' ] = $this -> time_now ;
// Update the last visit time
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_lastvisit = ' . (int) $this->data[' session_time '] . '
WHERE user_id = ' . (int) $this->data[' user_id ' ];
$db -> sql_query ( $sql );
2006-09-13 16:08:36 +00:00
$SID = '?sid=' ;
$_SID = '' ;
}
2007-07-15 20:53:27 +00:00
2002-10-20 19:19:07 +00:00
return true ;
2002-07-14 14:32:45 +00:00
}
2006-06-11 18:13:52 +00:00
2005-07-04 16:54:34 +00:00
/**
* Kills a session
*
* This method does what it says on the tin . It will delete a pre - existing session .
* It resets cookie information ( destroying any autologin key within that cookie data )
* and update the users information from the relevant session data . It will then
* grab guest user information .
*/
2006-12-24 13:11:54 +00:00
function session_kill ( $new_session = true )
2002-07-14 14:32:45 +00:00
{
2013-06-21 18:04:11 -04:00
global $SID , $_SID , $db , $config , $phpbb_root_path , $phpEx , $phpbb_container ;
2002-07-14 14:32:45 +00:00
2003-05-08 01:14:14 +00:00
$sql = 'DELETE FROM ' . SESSIONS_TABLE . "
2006-01-06 07:48:51 +00:00
WHERE session_id = '" . $db->sql_escape($this->session_id) . "'
2005-07-05 01:26:23 +00:00
AND session_user_id = " . (int) $this->data ['user_id'];
2002-07-14 14:32:45 +00:00
$db -> sql_query ( $sql );
2006-04-21 22:41:05 +00:00
// Allow connecting logout with external auth method logout
2006-06-11 18:13:52 +00:00
$method = basename ( trim ( $config [ 'auth_method' ]));
2006-04-21 22:41:05 +00:00
2013-06-21 18:04:11 -04:00
$provider = $phpbb_container -> get ( 'auth.provider.' . $method );
$provider -> logout ( $this -> data , $new_session );
2006-04-21 22:41:05 +00:00
2005-07-04 16:54:34 +00:00
if ( $this -> data [ 'user_id' ] != ANONYMOUS )
{
// Delete existing session, update last visit info first!
2006-01-06 07:48:51 +00:00
if ( ! isset ( $this -> data [ 'session_time' ]))
2006-01-05 21:22:44 +00:00
{
$this -> data [ 'session_time' ] = time ();
}
2006-06-11 18:13:52 +00:00
2005-07-04 16:54:34 +00:00
$sql = 'UPDATE ' . USERS_TABLE . '
2006-01-06 07:48:51 +00:00
SET user_lastvisit = ' . (int) $this->data[' session_time '] . '
WHERE user_id = ' . (int) $this->data[' user_id ' ];
2005-07-04 16:54:34 +00:00
$db -> sql_query ( $sql );
2005-04-10 18:07:12 +00:00
2005-12-15 18:25:01 +00:00
if ( $this -> cookie_data [ 'k' ])
2005-07-05 01:26:23 +00:00
{
$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
WHERE user_id = ' . (int) $this->data[' user_id ' ] . "
2005-12-15 18:25:01 +00:00
AND key_id = '" . $db->sql_escape(md5($this->cookie_data[' k '])) . "' " ;
2005-07-05 01:26:23 +00:00
$db -> sql_query ( $sql );
}
2006-06-11 18:13:52 +00:00
2005-07-04 16:54:34 +00:00
// Reset the data array
2006-06-11 18:13:52 +00:00
$this -> data = array ();
2005-07-04 16:54:34 +00:00
$sql = ' SELECT *
FROM ' . USERS_TABLE . '
WHERE user_id = ' . ANONYMOUS ;
$result = $db -> sql_query ( $sql );
$this -> data = $db -> sql_fetchrow ( $result );
$db -> sql_freeresult ( $result );
}
2006-06-11 18:13:52 +00:00
2005-07-17 14:51:57 +00:00
$cookie_expire = $this -> time_now - 31536000 ;
$this -> set_cookie ( 'u' , '' , $cookie_expire );
$this -> set_cookie ( 'k' , '' , $cookie_expire );
$this -> set_cookie ( 'sid' , '' , $cookie_expire );
unset ( $cookie_expire );
2006-06-11 18:13:52 +00:00
2005-07-04 16:54:34 +00:00
$SID = '?sid=' ;
2006-06-06 20:53:46 +00:00
$this -> session_id = $_SID = '' ;
2002-07-14 14:32:45 +00:00
2006-08-22 21:26:06 +00:00
// To make sure a valid session is created we create one for the anonymous user
2006-12-24 13:11:54 +00:00
if ( $new_session )
{
$this -> session_create ( ANONYMOUS );
}
2006-08-22 21:26:06 +00:00
2002-07-14 14:32:45 +00:00
return true ;
}
2005-07-04 16:54:34 +00:00
/**
* Session garbage collection
*
* This looks a lot more complex than it really is . Effectively we are
* deleting any sessions older than an admin definable limit . Due to the
* way in which we maintain session data we have to ensure we update user
* data before those sessions are destroyed . In addition this method
* removes autologin key information that is older than an admin defined
* limit .
*/
function session_gc ()
2002-07-14 14:32:45 +00:00
{
2009-06-02 14:12:23 +00:00
global $db , $config , $phpbb_root_path , $phpEx ;
2002-07-14 14:32:45 +00:00
2007-09-13 15:15:27 +00:00
$batch_size = 10 ;
2008-01-29 15:49:15 +00:00
2005-10-19 18:00:10 +00:00
if ( ! $this -> time_now )
{
$this -> time_now = time ();
}
2006-06-11 18:13:52 +00:00
2006-09-25 14:32:05 +00:00
// Firstly, delete guest sessions
$sql = 'DELETE FROM ' . SESSIONS_TABLE . '
WHERE session_user_id = ' . ANONYMOUS . '
AND session_time < ' . (int) ($this->time_now - $config[' session_length ' ]);
$db -> sql_query ( $sql );
2003-11-16 23:16:02 +00:00
2006-09-25 14:32:05 +00:00
// Get expired sessions, only most recent for each user
$sql = ' SELECT session_user_id , session_page , MAX ( session_time ) AS recent_time
FROM ' . SESSIONS_TABLE . '
WHERE session_time < ' . ($this->time_now - $config[' session_length ']) . '
GROUP BY session_user_id , session_page ' ;
2007-09-13 15:15:27 +00:00
$result = $db -> sql_query_limit ( $sql , $batch_size );
2004-01-30 12:14:48 +00:00
2006-09-25 14:32:05 +00:00
$del_user_id = array ();
$del_sessions = 0 ;
2006-08-12 13:14:39 +00:00
2006-10-26 10:58:58 +00:00
while ( $row = $db -> sql_fetchrow ( $result ))
2006-09-25 14:32:05 +00:00
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_lastvisit = ' . (int) $row[' recent_time '] . ", user_lastpage = ' " . $db->sql_escape ( $row['session_page'] ) . " '
WHERE user_id = " . (int) $row['session_user_id'] ;
$db -> sql_query ( $sql );
2006-08-12 13:14:39 +00:00
2006-09-25 14:32:05 +00:00
$del_user_id [] = ( int ) $row [ 'session_user_id' ];
$del_sessions ++ ;
}
$db -> sql_freeresult ( $result );
2002-07-14 14:32:45 +00:00
2006-09-25 14:32:05 +00:00
if ( sizeof ( $del_user_id ))
{
// Delete expired sessions
$sql = 'DELETE FROM ' . SESSIONS_TABLE . '
WHERE ' . $db->sql_in_set(' session_user_id ', $del_user_id) . '
AND session_time < ' . ($this->time_now - $config[' session_length ' ]);
$db -> sql_query ( $sql );
}
2002-07-14 14:32:45 +00:00
2007-09-13 15:15:27 +00:00
if ( $del_sessions < $batch_size )
2006-09-25 14:32:05 +00:00
{
2007-09-13 15:15:27 +00:00
// Less than 10 users, update gc timer ... else we want gc
2006-09-25 14:32:05 +00:00
// called again to delete other sessions
set_config ( 'session_last_gc' , $this -> time_now , true );
2008-01-29 15:49:15 +00:00
2007-09-13 15:15:27 +00:00
if ( $config [ 'max_autologin_time' ])
{
$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
WHERE last_login < ' . (time() - (86400 * (int) $config[' max_autologin_time ' ]));
$db -> sql_query ( $sql );
}
2009-06-07 11:34:01 +00:00
2009-06-02 14:12:23 +00:00
// only called from CRON; should be a safe workaround until the infrastructure gets going
2010-06-25 14:38:53 +02:00
if ( ! class_exists ( 'phpbb_captcha_factory' , false ))
2007-09-13 15:15:27 +00:00
{
2009-06-02 14:12:23 +00:00
include ( $phpbb_root_path . " includes/captcha/captcha_factory. " . $phpEx );
2007-09-13 15:15:27 +00:00
}
2013-09-16 01:24:05 +02:00
$captcha_factory = new \phpbb_captcha_factory ();
2013-07-22 15:04:30 -07:00
$captcha_factory -> garbage_collect ( $config [ 'captcha_plugin' ]);
2011-06-10 12:02:59 +02:00
$sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . '
WHERE attempt_time < ' . (time() - (int) $config[' ip_login_limit_time ' ]);
$db -> sql_query ( $sql );
2007-09-13 15:15:27 +00:00
}
2009-06-02 14:12:23 +00:00
return ;
2007-09-13 15:15:27 +00:00
}
2008-01-29 15:49:15 +00:00
2005-07-04 16:54:34 +00:00
/**
* Sets a cookie
*
2008-01-06 17:00:09 +00:00
* Sets a cookie of the given name with the specified data for the given length of time . If no time is specified , a session cookie will be set .
*
* @ param string $name Name of the cookie , will be automatically prefixed with the phpBB cookie name . track becomes [ cookie_name ] _track then .
* @ param string $cookiedata The data to hold within the cookie
* @ param int $cookietime The expiration time as UNIX timestamp . If 0 is provided , a session cookie is set .
2005-07-04 16:54:34 +00:00
*/
2002-10-05 11:38:10 +00:00
function set_cookie ( $name , $cookiedata , $cookietime )
{
2002-10-30 00:57:27 +00:00
global $config ;
2002-10-05 11:38:10 +00:00
2006-10-03 18:35:59 +00:00
$name_data = rawurlencode ( $config [ 'cookie_name' ] . '_' . $name ) . '=' . rawurlencode ( $cookiedata );
$expire = gmdate ( 'D, d-M-Y H:i:s \\G\\M\\T' , $cookietime );
$domain = ( ! $config [ 'cookie_domain' ] || $config [ 'cookie_domain' ] == 'localhost' || $config [ 'cookie_domain' ] == '127.0.0.1' ) ? '' : '; domain=' . $config [ 'cookie_domain' ];
2006-03-21 19:23:34 +00:00
2008-01-06 17:00:09 +00:00
header ( 'Set-Cookie: ' . $name_data . (( $cookietime ) ? '; expires=' . $expire : '' ) . '; path=' . $config [ 'cookie_path' ] . $domain . (( ! $config [ 'cookie_secure' ]) ? '' : '; secure' ) . '; HttpOnly' , false );
2005-07-04 16:54:34 +00:00
}
/**
* Check for banned user
*
* Checks whether the supplied user is banned by id , ip or email . If no parameters
2006-03-15 13:03:57 +00:00
* are passed to the method pre - existing session data is used . If $return is false
2007-07-15 20:53:27 +00:00
* this routine does not return on finding a banned user , it outputs a relevant
2006-03-15 13:03:57 +00:00
* message and stops execution .
2006-12-10 17:44:45 +00:00
*
* @ param string | array $user_ips Can contain a string with one IP or an array of multiple IPs
2005-07-04 16:54:34 +00:00
*/
2006-12-10 17:44:45 +00:00
function check_ban ( $user_id = false , $user_ips = false , $user_email = false , $return = false )
2005-07-04 16:54:34 +00:00
{
global $config , $db ;
2006-06-11 18:13:52 +00:00
2006-12-24 13:11:54 +00:00
if ( defined ( 'IN_CHECK_BAN' ))
{
return ;
}
2005-07-04 16:54:34 +00:00
$banned = false ;
2007-10-18 17:44:02 +00:00
$cache_ttl = 3600 ;
$where_sql = array ();
2005-07-04 16:54:34 +00:00
$sql = ' SELECT ban_ip , ban_userid , ban_email , ban_exclude , ban_give_reason , ban_end
FROM ' . BANLIST_TABLE . '
2007-10-18 17:44:02 +00:00
WHERE ' ;
2006-06-22 15:14:03 +00:00
// Determine which entries to check, only return those
if ( $user_email === false )
{
2007-10-18 17:44:02 +00:00
$where_sql [] = " ban_email = '' " ;
2006-06-22 15:14:03 +00:00
}
2006-12-10 17:44:45 +00:00
if ( $user_ips === false )
2006-06-22 15:14:03 +00:00
{
2007-10-18 17:44:02 +00:00
$where_sql [] = " (ban_ip = '' OR ban_exclude = 1) " ;
2006-06-22 15:14:03 +00:00
}
if ( $user_id === false )
{
2007-10-18 17:44:02 +00:00
$where_sql [] = '(ban_userid = 0 OR ban_exclude = 1)' ;
2006-06-22 15:14:03 +00:00
}
else
{
2007-10-18 17:44:02 +00:00
$cache_ttl = ( $user_id == ANONYMOUS ) ? 3600 : 0 ;
$_sql = '(ban_userid = ' . $user_id ;
2006-06-22 15:14:03 +00:00
if ( $user_email !== false )
{
2007-10-18 17:44:02 +00:00
$_sql .= " OR ban_email <> '' " ;
2006-06-22 15:14:03 +00:00
}
2006-12-10 17:44:45 +00:00
if ( $user_ips !== false )
2006-06-22 15:14:03 +00:00
{
2007-10-18 17:44:02 +00:00
$_sql .= " OR ban_ip <> '' " ;
2006-06-22 15:14:03 +00:00
}
2007-10-18 17:44:02 +00:00
$_sql .= ')' ;
$where_sql [] = $_sql ;
2006-06-22 15:14:03 +00:00
}
2007-10-18 17:44:02 +00:00
$sql .= ( sizeof ( $where_sql )) ? implode ( ' AND ' , $where_sql ) : '' ;
$result = $db -> sql_query ( $sql , $cache_ttl );
2005-07-04 16:54:34 +00:00
2006-10-06 18:43:55 +00:00
$ban_triggered_by = 'user' ;
2005-12-09 18:09:43 +00:00
while ( $row = $db -> sql_fetchrow ( $result ))
2005-01-02 19:06:45 +00:00
{
2007-10-18 17:44:02 +00:00
if ( $row [ 'ban_end' ] && $row [ 'ban_end' ] < time ())
{
continue ;
}
2006-12-10 20:13:46 +00:00
$ip_banned = false ;
if ( ! empty ( $row [ 'ban_ip' ]))
{
if ( ! is_array ( $user_ips ))
{
2007-06-29 13:00:54 +00:00
$ip_banned = preg_match ( '#^' . str_replace ( '\*' , '.*?' , preg_quote ( $row [ 'ban_ip' ], '#' )) . '$#i' , $user_ips );
2006-12-10 20:13:46 +00:00
}
else
{
foreach ( $user_ips as $user_ip )
{
2007-06-29 13:00:54 +00:00
if ( preg_match ( '#^' . str_replace ( '\*' , '.*?' , preg_quote ( $row [ 'ban_ip' ], '#' )) . '$#i' , $user_ip ))
2006-12-10 20:13:46 +00:00
{
$ip_banned = true ;
break ;
}
}
}
}
2005-12-09 18:09:43 +00:00
if (( ! empty ( $row [ 'ban_userid' ]) && intval ( $row [ 'ban_userid' ]) == $user_id ) ||
2006-12-10 20:13:46 +00:00
$ip_banned ||
2007-06-29 13:00:54 +00:00
( ! empty ( $row [ 'ban_email' ]) && preg_match ( '#^' . str_replace ( '\*' , '.*?' , preg_quote ( $row [ 'ban_email' ], '#' )) . '$#i' , $user_email )))
2005-07-04 16:54:34 +00:00
{
2005-12-09 18:09:43 +00:00
if ( ! empty ( $row [ 'ban_exclude' ]))
2005-07-04 16:54:34 +00:00
{
2005-12-09 18:09:43 +00:00
$banned = false ;
break ;
}
else
{
$banned = true ;
$ban_row = $row ;
2006-10-06 18:43:55 +00:00
if ( ! empty ( $row [ 'ban_userid' ]) && intval ( $row [ 'ban_userid' ]) == $user_id )
{
$ban_triggered_by = 'user' ;
}
2007-10-09 15:11:06 +00:00
else if ( $ip_banned )
2006-10-06 18:43:55 +00:00
{
$ban_triggered_by = 'ip' ;
}
else
{
$ban_triggered_by = 'email' ;
}
2005-12-09 18:09:43 +00:00
// Don't break. Check if there is an exclude rule for this user
2005-07-04 16:54:34 +00:00
}
}
2005-01-02 19:06:45 +00:00
}
2005-07-04 16:54:34 +00:00
$db -> sql_freeresult ( $result );
2006-03-15 13:03:57 +00:00
if ( $banned && ! $return )
2005-07-04 16:54:34 +00:00
{
2007-04-30 15:35:12 +00:00
global $template ;
2007-03-08 15:49:13 +00:00
// If the session is empty we need to create a valid one...
if ( empty ( $this -> session_id ))
{
2007-11-03 20:31:05 +00:00
// This seems to be no longer needed? - #14971
// $this->session_create(ANONYMOUS);
2007-03-08 15:49:13 +00:00
}
2005-07-04 16:54:34 +00:00
// Initiate environment ... since it won't be set at this stage
$this -> setup ();
2005-09-21 12:12:58 +00:00
// Logout the user, banned users are unable to use the normal 'logout' link
if ( $this -> data [ 'user_id' ] != ANONYMOUS )
2005-12-09 18:09:43 +00:00
{
2005-09-21 12:12:58 +00:00
$this -> session_kill ();
2005-10-19 18:00:10 +00:00
}
2006-06-11 18:13:52 +00:00
2006-12-24 13:11:54 +00:00
// We show a login box here to allow founders accessing the board if banned by IP
if ( defined ( 'IN_LOGIN' ) && $this -> data [ 'user_id' ] == ANONYMOUS )
{
global $phpEx ;
$this -> setup ( 'ucp' );
$this -> data [ 'is_registered' ] = $this -> data [ 'is_bot' ] = false ;
2007-04-30 15:35:12 +00:00
// Set as a precaution to allow login_box() handling this case correctly as well as this function not being executed again.
define ( 'IN_CHECK_BAN' , 1 );
2006-12-24 13:11:54 +00:00
login_box ( " index. $phpEx " );
// The false here is needed, else the user is able to circumvent the ban.
$this -> session_kill ( false );
}
2007-03-08 15:49:13 +00:00
// Ok, we catch the case of an empty session id for the anonymous user...
// This can happen if the user is logging in, banned by username and the login_box() being called "again".
2007-04-30 15:35:12 +00:00
if ( empty ( $this -> session_id ) && defined ( 'IN_CHECK_BAN' ))
2007-03-08 15:49:13 +00:00
{
$this -> session_create ( ANONYMOUS );
}
2005-07-04 16:54:34 +00:00
// Determine which message to output
2005-12-09 18:09:43 +00:00
$till_date = ( $ban_row [ 'ban_end' ]) ? $this -> format_date ( $ban_row [ 'ban_end' ]) : '' ;
$message = ( $ban_row [ 'ban_end' ]) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM' ;
2005-07-04 16:54:34 +00:00
$message = sprintf ( $this -> lang [ $message ], $till_date , '<a href="mailto:' . $config [ 'board_contact' ] . '">' , '</a>' );
2005-12-09 18:09:43 +00:00
$message .= ( $ban_row [ 'ban_give_reason' ]) ? '<br /><br />' . sprintf ( $this -> lang [ 'BOARD_BAN_REASON' ], $ban_row [ 'ban_give_reason' ]) : '' ;
2006-11-04 16:30:51 +00:00
$message .= '<br /><br /><em>' . $this -> lang [ 'BAN_TRIGGERED_BY_' . strtoupper ( $ban_triggered_by )] . '</em>' ;
2006-10-06 18:43:55 +00:00
2007-11-04 12:07:46 +00:00
// To circumvent session_begin returning a valid value and the check_ban() not called on second page view, we kill the session again
$this -> session_kill ( false );
2008-06-21 14:30:34 +00:00
// A very special case... we are within the cron script which is not supposed to print out the ban message... show blank page
if ( defined ( 'IN_CRON' ))
{
garbage_collection ();
exit_handler ();
exit ;
}
2005-07-04 16:54:34 +00:00
trigger_error ( $message );
}
2006-03-15 13:03:57 +00:00
2008-05-18 20:06:15 +00:00
return ( $banned && $ban_row [ 'ban_give_reason' ]) ? $ban_row [ 'ban_give_reason' ] : $banned ;
2005-07-04 16:54:34 +00:00
}
2006-06-11 18:13:52 +00:00
2006-09-28 15:04:59 +00:00
/**
* Check if ip is blacklisted
* This should be called only where absolutly necessary
*
* Only IPv4 ( rbldns does not support AAAA records / IPv6 lookups )
*
* @ author satmd ( from the php manual )
2006-12-02 13:19:40 +00:00
* @ param string $mode register / post - spamcop for example is ommitted for posting
2006-09-28 15:04:59 +00:00
* @ return false if ip is not blacklisted , else an array ([ checked server ], [ lookup ])
*/
2006-12-02 13:19:40 +00:00
function check_dnsbl ( $mode , $ip = false )
2006-09-28 15:04:59 +00:00
{
if ( $ip === false )
{
$ip = $this -> ip ;
}
2011-05-26 10:43:14 +02:00
// Neither Spamhaus nor Spamcop supports IPv6 addresses.
if ( strpos ( $ip , ':' ) !== false )
{
return false ;
}
2006-09-28 15:04:59 +00:00
$dnsbl_check = array (
2009-04-25 08:52:11 +00:00
'sbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=' ,
2006-09-28 15:04:59 +00:00
);
2006-12-02 13:19:40 +00:00
if ( $mode == 'register' )
{
$dnsbl_check [ 'bl.spamcop.net' ] = 'http://spamcop.net/bl.shtml?' ;
}
2006-09-28 15:04:59 +00:00
if ( $ip )
{
$quads = explode ( '.' , $ip );
$reverse_ip = $quads [ 3 ] . '.' . $quads [ 2 ] . '.' . $quads [ 1 ] . '.' . $quads [ 0 ];
2006-12-06 22:13:11 +00:00
// Need to be listed on all servers...
$listed = true ;
$info = array ();
2006-09-28 15:04:59 +00:00
foreach ( $dnsbl_check as $dnsbl => $lookup )
{
if ( phpbb_checkdnsrr ( $reverse_ip . '.' . $dnsbl . '.' , 'A' ) === true )
{
2006-12-06 22:13:11 +00:00
$info = array ( $dnsbl , $lookup . $ip );
}
else
{
$listed = false ;
2006-09-28 15:04:59 +00:00
}
}
2006-12-06 22:13:11 +00:00
if ( $listed )
{
return $info ;
}
2006-09-28 15:04:59 +00:00
}
return false ;
}
2007-02-22 16:20:11 +00:00
/**
* Check if URI is blacklisted
* This should be called only where absolutly necessary , for example on the submitted website field
* This function is not in use at the moment and is only included for testing purposes , it may not work at all !
* This means it is untested at the moment and therefore commented out
*
* @ param string $uri URI to check
* @ return true if uri is on blacklist , else false . Only blacklist is checked ( ~ zero FP ), no grey lists
function check_uribl ( $uri )
{
// Normally parse_url() is not intended to parse uris
// We need to get the top-level domain name anyway... change.
$uri = parse_url ( $uri );
if ( $uri === false || empty ( $uri [ 'host' ]))
{
return false ;
}
$uri = trim ( $uri [ 'host' ]);
if ( $uri )
{
// One problem here... the return parameter for the "windows" method is different from what
// we expect... this may render this check useless...
if ( phpbb_checkdnsrr ( $uri . '.multi.uribl.com.' , 'A' ) === true )
{
return true ;
}
}
return false ;
}
*/
2005-07-04 16:54:34 +00:00
/**
* Set / Update a persistent login key
*
* This method creates or updates a persistent session key . When a user makes
* use of persistent ( formerly auto - ) logins a key is generated and stored in the
* DB . When they revisit with the same key it ' s automatically updated in both the
* DB and cookie . Multiple keys may exist for each user representing different
* browsers or locations . As with _any_ non - secure - socket no passphrase login this
2006-06-11 18:13:52 +00:00
* remains vulnerable to exploit .
2005-07-04 16:54:34 +00:00
*/
function set_login_key ( $user_id = false , $key = false , $user_ip = false )
{
global $config , $db ;
2006-06-11 18:13:52 +00:00
2005-07-04 16:54:34 +00:00
$user_id = ( $user_id === false ) ? $this -> data [ 'user_id' ] : $user_id ;
$user_ip = ( $user_ip === false ) ? $this -> ip : $user_ip ;
2005-12-15 18:25:01 +00:00
$key = ( $key === false ) ? (( $this -> cookie_data [ 'k' ]) ? $this -> cookie_data [ 'k' ] : false ) : $key ;
2006-06-11 18:13:52 +00:00
2005-11-03 20:53:47 +00:00
$key_id = unique_id ( hexdec ( substr ( $this -> session_id , 0 , 8 )));
2006-06-11 18:13:52 +00:00
2005-07-04 16:54:34 +00:00
$sql_ary = array (
2005-11-03 20:53:47 +00:00
'key_id' => ( string ) md5 ( $key_id ),
2005-07-04 16:54:34 +00:00
'last_ip' => ( string ) $this -> ip ,
'last_login' => ( int ) time ()
);
2005-12-15 18:25:01 +00:00
2005-07-04 16:54:34 +00:00
if ( ! $key )
{
$sql_ary += array (
'user_id' => ( int ) $user_id
);
}
2006-06-11 18:13:52 +00:00
if ( $key )
{
$sql = 'UPDATE ' . SESSIONS_KEYS_TABLE . '
SET ' . $db->sql_build_array(' UPDATE ', $sql_ary) . '
WHERE user_id = ' . ( int ) $user_id . "
AND key_id = '" . $db->sql_escape(md5($key)) . "' " ;
}
else
{
$sql = 'INSERT INTO ' . SESSIONS_KEYS_TABLE . ' ' . $db -> sql_build_array ( 'INSERT' , $sql_ary );
}
2005-07-04 16:54:34 +00:00
$db -> sql_query ( $sql );
2006-06-11 18:13:52 +00:00
2005-11-03 20:53:47 +00:00
$this -> cookie_data [ 'k' ] = $key_id ;
2006-06-11 18:13:52 +00:00
2005-07-04 16:54:34 +00:00
return false ;
}
2006-03-18 22:05:08 +00:00
/**
* Reset all login keys for the specified user
*
* This method removes all current login keys for a specified ( or the current )
* user . It will be called on password change to render old keys unusable
*/
function reset_login_keys ( $user_id = false )
{
global $config , $db ;
2009-11-19 09:54:38 +00:00
$user_id = ( $user_id === false ) ? ( int ) $this -> data [ 'user_id' ] : ( int ) $user_id ;
2006-03-18 22:05:08 +00:00
2006-06-11 18:13:52 +00:00
$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
WHERE user_id = ' . ( int ) $user_id ;
2006-03-18 22:05:08 +00:00
$db -> sql_query ( $sql );
2010-01-25 18:19:18 +00:00
// If the user is logged in, update last visit info first before deleting sessions
2009-09-04 14:53:35 +00:00
$sql = ' SELECT session_time , session_page
FROM ' . SESSIONS_TABLE . '
WHERE session_user_id = ' . (int) $user_id . '
ORDER BY session_time DESC ' ;
$result = $db -> sql_query_limit ( $sql , 1 );
$row = $db -> sql_fetchrow ( $result );
$db -> sql_freeresult ( $result );
2010-01-25 18:19:18 +00:00
if ( $row )
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_lastvisit = ' . (int) $row[' session_time '] . ", user_lastpage = ' " . $db->sql_escape ( $row['session_page'] ) . " '
WHERE user_id = " . (int) $user_id ;
$db -> sql_query ( $sql );
}
2009-09-04 14:53:35 +00:00
2006-03-18 23:08:30 +00:00
// Let's also clear any current sessions for the specified user_id
// If it's the current user then we'll leave this session intact
$sql_where = 'session_user_id = ' . ( int ) $user_id ;
2009-11-19 09:54:38 +00:00
$sql_where .= ( $user_id === ( int ) $this -> data [ 'user_id' ]) ? " AND session_id <> ' " . $db -> sql_escape ( $this -> session_id ) . " ' " : '' ;
2006-03-18 23:08:30 +00:00
2007-07-15 20:53:27 +00:00
$sql = 'DELETE FROM ' . SESSIONS_TABLE . "
2006-03-18 23:08:30 +00:00
WHERE $sql_where " ;
$db -> sql_query ( $sql );
2006-03-18 22:05:08 +00:00
// We're changing the password of the current user and they have a key
// Lets regenerate it to be safe
2009-11-19 09:54:38 +00:00
if ( $user_id === ( int ) $this -> data [ 'user_id' ] && $this -> cookie_data [ 'k' ])
2006-03-18 22:05:08 +00:00
{
$this -> set_login_key ( $user_id );
}
}
2008-05-18 20:06:15 +00:00
2008-05-15 13:29:14 +00:00
/**
2008-05-18 20:06:15 +00:00
* Check if the request originated from the same page .
2008-05-15 13:29:14 +00:00
* @ param bool $check_script_path If true , the path will be checked as well
*/
function validate_referer ( $check_script_path = false )
{
2011-07-13 19:20:16 +02:00
global $config , $request ;
2009-08-04 10:04:54 +00:00
2008-05-15 13:29:14 +00:00
// no referer - nothing to validate, user's fault for turning it off (we only check on POST; so meta can't be the reason)
2008-09-15 18:41:27 +00:00
if ( empty ( $this -> referer ) || empty ( $this -> host ))
2008-05-15 13:29:14 +00:00
{
return true ;
}
2008-06-09 17:05:52 +00:00
2008-05-15 13:29:14 +00:00
$host = htmlspecialchars ( $this -> host );
$ref = substr ( $this -> referer , strpos ( $this -> referer , '://' ) + 3 );
2009-04-22 13:09:41 +00:00
2009-08-04 10:04:54 +00:00
if ( ! ( stripos ( $ref , $host ) === 0 ) && ( ! $config [ 'force_server_vars' ] || ! ( stripos ( $ref , $config [ 'server_name' ]) === 0 )))
2008-05-15 13:29:14 +00:00
{
return false ;
}
2008-05-17 14:34:32 +00:00
else if ( $check_script_path && rtrim ( $this -> page [ 'root_script_path' ], '/' ) !== '' )
2008-05-15 13:29:14 +00:00
{
$ref = substr ( $ref , strlen ( $host ));
2011-07-13 19:20:16 +02:00
$server_port = $request -> server ( 'SERVER_PORT' , 0 );
2008-06-09 17:05:52 +00:00
2008-05-17 14:35:23 +00:00
if ( $server_port !== 80 && $server_port !== 443 && stripos ( $ref , " : $server_port " ) === 0 )
2008-05-17 14:34:32 +00:00
{
$ref = substr ( $ref , strlen ( " : $server_port " ));
}
2008-06-09 17:05:52 +00:00
2008-05-15 13:29:14 +00:00
if ( ! ( stripos ( rtrim ( $ref , '/' ), rtrim ( $this -> page [ 'root_script_path' ], '/' )) === 0 ))
{
return false ;
}
}
2008-06-09 17:05:52 +00:00
2008-05-15 13:29:14 +00:00
return true ;
}
2008-06-02 17:10:21 +00:00
function unset_admin ()
{
global $db ;
$sql = 'UPDATE ' . SESSIONS_TABLE . '
SET session_admin = 0
WHERE session_id = \ '' . $db -> sql_escape ( $this -> session_id ) . '\'' ;
$db -> sql_query ( $sql );
}
2010-06-28 17:16:44 +02:00
/**
* Update the session data
*
* @ param array $session_data associative array of session keys to be updated
* @ param string $session_id optional session_id , defaults to current user ' s session_id
*/
public function update_session ( $session_data , $session_id = null )
{
global $db ;
$session_id = ( $session_id ) ? $session_id : $this -> session_id ;
$sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db -> sql_build_array ( 'UPDATE' , $session_data ) . "
WHERE session_id = '" . $db->sql_escape($session_id) . "' " ;
$db -> sql_query ( $sql );
}
2002-07-14 14:32:45 +00:00
}