diff options
author | Morris Jobke <hey@morrisjobke.de> | 2018-01-29 18:12:10 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-29 18:12:10 +0300 |
commit | 4fcdfbf5de5496cf1fc683b6a2f4c55764de8e02 (patch) | |
tree | 2daf3982a94dec5538b5defaecf5f86280ddad6c /lib | |
parent | 01482b32a171bb8529bc8baacbe764107e52e14c (diff) | |
parent | 5dbf73339542977698e1f3ae6d22624fab74fe3e (diff) |
Merge pull request #8078 from nextcloud/theming-validate-scss
SCSS hardening
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/Template/SCSSCacher.php | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/lib/private/Template/SCSSCacher.php b/lib/private/Template/SCSSCacher.php index a4604425544..8830a651f36 100644 --- a/lib/private/Template/SCSSCacher.php +++ b/lib/private/Template/SCSSCacher.php @@ -57,12 +57,18 @@ class SCSSCacher { /** @var IConfig */ protected $config; + /** @var \OC_Defaults */ + private $defaults; + /** @var string */ protected $serverRoot; /** @var ICache */ protected $depsCache; + /** @var null|string */ + private $injectedVariables; + /** * @param ILogger $logger * @param Factory $appDataFactory @@ -90,12 +96,14 @@ class SCSSCacher { /** * Process the caching process if needed + * * @param string $root Root path to the nextcloud installation * @param string $file * @param string $app The app name * @return boolean + * @throws NotPermittedException */ - public function process($root, $file, $app) { + public function process(string $root, string $file, string $app): bool { $path = explode('/', $root . '/' . $file); $fileNameSCSS = array_pop($path); @@ -123,7 +131,7 @@ class SCSSCacher { * @param $fileName * @return ISimpleFile */ - public function getCachedCSS($appName, $fileName) { + public function getCachedCSS(string $appName, string $fileName): ISimpleFile { $folder = $this->appData->getFolder($appName); return $folder->getFile($this->prependBaseurlPrefix($fileName)); } @@ -134,7 +142,7 @@ class SCSSCacher { * @param ISimpleFolder $folder * @return boolean */ - private function isCached($fileNameCSS, ISimpleFolder $folder) { + private function isCached(string $fileNameCSS, ISimpleFolder $folder) { try { $cachedFile = $folder->getFile($fileNameCSS); if ($cachedFile->getSize() > 0) { @@ -148,13 +156,14 @@ class SCSSCacher { } $deps = json_decode($deps, true); - foreach ($deps as $file=>$mtime) { + foreach ((array)$deps as $file=>$mtime) { if (!file_exists($file) || filemtime($file) > $mtime) { return false; } } + return true; } - return true; + return false; } catch(NotFoundException $e) { return false; } @@ -164,7 +173,7 @@ class SCSSCacher { * Check if the variables file has changed * @return bool */ - private function variablesChanged() { + private function variablesChanged(): bool { $injectedVariables = $this->getInjectedVariables(); if($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) { $this->resetCache(); @@ -176,14 +185,16 @@ class SCSSCacher { /** * Cache the file with AppData + * * @param string $path * @param string $fileNameCSS * @param string $fileNameSCSS * @param ISimpleFolder $folder * @param string $webDir * @return boolean + * @throws NotPermittedException */ - private function cache($path, $fileNameCSS, $fileNameSCSS, ISimpleFolder $folder, $webDir) { + private function cache(string $path, string $fileNameCSS, string $fileNameSCSS, ISimpleFolder $folder, string $webDir) { $scss = new Compiler(); $scss->setImportPaths([ $path, @@ -250,13 +261,14 @@ class SCSSCacher { * We need to regenerate all files when variables change */ private function resetCache() { + $this->injectedVariables = null; $appDirectory = $this->appData->getDirectoryListing(); if(empty($appDirectory)){ return; } foreach ($appDirectory as $folder) { foreach ($folder->getDirectoryListing() as $file) { - if (substr($file->getName(), -3) === "css" || substr($file->getName(), -4) === "deps") { + if (substr($file->getName(), -3) === 'css' || substr($file->getName(), -4) === 'deps') { $file->delete(); } } @@ -266,11 +278,24 @@ class SCSSCacher { /** * @return string SCSS code for variables from OC_Defaults */ - private function getInjectedVariables() { + private function getInjectedVariables(): string { + if ($this->injectedVariables !== null) { + return $this->injectedVariables; + } $variables = ''; foreach ($this->defaults->getScssVariables() as $key => $value) { $variables .= '$' . $key . ': ' . $value . ';'; } + + // check for valid variables / otherwise fall back to defaults + try { + $scss = new Compiler(); + $scss->compile($variables); + $this->injectedVariables = $variables; + } catch (ParserException $e) { + $this->logger->error($e, ['app' => 'core']); + } + return $variables; } @@ -280,8 +305,8 @@ class SCSSCacher { * @param string $webDir * @return string */ - private function rebaseUrls($css, $webDir) { - $re = '/url\([\'"]([\.\w?=\/-]*)[\'"]\)/x'; + private function rebaseUrls(string $css, string $webDir): string { + $re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x'; $subst = 'url(\''.$webDir.'/$1\')'; return preg_replace($re, $subst, $css); } @@ -292,20 +317,20 @@ class SCSSCacher { * @param string $fileName * @return string */ - public function getCachedSCSS($appName, $fileName) { + public function getCachedSCSS(string $appName, string $fileName): string { $tmpfileLoc = explode('/', $fileName); $fileName = array_pop($tmpfileLoc); $fileName = $this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)); - return substr($this->urlGenerator->linkToRoute('core.Css.getCss', array('fileName' => $fileName, 'appName' => $appName)), strlen(\OC::$WEBROOT) + 1); + return substr($this->urlGenerator->linkToRoute('core.Css.getCss', ['fileName' => $fileName, 'appName' => $appName]), strlen(\OC::$WEBROOT) + 1); } /** * Prepend hashed base url to the css file - * @param $cssFile + * @param string$cssFile * @return string */ - private function prependBaseurlPrefix($cssFile) { + private function prependBaseurlPrefix(string $cssFile): string { $frontendController = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true'); return substr(md5($this->urlGenerator->getBaseUrl() . $frontendController), 0, 8) . '-' . $cssFile; } @@ -318,7 +343,7 @@ class SCSSCacher { * @param string $webRoot the nextcloud installation root path * @return string the webDir */ - private function getWebDir($path, $appName, $serverRoot, $webRoot) { + private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string { // Detect if path is within server root AND if path is within an app path if ( strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) { // Get the file path within the app directory |