diff options
-rw-r--r-- | apps/files_external/3rdparty/composer.json | 2 | ||||
-rw-r--r-- | apps/files_external/3rdparty/composer.lock | 12 | ||||
-rw-r--r-- | apps/files_external/3rdparty/composer/installed.json | 12 | ||||
-rw-r--r-- | apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php | 53 | ||||
-rw-r--r-- | apps/files_sharing/js/public.js | 3 | ||||
-rw-r--r-- | apps/files_sharing/lib/Controller/ShareAPIController.php | 19 | ||||
-rw-r--r-- | apps/files_sharing/tests/ApiTest.php | 3 | ||||
-rw-r--r-- | build/integration/sharing_features/sharing-v1.feature | 4 | ||||
-rw-r--r-- | lib/private/App/AppStore/Fetcher/Fetcher.php | 9 | ||||
-rw-r--r-- | lib/public/AppFramework/Controller.php | 8 | ||||
-rw-r--r-- | package-lock.json | 6 | ||||
-rw-r--r-- | resources/locales.json | 8 | ||||
-rwxr-xr-x | resources/update-locales.php | 10 | ||||
-rw-r--r-- | tests/lib/App/AppStore/Fetcher/FetcherBase.php | 61 |
14 files changed, 146 insertions, 64 deletions
diff --git a/apps/files_external/3rdparty/composer.json b/apps/files_external/3rdparty/composer.json index 0ee0c268bb0..514108214da 100644 --- a/apps/files_external/3rdparty/composer.json +++ b/apps/files_external/3rdparty/composer.json @@ -9,6 +9,6 @@ }, "require": { "icewind/streams": "0.7.1", - "icewind/smb": "3.2.3" + "icewind/smb": "3.2.4" } } diff --git a/apps/files_external/3rdparty/composer.lock b/apps/files_external/3rdparty/composer.lock index e0716141c5f..aae061de55c 100644 --- a/apps/files_external/3rdparty/composer.lock +++ b/apps/files_external/3rdparty/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ef0d9929f5f25696e010d5733eb51fbb", + "content-hash": "9454f546b6ab8865140c991e8f197951", "packages": [ { "name": "icewind/smb", - "version": "v3.2.3", + "version": "v3.2.4", "source": { "type": "git", "url": "https://github.com/icewind1991/SMB.git", - "reference": "db50bb51bd0a0e55506e82cf439a9ecd232f64d4" + "reference": "999d6687ca9d4ac2600185c935b45206e47e604a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/icewind1991/SMB/zipball/db50bb51bd0a0e55506e82cf439a9ecd232f64d4", - "reference": "db50bb51bd0a0e55506e82cf439a9ecd232f64d4", + "url": "https://api.github.com/repos/icewind1991/SMB/zipball/999d6687ca9d4ac2600185c935b45206e47e604a", + "reference": "999d6687ca9d4ac2600185c935b45206e47e604a", "shasum": "" }, "require": { @@ -46,7 +46,7 @@ } ], "description": "php wrapper for smbclient and libsmbclient-php", - "time": "2020-04-08T15:20:22+00:00" + "time": "2020-05-11T14:12:35+00:00" }, { "name": "icewind/streams", diff --git a/apps/files_external/3rdparty/composer/installed.json b/apps/files_external/3rdparty/composer/installed.json index e2b841f206a..388a48e5560 100644 --- a/apps/files_external/3rdparty/composer/installed.json +++ b/apps/files_external/3rdparty/composer/installed.json @@ -1,17 +1,17 @@ [ { "name": "icewind/smb", - "version": "v3.2.3", - "version_normalized": "3.2.3.0", + "version": "v3.2.4", + "version_normalized": "3.2.4.0", "source": { "type": "git", "url": "https://github.com/icewind1991/SMB.git", - "reference": "db50bb51bd0a0e55506e82cf439a9ecd232f64d4" + "reference": "999d6687ca9d4ac2600185c935b45206e47e604a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/icewind1991/SMB/zipball/db50bb51bd0a0e55506e82cf439a9ecd232f64d4", - "reference": "db50bb51bd0a0e55506e82cf439a9ecd232f64d4", + "url": "https://api.github.com/repos/icewind1991/SMB/zipball/999d6687ca9d4ac2600185c935b45206e47e604a", + "reference": "999d6687ca9d4ac2600185c935b45206e47e604a", "shasum": "" }, "require": { @@ -22,7 +22,7 @@ "friendsofphp/php-cs-fixer": "^2.13", "phpunit/phpunit": "^7.0" }, - "time": "2020-04-08T15:20:22+00:00", + "time": "2020-05-11T14:12:35+00:00", "type": "library", "installation-source": "dist", "autoload": { diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php index 24344e6f0df..093cbb3b5dc 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php @@ -32,11 +32,6 @@ class NativeFileInfo implements IFileInfo { protected $attributeCache = null; /** - * @var int - */ - protected $modeCache; - - /** * @param NativeShare $share * @param string $path * @param string $name @@ -69,7 +64,7 @@ class NativeFileInfo implements IFileInfo { $rawAttributes = explode(',', $this->share->getAttribute($this->path, 'system.dos_attr.*')); $this->attributeCache = []; foreach ($rawAttributes as $rawAttribute) { - [$name, $value] = explode(':', $rawAttribute); + list($name, $value) = explode(':', $rawAttribute); $name = strtolower($name); if ($name == 'mode') { $this->attributeCache[$name] = (int)hexdec(substr($value, 2)); @@ -98,6 +93,18 @@ class NativeFileInfo implements IFileInfo { } /** + * On "mode": + * + * different smbclient versions seem to return different mode values for 'system.dos_attr.mode' + * + * older versions return the dos permissions mask as defined in `IFileInfo::MODE_*` while + * newer versions return the equivalent unix permission mask. + * + * Since the unix mask doesn't contain the proper hidden/archive/system flags we have to assume them + * as false (except for `hidden` where we use the unix dotfile convention) + */ + + /** * @return int */ protected function getMode() { @@ -109,7 +116,11 @@ class NativeFileInfo implements IFileInfo { */ public function isDirectory() { $mode = $this->getMode(); - return (bool)($mode & IFileInfo::MODE_DIRECTORY); + if ($mode > 0x80) { + return (bool)($mode & 0x4000); // 0x80: unix directory flag + } else { + return (bool)($mode & IFileInfo::MODE_DIRECTORY); + } } /** @@ -117,7 +128,11 @@ class NativeFileInfo implements IFileInfo { */ public function isReadOnly() { $mode = $this->getMode(); - return (bool)($mode & IFileInfo::MODE_READONLY); + if ($mode > 0x80) { + return !(bool)($mode & 0x80); // 0x80: owner write permissions + } else { + return (bool)($mode & IFileInfo::MODE_READONLY); + } } /** @@ -125,7 +140,11 @@ class NativeFileInfo implements IFileInfo { */ public function isHidden() { $mode = $this->getMode(); - return (bool)($mode & IFileInfo::MODE_HIDDEN); + if ($mode > 0x80) { + return $this->name[0] === '.'; + } else { + return (bool)($mode & IFileInfo::MODE_HIDDEN); + } } /** @@ -133,7 +152,11 @@ class NativeFileInfo implements IFileInfo { */ public function isSystem() { $mode = $this->getMode(); - return (bool)($mode & IFileInfo::MODE_SYSTEM); + if ($mode > 0x80) { + return false; + } else { + return (bool)($mode & IFileInfo::MODE_SYSTEM); + } } /** @@ -141,7 +164,11 @@ class NativeFileInfo implements IFileInfo { */ public function isArchived() { $mode = $this->getMode(); - return (bool)($mode & IFileInfo::MODE_ARCHIVE); + if ($mode > 0x80) { + return false; + } else { + return (bool)($mode & IFileInfo::MODE_ARCHIVE); + } } /** @@ -152,8 +179,8 @@ class NativeFileInfo implements IFileInfo { $attribute = $this->share->getAttribute($this->path, 'system.nt_sec_desc.acl.*+'); foreach (explode(',', $attribute) as $acl) { - [$user, $permissions] = explode(':', $acl, 2); - [$type, $flags, $mask] = explode('/', $permissions); + list($user, $permissions) = explode(':', $acl, 2); + list($type, $flags, $mask) = explode('/', $permissions); $mask = hexdec($mask); $acls[$user] = new ACL($type, $flags, $mask); diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 982f32dbdd9..3986506bca8 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -152,7 +152,8 @@ OCA.Sharing.PublicApp = { img.attr('src', $('#downloadURL').val()); imgcontainer.appendTo('#imgframe'); } else if (mimetype.substr(0, mimetype.indexOf('/')) === 'text' && window.btoa) { - if (OC.appswebroots['files_texteditor'] !== undefined) { + if (OC.appswebroots['files_texteditor'] !== undefined || + OC.appswebroots['text'] !== undefined) { // the text editor handles the previewing return; } diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index 49320d57f16..0fbd57b4713 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -216,15 +216,6 @@ class ShareAPIController extends OCSController { $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); } - // TODO: It might make sense to have a dedicated setting to allow/deny converting link shares into federated ones - // For link shares, we need to have the PERMISSION_SHARE if federated is enabled - if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { - if ($share->getShareType() === IShare::TYPE_LINK - || $share->getShareType() === IShare::TYPE_EMAIL) { - $result['permissions'] |= Constants::PERMISSION_SHARE; - } - } - if ($share->getShareType() === IShare::TYPE_USER) { $sharedWith = $this->userManager->get($share->getSharedWith()); $result['share_with'] = $share->getSharedWith(); @@ -511,6 +502,11 @@ class ShareAPIController extends OCSController { $permissions = Constants::PERMISSION_READ; } + // TODO: It might make sense to have a dedicated setting to allow/deny converting link shares into federated ones + if (($permissions & Constants::PERMISSION_READ) && $this->shareManager->outgoingServer2ServerSharesAllowed()) { + $permissions |= Constants::PERMISSION_SHARE; + } + $share->setPermissions($permissions); // Set password @@ -1055,6 +1051,11 @@ class ShareAPIController extends OCSController { } if ($newPermissions !== null) { + // TODO: It might make sense to have a dedicated setting to allow/deny converting link shares into federated ones + if (($newPermissions & Constants::PERMISSION_READ) && $this->shareManager->outgoingServer2ServerSharesAllowed()) { + $newPermissions |= Constants::PERMISSION_SHARE; + } + $share->setPermissions($newPermissions); $permissions = $newPermissions; } diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php index 365ea8dcb8e..9e7d8e5c693 100644 --- a/apps/files_sharing/tests/ApiTest.php +++ b/apps/files_sharing/tests/ApiTest.php @@ -999,7 +999,8 @@ class ApiTest extends TestCase { \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | - \OCP\Constants::PERMISSION_DELETE, + \OCP\Constants::PERMISSION_DELETE | + \OCP\Constants::PERMISSION_SHARE, $share1->getPermissions() ); diff --git a/build/integration/sharing_features/sharing-v1.feature b/build/integration/sharing_features/sharing-v1.feature index eb8006e565b..51a627dc6de 100644 --- a/build/integration/sharing_features/sharing-v1.feature +++ b/build/integration/sharing_features/sharing-v1.feature @@ -195,7 +195,7 @@ Feature: sharing | share_type | 3 | | file_source | A_NUMBER | | file_target | /FOLDER | - | permissions | 15 | + | permissions | 31 | | stime | A_NUMBER | | token | A_TOKEN | | storage | A_NUMBER | @@ -259,7 +259,7 @@ Feature: sharing | share_type | 3 | | file_source | A_NUMBER | | file_target | /FOLDER | - | permissions | 15 | + | permissions | 31 | | stime | A_NUMBER | | token | A_TOKEN | | storage | A_NUMBER | diff --git a/lib/private/App/AppStore/Fetcher/Fetcher.php b/lib/private/App/AppStore/Fetcher/Fetcher.php index 8f2fb0a7084..c109bacf135 100644 --- a/lib/private/App/AppStore/Fetcher/Fetcher.php +++ b/lib/private/App/AppStore/Fetcher/Fetcher.php @@ -41,7 +41,7 @@ use OCP\IConfig; use OCP\ILogger; abstract class Fetcher { - public const INVALIDATE_AFTER_SECONDS = 300; + public const INVALIDATE_AFTER_SECONDS = 3600; /** @var IAppData */ protected $appData; @@ -98,12 +98,11 @@ abstract class Fetcher { $options = [ 'timeout' => 10, + 'headers' => ['Accept-Encoding' => 'gzip'], ]; if ($ETag !== '') { - $options['headers'] = [ - 'If-None-Match' => $ETag, - ]; + $options['headers']['If-None-Match'] = $ETag; } $client = $this->clientService->newClient(); @@ -153,7 +152,7 @@ abstract class Fetcher { // No caching when the version has been updated if (isset($jsonBlob['ncversion']) && $jsonBlob['ncversion'] === $this->getVersion()) { - // If the timestamp is older than 300 seconds request the files new + // If the timestamp is older than 3600 seconds request the files new if ((int)$jsonBlob['timestamp'] > ($this->timeFactory->getTime() - self::INVALIDATE_AFTER_SECONDS)) { return $jsonBlob['data']; } diff --git a/lib/public/AppFramework/Controller.php b/lib/public/AppFramework/Controller.php index ca35d723242..db1f95634e0 100644 --- a/lib/public/AppFramework/Controller.php +++ b/lib/public/AppFramework/Controller.php @@ -91,6 +91,14 @@ abstract class Controller { unset($headers['Content-Type']); } $response->setHeaders(array_merge($dataHeaders, $headers)); + + if ($data->getETag() !== null) { + $response->setETag($data->getETag()); + } + if ($data->getLastModified() !== null) { + $response->setLastModified($data->getLastModified()); + } + return $response; } return new JSONResponse($data); diff --git a/package-lock.json b/package-lock.json index 2af7f1c8693..5f9093ce043 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11089,9 +11089,9 @@ } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/resources/locales.json b/resources/locales.json index a65cf530514..7cf9fa9b890 100644 --- a/resources/locales.json +++ b/resources/locales.json @@ -912,10 +912,6 @@ "name": "English (United States)" }, { - "code": "en_US_POSIX", - "name": "English (United States, Computer)" - }, - { "code": "en_VC", "name": "English (St. Vincent & Grenadines)" }, @@ -1400,6 +1396,10 @@ "name": "Irish" }, { + "code": "ga_GB", + "name": "Irish (United Kingdom)" + }, + { "code": "ga_IE", "name": "Irish (Ireland)" }, diff --git a/resources/update-locales.php b/resources/update-locales.php index d5addd0a9ae..50d848c76a6 100755 --- a/resources/update-locales.php +++ b/resources/update-locales.php @@ -29,13 +29,21 @@ if (!extension_loaded('intl')) { exit(1); } -$locales = array_map(function (string $localeCode) { +require '../3rdparty/autoload.php'; + +$locales = array_map(static function (string $localeCode) { return [ 'code' => $localeCode, 'name' => Locale::getDisplayName($localeCode, 'en') ]; }, ResourceBundle::getLocales('')); +$locales = array_filter($locales, static function (array $locale) { + return is_array(Punic\Data::explodeLocale($locale['code'])); +}); + +$locales = array_values($locales); + if (file_put_contents(__DIR__ . '/locales.json', json_encode($locales, JSON_PRETTY_PRINT)) === false) { echo 'Failed to update locales.json'; exit(1); diff --git a/tests/lib/App/AppStore/Fetcher/FetcherBase.php b/tests/lib/App/AppStore/Fetcher/FetcherBase.php index cfe0af40483..45f3f22b9d4 100644 --- a/tests/lib/App/AppStore/Fetcher/FetcherBase.php +++ b/tests/lib/App/AppStore/Fetcher/FetcherBase.php @@ -239,7 +239,7 @@ abstract class FetcherBase extends TestCase { $this->timeFactory ->expects($this->at(0)) ->method('getTime') - ->willReturn(1501); + ->willReturn(4801); $client = $this->createMock(IClient::class); $this->clientService ->expects($this->once()) @@ -249,7 +249,15 @@ abstract class FetcherBase extends TestCase { $client ->expects($this->once()) ->method('get') - ->with($this->endpoint) + ->with( + $this->equalTo($this->endpoint), + $this->equalTo([ + 'timeout' => 10, + 'headers' => [ + 'Accept-Encoding' => 'gzip', + ] + ]) + ) ->willReturn($response); $response ->expects($this->once()) @@ -342,7 +350,15 @@ abstract class FetcherBase extends TestCase { $client ->expects($this->once()) ->method('get') - ->with($this->endpoint) + ->with( + $this->equalTo($this->endpoint), + $this->equalTo([ + 'timeout' => 10, + 'headers' => [ + 'Accept-Encoding' => 'gzip', + ] + ]) + ) ->willReturn($response); $response ->expects($this->once()) @@ -430,7 +446,15 @@ abstract class FetcherBase extends TestCase { $client ->expects($this->once()) ->method('get') - ->with($this->endpoint) + ->with( + $this->equalTo($this->endpoint), + $this->equalTo([ + 'timeout' => 10, + 'headers' => [ + 'Accept-Encoding' => 'gzip', + ] + ]) + ) ->willReturn($response); $response ->expects($this->once()) @@ -495,7 +519,15 @@ abstract class FetcherBase extends TestCase { $client ->expects($this->once()) ->method('get') - ->with($this->endpoint) + ->with( + $this->equalTo($this->endpoint), + $this->equalTo([ + 'timeout' => 10, + 'headers' => [ + 'Accept-Encoding' => 'gzip', + ] + ]) + ) ->willThrowException(new \Exception()); $this->assertSame([], $this->fetcher->get()); @@ -533,11 +565,11 @@ abstract class FetcherBase extends TestCase { $this->timeFactory ->expects($this->at(0)) ->method('getTime') - ->willReturn(1501); + ->willReturn(4801); $this->timeFactory ->expects($this->at(1)) ->method('getTime') - ->willReturn(1502); + ->willReturn(4802); $client = $this->createMock(IClient::class); $this->clientService ->expects($this->once()) @@ -552,14 +584,15 @@ abstract class FetcherBase extends TestCase { $this->equalTo([ 'timeout' => 10, 'headers' => [ - 'If-None-Match' => '"myETag"' + 'Accept-Encoding' => 'gzip', + 'If-None-Match' => '"myETag"', ] ]) )->willReturn($response); $response->method('getStatusCode') ->willReturn(304); - $newData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; + $newData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"myETag\""}'; $file ->expects($this->at(1)) ->method('putContent') @@ -624,6 +657,7 @@ abstract class FetcherBase extends TestCase { $this->equalTo([ 'timeout' => 10, 'headers' => [ + 'Accept-Encoding' => 'gzip', 'If-None-Match' => '"myETag"', ] ]) @@ -638,7 +672,7 @@ abstract class FetcherBase extends TestCase { $response->method('getHeader') ->with($this->equalTo('ETag')) ->willReturn('"newETag"'); - $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"newETag\""}'; + $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"newETag\""}'; $file ->expects($this->at(1)) ->method('putContent') @@ -650,11 +684,11 @@ abstract class FetcherBase extends TestCase { $this->timeFactory ->expects($this->at(0)) ->method('getTime') - ->willReturn(1501); + ->willReturn(4801); $this->timeFactory ->expects($this->at(1)) ->method('getTime') - ->willReturn(1502); + ->willReturn(4802); $expected = [ [ @@ -710,6 +744,9 @@ abstract class FetcherBase extends TestCase { $this->equalTo($this->endpoint), $this->equalTo([ 'timeout' => 10, + 'headers' => [ + 'Accept-Encoding' => 'gzip', + ], ]) ) ->willReturn($response); |