summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorblizzz <blizzz@arthur-schiwon.de>2023-02-09 14:36:02 +0100
committerGitHub <noreply@github.com>2023-02-09 14:36:02 +0100
commit6a1983392e468591924bb2826877875aacd856cd (patch)
treef45734cc88c3a8de5f8d2227011d2192fab1edd5
parent67331c88dc53e45be6f2f39ad007824e7a6d8fb8 (diff)
parent4c60cddf7979c7b2615bef903348a928f12662d4 (diff)
downloadnextcloud-server-6a1983392e468591924bb2826877875aacd856cd.tar.gz
nextcloud-server-6a1983392e468591924bb2826877875aacd856cd.zip
Merge pull request #35842 from nextcloud/backport/25768/stable25
[stable25] Use mimetype from cache for workflow checks
-rw-r--r--apps/workflowengine/lib/Check/FileMimeType.php16
-rw-r--r--apps/workflowengine/tests/Check/FileMimeTypeTest.php192
2 files changed, 202 insertions, 6 deletions
diff --git a/apps/workflowengine/lib/Check/FileMimeType.php b/apps/workflowengine/lib/Check/FileMimeType.php
index 42b93bd9513..991d7ebc739 100644
--- a/apps/workflowengine/lib/Check/FileMimeType.php
+++ b/apps/workflowengine/lib/Check/FileMimeType.php
@@ -26,6 +26,7 @@
*/
namespace OCA\WorkflowEngine\Check;
+use OC\Files\Storage\Local;
use OCA\WorkflowEngine\Entity\File;
use OCP\Files\IMimeTypeDetector;
use OCP\Files\Storage\IStorage;
@@ -76,7 +77,7 @@ class FileMimeType extends AbstractStringCheck implements IFileCheck {
}
/**
- * The mimetype is only cached if the file exists. Otherwise files access
+ * The mimetype is only cached if the file has a valid mimetype. Otherwise files access
* control will cache "application/octet-stream" for all the target node on:
* rename, move, copy and all other methods which create a new item
*
@@ -91,7 +92,7 @@ class FileMimeType extends AbstractStringCheck implements IFileCheck {
* @return string
*/
protected function cacheAndReturnMimeType(string $storageId, ?string $path, string $mimeType): string {
- if ($path !== null && $this->storage->file_exists($path)) {
+ if ($path !== null && $mimeType !== 'application/octet-stream') {
$this->mimeType[$storageId][$path] = $mimeType;
}
@@ -122,12 +123,15 @@ class FileMimeType extends AbstractStringCheck implements IFileCheck {
if ($this->mimeType[$this->storage->getId()][$this->path] !== null) {
return $this->mimeType[$this->storage->getId()][$this->path];
}
-
- if ($this->storage->is_dir($this->path)) {
- return $this->cacheAndReturnMimeType($this->storage->getId(), $this->path, 'httpd/unix-directory');
+ $cacheEntry = $this->storage->getCache()->get($this->path);
+ if ($cacheEntry && $cacheEntry->getMimeType() !== 'application/octet-stream') {
+ return $this->cacheAndReturnMimeType($this->storage->getId(), $this->path, $cacheEntry->getMimeType());
}
- if ($this->storage->file_exists($this->path) && $this->storage->filesize($this->path)) {
+ if ($this->storage->file_exists($this->path) &&
+ $this->storage->filesize($this->path) &&
+ $this->storage->instanceOfStorage(Local::class)
+ ) {
$path = $this->storage->getLocalFile($this->path);
$mimeType = $this->mimeTypeDetector->detectContent($path);
return $this->cacheAndReturnMimeType($this->storage->getId(), $this->path, $mimeType);
diff --git a/apps/workflowengine/tests/Check/FileMimeTypeTest.php b/apps/workflowengine/tests/Check/FileMimeTypeTest.php
new file mode 100644
index 00000000000..3ebcaa8f4b3
--- /dev/null
+++ b/apps/workflowengine/tests/Check/FileMimeTypeTest.php
@@ -0,0 +1,192 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\WorkflowEngine\Tests\Check;
+
+use OC\Files\Storage\Temporary;
+use OCA\WorkflowEngine\Check\FileMimeType;
+use OCP\Files\IMimeTypeDetector;
+use OCP\IL10N;
+use OCP\IRequest;
+use Test\TestCase;
+
+class TemporaryNoLocal extends Temporary {
+ public function instanceOfStorage($className) {
+ if ($className === '\OC\Files\Storage\Local') {
+ return false;
+ } else {
+ return parent::instanceOfStorage($className);
+ }
+ }
+}
+
+/**
+ * @group DB
+ */
+class FileMimeTypeTest extends TestCase {
+ /** @var IL10N */
+ private $l10n;
+ /** @var IRequest */
+ private $request;
+ /** @var IMimeTypeDetector */
+ private $mimeDetector;
+
+ private $extensions = [
+ '.txt' => 'text/plain-path-detected',
+ ];
+
+ private $content = [
+ 'text-content' => 'text/plain-content-detected',
+ ];
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->l10n = $this->createMock(IL10N::class);
+ $this->request = $this->createMock(IRequest::class);
+ $this->mimeDetector = $this->createMock(IMimeTypeDetector::class);
+ $this->mimeDetector->method('detectPath')
+ ->willReturnCallback(function ($path) {
+ foreach ($this->extensions as $extension => $mime) {
+ if (strpos($path, $extension) !== false) {
+ return $mime;
+ }
+ }
+ return 'application/octet-stream';
+ });
+ $this->mimeDetector->method('detectContent')
+ ->willReturnCallback(function ($path) {
+ $body = file_get_contents($path);
+ foreach ($this->content as $match => $mime) {
+ if (strpos($body, $match) !== false) {
+ return $mime;
+ }
+ }
+ return 'application/octet-stream';
+ });
+ }
+
+ public function testUseCachedMimetype() {
+ $storage = new Temporary([]);
+ $storage->mkdir('foo');
+ $storage->file_put_contents('foo/bar.txt', 'asd');
+ $storage->getScanner()->scan('');
+
+
+ $check = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $check->setFileInfo($storage, 'foo/bar.txt');
+
+ $this->assertTrue($check->executeCheck('is', 'text/plain'));
+ }
+
+ public function testNonCachedNotExists() {
+ $storage = new Temporary([]);
+
+ $check = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $check->setFileInfo($storage, 'foo/bar.txt');
+
+ $this->assertTrue($check->executeCheck('is', 'text/plain-path-detected'));
+ }
+
+ public function testNonCachedLocal() {
+ $storage = new Temporary([]);
+ $storage->mkdir('foo');
+ $storage->file_put_contents('foo/bar.txt', 'text-content');
+
+ $check = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $check->setFileInfo($storage, 'foo/bar.txt');
+
+ $this->assertTrue($check->executeCheck('is', 'text/plain-content-detected'));
+ }
+
+ public function testNonCachedNotLocal() {
+ $storage = new TemporaryNoLocal([]);
+ $storage->mkdir('foo');
+ $storage->file_put_contents('foo/bar.txt', 'text-content');
+
+ $check = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $check->setFileInfo($storage, 'foo/bar.txt');
+
+ $this->assertTrue($check->executeCheck('is', 'text/plain-path-detected'));
+ }
+
+ public function testFallback() {
+ $storage = new Temporary([]);
+
+ $check = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $check->setFileInfo($storage, 'unknown');
+
+ $this->assertTrue($check->executeCheck('is', 'application/octet-stream'));
+ }
+
+ public function testFromCacheCached() {
+ $storage = new Temporary([]);
+ $storage->mkdir('foo');
+ $storage->file_put_contents('foo/bar.txt', 'asd');
+ $storage->getScanner()->scan('');
+
+ $check = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $check->setFileInfo($storage, 'foo/bar.txt');
+
+ $this->assertTrue($check->executeCheck('is', 'text/plain'));
+
+ $storage->getCache()->clear();
+
+ $this->assertTrue($check->executeCheck('is', 'text/plain'));
+
+ $newCheck = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $newCheck->setFileInfo($storage, 'foo/bar.txt');
+ $this->assertTrue($newCheck->executeCheck('is', 'text/plain-path-detected'));
+ }
+
+ public function testExistsCached() {
+ $storage = new TemporaryNoLocal([]);
+ $storage->mkdir('foo');
+ $storage->file_put_contents('foo/bar.txt', 'text-content');
+
+ $check = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $check->setFileInfo($storage, 'foo/bar.txt');
+
+ $this->assertTrue($check->executeCheck('is', 'text/plain-content-detected'));
+ $storage->unlink('foo/bar.txt');
+ $this->assertTrue($check->executeCheck('is', 'text/plain-content-detected'));
+
+ $newCheck = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $newCheck->setFileInfo($storage, 'foo/bar.txt');
+ $this->assertTrue($newCheck->executeCheck('is', 'text/plain-path-detected'));
+ }
+
+ public function testNonExistsNotCached() {
+ $storage = new TemporaryNoLocal([]);
+
+ $check = new FileMimeType($this->l10n, $this->request, $this->mimeDetector);
+ $check->setFileInfo($storage, 'foo/bar.txt');
+
+ $this->assertTrue($check->executeCheck('is', 'text/plain-path-detected'));
+
+ $storage->mkdir('foo');
+ $storage->file_put_contents('foo/bar.txt', 'text-content');
+
+ $this->assertTrue($check->executeCheck('is', 'text/plain-content-detected'));
+ }
+}