Version 4.1.19

This commit is contained in:
Neo committed 2025-12-19 05:38:56 -08:00
1 parent 28bd025b35
commit 2bd5025018
2674 files changed
+233518 -77766

No files matched your search

+179 -149
View File
@@ -2,9 +2,9 @@
/**
* @brief Front-end Dispatcher
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 18 Feb 2013
* @version SVN_VERSION_NUMBER
*/
@@ -53,10 +53,7 @@ class _Front extends \IPS\Dispatcher\Standard
/* Get cached page if available */
$this->checkCached();
/* Perform some legacy URL conversions*/
static::convertLegacyParameters();
/* Sync stuff when in developer mode */
if ( \IPS\IN_DEV )
{
@@ -69,91 +66,27 @@ class _Front extends \IPS\Dispatcher\Standard
/* Base JS */
static::baseJs();
/* FURLs only apply when calling to index.php */
$_calledScript = str_replace( '\\', '/', $_SERVER['SCRIPT_FILENAME'] );
$_scriptParts = explode( '/', $_calledScript );
array_pop( $_scriptParts );
$_calledScript = implode( '/', $_scriptParts );
/* If script_filename was /index.php then calledscript will be empty */
if( $_calledScript === '' )
/* Check friendly URL and whether it is correct */
try
{
$_calledScript = '/';
$this->checkUrl();
}
/* Handle friendly URLs */
if ( \IPS\Settings::i()->use_friendly_urls and $_calledScript == str_replace( '\\', '/', \IPS\ROOT_PATH ) )
catch( \OutOfRangeException $e )
{
try
/* Display a 404 */
$this->application = \IPS\Application::load('core');
$this->setDefaultModule();
if ( \IPS\Member::loggedIn()->isBanned() )
{
try
{
foreach ( \IPS\Request::i()->url()->getFriendlyUrlData( \IPS\Settings::i()->seo_r_on and !\IPS\Request::i()->isAjax() and mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and !\IPS\ENFORCE_ACCESS ) as $k => $v )
{
if( $k == 'module' )
{
$this->_module = NULL;
}
else if( $k == 'controller' )
{
$this->_controller = NULL;
}
\IPS\Request::i()->$k = $v;
}
}
catch ( \OutOfRangeException $e )
{
if( \IPS\Settings::i()->seo_r_on and !\IPS\Request::i()->isAjax() and mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and !\IPS\ENFORCE_ACCESS )
{
$defaultApplication = \IPS\Db::i()->select( 'app_directory', 'core_applications', 'app_default=1' )->first();
$furlDefinitionFile = \IPS\ROOT_PATH . "/applications/{$defaultApplication}/data/furl.json";
if ( file_exists( $furlDefinitionFile ) )
{
$furlDefinition = json_decode( preg_replace( '/\/\*.+?\*\//s', '', file_get_contents( $furlDefinitionFile ) ), TRUE );
if ( isset( $furlDefinition['topLevel'] ) and $furlDefinition['topLevel'] )
{
$baseUrl = parse_url( \IPS\Settings::i()->base_url );
$url = \IPS\Request::i()->url();
$query = \IPS\Settings::i()->htaccess_mod_rewrite ? ( isset( $url->data['path'] ) ? $url->data['path'] : '' ) : ( isset( $url->data['query'] ) ? ltrim( $url->data['query'], '/' ) : '' );
$query = preg_replace( '#^(' . preg_quote( rtrim( $baseUrl['path'], '/' ), '#' ) . ')/(index.php)?(?:(?:\?/|\?))?(.+?)?$#', '$3', $query );
if ( mb_substr( $query, 0, mb_strlen( $furlDefinition['topLevel'] ) ) === $furlDefinition['topLevel'] )
{
$target = preg_replace( '/(' . preg_quote( \IPS\Settings::i()->base_url, '/' ) . '(index.php\?\/)?)(' . preg_quote( $furlDefinition['topLevel'], '/' ) . ')\/?/', '$1', (string) $url );
\IPS\Output::i()->redirect( new \IPS\Http\Url( $target ) );
}
}
}
}
if ( !\IPS\Request::i()->isAjax() )
{
throw $e;
}
}
catch ( \DomainException $e )
{
\IPS\Output::i()->redirect( $e->getMessage() );
}
}
catch ( \Exception $e )
{
$this->application = \IPS\Application::load('core');
$this->setDefaultModule();
if ( \IPS\Member::loggedIn()->isBanned() )
{
\IPS\Output::i()->sidebar = FALSE;
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
}
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'app.js' ) );
\IPS\Output::i()->error( 'requested_route_404', '1S160/2', 404, '' );
\IPS\Output::i()->sidebar = FALSE;
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
}
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'app.js' ) );
\IPS\Output::i()->error( 'requested_route_404', '1S160/2', 404, '' );
}
/* Perform some legacy URL conversions*/
static::convertLegacyParameters();
/* Run global init */
try
@@ -177,8 +110,17 @@ class _Front extends \IPS\Dispatcher\Standard
/* Enable sidebar by default (controllers can turn it off if needed) */
\IPS\Output::i()->sidebar['enabled'] = ( \IPS\Request::i()->isAjax() ) ? FALSE : TRUE;
/* Add in RSS Feeds */
foreach( \IPS\core\Rss::getAllFeeds() AS $feed_id => $feed )
{
if ( $feed->groups == '*' OR \IPS\Member::loggedIn()->inGroup( $feed->groups ) )
{
\IPS\Output::i()->rssFeeds[ $feed->_title ] = $feed->url();
}
}
/* Are we online? */
if ( !( $this->application->directory == 'core' and $this->module->key == 'system' and ( $this->controller == 'login' /* Because you can login when offline */ or $this->controller == 'embed' /* Because the offline message can contain embedded media */ or $this->controller == 'lostpass' or $this->controller == 'register' ) ) AND !\IPS\Settings::i()->site_online AND $this->controllerLocation == 'front' AND !\IPS\Member::loggedIn()->group['g_access_offline'] )
if ( !\IPS\Settings::i()->site_online and !\IPS\Member::loggedIn()->group['g_access_offline'] and $this->controllerLocation == 'front' and !$this->application->allowOfflineAccess( $this->module, $this->controller, \IPS\Request::i()->do ) )
{
if ( \IPS\Request::i()->isAjax() )
{
@@ -206,41 +148,66 @@ class _Front extends \IPS\Dispatcher\Standard
}
else
{
\IPS\Output::i()->sidebar = FALSE;
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
if( $this->controller !== 'contact' )
if( !in_array( $this->controller, array( 'contact', 'warnings' ) ) )
{
$message = 'member_banned';
if ( !$ipBanned and $banEnd instanceof \IPS\DateTime )
{
$message = \IPS\Member::loggedIn()->language()->addToStack( 'member_banned_temp', FALSE, array( 'htmlsprintf' => array( $banEnd->html() ) ) );
}
\IPS\Output::i()->error( $message, '2S160/4', 403, '' );
\IPS\Output::i()->showBanned();
}
}
}
/* Do we need more info from the member or do they need to validate? */
if( \IPS\Member::loggedIn()->member_id )
if( \IPS\Member::loggedIn()->member_id and $this->controller !== 'language' and $this->controller !== 'theme' )
{
/* Need their name or email... */
if( ( !\IPS\Member::loggedIn()->real_name or !\IPS\Member::loggedIn()->email ) and $this->controller !== 'register' )
if( ( \IPS\Member::loggedIn()->real_name === '' or !\IPS\Member::loggedIn()->email ) and $this->controller !== 'register' )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=complete' ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=complete' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
}
/* Need them to validate... */
elseif( \IPS\Member::loggedIn()->members_bitoptions['validating'] and $this->controller !== 'register' and $this->controller !== 'login' and $this->controller != 'redirect' and $this->controller !== 'contact' )
elseif( \IPS\Member::loggedIn()->members_bitoptions['validating'] and $this->controller !== 'register' and $this->controller !== 'login' and $this->controller != 'redirect' and $this->controller !== 'contact' and $this->controller !== 'privacy' )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=validating', 'front', 'register' ) );
}
/* Need them to reconfirm terms/privacy policy */
elseif ( ( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_privacy'] or \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] ) and $this->controller !== 'register' )
/* Need them to reconfirm terms/privacy policy... */
elseif ( ( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_privacy'] or \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] ) and $this->controller !== 'register' and $this->controller !== 'ajax' )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=reconfirm', 'front', 'register' ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=reconfirm', 'front', 'register' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
}
/* Need to set up MFA... */
elseif ( !in_array( $this->controller, array( 'register', 'login', 'redirect', 'contact', 'privacy', 'ajax', 'settings' ) ) )
{
$haveAcceptableHandlers = FALSE;
$haveConfiguredHandler = FALSE;
foreach ( \IPS\MFA\MFAHandler::handlers() as $key => $handler )
{
if ( $handler->isEnabled() and $handler->memberCanUseHandler( \IPS\Member::loggedIn() ) )
{
$haveAcceptableHandlers = TRUE;
if ( $handler->memberHasConfiguredHandler( \IPS\Member::loggedIn() ) )
{
$haveConfiguredHandler = TRUE;
break;
}
}
}
if ( !$haveConfiguredHandler and $haveAcceptableHandlers )
{
if ( \IPS\Settings::i()->mfa_required_groups == '*' or \IPS\Member::loggedIn()->inGroup( explode( ',', \IPS\Settings::i()->mfa_required_groups ) ) )
{
if ( \IPS\Settings::i()->mfa_required_prompt === 'immediate' )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&do=initialMfa', 'front', 'settings' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
}
}
elseif ( \IPS\Settings::i()->mfa_optional_prompt === 'immediate' and !\IPS\Member::loggedIn()->members_bitoptions['security_questions_opt_out'] )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&do=initialMfa', 'front', 'settings' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
}
}
}
}
/* Permission Check */
@@ -269,7 +236,7 @@ class _Front extends \IPS\Dispatcher\Standard
if ( $this->module->key != 'system' AND $this->application->directory != $defaultApplication )
{
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=' . $this->application->directory . '&module=' . $this->module->key . '&controller=' . $this->module->default_controller, 'front', $this->module->key ), $this->module->_title );
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=' . $this->application->directory . '&module=' . $this->module->key . '&controller=' . $this->module->default_controller, 'front', array_key_exists( $this->module->key, \IPS\Http\Url::furlDefinition() ) ? $this->module->key : NULL ), $this->module->_title );
}
/* Figure out what the global search is */
@@ -282,7 +249,7 @@ class _Front extends \IPS\Dispatcher\Standard
$classes = $object->classes;
foreach ( $classes as $class )
{
if ( is_subclass_of( $class, 'IPS\Content\Searchable' ) and $class::$includeInSiteSearch )
if ( is_subclass_of( $class, 'IPS\Content\Searchable' ) and $class::includeInSiteSearch() )
{
$type = mb_strtolower( str_replace( '\\', '_', mb_substr( array_pop( $classes ), 4 ) ) );
\IPS\Output::i()->defaultSearchOption = array( $type, "{$type}_pl" );
@@ -295,6 +262,78 @@ class _Front extends \IPS\Dispatcher\Standard
}
}
/**
* Check whether the URL we visited is correct and route appropriately
*
* @return void
*/
protected function checkUrl()
{
/* Handle friendly URLs */
if ( \IPS\Settings::i()->use_friendly_urls )
{
$url = \IPS\Request::i()->url();
/* Redirect to the "correct" friendly URL if there is one */
if ( !\IPS\Request::i()->isAjax() and mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and !\IPS\ENFORCE_ACCESS )
{
$correctUrl = NULL;
/* If it's already a friendly URL, we need to check the SEO title is valid. If it isn't, we redirect iof "Force Friendly URLs" is enabled */
if ( $url instanceof \IPS\Http\Url\Friendly or ( $url instanceof \IPS\Http\Url\Internal and \IPS\Settings::i()->seo_r_on ) )
{
$correctUrl = $url->correctFriendlyUrl();
}
/* If they are accessing "index.php/whatever", we want "index.php?/whatever */
if ( !( $correctUrl instanceof \IPS\Http\Url ) and $url instanceof \IPS\Http\Url\Internal and mb_strpos( $url->data[ \IPS\Http\Url::COMPONENT_PATH ], '/index.php/' ) !== FALSE )
{
$pathFromBaseUrl = mb_substr( $url->data[ \IPS\Http\Url::COMPONENT_PATH ], mb_strlen( \IPS\Http\Url::internal('')->data[ \IPS\Http\Url::COMPONENT_PATH ] ) );
if ( preg_match( '/index.php\//', $pathFromBaseUrl ) )
{
$correctUrl = \IPS\Http\Url\Friendly::friendlyUrlFromComponent( 0, trim( mb_substr( $pathFromBaseUrl, 10 ), '/' ), $url->queryString );
}
}
/* Redirect to the correct URL if we got one */
if ( $correctUrl instanceof \IPS\Http\Url )
{
\IPS\Output::i()->redirect( $correctUrl, NULL, 301 );
}
}
/* If the accessed URL is friendly, set the "real" query string properties */
if ( $url instanceof \IPS\Http\Url\Friendly )
{
foreach ( ( $url->queryString + $url->hiddenQueryString ) as $k => $v )
{
if( $k == 'module' )
{
$this->_module = NULL;
}
else if( $k == 'controller' )
{
$this->_controller = NULL;
}
\IPS\Request::i()->$k = $v;
}
}
/* Otherwise if it's not a recognised URL, show a 404 */
elseif ( !( $url instanceof \IPS\Http\Url\Internal ) or $url->base !== 'front' )
{
/* Call the parent first in case we need to redirect to https, and so the correct locale, etc. is set */
try
{
parent::init();
}
catch ( \Exception $e ) { }
throw new \OutOfRangeException;
}
}
}
/**
* Define that the page should load even if the user is banned and not logged in
*
@@ -313,7 +352,7 @@ class _Front extends \IPS\Dispatcher\Standard
protected function checkCached()
{
/* If this is a guest and there's a full cached page, we can serve that */
if( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and !\IPS\Session\Front::loggedIn() and !isset( \IPS\Request::i()->cookie['noCache'] ) and !\IPS\Request::i()->ipAddressIsBanned() )
if( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and !isset( \IPS\Request::i()->csrfKey ) and !isset( \IPS\Request::i()->_mfaLogin ) and !\IPS\Session\Front::loggedIn() and !isset( \IPS\Request::i()->cookie['noCache'] ) and !\IPS\Request::i()->ipAddressIsBanned() and \IPS\CACHE_PAGE_TIMEOUT )
{
/* Which language? */
if ( isset( \IPS\Request::i()->cookie['language'] ) )
@@ -337,7 +376,7 @@ class _Front extends \IPS\Dispatcher\Standard
/* Get cache */
try
{
$cache = \IPS\Data\Cache::i()->getWithExpire( 'page_' . md5( ( !empty( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'] ) . '/' . $_SERVER['REQUEST_URI'] ) . "_{$language}_{$theme}", TRUE );
$cache = \IPS\Data\Cache::i()->getWithExpire( 'page_' . md5( (int) \IPS\Request::i()->isSecure() . ( !empty( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'] ) . '/' . $_SERVER['REQUEST_URI'] ) . "_{$language}_{$theme}", TRUE );
$sessionId = isset( \IPS\Request::i()->cookie['IPSSessionFront'] ) ? \IPS\Request::i()->cookie['IPSSessionFront'] : \IPS\Session::i()->id;
\IPS\Output::i()->sendOutput( str_replace( '{{csrfKey}}', md5( '&& 0&' . $sessionId ), $cache['output'] ), $cache['code'], $cache['contentType'], $cache['httpHeaders'], FALSE, TRUE );
@@ -353,49 +392,12 @@ class _Front extends \IPS\Dispatcher\Standard
*/
public static function convertLegacyParameters()
{
/* Convert &section= to &controller= */
if ( isset( \IPS\Request::i()->section ) AND !isset( \IPS\Request::i()->controller ) )
foreach( \IPS\Application::applications() as $directory => $application )
{
\IPS\Request::i()->controller = \IPS\Request::i()->section;
}
/* Convert &showtopic= */
if ( isset( \IPS\Request::i()->showtopic ) )
{
$url = \IPS\Http\Url::internal( 'app=forums&module=forums&controller=topic&id=' . \IPS\Request::i()->showtopic );
if ( isset( \IPS\Request::i()->p ) or isset( \IPS\Request::i()->findpost ) )
if( method_exists( $application, 'convertLegacyParameters' ) )
{
$url = $url->setQueryString( array( 'do' => 'findComment', 'comment' => \IPS\Request::i()->p ?: \IPS\Request::i()->findpost ) );
$application->convertLegacyParameters();
}
elseif ( isset( \IPS\Request::i()->page ) )
{
$url = $url->setQueryString( array( 'page' => \IPS\Request::i()->page ) );
}
\IPS\Output::i()->redirect( $url );
}
/* Convert &showforum= */
if ( isset( \IPS\Request::i()->showforum ) )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=forums&module=forums&controller=forums&id=' . \IPS\Request::i()->showforum ) );
}
/* Convert &showuser= */
if ( isset( \IPS\Request::i()->showuser ) )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=members&controller=profile&id=' . \IPS\Request::i()->showuser ) );
}
/* Support legacy subscriptions */
if( isset( \IPS\Request::i()->app ) AND \IPS\Request::i()->app == 'subscriptions' )
{
/* Redirecting isn't necessary, we just need to route the payment to the appropriate area.
@see \IPS\nexus\Application */
\IPS\Request::i()->app = 'nexus';
\IPS\Request::i()->module = 'payments';
\IPS\Request::i()->section = 'receive'; /* It actually looks for section=receive, so make sure we set that */
\IPS\Request::i()->controller = 'receive'; /* We set this just to be complete in case anywhere else only looks at controller */
\IPS\Request::i()->validate = 'paypal';
}
}
@@ -475,7 +477,7 @@ class _Front extends \IPS\Dispatcher\Standard
{
$appOrPlugin = isset( $widget['plugin'] ) ? \IPS\Plugin::load( $widget['plugin'] ) : \IPS\Application::load( $widget['app'] );
if( isset( $widget['plugin'] ) and !$appOrPlugin->enabled )
if( !$appOrPlugin->enabled )
{
continue;
}
@@ -489,7 +491,7 @@ class _Front extends \IPS\Dispatcher\Standard
}
catch ( \Exception $e )
{
\IPS\Log::i( LOG_ERR )->write( $e->getMessage() );
\IPS\Log::log( $e, 'dispatcher' );
}
}
}
@@ -512,10 +514,30 @@ class _Front extends \IPS\Dispatcher\Standard
/* Meta tags */
\IPS\Output::i()->buildMetaTags();
/* Check MFA */
$this->checkMfa();
/* Finish */
parent::finish();
}
/**
* Check MFA to see if we need to supply a code
*
* @return void
*/
public function checkMfa()
{
/* MFA Login? */
if ( isset( \IPS\Request::i()->_mfaLogin ) and isset( $_SESSION['processing2FA'] ) and $member = \IPS\Member::load( $_SESSION['processing2FA']['memberId'] ) and $member->member_id )
{
if ( $output = \IPS\MFA\MFAHandler::accessToArea( 'core', 'AuthenticateFront', \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=mfa', 'front', 'login' ), $member ) )
{
\IPS\Output::i()->output .= $output;
}
}
}
/**
* Output the basic javascript files every page needs
*
@@ -593,4 +615,12 @@ class _Front extends \IPS\Dispatcher\Standard
}
}
}
function run() {
/* отслеживаем переходы */
if ( $_SERVER['HTTP_REFERER'] )
{
\IPS\core\modules\admin\promotion\seovisitors::track( $_SERVER['HTTP_REFERER'], htmlentities( $_SERVER['QUERY_STRING'], \IPS\HTMLENTITIES, 'UTF-8', FALSE ), \IPS\Member::loggedIn()->member_id );
}
parent::run();
}
}