aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/admin_audit/lib/Actions/Sharing.php25
-rw-r--r--apps/dav/lib/Connector/Sabre/SharesPlugin.php1
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php1
-rw-r--r--apps/encryption/lib/Crypto/Encryption.php1
-rw-r--r--apps/files/lib/Command/TransferOwnership.php2
-rw-r--r--apps/files/lib/Controller/ApiController.php3
-rw-r--r--apps/files_external/3rdparty/composer.json2
-rw-r--r--apps/files_external/3rdparty/composer.lock12
-rw-r--r--apps/files_external/3rdparty/composer/autoload_classmap.php9
-rw-r--r--apps/files_external/3rdparty/composer/autoload_static.php9
-rw-r--r--apps/files_external/3rdparty/composer/installed.json12
-rw-r--r--apps/files_external/3rdparty/icewind/streams/.travis.yml7
-rw-r--r--apps/files_external/3rdparty/icewind/streams/README.md4
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php106
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/Wrapper.php14
-rw-r--r--apps/files_sharing/js/public.js19
-rw-r--r--apps/files_sharing/js/share.js2
-rw-r--r--apps/files_sharing/lib/Controller/DeletedShareAPIController.php56
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php71
-rw-r--r--apps/files_sharing/lib/Controller/ShareController.php1
-rw-r--r--apps/files_sharing/lib/MountProvider.php1
-rw-r--r--apps/files_sharing/lib/Updater.php1
-rw-r--r--apps/files_sharing/tests/ApiTest.php5
-rw-r--r--apps/files_sharing/tests/Controller/ShareAPIControllerTest.php491
-rw-r--r--apps/files_sharing/tests/MountProviderTest.php24
-rw-r--r--apps/files_sharing/tests/js/shareSpec.js20
-rw-r--r--apps/workflowengine/js/requestuseragentplugin.js19
-rw-r--r--build/integration/features/bootstrap/Provisioning.php24
-rw-r--r--build/integration/features/sharing-v1.feature12
-rw-r--r--core/img/actions/checkmark-white.svg1
-rw-r--r--core/img/actions/confirm-white.svg1
-rw-r--r--core/img/actions/info-white.svg1
-rw-r--r--core/js/share.js1
-rw-r--r--core/js/sharedialogresharerinfoview.js11
-rw-r--r--core/js/sharedialogshareelistview.js4
-rw-r--r--lib/private/App/CodeChecker/CodeChecker.php2
-rw-r--r--lib/private/Files/Stream/Encryption.php19
-rw-r--r--lib/private/Share/Constants.php3
-rw-r--r--lib/private/Share20/Manager.php10
-rw-r--r--lib/private/Share20/ProviderFactory.php34
-rw-r--r--resources/app-info.xsd1
-rw-r--r--tests/lib/Files/Stream/EncryptionTest.php11
-rw-r--r--tests/lib/Share20/ManagerTest.php50
-rw-r--r--version.php4
44 files changed, 1028 insertions, 79 deletions
diff --git a/apps/admin_audit/lib/Actions/Sharing.php b/apps/admin_audit/lib/Actions/Sharing.php
index b66c9f50eb8..0c4601eef38 100644
--- a/apps/admin_audit/lib/Actions/Sharing.php
+++ b/apps/admin_audit/lib/Actions/Sharing.php
@@ -78,6 +78,19 @@ class Sharing extends Action {
'id',
]
);
+ } elseif($params['shareType'] === Share::SHARE_TYPE_ROOM) {
+ $this->log(
+ 'The %s "%s" with ID "%s" has been shared to the room "%s" with permissions "%s" (Share ID: %s)',
+ $params,
+ [
+ 'itemType',
+ 'itemTarget',
+ 'itemSource',
+ 'shareWith',
+ 'permissions',
+ 'id',
+ ]
+ );
}
}
@@ -122,6 +135,18 @@ class Sharing extends Action {
'id',
]
);
+ } elseif($params['shareType'] === Share::SHARE_TYPE_ROOM) {
+ $this->log(
+ 'The %s "%s" with ID "%s" has been unshared from the room "%s" (Share ID: %s)',
+ $params,
+ [
+ 'itemType',
+ 'fileTarget',
+ 'itemSource',
+ 'shareWith',
+ 'id',
+ ]
+ );
}
}
diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
index 825b9821a2a..990cc4a808f 100644
--- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
@@ -124,6 +124,7 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin {
\OCP\Share::SHARE_TYPE_LINK,
\OCP\Share::SHARE_TYPE_REMOTE,
\OCP\Share::SHARE_TYPE_EMAIL,
+ \OCP\Share::SHARE_TYPE_ROOM,
];
foreach ($requestedShareTypes as $requestedShareType) {
// one of each type is enough to find out about the types
diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
index 63b84eb5c6c..d4dd3b49f34 100644
--- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
@@ -298,6 +298,7 @@ class SharesPluginTest extends \Test\TestCase {
[[\OCP\Share::SHARE_TYPE_GROUP]],
[[\OCP\Share::SHARE_TYPE_LINK]],
[[\OCP\Share::SHARE_TYPE_REMOTE]],
+ [[\OCP\Share::SHARE_TYPE_ROOM]],
[[\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP]],
[[\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_LINK]],
[[\OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK]],
diff --git a/apps/encryption/lib/Crypto/Encryption.php b/apps/encryption/lib/Crypto/Encryption.php
index bd75e4ae10c..3f6001cab74 100644
--- a/apps/encryption/lib/Crypto/Encryption.php
+++ b/apps/encryption/lib/Crypto/Encryption.php
@@ -254,7 +254,6 @@ class Encryption implements IEncryptionModule {
public function end($path, $position = 0) {
$result = '';
if ($this->isWriteOperation) {
- $this->keyManager->setVersion($path, $this->version + 1, new View());
// in case of a part file we remember the new signature versions
// the version will be set later on update.
// This way we make sure that other apps listening to the pre-hooks
diff --git a/apps/files/lib/Command/TransferOwnership.php b/apps/files/lib/Command/TransferOwnership.php
index 6113f6df54c..f417898f217 100644
--- a/apps/files/lib/Command/TransferOwnership.php
+++ b/apps/files/lib/Command/TransferOwnership.php
@@ -217,7 +217,7 @@ class TransferOwnership extends Command {
$output->writeln("Collecting all share information for files and folder of $this->sourceUser ...");
$progress = new ProgressBar($output, count($this->shares));
- foreach([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE] as $shareType) {
+ foreach([\OCP\Share::SHARE_TYPE_GROUP, \OCP\Share::SHARE_TYPE_USER, \OCP\Share::SHARE_TYPE_LINK, \OCP\Share::SHARE_TYPE_REMOTE, \OCP\Share::SHARE_TYPE_ROOM] as $shareType) {
$offset = 0;
while (true) {
$sharePage = $this->shareManager->getSharesBy($this->sourceUser, $shareType, null, true, 50, $offset);
diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php
index d71b998ffb1..9443b9776ae 100644
--- a/apps/files/lib/Controller/ApiController.php
+++ b/apps/files/lib/Controller/ApiController.php
@@ -214,7 +214,8 @@ class ApiController extends Controller {
\OCP\Share::SHARE_TYPE_GROUP,
\OCP\Share::SHARE_TYPE_LINK,
\OCP\Share::SHARE_TYPE_REMOTE,
- \OCP\Share::SHARE_TYPE_EMAIL
+ \OCP\Share::SHARE_TYPE_EMAIL,
+ \OCP\Share::SHARE_TYPE_ROOM
];
foreach ($requestedShareTypes as $requestedShareType) {
// one of each type is enough to find out about the types
diff --git a/apps/files_external/3rdparty/composer.json b/apps/files_external/3rdparty/composer.json
index 537159bbf66..caf87983c50 100644
--- a/apps/files_external/3rdparty/composer.json
+++ b/apps/files_external/3rdparty/composer.json
@@ -8,7 +8,7 @@
"classmap-authoritative": true
},
"require": {
- "icewind/streams": "0.5.2",
+ "icewind/streams": "0.6.1",
"icewind/smb": "3.0.0"
}
}
diff --git a/apps/files_external/3rdparty/composer.lock b/apps/files_external/3rdparty/composer.lock
index 7bfcdba3d2f..2339220ffbc 100644
--- a/apps/files_external/3rdparty/composer.lock
+++ b/apps/files_external/3rdparty/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "0235b6f1a4131c9312afef7a58f3a80e",
+ "content-hash": "1465c8a4b4139e514086d5803d90af2d",
"packages": [
{
"name": "icewind/smb",
@@ -49,16 +49,16 @@
},
{
"name": "icewind/streams",
- "version": "0.5.2",
+ "version": "0.6.1",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/Streams.git",
- "reference": "6bfd2fdbd99319f5e010d0a684409189a562cb1e"
+ "reference": "0a78597117d8a02937ea05206f219294449fb06e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/icewind1991/Streams/zipball/6bfd2fdbd99319f5e010d0a684409189a562cb1e",
- "reference": "6bfd2fdbd99319f5e010d0a684409189a562cb1e",
+ "url": "https://api.github.com/repos/icewind1991/Streams/zipball/0a78597117d8a02937ea05206f219294449fb06e",
+ "reference": "0a78597117d8a02937ea05206f219294449fb06e",
"shasum": ""
},
"require": {
@@ -86,7 +86,7 @@
}
],
"description": "A set of generic stream wrappers",
- "time": "2016-12-02T14:21:23+00:00"
+ "time": "2018-04-24T09:07:38+00:00"
}
],
"packages-dev": [],
diff --git a/apps/files_external/3rdparty/composer/autoload_classmap.php b/apps/files_external/3rdparty/composer/autoload_classmap.php
index d2e658d9f61..6c5f86a5796 100644
--- a/apps/files_external/3rdparty/composer/autoload_classmap.php
+++ b/apps/files_external/3rdparty/composer/autoload_classmap.php
@@ -51,14 +51,6 @@ return array(
'Icewind\\SMB\\Native\\NativeWriteStream' => $vendorDir . '/icewind/smb/src/Native/NativeWriteStream.php',
'Icewind\\SMB\\ServerFactory' => $vendorDir . '/icewind/smb/src/ServerFactory.php',
'Icewind\\SMB\\System' => $vendorDir . '/icewind/smb/src/System.php',
- 'Icewind\\SMB\\Test\\AbstractShareTest' => $vendorDir . '/icewind/smb/tests/AbstractShareTest.php',
- 'Icewind\\SMB\\Test\\NativeShareTest' => $vendorDir . '/icewind/smb/tests/NativeShareTest.php',
- 'Icewind\\SMB\\Test\\NativeStreamTest' => $vendorDir . '/icewind/smb/tests/NativeStreamTest.php',
- 'Icewind\\SMB\\Test\\NotifyHandlerTest' => $vendorDir . '/icewind/smb/tests/NotifyHandlerTest.php',
- 'Icewind\\SMB\\Test\\ParserTest' => $vendorDir . '/icewind/smb/tests/ParserTest.php',
- 'Icewind\\SMB\\Test\\ServerTest' => $vendorDir . '/icewind/smb/tests/ServerTest.php',
- 'Icewind\\SMB\\Test\\ShareTest' => $vendorDir . '/icewind/smb/tests/ShareTest.php',
- 'Icewind\\SMB\\Test\\TestCase' => $vendorDir . '/icewind/smb/tests/TestCase.php',
'Icewind\\SMB\\TimeZoneProvider' => $vendorDir . '/icewind/smb/src/TimeZoneProvider.php',
'Icewind\\SMB\\Wrapped\\Connection' => $vendorDir . '/icewind/smb/src/Wrapped/Connection.php',
'Icewind\\SMB\\Wrapped\\ErrorCodes' => $vendorDir . '/icewind/smb/src/Wrapped/ErrorCodes.php',
@@ -69,6 +61,7 @@ return array(
'Icewind\\SMB\\Wrapped\\Server' => $vendorDir . '/icewind/smb/src/Wrapped/Server.php',
'Icewind\\SMB\\Wrapped\\Share' => $vendorDir . '/icewind/smb/src/Wrapped/Share.php',
'Icewind\\Streams\\CallbackWrapper' => $vendorDir . '/icewind/streams/src/CallbackWrapper.php',
+ 'Icewind\\Streams\\CountWrapper' => $vendorDir . '/icewind/streams/src/CountWrapper.php',
'Icewind\\Streams\\Directory' => $vendorDir . '/icewind/streams/src/Directory.php',
'Icewind\\Streams\\DirectoryFilter' => $vendorDir . '/icewind/streams/src/DirectoryFilter.php',
'Icewind\\Streams\\DirectoryWrapper' => $vendorDir . '/icewind/streams/src/DirectoryWrapper.php',
diff --git a/apps/files_external/3rdparty/composer/autoload_static.php b/apps/files_external/3rdparty/composer/autoload_static.php
index 3234d89e5b9..658c947c9c2 100644
--- a/apps/files_external/3rdparty/composer/autoload_static.php
+++ b/apps/files_external/3rdparty/composer/autoload_static.php
@@ -81,14 +81,6 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3
'Icewind\\SMB\\Native\\NativeWriteStream' => __DIR__ . '/..' . '/icewind/smb/src/Native/NativeWriteStream.php',
'Icewind\\SMB\\ServerFactory' => __DIR__ . '/..' . '/icewind/smb/src/ServerFactory.php',
'Icewind\\SMB\\System' => __DIR__ . '/..' . '/icewind/smb/src/System.php',
- 'Icewind\\SMB\\Test\\AbstractShareTest' => __DIR__ . '/..' . '/icewind/smb/tests/AbstractShareTest.php',
- 'Icewind\\SMB\\Test\\NativeShareTest' => __DIR__ . '/..' . '/icewind/smb/tests/NativeShareTest.php',
- 'Icewind\\SMB\\Test\\NativeStreamTest' => __DIR__ . '/..' . '/icewind/smb/tests/NativeStreamTest.php',
- 'Icewind\\SMB\\Test\\NotifyHandlerTest' => __DIR__ . '/..' . '/icewind/smb/tests/NotifyHandlerTest.php',
- 'Icewind\\SMB\\Test\\ParserTest' => __DIR__ . '/..' . '/icewind/smb/tests/ParserTest.php',
- 'Icewind\\SMB\\Test\\ServerTest' => __DIR__ . '/..' . '/icewind/smb/tests/ServerTest.php',
- 'Icewind\\SMB\\Test\\ShareTest' => __DIR__ . '/..' . '/icewind/smb/tests/ShareTest.php',
- 'Icewind\\SMB\\Test\\TestCase' => __DIR__ . '/..' . '/icewind/smb/tests/TestCase.php',
'Icewind\\SMB\\TimeZoneProvider' => __DIR__ . '/..' . '/icewind/smb/src/TimeZoneProvider.php',
'Icewind\\SMB\\Wrapped\\Connection' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/Connection.php',
'Icewind\\SMB\\Wrapped\\ErrorCodes' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/ErrorCodes.php',
@@ -99,6 +91,7 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3
'Icewind\\SMB\\Wrapped\\Server' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/Server.php',
'Icewind\\SMB\\Wrapped\\Share' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/Share.php',
'Icewind\\Streams\\CallbackWrapper' => __DIR__ . '/..' . '/icewind/streams/src/CallbackWrapper.php',
+ 'Icewind\\Streams\\CountWrapper' => __DIR__ . '/..' . '/icewind/streams/src/CountWrapper.php',
'Icewind\\Streams\\Directory' => __DIR__ . '/..' . '/icewind/streams/src/Directory.php',
'Icewind\\Streams\\DirectoryFilter' => __DIR__ . '/..' . '/icewind/streams/src/DirectoryFilter.php',
'Icewind\\Streams\\DirectoryWrapper' => __DIR__ . '/..' . '/icewind/streams/src/DirectoryWrapper.php',
diff --git a/apps/files_external/3rdparty/composer/installed.json b/apps/files_external/3rdparty/composer/installed.json
index 3b2870a13bf..707b876e588 100644
--- a/apps/files_external/3rdparty/composer/installed.json
+++ b/apps/files_external/3rdparty/composer/installed.json
@@ -44,17 +44,17 @@
},
{
"name": "icewind/streams",
- "version": "0.5.2",
- "version_normalized": "0.5.2.0",
+ "version": "0.6.1",
+ "version_normalized": "0.6.1.0",
"source": {
"type": "git",
"url": "https://github.com/icewind1991/Streams.git",
- "reference": "6bfd2fdbd99319f5e010d0a684409189a562cb1e"
+ "reference": "0a78597117d8a02937ea05206f219294449fb06e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/icewind1991/Streams/zipball/6bfd2fdbd99319f5e010d0a684409189a562cb1e",
- "reference": "6bfd2fdbd99319f5e010d0a684409189a562cb1e",
+ "url": "https://api.github.com/repos/icewind1991/Streams/zipball/0a78597117d8a02937ea05206f219294449fb06e",
+ "reference": "0a78597117d8a02937ea05206f219294449fb06e",
"shasum": ""
},
"require": {
@@ -64,7 +64,7 @@
"phpunit/phpunit": "^4.8",
"satooshi/php-coveralls": "v1.0.0"
},
- "time": "2016-12-02T14:21:23+00:00",
+ "time": "2018-04-24T09:07:38+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
diff --git a/apps/files_external/3rdparty/icewind/streams/.travis.yml b/apps/files_external/3rdparty/icewind/streams/.travis.yml
index d2e1afaad67..68efcd2c744 100644
--- a/apps/files_external/3rdparty/icewind/streams/.travis.yml
+++ b/apps/files_external/3rdparty/icewind/streams/.travis.yml
@@ -4,11 +4,8 @@ php:
- 5.5
- 5.6
- 7.0
- - hhvm
-
-matrix:
- allow_failures:
- - php: hhvm # due to facebook/hhvm#3321
+ - 7.1
+ - 7.2
env:
global:
diff --git a/apps/files_external/3rdparty/icewind/streams/README.md b/apps/files_external/3rdparty/icewind/streams/README.md
index ca13db28e44..88ab2dd92a3 100644
--- a/apps/files_external/3rdparty/icewind/streams/README.md
+++ b/apps/files_external/3rdparty/icewind/streams/README.md
@@ -1,4 +1,4 @@
-#Streams#
+# Streams #
[![Build Status](https://travis-ci.org/icewind1991/Streams.svg?branch=master)](https://travis-ci.org/icewind1991/Streams)
[![Coverage Status](https://img.shields.io/coveralls/icewind1991/Streams.svg)](https://coveralls.io/r/icewind1991/Streams?branch=master)
@@ -6,7 +6,7 @@
Generic stream wrappers for php.
-##CallBackWrapper##
+## CallBackWrapper ##
A `CallBackWrapper` can be used to register callbacks on read, write and closing of the stream,
it wraps an existing stream and can thus be used for any stream in php
diff --git a/apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php
new file mode 100644
index 00000000000..8b86ab9187c
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php
@@ -0,0 +1,106 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 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 Icewind\Streams;
+
+/**
+ * Wrapper that counts the amount of data read and written
+ *
+ * The following options should be passed in the context when opening the stream
+ * [
+ * 'callback' => [
+ * 'source' => resource
+ * 'callback' => function($readCount, $writeCount){}
+ * ]
+ * ]
+ *
+ * The callback will be called when the stream is closed
+ */
+class CountWrapper extends Wrapper {
+ /**
+ * @var int
+ */
+ protected $readCount = 0;
+
+ /**
+ * @var int
+ */
+ protected $writeCount = 0;
+
+ /**
+ * @var callable
+ */
+ protected $callback;
+
+ /**
+ * Wraps a stream with the provided callbacks
+ *
+ * @param resource $source
+ * @param callable $callback
+ * @return resource
+ *
+ * @throws \BadMethodCallException
+ */
+ public static function wrap($source, $callback) {
+ if (!is_callable($callback)) {
+ throw new \InvalidArgumentException('Invalid or missing callback');
+ }
+ $context = stream_context_create(array(
+ 'count' => array(
+ 'source' => $source,
+ 'callback' => $callback
+ )
+ ));
+ return Wrapper::wrapSource($source, $context, 'callback', '\Icewind\Streams\CountWrapper');
+ }
+
+ protected function open() {
+ $context = $this->loadContext('count');
+ $this->callback = $context['callback'];
+ return true;
+ }
+
+ public function dir_opendir($path, $options) {
+ return $this->open();
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path) {
+ return $this->open();
+ }
+
+ public function stream_read($count) {
+ $result = parent::stream_read($count);
+ $this->readCount += strlen($result);
+ return $result;
+ }
+
+ public function stream_write($data) {
+ $result = parent::stream_write($data);
+ $this->writeCount += strlen($data);
+ return $result;
+ }
+
+ public function stream_close() {
+ $result = parent::stream_close();
+ call_user_func($this->callback, $this->readCount, $this->writeCount);
+ return $result;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php b/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
index 8e52eff9a08..babd2c1a0b3 100644
--- a/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
+++ b/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
@@ -26,12 +26,15 @@ abstract class Wrapper implements File, Directory {
protected $source;
protected static function wrapSource($source, $context, $protocol, $class) {
+ if (!is_resource($source)) {
+ throw new \BadMethodCallException();
+ }
try {
stream_wrapper_register($protocol, $class);
- if (@rewinddir($source) === false) {
- $wrapped = fopen($protocol . '://', 'r+', false, $context);
- } else {
+ if (self::isDirectoryHandle($source)) {
$wrapped = opendir($protocol . '://', $context);
+ } else {
+ $wrapped = fopen($protocol . '://', 'r+', false, $context);
}
} catch (\BadMethodCallException $e) {
stream_wrapper_unregister($protocol);
@@ -41,6 +44,11 @@ abstract class Wrapper implements File, Directory {
return $wrapped;
}
+ protected static function isDirectoryHandle($resource) {
+ $meta = stream_get_meta_data($resource);
+ return $meta['stream_type'] == 'dir';
+ }
+
/**
* Load the source from the stream context and return the context options
*
diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js
index 998964b2d8a..64ffe8bbf2e 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -72,7 +72,24 @@ OCA.Sharing.PublicApp = {
fileActions: fileActions,
detailsViewEnabled: false,
filesClient: filesClient,
- enableUpload: true
+ enableUpload: true,
+ multiSelectMenu: [
+ {
+ name: 'copyMove',
+ displayName: t('files', 'Move or copy'),
+ iconClass: 'icon-external',
+ },
+ {
+ name: 'download',
+ displayName: t('files', 'Download'),
+ iconClass: 'icon-download',
+ },
+ {
+ name: 'delete',
+ displayName: t('files', 'Delete'),
+ iconClass: 'icon-delete',
+ }
+ ]
}
);
this.files = OCA.Files.Files;
diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js
index a925920f3bc..0f8dc58a85e 100644
--- a/apps/files_sharing/js/share.js
+++ b/apps/files_sharing/js/share.js
@@ -144,6 +144,8 @@
hasShares = true;
} else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) {
hasShares = true;
+ } else if (shareType === OC.Share.SHARE_TYPE_ROOM) {
+ hasShares = true;
}
});
OCA.Sharing.Util._updateFileActionIcon($tr, hasShares, hasLink);
diff --git a/apps/files_sharing/lib/Controller/DeletedShareAPIController.php b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php
index d95b434e48f..6c7242ef613 100644
--- a/apps/files_sharing/lib/Controller/DeletedShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/DeletedShareAPIController.php
@@ -26,14 +26,17 @@ declare(strict_types=1);
namespace OCA\Files_Sharing\Controller;
+use OCP\App\IAppManager;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\AppFramework\OCSController;
+use OCP\AppFramework\QueryException;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IGroupManager;
use OCP\IRequest;
+use OCP\IServerContainer;
use OCP\IUserManager;
use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\Exceptions\ShareNotFound;
@@ -57,13 +60,21 @@ class DeletedShareAPIController extends OCSController {
/** @var IRootFolder */
private $rootFolder;
+ /** @var IAppManager */
+ private $appManager;
+
+ /** @var IServerContainer */
+ private $serverContainer;
+
public function __construct(string $appName,
IRequest $request,
ShareManager $shareManager,
string $UserId,
IUserManager $userManager,
IGroupManager $groupManager,
- IRootFolder $rootFolder) {
+ IRootFolder $rootFolder,
+ IAppManager $appManager,
+ IServerContainer $serverContainer) {
parent::__construct($appName, $request);
$this->shareManager = $shareManager;
@@ -71,8 +82,13 @@ class DeletedShareAPIController extends OCSController {
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->rootFolder = $rootFolder;
+ $this->appManager = $appManager;
+ $this->serverContainer = $serverContainer;
}
+ /**
+ * @suppress PhanUndeclaredClassMethod
+ */
private function formatShare(IShare $share): array {
$result = [
@@ -120,9 +136,19 @@ class DeletedShareAPIController extends OCSController {
$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
}
- $group = $this->groupManager->get($share->getSharedWith());
- $result['share_with'] = $share->getSharedWith();
- $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
+ if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) {
+ $group = $this->groupManager->get($share->getSharedWith());
+ $result['share_with'] = $share->getSharedWith();
+ $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
+ } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM) {
+ $result['share_with'] = $share->getSharedWith();
+ $result['share_with_displayname'] = '';
+
+ try {
+ $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
+ } catch (QueryException $e) {
+ }
+ }
return $result;
@@ -132,7 +158,10 @@ class DeletedShareAPIController extends OCSController {
* @NoAdminRequired
*/
public function index(): DataResponse {
- $shares = $this->shareManager->getDeletedSharedWith($this->userId, \OCP\Share::SHARE_TYPE_GROUP, null, -1, 0);
+ $groupShares = $this->shareManager->getDeletedSharedWith($this->userId, \OCP\Share::SHARE_TYPE_GROUP, null, -1, 0);
+ $roomShares = $this->shareManager->getDeletedSharedWith($this->userId, \OCP\Share::SHARE_TYPE_ROOM, null, -1, 0);
+
+ $shares = array_merge($groupShares, $roomShares);
$shares = array_map(function (IShare $share) {
return $this->formatShare($share);
@@ -165,4 +194,21 @@ class DeletedShareAPIController extends OCSController {
return new DataResponse([]);
}
+
+ /**
+ * Returns the helper of DeletedShareAPIController for room shares.
+ *
+ * If the Talk application is not enabled or the helper is not available
+ * a QueryException is thrown instead.
+ *
+ * @return \OCA\Spreed\Share\Helper\DeletedShareAPIController
+ * @throws QueryException
+ */
+ private function getRoomShareHelper() {
+ if (!$this->appManager->isEnabledForUser('spreed')) {
+ throw new QueryException();
+ }
+
+ return $this->serverContainer->query('\OCA\Spreed\Share\Helper\DeletedShareAPIController');
+ }
}
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index bda0047e66c..461c0e47320 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -37,6 +37,7 @@ use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCS\OCSForbiddenException;
use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\AppFramework\OCSController;
+use OCP\AppFramework\QueryException;
use OCP\Constants;
use OCP\Files\Folder;
use OCP\Files\Node;
@@ -46,6 +47,7 @@ use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IUserManager;
use OCP\IRequest;
+use OCP\IServerContainer;
use OCP\IURLGenerator;
use OCP\Files\IRootFolder;
use OCP\Lock\LockedException;
@@ -84,6 +86,8 @@ class ShareAPIController extends OCSController {
private $config;
/** @var IAppManager */
private $appManager;
+ /** @var IServerContainer */
+ private $serverContainer;
/**
* Share20OCS constructor.
@@ -99,6 +103,7 @@ class ShareAPIController extends OCSController {
* @param IL10N $l10n
* @param IConfig $config
* @param IAppManager $appManager
+ * @param IServerContainer $serverContainer
*/
public function __construct(
string $appName,
@@ -111,7 +116,8 @@ class ShareAPIController extends OCSController {
string $userId,
IL10N $l10n,
IConfig $config,
- IAppManager $appManager
+ IAppManager $appManager,
+ IServerContainer $serverContainer
) {
parent::__construct($appName, $request);
@@ -125,6 +131,7 @@ class ShareAPIController extends OCSController {
$this->l = $l10n;
$this->config = $config;
$this->appManager = $appManager;
+ $this->serverContainer = $serverContainer;
}
/**
@@ -134,6 +141,8 @@ class ShareAPIController extends OCSController {
* @param Node|null $recipientNode
* @return array
* @throws NotFoundException In case the node can't be resolved.
+ *
+ * @suppress PhanUndeclaredClassMethod
*/
protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = null): array {
$sharedBy = $this->userManager->get($share->getSharedBy());
@@ -231,6 +240,14 @@ class ShareAPIController extends OCSController {
$shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0);
$shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' '));
$result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
+ } else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
+ $result['share_with'] = $share->getSharedWith();
+ $result['share_with_displayname'] = '';
+
+ try {
+ $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
+ } catch (QueryException $e) {
+ }
}
@@ -315,7 +332,8 @@ class ShareAPIController extends OCSController {
throw new OCSNotFoundException($this->l->t('Could not delete share'));
}
- if ($share->getShareType() === Share::SHARE_TYPE_GROUP &&
+ if (($share->getShareType() === Share::SHARE_TYPE_GROUP ||
+ $share->getShareType() === Share::SHARE_TYPE_ROOM) &&
$share->getShareOwner() !== $this->currentUser &&
$share->getSharedBy() !== $this->currentUser) {
$this->shareManager->deleteFromSelf($share, $this->currentUser);
@@ -515,6 +533,12 @@ class ShareAPIController extends OCSController {
}
$share->setSharedWith($shareWith);
$share->setPermissions($permissions);
+ } else if ($shareType === Share::SHARE_TYPE_ROOM) {
+ try {
+ $this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
+ } catch (QueryException $e) {
+ throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
+ }
} else {
throw new OCSBadRequestException($this->l->t('Unknown share type'));
}
@@ -546,8 +570,9 @@ class ShareAPIController extends OCSController {
$userShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $node, -1, 0);
$groupShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $node, -1, 0);
$circleShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_CIRCLE, $node, -1, 0);
+ $roomShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $node, -1, 0);
- $shares = array_merge($userShares, $groupShares, $circleShares);
+ $shares = array_merge($userShares, $groupShares, $circleShares, $roomShares);
$shares = array_filter($shares, function (IShare $share) {
return $share->getShareOwner() !== $this->currentUser;
@@ -594,6 +619,7 @@ class ShareAPIController extends OCSController {
if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, false, -1, 0));
}
+ $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, false, -1, 0));
}
$formatted = [];
@@ -679,8 +705,9 @@ class ShareAPIController extends OCSController {
} else {
$circleShares = [];
}
+ $roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0);
- $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares);
+ $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares);
if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
$federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0);
@@ -864,6 +891,7 @@ class ShareAPIController extends OCSController {
/* Check if this is an incomming share */
$incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $share->getNode(), -1, 0);
$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0));
+ $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0));
/** @var \OCP\Share\IShare[] $incomingShares */
if (!empty($incomingShares)) {
@@ -888,6 +916,9 @@ class ShareAPIController extends OCSController {
return new DataResponse($this->formatShare($share));
}
+ /**
+ * @suppress PhanUndeclaredClassMethod
+ */
protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
// A file with permissions 0 can't be accessed by us. So Don't show it
if ($share->getPermissions() === 0) {
@@ -921,6 +952,14 @@ class ShareAPIController extends OCSController {
return true;
}
+ if ($share->getShareType() === Share::SHARE_TYPE_ROOM) {
+ try {
+ return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser);
+ } catch (QueryException $e) {
+ return false;
+ }
+ }
+
return false;
}
@@ -988,6 +1027,13 @@ class ShareAPIController extends OCSController {
// Do nothing, just try the other share type
}
+ try {
+ $share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser);
+ return $share;
+ } catch (ShareNotFound $e) {
+ // Do nothing, just try the other share type
+ }
+
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
throw new ShareNotFound();
}
@@ -1016,4 +1062,21 @@ class ShareAPIController extends OCSController {
$this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
}
}
+
+ /**
+ * Returns the helper of ShareAPIController for room shares.
+ *
+ * If the Talk application is not enabled or the helper is not available
+ * a QueryException is thrown instead.
+ *
+ * @return \OCA\Spreed\Share\Helper\ShareAPIController
+ * @throws QueryException
+ */
+ private function getRoomShareHelper() {
+ if (!$this->appManager->isEnabledForUser('spreed')) {
+ throw new QueryException();
+ }
+
+ return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController');
+ }
}
diff --git a/apps/files_sharing/lib/Controller/ShareController.php b/apps/files_sharing/lib/Controller/ShareController.php
index 6ebffed2b58..9594d6e71f5 100644
--- a/apps/files_sharing/lib/Controller/ShareController.php
+++ b/apps/files_sharing/lib/Controller/ShareController.php
@@ -399,6 +399,7 @@ class ShareController extends AuthPublicShareController {
\OCP\Util::addScript('files', 'fileinfomodel');
\OCP\Util::addScript('files', 'newfilemenu');
\OCP\Util::addScript('files', 'files');
+ \OCP\Util::addScript('files', 'filemultiselectmenu');
\OCP\Util::addScript('files', 'filelist');
\OCP\Util::addScript('files', 'keyboardshortcuts');
}
diff --git a/apps/files_sharing/lib/MountProvider.php b/apps/files_sharing/lib/MountProvider.php
index fd4c537210f..cb02a2b5f23 100644
--- a/apps/files_sharing/lib/MountProvider.php
+++ b/apps/files_sharing/lib/MountProvider.php
@@ -74,6 +74,7 @@ class MountProvider implements IMountProvider {
$shares = $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_USER, null, -1);
$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_GROUP, null, -1));
$shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_CIRCLE, null, -1));
+ $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_ROOM, null, -1));
// filter out excluded shares and group shares that includes self
$shares = array_filter($shares, function (\OCP\Share\IShare $share) use ($user) {
diff --git a/apps/files_sharing/lib/Updater.php b/apps/files_sharing/lib/Updater.php
index 784fe8b72b1..848ada62c7b 100644
--- a/apps/files_sharing/lib/Updater.php
+++ b/apps/files_sharing/lib/Updater.php
@@ -59,6 +59,7 @@ class Updater {
$shares = $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_USER, $src, false, -1);
$shares = array_merge($shares, $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $src, false, -1));
+ $shares = array_merge($shares, $shareManager->getSharesBy($userFolder->getOwner()->getUID(), \OCP\Share::SHARE_TYPE_ROOM, $src, false, -1));
// If the path we move is not a share we don't care
if (empty($shares)) {
diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php
index a68ec7de1f0..0616daed62d 100644
--- a/apps/files_sharing/tests/ApiTest.php
+++ b/apps/files_sharing/tests/ApiTest.php
@@ -41,6 +41,7 @@ use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IRequest;
+use OCP\IServerContainer;
/**
* Class ApiTest
@@ -109,6 +110,7 @@ class ApiTest extends TestCase {
}));
$config = $this->createMock(IConfig::class);
$appManager = $this->createMock(IAppManager::class);
+ $serverContainer = $this->createMock(IServerContainer::class);
return new ShareAPIController(
self::APP_NAME,
@@ -121,7 +123,8 @@ class ApiTest extends TestCase {
$userId,
$l,
$config,
- $appManager
+ $appManager,
+ $serverContainer
);
}
diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
index 4fd8162db3d..15c4071bc46 100644
--- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
@@ -38,6 +38,7 @@ use OCA\Files_Sharing\Controller\ShareAPIController;
use OCP\Files\NotFoundException;
use OCP\IGroupManager;
use OCP\IUserManager;
+use OCP\IServerContainer;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUser;
@@ -92,6 +93,9 @@ class ShareAPIControllerTest extends TestCase {
/** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */
private $appManager;
+ /** @var IServerContainer|\PHPUnit_Framework_MockObject_MockObject */
+ private $serverContainer;
+
protected function setUp() {
$this->shareManager = $this->createMock(IManager::class);
$this->shareManager
@@ -112,6 +116,7 @@ class ShareAPIControllerTest extends TestCase {
}));
$this->config = $this->createMock(IConfig::class);
$this->appManager = $this->createMock(IAppManager::class);
+ $this->serverContainer = $this->createMock(IServerContainer::class);
$this->ocs = new ShareAPIController(
$this->appName,
@@ -124,7 +129,8 @@ class ShareAPIControllerTest extends TestCase {
$this->currentUser,
$this->l,
$this->config,
- $this->appManager
+ $this->appManager,
+ $this->serverContainer
);
}
@@ -144,7 +150,8 @@ class ShareAPIControllerTest extends TestCase {
$this->currentUser,
$this->l,
$this->config,
- $this->appManager
+ $this->appManager,
+ $this->serverContainer
])->setMethods(['formatShare'])
->getMock();
}
@@ -159,10 +166,10 @@ class ShareAPIControllerTest extends TestCase {
*/
public function testDeleteShareShareNotFound() {
$this->shareManager
- ->expects($this->exactly(2))
+ ->expects($this->exactly(3))
->method('getShareById')
->will($this->returnCallback(function($id) {
- if ($id === 'ocinternal:42' || $id === 'ocFederatedSharing:42') {
+ if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42') {
throw new \OCP\Share\Exceptions\ShareNotFound();
} else {
throw new \Exception();
@@ -461,7 +468,8 @@ class ShareAPIControllerTest extends TestCase {
$this->currentUser,
$this->l,
$this->config,
- $this->appManager
+ $this->appManager,
+ $this->serverContainer
])->setMethods(['canAccessShare'])
->getMock();
@@ -596,6 +604,65 @@ class ShareAPIControllerTest extends TestCase {
$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
}
+ public function dataCanAccessRoomShare() {
+ $result = [];
+
+ $share = $this->createMock(IShare::class);
+ $share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_ROOM);
+ $share->method('getSharedWith')->willReturn('recipientRoom');
+
+ $result[] = [
+ false, $share, false, false
+ ];
+
+ $result[] = [
+ false, $share, false, true
+ ];
+
+ $result[] = [
+ true, $share, true, true
+ ];
+
+ $result[] = [
+ false, $share, true, false
+ ];
+
+ return $result;
+ }
+
+ /**
+ * @dataProvider dataCanAccessRoomShare
+ *
+ * @param bool $expects
+ * @param \OCP\Share\IShare $share
+ * @param bool helperAvailable
+ * @param bool canAccessShareByHelper
+ */
+ public function testCanAccessRoomShare(bool $expected, \OCP\Share\IShare $share, bool $helperAvailable, bool $canAccessShareByHelper) {
+ if (!$helperAvailable) {
+ $this->appManager->method('isEnabledForUser')
+ ->with('spreed')
+ ->willReturn(false);
+ } else {
+ $this->appManager->method('isEnabledForUser')
+ ->with('spreed')
+ ->willReturn(true);
+
+ $helper = $this->getMockBuilder('\OCA\Spreed\Share\Helper\ShareAPIController')
+ ->setMethods(array('canAccessShare'))
+ ->getMock();
+ $helper->method('canAccessShare')
+ ->with($share, $this->currentUser)
+ ->willReturn($canAccessShareByHelper);
+
+ $this->serverContainer->method('query')
+ ->with('\OCA\Spreed\Share\Helper\ShareAPIController')
+ ->willReturn($helper);
+ }
+
+ $this->assertEquals($expected, $this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
+ }
+
/**
* @expectedException \OCP\AppFramework\OCS\OCSNotFoundException
* @expectedExceptionMessage Please specify a file or folder path
@@ -733,7 +800,8 @@ class ShareAPIControllerTest extends TestCase {
$this->currentUser,
$this->l,
$this->config,
- $this->appManager
+ $this->appManager,
+ $this->serverContainer
])->setMethods(['formatShare'])
->getMock();
@@ -832,7 +900,8 @@ class ShareAPIControllerTest extends TestCase {
$this->currentUser,
$this->l,
$this->config,
- $this->appManager
+ $this->appManager,
+ $this->serverContainer
])->setMethods(['formatShare'])
->getMock();
@@ -1128,6 +1197,186 @@ class ShareAPIControllerTest extends TestCase {
$ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_LINK, null, 'false', '', null, 'a1b2d3');
}
+ public function testCreateShareRoom() {
+ $ocs = $this->mockFormatShare();
+
+ $share = $this->newShare();
+ $this->shareManager->method('newShare')->willReturn($share);
+
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
+ $this->rootFolder->expects($this->once())
+ ->method('getUserFolder')
+ ->with('currentUser')
+ ->willReturn($userFolder);
+
+ $path = $this->getMockBuilder(File::class)->getMock();
+ $storage = $this->getMockBuilder(Storage::class)->getMock();
+ $storage->method('instanceOfStorage')
+ ->with('OCA\Files_Sharing\External\Storage')
+ ->willReturn(false);
+ $path->method('getStorage')->willReturn($storage);
+ $userFolder->expects($this->once())
+ ->method('get')
+ ->with('valid-path')
+ ->willReturn($path);
+
+ $path->expects($this->once())
+ ->method('lock')
+ ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
+
+ $this->appManager->method('isEnabledForUser')
+ ->with('spreed')
+ ->willReturn(true);
+
+ $helper = $this->getMockBuilder('\OCA\Spreed\Share\Helper\ShareAPIController')
+ ->setMethods(array('createShare'))
+ ->getMock();
+ $helper->method('createShare')
+ ->with(
+ $share,
+ 'recipientRoom',
+ \OCP\Constants::PERMISSION_ALL &
+ ~\OCP\Constants::PERMISSION_DELETE &
+ ~\OCP\Constants::PERMISSION_CREATE,
+ ''
+ )->will($this->returnCallback(
+ function ($share) {
+ $share->setSharedWith('recipientRoom');
+ $share->setPermissions(
+ \OCP\Constants::PERMISSION_ALL &
+ ~\OCP\Constants::PERMISSION_DELETE &
+ ~\OCP\Constants::PERMISSION_CREATE
+ );
+ }
+ ));
+
+ $this->serverContainer->method('query')
+ ->with('\OCA\Spreed\Share\Helper\ShareAPIController')
+ ->willReturn($helper);
+
+ $this->shareManager->method('createShare')
+ ->with($this->callback(function (\OCP\Share\IShare $share) use ($path) {
+ return $share->getNode() === $path &&
+ $share->getPermissions() === (
+ \OCP\Constants::PERMISSION_ALL &
+ ~\OCP\Constants::PERMISSION_DELETE &
+ ~\OCP\Constants::PERMISSION_CREATE
+ ) &&
+ $share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM &&
+ $share->getSharedWith() === 'recipientRoom' &&
+ $share->getSharedBy() === 'currentUser';
+ }))
+ ->will($this->returnArgument(0));
+
+ $expected = new DataResponse([]);
+ $result = $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_ROOM, 'recipientRoom');
+
+ $this->assertInstanceOf(get_class($expected), $result);
+ $this->assertEquals($expected->getData(), $result->getData());
+ }
+
+ /**
+ * @expectedException \OCP\AppFramework\OCS\OCSForbiddenException
+ * @expectedExceptionMessage Sharing valid-path failed because the back end does not support room shares
+ */
+ public function testCreateShareRoomHelperNotAvailable() {
+ $ocs = $this->mockFormatShare();
+
+ $share = $this->newShare();
+ $this->shareManager->method('newShare')->willReturn($share);
+
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
+ $this->rootFolder->expects($this->once())
+ ->method('getUserFolder')
+ ->with('currentUser')
+ ->willReturn($userFolder);
+
+ $path = $this->getMockBuilder(File::class)->getMock();
+ $storage = $this->getMockBuilder(Storage::class)->getMock();
+ $storage->method('instanceOfStorage')
+ ->with('OCA\Files_Sharing\External\Storage')
+ ->willReturn(false);
+ $path->method('getStorage')->willReturn($storage);
+ $path->method('getPath')->willReturn('valid-path');
+ $userFolder->expects($this->once())
+ ->method('get')
+ ->with('valid-path')
+ ->willReturn($path);
+
+ $path->expects($this->once())
+ ->method('lock')
+ ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
+
+ $this->appManager->method('isEnabledForUser')
+ ->with('spreed')
+ ->willReturn(false);
+
+ $this->shareManager->expects($this->never())->method('createShare');
+
+ $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_ROOM, 'recipientRoom');
+ }
+
+ /**
+ * @expectedException \OCP\AppFramework\OCS\OCSNotFoundException
+ * @expectedExceptionMessage Exception thrown by the helper
+ */
+ public function testCreateShareRoomHelperThrowException() {
+ $ocs = $this->mockFormatShare();
+
+ $share = $this->newShare();
+ $this->shareManager->method('newShare')->willReturn($share);
+
+ $userFolder = $this->getMockBuilder(Folder::class)->getMock();
+ $this->rootFolder->expects($this->once())
+ ->method('getUserFolder')
+ ->with('currentUser')
+ ->willReturn($userFolder);
+
+ $path = $this->getMockBuilder(File::class)->getMock();
+ $storage = $this->getMockBuilder(Storage::class)->getMock();
+ $storage->method('instanceOfStorage')
+ ->with('OCA\Files_Sharing\External\Storage')
+ ->willReturn(false);
+ $path->method('getStorage')->willReturn($storage);
+ $userFolder->expects($this->once())
+ ->method('get')
+ ->with('valid-path')
+ ->willReturn($path);
+
+ $path->expects($this->once())
+ ->method('lock')
+ ->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
+
+ $this->appManager->method('isEnabledForUser')
+ ->with('spreed')
+ ->willReturn(true);
+
+ $helper = $this->getMockBuilder('\OCA\Spreed\Share\Helper\ShareAPIController')
+ ->setMethods(array('createShare'))
+ ->getMock();
+ $helper->method('createShare')
+ ->with(
+ $share,
+ 'recipientRoom',
+ \OCP\Constants::PERMISSION_ALL &
+ ~\OCP\Constants::PERMISSION_DELETE &
+ ~\OCP\Constants::PERMISSION_CREATE,
+ ''
+ )->will($this->returnCallback(
+ function ($share) {
+ throw new OCSNotFoundException("Exception thrown by the helper");
+ }
+ ));
+
+ $this->serverContainer->method('query')
+ ->with('\OCA\Spreed\Share\Helper\ShareAPIController')
+ ->willReturn($helper);
+
+ $this->shareManager->expects($this->never())->method('createShare');
+
+ $ocs->createShare('valid-path', \OCP\Constants::PERMISSION_ALL, \OCP\Share::SHARE_TYPE_ROOM, 'recipientRoom');
+ }
+
/**
* Test for https://github.com/owncloud/core/issues/22587
* TODO: Remove once proper solution is in place
@@ -1149,7 +1398,8 @@ class ShareAPIControllerTest extends TestCase {
$this->currentUser,
$this->l,
$this->config,
- $this->appManager
+ $this->appManager,
+ $this->serverContainer
])->setMethods(['formatShare'])
->getMock();
@@ -1681,7 +1931,8 @@ class ShareAPIControllerTest extends TestCase {
->method('getSharedWith')
->will($this->returnValueMap([
['currentUser', \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0, []],
- ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]]
+ ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]],
+ ['currentUser', \OCP\Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0, []]
]));
$this->shareManager->expects($this->never())->method('updateShare');
@@ -1726,7 +1977,8 @@ class ShareAPIControllerTest extends TestCase {
->method('getSharedWith')
->will($this->returnValueMap([
['currentUser', \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0, [$incomingShare]],
- ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, []]
+ ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, []],
+ ['currentUser', \OCP\Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0, []]
]));
$this->shareManager->expects($this->never())->method('updateShare');
@@ -1740,6 +1992,69 @@ class ShareAPIControllerTest extends TestCase {
}
}
+ public function testUpdateShareCannotIncreasePermissionsRoomShare() {
+ $ocs = $this->mockFormatShare();
+
+ $folder = $this->createMock(Folder::class);
+
+ $share = \OC::$server->getShareManager()->newShare();
+ $share
+ ->setId(42)
+ ->setSharedBy($this->currentUser)
+ ->setShareOwner('anotheruser')
+ ->setShareType(\OCP\Share::SHARE_TYPE_ROOM)
+ ->setSharedWith('group1')
+ ->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setNode($folder);
+
+ // note: updateShare will modify the received instance but getSharedWith will reread from the database,
+ // so their values will be different
+ $incomingShare = \OC::$server->getShareManager()->newShare();
+ $incomingShare
+ ->setId(42)
+ ->setSharedBy($this->currentUser)
+ ->setShareOwner('anotheruser')
+ ->setShareType(\OCP\Share::SHARE_TYPE_ROOM)
+ ->setSharedWith('group1')
+ ->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setNode($folder);
+
+ $this->request
+ ->method('getParam')
+ ->will($this->returnValueMap([
+ ['permissions', null, '31'],
+ ]));
+
+ $this->shareManager
+ ->method('getShareById')
+ ->will($this->returnCallback(
+ function ($id) use ($share) {
+ if ($id !== 'ocRoomShare:42') {
+ throw new \OCP\Share\Exceptions\ShareNotFound();
+ }
+
+ return $share;
+ }
+ ));
+
+ $this->shareManager->expects($this->any())
+ ->method('getSharedWith')
+ ->will($this->returnValueMap([
+ ['currentUser', \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0, []],
+ ['currentUser', \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0, []],
+ ['currentUser', \OCP\Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0, [$incomingShare]]
+ ]));
+
+ $this->shareManager->expects($this->never())->method('updateShare');
+
+ try {
+ $ocs->updateShare(42, 31);
+ $this->fail();
+ } catch (OCSNotFoundException $e) {
+ $this->assertEquals('Cannot increase permissions', $e->getMessage());
+ }
+ }
+
public function testUpdateShareCanIncreasePermissionsIfOwner() {
$ocs = $this->mockFormatShare();
@@ -2410,4 +2725,160 @@ class ShareAPIControllerTest extends TestCase {
$this->assertTrue($exception);
}
}
+
+ public function dataFormatRoomShare() {
+ $file = $this->getMockBuilder(File::class)->getMock();
+ $parent = $this->getMockBuilder(Folder::class)->getMock();
+
+ $file->method('getMimeType')->willReturn('myMimeType');
+
+ $file->method('getPath')->willReturn('file');
+
+ $parent->method('getId')->willReturn(1);
+ $file->method('getId')->willReturn(3);
+
+ $file->method('getParent')->willReturn($parent);
+
+ $cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock();
+ $cache->method('getNumericStorageId')->willReturn(100);
+ $storage = $this->getMockBuilder(Storage::class)->getMock();
+ $storage->method('getId')->willReturn('storageId');
+ $storage->method('getCache')->willReturn($cache);
+
+ $file->method('getStorage')->willReturn($storage);
+
+ $result = [];
+
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_ROOM)
+ ->setSharedWith('recipientRoom')
+ ->setSharedBy('initiator')
+ ->setShareOwner('owner')
+ ->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setNode($file)
+ ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
+ ->setTarget('myTarget')
+ ->setNote('personal note')
+ ->setId(42);
+
+ $result[] = [
+ [
+ 'id' => 42,
+ 'share_type' => \OCP\Share::SHARE_TYPE_ROOM,
+ 'uid_owner' => 'initiator',
+ 'displayname_owner' => 'initiator',
+ 'permissions' => 1,
+ 'stime' => 946684862,
+ 'parent' => null,
+ 'expiration' => null,
+ 'token' => null,
+ 'uid_file_owner' => 'owner',
+ 'displayname_file_owner' => 'owner',
+ 'note' => 'personal note',
+ 'path' => 'file',
+ 'item_type' => 'file',
+ 'storage_id' => 'storageId',
+ 'storage' => 100,
+ 'item_source' => 3,
+ 'file_source' => 3,
+ 'file_parent' => 1,
+ 'file_target' => 'myTarget',
+ 'share_with' => 'recipientRoom',
+ 'share_with_displayname' => '',
+ 'mail_send' => 0,
+ 'mimetype' => 'myMimeType',
+ ], $share, false, []
+ ];
+
+ $share = \OC::$server->getShareManager()->newShare();
+ $share->setShareType(\OCP\Share::SHARE_TYPE_ROOM)
+ ->setSharedWith('recipientRoom')
+ ->setSharedBy('initiator')
+ ->setShareOwner('owner')
+ ->setPermissions(\OCP\Constants::PERMISSION_READ)
+ ->setNode($file)
+ ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
+ ->setTarget('myTarget')
+ ->setNote('personal note')
+ ->setId(42);
+
+ $result[] = [
+ [
+ 'id' => 42,
+ 'share_type' => \OCP\Share::SHARE_TYPE_ROOM,
+ 'uid_owner' => 'initiator',
+ 'displayname_owner' => 'initiator',
+ 'permissions' => 1,
+ 'stime' => 946684862,
+ 'parent' => null,
+ 'expiration' => null,
+ 'token' => null,
+ 'uid_file_owner' => 'owner',
+ 'displayname_file_owner' => 'owner',
+ 'note' => 'personal note',
+ 'path' => 'file',
+ 'item_type' => 'file',
+ 'storage_id' => 'storageId',
+ 'storage' => 100,
+ 'item_source' => 3,
+ 'file_source' => 3,
+ 'file_parent' => 1,
+ 'file_target' => 'myTarget',
+ 'share_with' => 'recipientRoom',
+ 'share_with_displayname' => 'recipientRoomName',
+ 'mail_send' => 0,
+ 'mimetype' => 'myMimeType',
+ ], $share, true, [
+ 'share_with_displayname' => 'recipientRoomName'
+ ]
+ ];
+
+ return $result;
+ }
+
+ /**
+ * @dataProvider dataFormatRoomShare
+ *
+ * @param array $expects
+ * @param \OCP\Share\IShare $share
+ * @param bool $helperAvailable
+ * @param array $formatShareByHelper
+ */
+ public function testFormatRoomShare(array $expects, \OCP\Share\IShare $share, bool $helperAvailable, array $formatShareByHelper) {
+ $this->rootFolder->method('getUserFolder')
+ ->with($this->currentUser)
+ ->will($this->returnSelf());
+
+ $this->rootFolder->method('getById')
+ ->with($share->getNodeId())
+ ->willReturn([$share->getNode()]);
+
+ $this->rootFolder->method('getRelativePath')
+ ->with($share->getNode()->getPath())
+ ->will($this->returnArgument(0));
+
+ if (!$helperAvailable) {
+ $this->appManager->method('isEnabledForUser')
+ ->with('spreed')
+ ->willReturn(false);
+ } else {
+ $this->appManager->method('isEnabledForUser')
+ ->with('spreed')
+ ->willReturn(true);
+
+ $helper = $this->getMockBuilder('\OCA\Spreed\Share\Helper\ShareAPIController')
+ ->setMethods(array('formatShare'))
+ ->getMock();
+ $helper->method('formatShare')
+ ->with($share)
+ ->willReturn($formatShareByHelper);
+
+ $this->serverContainer->method('query')
+ ->with('\OCA\Spreed\Share\Helper\ShareAPIController')
+ ->willReturn($helper);
+ }
+
+ $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
+ $this->assertEquals($expects, $result);
+ }
}
diff --git a/apps/files_sharing/tests/MountProviderTest.php b/apps/files_sharing/tests/MountProviderTest.php
index b521e109cf9..7b533bf8106 100644
--- a/apps/files_sharing/tests/MountProviderTest.php
+++ b/apps/files_sharing/tests/MountProviderTest.php
@@ -114,6 +114,12 @@ class MountProviderTest extends \Test\TestCase {
$this->makeMockShare(4, 101, 'user2', '/share4', 31),
$this->makeMockShare(5, 100, 'user1', '/share4', 31),
];
+ $roomShares = [
+ $this->makeMockShare(6, 102, 'user2', '/share6', 0),
+ $this->makeMockShare(7, 102, 'user1', '/share6', 31),
+ $this->makeMockShare(8, 102, 'user2', '/share6', 31),
+ $this->makeMockShare(9, 102, 'user2', '/share6', 31),
+ ];
// tests regarding circles are made in the app itself.
$circleShares = [];
$this->user->expects($this->any())
@@ -131,15 +137,20 @@ class MountProviderTest extends \Test\TestCase {
->method('getSharedWith')
->with('user1', \OCP\Share::SHARE_TYPE_CIRCLE, null, -1)
->will($this->returnValue($circleShares));
+ $this->shareManager->expects($this->at(3))
+ ->method('getSharedWith')
+ ->with('user1', \OCP\Share::SHARE_TYPE_ROOM, null, -1)
+ ->will($this->returnValue($roomShares));
$this->shareManager->expects($this->any())
->method('newShare')
->will($this->returnCallback(function() use ($rootFolder, $userManager) {
return new \OC\Share20\Share($rootFolder, $userManager);
}));
$mounts = $this->provider->getMountsForUser($this->user, $this->loader);
- $this->assertCount(2, $mounts);
+ $this->assertCount(3, $mounts);
$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[0]);
$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[1]);
+ $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[2]);
$mountedShare1 = $mounts[0]->getShare();
$this->assertEquals('2', $mountedShare1->getId());
$this->assertEquals('user2', $mountedShare1->getShareOwner());
@@ -152,6 +163,12 @@ class MountProviderTest extends \Test\TestCase {
$this->assertEquals(101, $mountedShare2->getNodeId());
$this->assertEquals('/share4', $mountedShare2->getTarget());
$this->assertEquals(31, $mountedShare2->getPermissions());
+ $mountedShare3 = $mounts[2]->getShare();
+ $this->assertEquals('8', $mountedShare3->getId());
+ $this->assertEquals('user2', $mountedShare3->getShareOwner());
+ $this->assertEquals(102, $mountedShare3->getNodeId());
+ $this->assertEquals('/share6', $mountedShare3->getTarget());
+ $this->assertEquals(31, $mountedShare3->getPermissions());
}
public function mergeSharesDataProvider() {
@@ -316,6 +333,7 @@ class MountProviderTest extends \Test\TestCase {
// tests regarding circles are made in the app itself.
$circleShares = [];
+ $roomShares = [];
$this->shareManager->expects($this->at(0))
->method('getSharedWith')
->with('user1', \OCP\Share::SHARE_TYPE_USER)
@@ -328,6 +346,10 @@ class MountProviderTest extends \Test\TestCase {
->method('getSharedWith')
->with('user1', \OCP\Share::SHARE_TYPE_CIRCLE, null, -1)
->will($this->returnValue($circleShares));
+ $this->shareManager->expects($this->at(3))
+ ->method('getSharedWith')
+ ->with('user1', \OCP\Share::SHARE_TYPE_ROOM, null, -1)
+ ->will($this->returnValue($roomShares));
$this->shareManager->expects($this->any())
->method('newShare')
->will($this->returnCallback(function() use ($rootFolder, $userManager) {
diff --git a/apps/files_sharing/tests/js/shareSpec.js b/apps/files_sharing/tests/js/shareSpec.js
index 91060f6a735..554a3a82b34 100644
--- a/apps/files_sharing/tests/js/shareSpec.js
+++ b/apps/files_sharing/tests/js/shareSpec.js
@@ -108,6 +108,26 @@ describe('OCA.Sharing.Util tests', function() {
expect($action.find('.icon').hasClass('icon-public')).toEqual(false);
expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg');
});
+ it('shows simple share text with share icon when shared to a room', function() {
+ var $action, $tr;
+ fileList.setFiles([{
+ id: 1,
+ type: 'dir',
+ name: 'One',
+ path: '/subdir',
+ mimetype: 'text/plain',
+ size: 12,
+ permissions: OC.PERMISSION_ALL,
+ etag: 'abc',
+ shareTypes: [OC.Share.SHARE_TYPE_ROOM]
+ }]);
+ $tr = fileList.$el.find('tbody tr:first');
+ $action = $tr.find('.action-share');
+ expect($action.find('>span').text().trim()).toEqual('Shared');
+ expect($action.find('.icon').hasClass('icon-shared')).toEqual(true);
+ expect($action.find('.icon').hasClass('icon-public')).toEqual(false);
+ expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg');
+ });
it('shows simple share text with public icon when shared with link', function() {
var $action, $tr;
OC.Share.statuses = {1: {link: true, path: '/subdir'}};
diff --git a/apps/workflowengine/js/requestuseragentplugin.js b/apps/workflowengine/js/requestuseragentplugin.js
index 973f66cba31..881ea4b8ac7 100644
--- a/apps/workflowengine/js/requestuseragentplugin.js
+++ b/apps/workflowengine/js/requestuseragentplugin.js
@@ -44,7 +44,7 @@
var placeholder = 'Mozilla/5.0 User Agent';
- if (check['operator'] === 'matches' || check['operator'] === '!matches') {
+ if (check.operator === 'matches' || check.operator === '!matches') {
placeholder = '/^Mozilla\\/5\\.0 (.*)$/i';
}
@@ -56,8 +56,8 @@
placement: 'bottom'
});
- if (check['operator'] === 'matches' || check['operator'] === '!matches') {
- if (this._validateRegex(check['value'])) {
+ if (check.operator === 'matches' || check.operator === '!matches') {
+ if (this._validateRegex(check.value)) {
$(element).removeClass('invalid-input');
} else {
$(element).addClass('invalid-input');
@@ -70,21 +70,22 @@
children: [
{id: 'android', text: t('workflowengine', 'Android client')},
{id: 'ios', text: t('workflowengine', 'iOS client')},
- {id: 'desktop', text: t('workflowengine', 'Desktop client')}
+ {id: 'desktop', text: t('workflowengine', 'Desktop client')},
+ {id: 'mail', text: t('workflowengine', 'Thunderbird & Outlook addons')}
]
}
];
- if (this.predefinedValues.indexOf(check['value']) === -1) {
+ if (this.predefinedValues.indexOf(check.value) === -1) {
data.unshift({
- id: check['value'],
- text: check['value']
- })
+ id: check.value,
+ text: check.value
+ });
}
$(element).select2({
data: data,
createSearchChoice: function(term) {
- if (self.predefinedValues.indexOf(check['value']) === -1) {
+ if (self.predefinedValues.indexOf(check.value) === -1) {
return {
id: term,
text: term
diff --git a/build/integration/features/bootstrap/Provisioning.php b/build/integration/features/bootstrap/Provisioning.php
index 1a2c32ed8c6..c320be2be6c 100644
--- a/build/integration/features/bootstrap/Provisioning.php
+++ b/build/integration/features/bootstrap/Provisioning.php
@@ -680,6 +680,30 @@ trait Provisioning {
}
/**
+ * @Given /^app "([^"]*)" is not enabled$/
+ *
+ * Checks that the app is disabled or not installed.
+ *
+ * @param string $app
+ */
+ public function appIsNotEnabled($app) {
+ $fullUrl = $this->baseUrl . "v2.php/cloud/apps?filter=enabled";
+ $client = new Client();
+ $options = [];
+ if ($this->currentUser === 'admin') {
+ $options['auth'] = $this->adminUser;
+ }
+ $options['headers'] = [
+ 'OCS-APIREQUEST' => 'true',
+ ];
+
+ $this->response = $client->get($fullUrl, $options);
+ $respondedArray = $this->getArrayOfAppsResponded($this->response);
+ Assert::assertNotContains($app, $respondedArray);
+ Assert::assertEquals(200, $this->response->getStatusCode());
+ }
+
+ /**
* @Then /^user "([^"]*)" is disabled$/
* @param string $user
*/
diff --git a/build/integration/features/sharing-v1.feature b/build/integration/features/sharing-v1.feature
index 5708b7115e4..dd5cc9fff4f 100644
--- a/build/integration/features/sharing-v1.feature
+++ b/build/integration/features/sharing-v1.feature
@@ -43,6 +43,18 @@ Feature: sharing
Then the OCS status code should be "100"
And the HTTP status code should be "200"
+ Scenario: Creating a new room share when Talk is not enabled
+ Given As an "admin"
+ And app "spreed" is not enabled
+ And user "user0" exists
+ And As an "user0"
+ When creating a share with
+ | path | welcome.txt |
+ | shareWith | a-room-token |
+ | shareType | 10 |
+ Then the OCS status code should be "403"
+ And the HTTP status code should be "401"
+
Scenario: Creating a new public share
Given user "user0" exists
And As an "user0"
diff --git a/core/img/actions/checkmark-white.svg b/core/img/actions/checkmark-white.svg
new file mode 100644
index 00000000000..6190902ea2d
--- /dev/null
+++ b/core/img/actions/checkmark-white.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16"><path d="m2.35 7.3 4 4l7.3-7.3" stroke="white" stroke-width="2" fill="none"/></svg>
diff --git a/core/img/actions/confirm-white.svg b/core/img/actions/confirm-white.svg
new file mode 100644
index 00000000000..98a41adefe5
--- /dev/null
+++ b/core/img/actions/confirm-white.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 16 16" width="16" version="1.1" height="16"><path fill="#fff" d="m8.5 0.5c-0.8974 0-1.3404 1.0909-0.6973 1.7168l4.7837 4.7832h-11.573c-1.3523-0.019125-1.3523 2.0191 0 2h11.572l-4.7832 4.7832c-0.98163 0.94251 0.47155 2.3957 1.4141 1.4141l6.4911-6.49c0.387-0.3878 0.391-1.0228 0-1.414l-6.4906-6.4903c-0.1883-0.1935-0.4468-0.30268-0.7168-0.3027z"/></svg>
diff --git a/core/img/actions/info-white.svg b/core/img/actions/info-white.svg
new file mode 100644
index 00000000000..92f6e44add2
--- /dev/null
+++ b/core/img/actions/info-white.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 16 16" width="16" height="16"><path d="M5 7.474c.155.382.325.69.644.246.407-.268 1.76-1.427 1.662-.342-.368 2.017-.834 4.017-1.17 6.04-.393 1.114.634 2.067 1.637 1.31 1.078-.502 1.99-1.287 2.927-2.01-.144-.323-.25-.79-.596-.347-.468.24-1.47 1.318-1.696.472.315-2.18.975-4.295 1.365-6.462.397-1.005-.364-2.223-1.4-1.363C7.117 5.634 6.083 6.6 5 7.474zM9.46.005C8.15-.017 7.553 2.147 8.815 2.68c1.023.378 2.077-.714 1.79-1.75-.098-.542-.598-.97-1.147-.93z" fill="#fff"/></svg>
diff --git a/core/js/share.js b/core/js/share.js
index e4d9364b2d1..cef05eb6479 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -12,6 +12,7 @@ OC.Share = _.extend(OC.Share || {}, {
SHARE_TYPE_CIRCLE:7,
SHARE_TYPE_GUEST:8,
SHARE_TYPE_REMOTE_GROUP:9,
+ SHARE_TYPE_ROOM:10,
/**
* Regular expression for splitting parts of remote share owners:
diff --git a/core/js/sharedialogresharerinfoview.js b/core/js/sharedialogresharerinfoview.js
index fadd0a41f7b..06e18fef3f2 100644
--- a/core/js/sharedialogresharerinfoview.js
+++ b/core/js/sharedialogresharerinfoview.js
@@ -99,6 +99,17 @@
undefined,
{escape: false}
);
+ } else if (this.model.getReshareType() === OC.Share.SHARE_TYPE_ROOM) {
+ sharedByText = t(
+ 'core',
+ 'Shared with you and the conversation {conversation} by {owner}',
+ {
+ conversation: this.model.getReshareWithDisplayName(),
+ owner: ownerDisplayName
+ },
+ undefined,
+ {escape: false}
+ );
} else {
sharedByText = t(
'core',
diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js
index 2ed46f46768..2627d5fa662 100644
--- a/core/js/sharedialogshareelistview.js
+++ b/core/js/sharedialogshareelistview.js
@@ -243,6 +243,8 @@
} else if (shareType === OC.Share.SHARE_TYPE_EMAIL) {
shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'email') + ')';
} else if (shareType === OC.Share.SHARE_TYPE_CIRCLE) {
+ } else if (shareType === OC.Share.SHARE_TYPE_ROOM) {
+ shareWithDisplayName = shareWithDisplayName + " (" + t('core', 'conversation') + ')';
}
if (shareType === OC.Share.SHARE_TYPE_GROUP) {
@@ -291,7 +293,7 @@
shareWithTitle: shareWithTitle,
shareType: shareType,
shareId: this.model.get('shares')[shareIndex].id,
- modSeed: shareType !== OC.Share.SHARE_TYPE_USER && (shareType !== OC.Share.SHARE_TYPE_CIRCLE || shareWithAvatar),
+ modSeed: shareWithAvatar || (shareType !== OC.Share.SHARE_TYPE_USER && shareType !== OC.Share.SHARE_TYPE_CIRCLE && shareType !== OC.Share.SHARE_TYPE_ROOM),
isRemoteShare: shareType === OC.Share.SHARE_TYPE_REMOTE,
isRemoteGroupShare: shareType === OC.Share.SHARE_TYPE_REMOTE_GROUP,
isNoteAvailable: shareType !== OC.Share.SHARE_TYPE_REMOTE && shareType !== OC.Share.SHARE_TYPE_REMOTE_GROUP,
diff --git a/lib/private/App/CodeChecker/CodeChecker.php b/lib/private/App/CodeChecker/CodeChecker.php
index 456a78aa122..d2f6d7451b4 100644
--- a/lib/private/App/CodeChecker/CodeChecker.php
+++ b/lib/private/App/CodeChecker/CodeChecker.php
@@ -82,7 +82,7 @@ class CodeChecker extends BasicEmitter {
public function analyseFolder(string $appId, string $folder): array {
$errors = [];
- $excludedDirectories = ['vendor', '3rdparty', '.git', 'l10n', 'tests', 'test'];
+ $excludedDirectories = ['vendor', '3rdparty', '.git', 'l10n', 'tests', 'test', 'build'];
if ($appId === 'password_policy') {
$excludedDirectories[] = 'lists';
}
diff --git a/lib/private/Files/Stream/Encryption.php b/lib/private/Files/Stream/Encryption.php
index 65d379c0289..3c884a99ae7 100644
--- a/lib/private/Files/Stream/Encryption.php
+++ b/lib/private/Files/Stream/Encryption.php
@@ -102,6 +102,9 @@ class Encryption extends Wrapper {
/** @var array */
protected $expectedContextProperties;
+ /** @var bool */
+ protected $fileUpdated;
+
public function __construct() {
$this->expectedContextProperties = array(
'source',
@@ -235,6 +238,7 @@ class Encryption extends Wrapper {
$this->position = 0;
$this->cache = '';
$this->writeFlag = false;
+ $this->fileUpdated = false;
$this->unencryptedBlockSize = $this->encryptionModule->getUnencryptedBlockSize($this->signed);
if (
@@ -313,7 +317,6 @@ class Encryption extends Wrapper {
}
public function stream_write($data) {
-
$length = 0;
// loop over $data to fit it in 6126 sized unencrypted blocks
while (isset($data[0])) {
@@ -333,6 +336,7 @@ class Encryption extends Wrapper {
// switch the writeFlag so flush() will write the block
$this->writeFlag = true;
+ $this->fileUpdated = true;
// determine the relative position in the current block
$blockPosition = ($this->position % $this->unencryptedBlockSize);
@@ -414,7 +418,18 @@ class Encryption extends Wrapper {
}
$this->encryptionStorage->updateUnencryptedSize($this->fullPath, $this->unencryptedSize);
}
- return parent::stream_close();
+ $result = parent::stream_close();
+
+ if ($this->fileUpdated) {
+ $cache = $this->storage->getCache();
+ $cacheEntry = $cache->get($this->internalPath);
+ if ($cacheEntry) {
+ $version = $cacheEntry['encryptedVersion'] + 1;
+ $cache->update($cacheEntry->getId(), ['encrypted' => $version, 'encryptedVersion' => $version]);
+ }
+ }
+
+ return $result;
}
/**
diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php
index 4eb79734c06..72dc5cd43be 100644
--- a/lib/private/Share/Constants.php
+++ b/lib/private/Share/Constants.php
@@ -31,6 +31,7 @@ class Constants {
const SHARE_TYPE_USER = 0;
const SHARE_TYPE_GROUP = 1;
+ // const SHARE_TYPE_USERGROUP = 2; // Internal type used by DefaultShareProvider
const SHARE_TYPE_LINK = 3;
const SHARE_TYPE_EMAIL = 4;
const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it
@@ -38,6 +39,8 @@ class Constants {
const SHARE_TYPE_CIRCLE = 7;
const SHARE_TYPE_GUEST = 8;
const SHARE_TYPE_REMOTE_GROUP = 9;
+ const SHARE_TYPE_ROOM = 10;
+ // const SHARE_TYPE_USERROOM = 11; // Internal type used by RoomShareProvider
const FORMAT_NONE = -1;
const FORMAT_STATUSES = -2;
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index d0316b44c1a..037ea53048a 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -239,6 +239,7 @@ class Manager implements IManager {
if ($circle === null) {
throw new \InvalidArgumentException('SharedWith is not a valid circle');
}
+ } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_ROOM) {
} else {
// We can't handle other types yet
throw new \InvalidArgumentException('unknown share type');
@@ -1247,6 +1248,15 @@ class Manager implements IManager {
}
}
+ if ($share === null && $this->shareProviderExists(\OCP\Share::SHARE_TYPE_ROOM)) {
+ try {
+ $provider = $this->factory->getProviderForType(\OCP\Share::SHARE_TYPE_ROOM);
+ $share = $provider->getShareByToken($token);
+ } catch (ProviderException $e) {
+ } catch (ShareNotFound $e) {
+ }
+ }
+
if ($share === null) {
throw new ShareNotFound($this->l->t('The requested share does not exist anymore'));
}
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index 0aacca409d1..6cb6c082df5 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -60,6 +60,8 @@ class ProviderFactory implements IProviderFactory {
private $shareByCircleProvider = null;
/** @var bool */
private $circlesAreNotAvailable = false;
+ /** @var \OCA\Spreed\Share\RoomShareProvider */
+ private $roomShareProvider = null;
/**
* IProviderFactory constructor.
@@ -221,6 +223,30 @@ class ProviderFactory implements IProviderFactory {
return $this->shareByCircleProvider;
}
+ /**
+ * Create the room share provider
+ *
+ * @return RoomShareProvider
+ */
+ protected function getRoomShareProvider() {
+ if ($this->roomShareProvider === null) {
+ /*
+ * Check if the app is enabled
+ */
+ $appManager = $this->serverContainer->getAppManager();
+ if (!$appManager->isEnabledForUser('spreed')) {
+ return null;
+ }
+
+ try {
+ $this->roomShareProvider = $this->serverContainer->query('\OCA\Spreed\Share\RoomShareProvider');
+ } catch (\OCP\AppFramework\QueryException $e) {
+ return null;
+ }
+ }
+
+ return $this->roomShareProvider;
+ }
/**
* @inheritdoc
@@ -235,6 +261,8 @@ class ProviderFactory implements IProviderFactory {
$provider = $this->getShareByMailProvider();
} else if ($id === 'ocCircleShare') {
$provider = $this->getShareByCircleProvider();
+ } else if ($id === 'ocRoomShare') {
+ $provider = $this->getRoomShareProvider();
}
if ($provider === null) {
@@ -261,6 +289,8 @@ class ProviderFactory implements IProviderFactory {
$provider = $this->getShareByMailProvider();
} else if ($shareType === \OCP\Share::SHARE_TYPE_CIRCLE) {
$provider = $this->getShareByCircleProvider();
+ } else if ($shareType === \OCP\Share::SHARE_TYPE_ROOM) {
+ $provider = $this->getRoomShareProvider();
}
@@ -281,6 +311,10 @@ class ProviderFactory implements IProviderFactory {
if ($shareByCircle !== null) {
$shares[] = $shareByCircle;
}
+ $roomShare = $this->getRoomShareProvider();
+ if ($roomShare !== null) {
+ $shares[] = $roomShare;
+ }
return $shares;
}
diff --git a/resources/app-info.xsd b/resources/app-info.xsd
index 4460b0f63b9..516d984674e 100644
--- a/resources/app-info.xsd
+++ b/resources/app-info.xsd
@@ -344,6 +344,7 @@
<xs:enumeration value="social"/>
<xs:enumeration value="tools"/>
<xs:enumeration value="games"/>
+ <xs:enumeration value="search"/>
</xs:restriction>
</xs:simpleType>
diff --git a/tests/lib/Files/Stream/EncryptionTest.php b/tests/lib/Files/Stream/EncryptionTest.php
index 983428ee51d..d7a5554acfd 100644
--- a/tests/lib/Files/Stream/EncryptionTest.php
+++ b/tests/lib/Files/Stream/EncryptionTest.php
@@ -2,8 +2,10 @@
namespace Test\Files\Stream;
+use OC\Files\Cache\CacheEntry;
use OC\Files\View;
use OC\Memcache\ArrayCache;
+use OCP\Files\Cache\ICache;
use OCP\IConfig;
class EncryptionTest extends \Test\TestCase {
@@ -26,6 +28,7 @@ class EncryptionTest extends \Test\TestCase {
$header = [];
$uid = '';
$this->encryptionModule = $this->buildMockModule();
+ $cache = $this->createMock(ICache::class);
$storage = $this->getMockBuilder('\OC\Files\Storage\Storage')
->disableOriginalConstructor()->getMock();
$encStorage = $this->getMockBuilder('\OC\Files\Storage\Wrapper\Encryption')
@@ -49,6 +52,13 @@ class EncryptionTest extends \Test\TestCase {
$util->expects($this->any())
->method('getUidAndFilename')
->willReturn(['user1', $internalPath]);
+ $storage->expects($this->any())->method('getCache')->willReturn($cache);
+ $entry = new CacheEntry([
+ 'fileid' => 5,
+ 'encryptedVersion' => 2,
+ ]);
+ $cache->expects($this->any())->method('get')->willReturn($entry );
+ $cache->expects($this->any())->method('update')->with(5, ['encrypted' => 3, 'encryptedVersion' => 3]);
return $wrapper::wrap($source, $internalPath,
@@ -208,6 +218,7 @@ class EncryptionTest extends \Test\TestCase {
public function testSeek() {
$fileName = tempnam("/tmp", "FOO");
+
$stream = $this->getStream($fileName, 'w+', 0);
$this->assertEquals(6, fwrite($stream, 'foobar'));
$this->assertEquals(0, fseek($stream, 3));
diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php
index 7106e22b264..1125cae9565 100644
--- a/tests/lib/Share20/ManagerTest.php
+++ b/tests/lib/Share20/ManagerTest.php
@@ -2165,6 +2165,56 @@ class ManagerTest extends \Test\TestCase {
$this->assertSame($share, $ret);
}
+ public function testGetShareByTokenRoom() {
+ $this->config
+ ->expects($this->once())
+ ->method('getAppValue')
+ ->with('core', 'shareapi_allow_links', 'yes')
+ ->willReturn('no');
+
+ $factory = $this->createMock(IProviderFactory::class);
+
+ $manager = new Manager(
+ $this->logger,
+ $this->config,
+ $this->secureRandom,
+ $this->hasher,
+ $this->mountManager,
+ $this->groupManager,
+ $this->l,
+ $this->l10nFactory,
+ $factory,
+ $this->userManager,
+ $this->rootFolder,
+ $this->eventDispatcher,
+ $this->mailer,
+ $this->urlGenerator,
+ $this->defaults
+ );
+
+ $share = $this->createMock(IShare::class);
+
+ $roomShareProvider = $this->createMock(IShareProvider::class);
+
+ $factory->expects($this->any())
+ ->method('getProviderForType')
+ ->will($this->returnCallback(function($shareType) use ($roomShareProvider) {
+ if ($shareType !== \OCP\Share::SHARE_TYPE_ROOM) {
+ throw new Exception\ProviderException();
+ }
+
+ return $roomShareProvider;
+ }));
+
+ $roomShareProvider->expects($this->once())
+ ->method('getShareByToken')
+ ->with('token')
+ ->willReturn($share);
+
+ $ret = $manager->getShareByToken('token');
+ $this->assertSame($share, $ret);
+ }
+
public function testGetShareByTokenWithException() {
$this->config
->expects($this->once())
diff --git a/version.php b/version.php
index 38ed681b593..4146fb97ccd 100644
--- a/version.php
+++ b/version.php
@@ -29,10 +29,10 @@
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
-$OC_Version = array(14, 0, 0, 14);
+$OC_Version = array(14, 0, 0, 15);
// The human readable string
-$OC_VersionString = '14.0.0 Beta 2';
+$OC_VersionString = '14.0.0 Beta 3';
$OC_VersionCanBeUpgradedFrom = [
'nextcloud' => [