Version 4.6.0
This commit is contained in:
1 parent
f79dcf067a
commit
517a5e1f70
2036 files changed
+110041
-26162
No files matched your search
@@ -56,9 +56,6 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
\IPS\Output::i()->sidebar['appmenu'] = '';
|
||||
|
||||
/* Disable sending of referrer to third party sites from AdminCP */
|
||||
\IPS\Output::i()->sendHeader( "Referrer-Policy: origin-when-cross-origin" );
|
||||
|
||||
/* Sync stuff when in developer mode */
|
||||
if ( \IPS\IN_DEV )
|
||||
{
|
||||
@@ -176,7 +173,13 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
}
|
||||
|
||||
|
||||
\IPS\Db::i()->readWriteSeparation = FALSE;
|
||||
if ( isset( $this->classname::$allowRWSeparation ) and $this->classname::$allowRWSeparation )
|
||||
{
|
||||
\IPS\Db::i()->readWriteSeparation = TRUE;
|
||||
}
|
||||
|
||||
/* 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' ) ) )
|
||||
{
|
||||
@@ -413,6 +416,16 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
$_apps = array_keys( $acpTabOrder );
|
||||
uksort( $this->menu['tabs'], function($a, $b) use ( $_apps )
|
||||
{
|
||||
if( !\in_array( $a, $_apps ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( !\in_array( $b, $_apps ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return array_search( $a, $_apps ) - array_search( $b, $_apps );
|
||||
} );
|
||||
|
||||
@@ -424,6 +437,16 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
uksort( $this->menu['tabs'][ $app ], function($a, $b) use ( $submenu )
|
||||
{
|
||||
if( !\in_array( $a, $submenu ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( !\in_array( $b, $submenu ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return array_search( $a, $submenu ) - array_search( $b, $submenu );
|
||||
} );
|
||||
}
|
||||
|
||||
@@ -327,6 +327,9 @@ class _Api extends \IPS\Dispatcher
|
||||
/* Run it */
|
||||
$controller = new $class( $this->apiKey, $this->accessToken );
|
||||
$response = $controller->execute( $pathBits, $shouldLog );
|
||||
|
||||
/* Store if we need to mask anything in logs */
|
||||
$this->parametersToMask = ( $controller->methodCalled AND isset( $controller->parametersToMask[ $controller->methodCalled ] ) ) ? $controller->parametersToMask[ $controller->methodCalled ] : NULL;
|
||||
|
||||
/* Send Output */
|
||||
$output = $response->getOutput();
|
||||
@@ -345,6 +348,11 @@ class _Api extends \IPS\Dispatcher
|
||||
$this->_respond( json_encode( array( 'errorCode' => 'EX' . $e->getCode(), 'errorMessage' => \IPS\IN_DEV ? $e->getMessage() : 'UNKNOWN_ERROR' ), JSON_PRETTY_PRINT ), 500 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parameters to mask in logs per the controller
|
||||
*/
|
||||
protected $parametersToMask = NULL;
|
||||
|
||||
/**
|
||||
* Log
|
||||
@@ -358,12 +366,25 @@ class _Api extends \IPS\Dispatcher
|
||||
{
|
||||
try
|
||||
{
|
||||
$_requestData = $_REQUEST;
|
||||
|
||||
if( $this->parametersToMask AND \count( $this->parametersToMask ) )
|
||||
{
|
||||
foreach( $_requestData as $k => $v )
|
||||
{
|
||||
if( \in_array( $k, $this->parametersToMask ) )
|
||||
{
|
||||
$_requestData[ $k ] = '******';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Db::i()->insert( 'core_api_logs', array(
|
||||
'endpoint' => $this->path,
|
||||
'method' => $_SERVER['REQUEST_METHOD'],
|
||||
'api_key' => $this->rawApiKey,
|
||||
'ip_address' => \IPS\Request::i()->ipAddress(),
|
||||
'request_data' => json_encode( $_REQUEST, JSON_PRETTY_PRINT ),
|
||||
'request_data' => json_encode( $_requestData, JSON_PRETTY_PRINT ),
|
||||
'response_code' => $httpResponseCode,
|
||||
'response_output' => $response,
|
||||
'date' => time(),
|
||||
@@ -387,7 +408,8 @@ class _Api extends \IPS\Dispatcher
|
||||
*/
|
||||
protected function _respond( $response, $httpResponseCode, $oauthError=NULL, $log=FALSE )
|
||||
{
|
||||
$headers = array();
|
||||
$headers = ( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' ) ? \IPS\Output::getCacheHeaders( time(), 60 ) : \IPS\Output::getNoCacheHeaders();
|
||||
|
||||
if ( $this->rawAccessToken and $oauthError )
|
||||
{
|
||||
$headers['WWW-Authenticate'] = "Bearer error=\"{$oauthError}\"";
|
||||
|
||||
@@ -98,9 +98,10 @@ abstract class _Dispatcher
|
||||
$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" );
|
||||
foreach( \IPS\Output::getNoCacheHeaders() as $headerKey => $headerValue )
|
||||
{
|
||||
header( "{$headerKey}: {$headerValue}" );
|
||||
}
|
||||
header( "Location: {$url}/" . \IPS\CP_DIRECTORY . "/install/" );
|
||||
exit;
|
||||
}
|
||||
|
||||
+60
-28
@@ -48,9 +48,10 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
|
||||
/* 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" );
|
||||
foreach( \IPS\Output::getNoCacheHeaders() as $headerKey => $headerValue )
|
||||
{
|
||||
header( "{$headerKey}: {$headerValue}" );
|
||||
}
|
||||
|
||||
if ( \IPS\CIC and ! \IPS\Session\Front::loggedIn() and ! \IPS\Session\Front::i()->userAgent->spider )
|
||||
{
|
||||
@@ -121,11 +122,7 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
|
||||
/* 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' ) ) );
|
||||
}
|
||||
$this->_setReferralCookie();
|
||||
|
||||
/* Enable sidebar by default (controllers can turn it off if needed) */
|
||||
\IPS\Output::i()->sidebar['enabled'] = ( \IPS\Request::i()->isAjax() ) ? FALSE : TRUE;
|
||||
@@ -153,7 +150,14 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
|
||||
/* Member Ban? */
|
||||
$ipBanned = \IPS\Request::i()->ipAddressIsBanned();
|
||||
|
||||
/* IP Ban check happens only the Login and Register Controller for guests */
|
||||
$ipBanned = FALSE;
|
||||
if( \IPS\Member::loggedIn()->member_id OR \in_array( $this->controller, array( 'register', 'login' ) ) )
|
||||
{
|
||||
$ipBanned = \IPS\Request::i()->ipAddressIsBanned();
|
||||
}
|
||||
|
||||
if ( $ipBanned or $banEnd = \IPS\Member::loggedIn()->isBanned() )
|
||||
{
|
||||
if ( !$ipBanned and !\IPS\Member::loggedIn()->member_id )
|
||||
@@ -188,7 +192,7 @@ 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', 'embed', 'metatags' );
|
||||
$legalControllers = array( 'privacy', 'contact', 'terms', 'embed', 'metatags', 'store', 'checkout', 'subscriptions' );
|
||||
|
||||
/* 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 ) )
|
||||
@@ -219,19 +223,9 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 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', 'embed' ) ) )
|
||||
if ( !\in_array( $this->controller, array( 'register', 'login', 'redirect', 'ajax', 'settings', 'embed' ) ) )
|
||||
{
|
||||
$haveAcceptableHandlers = FALSE;
|
||||
$haveConfiguredHandler = FALSE;
|
||||
@@ -263,6 +257,18 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Need to reset password */
|
||||
if ( $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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Permission Check */
|
||||
@@ -325,6 +331,20 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the referral cookie if appropriate
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _setReferralCookie()
|
||||
{
|
||||
/* 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' ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the URL we visited is correct and route appropriately
|
||||
*
|
||||
@@ -431,8 +451,23 @@ 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 !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 )
|
||||
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\CACHE_PAGE_TIMEOUT )
|
||||
{
|
||||
/* Check whether a 304 Not modified response is appropriate */
|
||||
if( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) AND ( new \IPS\DateTime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) )->getTimestamp() > ( time() - \IPS\CACHE_PAGE_TIMEOUT ) )
|
||||
{
|
||||
/* This is intentionally using PHP methods to avoid database connections */
|
||||
$this->destruct = false;
|
||||
header('HTTP/1.1 304 Not Modified' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/* Only check the output cache if it is enabled */
|
||||
if( empty( \IPS\OUTPUT_CACHE_METHOD ) OR ( !empty( \IPS\OUTPUT_CACHE_METHOD ) AND \IPS\OUTPUT_CACHE_METHOD == 'None' ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Which language? */
|
||||
if ( isset( \IPS\Request::i()->cookie['language'] ) )
|
||||
{
|
||||
@@ -464,11 +499,8 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
/* 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 );
|
||||
}
|
||||
|
||||
$this->_setReferralCookie();
|
||||
|
||||
\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 );
|
||||
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ class _GraphQL extends Api
|
||||
|
||||
/* Execute! */
|
||||
$result = \GraphQL\GraphQL::executeQuery(
|
||||
new \GraphQL\Schema([
|
||||
new \GraphQL\Type\Schema([
|
||||
'query' => \IPS\Api\GraphQL\TypeRegistry::query(),
|
||||
'mutation' => \IPS\Api\GraphQL\TypeRegistry::mutation()
|
||||
]),
|
||||
@@ -136,7 +136,7 @@ class _GraphQL extends Api
|
||||
);
|
||||
|
||||
/* 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 );
|
||||
$output = $result->toArray( ( \IPS\IN_DEV OR \IPS\DEBUG_GRAPHQL ) ? \GraphQL\Error\DebugFlag::INCLUDE_DEBUG_MESSAGE | \GraphQL\Error\DebugFlag::INCLUDE_TRACE : false );
|
||||
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $output );
|
||||
$this->_respond( json_encode( $output, JSON_PRETTY_PRINT ), 200 );
|
||||
|
||||
|
||||
@@ -113,6 +113,11 @@ abstract class _Standard extends \IPS\Dispatcher
|
||||
parent::finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize tasks
|
||||
*/
|
||||
protected $runTasks = FALSE;
|
||||
|
||||
/**
|
||||
* Init
|
||||
*
|
||||
@@ -121,6 +126,8 @@ abstract class _Standard extends \IPS\Dispatcher
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->runTasks = (bool) \IPS\Member::loggedIn()->member_id;
|
||||
|
||||
/* Force HTTPs and correct domain (e.g. not "www." if that's not in the base URL) */
|
||||
if ( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' )
|
||||
{
|
||||
@@ -297,6 +304,12 @@ abstract class _Standard extends \IPS\Dispatcher
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable destruct method
|
||||
* @note Disable to avoid an automatic database connection
|
||||
*/
|
||||
public $destruct = true;
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
* Runs tasks
|
||||
@@ -306,17 +319,15 @@ 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\SITE_FILES_PATH . '/conf_global.php' ) )
|
||||
if( !file_exists( \IPS\SITE_FILES_PATH . '/conf_global.php' ) OR !$this->destruct )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->member_id and \IPS\Settings::i()->task_use_cron == 'normal' and !\IPS\Request::i()->isAjax() )
|
||||
if ( $this->runTasks 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