Sanitize input and small fixes

Signed-off-by: Julius Haertl <jus@bitgrid.net>
This commit is contained in:
Julius Haertl 2016-11-04 18:55:00 +01:00
parent 3a400f92d1
commit 78de213b85
No known key found for this signature in database
GPG Key ID: 4C614C6ED2CDE6DF
7 changed files with 61 additions and 45 deletions

View File

@ -64,13 +64,13 @@ return ['routes' => [
'name' => 'Icon#getFavicon', 'name' => 'Icon#getFavicon',
'url' => '/favicon/{app}', 'url' => '/favicon/{app}',
'verb' => 'GET', 'verb' => 'GET',
'defaults' => array("app" => "core"), 'defaults' => array('app' => 'core'),
], ],
[ [
'name' => 'Icon#getTouchIcon', 'name' => 'Icon#getTouchIcon',
'url' => '/icon/{app}', 'url' => '/icon/{app}',
'verb' => 'GET', 'verb' => 'GET',
'defaults' => array("app" => "core"), 'defaults' => array('app' => 'core'),
], ],
[ [
'name' => 'Icon#getThemedIcon', 'name' => 'Icon#getThemedIcon',

View File

@ -27,6 +27,7 @@ use OCA\Theming\ImageManager;
use OCA\Theming\ThemingDefaults; use OCA\Theming\ThemingDefaults;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Http; use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\DataDisplayResponse; use OCP\AppFramework\Http\DataDisplayResponse;
use OCP\AppFramework\Http\FileDisplayResponse; use OCP\AppFramework\Http\FileDisplayResponse;
use OCP\AppFramework\Utility\ITimeFactory; use OCP\AppFramework\Utility\ITimeFactory;
@ -131,7 +132,8 @@ class IconController extends Controller {
$response->addHeader('Expires', $expires->format(\DateTime::RFC2822)); $response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
$response->addHeader('Pragma', 'cache'); $response->addHeader('Pragma', 'cache');
} else { } else {
$response = new DataDisplayResponse(null, Http::STATUS_NOT_FOUND); $response = new Response();
$response->setStatus(Http::STATUS_NOT_FOUND);
$response->cacheFor(0); $response->cacheFor(0);
$response->setLastModified(new \DateTime('now', new \DateTimeZone('GMT'))); $response->setLastModified(new \DateTime('now', new \DateTimeZone('GMT')));
} }
@ -163,7 +165,8 @@ class IconController extends Controller {
$response->addHeader('Expires', $expires->format(\DateTime::RFC2822)); $response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
$response->addHeader('Pragma', 'cache'); $response->addHeader('Pragma', 'cache');
} else { } else {
$response = new DataDisplayResponse(null, Http::STATUS_NOT_FOUND); $response = new Response();
$response->setStatus(Http::STATUS_NOT_FOUND);
$response->cacheFor(0); $response->cacheFor(0);
$response->setLastModified(new \DateTime('now', new \DateTimeZone('GMT'))); $response->setLastModified(new \DateTime('now', new \DateTimeZone('GMT')));
} }

View File

@ -109,7 +109,4 @@ class ImageManager {
} }
} }
} }
} }

View File

