Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Stable12] fix scss webroot and url rewrite #7688

Merged
merged 15 commits into from Jan 5, 2018
4 changes: 2 additions & 2 deletions lib/private/Template/CSSResourceLocator.php
Expand Up @@ -104,7 +104,7 @@ protected function cacheAndAppendScssIfExist($root, $file, $app = 'core') {
if($this->scssCacher !== null) {
if($this->scssCacher->process($root, $file, $app)) {

$this->append($root, $this->scssCacher->getCachedSCSS($app, $file), false, true, true);
$this->append($root, $this->scssCacher->getCachedSCSS($app, $file), \OC::$WEBROOT, true, true);
return true;
} else {
$this->logger->warning('Failed to compile and/or save '.$root.'/'.$file, ['app' => 'core']);
Expand Down Expand Up @@ -141,7 +141,7 @@ public function append($root, $file, $webRoot = null, $throw = true, $scss = fal
}
}

$this->resources[] = array($webRoot? : '/', $webRoot, $file);
$this->resources[] = array($webRoot? : \OC::$WEBROOT, $webRoot, $file);
}
}
}
38 changes: 29 additions & 9 deletions lib/private/Template/SCSSCacher.php
Expand Up @@ -2,6 +2,13 @@
/**
* @copyright Copyright (c) 2016, John Molakvoæ (skjnldsv@protonmail.com)
*
* @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
* @author Julius Haertl <jus@bitgrid.net>
* @author Julius Härtl <jus@bitgrid.net>
* @author Lukas Reschke <lukas@statuscode.ch>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -95,8 +102,7 @@ public function process($root, $file, $app) {
$fileNameCSS = $this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS));

$path = implode('/', $path);

$webDir = substr($path, strlen($this->serverRoot)+1);
$webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT);

try {
$folder = $this->appData->getFolder($app);
Expand Down Expand Up @@ -181,7 +187,7 @@ private function cache($path, $fileNameCSS, $fileNameSCSS, ISimpleFolder $folder
$scss = new Compiler();
$scss->setImportPaths([
$path,
\OC::$SERVERROOT . '/core/css/',
$this->serverRoot . '/core/css/',
]);
// Continue after throw
$scss->setIgnoreErrors(true);
Expand Down Expand Up @@ -276,12 +282,7 @@ private function getInjectedVariables() {
*/
private function rebaseUrls($css, $webDir) {
$re = '/url\([\'"]([\.\w?=\/-]*)[\'"]\)/x';
// OC\Route\Router:75
if(($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) {
$subst = 'url(\'../../'.$webDir.'/$1\')';
} else {
$subst = 'url(\'../../../'.$webDir.'/$1\')';
}
$subst = 'url('.$webDir.'/$1)';
return preg_replace($re, $subst, $css);
}

Expand All @@ -307,4 +308,23 @@ public function getCachedSCSS($appName, $fileName) {
private function prependBaseurlPrefix($cssFile) {
return md5($this->urlGenerator->getBaseUrl()) . '-' . $cssFile;
}

/**
* Get WebDir root
* @param string $path the css file path
* @param string $appName the app name
* @param string $serverRoot the server root path
* @param string $webRoot the nextcloud installation root path
* @return string the webDir
*/
private function getWebDir($path, $appName, $serverRoot, $webRoot) {
// 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
$appDirectoryPath = explode($appName, $path)[1];
// Remove the webroot
return str_replace($webRoot, '', $appWebPath.$appDirectoryPath);
}
return $webRoot.substr($path, strlen($serverRoot));
}
}
11 changes: 11 additions & 0 deletions tests/lib/LegacyHelperTest.php
Expand Up @@ -12,6 +12,17 @@
use OC_Helper;

