2644 lines
63 KiB
PHP
2644 lines
63 KiB
PHP
<?php
|
|
|
|
/**
|
|
* <pre>
|
|
* Invision Power Services
|
|
* IP.Board v3.4.6
|
|
* Registry class for setup
|
|
* Last Updated: $Date: 2013-05-02 23:43:16 -0400 (Thu, 02 May 2013) $
|
|
* </pre>
|
|
*
|
|
* @author Matt Mecham
|
|
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
|
* @license http://www.invisionpower.com/company/standards.php#license
|
|
* @package IP.Board
|
|
* @link http://www.invisionpower.com
|
|
* @since 1st December 2008
|
|
* @version $Revision: 12217 $
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* ipsRegistry class for install/upgrade
|
|
* @package IP.Board
|
|
* @ignore
|
|
*/
|
|
class ipsRegistry
|
|
{
|
|
/**
|
|
* Stored values
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private $values = array();
|
|
|
|
/**
|
|
* Registry instance
|
|
*
|
|
* @access private
|
|
* @var object
|
|
*/
|
|
private static $instance;
|
|
|
|
/**
|
|
* Are we initiated
|
|
*
|
|
* @access private
|
|
* @var bool
|
|
*/
|
|
private static $initiated = FALSE;
|
|
|
|
/**
|
|
* Singleton handles
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private static $handles = array();
|
|
|
|
/**#@+
|
|
* Holds core variable data
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private static $_coreVariables = array();
|
|
private static $_masterCoreVariables = array();
|
|
/**#@-*/
|
|
|
|
/**
|
|
* Stored object references
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private static $classes = array();
|
|
|
|
/**
|
|
* Global config data
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
static public $_config = array();
|
|
|
|
/**#@+
|
|
* Stored URLs
|
|
*
|
|
* @access public
|
|
* @var mixed Array, string
|
|
*/
|
|
static public $urls = array();
|
|
static public $processed_url = '';
|
|
/**#@-*/
|
|
|
|
/**
|
|
* Server load
|
|
*
|
|
* @access public
|
|
* @var string
|
|
*/
|
|
static public $server_load;
|
|
|
|
/**#@+
|
|
* Version numbers
|
|
*
|
|
* @access public
|
|
* @var string
|
|
*/
|
|
static public $version = IPB_VERSION;
|
|
static public $acpversion = IPB_LONG_VERSION;
|
|
static public $vn_full = '';
|
|
static public $vn_build_date = '';
|
|
static public $vn_build_reason = '';
|
|
/**#@-*/
|
|
|
|
/**#@+
|
|
* Applications and modules
|
|
*
|
|
* @access public
|
|
* @var mixed Array, string
|
|
*/
|
|
static public $applications = array();
|
|
static public $modules = array();
|
|
static public $modules_by_section = array();
|
|
static public $current_application = '';
|
|
static public $current_module = '';
|
|
static public $current_section = '';
|
|
/**#@-*/
|
|
|
|
/**
|
|
* Application class vars
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
static public $app_class = array();
|
|
|
|
/**
|
|
* Settings
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
static public $settings = array();
|
|
|
|
/**
|
|
* Request params
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
static public $request = array();
|
|
|
|
/**
|
|
* Singleton init
|
|
*
|
|
* @access public
|
|
* @return object Reference to ourself
|
|
*/
|
|
static public function instance()
|
|
{
|
|
if ( ! self::$instance )
|
|
{
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Custom destructor
|
|
*
|
|
* @access public
|
|
* @return @e void
|
|
*/
|
|
static public function __myDestruct()
|
|
{
|
|
foreach( self::$handles as $name => $obj )
|
|
{
|
|
if ( method_exists( $obj, '__myDestruct' ) )
|
|
{
|
|
$obj->__myDestruct();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initiate the registry
|
|
*
|
|
* @access public
|
|
* @return @e void
|
|
*/
|
|
public static function init()
|
|
{
|
|
if ( self::$initiated === TRUE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
self::$initiated = TRUE;
|
|
|
|
/* Log current upgrade step */
|
|
self::logUpgradeStep();
|
|
|
|
/* Load static classes */
|
|
require( IPS_ROOT_PATH . "sources/base/core.php" );/*noLibHook*/
|
|
require( IPS_ROOT_PATH . "sources/base/ipsMember.php" );/*noLibHook*/
|
|
require_once( IPS_ROOT_PATH . "setup/sources/base/setup.php" );/*noLibHook*/
|
|
|
|
/* Load conf global and set up DB */
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
if ( ! is_file( DOC_IPS_ROOT_PATH . "conf_global.php" ) )
|
|
{
|
|
print "Cannot locate: " . DOC_IPS_ROOT_PATH . "conf_global.php";
|
|
exit();
|
|
}
|
|
|
|
self::loadConfGlobal();
|
|
|
|
/* Got settings? */
|
|
if ( ! ipsRegistry::$settings['sql_driver'] )
|
|
{
|
|
print "Settings not loaded from: " . DOC_IPS_ROOT_PATH . "conf_global.php - did you mean to install?";
|
|
exit();
|
|
}
|
|
|
|
self::setDBHandle();
|
|
}
|
|
else
|
|
{
|
|
/* Ensure char set is defined */
|
|
if( ! defined( 'IPS_DOC_CHAR_SET' ) )
|
|
{
|
|
define( 'IPS_DOC_CHAR_SET', strtoupper( IPSSetUp::charSet ) );
|
|
}
|
|
|
|
if ( ! defined('IPS_CACHE_PATH') )
|
|
{
|
|
define( 'IPS_CACHE_PATH', DOC_IPS_ROOT_PATH );
|
|
}
|
|
|
|
require IPS_ROOT_PATH . "setup/sources/base/install.php";/*noLibHook*/
|
|
}
|
|
|
|
/* Input set up... */
|
|
if ( is_array( $_POST ) and count( $_POST ) )
|
|
{
|
|
foreach( $_POST as $key => $value )
|
|
{
|
|
# Skip post arrays
|
|
if ( ! is_array( $value ) )
|
|
{
|
|
$_POST[ $key ] = IPSText::stripslashes( $value );
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Clean globals, first.
|
|
//-----------------------------------------
|
|
|
|
IPSLib::cleanGlobals( $_GET );
|
|
IPSLib::cleanGlobals( $_POST );
|
|
IPSLib::cleanGlobals( $_COOKIE );
|
|
IPSLib::cleanGlobals( $_REQUEST );
|
|
|
|
# GET first
|
|
$input = IPSLib::parseIncomingRecursively( $_GET, array() );
|
|
|
|
# Then overwrite with POST
|
|
self::$request = IPSLib::parseIncomingRecursively( $_POST, $input );
|
|
|
|
# Assign request method
|
|
self::$request['request_method'] = strtolower( my_getenv('REQUEST_METHOD') );
|
|
|
|
self::_setUpAppData();
|
|
|
|
/* Make sure it's a string */
|
|
if ( is_array( self::$request['section'] ) )
|
|
{
|
|
self::$request['section'] = '';
|
|
}
|
|
|
|
/* Get caches */
|
|
self::$handles['caches'] = ips_CacheRegistry::instance();
|
|
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
/* Make sure all is well before we proceed */
|
|
self::instance()->setUpSettings();
|
|
|
|
/* Build module and application caches */
|
|
self::instance()->checkCaches();
|
|
|
|
/* Load 'legacy' systems */
|
|
$file = '';
|
|
|
|
if ( IPSSetUp::is300plus() === TRUE )
|
|
{
|
|
$file = '3xx.php';
|
|
}
|
|
else if ( IPSSetUp::is200plus() === TRUE )
|
|
{
|
|
$file = '2xx.php';
|
|
}
|
|
else
|
|
{
|
|
$file = '1xx.php';
|
|
}
|
|
|
|
require_once( IPS_ROOT_PATH . 'setup/sources/legacy/' . $file );/*noLibHook*/
|
|
self::instance()->setClass( 'legacy', new upgradeLegacy( self::instance() ) );
|
|
}
|
|
|
|
/* Set up member */
|
|
self::$handles['member'] = ips_MemberRegistry::instance();
|
|
|
|
# Thaw saved data
|
|
IPSSetUp::thawSavedData();
|
|
|
|
/* Gather other classes */
|
|
require_once( IPS_ROOT_PATH . 'setup/sources/classes/output/output.php' );/*noLibHook*/
|
|
|
|
self::instance()->setClass( 'output', new output( self::instance(), TRUE ) );
|
|
|
|
# Fetch global config
|
|
if ( self::readGlobalConfig() === FALSE )
|
|
{
|
|
self::getClass('output')->addError( "Could not load config.xml" );
|
|
}
|
|
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
/* Check session status */
|
|
$validationStatus = self::member()->sessionClass()->getStatus();
|
|
$validationMessage = self::member()->sessionClass()->getMessage();
|
|
|
|
if ( ( self::$request['section'] AND self::$request['section'] != 'index' ) AND ( ! $validationStatus ) )
|
|
{
|
|
/* Force log in */
|
|
self::getClass('output')->setTitle( "Upgrader: Error" );
|
|
self::getClass('output')->setNextAction( '' );
|
|
self::getClass('output')->addContent( self::getClass('output')->template()->page_error( $validationMessage ) );
|
|
self::getClass('output')->sendOutput();
|
|
exit();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Installer locked?
|
|
if ( is_file( DOC_IPS_ROOT_PATH . 'cache/installer_lock.php' ) )
|
|
{
|
|
self::getClass('output')->setTitle( "Installer: Error" );
|
|
self::getClass('output')->setNextAction( '' );
|
|
self::getClass('output')->addContent( self::getClass('output')->template()->page_locked() );
|
|
self::getClass('output')->sendOutput();
|
|
exit();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Log the step we are in the upgrade routine
|
|
*/
|
|
static public function logUpgradeStep()
|
|
{
|
|
$_log = date('r') . "\n";
|
|
$_log .= $_SERVER['REQUEST_URI'] . "\n";
|
|
|
|
$_filename = "UPGRADE_LOG_" . date('d_m_Y') . '.cgi';
|
|
|
|
file_put_contents( DOC_IPS_ROOT_PATH . 'cache/' . $_filename, $_log, FILE_APPEND );
|
|
}
|
|
|
|
/**
|
|
* Load conf_global
|
|
*
|
|
* @access public
|
|
* @return @e void
|
|
*/
|
|
static public function loadConfGlobal()
|
|
{
|
|
/* Load config file */
|
|
if ( is_file( DOC_IPS_ROOT_PATH . 'conf_global.php' ) )
|
|
{
|
|
$INFO = array();
|
|
require( DOC_IPS_ROOT_PATH . 'conf_global.php' );/*noLibHook*/
|
|
|
|
if ( is_array( $INFO ) && count( $INFO ) )
|
|
{
|
|
foreach( $INFO as $key => $val )
|
|
{
|
|
ipsRegistry::$settings[ $key ] = $val;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set database handle
|
|
*
|
|
* @access public
|
|
* @return @e void
|
|
*/
|
|
static public function setDBHandle()
|
|
{
|
|
self::$handles['db'] = ips_DBRegistry::instance();
|
|
self::$handles['db']->setDB( ipsRegistry::$settings['sql_driver'] );
|
|
}
|
|
|
|
/**
|
|
* Auto loads next action
|
|
*
|
|
* @access public
|
|
* @param string Section key
|
|
* @return @e void
|
|
*/
|
|
static public function autoLoadNextAction( $section )
|
|
{
|
|
self::getClass('output')->currentPage = $section;
|
|
self::$request['do'] = '';
|
|
|
|
$_class = IPS_APP_COMPONENT . '_' . $section;
|
|
|
|
require_once( IPS_ROOT_PATH . 'setup/applications/' . IPS_APP_COMPONENT . '/sections/' . $section . '.php' );/*noLibHook*/
|
|
$action = new $_class();
|
|
$action->makeRegistryShortcuts( self::instance() );
|
|
$action->doExecute( self::instance() );
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Read conf_global
|
|
*
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
static public function readGlobalConfig()
|
|
{
|
|
/* Fetch core writeable files */
|
|
require_once( IPS_KERNEL_PATH . 'classXML.php' );/*noLibHook*/
|
|
$xml = new classXML( IPSSetUp::charSet );
|
|
|
|
try
|
|
{
|
|
$xml->load( IPS_ROOT_PATH . 'setup/xml/config.xml' );
|
|
|
|
foreach( $xml->fetchElements( 'package' ) as $xmlelement )
|
|
{
|
|
$data = $xml->fetchElementsFromRecord( $xmlelement );
|
|
|
|
self::$_config = $data;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
catch( Exception $error )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Grabs apps bitwise array
|
|
*
|
|
* @access public
|
|
* @param string $appDir
|
|
* @return string Core variables
|
|
*/
|
|
static public function fetchBitWiseOptions( $appDir )
|
|
{
|
|
if ( $appDir == 'global' )
|
|
{
|
|
return self::_fetchCoreVariables( 'bitwise' );
|
|
}
|
|
else
|
|
{
|
|
return self::_fetchAppCoreVariables( $appDir, 'bitwise' );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch global config data as array
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
static public function fetchGlobalConfigAsArray()
|
|
{
|
|
return is_array( self::$_config ) ? self::$_config : array();
|
|
}
|
|
|
|
/**
|
|
* Fetch global config value
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @return string
|
|
*/
|
|
static public function fetchGlobalConfigValue( $key )
|
|
{
|
|
return isset( self::$_config[ $key ] ) ? self::$_config[ $key ] : FALSE;
|
|
}
|
|
|
|
/**
|
|
* Grab the app class file
|
|
*
|
|
* @param string $app Application to check for app class
|
|
* @return mixed Null if invalid or no app passed, otherwise app class object
|
|
*/
|
|
public static function getAppClass( $app='' )
|
|
{
|
|
if( !$app OR !is_string($app) )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
# Load app class
|
|
if ( ! isset( self::$app_class[ $app ] ) )
|
|
{
|
|
self::$app_class[ $app ] = null;
|
|
|
|
$_file = IPSLib::getAppDir( $app ) . '/app_class_' . $app . '.php';
|
|
$_name = 'app_class_' . $app;
|
|
|
|
if ( is_file( $_file ) )
|
|
{
|
|
$classToLoad = IPSLib::loadLibrary( $_file, $_name, $app );
|
|
|
|
self::$app_class[ $app ] = new $classToLoad( self::instance() );
|
|
}
|
|
}
|
|
|
|
return self::$app_class[ $app ];
|
|
}
|
|
|
|
/**
|
|
* Loads application's core variables (if required)
|
|
*
|
|
* @access public
|
|
* @param string App key (dir.. that's directory, not duuhr)
|
|
* @return @e void
|
|
*/
|
|
static public function _loadCoreVariables()
|
|
{
|
|
if ( ! is_object( self::$_masterCoreVariables['__CLASS__'] ) )
|
|
{
|
|
require_once( IPS_ROOT_PATH . 'extensions/coreVariables.php' );/*noLibHook*/
|
|
|
|
/* Add handle */
|
|
self::$_masterCoreVariables['__CLASS__'] = new coreVariables();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches apps core variable data
|
|
*
|
|
* @access public
|
|
* @param string Type of variable to return
|
|
* @return string
|
|
*/
|
|
public static function _fetchCoreVariables( $type )
|
|
{
|
|
if ( ! is_array( self::$_masterCoreVariables[ $type ] ) )
|
|
{
|
|
self::_loadCoreVariables();
|
|
|
|
switch( $type )
|
|
{
|
|
case 'cache':
|
|
case 'cacheload':
|
|
$return = self::$_masterCoreVariables['__CLASS__']->fetchCaches();
|
|
self::$_masterCoreVariables['cache'] = is_array( $return['caches'] ) ? $return['caches'] : array();
|
|
self::$_masterCoreVariables['cacheload'] = is_array( $return['cacheload'] ) ? $return['cacheload'] : array();
|
|
break;
|
|
case 'redirect':
|
|
$return = self::$_masterCoreVariables['__CLASS__']->fetchRedirects();
|
|
self::$_masterCoreVariables['redirect'] = is_array( $return ) ? $return : array();
|
|
break;
|
|
case 'templates':
|
|
$return = self::$_masterCoreVariables['__CLASS__']->fetchTemplates();
|
|
self::$_masterCoreVariables['templates'] = is_array( $return ) ? $return : array();
|
|
break;
|
|
case 'bitwise':
|
|
$return = self::$_masterCoreVariables['__CLASS__']->fetchBitwise();
|
|
self::$_masterCoreVariables['bitwise'] = is_array( $return ) ? $return : array();
|
|
break;
|
|
}
|
|
}
|
|
|
|
return self::$_masterCoreVariables[ $type ];
|
|
}
|
|
|
|
/**
|
|
* Loads application's core variables (if required)
|
|
*
|
|
* @access private
|
|
* @param string App key (dir.. that's directory, not duuhr)
|
|
* @return @e void
|
|
*/
|
|
static private function _loadAppCoreVariables( $appDir )
|
|
{
|
|
if ( ! isset( self::$_coreVariables[ $appDir ] ) )
|
|
{
|
|
if( is_file( IPSLib::getAppDir( $appDir ) . '/extensions/coreVariables.php' ) )
|
|
{
|
|
require( IPSLib::getAppDir( $appDir ) . '/extensions/coreVariables.php' );/*noLibHook*/
|
|
|
|
/* Add caches */
|
|
self::$_coreVariables[ $appDir ]['cache'] = is_array( $CACHE ) ? $CACHE : array();
|
|
self::$_coreVariables[ $appDir ]['cacheload'] = is_array( $_LOAD ) ? $_LOAD : array();
|
|
|
|
/* Add redirect */
|
|
self::$_coreVariables[ $appDir ]['redirect'] = is_array( $_RESET ) ? $_RESET : array();
|
|
|
|
/* Add bitwise */
|
|
self::$_coreVariables[ $appDir ]['bitwise'] = is_array( $_BITWISE ) ? $_BITWISE : array();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches apps core variable data
|
|
*
|
|
* @access public
|
|
* @param string App dir
|
|
* @param string Type of variable to return
|
|
* @return string
|
|
*/
|
|
static public function _fetchAppCoreVariables( $appDir, $type )
|
|
{
|
|
if ( ! is_array( self::$_coreVariables[ $appDir ][ $type ] ) )
|
|
{
|
|
self::_loadAppCoreVariables( $appDir );
|
|
}
|
|
|
|
return self::$_coreVariables[ $appDir ][ $type ];
|
|
}
|
|
|
|
/**
|
|
* Store object handles so we don't need to reinit them
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @param object Value
|
|
* @return @e void
|
|
*/
|
|
static public function setClass( $key='', $value='' )
|
|
{
|
|
self::instance()->checkForInit();
|
|
|
|
if ( ! $key OR ! $value )
|
|
{
|
|
throw new Exception( "Missing a key or value" );
|
|
}
|
|
else if ( ! is_object( $value ) )
|
|
{
|
|
throw new Exception( "$value is not an object" );
|
|
}
|
|
|
|
self::$classes[ $key ] = $value;
|
|
}
|
|
|
|
/**
|
|
* Function for retrieving class handles
|
|
* AUTOLOADED classes are as follows:
|
|
* KERNEL -> class_captcha
|
|
* KERNEL -> classTemplateEngine (templateEngine)
|
|
* CORE -> localization class
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @return object
|
|
*/
|
|
static public function getClass( $key )
|
|
{
|
|
self::instance()->checkForInit();
|
|
|
|
/* Do some magic here to retreive common classes without
|
|
having to initialize them first */
|
|
if ( ! isset( self::$classes[ $key ] ) || ! is_object( self::$classes[ $key ] ) )
|
|
{
|
|
switch( $key )
|
|
{
|
|
default:
|
|
throw new Exception( "$key is not an object" );
|
|
break;
|
|
case 'class_captcha':
|
|
require_once( IPS_KERNEL_PATH . 'classCaptcha.php' );/*noLibHook*/
|
|
self::$classes['class_captcha'] = new classCaptcha( self::instance() );
|
|
break;
|
|
case 'templateEngine':
|
|
require_once( IPS_KERNEL_PATH . 'classTemplateEngine.php' );/*noLibHook*/
|
|
self::$classes['templateEngine'] = new classTemplate( IPS_ROOT_PATH . 'sources/template_plugins' );
|
|
break;
|
|
case 'class_localization':
|
|
require_once( IPS_ROOT_PATH . 'sources/classes/class_localization.php' );/*noLibHook*/
|
|
self::$classes['class_localization'] = new class_localization( self::instance() );
|
|
break;
|
|
case 'permissions':
|
|
require_once( IPS_ROOT_PATH . 'sources/classes/class_public_permissions.php' );/*noLibHook*/
|
|
self::$classes['permissions'] = new classPublicPermissions( self::instance() );
|
|
break;
|
|
/* Yes I know this is forums app and not global, but it's still called so much this is a good idea */
|
|
case 'class_forums':
|
|
require_once( IPSLib::getAppDir( 'forums' ) . "/sources/classes/forums/class_forums.php" );/*noLibHook*/
|
|
self::$classes['class_forums'] = new class_forums( self::instance() );
|
|
self::$classes['class_forums']->strip_invisible = true;
|
|
self::$classes['class_forums']->forumsInit();
|
|
break;
|
|
case 'classItemMarking':
|
|
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/itemmarking/classItemMarking.php', 'classItemMarking' );
|
|
self::$classes['classItemMarking'] = new $classToLoad( self::instance() );
|
|
break;
|
|
|
|
}
|
|
|
|
return self::$classes[ $key ];
|
|
}
|
|
else
|
|
{
|
|
return self::$classes[ $key ];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return a list of classes
|
|
* IN_DEV ONLY
|
|
*
|
|
* @access public
|
|
* @return mixed Array of items, or false
|
|
*/
|
|
public static function getLoadedClassesAsArray()
|
|
{
|
|
if ( ! IN_DEV )
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return array_keys( self::$classes );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shortcut for accessing registry objects
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @return object
|
|
*/
|
|
public function __get( $key )
|
|
{
|
|
self::instance()->checkForInit();
|
|
|
|
$_class = self::getClass( $key );
|
|
|
|
if ( is_object( $_class ) )
|
|
{
|
|
return $_class;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find out if a class is loaded
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @return bool
|
|
*/
|
|
static public function isClassLoaded( $key )
|
|
{
|
|
return ( isset( self::$classes[ $key ] ) && is_object( self::$classes[ $key ] ) ) ? TRUE : FALSE;
|
|
}
|
|
|
|
/**
|
|
* Get database object
|
|
*
|
|
* @access public
|
|
* @param string DB connection key
|
|
* @return object
|
|
*/
|
|
static public function DB( $key='' )
|
|
{
|
|
if ( self::$settings['sql_user'] )
|
|
{
|
|
self::instance()->checkForInit();
|
|
return self::$handles['db']->getDB( $key );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get database functions object
|
|
*
|
|
* @access public
|
|
* @param string DB connection key
|
|
* @return object
|
|
*/
|
|
static public function dbFunctions( $key='' )
|
|
{
|
|
self::instance()->checkForInit();
|
|
return self::$handles['db'];
|
|
}
|
|
|
|
/**
|
|
* Get cache object
|
|
*
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
static public function cache()
|
|
{
|
|
self::instance()->checkForInit();
|
|
return self::$handles['caches'];
|
|
}
|
|
|
|
/**
|
|
* Get cache object
|
|
*
|
|
* @access public
|
|
* @return array
|
|
* @see fetchSettings()
|
|
*/
|
|
static public function settings()
|
|
{
|
|
self::instance()->checkForInit();
|
|
return ipsRegistry::$settings;
|
|
}
|
|
|
|
/**
|
|
* Fetch all the settings
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
static public function &fetchSettings()
|
|
{
|
|
return ipsRegistry::$settings;
|
|
}
|
|
|
|
/**
|
|
* Fetch request items
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
static public function &fetchRequest()
|
|
{
|
|
return ipsRegistry::$request;
|
|
}
|
|
|
|
/**
|
|
* Fetch request items
|
|
*
|
|
* @access public
|
|
* @return array
|
|
* @see fetchRequest()
|
|
*/
|
|
static public function request()
|
|
{
|
|
self::instance()->checkForInit();
|
|
return ipsRegistry::$request;
|
|
}
|
|
|
|
/**
|
|
* Fetch member object
|
|
*
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
static public function member()
|
|
{
|
|
self::instance()->checkForInit();
|
|
|
|
if( isset( self::$handles['member'] ) )
|
|
{
|
|
return self::$handles['member'];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the current application
|
|
*
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
static public function getCurrentApplication()
|
|
{
|
|
return self::$current_application;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of applications
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getApplications()
|
|
{
|
|
/* Can be called before 'applications' cache has been rebuilt, i.e. db checker when coming from 2.3.6 -> current */
|
|
if( !count(self::$applications) )
|
|
{
|
|
ipsRegistry::DB()->build( array( 'select' => '*', 'from' => 'core_applications' ) );
|
|
ipsRegistry::DB()->execute();
|
|
|
|
while( $r = ipsRegistry::DB()->fetch() )
|
|
{
|
|
self::$applications[ $r['app_directory'] ] = $r;
|
|
}
|
|
}
|
|
|
|
return self::$applications;
|
|
}
|
|
|
|
/**
|
|
* Check to see if we are initialized
|
|
*
|
|
* @access protected
|
|
* @return @e void
|
|
*/
|
|
protected function checkForInit()
|
|
{
|
|
if ( self::$initiated !== TRUE )
|
|
{
|
|
throw new Exception('ipsRegistry has not been initiated. Do so by calling ipsRegistry::init()' );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Set up request redirect stuff
|
|
*
|
|
* @return @e void
|
|
* @author MattMecham
|
|
* @access protected
|
|
*/
|
|
protected static function _setUpAppData()
|
|
{
|
|
$_default = ( IPS_IS_UPGRADER ) ? 'upgrade' : 'install';
|
|
|
|
# Finalize the app component constants
|
|
$_appcomponent = preg_replace( "/[^a-zA-Z0-9\-\_]/", "" , ( isset( $_REQUEST['app'] ) && trim( $_REQUEST['app'] ) ? $_REQUEST['app'] : $_default ) );
|
|
define( 'IPS_APP_COMPONENT', ( $_appcomponent ) ? $_appcomponent : $_default );
|
|
|
|
self::$current_section = IPSText::alphanumericalClean( $_REQUEST['section'] );
|
|
}
|
|
|
|
/**
|
|
* Set up settings
|
|
*
|
|
* @return @e void
|
|
* @author MattMecham
|
|
* @access protected
|
|
*/
|
|
protected function setUpSettings()
|
|
{
|
|
$settings_cache = self::$handles['caches']->getCache('settings');
|
|
|
|
if ( ! is_array( $settings_cache ) OR ! count( $settings_cache ) )
|
|
{
|
|
/* Ok, if we're an upgrader and we're 1.3... */
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
$settings_cache = array();
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( "Could not initiate the registry, the settings cache is empty or missing" );
|
|
}
|
|
}
|
|
|
|
foreach( $settings_cache as $k => $v )
|
|
{
|
|
ipsRegistry::$settings[$k] = $v;
|
|
}
|
|
|
|
if ( ! defined('IPS_CACHE_PATH') )
|
|
{
|
|
define( 'IPS_CACHE_PATH', ( IPS_IS_UPGRADER ) ? ( ! empty( ipsRegistry::$settings['ipb_cache_path'] ) ? ipsRegistry::$settings['ipb_cache_path'] : DOC_IPS_ROOT_PATH ) : DOC_IPS_ROOT_PATH );
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Back up base URL
|
|
//-----------------------------------------
|
|
|
|
ipsRegistry::$settings['base_url'] = ( ipsRegistry::$settings['board_url'] ) ? ipsRegistry::$settings['board_url'] : ipsRegistry::$settings['base_url'];
|
|
ipsRegistry::$settings['_original_base_url'] = ipsRegistry::$settings['base_url'];
|
|
|
|
//-----------------------------------------
|
|
// Make a safe query string
|
|
//-----------------------------------------
|
|
|
|
ipsRegistry::$settings['query_string_safe'] = str_replace( '&amp;', '&', IPSText::parseCleanValue( urldecode( my_getenv('QUERY_STRING') ) ) );
|
|
ipsRegistry::$settings['query_string_real'] = str_replace( '&' , '&' , ipsRegistry::$settings['query_string_safe'] );
|
|
|
|
//-----------------------------------------
|
|
// Format it..
|
|
//-----------------------------------------
|
|
|
|
ipsRegistry::$settings['query_string_formatted'] = str_replace( ipsRegistry::$settings['board_url'] . '/index.'.ipsRegistry::$settings['php_ext'].'?', '', ipsRegistry::$settings['query_string_safe'] );
|
|
ipsRegistry::$settings['query_string_formatted'] = preg_replace( "#s=([a-z0-9]){32}#", '', ipsRegistry::$settings['query_string_formatted'] );
|
|
|
|
//-----------------------------------------
|
|
// Default settings
|
|
//-----------------------------------------
|
|
|
|
ipsRegistry::$settings['_admin_link'] = ipsRegistry::$settings['base_url'] . '/' . CP_DIRECTORY . '/index.php';
|
|
ipsRegistry::$settings['max_user_name_length'] = ipsRegistry::$settings['max_user_name_length'] ? ipsRegistry::$settings['max_user_name_length'] : 26;
|
|
|
|
# Upload
|
|
ipsRegistry::$settings['upload_dir'] = ipsRegistry::$settings['upload_dir'] ? ipsRegistry::$settings['upload_dir'] : DOC_IPS_ROOT_PATH.'uploads';
|
|
ipsRegistry::$settings['upload_url'] = ipsRegistry::$settings['upload_url'] ? ipsRegistry::$settings['upload_url'] :ipsRegistry::$settings['base_url'] . '/uploads';
|
|
|
|
# Char set
|
|
ipsRegistry::$settings['gb_char_set'] = ipsRegistry::$settings['gb_char_set'] ? ipsRegistry::$settings['gb_char_set'] : 'UTF-8';
|
|
|
|
if( !defined( 'IPS_DOC_CHAR_SET' ) )
|
|
{
|
|
define( 'IPS_DOC_CHAR_SET', ipsRegistry::$settings['gb_char_set'] );
|
|
}
|
|
|
|
# If htaccess mod rewrite is on, enforce path_info usage
|
|
ipsRegistry::$settings['url_type'] = ( ipsRegistry::$settings['htaccess_mod_rewrite'] ) ? 'path_info' : ipsRegistry::$settings['url_type'];
|
|
}
|
|
|
|
/**
|
|
* Check caches
|
|
*
|
|
* @return @e void
|
|
* @author MattMecham
|
|
* @access protected
|
|
*/
|
|
protected function checkCaches()
|
|
{
|
|
//-----------------------------------------
|
|
// Check app cache data
|
|
//-----------------------------------------
|
|
|
|
$group_cache = self::$handles['caches']->getCache('group_cache');
|
|
|
|
if ( ! is_array( $group_cache ) OR ! count( $group_cache ) )
|
|
{
|
|
/* Another catch for IPB 1.3 */
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
if ( IPSSetUp::is200plus() !== TRUE )
|
|
{
|
|
/* Er.. don't actually think we need 'em to be honest */
|
|
self::DB()->delete( 'cache_store', 'cs_key=\'group_cache\'' );
|
|
|
|
self::DB()->build( array( 'select' => '*',
|
|
'from' => 'groups' ) );
|
|
|
|
self::DB()->execute();
|
|
|
|
$groups = array();
|
|
|
|
while( $row = self::DB()->fetch() )
|
|
{
|
|
$groups[ $row['g_id'] ] = $row;
|
|
}
|
|
|
|
self::DB()->insert( 'cache_store', array( 'cs_key' => 'group_cache',
|
|
'cs_value' => serialize( $groups ) ) );
|
|
}
|
|
else
|
|
{
|
|
//$this->cache()->rebuildCache( 'group_cache', 'global' );
|
|
}
|
|
}
|
|
}
|
|
|
|
$app_cache = self::$handles['caches']->getCache('app_cache');
|
|
|
|
//-----------------------------------------
|
|
// Build app data and APP specific load requests
|
|
//-----------------------------------------
|
|
|
|
if( is_array($app_cache) AND count($app_cache) )
|
|
{
|
|
foreach( $app_cache as $_app_dir => $_app_data )
|
|
{
|
|
if ( !IPS_IS_TASK AND ( IPS_AREA == 'public' && ! $_app_data['app_public_title'] ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$_app_data['app_public_title'] = ( $_app_data['app_public_title'] ) ? $_app_data['app_public_title'] : $_app_data['app_title'];
|
|
self::$applications[ $_app_dir ] = $_app_data;
|
|
}
|
|
}
|
|
|
|
/* Sort by position */
|
|
uasort( self::$applications, 'ipsRegistry::_appPositionSort' );
|
|
}
|
|
|
|
/**
|
|
* Sort by position
|
|
*
|
|
* @return integer
|
|
*/
|
|
protected static function _appPositionSort( $a, $b )
|
|
{
|
|
$a['app_position'] = ( isset( $a['app_position'] ) ) ? $a['app_position'] : 0;
|
|
$b['app_position'] = ( isset( $b['app_position'] ) ) ? $b['app_position'] : 0;
|
|
|
|
return ( $a['app_position'] > $b['app_position'] ) ? +1 : -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ips_base_Registry
|
|
*
|
|
*/
|
|
abstract class ips_base_Registry
|
|
{
|
|
/**
|
|
* Generic data storage for each class that extends ips_base_Registry
|
|
*
|
|
* @access protected
|
|
* @var array
|
|
*/
|
|
protected $data_store = array();
|
|
|
|
/**
|
|
* get()
|
|
*
|
|
* Returns the value for the specified key from the data_store, can be overriden by child classes
|
|
*
|
|
* @access public
|
|
* @param mixed $key
|
|
* @return mixed
|
|
*/
|
|
protected function get( $key )
|
|
{
|
|
if( isset( $this->data_store[ $key ] ) )
|
|
{
|
|
return $this->data_store[ $key ];
|
|
}
|
|
else
|
|
{
|
|
return '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* set()
|
|
*
|
|
* Sets a value in the data_store
|
|
*
|
|
* @access public
|
|
* @param mixed $key
|
|
* @param mixed $val
|
|
* @return mixed
|
|
*/
|
|
protected function set( $key, $val )
|
|
{
|
|
$this->data_store[ $key ] = $val;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Base Database class
|
|
*/
|
|
class ips_DBRegistry extends ips_base_Registry
|
|
{
|
|
/**
|
|
* DB instance
|
|
*
|
|
* @access private
|
|
* @var object
|
|
*/
|
|
private static $instance;
|
|
|
|
/**
|
|
* Static array for variables
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private static $vars = array();
|
|
|
|
/**
|
|
* Static DB prefixes
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private static $dbPrefixes = array( '__default__' => '' );
|
|
|
|
/**
|
|
* Static DB driver
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private static $dbDrivers = array( '__default__' => '' );
|
|
|
|
/**
|
|
* Static default DB object
|
|
*
|
|
* @access private
|
|
* @var string
|
|
*/
|
|
private static $defaultKey = '__default__';
|
|
|
|
/**
|
|
* Cache files tried to load
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private static $_queryFilesTriedToLoad = array();
|
|
|
|
/**
|
|
* Cache file parsed names
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private static $_queryFilesNames = array();
|
|
|
|
/**
|
|
* Singleton init
|
|
*
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
static public function instance()
|
|
{
|
|
if ( ! self::$instance )
|
|
{
|
|
self::$instance = new self();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Get DB instance
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @return object
|
|
*/
|
|
static public function getDB( $key='' )
|
|
{
|
|
$key = ( $key ) ? $key : self::$defaultKey;
|
|
|
|
return self::instance()->get( $key );
|
|
}
|
|
|
|
/**
|
|
* Return the prefix for this connection
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @return string
|
|
*/
|
|
static public function getPrefix( $key='' )
|
|
{
|
|
$key = ( $key ) ? $key : self::$defaultKey;
|
|
|
|
if ( isset(self::$dbPrefixes[$key]) )
|
|
{
|
|
return self::$dbPrefixes[ $key ];
|
|
}
|
|
else
|
|
{
|
|
throw new Exception( "Database connection key $key does not exist" );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the driver type currently in use, ex: mysql
|
|
*
|
|
* @access public
|
|
* @param string $key Key of the db connection to check
|
|
* @return object
|
|
*/
|
|
static public function getDriverType( $key= '' )
|
|
{
|
|
/* Set Key */
|
|
$key = ( $key ) ? $key : self::$defaultKey;
|
|
|
|
return self::$dbDrivers[ $key ];
|
|
}
|
|
|
|
/**
|
|
* Sets the DB instance
|
|
*
|
|
* @access public
|
|
* @param object $db_driver DB instance
|
|
* @param string $key Key of the db connection to check
|
|
* @return @e void
|
|
*/
|
|
|
|
static function setDB( $db_driver, $key='' )
|
|
{
|
|
/* INIT */
|
|
$db_driver = strtolower( $db_driver );
|
|
$query_file_extra = ( IPS_AREA == 'admin' ) ? '_admin' : '';
|
|
$key = ( $key ) ? $key : self::$defaultKey;
|
|
|
|
/* Fix up settings */
|
|
if ( ! class_exists( 'dbMain' ) )
|
|
{
|
|
require_once ( IPS_KERNEL_PATH . 'classDb' . ucwords($db_driver) . ".php" );/*noLibHook*/
|
|
}
|
|
|
|
$classname = "db_driver_" . $db_driver;
|
|
|
|
/* INIT Object */
|
|
self::instance()->dbObjects[ $key ] = new $classname;
|
|
|
|
self::instance()->dbObjects[ $key ]->obj['sql_database'] = ipsRegistry::$settings['sql_database'];
|
|
self::instance()->dbObjects[ $key ]->obj['sql_user'] = ipsRegistry::$settings['sql_user'];
|
|
self::instance()->dbObjects[ $key ]->obj['sql_port'] = ipsRegistry::$settings['sql_port'];
|
|
self::instance()->dbObjects[ $key ]->obj['sql_socket'] = isset(ipsRegistry::$settings['sql_socket']) ? ipsRegistry::$settings['sql_socket'] : null;
|
|
self::instance()->dbObjects[ $key ]->obj['sql_pass'] = str_replace( '\\\'', '\'', ipsRegistry::$settings['sql_pass'] );
|
|
self::instance()->dbObjects[ $key ]->obj['sql_host'] = ipsRegistry::$settings['sql_host'];
|
|
self::instance()->dbObjects[ $key ]->obj['sql_charset'] = ipsRegistry::$settings['sql_charset'];
|
|
self::instance()->dbObjects[ $key ]->obj['sql_tbl_prefix'] = ipsRegistry::$settings['sql_tbl_prefix'] ? ipsRegistry::$settings['sql_tbl_prefix'] : '';
|
|
self::instance()->dbObjects[ $key ]->obj['force_new_connection'] = ( $key != self::$defaultKey ) ? 1 : 0;
|
|
self::instance()->dbObjects[ $key ]->obj['persistent'] = isset(ipsRegistry::$settings['persistent']) ? ipsRegistry::$settings['persistent'] : 0;
|
|
self::instance()->dbObjects[ $key ]->obj['use_shutdown'] = IPS_USE_SHUTDOWN;
|
|
# Error log
|
|
self::instance()->dbObjects[ $key ]->obj['error_log'] = DOC_IPS_ROOT_PATH . 'cache/sql_error_log_'.date('m_d_y').'.cgi';
|
|
self::instance()->dbObjects[ $key ]->obj['use_error_log'] = 0;//IN_DEV ? 0 : 1;
|
|
# Debug log - Don't use this on a production board!
|
|
self::instance()->dbObjects[ $key ]->obj['debug_log'] = DOC_IPS_ROOT_PATH . 'cache/sql_debug_log_'.date('m_d_y').'.cgi';
|
|
self::instance()->dbObjects[ $key ]->obj['use_debug_log'] = IN_DEV ? 0 : 0;
|
|
|
|
//---------------------------------------------
|
|
// Required vars?
|
|
//---------------------------------------------
|
|
|
|
if ( is_array( self::instance()->dbObjects[ $key ]->connect_vars ) and count( self::instance()->dbObjects[ $key ]->connect_vars ) )
|
|
{
|
|
foreach( self::instance()->dbObjects[ $key ]->connect_vars as $k => $v )
|
|
{
|
|
self::instance()->dbObjects[ $key ]->connect_vars[ $k ] = ipsRegistry::$settings[ $k ];
|
|
}
|
|
}
|
|
|
|
//------------------------------------------
|
|
// Backwards compat
|
|
//------------------------------------------
|
|
|
|
if ( ! self::instance()->dbObjects[ $key ]->connect_vars['mysql_tbl_type'] )
|
|
{
|
|
self::instance()->dbObjects[ $key ]->connect_vars['mysql_tbl_type'] = 'myisam';
|
|
}
|
|
|
|
//------------------------------------------
|
|
// Update settings
|
|
//------------------------------------------
|
|
|
|
self::$dbPrefixes[ $key ] = self::instance()->dbObjects[ $key ]->obj['sql_tbl_prefix'];
|
|
self::$dbDrivers[ $key ] = $db_driver;
|
|
|
|
//------------------------------------------
|
|
// Get a DB connection
|
|
//------------------------------------------
|
|
|
|
self::instance()->dbObjects[ $key ]->connect();
|
|
|
|
self::instance()->set( $key, self::instance()->dbObjects[ $key ] );
|
|
}
|
|
|
|
/**
|
|
* Fetch query file, if available
|
|
*
|
|
* @access public
|
|
* @param string 'public' or 'admin'
|
|
* @param string App dir
|
|
* @param string Key
|
|
* @return boolean
|
|
*/
|
|
static public function loadQueryFile( $where, $app, $key='' )
|
|
{
|
|
$key = ( $key ) ? $key : self::$defaultKey;
|
|
$where = ( $where == 'admin' ) ? 'admin' : 'public';
|
|
$driver = self::getDriverType( $key );
|
|
|
|
/* Already tried to load? */
|
|
if ( isset( self::$_queryFilesTriedToLoad[ $app . '-' . $driver ] ) )
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
self::$_queryFilesTriedToLoad[ $app . '-' . $driver ] = 1;
|
|
}
|
|
|
|
$file = self::fetchQueryFileName( $where, $app, $key );
|
|
$class = self::fetchQueryFileClassName( $where, $app, $key );
|
|
|
|
IPSDebug::addMessage( "* Checking for query cache file: " . $file );
|
|
|
|
if ( is_file( $file ) )
|
|
{
|
|
self::getDB( $key )->loadCacheFile( $file, $class, TRUE );
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch query file, if available
|
|
*
|
|
* @access public
|
|
* @param string 'public' or 'admin'
|
|
* @param string App dir
|
|
* @param string Key
|
|
* @return File name
|
|
*/
|
|
static public function fetchQueryFileClassName( $where, $app, $key='' )
|
|
{
|
|
$key = ( $key ) ? $key : self::$defaultKey;
|
|
$where = ( $where == 'admin' ) ? 'admin' : 'public';
|
|
|
|
return $where . '_' . $app . '_sql_queries';
|
|
}
|
|
|
|
/**
|
|
* Fetch query file, if available
|
|
*
|
|
* @access public
|
|
* @param string 'public' or 'admin'
|
|
* @param string App dir
|
|
* @param string Key
|
|
* @return File name
|
|
*/
|
|
static public function fetchQueryFileName( $where, $app, $key='' )
|
|
{
|
|
$key = ( $key ) ? $key : self::$defaultKey;
|
|
$where = ( $where == 'admin' ) ? 'admin' : 'public';
|
|
$driver = self::getDriverType( $key );
|
|
|
|
/* Already tried to load? */
|
|
if ( ! isset( self::$_queryFilesNames[ $app . '-' . $driver ] ) )
|
|
{
|
|
self::$_queryFilesNames[ $app . '-' . $driver ] = IPSLib::getAppDir( $app ) . '/sql/' . $driver . '_' . $where . '.php';
|
|
}
|
|
|
|
return self::$_queryFilesNames[ $app . '-' . $driver ];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stub class to prevent other classes from breaking
|
|
*/
|
|
class ips_CacheRegistry extends ips_base_Registry
|
|
{
|
|
/**
|
|
* Instance
|
|
*
|
|
* @access private
|
|
* @var object
|
|
*/
|
|
private static $instance;
|
|
|
|
/**
|
|
* Save options
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private $save_options = array();
|
|
|
|
/**
|
|
* Cache library
|
|
*
|
|
* @access private
|
|
* @var object
|
|
*/
|
|
private static $cacheLib;
|
|
|
|
/**
|
|
* Holds debug info
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $debugInfo = array();
|
|
|
|
/**
|
|
* Initialized flag
|
|
*
|
|
* @access private
|
|
* @var bool
|
|
*/
|
|
private static $initiated = FALSE;
|
|
|
|
/**
|
|
* Singleton instance
|
|
*
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
static public function instance()
|
|
{
|
|
if ( ! self::$instance )
|
|
{
|
|
self::$instance = new self();
|
|
self::$instance->init();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Initialize class
|
|
*
|
|
* @access private
|
|
* @return @e void
|
|
*/
|
|
private function init()
|
|
{
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
if ( self::$initiated !== TRUE )
|
|
{
|
|
//--------------------------------
|
|
// Eaccelerator...
|
|
//--------------------------------
|
|
|
|
if( function_exists('eaccelerator_get') AND ipsRegistry::$settings['use_eaccelerator'] == 1 )
|
|
{
|
|
require IPS_KERNEL_PATH.'interfaces/interfaceCache.php';/*noLibHook*/
|
|
require IPS_KERNEL_PATH.'classCacheEaccelerator.php';/*noLibHook*/
|
|
self::$cacheLib = new classCacheEaccelerator( ipsRegistry::$settings['board_url'] );
|
|
}
|
|
|
|
//--------------------------------
|
|
// Memcache
|
|
//--------------------------------
|
|
|
|
else if( function_exists('memcache_connect') AND ipsRegistry::$settings['use_memcache'] == 1 )
|
|
{
|
|
require IPS_KERNEL_PATH.'interfaces/interfaceCache.php';/*noLibHook*/
|
|
require IPS_KERNEL_PATH.'classCacheMemcache.php';/*noLibHook*/
|
|
self::$cacheLib = new classCacheMemcache( ipsRegistry::$settings['board_url'], ipsRegistry::$settings );
|
|
}
|
|
|
|
//--------------------------------
|
|
// XCache...
|
|
//--------------------------------
|
|
|
|
else if( function_exists('xcache_get') AND ipsRegistry::$settings['use_xcache'] == 1 )
|
|
{
|
|
require IPS_KERNEL_PATH.'interfaces/interfaceCache.php';/*noLibHook*/
|
|
require IPS_KERNEL_PATH.'classCacheXcache.php';/*noLibHook*/
|
|
self::$cacheLib = new classCacheXcache( ipsRegistry::$settings['board_url'] );
|
|
}
|
|
|
|
//--------------------------------
|
|
// APC...
|
|
//--------------------------------
|
|
|
|
else if( function_exists('apc_fetch') AND ipsRegistry::$settings['use_apc'] == 1 )
|
|
{
|
|
require IPS_KERNEL_PATH.'interfaces/interfaceCache.php';/*noLibHook*/
|
|
require IPS_KERNEL_PATH.'classCacheApc.php';/*noLibHook*/
|
|
self::$cacheLib = new classCacheApc( ipsRegistry::$settings['board_url'] );
|
|
}
|
|
|
|
//--------------------------------
|
|
// Diskcache
|
|
//--------------------------------
|
|
|
|
else if( ipsRegistry::$settings['use_diskcache'] == 1 )
|
|
{
|
|
require IPS_KERNEL_PATH.'interfaces/interfaceCache.php';/*noLibHook*/
|
|
require IPS_KERNEL_PATH.'classCacheDiskcache.php';/*noLibHook*/
|
|
self::$cacheLib = new classCacheDiskcache( ipsRegistry::$settings['board_url'] );
|
|
}
|
|
|
|
if( is_object(self::$cacheLib) AND self::$cacheLib->crashed )
|
|
{
|
|
// There was a problem - not installed maybe?
|
|
self::$cacheLib = NULL;
|
|
}
|
|
|
|
$caches = array();
|
|
$_caches = array();
|
|
$_load = array();
|
|
$_pre_load = IPSDebug::getMemoryDebugFlag();
|
|
|
|
//-----------------------------------------
|
|
// Get default cache list
|
|
//-----------------------------------------
|
|
|
|
$CACHE = ipsRegistry::_fetchCoreVariables( 'cache' );
|
|
$_LOAD = ipsRegistry::_fetchCoreVariables( 'cacheload' );
|
|
|
|
if ( is_array( $CACHE ) )
|
|
{
|
|
foreach( $CACHE as $key => $data )
|
|
{
|
|
if ( isset($data['acp_only']) AND $data['acp_only'] AND IPS_AREA != 'admin' )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$_caches[ $key ] = $CACHE;
|
|
|
|
if ( $data['default_load'] )
|
|
{
|
|
$caches[ $key ] = $key;
|
|
}
|
|
}
|
|
|
|
if( count($_LOAD) )
|
|
{
|
|
foreach( $_LOAD as $key => $one )
|
|
{
|
|
$_load[ $key ] = $key;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Get application cache list
|
|
//-----------------------------------------
|
|
|
|
if ( IPS_APP_COMPONENT )
|
|
{
|
|
$CACHE = ipsRegistry::_fetchAppCoreVariables( IPS_APP_COMPONENT, 'cache' );
|
|
$_LOAD = ipsRegistry::_fetchAppCoreVariables( IPS_APP_COMPONENT, 'cacheload' );
|
|
|
|
if ( is_array( $CACHE ) )
|
|
{
|
|
foreach( $CACHE as $key => $data )
|
|
{
|
|
if ( isset( $data['acp_only'] ) && $data['acp_only'] AND IPS_AREA != 'admin' )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$_caches[ $key ] = $CACHE;
|
|
|
|
if ( $data['default_load'] )
|
|
{
|
|
$caches[ $key ] = $key;
|
|
}
|
|
}
|
|
|
|
if( count($_LOAD) )
|
|
{
|
|
foreach( $_LOAD as $key => $one )
|
|
{
|
|
$_load[ $key ] = $key;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( is_array($_load) AND count($_load) )
|
|
{
|
|
foreach( $_load as $key )
|
|
{
|
|
$caches[ $key ] = $key;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Load 'em
|
|
//-----------------------------------------
|
|
|
|
self::_loadCaches( $caches );
|
|
|
|
}
|
|
|
|
self::$initiated = TRUE;
|
|
}
|
|
else
|
|
{
|
|
self::$initiated = TRUE;
|
|
self::instance()->data_store = array();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load cache(s)
|
|
*
|
|
* @param array Array of caches to load: array( 'group_cache', 'forum_cache' )
|
|
* @return mixed Loaded Cache
|
|
* @access private
|
|
* @author MattMecham
|
|
*/
|
|
private static function _loadCaches( $caches=array() )
|
|
{
|
|
if ( ! is_array( $caches ) OR ! count( $caches ) )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Finalize
|
|
//-----------------------------------------
|
|
|
|
$cachelist = "'".implode( "','", $caches )."'";
|
|
|
|
//--------------------------------
|
|
// Eaccelerator...
|
|
//--------------------------------
|
|
|
|
if ( is_object( self::$cacheLib ) )
|
|
{
|
|
$temp_cache = array();
|
|
$new_cache_array = array();
|
|
|
|
foreach( $caches as $key )
|
|
{
|
|
$temp_cache[$key] = self::$cacheLib->getFromCache( $key );
|
|
|
|
if ( ! $temp_cache[$key] )
|
|
{
|
|
$new_cache_array[] = $key;
|
|
}
|
|
else
|
|
{
|
|
if ( is_string($temp_cache[$key]) AND strstr( $temp_cache[$key], "a:" ) !== false )
|
|
{
|
|
self::instance()->data_store[ $key ] = unserialize( $temp_cache[$key] );
|
|
}
|
|
else if( $temp_cache[$key] == "EMPTY" )
|
|
{
|
|
self::instance()->data_store[ $key ] = NULL;
|
|
}
|
|
else
|
|
{
|
|
self::instance()->data_store[ $key ] = $temp_cache[$key];
|
|
}
|
|
}
|
|
}
|
|
|
|
$cachearray = $new_cache_array;
|
|
|
|
unset($new_cache_array, $temp_cache);
|
|
}
|
|
|
|
//--------------------------------
|
|
// Get from DB...
|
|
//--------------------------------
|
|
|
|
if ( $cachelist )
|
|
{
|
|
/* This is here for veeeeeery old 1.0.1 upgrades */
|
|
if( !ipsRegistry::DB()->checkForTable('cache_store') )
|
|
{
|
|
ipsRegistry::DB()->query( "create table ".ipsRegistry::dbFunctions()->getPrefix()."cache_store (
|
|
cs_key varchar(255) NOT NULL default '',
|
|
cs_value text NULL,
|
|
cs_extra varchar(255) NOT NULL default '',
|
|
PRIMARY KEY(cs_key)
|
|
);" );
|
|
}
|
|
|
|
ipsRegistry::DB()->build( array( 'select' => '*', 'from' => 'cache_store', 'where' => "cs_key IN ( $cachelist )" ) );
|
|
ipsRegistry::DB()->execute();
|
|
|
|
$_seenKeys = array();
|
|
|
|
while ( $r = ipsRegistry::DB()->fetch() )
|
|
{
|
|
$_seenKeys[ $r['cs_key'] ] = $r['cs_key'];
|
|
|
|
self::instance()->debugInfo[ $r['cs_key'] ] = array( 'size' => IPSLib::strlenToBytes( strlen($r['cs_value']) ) );
|
|
|
|
if ( $r['cs_array'] OR substr( $r['cs_value'], 0, 2 ) == "a:" )
|
|
{
|
|
self::instance()->data_store[ $r['cs_key'] ] = unserialize( $r['cs_value'] );
|
|
|
|
if ( ! is_array( self::instance()->data_store[ $r['cs_key'] ] ) )
|
|
{
|
|
self::instance()->data_store[ $r['cs_key'] ] = array();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self::instance()->data_store[ $r['cs_key'] ] = ( $r['cs_value'] ) ? $r['cs_value'] : NULL;
|
|
}
|
|
|
|
if ( is_object( self::$cacheLib ) )
|
|
{
|
|
if ( ! $r['cs_value'] )
|
|
{
|
|
$r['cs_value'] = "EMPTY";
|
|
}
|
|
|
|
self::$cacheLib->putInCache( $r['cs_key'], $r['cs_value'] );
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Make sure each key is in data_store otherwise
|
|
// repeated calls will keep trying to load it
|
|
//-----------------------------------------
|
|
|
|
foreach( $caches as $_cache )
|
|
{
|
|
if ( ! in_array( $_cache, $_seenKeys ) )
|
|
{
|
|
self::instance()->data_store[ $_cache ] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set a cache
|
|
*
|
|
* @access protected
|
|
* @param string Cache Key
|
|
* @param mixed Cache value (typically an array)
|
|
* @return @e void
|
|
*/
|
|
protected function cacheSet( $key, $val )
|
|
{
|
|
/* Update in_memory cache */
|
|
$this->data_store[ $key ] = $val;
|
|
|
|
$this->save_options['donow'] = isset($this->save_options['donow']) ? $this->save_options['donow'] : 0;
|
|
|
|
//-----------------------------------------
|
|
// Next...
|
|
//-----------------------------------------
|
|
|
|
if ( $key )
|
|
{
|
|
if ( ! isset($val) OR ! $val )
|
|
{
|
|
if ( isset($this->save_options['array']) AND $this->save_options['array'] )
|
|
{
|
|
$value = serialize($this->data_store[ $key ]);
|
|
}
|
|
else
|
|
{
|
|
$value = $this->data_store[ $key ];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( isset($this->save_options['array']) AND $this->save_options['array'] )
|
|
{
|
|
$value = serialize($val);
|
|
}
|
|
else
|
|
{
|
|
$value = $val;
|
|
}
|
|
}
|
|
|
|
ipsRegistry::DB()->preventAddSlashes( array( 'cs_key' => 1 ) );
|
|
|
|
if ( $this->save_options['donow'] )
|
|
{
|
|
ipsRegistry::DB()->replace( 'cache_store', array( 'cs_array' => intval($this->save_options['array']), 'cs_key' => $key, 'cs_value' => $value, 'cs_updated' => time() ), array( 'cs_key' ) );
|
|
}
|
|
else
|
|
{
|
|
ipsRegistry::DB()->replace( 'cache_store', array( 'cs_array' => intval($this->save_options['array']), 'cs_key' => $key, 'cs_value' => $value, 'cs_updated' => time() ), array( 'cs_key' ), true );
|
|
}
|
|
}
|
|
|
|
/* Reest... */
|
|
$this->save_options = array();
|
|
}
|
|
|
|
/**
|
|
* Check to see if the cache exists or not
|
|
*
|
|
* @access public
|
|
* @param string Cache name
|
|
* @return boolean
|
|
*/
|
|
static public function exists( $key )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* Override the get() ArrayAccess method for the cache lib
|
|
* The default method just pulls from data_store, but the cache library can dynamically load caches, so we need
|
|
* to properly use getCache so the cache is loaded if it's not already
|
|
*
|
|
* @access protected
|
|
* @param mixed $key
|
|
* @return string
|
|
*/
|
|
protected function get( $key )
|
|
{
|
|
if ( ! in_array( $key, array_keys( self::instance()->data_store ) ) )
|
|
{
|
|
$cache = self::instance()->getCache( $key );
|
|
}
|
|
else
|
|
{
|
|
$cache = self::instance()->data_store[ $key ];
|
|
}
|
|
|
|
return $cache;
|
|
}
|
|
|
|
/**
|
|
* Get the cache
|
|
* If the cache has not been loaded during init(), then it'll load the
|
|
* cache.
|
|
*
|
|
* @access public
|
|
* @param string Cache key
|
|
* @param mixed The loaded cache [typically an array]
|
|
* @return string
|
|
*/
|
|
static public function getCache( $key )
|
|
{
|
|
if ( ! in_array( $key, array_keys( self::instance()->data_store ) ) )
|
|
{
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
self::_loadCaches( array( $key ) );
|
|
}
|
|
|
|
$cache = self::instance()->data_store[ $key ];
|
|
}
|
|
else
|
|
{
|
|
$cache = self::instance()->data_store[ $key ];
|
|
}
|
|
|
|
return $cache;
|
|
}
|
|
|
|
/**
|
|
* Fetch all the caches as a reference
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
static public function &fetchCaches()
|
|
{
|
|
return self::instance()->data_store;
|
|
}
|
|
|
|
/**
|
|
* Update a cache temporarily (do not save to db)
|
|
*
|
|
* @access public
|
|
* @param string Cache key
|
|
* @param mixed Cache value
|
|
* @return @e void
|
|
*/
|
|
static public function updateCacheWithoutSaving( $key, $value )
|
|
{
|
|
self::instance()->data_store[ $key ] = $value;
|
|
}
|
|
|
|
/**
|
|
* Update a cache permanantly (save to db)
|
|
*
|
|
* @access public
|
|
* @param string Cache key
|
|
* @param mixed Cache value
|
|
* @param array Options
|
|
* @return mixed
|
|
*/
|
|
static public function setCache( $key, $value, $options=array() )
|
|
{
|
|
if ( ! $key )
|
|
{
|
|
throw new Exception( "Key missing in setCache" );
|
|
}
|
|
|
|
self::instance()->save_options = $options;
|
|
return self::instance()->cacheSet( $key, $value );
|
|
}
|
|
|
|
/**
|
|
* Store into cache library
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @param mixed Item to cache
|
|
* @param int Time to live
|
|
* @return mixed
|
|
*/
|
|
static public function putWithCacheLib( $key, $value, $ttl=0 )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Rebuild a cache
|
|
*
|
|
* @access public
|
|
* @param string Cache key
|
|
* @param string Application
|
|
* @return @e void
|
|
*/
|
|
static public function rebuildCache( $key, $app='' )
|
|
{
|
|
/* INIT */
|
|
$app = IPSText::alphanumericalClean( $app );
|
|
$_caches = array();
|
|
|
|
if( $app )
|
|
{
|
|
if ( $app == 'global' )
|
|
{
|
|
$_caches = ipsRegistry::_fetchCoreVariables( 'cache' );
|
|
}
|
|
else
|
|
{
|
|
/* isset there is needed to prevent issues on applications installation */
|
|
if( isset( ipsRegistry::$applications[$app] ) && !IPSLib::appIsInstalled($app) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
$_caches = ipsRegistry::_fetchAppCoreVariables( $app, 'cache' );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Get all caches from all apps */
|
|
$_caches = ipsRegistry::_fetchCoreVariables( 'cache' );
|
|
|
|
foreach( ipsRegistry::$applications as $appDir => $appData )
|
|
{
|
|
$CACHE = ipsRegistry::_fetchAppCoreVariables( $appDir, 'cache' );
|
|
|
|
if ( is_array( $CACHE ) )
|
|
{
|
|
$_caches = array_merge( $_caches, $CACHE );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Rebuild the cache, if found */
|
|
if( isset( $_caches[ $key ] ) )
|
|
{
|
|
$file_to_check = $_caches[ $key ]['recache_file'];
|
|
|
|
if ( $file_to_check AND is_file( $file_to_check ) )
|
|
{
|
|
$_func = $_caches[ $key ]['recache_function'];
|
|
|
|
/* Hackish way to check for action overloader */
|
|
if ( strpos( $file_to_check, '/modules_' ) !== FALSE )
|
|
{
|
|
$_class = IPSLib::loadActionOverloader( $file_to_check, $_caches[ $key ]['recache_class'] );
|
|
}
|
|
elseif ( $app )
|
|
{
|
|
$_class = IPSLib::loadLibrary( $file_to_check, $_caches[ $key ]['recache_class'], ($app == 'global') ? 'core' : $app );
|
|
}
|
|
|
|
/* Fallback */
|
|
if ( !$_class )
|
|
{
|
|
$_class = $_caches[ $key ]['recache_class'];
|
|
}
|
|
|
|
$recache = new $_class( ipsRegistry::instance() );
|
|
|
|
if( method_exists( $recache, 'makeRegistryShortcuts' ) )
|
|
{
|
|
$recache->makeRegistryShortcuts( ipsRegistry::instance() );
|
|
}
|
|
|
|
$recache->$_func();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a cache from DB and alt cache store
|
|
*
|
|
* @param mixed Cache key, or array of cache keys
|
|
* @return @e boolean
|
|
*/
|
|
static public function deleteCache( $keys )
|
|
{
|
|
if ( is_string( $keys ) )
|
|
{
|
|
ipsRegistry::DB()->delete( 'cache_store', "cs_key='{$keys}'" );
|
|
|
|
if ( is_object( self::$cacheLib ) )
|
|
{
|
|
self::$cacheLib->removeFromCache( $keys );
|
|
}
|
|
}
|
|
elseif ( is_array( $keys ) && count( $keys ) )
|
|
{
|
|
ipsRegistry::DB()->delete( 'cache_store', "cs_key IN('" . implode( "','", $keys ) . "')" );
|
|
|
|
if ( is_object( self::$cacheLib ) )
|
|
{
|
|
foreach( $keys as $key )
|
|
{
|
|
self::$cacheLib->removeFromCache( $keys );
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Base application class
|
|
*/
|
|
class ips_MemberRegistry extends ips_base_Registry
|
|
{
|
|
/**
|
|
* Object instance
|
|
*
|
|
* @access private
|
|
* @var object
|
|
*/
|
|
private static $instance;
|
|
|
|
/**
|
|
* Settings
|
|
*
|
|
* @access private
|
|
* @var array
|
|
*/
|
|
private $settings = array();
|
|
|
|
/**
|
|
* Member data
|
|
*
|
|
* @access protected
|
|
* @var array
|
|
*/
|
|
protected static $member = array();
|
|
|
|
/**
|
|
* Member id
|
|
*
|
|
* @access public
|
|
* @var int
|
|
*/
|
|
public $member_id = 0;
|
|
|
|
/**
|
|
* Perm mask id
|
|
*
|
|
* @access public
|
|
* @var int
|
|
*/
|
|
public $perm_id = 0;
|
|
|
|
/**
|
|
* Array of perm mask ids
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $perm_id_array = array();
|
|
|
|
/**
|
|
* Hash to use in forms
|
|
*
|
|
* @access public
|
|
* @var string
|
|
*/
|
|
public $form_hash = '';
|
|
|
|
/**
|
|
* Language pack id
|
|
*
|
|
* @access public
|
|
* @var int
|
|
*/
|
|
public $language_id = '1';
|
|
|
|
/**
|
|
* Skin id
|
|
*
|
|
* @access public
|
|
* @var int
|
|
*/
|
|
public $skin_id = 0;
|
|
|
|
/**
|
|
* Member preferences
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $preferences = array();
|
|
|
|
/**
|
|
* Member session id
|
|
*
|
|
* @access public
|
|
* @var string
|
|
*/
|
|
public $session_id = 0;
|
|
|
|
/**
|
|
* Session type
|
|
*
|
|
* @access public
|
|
* @var string
|
|
*/
|
|
public $session_type = '';
|
|
|
|
/**
|
|
* Member IP Address
|
|
*
|
|
* @access public
|
|
* @var string
|
|
*/
|
|
public $ip_address = '';
|
|
|
|
/**
|
|
* Member last click timestamp
|
|
*
|
|
* @access public
|
|
* @var int
|
|
*/
|
|
public $last_click = 0;
|
|
|
|
/**
|
|
* Member location
|
|
*
|
|
* @access public
|
|
* @var string
|
|
*/
|
|
public $location = '';
|
|
|
|
/**
|
|
* ACP tab data
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $acp_tab_data = array();
|
|
|
|
/**
|
|
* Member user agent
|
|
*
|
|
* @access public
|
|
* @var string
|
|
*/
|
|
public $user_agent = '';
|
|
|
|
/**
|
|
* Member browser info
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $browser = array();
|
|
|
|
/**
|
|
* Member operating system
|
|
*
|
|
* @access public
|
|
* @var string
|
|
*/
|
|
public $operating_system = 'unknown';
|
|
|
|
/**
|
|
* Is this a bot?
|
|
*
|
|
* @access public
|
|
* @var bool
|
|
*/
|
|
public $is_not_human = false;
|
|
|
|
/**
|
|
* Users this member is ignoring
|
|
*
|
|
* @access public
|
|
* @var array
|
|
*/
|
|
public $ignored_users = array();
|
|
|
|
/**
|
|
* Session class
|
|
*
|
|
* @access private
|
|
* @var object
|
|
*/
|
|
private static $session_class;
|
|
|
|
/**
|
|
* Initialized yet?
|
|
*
|
|
* @access public
|
|
* @var bool
|
|
*/
|
|
private static $initiated = FALSE;
|
|
|
|
/**
|
|
* Initialize this object
|
|
*
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
static public function instance()
|
|
{
|
|
if ( ! self::$instance )
|
|
{
|
|
self::$instance = new self();
|
|
self::init();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Destructor
|
|
*
|
|
* @access public
|
|
* @return @e void
|
|
*/
|
|
public function __myDestruct()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Our singleton INIT function
|
|
*
|
|
* @access protected
|
|
* @return @e void
|
|
*/
|
|
protected static function init()
|
|
{
|
|
if ( self::$initiated !== TRUE )
|
|
{
|
|
//-----------------------------------------
|
|
// IP Address
|
|
//-----------------------------------------
|
|
|
|
if ( ipsRegistry::$settings['xforward_matching'] )
|
|
{
|
|
foreach( array_reverse( explode( ',', my_getenv('HTTP_X_FORWARDED_FOR') ) ) as $x_f )
|
|
{
|
|
$addrs[] = trim($x_f);
|
|
}
|
|
|
|
$addrs[] = my_getenv('HTTP_CLIENT_IP');
|
|
$addrs[] = my_getenv('HTTP_X_CLUSTER_CLIENT_IP');
|
|
$addrs[] = my_getenv('HTTP_PROXY_USER');
|
|
}
|
|
|
|
$addrs[] = my_getenv('REMOTE_ADDR');
|
|
|
|
//-----------------------------------------
|
|
// Do we have one yet?
|
|
//-----------------------------------------
|
|
|
|
foreach ( $addrs as $ip )
|
|
{
|
|
//-----------------------------------------
|
|
// IP v4
|
|
//-----------------------------------------
|
|
|
|
if ( IPSLib::validateIPv4( $ip ) )
|
|
{
|
|
self::instance()->ip_address = $ip;
|
|
break;
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// IP v6
|
|
//-----------------------------------------
|
|
|
|
else if ( IPSLib::validateIPv6( $ip ) )
|
|
{
|
|
self::instance()->ip_address = $ip;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Make sure we take a valid IP address
|
|
//-----------------------------------------
|
|
|
|
if ( !self::instance()->ip_address AND ! isset( $_SERVER['SHELL'] ) AND $_SERVER['SESSIONNAME'] != 'Console' )
|
|
{
|
|
print "Could not determine your IP address";
|
|
exit();
|
|
}
|
|
|
|
if ( IPS_IS_UPGRADER )
|
|
{
|
|
require_once( IPS_ROOT_PATH . "setup/sources/classes/session/sessions.php" );/*noLibHook*/
|
|
|
|
self::$session_class = new sessions();
|
|
}
|
|
else
|
|
{
|
|
self::setMember(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Interface to session class
|
|
*
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
public static function sessionClass()
|
|
{
|
|
return self::$session_class;
|
|
}
|
|
|
|
/**
|
|
* Get a member property
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @return mixed Member property
|
|
*/
|
|
static public function getProperty( $key )
|
|
{
|
|
return self::instance()->get( $key );
|
|
}
|
|
|
|
/**
|
|
* Set a member property
|
|
*
|
|
* @access public
|
|
* @param string Key
|
|
* @param mixed Value
|
|
* @return @e void
|
|
*/
|
|
static public function setProperty( $key, $value )
|
|
{
|
|
return self::instance()->set( $key, $value );
|
|
}
|
|
|
|
/**
|
|
* Fetch all the member data as a reference
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
static public function &fetchMemberData()
|
|
{
|
|
return self::instance()->data_store;
|
|
}
|
|
|
|
/**
|
|
* Set current member to the member ID specified
|
|
*
|
|
* @param integer Member ID
|
|
* @return @e void
|
|
*/
|
|
static public function setMember( $member_id )
|
|
{
|
|
//-----------------------------------------
|
|
// INIT
|
|
//-----------------------------------------
|
|
|
|
$member_id = intval( $member_id );
|
|
$addrs = array();
|
|
|
|
//-----------------------------------------
|
|
// If we have a member ID, set up the member
|
|
//-----------------------------------------
|
|
|
|
if ( $member_id )
|
|
{
|
|
self::instance()->data_store = IPSMember::load( $member_id, 'extendedProfile,customFields,groups,itemMarkingStorage' );
|
|
}
|
|
|
|
/* Got a member ID? */
|
|
if ( !empty($member_id) && self::instance()->data_store['member_id'] )
|
|
{
|
|
self::setUpMember();
|
|
|
|
# Form hash
|
|
self::instance()->form_hash = md5( self::instance()->data_store['email'].'&'.self::instance()->data_store['member_login_key'].'&'.self::instance()->data_store['joined'] );
|
|
}
|
|
else
|
|
{
|
|
self::instance()->data_store = IPSMember::setUpGuest();
|
|
|
|
self::instance()->perm_id = !empty(self::instance()->data_store['org_perm_id']) ? self::instance()->data_store['org_perm_id'] : self::instance()->data_store['g_perm_id'];
|
|
self::instance()->perm_id_array = explode( ',', self::instance()->perm_id );
|
|
|
|
# Form hash
|
|
self::instance()->form_hash = md5("this is only here to prevent it breaking on guests");
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Set member data
|
|
//-----------------------------------------
|
|
|
|
self::instance()->member_id = $member_id;
|
|
}
|
|
|
|
/**
|
|
* Set up a member's perms based on secondary groups
|
|
*
|
|
* @access public
|
|
* @param array Member data
|
|
* @return array New member data
|
|
*/
|
|
static public function setUpSecondaryGroups( $data )
|
|
{
|
|
if ( isset($data['mgroup_others']) AND $data['mgroup_others'] )
|
|
{
|
|
$cache = ipsRegistry::cache()->getCache('group_cache');
|
|
$groups_id = explode( ',', $data['mgroup_others'] );
|
|
$exclude = array( 'g_title', 'g_icon', 'prefix', 'suffix', 'g_promotion', 'g_photo_max_vars' );
|
|
$less_is_more = array( 'g_search_flood' );
|
|
$zero_is_best = array( 'g_attach_max', 'g_attach_per_post', 'g_edit_cutoff', 'g_max_messages' );
|
|
|
|
# Blog
|
|
$zero_is_best = array_merge( $zero_is_best, array( 'g_blog_attach_max', 'g_blog_attach_per_entry', 'g_blog_preventpublish' ) );
|
|
|
|
# Gallery
|
|
$zero_is_best = array_merge( $zero_is_best, array( 'g_max_diskspace', 'g_max_upload', 'g_max_transfer', 'g_max_views', 'g_album_limit', 'g_img_album_limit', 'g_movie_size' ) );
|
|
|
|
if ( count( $groups_id ) )
|
|
{
|
|
foreach( $groups_id as $pid )
|
|
{
|
|
if ( ! isset($cache[ $pid ]['g_id']) OR ! $cache[ $pid ]['g_id'] )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Loop through and mix
|
|
//-----------------------------------------
|
|
|
|
foreach( $cache[ $pid ] as $k => $v )
|
|
{
|
|
if ( ! in_array( $k, $exclude ) )
|
|
{
|
|
//-----------------------------------------
|
|
// Add to perm id list
|
|
//-----------------------------------------
|
|
|
|
if ( $k == 'g_perm_id' )
|
|
{
|
|
$data['g_perm_id'] .= ','.$v;
|
|
}
|
|
else if ( in_array( $k, $zero_is_best ) )
|
|
{
|
|
if ( $data[ $k ] == 0 )
|
|
{
|
|
continue;
|
|
}
|
|
else if( $v == 0 )
|
|
{
|
|
$data[ $k ] = 0;
|
|
}
|
|
else if ( $v > $data[ $k ] )
|
|
{
|
|
$data[ $k ] = $v;
|
|
}
|
|
}
|
|
else if ( in_array( $k, $less_is_more ) )
|
|
{
|
|
if ( $v < $data[ $k ] )
|
|
{
|
|
$data[ $k ] = $v;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( $v > $data[ $k ] )
|
|
{
|
|
$data[ $k ] = $v;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------
|
|
// Tidy perms_id
|
|
//-----------------------------------------
|
|
|
|
$rmp = array();
|
|
$tmp = explode( ',', IPSText::cleanPermString($data['g_perm_id']) );
|
|
|
|
if ( count( $tmp ) )
|
|
{
|
|
foreach( $tmp as $t )
|
|
{
|
|
$rmp[ $t ] = $t;
|
|
}
|
|
}
|
|
|
|
if ( count( $rmp ) )
|
|
{
|
|
$data['g_perm_id'] = implode( ',', $rmp );
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Set up a member
|
|
*
|
|
* @access private
|
|
* @return @e void
|
|
*/
|
|
static public function setUpMember()
|
|
{
|
|
//-----------------------------------------
|
|
// INIT
|
|
//-----------------------------------------
|
|
|
|
$cache = ipsRegistry::cache()->getCache('group_cache');
|
|
|
|
//-----------------------------------------
|
|
// Set up main 'display' group
|
|
//-----------------------------------------
|
|
|
|
self::instance()->data_store = is_array($cache[ self::instance()->data_store['member_group_id'] ]) ? array_merge( self::instance()->data_store, $cache[ self::instance()->data_store['member_group_id'] ] ) : self::instance()->data_store;
|
|
|
|
//-----------------------------------------
|
|
// Work out permissions
|
|
//-----------------------------------------
|
|
|
|
self::instance()->data_store = self::instance()->setUpSecondaryGroups( self::instance()->data_store );
|
|
|
|
self::instance()->perm_id = ( isset(self::instance()->data_store['org_perm_id']) AND self::instance()->data_store['org_perm_id'] ) ? self::instance()->data_store['org_perm_id'] : self::instance()->data_store['g_perm_id'];
|
|
self::instance()->perm_id_array = explode( ",", self::instance()->perm_id );
|
|
}
|
|
} |