From 9fea092c4394aa11c766aa3403199dfd4ebf5127 Mon Sep 17 00:00:00 2001
From: the-djmaze <>
Date: Tue, 11 Jan 2022 15:55:48 +0100
Subject: [PATCH] Cleanup RainLoop\Service with improved ?admin path detection
---
dev/Common/Links.js | 12 +-
plugins/README.md | 4 -
.../libraries/RainLoop/Plugins/Manager.php | 2 +-
.../0.0.0/app/libraries/RainLoop/Service.php | 116 ++++++++----------
.../app/libraries/RainLoop/ServiceActions.php | 11 +-
5 files changed, 63 insertions(+), 82 deletions(-)
diff --git a/dev/Common/Links.js b/dev/Common/Links.js
index b8769e56bf..8ed3a9da77 100644
--- a/dev/Common/Links.js
+++ b/dev/Common/Links.js
@@ -6,7 +6,11 @@ const
HASH_PREFIX = '#/',
SERVER_PREFIX = './?',
VERSION = Settings.app('version'),
- VERSION_PREFIX = Settings.app('webVersionPath') || 'snappymail/v/' + VERSION + '/';
+ VERSION_PREFIX = Settings.app('webVersionPath') || 'snappymail/v/' + VERSION + '/',
+
+ adminPath = () => rl.adminArea() && !Settings.app('adminHostUse'),
+
+ prefix = () => SERVER_PREFIX + (adminPath() ? Settings.app('adminPath') : '');
export const
SUB_QUERY_PREFIX = '&q[]=',
@@ -20,9 +24,7 @@ export const
/**
* @returns {string}
*/
- logoutLink = () => (rl.adminArea() && !Settings.app('adminHostUse'))
- ? SERVER_PREFIX + Settings.app('adminPath')
- : ROOT,
+ logoutLink = () => adminPath() ? prefix() : ROOT,
/**
* @param {string} type
@@ -49,7 +51,7 @@ export const
* @param {string} type
* @returns {string}
*/
- serverRequest = type => SERVER_PREFIX + '/' + type + '/' + SUB_QUERY_PREFIX + '/0/',
+ serverRequest = type => prefix() + '/' + type + '/' + SUB_QUERY_PREFIX + '/0/',
/**
* @param {string} lang
diff --git a/plugins/README.md b/plugins/README.md
index 2a830deeae..fe34753101 100644
--- a/plugins/README.md
+++ b/plugins/README.md
@@ -178,10 +178,6 @@ $Plugin->addHook('hook.name', 'functionName');
params:
array &$aPaths
-### filter.http-query
- params:
- string &$sQuery
-
### filter.json-response
params:
string $sAction
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php
index 9f679de2de..84def593fa 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php
@@ -34,7 +34,7 @@ public function __construct(\RainLoop\Actions $oActions)
$this->oLogger = null;
$this->oActions = $oActions;
- $oConfig = $this->oActions->Config();
+ $oConfig = $oActions->Config();
$this->bIsEnabled = (bool) $oConfig->Get('plugins', 'enable', false);
if ($this->bIsEnabled) {
$sList = $oConfig->Get('plugins', 'enabled_list', '');
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Service.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Service.php
index 7da25e125e..dd808ca713 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Service.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Service.php
@@ -2,31 +2,8 @@
namespace RainLoop;
-class Service
+abstract class Service
{
- /**
- * @var \MailSo\Base\Http
- */
- private $oHttp;
-
- /**
- * @var \RainLoop\Actions
- */
- private $oActions;
-
- /**
- * @var \RainLoop\ServiceActions
- */
- private $oServiceActions;
-
- function __construct()
- {
- $this->oHttp = \MailSo\Base\Http::SingletonInstance();
- $this->oActions = Api::Actions();
-
- $this->oServiceActions = new ServiceActions($this->oHttp, $this->oActions);
- }
-
/**
* @staticvar bool $bOne
*/
@@ -35,23 +12,23 @@ public static function Handle() : bool
static $bOne = null;
if (null === $bOne)
{
- $bOne = (new self)->RunResult();
+ $bOne = static::RunResult();
}
return $bOne;
}
- public function RunResult() : bool
+ private static function RunResult() : bool
{
- if ($this->oActions->Config()->Get('debug', 'enable', false))
+ $oConfig = Api::Config();
+
+ if ($oConfig->Get('debug', 'enable', false))
{
\error_reporting(E_ALL);
\ini_set('display_errors', 1);
\ini_set('log_errors', 1);
}
- $oConfig = $this->oActions->Config();
-
$sServer = \trim($oConfig->Get('security', 'custom_server_signature', ''));
if (\strlen($sServer))
{
@@ -64,7 +41,7 @@ public function RunResult() : bool
// Google FLoC
\header('Permissions-Policy: interest-cohort=()');
- $this->setCSP();
+ static::setCSP();
$sXFrameOptionsHeader = \trim($oConfig->Get('security', 'x_frame_options_header', '')) ?: 'DENY';
\header('X-Frame-Options: '.$sXFrameOptionsHeader);
@@ -72,9 +49,10 @@ public function RunResult() : bool
$sXssProtectionOptionsHeader = \trim($oConfig->Get('security', 'x_xss_protection_header', '')) ?: '1; mode=block';
\header('X-XSS-Protection: '.$sXssProtectionOptionsHeader);
- if ($oConfig->Get('labs', 'force_https', false) && !$this->oHttp->IsSecure())
+ $oHttp = \MailSo\Base\Http::SingletonInstance();
+ if ($oConfig->Get('labs', 'force_https', false) && !$oHttp->IsSecure())
{
- \header('Location: https://'.$this->oHttp->GetHost(false, false).$this->oHttp->GetUrl());
+ \header('Location: https://'.$oHttp->GetHost(false, false).$oHttp->GetUrl());
exit(0);
}
@@ -95,32 +73,36 @@ public function RunResult() : bool
}
}
- $this->oActions->Plugins()->RunHook('filter.http-query', array(&$sQuery));
$aPaths = \explode('/', $sQuery);
-// unset($aPaths[1]); // was the rlspecauth/AuthAccountHash token
- $this->oActions->Plugins()->RunHook('filter.http-paths', array(&$aPaths));
$bAdmin = false;
$sAdminPanelHost = $oConfig->Get('security', 'admin_panel_host', '');
if (empty($sAdminPanelHost))
{
$bAdmin = !empty($aPaths[0]) && ($oConfig->Get('security', 'admin_panel_key', '') ?: 'admin') === $aPaths[0];
+ $bAdmin && \array_shift($aPaths);
}
- else if (empty($aPaths[0]) &&
- \mb_strtolower($sAdminPanelHost) === \mb_strtolower($this->oHttp->GetHost()))
+ else if (empty($aPaths[0]) && \mb_strtolower($sAdminPanelHost) === \mb_strtolower($oHttp->GetHost()))
{
$bAdmin = true;
}
- if ($this->oHttp->IsPost())
+ $oActions = Api::Actions();
+// $oActions = $bAdmin ? new ActionsAdmin() : Api::Actions();
+
+ $oActions->Plugins()->RunHook('filter.http-paths', array(&$aPaths));
+
+ if ($oHttp->IsPost())
{
- $this->oHttp->ServerNoCache();
+ $oHttp->ServerNoCache();
}
+ $oServiceActions = new ServiceActions($oHttp, $oActions);
+
if ($bAdmin && !$oConfig->Get('security', 'allow_admin_panel', true))
{
\MailSo\Base\Http::StatusHeader(403);
- echo $this->oServiceActions->ErrorTemplates('Access Denied.',
+ echo $oServiceActions->ErrorTemplates('Access Denied.',
'Access to the SnappyMail Admin Panel is not allowed!');
return false;
@@ -128,11 +110,11 @@ public function RunResult() : bool
$bIndex = true;
$sResult = '';
- if (\count($aPaths) && !empty($aPaths[0]) && !$bAdmin && 'index' !== \strtolower($aPaths[0]))
+ if (\count($aPaths) && !empty($aPaths[0]) && 'index' !== \strtolower($aPaths[0]))
{
if (!\SnappyMail\HTTP\SecFetch::isSameOrigin()) {
\MailSo\Base\Http::StatusHeader(403);
- echo $this->oServiceActions->ErrorTemplates('Access Denied.',
+ echo $oServiceActions->ErrorTemplates('Access Denied.',
"Disallowed Sec-Fetch
Dest: " . ($_SERVER['HTTP_SEC_FETCH_DEST'] ?? '') . "
Mode: " . ($_SERVER['HTTP_SEC_FETCH_MODE'] ?? '') . "
@@ -145,13 +127,13 @@ public function RunResult() : bool
$sMethodName = 'Service'.\preg_replace('/@.+$/', '', $aPaths[0]);
$sMethodExtra = \strpos($aPaths[0], '@') ? \preg_replace('/^[^@]+@/', '', $aPaths[0]) : '';
- if (\method_exists($this->oServiceActions, $sMethodName) &&
- \is_callable(array($this->oServiceActions, $sMethodName)))
+ if (\method_exists($oServiceActions, $sMethodName) &&
+ \is_callable(array($oServiceActions, $sMethodName)))
{
- $this->oServiceActions->SetQuery($sQuery)->SetPaths($aPaths);
- $sResult = $this->oServiceActions->{$sMethodName}($sMethodExtra);
+ $oServiceActions->SetQuery($sQuery)->SetPaths($aPaths);
+ $sResult = $oServiceActions->{$sMethodName}($sMethodExtra);
}
- else if (!$this->oActions->Plugins()->RunAdditionalPart($aPaths[0], $aPaths))
+ else if (!$oActions->Plugins()->RunAdditionalPart($aPaths[0], $aPaths))
{
$bIndex = true;
}
@@ -161,11 +143,11 @@ public function RunResult() : bool
{
// if (!\SnappyMail\HTTP\SecFetch::isEntering()) {
\header('Content-Type: text/html; charset=utf-8');
- $this->oHttp->ServerNoCache();
+ $oHttp->ServerNoCache();
if (!\is_dir(APP_DATA_FOLDER_PATH) || !\is_writable(APP_DATA_FOLDER_PATH))
{
- echo $this->oServiceActions->ErrorTemplates(
+ echo $oServiceActions->ErrorTemplates(
'Permission denied!',
'SnappyMail can not access the data folder "'.APP_DATA_FOLDER_PATH.'"'
);
@@ -173,22 +155,22 @@ public function RunResult() : bool
return false;
}
- $sLanguage = $this->oActions->GetLanguage($bAdmin);
+ $sLanguage = $oActions->GetLanguage($bAdmin);
$sAppJsMin = $oConfig->Get('labs', 'use_app_debug_js', false) ? '' : '.min';
$sAppCssMin = $oConfig->Get('labs', 'use_app_debug_css', false) ? '' : '.min';
$sFaviconUrl = (string) $oConfig->Get('webmail', 'favicon_url', '');
- $sFaviconPngLink = $sFaviconUrl ? $sFaviconUrl : $this->oActions->StaticPath('apple-touch-icon.png');
- $sAppleTouchLink = $sFaviconUrl ? '' : $this->oActions->StaticPath('apple-touch-icon.png');
+ $sFaviconPngLink = $sFaviconUrl ? $sFaviconUrl : $oActions->StaticPath('apple-touch-icon.png');
+ $sAppleTouchLink = $sFaviconUrl ? '' : $oActions->StaticPath('apple-touch-icon.png');
$aTemplateParameters = array(
'{{BaseAppFaviconPngLinkTag}}' => $sFaviconPngLink ? '' : '',
'{{BaseAppFaviconTouchLinkTag}}' => $sAppleTouchLink ? '' : '',
- '{{BaseAppMainCssLink}}' => $this->oActions->StaticPath('css/'.($bAdmin ? 'admin' : 'app').$sAppCssMin.'.css'),
- '{{BaseAppThemeCssLink}}' => $this->oActions->ThemeLink($bAdmin),
- '{{BaseAppManifestLink}}' => $this->oActions->StaticPath('manifest.json'),
+ '{{BaseAppMainCssLink}}' => $oActions->StaticPath('css/'.($bAdmin ? 'admin' : 'app').$sAppCssMin.'.css'),
+ '{{BaseAppThemeCssLink}}' => $oActions->ThemeLink($bAdmin),
+ '{{BaseAppManifestLink}}' => $oActions->StaticPath('manifest.json'),
'{{LoadingDescriptionEsc}}' => \htmlspecialchars($oConfig->Get('webmail', 'loading_description', 'SnappyMail'), ENT_QUOTES|ENT_IGNORE, 'UTF-8'),
'{{BaseAppAdmin}}' => $bAdmin ? 1 : 0
);
@@ -199,22 +181,22 @@ public function RunResult() : bool
$sCacheFileName = 'TMPL:' . $sLanguage . \md5(
\json_encode(array(
$oConfig->Get('cache', 'index', ''),
- $this->oActions->Plugins()->Hash(),
+ $oActions->Plugins()->Hash(),
$sAppJsMin,
$sAppCssMin,
$aTemplateParameters,
APP_VERSION
))
);
- $sResult = $this->oActions->Cacher()->Get($sCacheFileName);
+ $sResult = $oActions->Cacher()->Get($sCacheFileName);
}
if ($sResult) {
$sResult .= '';
} else {
- $aTemplateParameters['{{BaseAppThemeCss}}'] = $this->oActions->compileCss($this->oActions->GetTheme($bAdmin), $bAdmin);
- $aTemplateParameters['{{BaseLanguage}}'] = $this->oActions->compileLanguage($sLanguage, $bAdmin);
- $aTemplateParameters['{{BaseTemplates}}'] = $this->oServiceActions->compileTemplates($bAdmin);
+ $aTemplateParameters['{{BaseAppThemeCss}}'] = $oActions->compileCss($oActions->GetTheme($bAdmin), $bAdmin);
+ $aTemplateParameters['{{BaseLanguage}}'] = $oActions->compileLanguage($sLanguage, $bAdmin);
+ $aTemplateParameters['{{BaseTemplates}}'] = $oServiceActions->compileTemplates($bAdmin);
$aTemplateParameters['{{BaseAppBootCss}}'] = \file_get_contents(APP_VERSION_ROOT_PATH.'static/css/boot'.$sAppCssMin.'.css');
$aTemplateParameters['{{BaseAppBootScript}}'] = \file_get_contents(APP_VERSION_ROOT_PATH.'static/js'.($sAppJsMin ? '/min' : '').'/boot'.$sAppJsMin.'.js');
$sResult = \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Index.html'), $aTemplateParameters);
@@ -229,17 +211,17 @@ public function RunResult() : bool
$sResult = Utils::ClearHtmlOutput($sResult);
}
if ($sCacheFileName) {
- $this->oActions->Cacher()->Set($sCacheFileName, $sResult);
+ $oActions->Cacher()->Set($sCacheFileName, $sResult);
}
}
$sScriptNonce = \SnappyMail\UUID::generate();
- $this->setCSP($sScriptNonce);
+ static::setCSP($sScriptNonce);
$sResult = \str_replace('nonce=""', 'nonce="'.$sScriptNonce.'"', $sResult);
/*
\preg_match('', $sResult, $script);
$sScriptHash = 'sha256-'.\base64_encode(\hash('sha256', $script[1], true));
- $this->setCSP(null, $sScriptHash);
+ static::setCSP(null, $sScriptHash);
*/
}
else if (!\headers_sent())
@@ -251,17 +233,17 @@ public function RunResult() : bool
echo $sResult;
unset($sResult);
- $this->oActions->BootEnd();
+ $oActions->BootEnd();
return true;
}
- private function setCSP(string $sScriptNonce = null) : void
+ private static function setCSP(string $sScriptNonce = null) : void
{
// "img-src https:" is allowed due to remote images in e-mails
- $sContentSecurityPolicy = \trim($this->oActions->Config()->Get('security', 'content_security_policy', ''))
+ $sContentSecurityPolicy = \trim(Api::Config()->Get('security', 'content_security_policy', ''))
?: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data: https: http:; style-src 'self' 'unsafe-inline'";
- if ($this->oActions->Config()->Get('security', 'use_local_proxy_for_external_images', '')) {
+ if (Api::Config()->Get('security', 'use_local_proxy_for_external_images', '')) {
$sContentSecurityPolicy = \preg_replace('/(img-src[^;]+)\\shttps:(\\s|;|$)/D', '$1$2', $sContentSecurityPolicy);
$sContentSecurityPolicy = \preg_replace('/(img-src[^;]+)\\shttp:(\\s|;|$)/D', '$1$2', $sContentSecurityPolicy);
}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
index d1d9c239f4..177c3cb4e0 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
@@ -99,6 +99,7 @@ public function ServiceJson() : string
}
else if (!empty($sAction))
{
+ // if ($this->oActions instanceof ActionsAdmin)
if (0 === \stripos($sAction, 'Admin') && 'AdminLogin' !== $sAction && 'AdminLogout' !== $sAction) {
$this->oActions->IsAdminLoggined();
}
@@ -335,7 +336,7 @@ public function ServiceProxyExternal() : string
{
$bResult = false;
$sData = empty($this->aPaths[1]) ? '' : $this->aPaths[1];
- if (!empty($sData) && $this->oActions->Config()->Get('labs', 'use_local_proxy_for_external_images', false))
+ if (!empty($sData) && $this->Config()->Get('labs', 'use_local_proxy_for_external_images', false))
{
$this->oActions->verifyCacheByKey($sData);
@@ -419,8 +420,8 @@ public function ServiceRaw() : string
if (\strlen($sRawError))
{
- $this->oActions->Logger()->Write($sRawError, \MailSo\Log\Enumerations\Type::ERROR);
- $this->oActions->Logger()->WriteDump($this->aPaths, \MailSo\Log\Enumerations\Type::ERROR, 'PATHS');
+ $this->Logger()->Write($sRawError, \MailSo\Log\Enumerations\Type::ERROR);
+ $this->Logger()->WriteDump($this->aPaths, \MailSo\Log\Enumerations\Type::ERROR, 'PATHS');
}
if ($oException)
@@ -702,7 +703,7 @@ public function ServiceSso() : string
}
catch (\Throwable $oException)
{
- $this->oActions->Logger()->WriteException($oException);
+ $this->Logger()->WriteException($oException);
}
}
}
@@ -736,7 +737,7 @@ public function ServiceRemoteAutoLogin() : string
}
catch (\Throwable $oException)
{
- $this->oActions->Logger()->WriteException($oException);
+ $this->Logger()->WriteException($oException);
}
}