@ -58,6 +58,7 @@ class ThemingDefaults extends \OC_Defaults {
* @param IURLGenerator $urlGenerator * @param IURLGenerator $urlGenerator
* @param \OC_Defaults $defaults * @param \OC_Defaults $defaults
* @param IRootFolder $rootFolder * @param IRootFolder $rootFolder
* @param ICacheFactory $cacheFactory
*/ */
public function __construct(IConfig $config, public function __construct(IConfig $config,
IL10N $l, IL10N $l,

View File

@ -28,9 +28,18 @@ use OCP\Files\IRootFolder;
class Util { class Util {
/** @var IConfig */
private $config; private $config;
/** @var IRootFolder */
private $rootFolder; private $rootFolder;
/**
* Util constructor.
*
* @param IConfig $config
* @param IRootFolder $rootFolder
*/
public function __construct(IConfig $config, IRootFolder $rootFolder) { public function __construct(IConfig $config, IRootFolder $rootFolder) {
$this->config = $config; $this->config = $config;
$this->rootFolder = $rootFolder; $this->rootFolder = $rootFolder;
@ -98,14 +107,17 @@ class Util {
* @return string path to app icon / logo * @return string path to app icon / logo
*/ */
public function getAppIcon($app) { public function getAppIcon($app) {
$app = str_replace(array('\0', '/', '\\', '..'), '', $app);
$appPath = \OC_App::getAppPath($app); $appPath = \OC_App::getAppPath($app);
$icon = $appPath . '/img/' . $app . '.svg'; if ($appPath !== false) {
if(file_exists($icon)) { $icon = $appPath . '/img/' . $app . '.svg';
return $icon; if (file_exists($icon)) {
} return $icon;
$icon = $appPath . '/img/app.svg'; }
if(file_exists($icon)) { $icon = $appPath . '/img/app.svg';
return $icon; if (file_exists($icon)) {
return $icon;
}
} }
if($this->config->getAppValue('theming', 'logoMime', '') !== '' && $this->rootFolder->nodeExists('/themedinstancelogo')) { if($this->config->getAppValue('theming', 'logoMime', '') !== '' && $this->rootFolder->nodeExists('/themedinstancelogo')) {
return $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/') . '/themedinstancelogo'; return $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/') . '/themedinstancelogo';
@ -119,32 +131,36 @@ class Util {
* @return string absolute path to image * @return string absolute path to image
*/ */
public function getAppImage($app, $image) { public function getAppImage($app, $image) {
$app = str_replace(array('\0', '/', '\\', '..'), '', $app);
$image = str_replace(array('\0', '\\', '..'), '', $image);
$appPath = \OC_App::getAppPath($app); $appPath = \OC_App::getAppPath($app);
if($app==="core") { if ($app === "core") {
$icon = \OC::$SERVERROOT . '/core/img/' . $image; $icon = \OC::$SERVERROOT . '/core/img/' . $image;
if(file_exists($icon)) { if (file_exists($icon)) {
return $icon;
}
}
if ($appPath !== false) {
$icon = $appPath . '/img/' . $image;
if (file_exists($icon)) {
return $icon;
}
$icon = $appPath . '/img/' . $image . '.svg';
if (file_exists($icon)) {
return $icon;
}
$icon = $appPath . '/img/' . $image . '.png';
if (file_exists($icon)) {
return $icon;
}
$icon = $appPath . '/img/' . $image . '.gif';
if (file_exists($icon)) {
return $icon;
}
$icon = $appPath . '/img/' . $image . '.jpg';
if (file_exists($icon)) {
return $icon; return $icon;
} }
}
$icon = $appPath . '/img/' . $image;
if(file_exists($icon)) {
return $icon;
}
$icon = $appPath . '/img/' . $image . '.svg';
if(file_exists($icon)) {
return $icon;
}
$icon = $appPath . '/img/' . $image . '.png';
if(file_exists($icon)) {
return $icon;
}
$icon = $appPath . '/img/' . $image . '.gif';
if(file_exists($icon)) {
return $icon;
}
$icon = $appPath . '/img/' . $image . '.jpg';
if(file_exists($icon)) {
return $icon;
} }
return false; return false;
} }

View File

@ -30,7 +30,6 @@ use OCP\AppFramework\Http\DataDisplayResponse;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException; use OCP\Files\NotFoundException;
use OCP\IConfig; use OCP\IConfig;
use OCP\IL10N;
use OCP\IRequest; use OCP\IRequest;
use Test\TestCase; use Test\TestCase;
use OCA\Theming\Util; use OCA\Theming\Util;
@ -47,7 +46,7 @@ class IconControllerTest extends TestCase {
private $util; private $util;
/** @var \OCP\AppFramework\Utility\ITimeFactory */ /** @var \OCP\AppFramework\Utility\ITimeFactory */
private $timeFactory; private $timeFactory;
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ /** @var IconController|\PHPUnit_Framework_MockObject_MockObject */
private $iconController; private $iconController;
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config; private $config;
@ -110,8 +109,6 @@ class IconControllerTest extends TestCase {
$expected->addHeader('Expires', $expires->format(\DateTime::RFC2822)); $expected->addHeader('Expires', $expires->format(\DateTime::RFC2822));
$expected->addHeader('Pragma', 'cache'); $expected->addHeader('Pragma', 'cache');
@$this->assertEquals($expected, $this->iconController->getThemedIcon('core', 'filetypes/folder.svg')); @$this->assertEquals($expected, $this->iconController->getThemedIcon('core', 'filetypes/folder.svg'));
} }
public function testGetFaviconDefault() { public function testGetFaviconDefault() {
@ -152,7 +149,8 @@ class IconControllerTest extends TestCase {
$this->themingDefaults->expects($this->any()) $this->themingDefaults->expects($this->any())
->method('shouldReplaceIcons') ->method('shouldReplaceIcons')
->willReturn(false); ->willReturn(false);
$expected = new DataDisplayResponse(null, Http::STATUS_NOT_FOUND); $expected = new Http\Response();
$expected->setStatus(Http::STATUS_NOT_FOUND);
$expected->cacheFor(0); $expected->cacheFor(0);
$expected->setLastModified(new \DateTime('now', new \DateTimeZone('GMT'))); $expected->setLastModified(new \DateTime('now', new \DateTimeZone('GMT')));
$this->assertEquals($expected, $this->iconController->getFavicon()); $this->assertEquals($expected, $this->iconController->getFavicon());
@ -196,7 +194,8 @@ class IconControllerTest extends TestCase {
$this->themingDefaults->expects($this->any()) $this->themingDefaults->expects($this->any())
->method('shouldReplaceIcons') ->method('shouldReplaceIcons')
->willReturn(false); ->willReturn(false);
$expected = new DataDisplayResponse(null, Http::STATUS_NOT_FOUND); $expected = new Http\Response();
$expected->setStatus(Http::STATUS_NOT_FOUND);
$expected->cacheFor(0); $expected->cacheFor(0);
$expected->setLastModified(new \DateTime('now', new \DateTimeZone('GMT'))); $expected->setLastModified(new \DateTime('now', new \DateTimeZone('GMT')));
$this->assertEquals($expected, $this->iconController->getTouchIcon()); $this->assertEquals($expected, $this->iconController->getTouchIcon());

View File

@ -97,14 +97,13 @@ class UtilTest extends TestCase {
$expected = 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTYiIHdpZHRoPSIxNiI+PHBhdGggZD0iTTggMWE3IDcgMCAwIDAtNyA3IDcgNyAwIDAgMCA3IDcgNyA3IDAgMCAwIDctNyA3IDcgMCAwIDAtNy03em0wIDFhNiA2IDAgMCAxIDYgNiA2IDYgMCAwIDEtNiA2IDYgNiAwIDAgMS02LTYgNiA2IDAgMCAxIDYtNnptMCAyYTQgNCAwIDEgMCAwIDggNCA0IDAgMCAwIDAtOHoiIGZpbGw9IiNmZmZmZmYiLz48L3N2Zz4='; $expected = 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTYiIHdpZHRoPSIxNiI+PHBhdGggZD0iTTggMWE3IDcgMCAwIDAtNyA3IDcgNyAwIDAgMCA3IDcgNyA3IDAgMCAwIDctNyA3IDcgMCAwIDAtNy03em0wIDFhNiA2IDAgMCAxIDYgNiA2IDYgMCAwIDEtNiA2IDYgNiAwIDAgMS02LTYgNiA2IDAgMCAxIDYtNnptMCAyYTQgNCAwIDEgMCAwIDggNCA0IDAgMCAwIDAtOHoiIGZpbGw9IiNmZmZmZmYiLz48L3N2Zz4=';
$this->assertEquals($expected, $button); $this->assertEquals($expected, $button);
} }
public function testGenerateRadioButtonBlack() { public function testGenerateRadioButtonBlack() {
$button = $this->util->generateRadioButton('#000000'); $button = $this->util->generateRadioButton('#000000');
$expected = 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTYiIHdpZHRoPSIxNiI+PHBhdGggZD0iTTggMWE3IDcgMCAwIDAtNyA3IDcgNyAwIDAgMCA3IDcgNyA3IDAgMCAwIDctNyA3IDcgMCAwIDAtNy03em0wIDFhNiA2IDAgMCAxIDYgNiA2IDYgMCAwIDEtNiA2IDYgNiAwIDAgMS02LTYgNiA2IDAgMCAxIDYtNnptMCAyYTQgNCAwIDEgMCAwIDggNCA0IDAgMCAwIDAtOHoiIGZpbGw9IiMwMDAwMDAiLz48L3N2Zz4='; $expected = 'PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTYiIHdpZHRoPSIxNiI+PHBhdGggZD0iTTggMWE3IDcgMCAwIDAtNyA3IDcgNyAwIDAgMCA3IDcgNyA3IDAgMCAwIDctNyA3IDcgMCAwIDAtNy03em0wIDFhNiA2IDAgMCAxIDYgNiA2IDYgMCAwIDEtNiA2IDYgNiAwIDAgMS02LTYgNiA2IDAgMCAxIDYtNnptMCAyYTQgNCAwIDEgMCAwIDggNCA0IDAgMCAwIDAtOHoiIGZpbGw9IiMwMDAwMDAiLz48L3N2Zz4=';
$this->assertEquals($expected, $button); $this->assertEquals($expected, $button);
} }
/** /**
* @dataProvider dataGetAppIcon * @dataProvider dataGetAppIcon
*/ */
@ -137,6 +136,7 @@ class UtilTest extends TestCase {
public function testGetAppImage($app, $image, $expected) { public function testGetAppImage($app, $image, $expected) {
$this->assertEquals($expected, $this->util->getAppImage($app, $image)); $this->assertEquals($expected, $this->util->getAppImage($app, $image));
} }
public function dataGetAppImage() { public function dataGetAppImage() {
return [ return [
['core', 'logo.svg', \OC::$SERVERROOT . '/core/img/logo.svg'], ['core', 'logo.svg', \OC::$SERVERROOT . '/core/img/logo.svg'],