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 ) );
|
||||
|
||||
Reference in new issue
Block a user