Version 4.3.0

This commit is contained in:
Neo committed 2025-12-19 05:47:12 -08:00
1 parent 96997ddd8e
commit fe1acf984a
1349 files changed
+116159 -67711

No files matched your search

+45 -32
View File
@@ -36,17 +36,26 @@ class _Front extends \IPS\Dispatcher\Standard
{
/* Get cached page if available */
$this->checkCached();
/* Set up in progress? */
if ( isset( \IPS\Settings::i()->setup_in_progress ) AND \IPS\Settings::i()->setup_in_progress )
{
$protocol = '1.0';
if( isset( $_SERVER['SERVER_PROTOCOL'] ) and \strstr( $_SERVER['SERVER_PROTOCOL'], '/1.0' ) !== false )
{
header( "HTTP/1.0 503 Service Unavailable" );
$protocol = '1.1';
}
if ( \IPS\CIC and ! \IPS\Session\Front::loggedIn() and ! \IPS\Session\Front::i()->userAgent->spider )
{
/* The software is unavailable, but the site is up so we do not want to affect our cloud downtime statistics and trigger monitoring alarms
if we are not a search engine */
header( "HTTP/{$protocol} 200 OK" );
}
else
{
header( "HTTP/1.1 503 Service Unavailable" );
header( "HTTP/{$protocol} 503 Service Unavailable" );
header( "Retry-After: 300"); #5 minutes
}
require \IPS\ROOT_PATH . '/' . \IPS\UPGRADING_PAGE;
@@ -93,7 +102,7 @@ class _Front extends \IPS\Dispatcher\Standard
parent::init();
}
catch ( \DomainException $e )
{
{
// If this is a "no permission", and they're validating - show the validating screen instead
if( $e->getCode() === 6 and \IPS\Member::loggedIn()->member_id and \IPS\Member::loggedIn()->members_bitoptions['validating'] )
{
@@ -163,7 +172,7 @@ class _Front extends \IPS\Dispatcher\Standard
}
/* Do we need more info from the member or do they need to validate? */
if( \IPS\Member::loggedIn()->member_id and $this->controller !== 'language' and $this->controller !== 'theme' )
if( \IPS\Member::loggedIn()->member_id and $this->controller !== 'language' and $this->controller !== 'theme' and $this->controller !== 'ajax' )
{
/* Need their name or email... */
if( ( \IPS\Member::loggedIn()->real_name === '' or !\IPS\Member::loggedIn()->email ) and $this->controller !== 'register' )
@@ -181,7 +190,7 @@ class _Front extends \IPS\Dispatcher\Standard
\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() ) ) );
}
/* Have required profile actions that need completing */
else if ( !\IPS\Member::loggedIn()->members_bitoptions['profile_completed'] AND !in_array( $this->controller, array( 'register', 'login', 'redirect', 'contact', 'privacy', 'ajax', 'settings' ) ) AND $completion = \IPS\Member::loggedIn()->profileCompletion() AND count( $completion['required'] ) )
else if ( \IPS\Settings::i()->quick_register AND !\IPS\Member::loggedIn()->members_bitoptions['profile_completed'] AND !in_array( $this->controller, array( 'register', 'login', 'redirect', 'contact', 'privacy', 'ajax', 'settings' ) ) AND $completion = \IPS\Member::loggedIn()->profileCompletion() AND count( $completion['required'] ) )
{
foreach( $completion['required'] AS $id => $completed )
{
@@ -231,7 +240,7 @@ class _Front extends \IPS\Dispatcher\Standard
{
if ( !\IPS\Member::loggedIn()->member_id and isset( \IPS\Request::i()->_mfaLogin ) )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https )->setQueryString( '_mfaLogin', 1 ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->setQueryString( '_mfaLogin', 1 ) );
}
\IPS\Output::i()->error( ( \IPS\Member::loggedIn()->member_id ? 'no_module_permission' : 'no_module_permission_guest' ), '2S100/2', 403, 'no_module_permission_admin' );
}
@@ -260,21 +269,18 @@ class _Front extends \IPS\Dispatcher\Standard
}
/* Figure out what the global search is */
if ( !$this->application->default )
foreach ( $this->application->extensions( 'core', 'ContentRouter' ) as $object )
{
foreach ( $this->application->extensions( 'core', 'ContentRouter' ) as $object )
if ( count( $object->classes ) === 1 )
{
if ( count( $object->classes ) === 1 )
$classes = $object->classes;
foreach ( $classes as $class )
{
$classes = $object->classes;
foreach ( $classes as $class )
if ( is_subclass_of( $class, 'IPS\Content\Searchable' ) and $class::includeInSiteSearch() and $this->module->key == $class::$module )
{
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" );
break;
}
$type = mb_strtolower( str_replace( '\\', '_', mb_substr( array_pop( $classes ), 4 ) ) );
\IPS\Output::i()->defaultSearchOption = array( $type, "{$type}_pl" );
break;
}
}
}
@@ -371,12 +377,25 @@ class _Front extends \IPS\Dispatcher\Standard
*/
protected function checkCached()
{
/* If we are using a caching engine and Database datastore, then avoid checking cache validity because it will hit MySQL to load the cacheKeys. As this is guest caching, we accept that stale data is ok */
if ( \IPS\STORE_METHOD === 'Database' AND \IPS\CACHE_METHOD !== 'None' )
/* Store page view in Redis */
if ( \IPS\CACHE_METHOD == 'Redis' and \IPS\CIC and !\IPS\Request::i()->isAjax() )
{
\IPS\Data\Store::i()->cacheCheck = false;
try
{
if( \IPS\Redis::i() === NULL )
{
throw new \RedisException( 'Redis instance is NULL', -1 );
}
\IPS\Redis::i()->logPageHit();
}
catch( \RedisException $e )
{
/* Sometimes the connection can be reset - we don't want to let an uncaught exception bubble up in those cases */
\IPS\Log::log( $e, 'redis' );
}
}
/* If this is a guest and there's a full cached page, we can serve that */
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 )
{
@@ -408,12 +427,6 @@ class _Front extends \IPS\Dispatcher\Standard
\IPS\Output::i()->sendOutput( str_replace( '{{csrfKey}}', md5( '& 0&' . $sessionId ), $cache['output'] ), $cache['code'], $cache['contentType'], $cache['httpHeaders'], FALSE, TRUE );
}
catch ( \OutOfRangeException $e ) {}
/* Turn back on cache validation if we are still here */
if ( \IPS\STORE_METHOD === 'Database' AND \IPS\CACHE_METHOD !== 'None' )
{
\IPS\Data\Store::i()->cacheCheck = true;
}
}
}
@@ -481,7 +494,7 @@ class _Front extends \IPS\Dispatcher\Standard
if( count( $widgets ) )
{
if ( \IPS\CACHE_METHOD === 'None' and ! \IPS\Theme::isUsingTemplateDiskCache() )
if ( ( \IPS\Data\Cache::i() instanceof \IPS\Data\Cache\None ) and ! \IPS\Theme::isUsingTemplateDiskCache() )
{
$templateLoad = array();
foreach ( $widgets as $areaKey => $area )
@@ -517,8 +530,8 @@ class _Front extends \IPS\Dispatcher\Standard
continue;
}
$_widget = \IPS\Widget::load( $appOrPlugin, $widget['key'], ( ! empty($widget['unique'] ) ? $widget['unique'] : uniqid() ), ( isset( $widget['configuration'] ) ) ? $widget['configuration'] : array(), ( isset( $widget['restrict'] ) ? $widget['restrict'] : null ), ( $areaKey == 'sidebar' ) ? 'vertical' : 'horizontal' );
if ( \IPS\CACHE_METHOD === 'None' and isset( $_widget->cacheKey ) )
$_widget = \IPS\Widget::load( $appOrPlugin, $widget['key'], ( ! empty($widget['unique'] ) ? $widget['unique'] : mt_rand() ), ( isset( $widget['configuration'] ) ) ? $widget['configuration'] : array(), ( isset( $widget['restrict'] ) ? $widget['restrict'] : null ), ( $areaKey == 'sidebar' ) ? 'vertical' : 'horizontal' );
if ( ( \IPS\Data\Cache::i() instanceof \IPS\Data\Cache\None ) and isset( $_widget->cacheKey ) )
{
$storeLoad[] = $_widget->cacheKey;
}
@@ -531,7 +544,7 @@ class _Front extends \IPS\Dispatcher\Standard
}
}
if( \IPS\CACHE_METHOD === 'None' and count( $storeLoad ) )
if( ( \IPS\Data\Cache::i() instanceof \IPS\Data\Cache\None ) and count( $storeLoad ) )
{
\IPS\Data\Store::i()->loadIntoMemory( $storeLoad );
}