1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc. |
4
|
|
|
* |
5
|
|
|
* @author Joas Schilling <[email protected]> |
6
|
|
|
* @author Roeland Jago Douma <[email protected]> |
7
|
|
|
* @author Vincent Petry <[email protected]> |
8
|
|
|
* |
9
|
|
|
* @license AGPL-3.0 |
10
|
|
|
* |
11
|
|
|
* This code is free software: you can redistribute it and/or modify |
12
|
|
|
* it under the terms of the GNU Affero General Public License, version 3, |
13
|
|
|
* as published by the Free Software Foundation. |
14
|
|
|
* |
15
|
|
|
* This program is distributed in the hope that it will be useful, |
16
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
17
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18
|
|
|
* GNU Affero General Public License for more details. |
19
|
|
|
* |
20
|
|
|
* You should have received a copy of the GNU Affero General Public License, version 3, |
21
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/> |
22
|
|
|
* |
23
|
|
|
*/ |
24
|
|
|
namespace OCA\Files_Sharing\API; |
25
|
|
|
|
26
|
|
|
use OCP\Files\NotFoundException; |
27
|
|
|
use OCP\IGroupManager; |
28
|
|
|
use OCP\IL10N; |
29
|
|
|
use OCP\IUserManager; |
30
|
|
|
use OCP\IRequest; |
31
|
|
|
use OCP\IURLGenerator; |
32
|
|
|
use OCP\IUser; |
33
|
|
|
use OCP\Files\IRootFolder; |
34
|
|
|
use OCP\Lock\LockedException; |
35
|
|
|
use OCP\Share; |
36
|
|
|
use OCP\Share\IManager; |
37
|
|
|
use OCP\Share\Exceptions\ShareNotFound; |
38
|
|
|
use OCP\Share\Exceptions\GenericShareException; |
39
|
|
|
use OCP\Lock\ILockingProvider; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Class Share20OCS |
43
|
|
|
* |
44
|
|
|
* @package OCA\Files_Sharing\API |
45
|
|
|
*/ |
46
|
|
|
class Share20OCS { |
47
|
|
|
|
48
|
|
|
/** @var IManager */ |
49
|
|
|
private $shareManager; |
50
|
|
|
/** @var IGroupManager */ |
51
|
|
|
private $groupManager; |
52
|
|
|
/** @var IUserManager */ |
53
|
|
|
private $userManager; |
54
|
|
|
/** @var IRequest */ |
55
|
|
|
private $request; |
56
|
|
|
/** @var IRootFolder */ |
57
|
|
|
private $rootFolder; |
58
|
|
|
/** @var IURLGenerator */ |
59
|
|
|
private $urlGenerator; |
60
|
|
|
/** @var IUser */ |
61
|
|
|
private $currentUser; |
62
|
|
|
/** @var IL10N */ |
63
|
|
|
private $l; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Share20OCS constructor. |
67
|
|
|
* |
68
|
|
|
* @param IManager $shareManager |
69
|
|
|
* @param IGroupManager $groupManager |
70
|
|
|
* @param IUserManager $userManager |
71
|
|
|
* @param IRequest $request |
72
|
|
|
* @param IRootFolder $rootFolder |
73
|
|
|
* @param IURLGenerator $urlGenerator |
74
|
|
|
* @param IUser $currentUser |
75
|
|
|
*/ |
76
|
|
|
public function __construct( |
77
|
|
|
IManager $shareManager, |
78
|
|
|
IGroupManager $groupManager, |
79
|
|
|
IUserManager $userManager, |
80
|
|
|
IRequest $request, |
81
|
|
|
IRootFolder $rootFolder, |
82
|
|
|
IURLGenerator $urlGenerator, |
83
|
|
|
IUser $currentUser, |
84
|
|
|
IL10N $l10n |
85
|
|
|
) { |
86
|
|
|
$this->shareManager = $shareManager; |
87
|
|
|
$this->userManager = $userManager; |
88
|
|
|
$this->groupManager = $groupManager; |
89
|
|
|
$this->request = $request; |
90
|
|
|
$this->rootFolder = $rootFolder; |
91
|
|
|
$this->urlGenerator = $urlGenerator; |
92
|
|
|
$this->currentUser = $currentUser; |
93
|
|
|
$this->l = $l10n; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Convert an IShare to an array for OCS output |
98
|
|
|
* |
99
|
|
|
* @param \OCP\Share\IShare $share |
100
|
|
|
* @return array |
101
|
|
|
* @throws NotFoundException In case the node can't be resolved. |
102
|
|
|
*/ |
103
|
|
|
protected function formatShare(\OCP\Share\IShare $share) { |
104
|
|
|
$sharedBy = $this->userManager->get($share->getSharedBy()); |
105
|
|
|
$shareOwner = $this->userManager->get($share->getShareOwner()); |
106
|
|
|
|
107
|
|
|
$result = [ |
108
|
|
|
'id' => $share->getId(), |
109
|
|
|
'share_type' => $share->getShareType(), |
110
|
|
|
'uid_owner' => $share->getSharedBy(), |
111
|
|
|
'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(), |
112
|
|
|
'permissions' => $share->getPermissions(), |
113
|
|
|
'stime' => $share->getShareTime()->getTimestamp(), |
114
|
|
|
'parent' => null, |
115
|
|
|
'expiration' => null, |
116
|
|
|
'token' => null, |
117
|
|
|
'uid_file_owner' => $share->getShareOwner(), |
118
|
|
|
'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(), |
119
|
|
|
]; |
120
|
|
|
|
121
|
|
|
$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); |
122
|
|
|
$nodes = $userFolder->getById($share->getNodeId()); |
123
|
|
|
|
124
|
|
|
if (empty($nodes)) { |
125
|
|
|
throw new NotFoundException(); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
$node = $nodes[0]; |
129
|
|
|
|
130
|
|
|
$result['path'] = $userFolder->getRelativePath($node->getPath()); |
131
|
|
|
if ($node instanceOf \OCP\Files\Folder) { |
132
|
|
|
$result['item_type'] = 'folder'; |
133
|
|
|
} else { |
134
|
|
|
$result['item_type'] = 'file'; |
135
|
|
|
} |
136
|
|
|
$result['mimetype'] = $node->getMimeType(); |
137
|
|
|
$result['storage_id'] = $node->getStorage()->getId(); |
138
|
|
|
$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId(); |
139
|
|
|
$result['item_source'] = $node->getId(); |
140
|
|
|
$result['file_source'] = $node->getId(); |
141
|
|
|
$result['file_parent'] = $node->getParent()->getId(); |
142
|
|
|
$result['file_target'] = $share->getTarget(); |
143
|
|
|
|
144
|
|
|
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { |
145
|
|
|
$sharedWith = $this->userManager->get($share->getSharedWith()); |
146
|
|
|
$result['share_with'] = $share->getSharedWith(); |
147
|
|
|
$result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith(); |
148
|
|
|
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { |
149
|
|
|
$result['share_with'] = $share->getSharedWith(); |
150
|
|
|
$result['share_with_displayname'] = $share->getSharedWith(); |
151
|
|
|
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { |
152
|
|
|
|
153
|
|
|
$result['share_with'] = $share->getPassword(); |
154
|
|
|
$result['share_with_displayname'] = $share->getPassword(); |
155
|
|
|
|
156
|
|
|
$result['token'] = $share->getToken(); |
157
|
|
|
$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); |
158
|
|
|
|
159
|
|
|
$expiration = $share->getExpirationDate(); |
160
|
|
|
if ($expiration !== null) { |
161
|
|
|
$result['expiration'] = $expiration->format('Y-m-d 00:00:00'); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE) { |
165
|
|
|
$result['share_with'] = $share->getSharedWith(); |
166
|
|
|
$result['share_with_displayname'] = $share->getSharedWith(); |
167
|
|
|
$result['token'] = $share->getToken(); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
$result['mail_send'] = $share->getMailSend() ? 1 : 0; |
171
|
|
|
|
172
|
|
|
return $result; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Get a specific share by id |
177
|
|
|
* |
178
|
|
|
* @param string $id |
179
|
|
|
* @return \OC_OCS_Result |
180
|
|
|
*/ |
181
|
|
|
public function getShare($id) { |
182
|
|
|
if (!$this->shareManager->shareApiEnabled()) { |
183
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); |
|
|
|
|
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
try { |
187
|
|
|
$share = $this->getShareById($id); |
188
|
|
|
} catch (ShareNotFound $e) { |
189
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); |
|
|
|
|
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
if ($this->canAccessShare($share)) { |
193
|
|
|
try { |
194
|
|
|
$share = $this->formatShare($share); |
195
|
|
|
return new \OC_OCS_Result([$share]); |
|
|
|
|
196
|
|
|
} catch (NotFoundException $e) { |
197
|
|
|
//Fall trough |
198
|
|
|
} |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); |
|
|
|
|
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Delete a share |
206
|
|
|
* |
207
|
|
|
* @param string $id |
208
|
|
|
* @return \OC_OCS_Result |
209
|
|
|
*/ |
210
|
|
|
public function deleteShare($id) { |
211
|
|
|
if (!$this->shareManager->shareApiEnabled()) { |
212
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); |
|
|
|
|
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
try { |
216
|
|
|
$share = $this->getShareById($id); |
217
|
|
|
} catch (ShareNotFound $e) { |
218
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); |
|
|
|
|
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
try { |
222
|
|
|
$share->getNode()->lock(ILockingProvider::LOCK_SHARED); |
223
|
|
|
} catch (LockedException $e) { |
224
|
|
|
return new \OC_OCS_Result(null, 404, 'could not delete share'); |
|
|
|
|
225
|
|
|
} |
226
|
|
|
|
227
|
|
View Code Duplication |
if (!$this->canAccessShare($share, false)) { |
|
|
|
|
228
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
229
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Could not delete share')); |
|
|
|
|
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
$this->shareManager->deleteShare($share); |
233
|
|
|
|
234
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
235
|
|
|
|
236
|
|
|
return new \OC_OCS_Result(); |
|
|
|
|
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* @return \OC_OCS_Result |
241
|
|
|
*/ |
242
|
|
|
public function createShare() { |
243
|
|
|
$share = $this->shareManager->newShare(); |
244
|
|
|
|
245
|
|
|
if (!$this->shareManager->shareApiEnabled()) { |
246
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); |
|
|
|
|
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
// Verify path |
250
|
|
|
$path = $this->request->getParam('path', null); |
251
|
|
|
if ($path === null) { |
252
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a file or folder path')); |
|
|
|
|
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); |
256
|
|
|
try { |
257
|
|
|
$path = $userFolder->get($path); |
258
|
|
|
} catch (NotFoundException $e) { |
259
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist')); |
|
|
|
|
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
$share->setNode($path); |
263
|
|
|
|
264
|
|
|
try { |
265
|
|
|
$share->getNode()->lock(ILockingProvider::LOCK_SHARED); |
266
|
|
|
} catch (LockedException $e) { |
267
|
|
|
return new \OC_OCS_Result(null, 404, 'Could not create share'); |
|
|
|
|
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
// Parse permissions (if available) |
271
|
|
|
$permissions = $this->request->getParam('permissions', null); |
272
|
|
|
if ($permissions === null) { |
273
|
|
|
$permissions = \OCP\Constants::PERMISSION_ALL; |
274
|
|
|
} else { |
275
|
|
|
$permissions = (int)$permissions; |
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
if ($permissions < 0 || $permissions > \OCP\Constants::PERMISSION_ALL) { |
279
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
280
|
|
|
return new \OC_OCS_Result(null, 404, 'invalid permissions'); |
|
|
|
|
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
// Shares always require read permissions |
284
|
|
|
$permissions |= \OCP\Constants::PERMISSION_READ; |
285
|
|
|
|
286
|
|
|
if ($path instanceof \OCP\Files\File) { |
287
|
|
|
// Single file shares should never have delete or create permissions |
288
|
|
|
$permissions &= ~\OCP\Constants::PERMISSION_DELETE; |
289
|
|
|
$permissions &= ~\OCP\Constants::PERMISSION_CREATE; |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
/* |
293
|
|
|
* Hack for https://github.com/owncloud/core/issues/22587 |
294
|
|
|
* We check the permissions via webdav. But the permissions of the mount point |
295
|
|
|
* do not equal the share permissions. Here we fix that for federated mounts. |
296
|
|
|
*/ |
297
|
|
|
if ($path->getStorage()->instanceOfStorage('OCA\Files_Sharing\External\Storage')) { |
298
|
|
|
$permissions &= ~($permissions & ~$path->getPermissions()); |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
$shareWith = $this->request->getParam('shareWith', null); |
302
|
|
|
$shareType = (int)$this->request->getParam('shareType', '-1'); |
303
|
|
|
|
304
|
|
|
if ($shareType === \OCP\Share::SHARE_TYPE_USER) { |
305
|
|
|
// Valid user is required to share |
306
|
|
View Code Duplication |
if ($shareWith === null || !$this->userManager->userExists($shareWith)) { |
|
|
|
|
307
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
308
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid user')); |
|
|
|
|
309
|
|
|
} |
310
|
|
|
$share->setSharedWith($shareWith); |
311
|
|
|
$share->setPermissions($permissions); |
312
|
|
|
} else if ($shareType === \OCP\Share::SHARE_TYPE_GROUP) { |
313
|
|
View Code Duplication |
if (!$this->shareManager->allowGroupSharing()) { |
|
|
|
|
314
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
315
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Group sharing is disabled by the administrator')); |
|
|
|
|
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
// Valid group is required to share |
319
|
|
View Code Duplication |
if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) { |
|
|
|
|
320
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
321
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Please specify a valid group')); |
|
|
|
|
322
|
|
|
} |
323
|
|
|
$share->setSharedWith($shareWith); |
324
|
|
|
$share->setPermissions($permissions); |
325
|
|
|
} else if ($shareType === \OCP\Share::SHARE_TYPE_LINK) { |
326
|
|
|
//Can we even share links? |
327
|
|
View Code Duplication |
if (!$this->shareManager->shareApiAllowLinks()) { |
|
|
|
|
328
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
329
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Public link sharing is disabled by the administrator')); |
|
|
|
|
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/* |
333
|
|
|
* For now we only allow 1 link share. |
334
|
|
|
* Return the existing link share if this is a duplicate |
335
|
|
|
*/ |
336
|
|
|
$existingShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, false, 1, 0); |
337
|
|
|
if (!empty($existingShares)) { |
338
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
339
|
|
|
return new \OC_OCS_Result($this->formatShare($existingShares[0])); |
|
|
|
|
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
$publicUpload = $this->request->getParam('publicUpload', null); |
343
|
|
|
if ($publicUpload === 'true') { |
344
|
|
|
// Check if public upload is allowed |
345
|
|
View Code Duplication |
if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { |
|
|
|
|
346
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
347
|
|
|
return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); |
|
|
|
|
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
// Public upload can only be set for folders |
351
|
|
View Code Duplication |
if ($path instanceof \OCP\Files\File) { |
|
|
|
|
352
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
353
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Public upload is only possible for publicly shared folders')); |
|
|
|
|
354
|
|
|
} |
355
|
|
|
|
356
|
|
|
$share->setPermissions( |
357
|
|
|
\OCP\Constants::PERMISSION_READ | |
358
|
|
|
\OCP\Constants::PERMISSION_CREATE | |
359
|
|
|
\OCP\Constants::PERMISSION_UPDATE | |
360
|
|
|
\OCP\Constants::PERMISSION_DELETE |
361
|
|
|
); |
362
|
|
|
} else { |
363
|
|
|
$share->setPermissions(\OCP\Constants::PERMISSION_READ); |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
// Set password |
367
|
|
|
$password = $this->request->getParam('password', ''); |
368
|
|
|
|
369
|
|
|
if ($password !== '') { |
370
|
|
|
$share->setPassword($password); |
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
//Expire date |
374
|
|
|
$expireDate = $this->request->getParam('expireDate', ''); |
375
|
|
|
|
376
|
|
View Code Duplication |
if ($expireDate !== '') { |
|
|
|
|
377
|
|
|
try { |
378
|
|
|
$expireDate = $this->parseDate($expireDate); |
379
|
|
|
$share->setExpirationDate($expireDate); |
380
|
|
|
} catch (\Exception $e) { |
381
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
382
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Invalid date, date format must be YYYY-MM-DD')); |
|
|
|
|
383
|
|
|
} |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
} else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) { |
387
|
|
|
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { |
388
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
389
|
|
|
return new \OC_OCS_Result(null, 403, $this->l->t('Sharing %s failed because the back end does not allow shares from type %s', [$path->getPath(), $shareType])); |
|
|
|
|
390
|
|
|
} |
391
|
|
|
|
392
|
|
|
$share->setSharedWith($shareWith); |
393
|
|
|
$share->setPermissions($permissions); |
394
|
|
View Code Duplication |
} else { |
|
|
|
|
395
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
396
|
|
|
return new \OC_OCS_Result(null, 400, $this->l->t('Unknown share type')); |
|
|
|
|
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
$share->setShareType($shareType); |
400
|
|
|
$share->setSharedBy($this->currentUser->getUID()); |
401
|
|
|
|
402
|
|
|
try { |
403
|
|
|
$share = $this->shareManager->createShare($share); |
404
|
|
|
} catch (GenericShareException $e) { |
405
|
|
|
$code = $e->getCode() === 0 ? 403 : $e->getCode(); |
406
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
407
|
|
|
return new \OC_OCS_Result(null, $code, $e->getHint()); |
|
|
|
|
408
|
|
|
}catch (\Exception $e) { |
409
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
410
|
|
|
return new \OC_OCS_Result(null, 403, $e->getMessage()); |
|
|
|
|
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
$output = $this->formatShare($share); |
414
|
|
|
|
415
|
|
|
$share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); |
416
|
|
|
|
417
|
|
|
return new \OC_OCS_Result($output); |
|
|
|
|
418
|
|
|
} |
419
|
|
|
|
420
|
|
|
/** |
421
|
|
|
* @param \OCP\Files\File|\OCP\Files\Folder $node |
422
|
|
|
* @return \OC_OCS_Result |
423
|
|
|
*/ |
424
|
|
|
private function getSharedWithMe($node = null) { |
425
|
|
|
$userShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, -1, 0); |
426
|
|
|
$groupShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, -1, 0); |
427
|
|
|
|
428
|
|
|
$shares = array_merge($userShares, $groupShares); |
429
|
|
|
|
430
|
|
|
$formatted = []; |
431
|
|
|
foreach ($shares as $share) { |
432
|
|
|
if ($this->canAccessShare($share)) { |
433
|
|
|
try { |
434
|
|
|
$formatted[] = $this->formatShare($share); |
435
|
|
|
} catch (NotFoundException $e) { |
436
|
|
|
// Ignore this share |
437
|
|
|
} |
438
|
|
|
} |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
return new \OC_OCS_Result($formatted); |
|
|
|
|
442
|
|
|
} |
443
|
|
|
|
444
|
|
|
/** |
445
|
|
|
* @param \OCP\Files\Folder $folder |
446
|
|
|
* @return \OC_OCS_Result |
447
|
|
|
*/ |
448
|
|
|
private function getSharesInDir($folder) { |
449
|
|
|
if (!($folder instanceof \OCP\Files\Folder)) { |
450
|
|
|
return new \OC_OCS_Result(null, 400, $this->l->t('Not a directory')); |
|
|
|
|
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
$nodes = $folder->getDirectoryListing(); |
454
|
|
|
/** @var \OCP\Share\IShare[] $shares */ |
455
|
|
|
$shares = []; |
456
|
|
|
foreach ($nodes as $node) { |
457
|
|
|
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $node, false, -1, 0)); |
458
|
|
|
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $node, false, -1, 0)); |
459
|
|
|
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $node, false, -1, 0)); |
460
|
|
|
if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { |
461
|
|
|
$shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $node, false, -1, 0)); |
462
|
|
|
} |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
$formatted = []; |
466
|
|
|
foreach ($shares as $share) { |
467
|
|
|
try { |
468
|
|
|
$formatted[] = $this->formatShare($share); |
469
|
|
|
} catch (NotFoundException $e) { |
470
|
|
|
//Ignore this share |
471
|
|
|
} |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
return new \OC_OCS_Result($formatted); |
|
|
|
|
475
|
|
|
} |
476
|
|
|
|
477
|
|
|
/** |
478
|
|
|
* The getShares function. |
479
|
|
|
* |
480
|
|
|
* - Get shares by the current user |
481
|
|
|
* - Get shares by the current user and reshares (?reshares=true) |
482
|
|
|
* - Get shares with the current user (?shared_with_me=true) |
483
|
|
|
* - Get shares for a specific path (?path=...) |
484
|
|
|
* - Get all shares in a folder (?subfiles=true&path=..) |
485
|
|
|
* |
486
|
|
|
* @return \OC_OCS_Result |
487
|
|
|
*/ |
488
|
|
|
public function getShares() { |
489
|
|
|
if (!$this->shareManager->shareApiEnabled()) { |
490
|
|
|
return new \OC_OCS_Result(); |
|
|
|
|
491
|
|
|
} |
492
|
|
|
|
493
|
|
|
$sharedWithMe = $this->request->getParam('shared_with_me', null); |
494
|
|
|
$reshares = $this->request->getParam('reshares', null); |
495
|
|
|
$subfiles = $this->request->getParam('subfiles'); |
496
|
|
|
$path = $this->request->getParam('path', null); |
497
|
|
|
|
498
|
|
|
if ($path !== null) { |
499
|
|
|
$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); |
500
|
|
|
try { |
501
|
|
|
$path = $userFolder->get($path); |
502
|
|
|
$path->lock(ILockingProvider::LOCK_SHARED); |
503
|
|
|
} catch (\OCP\Files\NotFoundException $e) { |
504
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong path, file/folder doesn\'t exist')); |
|
|
|
|
505
|
|
|
} catch (LockedException $e) { |
506
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Could not lock path')); |
|
|
|
|
507
|
|
|
} |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
if ($sharedWithMe === 'true') { |
511
|
|
|
$result = $this->getSharedWithMe($path); |
|
|
|
|
512
|
|
|
if ($path !== null) { |
513
|
|
|
$path->unlock(ILockingProvider::LOCK_SHARED); |
514
|
|
|
} |
515
|
|
|
return $result; |
516
|
|
|
} |
517
|
|
|
|
518
|
|
|
if ($subfiles === 'true') { |
519
|
|
|
$result = $this->getSharesInDir($path); |
|
|
|
|
520
|
|
|
if ($path !== null) { |
521
|
|
|
$path->unlock(ILockingProvider::LOCK_SHARED); |
522
|
|
|
} |
523
|
|
|
return $result; |
524
|
|
|
} |
525
|
|
|
|
526
|
|
|
if ($reshares === 'true') { |
527
|
|
|
$reshares = true; |
528
|
|
|
} else { |
529
|
|
|
$reshares = false; |
530
|
|
|
} |
531
|
|
|
|
532
|
|
|
// Get all shares |
533
|
|
|
$userShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $path, $reshares, -1, 0); |
534
|
|
|
$groupShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0); |
535
|
|
|
$linkShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0); |
536
|
|
|
$shares = array_merge($userShares, $groupShares, $linkShares); |
537
|
|
|
|
538
|
|
|
if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { |
539
|
|
|
$federatedShares = $this->shareManager->getSharesBy($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0); |
540
|
|
|
$shares = array_merge($shares, $federatedShares); |
541
|
|
|
} |
542
|
|
|
|
543
|
|
|
$formatted = []; |
544
|
|
|
foreach ($shares as $share) { |
545
|
|
|
try { |
546
|
|
|
$formatted[] = $this->formatShare($share); |
547
|
|
|
} catch (NotFoundException $e) { |
548
|
|
|
//Ignore share |
549
|
|
|
} |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
if ($path !== null) { |
553
|
|
|
$path->unlock(ILockingProvider::LOCK_SHARED); |
554
|
|
|
} |
555
|
|
|
|
556
|
|
|
return new \OC_OCS_Result($formatted); |
|
|
|
|
557
|
|
|
} |
558
|
|
|
|
559
|
|
|
/** |
560
|
|
|
* @param int $id |
561
|
|
|
* @return \OC_OCS_Result |
562
|
|
|
*/ |
563
|
|
|
public function updateShare($id) { |
564
|
|
|
if (!$this->shareManager->shareApiEnabled()) { |
565
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Share API is disabled')); |
|
|
|
|
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
try { |
569
|
|
|
$share = $this->getShareById($id); |
570
|
|
|
} catch (ShareNotFound $e) { |
571
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); |
|
|
|
|
572
|
|
|
} |
573
|
|
|
|
574
|
|
|
$share->getNode()->lock(\OCP\Lock\ILockingProvider::LOCK_SHARED); |
575
|
|
|
|
576
|
|
View Code Duplication |
if (!$this->canAccessShare($share, false)) { |
|
|
|
|
577
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
578
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Wrong share ID, share doesn\'t exist')); |
|
|
|
|
579
|
|
|
} |
580
|
|
|
|
581
|
|
|
$permissions = $this->request->getParam('permissions', null); |
582
|
|
|
$password = $this->request->getParam('password', null); |
583
|
|
|
$publicUpload = $this->request->getParam('publicUpload', null); |
584
|
|
|
$expireDate = $this->request->getParam('expireDate', null); |
585
|
|
|
|
586
|
|
|
/* |
587
|
|
|
* expirationdate, password and publicUpload only make sense for link shares |
588
|
|
|
*/ |
589
|
|
|
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { |
590
|
|
|
if ($permissions === null && $password === null && $publicUpload === null && $expireDate === null) { |
591
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
592
|
|
|
return new \OC_OCS_Result(null, 400, 'Wrong or no update parameter given'); |
|
|
|
|
593
|
|
|
} |
594
|
|
|
|
595
|
|
|
$newPermissions = null; |
596
|
|
|
if ($publicUpload === 'true') { |
597
|
|
|
$newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; |
598
|
|
|
} else if ($publicUpload === 'false') { |
599
|
|
|
$newPermissions = \OCP\Constants::PERMISSION_READ; |
600
|
|
|
} |
601
|
|
|
|
602
|
|
|
if ($permissions !== null) { |
603
|
|
|
$newPermissions = (int)$permissions; |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
if ($newPermissions !== null && |
607
|
|
|
!in_array($newPermissions, [ |
608
|
|
|
\OCP\Constants::PERMISSION_READ, |
609
|
|
|
\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE, // legacy |
610
|
|
|
\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE, // correct |
611
|
|
|
\OCP\Constants::PERMISSION_CREATE, // hidden file list |
612
|
|
|
]) |
613
|
|
|
) { |
614
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
615
|
|
|
return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links')); |
|
|
|
|
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
if ( |
619
|
|
|
// legacy |
620
|
|
|
$newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) || |
621
|
|
|
// correct |
622
|
|
|
$newPermissions === (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE) |
623
|
|
|
) { |
624
|
|
View Code Duplication |
if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { |
|
|
|
|
625
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
626
|
|
|
return new \OC_OCS_Result(null, 403, $this->l->t('Public upload disabled by the administrator')); |
|
|
|
|
627
|
|
|
} |
628
|
|
|
|
629
|
|
View Code Duplication |
if (!($share->getNode() instanceof \OCP\Files\Folder)) { |
|
|
|
|
630
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
631
|
|
|
return new \OC_OCS_Result(null, 400, $this->l->t('Public upload is only possible for publicly shared folders')); |
|
|
|
|
632
|
|
|
} |
633
|
|
|
|
634
|
|
|
// normalize to correct public upload permissions |
635
|
|
|
$newPermissions = \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE; |
636
|
|
|
} |
637
|
|
|
|
638
|
|
|
if ($newPermissions !== null) { |
639
|
|
|
$share->setPermissions($newPermissions); |
640
|
|
|
} |
641
|
|
|
|
642
|
|
|
if ($expireDate === '') { |
643
|
|
|
$share->setExpirationDate(null); |
|
|
|
|
644
|
|
View Code Duplication |
} else if ($expireDate !== null) { |
|
|
|
|
645
|
|
|
try { |
646
|
|
|
$expireDate = $this->parseDate($expireDate); |
647
|
|
|
} catch (\Exception $e) { |
648
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
649
|
|
|
return new \OC_OCS_Result(null, 400, $e->getMessage()); |
|
|
|
|
650
|
|
|
} |
651
|
|
|
$share->setExpirationDate($expireDate); |
652
|
|
|
} |
653
|
|
|
|
654
|
|
|
if ($password === '') { |
655
|
|
|
$share->setPassword(null); |
656
|
|
|
} else if ($password !== null) { |
657
|
|
|
$share->setPassword($password); |
658
|
|
|
} |
659
|
|
|
|
660
|
|
|
} else { |
661
|
|
|
// For other shares only permissions is valid. |
662
|
|
|
if ($permissions === null) { |
663
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
664
|
|
|
return new \OC_OCS_Result(null, 400, $this->l->t('Wrong or no update parameter given')); |
|
|
|
|
665
|
|
|
} else { |
666
|
|
|
$permissions = (int)$permissions; |
667
|
|
|
$share->setPermissions($permissions); |
668
|
|
|
} |
669
|
|
|
} |
670
|
|
|
|
671
|
|
|
if ($permissions !== null) { |
672
|
|
|
/* Check if this is an incomming share */ |
673
|
|
|
$incomingShares = $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_USER, $share->getNode(), -1, 0); |
674
|
|
|
$incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser->getUID(), \OCP\Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0)); |
675
|
|
|
|
676
|
|
|
if (!empty($incomingShares)) { |
677
|
|
|
$maxPermissions = 0; |
678
|
|
|
foreach ($incomingShares as $incomingShare) { |
679
|
|
|
$maxPermissions |= $incomingShare->getPermissions(); |
680
|
|
|
} |
681
|
|
|
|
682
|
|
View Code Duplication |
if ($share->getPermissions() & ~$maxPermissions) { |
|
|
|
|
683
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
684
|
|
|
return new \OC_OCS_Result(null, 404, $this->l->t('Cannot increase permissions')); |
|
|
|
|
685
|
|
|
} |
686
|
|
|
} |
687
|
|
|
} |
688
|
|
|
|
689
|
|
|
|
690
|
|
|
try { |
691
|
|
|
$share = $this->shareManager->updateShare($share); |
692
|
|
|
} catch (\Exception $e) { |
693
|
|
|
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED); |
694
|
|
|
return new \OC_OCS_Result(null, 400, $e->getMessage()); |
|
|
|
|
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
$share->getNode()->unlock(\OCP\Lock\ILockingProvider::LOCK_SHARED); |
698
|
|
|
|
699
|
|
|
return new \OC_OCS_Result($this->formatShare($share)); |
|
|
|
|
700
|
|
|
} |
701
|
|
|
|
702
|
|
|
/** |
703
|
|
|
* @param \OCP\Share\IShare $share |
704
|
|
|
* @return bool |
705
|
|
|
*/ |
706
|
|
|
protected function canAccessShare(\OCP\Share\IShare $share, $checkGroups = true) { |
707
|
|
|
// A file with permissions 0 can't be accessed by us. So Don't show it |
708
|
|
|
if ($share->getPermissions() === 0) { |
709
|
|
|
return false; |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
// Owner of the file and the sharer of the file can always get share |
713
|
|
|
if ($share->getShareOwner() === $this->currentUser->getUID() || |
714
|
|
|
$share->getSharedBy() === $this->currentUser->getUID() |
715
|
|
|
) { |
716
|
|
|
return true; |
717
|
|
|
} |
718
|
|
|
|
719
|
|
|
// If the share is shared with you (or a group you are a member of) |
720
|
|
|
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER && |
721
|
|
|
$share->getSharedWith() === $this->currentUser->getUID()) { |
722
|
|
|
return true; |
723
|
|
|
} |
724
|
|
|
|
725
|
|
|
if ($checkGroups && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { |
726
|
|
|
$sharedWith = $this->groupManager->get($share->getSharedWith()); |
727
|
|
|
if ($sharedWith->inGroup($this->currentUser)) { |
728
|
|
|
return true; |
729
|
|
|
} |
730
|
|
|
} |
731
|
|
|
|
732
|
|
|
return false; |
733
|
|
|
} |
734
|
|
|
|
735
|
|
|
/** |
736
|
|
|
* Make sure that the passed date is valid ISO 8601 |
737
|
|
|
* So YYYY-MM-DD |
738
|
|
|
* If not throw an exception |
739
|
|
|
* |
740
|
|
|
* @param string $expireDate |
741
|
|
|
* |
742
|
|
|
* @throws \Exception |
743
|
|
|
* @return \DateTime |
744
|
|
|
*/ |
745
|
|
|
private function parseDate($expireDate) { |
746
|
|
|
try { |
747
|
|
|
$date = new \DateTime($expireDate); |
748
|
|
|
} catch (\Exception $e) { |
749
|
|
|
throw new \Exception('Invalid date. Format must be YYYY-MM-DD'); |
750
|
|
|
} |
751
|
|
|
|
752
|
|
|
if ($date === false) { |
753
|
|
|
throw new \Exception('Invalid date. Format must be YYYY-MM-DD'); |
754
|
|
|
} |
755
|
|
|
|
756
|
|
|
$date->setTime(0,0,0); |
757
|
|
|
|
758
|
|
|
return $date; |
759
|
|
|
} |
760
|
|
|
|
761
|
|
|
/** |
762
|
|
|
* Since we have multiple providers but the OCS Share API v1 does |
763
|
|
|
* not support this we need to check all backends. |
764
|
|
|
* |
765
|
|
|
* @param string $id |
766
|
|
|
* @return \OCP\Share\IShare |
767
|
|
|
* @throws ShareNotFound |
768
|
|
|
*/ |
769
|
|
|
private function getShareById($id) { |
770
|
|
|
$share = null; |
771
|
|
|
|
772
|
|
|
// First check if it is an internal share. |
773
|
|
|
try { |
774
|
|
|
$share = $this->shareManager->getShareById('ocinternal:'.$id); |
775
|
|
|
} catch (ShareNotFound $e) { |
776
|
|
|
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { |
777
|
|
|
throw new ShareNotFound(); |
778
|
|
|
} |
779
|
|
|
|
780
|
|
|
$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id); |
781
|
|
|
} |
782
|
|
|
|
783
|
|
|
return $share; |
784
|
|
|
} |
785
|
|
|
} |
786
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.