diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/dav/l10n/bg.js | 3 | ||||
-rw-r--r-- | apps/dav/l10n/bg.json | 3 | ||||
-rw-r--r-- | apps/dav/l10n/cs.js | 3 | ||||
-rw-r--r-- | apps/dav/l10n/cs.json | 3 | ||||
-rw-r--r-- | apps/dav/lib/CalDAV/Reminder/ReminderService.php | 1 | ||||
-rw-r--r-- | apps/dav/lib/Comments/EntityCollection.php | 7 | ||||
-rw-r--r-- | apps/dav/lib/Connector/Sabre/Principal.php | 4 | ||||
-rw-r--r-- | apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php | 2 | ||||
-rw-r--r-- | apps/files_sharing/lib/Controller/ShareInfoController.php | 26 | ||||
-rw-r--r-- | apps/files_sharing/lib/External/Storage.php | 6 | ||||
-rw-r--r-- | apps/files_versions/l10n/eu.js | 9 | ||||
-rw-r--r-- | apps/files_versions/l10n/eu.json | 9 | ||||
-rw-r--r-- | apps/theming/l10n/bg.js | 2 | ||||
-rw-r--r-- | apps/theming/l10n/bg.json | 2 | ||||
-rw-r--r-- | apps/workflowengine/lib/Check/FileMimeType.php | 16 | ||||
-rw-r--r-- | apps/workflowengine/tests/Check/FileMimeTypeTest.php | 192 |
16 files changed, 257 insertions, 31 deletions
diff --git a/apps/dav/l10n/bg.js b/apps/dav/l10n/bg.js index e7dd55155f0..85fba41fc61 100644 --- a/apps/dav/l10n/bg.js +++ b/apps/dav/l10n/bg.js @@ -72,8 +72,11 @@ OC.L10N.register( "Where: %s" : "Къде: %s", "%1$s via %2$s" : "%1$s чрез %2$s", "Cancelled: %1$s" : "Отказан: %1$s", + "\"%1$s\" has been canceled" : "„%1$s“ е отказано", "Re: %1$s" : "Re: %1$s", + "%1$s has responded your invitation" : "%1$s отговори на вашата покана", "Invitation: %1$s" : "Покана: %1$s", + "%1$s would like to invite you to \"%2$s\"" : "%1$s желае да ви покани на „%2$s“", "Organizer:" : "Organizer/организатор/:", "Attendees:" : "Участници:", "Title:" : "Заглавие:", diff --git a/apps/dav/l10n/bg.json b/apps/dav/l10n/bg.json index fc6d709a5b0..7fe1597b807 100644 --- a/apps/dav/l10n/bg.json +++ b/apps/dav/l10n/bg.json @@ -70,8 +70,11 @@ "Where: %s" : "Къде: %s", "%1$s via %2$s" : "%1$s чрез %2$s", "Cancelled: %1$s" : "Отказан: %1$s", + "\"%1$s\" has been canceled" : "„%1$s“ е отказано", "Re: %1$s" : "Re: %1$s", + "%1$s has responded your invitation" : "%1$s отговори на вашата покана", "Invitation: %1$s" : "Покана: %1$s", + "%1$s would like to invite you to \"%2$s\"" : "%1$s желае да ви покани на „%2$s“", "Organizer:" : "Organizer/организатор/:", "Attendees:" : "Участници:", "Title:" : "Заглавие:", diff --git a/apps/dav/l10n/cs.js b/apps/dav/l10n/cs.js index 26470e05ec9..869065e72cd 100644 --- a/apps/dav/l10n/cs.js +++ b/apps/dav/l10n/cs.js @@ -72,8 +72,11 @@ OC.L10N.register( "Where: %s" : "Kde: %s", "%1$s via %2$s" : "%1$s prostřednictvím %2$s", "Cancelled: %1$s" : "Zrušeno: %1$s", + "\"%1$s\" has been canceled" : "„%1$s“ bylo zrušeno", "Re: %1$s" : "Odp.: %1$s", + "%1$s has responded your invitation" : "%1$s odpověděl(a) na vaši pozvánku", "Invitation: %1$s" : "Pozvánka: %1$s", + "%1$s would like to invite you to \"%2$s\"" : "%1$s by vás ráda pozval(a) na „%2$s“", "Organizer:" : "Organizátor:", "Attendees:" : "Účastníci:", "Title:" : "Název:", diff --git a/apps/dav/l10n/cs.json b/apps/dav/l10n/cs.json index 71fda387226..d19552b5837 100644 --- a/apps/dav/l10n/cs.json +++ b/apps/dav/l10n/cs.json @@ -70,8 +70,11 @@ "Where: %s" : "Kde: %s", "%1$s via %2$s" : "%1$s prostřednictvím %2$s", "Cancelled: %1$s" : "Zrušeno: %1$s", + "\"%1$s\" has been canceled" : "„%1$s“ bylo zrušeno", "Re: %1$s" : "Odp.: %1$s", + "%1$s has responded your invitation" : "%1$s odpověděl(a) na vaši pozvánku", "Invitation: %1$s" : "Pozvánka: %1$s", + "%1$s would like to invite you to \"%2$s\"" : "%1$s by vás ráda pozval(a) na „%2$s“", "Organizer:" : "Organizátor:", "Attendees:" : "Účastníci:", "Title:" : "Název:", diff --git a/apps/dav/lib/CalDAV/Reminder/ReminderService.php b/apps/dav/lib/CalDAV/Reminder/ReminderService.php index 2911e502049..e0701c75040 100644 --- a/apps/dav/lib/CalDAV/Reminder/ReminderService.php +++ b/apps/dav/lib/CalDAV/Reminder/ReminderService.php @@ -201,7 +201,6 @@ class ReminderService { return; } - /** @var VObject\Component\VCalendar $vcalendar */ $vcalendar = $this->parseCalendarData($calendarData); if (!$vcalendar) { return; diff --git a/apps/dav/lib/Comments/EntityCollection.php b/apps/dav/lib/Comments/EntityCollection.php index d9b06e1240c..59eda21df36 100644 --- a/apps/dav/lib/Comments/EntityCollection.php +++ b/apps/dav/lib/Comments/EntityCollection.php @@ -163,12 +163,9 @@ class EntityCollection extends RootCollection implements IProperties { /** * Sets the read marker to the specified date for the logged in user - * - * @param \DateTime $value - * @return bool */ - public function setReadMarker($value) { - $dateTime = new \DateTime($value); + public function setReadMarker(?string $value): bool { + $dateTime = new \DateTime($value ?? 'now'); $user = $this->userSession->getUser(); $this->commentsManager->setReadMark($this->name, $this->id, $dateTime, $user); return true; diff --git a/apps/dav/lib/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php index c1ad2535936..2a110e928ad 100644 --- a/apps/dav/lib/Connector/Sabre/Principal.php +++ b/apps/dav/lib/Connector/Sabre/Principal.php @@ -601,8 +601,8 @@ class Principal implements BackendInterface { public function getEmailAddressesOfPrincipal(array $principal): array { $emailAddresses = []; - if (($primaryAddress = $principal['{http://sabredav.org/ns}email-address'])) { - $emailAddresses[] = $primaryAddress; + if (isset($principal['{http://sabredav.org/ns}email-address'])) { + $emailAddresses[] = $principal['{http://sabredav.org/ns}email-address']; } if (isset($principal['{DAV:}alternate-URI-set'])) { diff --git a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php index 2e7939aa614..a6bbeba16a3 100644 --- a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php +++ b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php @@ -108,7 +108,7 @@ class CustomPropertiesBackendTest extends TestCase { $query->select('propertyname', 'propertyvalue') ->from('properties') ->where($query->expr()->eq('userid', $query->createNamedParameter($user))) - ->where($query->expr()->eq('propertypath', $query->createNamedParameter($this->formatPath($path)))); + ->andWhere($query->expr()->eq('propertypath', $query->createNamedParameter($this->formatPath($path)))); $result = $query->execute(); $data = []; diff --git a/apps/files_sharing/lib/Controller/ShareInfoController.php b/apps/files_sharing/lib/Controller/ShareInfoController.php index 429eb91bc92..0e2dd1667e1 100644 --- a/apps/files_sharing/lib/Controller/ShareInfoController.php +++ b/apps/files_sharing/lib/Controller/ShareInfoController.php @@ -59,13 +59,8 @@ class ShareInfoController extends ApiController { * @PublicPage * @NoCSRFRequired * @BruteForceProtection(action=shareinfo) - * - * @param string $t - * @param null $password - * @param null $dir - * @return JSONResponse */ - public function info($t, $password = null, $dir = null) { + public function info(string $t, ?string $password = null, ?string $dir = null, int $depth = -1): JSONResponse { try { $share = $this->shareManager->getShareByToken($t); } catch (ShareNotFound $e) { @@ -96,34 +91,39 @@ class ShareInfoController extends ApiController { } } - return new JSONResponse($this->parseNode($node, $permissionMask)); + return new JSONResponse($this->parseNode($node, $permissionMask, $depth)); } - private function parseNode(Node $node, int $permissionMask) { + private function parseNode(Node $node, int $permissionMask, int $depth): array { if ($node instanceof File) { return $this->parseFile($node, $permissionMask); } - return $this->parseFolder($node, $permissionMask); + /** @var Folder $node */ + return $this->parseFolder($node, $permissionMask, $depth); } - private function parseFile(File $file, int $permissionMask) { + private function parseFile(File $file, int $permissionMask): array { return $this->format($file, $permissionMask); } - private function parseFolder(Folder $folder, int $permissionMask) { + private function parseFolder(Folder $folder, int $permissionMask, int $depth): array { $data = $this->format($folder, $permissionMask); + if ($depth === 0) { + return $data; + } + $data['children'] = []; $nodes = $folder->getDirectoryListing(); foreach ($nodes as $node) { - $data['children'][] = $this->parseNode($node, $permissionMask); + $data['children'][] = $this->parseNode($node, $permissionMask, $depth <= -1 ? -1 : $depth - 1); } return $data; } - private function format(Node $node, int $permissionMask) { + private function format(Node $node, int $permissionMask): array { $entry = []; $entry['id'] = $node->getId(); diff --git a/apps/files_sharing/lib/External/Storage.php b/apps/files_sharing/lib/External/Storage.php index 296e7ddf85b..5904727a141 100644 --- a/apps/files_sharing/lib/External/Storage.php +++ b/apps/files_sharing/lib/External/Storage.php @@ -214,7 +214,7 @@ class Storage extends DAV implements ISharedStorage, IDisableEncryptionStorage, public function checkStorageAvailability() { // see if we can find out why the share is unavailable try { - $this->getShareInfo(); + $this->getShareInfo(0); } catch (NotFoundException $e) { // a 404 can either mean that the share no longer exists or there is no Nextcloud on the remote if ($this->testRemote()) { @@ -308,7 +308,7 @@ class Storage extends DAV implements ISharedStorage, IDisableEncryptionStorage, * @throws NotFoundException * @throws \Exception */ - public function getShareInfo() { + public function getShareInfo(int $depth = -1) { $remote = $this->getRemote(); $token = $this->getToken(); $password = $this->getPassword(); @@ -331,7 +331,7 @@ class Storage extends DAV implements ISharedStorage, IDisableEncryptionStorage, $client = \OC::$server->getHTTPClientService()->newClient(); try { $response = $client->post($url, [ - 'body' => ['password' => $password], + 'body' => ['password' => $password, 'depth' => $depth], 'timeout' => 10, 'connect_timeout' => 10, ]); diff --git a/apps/files_versions/l10n/eu.js b/apps/files_versions/l10n/eu.js index 1a1405d924f..f3e0632b4e5 100644 --- a/apps/files_versions/l10n/eu.js +++ b/apps/files_versions/l10n/eu.js @@ -4,10 +4,19 @@ OC.L10N.register( "Versions" : "Bertsioak", "This application automatically maintains older versions of files that are changed." : "Aplikazio honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu automatikoki.", "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aplikazio honek automatikoki mantentzen ditu aldatzen diren fitxategien bertsio zaharragoak. Gaituta dagoenean, ezkutuko bertsioen karpeta batez hornitzen da erabiltzaile bakoitzaren direktorioa, fitxategien bertsio zaharrak gordetzeko. Erabiltzaileak edozein unetan bertsio zaharrago batera leheneratu dezake web interfazearen bidez, ordeztutako fitxategia bertsio bihurtuz. Aplikazioak automatikoki kudeatzen du bertsioen karpeta, erabiltzailea bertsioak direla eta kuotarik gabe geratuko ez dela ziurtatzeko.\n\t\tBertsioak iraungitzeaz gain, bertsioen aplikazioak ziurtatzen du ez dela inoiz erabiliko erabiltzailearen uneko espazio librearen %50 baino gehiago. Biltegiratutako bertsioek muga hori gainditzen badute, aplikazioak bertsio zaharrenak ezabatuko ditu, mugara jaitsi arte. Informazio gehiago dago eskuragarri bertsioen dokumentazioan.", + "Edit version name" : "Editatu bertsioaren izena", "Restore version" : "Leheneratu bertsioa", "Download version" : "Deskargatu bertsioa", + "Delete version" : "Ezabatu bertsioa", + "Version name" : "Bertsioaren izena", + "Remove version name" : "Kendu bertsioaren izena", + "Save version name" : "Gorde bertsioaren izena", + "Initial version restored" : "Hasierako bertsioa leheneratua", "Version restored" : "Bertsioa leheneratu da", "Could not restore version" : "Ezin izan da bertsioa leheneratu", + "Could not set version name" : "Ezin izan da bertsioaren izena ezarri", + "Could not delete version" : "Ezin izan da bertsioa ezabatu", + "${version.label} restored" : "${version.label} leheneratuta", "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Fitxategi honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu. Aktibatzen denean, bertsioen karpeta ezkutu bat sortzen da erabiltzailearen karpeta barruan eta bertan gordetzen dira bertsio zaharrak. Erabiltzailek edozein bertsio zaharretara itzultzea erabaki dezake web interfazea erabiliz, ordezkatutako fitxategia bertsio bilakatuz. Aplikazio honek bertsioen karpeta automatikoki kudeatzen du erabiltzaileak ez dezan mugarik gainditu bertsioengatik.\n\t\tBertsioak iraungitzeaz gain, bertsioen aplikazio honek erabiltzailearen toki libre guztiaren %50 baino gehiago ez erabiltzea bermatzen du. Gordetako bertsioek muga hori gainditzen badute, aplikazioak bertsio zaharrenak ezabatuko ditu mugara iritsi arte. Informazio gehiago lortzeko aplikazioaren dokumentazioa irakurri dezakezu.", "Failed to revert {file} to revision {timestamp}." : "Errorea egon da {fitxategia} {timestamp} bertsiora leheneratzean.", "_%n byte_::_%n bytes_" : ["%nbyte","%n bytes"], diff --git a/apps/files_versions/l10n/eu.json b/apps/files_versions/l10n/eu.json index 23ee73955b1..43a61c3d6ee 100644 --- a/apps/files_versions/l10n/eu.json +++ b/apps/files_versions/l10n/eu.json @@ -2,10 +2,19 @@ "Versions" : "Bertsioak", "This application automatically maintains older versions of files that are changed." : "Aplikazio honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu automatikoki.", "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user's directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user does not run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user's currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Aplikazio honek automatikoki mantentzen ditu aldatzen diren fitxategien bertsio zaharragoak. Gaituta dagoenean, ezkutuko bertsioen karpeta batez hornitzen da erabiltzaile bakoitzaren direktorioa, fitxategien bertsio zaharrak gordetzeko. Erabiltzaileak edozein unetan bertsio zaharrago batera leheneratu dezake web interfazearen bidez, ordeztutako fitxategia bertsio bihurtuz. Aplikazioak automatikoki kudeatzen du bertsioen karpeta, erabiltzailea bertsioak direla eta kuotarik gabe geratuko ez dela ziurtatzeko.\n\t\tBertsioak iraungitzeaz gain, bertsioen aplikazioak ziurtatzen du ez dela inoiz erabiliko erabiltzailearen uneko espazio librearen %50 baino gehiago. Biltegiratutako bertsioek muga hori gainditzen badute, aplikazioak bertsio zaharrenak ezabatuko ditu, mugara jaitsi arte. Informazio gehiago dago eskuragarri bertsioen dokumentazioan.", + "Edit version name" : "Editatu bertsioaren izena", "Restore version" : "Leheneratu bertsioa", "Download version" : "Deskargatu bertsioa", + "Delete version" : "Ezabatu bertsioa", + "Version name" : "Bertsioaren izena", + "Remove version name" : "Kendu bertsioaren izena", + "Save version name" : "Gorde bertsioaren izena", + "Initial version restored" : "Hasierako bertsioa leheneratua", "Version restored" : "Bertsioa leheneratu da", "Could not restore version" : "Ezin izan da bertsioa leheneratu", + "Could not set version name" : "Ezin izan da bertsioaren izena ezarri", + "Could not delete version" : "Ezin izan da bertsioa ezabatu", + "${version.label} restored" : "${version.label} leheneratuta", "This application automatically maintains older versions of files that are changed. When enabled, a hidden versions folder is provisioned in every user’s directory and is used to store old file versions. A user can revert to an older version through the web interface at any time, with the replaced file becoming a version. The app automatically manages the versions folder to ensure the user doesn’t run out of Quota because of versions.\n\t\tIn addition to the expiry of versions, the versions app makes certain never to use more than 50% of the user’s currently available free space. If stored versions exceed this limit, the app will delete the oldest versions first until it meets this limit. More information is available in the Versions documentation." : "Fitxategi honek aldatzen diren fitxategien bertsio zaharrak mantentzen ditu. Aktibatzen denean, bertsioen karpeta ezkutu bat sortzen da erabiltzailearen karpeta barruan eta bertan gordetzen dira bertsio zaharrak. Erabiltzailek edozein bertsio zaharretara itzultzea erabaki dezake web interfazea erabiliz, ordezkatutako fitxategia bertsio bilakatuz. Aplikazio honek bertsioen karpeta automatikoki kudeatzen du erabiltzaileak ez dezan mugarik gainditu bertsioengatik.\n\t\tBertsioak iraungitzeaz gain, bertsioen aplikazio honek erabiltzailearen toki libre guztiaren %50 baino gehiago ez erabiltzea bermatzen du. Gordetako bertsioek muga hori gainditzen badute, aplikazioak bertsio zaharrenak ezabatuko ditu mugara iritsi arte. Informazio gehiago lortzeko aplikazioaren dokumentazioa irakurri dezakezu.", "Failed to revert {file} to revision {timestamp}." : "Errorea egon da {fitxategia} {timestamp} bertsiora leheneratzean.", "_%n byte_::_%n bytes_" : ["%nbyte","%n bytes"], diff --git a/apps/theming/l10n/bg.js b/apps/theming/l10n/bg.js index 602b01bf499..f67436f2c48 100644 --- a/apps/theming/l10n/bg.js +++ b/apps/theming/l10n/bg.js @@ -21,6 +21,8 @@ OC.L10N.register( "Could not write file to disk" : " Файлът не можа да бъде записан на диск", "A PHP extension stopped the file upload" : "PHP разширение спря качването на файла", "No file uploaded" : "Няма качен файл", + "Failed to clean up the old administration theming images folder" : "Неуспешно почистване на папка със стари изображения на администраторски теми", + "Failed to cleanup the old administration image folder" : "Неуспешно почистване на старата папка с изображения на администратора", "You are already using a custom theme. Theming app settings might be overwritten by that." : "Вече използвате персонализирана тема. Настройките на приложението за теми могат да бъдат презаписани от това.", "Theming" : "Теми", "Appearance and accessibility" : "Изглед и достъпност", diff --git a/apps/theming/l10n/bg.json b/apps/theming/l10n/bg.json index 71044542fdb..a4d340eea73 100644 --- a/apps/theming/l10n/bg.json +++ b/apps/theming/l10n/bg.json @@ -19,6 +19,8 @@ "Could not write file to disk" : " Файлът не можа да бъде записан на диск", "A PHP extension stopped the file upload" : "PHP разширение спря качването на файла", "No file uploaded" : "Няма качен файл", + "Failed to clean up the old administration theming images folder" : "Неуспешно почистване на папка със стари изображения на администраторски теми", + "Failed to cleanup the old administration image folder" : "Неуспешно почистване на старата папка с изображения на администратора", "You are already using a custom theme. Theming app settings might be overwritten by that." : "Вече използвате персонализирана тема. Настройките на приложението за теми могат да бъдат презаписани от това.", "Theming" : "Теми", "Appearance and accessibility" : "Изглед и достъпност", 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')); + } +} |