Version 4.5.0
This commit is contained in:
1 parent
1a0c7fd3c2
commit
f79dcf067a
3791 files changed
+248032
-76372
No files matched your search
+114
-28
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Dispatcher;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -99,9 +99,14 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'core.css', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'responsive.css', 'core', 'front' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'responsive.css', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('admin_newFeatures.js', 'core') );
|
||||
|
||||
/* JS */
|
||||
\IPS\Output::i()->globalControllers[] = 'core.admin.core.app';
|
||||
if ( \IPS\Member::loggedIn()->getFeatureHighlights( FALSE ) )
|
||||
{
|
||||
\IPS\Output::i()->globalControllers[] = 'core.admin.core.newFeatures';
|
||||
}
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin.js' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jquery/jquery-ui.js', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jquery/jquery-touchpunch.js', 'core', 'interface' ) );
|
||||
@@ -113,7 +118,7 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
/* These are just defaults in case we hit an immediate error, e.g. app or controller doesn't exist */
|
||||
\IPS\Output::i()->sidebar['sidebar'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->sidebar( array(), 'core_overview' );
|
||||
\IPS\Output::i()->sidebar['appmenu'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->appmenu( $menu, 'core' );
|
||||
\IPS\Output::i()->sidebar['appmenu'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->appmenu( $menu, 'core', 'core_overview_dashboard' );
|
||||
\IPS\Output::i()->sidebar['mobilenav'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->mobileNavigation( $menu, 'core' );
|
||||
}
|
||||
|
||||
@@ -144,18 +149,18 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
/* If someone calls this from command line, while it wouldn't work, the key won't be set */
|
||||
if( isset( $_SERVER['QUERY_STRING'] ) )
|
||||
{
|
||||
$url = $url->setQueryString( 'ref', base64_encode( preg_replace( '!adsess=((\w){32}|&)!', "", $_SERVER['QUERY_STRING'] ) ) );
|
||||
$url = $url->setQueryString( 'ref', base64_encode( $_SERVER['QUERY_STRING'] ) );
|
||||
}
|
||||
}
|
||||
else if( isset( $_SERVER['HTTP_REFERER'] ) )
|
||||
{
|
||||
$previous = preg_replace( "/^(.+?)\/\?/", "", $_SERVER['HTTP_REFERER'] );
|
||||
$url = $url->setQueryString( 'ref', base64_encode( preg_replace( '!adsess=.*?(&|$)!', "", $previous ) ) );
|
||||
$url = $url->setQueryString( 'ref', base64_encode( $previous ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
|
||||
|
||||
/* Init */
|
||||
try
|
||||
{
|
||||
@@ -166,8 +171,14 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
\IPS\Output::i()->error( $e->getMessage(), '2S100/' . $e->getCode(), $e->getCode() === 4 ? 403 : 404, '' );
|
||||
}
|
||||
|
||||
/* Unless there is a flag telling us we have specifically added CSRF checks, assume any AdminCP action which contains more than app/module/controller/id (i.e. anything with "do") requires CSRF-protection */
|
||||
if ( !isset( $this->classname::$csrfProtected ) and array_diff( array_keys( \IPS\Request::i()->url()->queryString ), array( 'app', 'module', 'controller', 'id' ) ) )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
}
|
||||
|
||||
/* If we are in recovery mode, but not actually doing the recovery process, or logging in, then we need them to remove the constant */
|
||||
if ( \IPS\RECOVERY_MODE === TRUE AND !in_array( $this->controller, array( 'recovery', 'login' ) ) )
|
||||
if ( \IPS\RECOVERY_MODE === TRUE AND !\in_array( $this->controller, array( 'recovery', 'login' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'recovery_mode_remove_constant', '1S107/3', 403, '' );
|
||||
}
|
||||
@@ -176,12 +187,14 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
if (
|
||||
(
|
||||
$this->module->key !== 'system' or
|
||||
!in_array( $this->controller, array( 'login', 'language', 'theme', 'livesearch', 'editor', 'ajax' ) )
|
||||
!\in_array( $this->controller, array( 'login', 'language', 'theme', 'livesearch', 'editor', 'ajax' ) )
|
||||
) and
|
||||
/* Every admin can view and manage his own acp notification */
|
||||
( $this->module->key !== 'overview' or $this->controller !== 'notifications' ) and
|
||||
(
|
||||
$this->module->key !== 'members' or
|
||||
$this->controller !== 'members' or
|
||||
!in_array( \IPS\Request::i()->do, array( 'adminDetails', 'adminEmail', 'adminPassword' ) )
|
||||
!\in_array( \IPS\Request::i()->do, array( 'adminDetails', 'adminEmail', 'adminPassword' ) )
|
||||
) and
|
||||
/* This is slightly hacky, but the upgrader was moved to the system module, however the ACP restriction is still set to overview.
|
||||
To avoid unintentionally removing restrictions via an upgrade by moving the restriction, we reference the overview module for the restriction check instead */
|
||||
@@ -191,6 +204,12 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2S107/1', 403, '' );
|
||||
}
|
||||
|
||||
/* Support is not available for demos */
|
||||
if ( \IPS\DEMO_MODE AND $this->module->application === 'core' AND $this->module->key === 'support' )
|
||||
{
|
||||
\IPS\Output::i()->error( 'demo_mode_function_blocked', '1S107/4', 403, '' );
|
||||
}
|
||||
|
||||
/* ACP search keywords */
|
||||
if ( \IPS\IN_DEV )
|
||||
{
|
||||
@@ -203,7 +222,7 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
|
||||
$restrictions = array();
|
||||
|
||||
$file = \IPS\ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json";
|
||||
$file = $this->application->getApplicationPath() . "/data/acprestrictions.json";
|
||||
if ( file_exists( $file ) )
|
||||
{
|
||||
$restrictions = json_decode( file_get_contents( $file ), TRUE );
|
||||
@@ -239,9 +258,23 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
/* Work out what tab we're on */
|
||||
$currentTab = NULL;
|
||||
$currentItem = NULL;
|
||||
|
||||
foreach ( $this->application->acpMenu() as $moduleKey => $items )
|
||||
{
|
||||
if ( $moduleKey === $this->module->key )
|
||||
/* If the module key does not match, we still need to inspect each item to see if a module_url that matches was specified */
|
||||
$moduleUrlMatches = FALSE;
|
||||
|
||||
foreach( $items as $item )
|
||||
{
|
||||
if( isset( $item['module_url'] ) AND $item['module_url'] == $this->module->key )
|
||||
{
|
||||
$moduleUrlMatches = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $moduleUrlMatches OR $moduleKey === $this->module->key )
|
||||
{
|
||||
foreach ( $items as $itemKey => $item )
|
||||
{
|
||||
@@ -249,28 +282,48 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
$currentTab = $item['tab'];
|
||||
}
|
||||
if ( $item['controller'] === $this->controller )
|
||||
|
||||
$additionalChecksPass = TRUE;
|
||||
|
||||
if( isset( $item['menu_checks'] ) AND \is_array( $item['menu_checks'] ) )
|
||||
{
|
||||
foreach( $item['menu_checks'] as $key => $value )
|
||||
{
|
||||
if( !isset( \IPS\Request::i()->$key ) OR \IPS\Request::i()->$key != $value )
|
||||
{
|
||||
$additionalChecksPass = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $additionalChecksPass === TRUE and ( $item['controller'] === $this->controller or ( isset( $item['subcontrollers'] ) and \in_array( $this->controller, explode( ",", $item['subcontrollers'] ) ) ) ) )
|
||||
{
|
||||
break;
|
||||
$controllerForKey = ( isset( $item['menu_controller'] ) ) ? $item['menu_controller'] : $item['controller'];
|
||||
|
||||
$currentItem = $this->application->directory . "_" . $moduleKey . "_" . $controllerForKey;
|
||||
|
||||
if( $currentTab != $item['tab'] )
|
||||
{
|
||||
$currentTab = $item['tab'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$currentTab )
|
||||
{
|
||||
$currentTab = $this->application->directory;
|
||||
}
|
||||
|
||||
|
||||
/* Display */
|
||||
if( $this->controller !== 'login' )
|
||||
if ( isset( $menu['tabs'][ $currentTab ] ) )
|
||||
{
|
||||
if ( isset( $menu['tabs'][ $currentTab ] ) )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['sidebar'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->sidebar( $menu['tabs'][ $currentTab ], $this->application->directory . '_' . $this->module->key );
|
||||
}
|
||||
\IPS\Output::i()->sidebar['appmenu'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->appmenu( $menu, $currentTab );
|
||||
\IPS\Output::i()->sidebar['mobilenav'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->mobileNavigation( $menu, $currentTab );
|
||||
\IPS\Output::i()->sidebar['sidebar'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->sidebar( $menu['tabs'][ $currentTab ], $this->application->directory . '_' . $this->module->key );
|
||||
}
|
||||
\IPS\Output::i()->sidebar['appmenu'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->appmenu( $menu, $currentTab, $currentItem );
|
||||
\IPS\Output::i()->sidebar['mobilenav'] = \IPS\Theme::i()->getTemplate( 'global', 'core' )->mobileNavigation( $menu, $currentTab, $currentItem );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,7 +331,7 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
/**
|
||||
* Build Menu
|
||||
*
|
||||
* @param bool If TRUE, will rebuild
|
||||
* @param bool $rebuild If TRUE, will rebuild
|
||||
* @return array
|
||||
*/
|
||||
public function buildMenu( $rebuild=FALSE )
|
||||
@@ -307,21 +360,54 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
foreach ( $items as $itemKey => $item )
|
||||
{
|
||||
if ( isset( $item['callback'] ) and !eval( $item['callback'] ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$moduleUrl = ( isset( $item['module_url'] ) ) ? $item['module_url'] : $moduleKey;
|
||||
$moduleToCheck = ( isset( $item['restriction_module'] ) ) ? $item['restriction_module'] : $moduleKey;
|
||||
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( $app, $moduleToCheck ) )
|
||||
{
|
||||
if ( !$item['restriction'] or \IPS\Member::loggedIn()->hasAcpRestriction( $app, $moduleToCheck, $item['restriction'] ) )
|
||||
{
|
||||
if( !$item['restriction'] )
|
||||
{
|
||||
$canAccess = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mb_strpos( $item['restriction'], ',' ) )
|
||||
{
|
||||
$restrictions = explode( ',', $item['restriction'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$restrictions = array( $item['restriction'] );
|
||||
}
|
||||
|
||||
$canAccess = FALSE;
|
||||
|
||||
foreach( $restrictions as $restrictionKey )
|
||||
{
|
||||
if( \IPS\Member::loggedIn()->hasAcpRestriction( $app, $moduleToCheck, $restrictionKey ) )
|
||||
{
|
||||
$canAccess = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $canAccess )
|
||||
{
|
||||
$this->menu['tabs'][ $item['tab'] ][ "{$app->directory}_{$moduleKey}" ][ $itemKey ] = "app={$app->directory}&module={$moduleKey}&controller={$item['controller']}" . ( $item['do'] ? "&do={$item['do']}" : '' );
|
||||
$this->menu['tabs'][ $item['tab'] ][ "{$app->directory}_{$moduleKey}" ][ $itemKey ] = "app={$app->directory}&module={$moduleUrl}&controller={$item['controller']}" . ( $item['do'] ? "&do={$item['do']}" : '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( $acpTabOrder !== NULL )
|
||||
{
|
||||
$_apps = array_keys( $acpTabOrder );
|
||||
@@ -398,7 +484,7 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
catch( \UnderflowException $ex )
|
||||
{
|
||||
$this->acpTabOrder = array( 'core' => array(), 'community' => array(), 'members' => array(), 'nexus' => array(), 'cms' => array(), 'stats' => array(), 'customization' => array() );
|
||||
$this->acpTabOrder = array( 'core' => array(), 'community' => array(), 'members' => array(), 'nexus' => array(), 'cms' => array(), 'stats' => array(), 'customization' => array(), 'marketplace' => array() );
|
||||
}
|
||||
|
||||
\IPS\Request::i()->setCookie( 'acpTabs', json_encode( $this->acpTabOrder ) );
|
||||
|
||||
+19
-68
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Dispatcher;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -78,6 +78,10 @@ class _Api extends \IPS\Dispatcher
|
||||
if ( $this->rawAccessToken )
|
||||
{
|
||||
$this->_setAccessToken();
|
||||
if ( !$this->accessToken['scope'] or !json_decode( $this->accessToken['scope'] ) )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'NO_SCOPES', '3S290/B', 401, 'insufficient_scope' );
|
||||
}
|
||||
}
|
||||
elseif ( $this->rawApiKey )
|
||||
{
|
||||
@@ -97,9 +101,9 @@ class _Api extends \IPS\Dispatcher
|
||||
$response = json_encode( array( 'errorCode' => $e->exceptionCode, 'errorMessage' => $e->getMessage() ), JSON_PRETTY_PRINT );
|
||||
|
||||
/* Do we need to log this? */
|
||||
if ( $this->rawApiKey !== 'test' and in_array( $e->exceptionCode, array( '2S290/8', '2S290/B', '3S290/7', '3S290/9' ) ) )
|
||||
if ( $this->rawApiKey !== 'test' and \in_array( $e->exceptionCode, array( '2S290/8', '2S290/B', '3S290/7', '3S290/9' ) ) )
|
||||
{
|
||||
$this->_log( $response, $e->getCode(), in_array( $e->exceptionCode, array( '3S290/7', '3S290/9', '3S290/B' ) ) );
|
||||
$this->_log( $response, $e->getCode(), \in_array( $e->exceptionCode, array( '3S290/7', '3S290/9', '3S290/B' ) ) );
|
||||
}
|
||||
|
||||
/* Output */
|
||||
@@ -154,48 +158,7 @@ class _Api extends \IPS\Dispatcher
|
||||
*/
|
||||
public function _setRawCredentials()
|
||||
{
|
||||
/* Check if an API Key or Access Token has been passed as a parameter in the query string. Because of the
|
||||
obvious security issues with this, we do not recommend it, but sometimes it is the only choice */
|
||||
if ( isset( \IPS\Request::i()->key ) )
|
||||
{
|
||||
$this->rawApiKey = \IPS\Request::i()->key;
|
||||
return;
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->access_token ) and ( !\IPS\OAUTH_REQUIRES_HTTPS or \IPS\Request::i()->isSecure() ) )
|
||||
{
|
||||
$this->rawAccessToken = \IPS\Request::i()->access_token;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look for an API key in an automatically decoded HTTP Basic header */
|
||||
if ( isset( $_SERVER['PHP_AUTH_USER'] ) )
|
||||
{
|
||||
$this->rawApiKey = $_SERVER['PHP_AUTH_USER'];
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we're still here, try to find an Authorization header - start with $_SERVER... */
|
||||
$authorizationHeader = NULL;
|
||||
foreach ( $_SERVER as $k => $v )
|
||||
{
|
||||
if ( mb_substr( $k, -18 ) == 'HTTP_AUTHORIZATION' )
|
||||
{
|
||||
$authorizationHeader = $v;
|
||||
}
|
||||
}
|
||||
|
||||
/* ...if we didn't find anything there, try apache_request_headers() */
|
||||
if ( !$authorizationHeader and function_exists('apache_request_headers') )
|
||||
{
|
||||
$headers = @apache_request_headers();
|
||||
if ( isset( $headers['Authorization'] ) )
|
||||
{
|
||||
$authorizationHeader = $headers['Authorization'];
|
||||
}
|
||||
}
|
||||
|
||||
/* If we managed to get one, set if it's an API Key or an Access Token */
|
||||
if ( $authorizationHeader )
|
||||
if ( $authorizationHeader = \IPS\Request::i()->authorizationHeader() )
|
||||
{
|
||||
if ( mb_substr( $authorizationHeader, 0, 7 ) === 'Bearer ' and ( !\IPS\OAUTH_REQUIRES_HTTPS or \IPS\Request::i()->isSecure() ) )
|
||||
{
|
||||
@@ -263,7 +226,7 @@ class _Api extends \IPS\Dispatcher
|
||||
{
|
||||
$this->apiKey = \IPS\Api\Key::load( $this->rawApiKey );
|
||||
|
||||
if ( $this->apiKey->allowed_ips and !in_array( \IPS\Request::i()->ipAddress(), explode( ',', $this->apiKey->allowed_ips ) ) )
|
||||
if ( $this->apiKey->allowed_ips and !\in_array( \IPS\Request::i()->ipAddress(), explode( ',', $this->apiKey->allowed_ips ) ) )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'IP_ADDRESS_NOT_ALLOWED', '2S290/8', 403 );
|
||||
}
|
||||
@@ -283,22 +246,7 @@ class _Api extends \IPS\Dispatcher
|
||||
{
|
||||
try
|
||||
{
|
||||
$exploded = explode( '_', $this->rawAccessToken );
|
||||
|
||||
if ( !isset( $exploded[0] ) or !isset( $exploded[1] ) )
|
||||
{
|
||||
throw new \UnderflowException;
|
||||
}
|
||||
|
||||
$this->accessToken = \IPS\Db::i()->select( '*', 'core_oauth_server_access_tokens', array( 'client_id=? AND access_token=?', $exploded[0], $exploded[1] ) )->first();
|
||||
if ( $this->accessToken['access_token_expires'] and $this->accessToken['access_token_expires'] < time() )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'EXPIRED_ACCESS_TOKEN', '1S290/E', 401, 'invalid_token' );
|
||||
}
|
||||
if ( !$this->accessToken['scope'] or !json_decode( $this->accessToken['scope'] ) )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'NO_SCOPES', '3S290/B', 401, 'insufficient_scope' );
|
||||
}
|
||||
$this->accessToken = \IPS\Api\OAuthClient::accessTokenDetails( $this->rawAccessToken );
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
@@ -317,7 +265,7 @@ class _Api extends \IPS\Dispatcher
|
||||
{
|
||||
if ( isset( $_SERVER['HTTP_X_IPS_LANGUAGE'] ) )
|
||||
{
|
||||
$this->language = \IPS\Lang::load( intval( $_SERVER['HTTP_X_IPS_LANGUAGE'] ) );
|
||||
$this->language = \IPS\Lang::load( \intval( $_SERVER['HTTP_X_IPS_LANGUAGE'] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -381,9 +329,10 @@ class _Api extends \IPS\Dispatcher
|
||||
$response = $controller->execute( $pathBits, $shouldLog );
|
||||
|
||||
/* Send Output */
|
||||
$output = json_encode( $response->getOutput(), JSON_PRETTY_PRINT );
|
||||
$output = $response->getOutput();
|
||||
$this->language->parseOutputForDisplay( $output );
|
||||
$this->_respond( $output, $response->httpCode, NULL, $shouldLog, TRUE );
|
||||
|
||||
$this->_respond( json_encode( $output, JSON_PRETTY_PRINT ), $response->httpCode, NULL, $shouldLog, TRUE );
|
||||
}
|
||||
catch ( \IPS\Api\Exception $e )
|
||||
{
|
||||
@@ -430,9 +379,11 @@ class _Api extends \IPS\Dispatcher
|
||||
/**
|
||||
* Output response
|
||||
*
|
||||
* @param string $response Response to output
|
||||
* @param int $httpResponseCode HTTP Response Code
|
||||
* @param bool $parseLanguage If response should be language parsed
|
||||
* @param string $response Response to output
|
||||
* @param int $httpResponseCode HTTP Response Code
|
||||
* @param NULL|string $oauthError OAuth error
|
||||
* @param bool $log Whether or not to log the response
|
||||
* @return void
|
||||
*/
|
||||
protected function _respond( $response, $httpResponseCode, $oauthError=NULL, $log=FALSE )
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Dispatcher;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -26,7 +26,15 @@ class _Build extends \IPS\Dispatcher
|
||||
* @brief Controller Location
|
||||
*/
|
||||
public $controllerLocation = 'front';
|
||||
|
||||
/**
|
||||
* @brief Application
|
||||
*/
|
||||
public $application = 'core';
|
||||
|
||||
/**
|
||||
* @brief Module
|
||||
*/
|
||||
public $module = 'system';
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Dispatcher;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -26,6 +26,11 @@ abstract class _Controller
|
||||
* @brief Base URL
|
||||
*/
|
||||
public $url;
|
||||
|
||||
/**
|
||||
* @brief Is this for displaying "content"? Affects if advertisements may be shown
|
||||
*/
|
||||
public $isContentPage = TRUE;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -37,7 +42,7 @@ abstract class _Controller
|
||||
{
|
||||
if ( $url === NULL )
|
||||
{
|
||||
$class = get_called_class();
|
||||
$class = \get_called_class();
|
||||
$exploded = explode( '\\', $class );
|
||||
$this->url = \IPS\Http\Url::internal( "app={$exploded[1]}&module={$exploded[4]}&controller={$exploded[5]}", \IPS\Dispatcher::i()->controllerLocation );
|
||||
}
|
||||
@@ -148,7 +153,7 @@ abstract class _Controller
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->page ) and \IPS\Request::i()->page > 1 )
|
||||
{
|
||||
$params['page'] = intval( \IPS\Request::i()->page );
|
||||
$params['page'] = \intval( \IPS\Request::i()->page );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->embedDo ) )
|
||||
{
|
||||
@@ -207,7 +212,7 @@ abstract class _Controller
|
||||
\IPS\Output::i()->metaTags['robots'] = 'noindex';
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->embedInternal( $output, $js ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->embedInternal( $output, $js ), 200, 'text/html' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -47,7 +47,7 @@ abstract class _Dispatcher
|
||||
{
|
||||
if( static::$instance === NULL )
|
||||
{
|
||||
$class = get_called_class();
|
||||
$class = \get_called_class();
|
||||
|
||||
if( $class == 'IPS\\Dispatcher' )
|
||||
{
|
||||
@@ -59,14 +59,14 @@ abstract class _Dispatcher
|
||||
if( static::$instance->controllerLocation != 'setup' )
|
||||
{
|
||||
$_redirect = FALSE;
|
||||
|
||||
if ( !file_exists( \IPS\ROOT_PATH . '/conf_global.php' ) )
|
||||
|
||||
if ( !file_exists( \IPS\SITE_FILES_PATH . '/conf_global.php' ) )
|
||||
{
|
||||
$_redirect = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
require \IPS\ROOT_PATH . '/conf_global.php';
|
||||
require \IPS\SITE_FILES_PATH . '/conf_global.php';
|
||||
|
||||
if( !isset( $INFO['sql_database'] ) )
|
||||
{
|
||||
@@ -94,9 +94,15 @@ abstract class _Dispatcher
|
||||
|
||||
if( $_redirect === TRUE )
|
||||
{
|
||||
/* conf_global.php does not exist, forward to installer */
|
||||
$url = ( \IPS\Request::i()->isSecure() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . rtrim( dirname( $_SERVER['SCRIPT_NAME'] ), '/' );
|
||||
\IPS\Output::i()->redirect( "{$url}/" . \IPS\CP_DIRECTORY . "/install/" );
|
||||
/* conf_global.php does not exist, forward to installer - we'll do this manually to avoid any code in Output.php that anticipates the installation already being complete (such as setting CSP header in __construct()) */
|
||||
$url = ( \IPS\Request::i()->isSecure() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . rtrim( \dirname( $_SERVER['SCRIPT_NAME'] ), '/' );
|
||||
|
||||
header( "HTTP/1.1 307 Temporary Redirect" );
|
||||
header( "Cache-Control: no-cache, no-store, must-revalidate" );
|
||||
header( "Pragma: no-cache" );
|
||||
header( "Expires: 0" );
|
||||
header( "Location: {$url}/" . \IPS\CP_DIRECTORY . "/install/" );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,12 +113,12 @@ abstract class _Dispatcher
|
||||
}
|
||||
|
||||
/**
|
||||
* Controller Classname
|
||||
* @brief Controller Classname
|
||||
*/
|
||||
protected $classname;
|
||||
|
||||
/**
|
||||
* Controller instance
|
||||
* @brief Controller instance
|
||||
*/
|
||||
public $dispatcherController;
|
||||
|
||||
@@ -158,12 +164,12 @@ abstract class _Dispatcher
|
||||
/* If we're still here - output */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( \IPS\Output::i()->output ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( \IPS\Output::i()->output ), 200, 'text/html' );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just prefetch this to save a query later */
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, \IPS\Output::i()->output, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, \IPS\Output::i()->output, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) ), 200, 'text/html' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Dispatcher;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
|
||||
+115
-50
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Dispatcher;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -26,11 +26,12 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
* Controller Location
|
||||
*/
|
||||
public $controllerLocation = 'front';
|
||||
|
||||
|
||||
/**
|
||||
* Init
|
||||
*
|
||||
* @return void
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
@@ -45,6 +46,11 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
$protocol = '1.1';
|
||||
}
|
||||
|
||||
/* Don't allow the setup in progress page to be cached, it will only be displayed for a very short period of time */
|
||||
header( "Cache-Control: no-cache, no-store, must-revalidate" );
|
||||
header( "Pragma: no-cache" );
|
||||
header( "Expires: 0" );
|
||||
|
||||
if ( \IPS\CIC and ! \IPS\Session\Front::loggedIn() and ! \IPS\Session\Front::i()->userAgent->spider )
|
||||
{
|
||||
@@ -114,14 +120,22 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
\IPS\Output::i()->error( $e->getMessage(), '2S100/' . $e->getCode(), $e->getCode() === 4 ? 403 : 404, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Set a referral cookie */
|
||||
if( \IPS\Settings::i()->ref_on and isset( \IPS\Request::i()->_rid ) )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'referred_by', \intval( \IPS\Request::i()->_rid ), \IPS\DateTime::create()->add( new \DateInterval( 'P1Y' ) ) );
|
||||
}
|
||||
|
||||
/* 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 )
|
||||
foreach( \IPS\core\Rss::getStore() AS $feed_id => $feed )
|
||||
{
|
||||
if ( $feed->groups == '*' OR \IPS\Member::loggedIn()->inGroup( $feed->groups ) )
|
||||
$feed = \IPS\core\Rss::constructFromData( $feed );
|
||||
|
||||
if ( $feed->_enabled AND ( $feed->groups == '*' OR \IPS\Member::loggedIn()->inGroup( $feed->groups ) ) )
|
||||
{
|
||||
\IPS\Output::i()->rssFeeds[ $feed->_title ] = $feed->url();
|
||||
}
|
||||
@@ -164,7 +178,7 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
\IPS\Output::i()->sidebar = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
if( !in_array( $this->controller, array( 'contact', 'warnings' ) ) )
|
||||
if( !\in_array( $this->controller, array( 'contact', 'warnings', 'privacy', 'guidelines', 'metatags' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->showBanned();
|
||||
}
|
||||
@@ -174,13 +188,13 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
/* Do we need more info from the member or do they need to validate? */
|
||||
|
||||
/* This controllers should always be accessible, no matter if the member is awaiting validation or needs to set up the email or name */
|
||||
$legalControllers = array( 'privacy', 'contact', 'terms' );
|
||||
$legalControllers = array( 'privacy', 'contact', 'terms', 'embed', 'metatags' );
|
||||
|
||||
/* 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' and $this->controller !== 'ajax' and !\in_array( $this->controller, $legalControllers ) )
|
||||
{
|
||||
/* 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' and $this->controller !== 'login' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=complete' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
|
||||
}
|
||||
@@ -195,18 +209,29 @@ 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\Settings::i()->quick_register AND !\IPS\Member::loggedIn()->members_bitoptions['profile_completed'] AND !in_array( $this->controller, array( 'register', 'login', 'redirect', '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', 'ajax', 'settings', 'checkout', 'pixabay', 'editor' ) ) AND $completion = \IPS\Member::loggedIn()->profileCompletion() AND \count( $completion['required'] ) )
|
||||
{
|
||||
foreach( $completion['required'] AS $id => $completed )
|
||||
{
|
||||
if ( $completed === FALSE )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=register&do=finish", 'front', 'register' ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=register&do=finish&_new=1", 'front', 'register' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Need to reset password */
|
||||
elseif ( $this->controller !== 'settings' AND ( !isset( \IPS\Request::i()->area ) OR \IPS\Request::i()->area !== 'password' ) )
|
||||
{
|
||||
foreach( \IPS\Login::methods() AS $method )
|
||||
{
|
||||
if ( $url = $method->forcePasswordResetUrl( \IPS\Member::loggedIn(), \IPS\Request::i()->url() ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Need to set up MFA... */
|
||||
elseif ( !in_array( $this->controller, array( 'register', 'login', 'redirect', 'ajax', 'settings' ) ) )
|
||||
elseif ( !\in_array( $this->controller, array( 'register', 'login', 'redirect', 'ajax', 'settings', 'embed' ) ) )
|
||||
{
|
||||
$haveAcceptableHandlers = FALSE;
|
||||
$haveConfiguredHandler = FALSE;
|
||||
@@ -237,17 +262,24 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
\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 */
|
||||
if ( !\IPS\Member::loggedIn()->canAccessModule( $this->module ) )
|
||||
try
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id and isset( \IPS\Request::i()->_mfaLogin ) )
|
||||
if ( !\IPS\Member::loggedIn()->canAccessModule( $this->module ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->setQueryString( '_mfaLogin', 1 ) );
|
||||
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' )->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' );
|
||||
}
|
||||
\IPS\Output::i()->error( ( \IPS\Member::loggedIn()->member_id ? 'no_module_permission' : 'no_module_permission_guest' ), '2S100/2', 403, 'no_module_permission_admin' );
|
||||
}
|
||||
catch( \InvalidArgumentException $e ) # invalid module
|
||||
{
|
||||
\IPS\Output::i()->error( 'requested_route_404', '2S160/5', 404, '' );
|
||||
}
|
||||
|
||||
/* Stuff for output */
|
||||
@@ -276,7 +308,7 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
/* Figure out what the global search is */
|
||||
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 )
|
||||
@@ -319,18 +351,28 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
/* 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 ) )
|
||||
$pathFromBaseUrl = ltrim( mb_substr( $url->data[ \IPS\Http\Url::COMPONENT_PATH ], mb_strlen( \IPS\Http\Url::internal('')->data[ \IPS\Http\Url::COMPONENT_PATH ] ) ), '/' );
|
||||
if ( mb_substr( $pathFromBaseUrl, 0, 10 ) === 'index.php/' )
|
||||
{
|
||||
$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 )
|
||||
{
|
||||
if( $correctUrl->seoPagination and \in_array( 'page', array_keys( $url->hiddenQueryString ) ) )
|
||||
{
|
||||
$correctUrl = $correctUrl->setPage( 'page', $url->hiddenQueryString['page'] );
|
||||
}
|
||||
\IPS\Output::i()->redirect( $correctUrl, NULL, 301 );
|
||||
}
|
||||
|
||||
/* Check pagination */
|
||||
if ( $url instanceof \IPS\Http\Url\Friendly and $url->seoPagination and \in_array( 'page', array_keys( $url->queryString ) ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url->setPage( 'page', $url->queryString['page'] )->stripQueryString('page'), NULL, 301 );
|
||||
}
|
||||
}
|
||||
|
||||
/* If the accessed URL is friendly, set the "real" query string properties */
|
||||
@@ -346,7 +388,13 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
$this->_controller = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* If this is a POST request, and this key has already been populated, do not overwrite it as this allows form input to be ignored and the query string data used */
|
||||
if ( \IPS\Request::i()->requestMethod() == 'POST' and isset( \IPS\Request::i()->$k ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
\IPS\Request::i()->$k = $v;
|
||||
}
|
||||
}
|
||||
@@ -382,25 +430,6 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
*/
|
||||
protected function checkCached()
|
||||
{
|
||||
/* Store page view in Redis */
|
||||
if ( \IPS\CACHE_METHOD == 'Redis' and \IPS\CIC and !\IPS\Request::i()->isAjax() )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
@@ -423,13 +452,25 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
/* Which theme? */
|
||||
$theme = isset( \IPS\Request::i()->cookie['theme'] ) ? \IPS\Request::i()->cookie['theme'] : '';
|
||||
|
||||
/* Make sure a session is initiated */
|
||||
\IPS\Session\Front::i();
|
||||
|
||||
/* Get cache */
|
||||
try
|
||||
{
|
||||
$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 );
|
||||
$cache = \IPS\Output\Cache::i()->get( 'page_' . md5( (string) \IPS\Request::i()->url() ) . "_{$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 );
|
||||
/* RSS feeds can be shown cached, all other pages contain a cache buster once logged in */
|
||||
$cache['meta']['httpHeaders'] += \IPS\Output::getCacheHeaders( $cache['meta']['lastUpdated'], \IPS\CACHE_PAGE_TIMEOUT );
|
||||
|
||||
if( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) AND $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $cache['meta']['httpHeaders']['Last-Modified'] )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( NULL, 304, $cache['meta']['contentType'], $cache['meta']['httpHeaders'], FALSE, TRUE, FALSE, FALSE );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sendOutput( str_replace( '{{csrfKey}}', md5( \IPS\SUITE_UNIQUE_KEY . '&& 0&' . $sessionId ), $cache['output'] ), $cache['meta']['code'], $cache['meta']['contentType'], $cache['meta']['httpHeaders'], FALSE, TRUE );
|
||||
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) {}
|
||||
}
|
||||
@@ -466,11 +507,11 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
$widgets = array();
|
||||
|
||||
if ( ! isset( \IPS\Output::i()->sidebar['widgets'] ) OR ! is_array( \IPS\Output::i()->sidebar['widgets'] ) )
|
||||
if ( ! isset( \IPS\Output::i()->sidebar['widgets'] ) OR ! \is_array( \IPS\Output::i()->sidebar['widgets'] ) )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['widgets'] = array();
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
$widgetConfig = \IPS\Db::i()->select( '*', 'core_widget_areas', array( 'app=? AND module=? AND controller=?', $this->application->directory, $this->module->key, $this->controller ) );
|
||||
@@ -497,7 +538,7 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
|
||||
if( count( $widgets ) )
|
||||
if( \count( $widgets ) )
|
||||
{
|
||||
if ( ( \IPS\Data\Cache::i() instanceof \IPS\Data\Cache\None ) and ! \IPS\Theme::isUsingTemplateDiskCache() )
|
||||
{
|
||||
@@ -514,7 +555,7 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
|
||||
if( count( $templateLoad ) )
|
||||
if( \count( $templateLoad ) )
|
||||
{
|
||||
\IPS\Data\Store::i()->loadIntoMemory( $templateLoad );
|
||||
}
|
||||
@@ -522,6 +563,7 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
|
||||
$widgetObjects = array();
|
||||
$storeLoad = array();
|
||||
$googleFonts = array();
|
||||
foreach ( $widgets as $areaKey => $area )
|
||||
{
|
||||
foreach ( $area as $widget )
|
||||
@@ -540,6 +582,23 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
$storeLoad[] = $_widget->cacheKey;
|
||||
}
|
||||
|
||||
if ( \in_array( 'IPS\Widget\Builder', class_implements( $_widget ) ) )
|
||||
{
|
||||
if ( ! empty( $_widget->configuration['widget_adv__font'] ) and $_widget->configuration['widget_adv__font'] !== 'inherit' )
|
||||
{
|
||||
$font = $_widget->configuration['widget_adv__font'];
|
||||
|
||||
if ( \mb_substr( $font, -6 ) === ' black' )
|
||||
{
|
||||
$fontWeight = 900;
|
||||
$font = \mb_substr( $font, 0, -6 ) . ':400,900';
|
||||
}
|
||||
|
||||
$googleFonts[ $font ] = $font;
|
||||
}
|
||||
}
|
||||
|
||||
$widgetObjects[ $areaKey ][] = $_widget;
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
@@ -549,7 +608,12 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
|
||||
if( ( \IPS\Data\Cache::i() instanceof \IPS\Data\Cache\None ) and count( $storeLoad ) )
|
||||
if ( \count( $googleFonts ) )
|
||||
{
|
||||
\IPS\Output::i()->linkTags['googlefonts'] = array('rel' => 'stylesheet', 'href' => "https://fonts.googleapis.com/css?family=" . implode( "|", array_values( $googleFonts ) ) . "&display=swap");
|
||||
}
|
||||
|
||||
if( ( \IPS\Data\Cache::i() instanceof \IPS\Data\Cache\None ) and \count( $storeLoad ) )
|
||||
{
|
||||
\IPS\Data\Store::i()->loadIntoMemory( $storeLoad );
|
||||
}
|
||||
@@ -563,10 +627,10 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Meta tags */
|
||||
\IPS\Output::i()->buildMetaTags();
|
||||
|
||||
|
||||
/* Check MFA */
|
||||
$this->checkMfa();
|
||||
|
||||
@@ -617,6 +681,7 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
\IPS\Output::i()->globalControllers[] = 'core.front.core.app';
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front.js' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_core.js', 'core', 'front' ) );
|
||||
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['bw_using_skin_gen'] AND ( isset( \IPS\Request::i()->cookie['vseThemeId'] ) AND \IPS\Request::i()->cookie['vseThemeId'] ) and \IPS\Member::loggedIn()->isAdmin() and \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'customization', 'theme_easy_editor' ) )
|
||||
{
|
||||
@@ -674,7 +739,7 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/query_log.css', 'core', 'front' ) );
|
||||
}
|
||||
if ( \IPS\CACHING_LOG )
|
||||
if ( \IPS\CACHING_LOG or \IPS\REDIS_LOG )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/caching_log.css', 'core', 'front' ) );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief GraphQL API Dispatcher
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @since 3 Dec 2015
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\Dispatcher;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/* Register our GraphQL library */
|
||||
\IPS\IPS::$PSR0Namespaces['GraphQL'] = \IPS\ROOT_PATH . "/system/3rd_party/graphql-php";
|
||||
|
||||
/**
|
||||
* @brief API Dispatcher
|
||||
*/
|
||||
class _GraphQL extends Api
|
||||
{
|
||||
/**
|
||||
* @brief Path
|
||||
*/
|
||||
public $path = '/graphql';
|
||||
|
||||
/**
|
||||
* Init
|
||||
*
|
||||
* @return void
|
||||
* @throws \DomainException
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
try
|
||||
{
|
||||
/* Check our IP address isn't banned */
|
||||
$this->_checkIpAddressIsAllowed();
|
||||
|
||||
/* If this is a pre-flight request, acknowldge it */
|
||||
// @todo review this approach
|
||||
if( $_SERVER['REQUEST_METHOD'] === 'OPTIONS' )
|
||||
{
|
||||
$this->_respond( '', 200 );
|
||||
}
|
||||
|
||||
/* Authenticate */
|
||||
$client = NULL;
|
||||
$this->_setRawCredentials();
|
||||
try
|
||||
{
|
||||
if ( $this->rawAccessToken )
|
||||
{
|
||||
$this->_setAccessToken();
|
||||
$client = \IPS\Api\OAuthClient::load( $this->accessToken['client_id'] );
|
||||
\IPS\Member::$loggedInMember = \IPS\Member::load( $this->accessToken['member_id'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$client = \IPS\Api\OAuthClient::load( $this->rawApiKey );
|
||||
\IPS\Member::$loggedInMember = new \IPS\Member;
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'INVALID_API_KEY', '3S290/7', 401 );
|
||||
}
|
||||
|
||||
/* Check that the OAuth client has access to the GraphQL API */
|
||||
if ( !$client->graphql )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'NO_GRAPHQL_ACCESS', '2S291/3', 403 );
|
||||
}
|
||||
}
|
||||
catch ( \IPS\Api\Exception $e )
|
||||
{
|
||||
/* Build resonse */
|
||||
$response = json_encode( array( 'errors' => array( array( 'message' => $e->getMessage(), 'id' => $e->exceptionCode ) ) ), JSON_PRETTY_PRINT );
|
||||
|
||||
/* Do we need to log this? */
|
||||
if ( \in_array( $e->exceptionCode, array( '2S290/8', '2S290/B', '3S290/7', '3S290/9' ) ) )
|
||||
{
|
||||
$this->_log( $response, $e->getCode(), \in_array( $e->exceptionCode, array( '3S290/7', '3S290/9', '3S290/B' ) ) );
|
||||
}
|
||||
|
||||
/* Output */
|
||||
$this->_respond( $response, $e->getCode(), $e->oauthError );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
try
|
||||
{
|
||||
/* Work out the query (can either use a JSON-encoded or form-encoded) body */
|
||||
$query = NULL;
|
||||
$variables = NULL;
|
||||
if( \IPS\Request::i()->query )
|
||||
{
|
||||
$query = \IPS\Request::i()->query;
|
||||
$variables = ( isset( \IPS\Request::i()->variables ) AND \is_array( \IPS\Request::i()->variables ) ) ? \IPS\Request::i()->variables : [];
|
||||
}
|
||||
elseif ( $json = json_decode( file_get_contents('php://input'), TRUE ) )
|
||||
{
|
||||
$query = $json['query'];
|
||||
if( isset( $json['variables'] ) )
|
||||
{
|
||||
$variables = $json['variables'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute! */
|
||||
$result = \GraphQL\GraphQL::executeQuery(
|
||||
new \GraphQL\Schema([
|
||||
'query' => \IPS\Api\GraphQL\TypeRegistry::query(),
|
||||
'mutation' => \IPS\Api\GraphQL\TypeRegistry::mutation()
|
||||
]),
|
||||
$query,
|
||||
NULL, // $rootValue
|
||||
[
|
||||
'member' => \IPS\Member::loggedIn()
|
||||
], // $context
|
||||
$variables
|
||||
);
|
||||
|
||||
/* Convert result into JSON and send */
|
||||
$output = $result->toArray( ( \IPS\IN_DEV OR \IPS\DEBUG_GRAPHQL ) ? \GraphQL\Error\Debug::INCLUDE_DEBUG_MESSAGE | \GraphQL\Error\Debug::INCLUDE_TRACE : false );
|
||||
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $output );
|
||||
$this->_respond( json_encode( $output, JSON_PRETTY_PRINT ), 200 );
|
||||
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$response = json_encode( array( 'errors' => array( array( 'message' => ( \IPS\IN_DEV OR \IPS\DEBUG_GRAPHQL ) ? $e->getMessage() : 'UNKNOWN_ERROR', 'id' => $e->getCode() ) ) ), JSON_PRETTY_PRINT );
|
||||
$this->_respond( $response, 500 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Dispatcher;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -116,7 +116,7 @@ class _Setup extends \IPS\Dispatcher
|
||||
{
|
||||
try
|
||||
{
|
||||
file_put_contents( \IPS\ROOT_PATH . '/conf_global.php', '' );
|
||||
file_put_contents( \IPS\ROOT_PATH. '/conf_global.php', '' );
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
@@ -137,7 +137,7 @@ class _Setup extends \IPS\Dispatcher
|
||||
/* Upgrader Checks */
|
||||
else
|
||||
{
|
||||
if ( !file_exists( \IPS\ROOT_PATH . '/conf_global.php' ) )
|
||||
if ( !file_exists( \IPS\SITE_FILES_PATH . '/conf_global.php' ) )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Member::loggedIn()->language()->addToStack('upgrade_error'), '', \IPS\Member::loggedIn()->language()->addToStack('no_conf_global'), \IPS\ROOT_PATH ), 200, 'text/html', array(), FALSE );
|
||||
}
|
||||
@@ -152,7 +152,7 @@ class _Setup extends \IPS\Dispatcher
|
||||
}
|
||||
}
|
||||
|
||||
require \IPS\ROOT_PATH . '/conf_global.php';
|
||||
require \IPS\SITE_FILES_PATH . '/conf_global.php';
|
||||
if ( !isset( $INFO ) )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Member::loggedIn()->language()->addToStack('upgrade_error'), '', \IPS\Member::loggedIn()->language()->addToStack('bad_conf_global'), \IPS\ROOT_PATH ), 200, 'text/html', array(), FALSE );
|
||||
@@ -197,8 +197,7 @@ class _Setup extends \IPS\Dispatcher
|
||||
|
||||
if( !@session_start() )
|
||||
{
|
||||
$lastError = error_get_last();
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'session_no_good', FALSE, array( 'sprintf' => array( $lastError['message'] ) ) ), '4S109/5', 500, '' );
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'session_no_good', FALSE, array( 'sprintf' => array( \IPS\IPS::$lastError ? \IPS\IPS::$lastError->getMessage() : NULL ) ) ), '4S109/5', 500, '' );
|
||||
}
|
||||
|
||||
if( $this->classname != 'IPS\core\modules\setup\upgrade\done' and $this->setupLocation != 'install' and $this->step > 1 AND ( !isset( $_SESSION['uniqueKey'] ) OR $_SESSION['uniqueKey'] != \IPS\Request::i()->key ) )
|
||||
@@ -223,11 +222,11 @@ class _Setup extends \IPS\Dispatcher
|
||||
/* If we're still here - output */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( \IPS\Output::i()->output ), 200, 'text/html', \IPS\Output::i()->httpHeaders, FALSE, FALSE, TRUE, FALSE );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( \IPS\Output::i()->output ), 200, 'text/html', array(), FALSE, FALSE, TRUE, FALSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, \IPS\Output::i()->output ), 200, 'text/html', \IPS\Output::i()->httpHeaders, FALSE, FALSE, TRUE, FALSE );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, \IPS\Output::i()->output ), 200, 'text/html', array(), FALSE, FALSE, TRUE, FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace IPS\Dispatcher;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
@@ -58,7 +58,7 @@ abstract class _Standard extends \IPS\Dispatcher
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( \IPS\Lang::languages() ) > 1 )
|
||||
if ( \count( \IPS\Lang::languages() ) > 1 )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'flags.css', 'core', 'global' ) );
|
||||
}
|
||||
@@ -82,20 +82,15 @@ abstract class _Standard extends \IPS\Dispatcher
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'plugins.js', 'core', 'plugins' ) );
|
||||
\IPS\Output::i()->jsVars['date_format'] = mb_strtolower( \IPS\Member::loggedIn()->language()->preferredDateFormat() );
|
||||
\IPS\Output::i()->jsVars['date_first_day'] = 0;
|
||||
\IPS\Output::i()->jsVars['remote_image_proxy'] = intval( \IPS\Settings::i()->remote_image_proxy );
|
||||
\IPS\Output::i()->jsVars['ipb_url_filter_option'] = \IPS\Settings::i()->ipb_url_filter_option;
|
||||
\IPS\Output::i()->jsVars['url_filter_any_action'] = \IPS\Settings::i()->url_filter_any_action;
|
||||
\IPS\Output::i()->jsVars['bypass_profanity'] = intval( \IPS\Member::loggedIn()->group['g_bypass_badwords'] );
|
||||
\IPS\Output::i()->jsVars['bypass_profanity'] = \intval( \IPS\Member::loggedIn()->group['g_bypass_badwords'] );
|
||||
\IPS\Output::i()->jsVars['emoji_style'] = ( \IPS\Settings::i()->getFromConfGlobal('sql_utf8mb4') === TRUE ) ? \IPS\Settings::i()->emoji_style : 'disabled';
|
||||
\IPS\Output::i()->jsVars['emoji_shortcodes'] = \IPS\Settings::i()->emoji_shortcodes;
|
||||
\IPS\Output::i()->jsVars['emoji_ascii'] = \IPS\Settings::i()->emoji_ascii;
|
||||
\IPS\Output::i()->jsVars['emoji_cache'] = \IPS\Settings::i()->emoji_cache;
|
||||
|
||||
/* Load the howler JS package if notifications are enabled */
|
||||
if( !\IPS\Member::loggedIn()->members_bitoptions['disable_notification_sounds'] )
|
||||
{
|
||||
array_unshift( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'howler/howler.core.min.js', 'core', 'interface' )[0] );
|
||||
}
|
||||
\IPS\Output::i()->jsVars['emoji_shortcodes'] = (bool) \IPS\Settings::i()->emoji_shortcodes;
|
||||
\IPS\Output::i()->jsVars['emoji_ascii'] = (bool) \IPS\Settings::i()->emoji_ascii;
|
||||
\IPS\Output::i()->jsVars['emoji_cache'] = (int) \IPS\Settings::i()->emoji_cache;
|
||||
\IPS\Output::i()->jsVars['image_jpg_quality'] = (int) \IPS\Settings::i()->image_jpg_quality ?: 85;
|
||||
\IPS\Output::i()->jsVars['cloud2'] = (bool) \IPS\CIC2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +224,7 @@ abstract class _Standard extends \IPS\Dispatcher
|
||||
/* Set controller */
|
||||
$this->controller = isset( \IPS\Request::i()->controller ) ? \IPS\Request::i()->controller : $this->module->default_controller;
|
||||
|
||||
if( is_array( $this->controller ) )
|
||||
if( \is_array( $this->controller ) )
|
||||
{
|
||||
$this->controller = NULL;
|
||||
throw new \DomainException( 'requested_route_404', 7 );
|
||||
@@ -311,15 +306,17 @@ abstract class _Standard extends \IPS\Dispatcher
|
||||
public function __destruct()
|
||||
{
|
||||
/* If you visit and you are redirected to installer, this code should not run */
|
||||
if( !file_exists( \IPS\ROOT_PATH . '/conf_global.php' ) )
|
||||
if( !file_exists( \IPS\SITE_FILES_PATH . '/conf_global.php' ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( \IPS\Session\Front::loggedIn() and \IPS\Settings::i()->task_use_cron == 'normal' )
|
||||
if ( \IPS\Member::loggedIn()->member_id and \IPS\Settings::i()->task_use_cron == 'normal' and !\IPS\Request::i()->isAjax() )
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\Db::i()->readWriteSeparation = FALSE;
|
||||
|
||||
$task = \IPS\Task::queued();
|
||||
if ( $task )
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user