From 405bbc1c6195f7735d920451fe18476ec4bd0054 Mon Sep 17 00:00:00 2001 From: Morris Jobke Date: Wed, 25 Oct 2017 17:57:21 +0200 Subject: [PATCH] Improve mimetype detection for object storages Object storage instances always fall back to the content based mimetype detection, because the file name for object storage was always random due to the fact that it was temporarily storage in a generated temp file. This patch adds a check before that to make sure to use the original file name for this purpose and also remove possible other extensions like the versioning or part file extension. Signed-off-by: Morris Jobke --- lib/private/Files/ObjectStore/ObjectStoreStorage.php | 10 +++++++++- lib/private/Files/Type/Detection.php | 4 ++++ tests/lib/Files/Type/DetectionTest.php | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php index ded69e8079b..15df808684b 100644 --- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php +++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php @@ -390,7 +390,15 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common { $stat['size'] = filesize($tmpFile); $stat['mtime'] = $mTime; $stat['storage_mtime'] = $mTime; - $stat['mimetype'] = \OC::$server->getMimeTypeDetector()->detect($tmpFile); + + // run path based detection first, to use file extension because $tmpFile is only a random string + $mimetypeDetector = \OC::$server->getMimeTypeDetector(); + $mimetype = $mimetypeDetector->detectPath($path); + if ($mimetype === 'application/octet-stream') { + $mimetype = $mimetypeDetector->detect($tmpFile); + } + + $stat['mimetype'] = $mimetype; $stat['etag'] = $this->getETag($path); $fileId = $this->getCache()->put($path, $stat); diff --git a/lib/private/Files/Type/Detection.php b/lib/private/Files/Type/Detection.php index cd4ddc2f067..928c68251cf 100644 --- a/lib/private/Files/Type/Detection.php +++ b/lib/private/Files/Type/Detection.php @@ -173,6 +173,10 @@ class Detection implements IMimeTypeDetector { // note: leading dot doesn't qualify as extension if (strpos($fileName, '.') > 0) { + + // remove versioning extension: name.v1508946057 and transfer extension: name.ocTransferId2057600214.part + $fileName = preg_replace('!((\.v\d+)|((.ocTransferId\d+)?.part))$!', '', $fileName); + //try to guess the type by the file extension $extension = strtolower(strrchr($fileName, '.')); $extension = substr($extension, 1); //remove leading . diff --git a/tests/lib/Files/Type/DetectionTest.php b/tests/lib/Files/Type/DetectionTest.php index 295b9bf9fac..1d01a96fcc0 100644 --- a/tests/lib/Files/Type/DetectionTest.php +++ b/tests/lib/Files/Type/DetectionTest.php @@ -84,6 +84,8 @@ class DetectionTest extends \Test\TestCase { $this->assertEquals('application/octet-stream', $this->detection->detectPath('..hidden')); $this->assertEquals('application/octet-stream', $this->detection->detectPath('foo')); $this->assertEquals('application/octet-stream', $this->detection->detectPath('')); + $this->assertEquals('image/png', $this->detection->detectPath('foo.png.ocTransferId123456789.part')); + $this->assertEquals('image/png', $this->detection->detectPath('foo.png.v1234567890')); } public function testDetectString() {