class LegacyHelperTest extends \Test\TestCase {
/** @var string */
private $originalWebRoot;

public function setUp() {
$this->originalWebRoot = \OC::$WEBROOT;
}

public function tearDown() {
// Reset webRoot
\OC::$WEBROOT = $this->originalWebRoot;
}

/**
* @dataProvider humanFileSizeProvider
Expand Down
2 changes: 1 addition & 1 deletion tests/lib/Template/CSSResourceLocatorTest.php
Expand Up @@ -204,7 +204,7 @@ public function testFindSCSSWithAppPathSymlink() {
$webRoot = $resource[1];
$file = $resource[2];

$expectedRoot = '/';
$expectedRoot = '';
$expectedWebRoot = '';
$expectedFile = 'test-file';

Expand Down
64 changes: 53 additions & 11 deletions tests/lib/Template/SCSSCacherTest.php
Expand Up @@ -352,19 +352,10 @@ public function testCacheFailure() {
}

public function testRebaseUrls() {
$webDir = 'apps/files/css';
$webDir = '/apps/files/css';
$css = '#id { background-image: url(\'../img/image.jpg\'); }';
$actual = self::invokePrivate($this->scssCacher, 'rebaseUrls', [$css, $webDir]);
$expected = '#id { background-image: url(\'../../../apps/files/css/../img/image.jpg\'); }';
$this->assertEquals($expected, $actual);
}

public function testRebaseUrlsIgnoreFrontendController() {
$this->config->expects($this->once())->method('getSystemValue')->with('htaccess.IgnoreFrontController', false)->willReturn(true);
$webDir = 'apps/files/css';
$css = '#id { background-image: url(\'../img/image.jpg\'); }';
$actual = self::invokePrivate($this->scssCacher, 'rebaseUrls', [$css, $webDir]);
$expected = '#id { background-image: url(\'../../apps/files/css/../img/image.jpg\'); }';
$expected = '#id { background-image: url(\'/apps/files/css/../img/image.jpg\'); }';
$this->assertEquals($expected, $actual);
}

Expand Down Expand Up @@ -393,4 +384,55 @@ public function testGetCachedSCSS($appName, $fileName, $result) {
$this->assertEquals(substr($result, 1), $actual);
}

private function randomString() {
return sha1(uniqid(mt_rand(), true));
}

private function rrmdir($directory) {
$files = array_diff(scandir($directory), array('.','..'));
foreach ($files as $file) {
if (is_dir($directory . '/' . $file)) {
$this->rrmdir($directory . '/' . $file);
} else {
unlink($directory . '/' . $file);
}
}
return rmdir($directory);
}

public function dataGetWebDir() {
return [
// Root installation
['/http/core/css', 'core', '', '/http', '/core/css'],
['/http/apps/scss/css', 'scss', '', '/http', '/apps/scss/css'],
['/srv/apps2/scss/css', 'scss', '', '/http', '/apps2/scss/css'],
// Sub directory install
['/http/nextcloud/core/css', 'core', '/nextcloud', '/http/nextcloud', '/nextcloud/core/css'],
['/http/nextcloud/apps/scss/css', 'scss', '/nextcloud', '/http/nextcloud', '/nextcloud/apps/scss/css'],
['/srv/apps2/scss/css', 'scss', '/nextcloud', '/http/nextcloud', '/apps2/scss/css']
];
}

/**
* @param $path
* @param $appName
* @param $webRoot
* @param $serverRoot
* @dataProvider dataGetWebDir
*/
public function testgetWebDir($path, $appName, $webRoot, $serverRoot, $correctWebDir) {
$tmpDir = sys_get_temp_dir().'/'.$this->randomString();
// Adding fake apps folder and create fake app install
\OC::$APPSROOTS[] = [
'path' => $tmpDir.'/srv/apps2',
'url' => '/apps2',
'writable' => false
];
mkdir($tmpDir.$path, 0777, true);
$actual = self::invokePrivate($this->scssCacher, 'getWebDir', [$tmpDir.$path, $appName, $tmpDir.$serverRoot, $webRoot]);
$this->assertEquals($correctWebDir, $actual);
array_pop(\OC::$APPSROOTS);
$this->rrmdir($tmpDir.$path);
}

}
10 changes: 8 additions & 2 deletions tests/lib/UrlGeneratorTest.php
Expand Up @@ -27,6 +27,8 @@ class UrlGeneratorTest extends \Test\TestCase {
private $request;
/** @var IURLGenerator */
private $urlGenerator;
/** @var string */
private $originalWebRoot;

public function setUp() {
parent::setUp();
Expand All @@ -38,6 +40,12 @@ public function setUp() {
$this->cacheFactory,
$this->request
);
$this->originalWebRoot = \OC::$WEBROOT;
}

public function tearDown() {
// Reset webRoot
\OC::$WEBROOT = $this->originalWebRoot;
}

private function mockBaseUrl() {
Expand All @@ -47,7 +55,6 @@ private function mockBaseUrl() {
$this->request->expects($this->once())
->method('getServerHost')
->willReturn('localhost');

}

/**
Expand Down Expand Up @@ -156,4 +163,3 @@ public function testGetBaseUrl() {
}

}