Completed
Pull Request — master (#9345)
by Björn
51:27 queued 26:41
created
lib/public/Federation/Exceptions/ActionNotSupportedException.php 1 patch
Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -32,17 +32,17 @@
 block discarded – undo
32 32
  */
33 33
 class ActionNotSupportedException extends HintException {
34 34
 
35
-	/**
36
-	 * ActionNotSupportedException constructor.
37
-	 *
38
-	 * @since 14.0.0
39
-	 *
40
-	 */
41
-	public function __construct($action) {
42
-		$l = \OC::$server->getL10N('federation');
43
-		$message = 'Action "' . $action . '" not supported or implemented.';
44
-		$hint = $l->t('Action "%s" not supported or implemented.', [$action]);
45
-		parent::__construct($message, $hint);
46
-	}
35
+    /**
36
+     * ActionNotSupportedException constructor.
37
+     *
38
+     * @since 14.0.0
39
+     *
40
+     */
41
+    public function __construct($action) {
42
+        $l = \OC::$server->getL10N('federation');
43
+        $message = 'Action "' . $action . '" not supported or implemented.';
44
+        $hint = $l->t('Action "%s" not supported or implemented.', [$action]);
45
+        parent::__construct($message, $hint);
46
+    }
47 47
 
48 48
 }
Please login to merge, or discard this patch.
lib/public/Federation/ICloudFederationFactory.php 1 patch
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -30,33 +30,33 @@
 block discarded – undo
30 30
  */
31 31
 interface ICloudFederationFactory {
32 32
 
33
-	/**
34
-	 * get a CloudFederationShare Object to prepare a share you want to send
35
-	 *
36
-	 * @param string $shareWith
37
-	 * @param string $name resource name (e.g. document.odt)
38
-	 * @param string $description share description (optional)
39
-	 * @param string $providerId resource UID on the provider side
40
-	 * @param string $owner provider specific UID of the user who owns the resource
41
-	 * @param string $ownerDisplayName display name of the user who shared the item
42
-	 * @param string $sharedBy provider specific UID of the user who shared the resource
43
-	 * @param string $sharedByDisplayName display name of the user who shared the resource
44
-	 * @param string $sharedSecret used to authenticate requests across servers
45
-	 * @param string $shareType ('group' or 'user' share)
46
-	 * @param $resourceType ('file', 'calendar',...)
47
-	 * @return ICloudFederationShare
48
-	 *
49
-	 * @since 14.0.0
50
-	 */
51
-	public function getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $sharedSecret, $shareType, $resourceType);
33
+    /**
34
+     * get a CloudFederationShare Object to prepare a share you want to send
35
+     *
36
+     * @param string $shareWith
37
+     * @param string $name resource name (e.g. document.odt)
38
+     * @param string $description share description (optional)
39
+     * @param string $providerId resource UID on the provider side
40
+     * @param string $owner provider specific UID of the user who owns the resource
41
+     * @param string $ownerDisplayName display name of the user who shared the item
42
+     * @param string $sharedBy provider specific UID of the user who shared the resource
43
+     * @param string $sharedByDisplayName display name of the user who shared the resource
44
+     * @param string $sharedSecret used to authenticate requests across servers
45
+     * @param string $shareType ('group' or 'user' share)
46
+     * @param $resourceType ('file', 'calendar',...)
47
+     * @return ICloudFederationShare
48
+     *
49
+     * @since 14.0.0
50
+     */
51
+    public function getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $sharedSecret, $shareType, $resourceType);
52 52
 
53
-	/**
54
-	 * get a Cloud FederationNotification object to prepare a notification you
55
-	 * want to send
56
-	 *
57
-	 * @return ICloudFederationNotification
58
-	 *
59
-	 * @since 14.0.0
60
-	 */
61
-	public function getCloudFederationNotification();
53
+    /**
54
+     * get a Cloud FederationNotification object to prepare a notification you
55
+     * want to send
56
+     *
57
+     * @return ICloudFederationNotification
58
+     *
59
+     * @since 14.0.0
60
+     */
61
+    public function getCloudFederationNotification();
62 62
 }
Please login to merge, or discard this patch.
lib/public/Federation/Exceptions/AuthenticationFailedException.php 1 patch
Indentation   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -32,17 +32,17 @@
 block discarded – undo
32 32
  */
33 33
 class AuthenticationFailedException extends HintException {
34 34
 
35
-	/**
36
-	 * BadRequestException constructor.
37
-	 *
38
-	 * @since 14.0.0
39
-	 *
40
-	 */
41
-	public function __construct() {
42
-		$l = \OC::$server->getL10N('federation');
43
-		$message = 'Authentication failed, wrong token or provider ID given';
44
-		$hint = $l->t('Authentication failed, wrong token or provider ID given');
45
-		parent::__construct($message, $hint);
46
-	}
35
+    /**
36
+     * BadRequestException constructor.
37
+     *
38
+     * @since 14.0.0
39
+     *
40
+     */
41
+    public function __construct() {
42
+        $l = \OC::$server->getL10N('federation');
43
+        $message = 'Authentication failed, wrong token or provider ID given';
44
+        $hint = $l->t('Authentication failed, wrong token or provider ID given');
45
+        parent::__construct($message, $hint);
46
+    }
47 47
 
48 48
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/Controller/RequestHandlerController.php 1 patch
Indentation   +427 added lines, -427 removed lines patch added patch discarded remove patch
@@ -52,431 +52,431 @@
 block discarded – undo
52 52
 
53 53
 class RequestHandlerController extends OCSController {
54 54
 
55
-	/** @var FederatedShareProvider */
56
-	private $federatedShareProvider;
57
-
58
-	/** @var IDBConnection */
59
-	private $connection;
60
-
61
-	/** @var Share\IManager */
62
-	private $shareManager;
63
-
64
-	/** @var Notifications */
65
-	private $notifications;
66
-
67
-	/** @var AddressHandler */
68
-	private $addressHandler;
69
-
70
-	/** @var  IUserManager */
71
-	private $userManager;
72
-
73
-	/** @var string */
74
-	private $shareTable = 'share';
75
-
76
-	/** @var ICloudIdManager */
77
-	private $cloudIdManager;
78
-
79
-	/** @var ILogger */
80
-	private $logger;
81
-
82
-	/** @var ICloudFederationFactory */
83
-	private $cloudFederationFactory;
84
-
85
-	/** @var ICloudFederationProviderManager */
86
-	private $cloudFederationProviderManager;
87
-
88
-	/**
89
-	 * Server2Server constructor.
90
-	 *
91
-	 * @param string $appName
92
-	 * @param IRequest $request
93
-	 * @param FederatedShareProvider $federatedShareProvider
94
-	 * @param IDBConnection $connection
95
-	 * @param Share\IManager $shareManager
96
-	 * @param Notifications $notifications
97
-	 * @param AddressHandler $addressHandler
98
-	 * @param IUserManager $userManager
99
-	 * @param ICloudIdManager $cloudIdManager
100
-	 * @param ILogger $logger
101
-	 * @param ICloudFederationFactory $cloudFederationFactory
102
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
103
-	 */
104
-	public function __construct($appName,
105
-								IRequest $request,
106
-								FederatedShareProvider $federatedShareProvider,
107
-								IDBConnection $connection,
108
-								Share\IManager $shareManager,
109
-								Notifications $notifications,
110
-								AddressHandler $addressHandler,
111
-								IUserManager $userManager,
112
-								ICloudIdManager $cloudIdManager,
113
-								ILogger $logger,
114
-								ICloudFederationFactory $cloudFederationFactory,
115
-								ICloudFederationProviderManager $cloudFederationProviderManager
116
-	) {
117
-		parent::__construct($appName, $request);
118
-
119
-		$this->federatedShareProvider = $federatedShareProvider;
120
-		$this->connection = $connection;
121
-		$this->shareManager = $shareManager;
122
-		$this->notifications = $notifications;
123
-		$this->addressHandler = $addressHandler;
124
-		$this->userManager = $userManager;
125
-		$this->cloudIdManager = $cloudIdManager;
126
-		$this->logger = $logger;
127
-		$this->cloudFederationFactory = $cloudFederationFactory;
128
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
129
-	}
130
-
131
-	/**
132
-	 * @NoCSRFRequired
133
-	 * @PublicPage
134
-	 *
135
-	 * create a new share
136
-	 *
137
-	 * @return Http\DataResponse
138
-	 * @throws OCSException
139
-	 */
140
-	public function createShare() {
141
-
142
-		$remote = isset($_POST['remote']) ? $_POST['remote'] : null;
143
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
144
-		$name = isset($_POST['name']) ? $_POST['name'] : null;
145
-		$owner = isset($_POST['owner']) ? $_POST['owner'] : null;
146
-		$sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null;
147
-		$shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
148
-		$remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
149
-		$sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null;
150
-		$ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null;
151
-
152
-		if ($ownerFederatedId === null) {
153
-			$ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId();
154
-		}
155
-		// if the owner of the share and the initiator are the same user
156
-		// we also complete the federated share ID for the initiator
157
-		if ($sharedByFederatedId === null && $owner === $sharedBy) {
158
-			$sharedByFederatedId = $ownerFederatedId;
159
-		}
160
-
161
-		$share = $this->cloudFederationFactory->getCloudFederationShare(
162
-			$shareWith,
163
-			$name,
164
-			'',
165
-			$remoteId,
166
-			$ownerFederatedId,
167
-			$owner,
168
-			$sharedByFederatedId,
169
-			$sharedBy,
170
-			$token,
171
-			'user',
172
-			'file'
173
-		);
174
-
175
-		try {
176
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
177
-			$provider->shareReceived($share);
178
-		} catch (ProviderDoesNotExistsException $e) {
179
-			throw new OCSException('Server does not support federated cloud sharing', 503);
180
-		} catch (ProviderCouldNotAddShareException $e) {
181
-			throw new OCSException($e->getMessage(), 400);
182
-		} catch (\Exception $e) {
183
-			throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
184
-		}
185
-
186
-		return new Http\DataResponse();
187
-	}
188
-
189
-	/**
190
-	 * @NoCSRFRequired
191
-	 * @PublicPage
192
-	 *
193
-	 * create re-share on behalf of another user
194
-	 *
195
-	 * @param int $id
196
-	 * @return Http\DataResponse
197
-	 * @throws OCSBadRequestException
198
-	 * @throws OCSException
199
-	 * @throws OCSForbiddenException
200
-	 */
201
-	public function reShare($id) {
202
-
203
-		$token = $this->request->getParam('token', null);
204
-		$shareWith = $this->request->getParam('shareWith', null);
205
-		$permission = (int)$this->request->getParam('permission', null);
206
-		$remoteId = (int)$this->request->getParam('remoteId', null);
207
-
208
-		if ($id === null ||
209
-			$token === null ||
210
-			$shareWith === null ||
211
-			$permission === null ||
212
-			$remoteId === null
213
-		) {
214
-			throw new OCSBadRequestException();
215
-		}
216
-
217
-		$notification = [
218
-			'sharedSecret' => $token,
219
-			'shareWith' => $shareWith,
220
-			'senderId' => $remoteId,
221
-			'message' => 'Recipient of a share ask the owner to reshare the file'
222
-		];
223
-
224
-		try {
225
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
226
-			list($newToken, $localId) = $provider->notificationReceived('REQUEST_RESHARE', $id, $notification);
227
-			return new Http\DataResponse([
228
-				'token' => $newToken,
229
-				'remoteId' => $localId
230
-			]);
231
-		} catch (ProviderDoesNotExistsException $e) {
232
-			throw new OCSException('Server does not support federated cloud sharing', 503);
233
-		} catch (ShareNotFound $e) {
234
-			$this->logger->debug('Share not found: ' . $e->getMessage());
235
-		} catch (\Exception $e) {
236
-			$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
237
-		}
238
-
239
-		throw new OCSBadRequestException();
240
-	}
241
-
242
-
243
-	/**
244
-	 * @NoCSRFRequired
245
-	 * @PublicPage
246
-	 *
247
-	 * accept server-to-server share
248
-	 *
249
-	 * @param int $id
250
-	 * @return Http\DataResponse
251
-	 * @throws OCSException
252
-	 * @throws ShareNotFound
253
-	 * @throws \OC\HintException
254
-	 */
255
-	public function acceptShare($id) {
256
-
257
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
258
-
259
-		$notification = [
260
-			'sharedSecret' => $token,
261
-			'message' => 'Recipient accept the share'
262
-		];
263
-
264
-		try {
265
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
266
-			$provider->notificationReceived('SHARE_ACCEPTED', $id, $notification);
267
-		} catch (ProviderDoesNotExistsException $e) {
268
-			throw new OCSException('Server does not support federated cloud sharing', 503);
269
-		} catch (ShareNotFound $e) {
270
-			$this->logger->debug('Share not found: ' . $e->getMessage());
271
-		} catch (\Exception $e) {
272
-			$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
273
-		}
274
-
275
-		return new Http\DataResponse();
276
-	}
277
-
278
-	/**
279
-	 * @NoCSRFRequired
280
-	 * @PublicPage
281
-	 *
282
-	 * decline server-to-server share
283
-	 *
284
-	 * @param int $id
285
-	 * @return Http\DataResponse
286
-	 * @throws OCSException
287
-	 */
288
-	public function declineShare($id) {
289
-
290
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
291
-
292
-		$notification = [
293
-			'sharedSecret' => $token,
294
-			'message' => 'Recipient declined the share'
295
-		];
296
-
297
-		try {
298
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
299
-			$provider->notificationReceived('SHARE_DECLINED', $id, $notification);
300
-		} catch (ProviderDoesNotExistsException $e) {
301
-			throw new OCSException('Server does not support federated cloud sharing', 503);
302
-		} catch (ShareNotFound $e) {
303
-			$this->logger->debug('Share not found: ' . $e->getMessage());
304
-		} catch (\Exception $e) {
305
-			$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
306
-		}
307
-
308
-		return new Http\DataResponse();
309
-	}
310
-
311
-	/**
312
-	 * @NoCSRFRequired
313
-	 * @PublicPage
314
-	 *
315
-	 * remove server-to-server share if it was unshared by the owner
316
-	 *
317
-	 * @param int $id
318
-	 * @return Http\DataResponse
319
-	 * @throws OCSException
320
-	 */
321
-	public function unshare($id) {
322
-
323
-		if (!$this->isS2SEnabled()) {
324
-			throw new OCSException('Server does not support federated cloud sharing', 503);
325
-		}
326
-
327
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
328
-
329
-		try {
330
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
331
-			$notification = ['sharedSecret' => $token];
332
-			$provider->notificationReceived('SHARE_UNSHARED', $id, $notification);
333
-		} catch (\Exception $e) {
334
-			$this->logger->debug('processing unshare notification failed: ' . $e->getMessage());
335
-		}
336
-
337
-		return new Http\DataResponse();
338
-	}
339
-
340
-	private function cleanupRemote($remote) {
341
-		$remote = substr($remote, strpos($remote, '://') + 3);
342
-
343
-		return rtrim($remote, '/');
344
-	}
345
-
346
-
347
-	/**
348
-	 * @NoCSRFRequired
349
-	 * @PublicPage
350
-	 *
351
-	 * federated share was revoked, either by the owner or the re-sharer
352
-	 *
353
-	 * @param int $id
354
-	 * @return Http\DataResponse
355
-	 * @throws OCSBadRequestException
356
-	 */
357
-	public function revoke($id) {
358
-
359
-		$token = $this->request->getParam('token');
360
-
361
-		try {
362
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
363
-			$notification = ['sharedSecret' => $token];
364
-			$provider->notificationReceived('RESHARE_UNDO', $id, $notification);
365
-			return new Http\DataResponse();
366
-		} catch (\Exception $e) {
367
-			throw new OCSBadRequestException();
368
-		}
369
-
370
-	}
371
-
372
-	/**
373
-	 * check if server-to-server sharing is enabled
374
-	 *
375
-	 * @param bool $incoming
376
-	 * @return bool
377
-	 */
378
-	private function isS2SEnabled($incoming = false) {
379
-
380
-		$result = \OCP\App::isEnabled('files_sharing');
381
-
382
-		if ($incoming) {
383
-			$result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
384
-		} else {
385
-			$result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
386
-		}
387
-
388
-		return $result;
389
-	}
390
-
391
-	/**
392
-	 * @NoCSRFRequired
393
-	 * @PublicPage
394
-	 *
395
-	 * update share information to keep federated re-shares in sync
396
-	 *
397
-	 * @param int $id
398
-	 * @return Http\DataResponse
399
-	 * @throws OCSBadRequestException
400
-	 */
401
-	public function updatePermissions($id) {
402
-		$token = $this->request->getParam('token', null);
403
-		$ncPermissions = $this->request->getParam('permissions', null);
404
-
405
-		try {
406
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
407
-			$ocmPermissions = $this->ncPermissions2ocmPermissions((int)$ncPermissions);
408
-			$notification = ['sharedSecret' => $token, 'permission' => $ocmPermissions];
409
-			$provider->notificationReceived('RESHARE_CHANGE_PERMISSION', $id, $notification);
410
-		} catch (\Exception $e) {
411
-			$this->logger->debug($e->getMessage());
412
-			throw new OCSBadRequestException();
413
-		}
414
-
415
-		return new Http\DataResponse();
416
-	}
417
-
418
-	/**
419
-	 * translate Nextcloud permissions to OCM Permissions
420
-	 *
421
-	 * @param $ncPermissions
422
-	 * @return array
423
-	 */
424
-	protected function ncPermissions2ocmPermissions($ncPermissions) {
425
-
426
-		$ocmPermissions = [];
427
-
428
-		if ($ncPermissions & Constants::PERMISSION_SHARE) {
429
-			$ocmPermissions[] = 'share';
430
-		}
431
-
432
-		if ($ncPermissions & Constants::PERMISSION_READ) {
433
-			$ocmPermissions[] = 'read';
434
-		}
435
-
436
-		if (($ncPermissions & Constants::PERMISSION_CREATE) ||
437
-			($ncPermissions & Constants::PERMISSION_UPDATE)) {
438
-			$ocmPermissions[] = 'write';
439
-		}
440
-
441
-		return $ocmPermissions;
442
-
443
-	}
444
-
445
-	/**
446
-	 * @NoCSRFRequired
447
-	 * @PublicPage
448
-	 *
449
-	 * change the owner of a server-to-server share
450
-	 *
451
-	 * @param int $id
452
-	 * @return Http\DataResponse
453
-	 * @throws \InvalidArgumentException
454
-	 * @throws OCSException
455
-	 */
456
-	public function move($id) {
457
-
458
-		if (!$this->isS2SEnabled()) {
459
-			throw new OCSException('Server does not support federated cloud sharing', 503);
460
-		}
461
-
462
-		$token = $this->request->getParam('token');
463
-		$remote = $this->request->getParam('remote');
464
-		$newRemoteId = $this->request->getParam('remote_id', $id);
465
-		$cloudId = $this->cloudIdManager->resolveCloudId($remote);
466
-
467
-		$qb = $this->connection->getQueryBuilder();
468
-		$query = $qb->update('share_external')
469
-			->set('remote', $qb->createNamedParameter($cloudId->getRemote()))
470
-			->set('owner', $qb->createNamedParameter($cloudId->getUser()))
471
-			->set('remote_id', $qb->createNamedParameter($newRemoteId))
472
-			->where($qb->expr()->eq('remote_id', $qb->createNamedParameter($id)))
473
-			->andWhere($qb->expr()->eq('share_token', $qb->createNamedParameter($token)));
474
-		$affected = $query->execute();
475
-
476
-		if ($affected > 0) {
477
-			return new Http\DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]);
478
-		} else {
479
-			throw new OCSBadRequestException('Share not found or token invalid');
480
-		}
481
-	}
55
+    /** @var FederatedShareProvider */
56
+    private $federatedShareProvider;
57
+
58
+    /** @var IDBConnection */
59
+    private $connection;
60
+
61
+    /** @var Share\IManager */
62
+    private $shareManager;
63
+
64
+    /** @var Notifications */
65
+    private $notifications;
66
+
67
+    /** @var AddressHandler */
68
+    private $addressHandler;
69
+
70
+    /** @var  IUserManager */
71
+    private $userManager;
72
+
73
+    /** @var string */
74
+    private $shareTable = 'share';
75
+
76
+    /** @var ICloudIdManager */
77
+    private $cloudIdManager;
78
+
79
+    /** @var ILogger */
80
+    private $logger;
81
+
82
+    /** @var ICloudFederationFactory */
83
+    private $cloudFederationFactory;
84
+
85
+    /** @var ICloudFederationProviderManager */
86
+    private $cloudFederationProviderManager;
87
+
88
+    /**
89
+     * Server2Server constructor.
90
+     *
91
+     * @param string $appName
92
+     * @param IRequest $request
93
+     * @param FederatedShareProvider $federatedShareProvider
94
+     * @param IDBConnection $connection
95
+     * @param Share\IManager $shareManager
96
+     * @param Notifications $notifications
97
+     * @param AddressHandler $addressHandler
98
+     * @param IUserManager $userManager
99
+     * @param ICloudIdManager $cloudIdManager
100
+     * @param ILogger $logger
101
+     * @param ICloudFederationFactory $cloudFederationFactory
102
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
103
+     */
104
+    public function __construct($appName,
105
+                                IRequest $request,
106
+                                FederatedShareProvider $federatedShareProvider,
107
+                                IDBConnection $connection,
108
+                                Share\IManager $shareManager,
109
+                                Notifications $notifications,
110
+                                AddressHandler $addressHandler,
111
+                                IUserManager $userManager,
112
+                                ICloudIdManager $cloudIdManager,
113
+                                ILogger $logger,
114
+                                ICloudFederationFactory $cloudFederationFactory,
115
+                                ICloudFederationProviderManager $cloudFederationProviderManager
116
+    ) {
117
+        parent::__construct($appName, $request);
118
+
119
+        $this->federatedShareProvider = $federatedShareProvider;
120
+        $this->connection = $connection;
121
+        $this->shareManager = $shareManager;
122
+        $this->notifications = $notifications;
123
+        $this->addressHandler = $addressHandler;
124
+        $this->userManager = $userManager;
125
+        $this->cloudIdManager = $cloudIdManager;
126
+        $this->logger = $logger;
127
+        $this->cloudFederationFactory = $cloudFederationFactory;
128
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
129
+    }
130
+
131
+    /**
132
+     * @NoCSRFRequired
133
+     * @PublicPage
134
+     *
135
+     * create a new share
136
+     *
137
+     * @return Http\DataResponse
138
+     * @throws OCSException
139
+     */
140
+    public function createShare() {
141
+
142
+        $remote = isset($_POST['remote']) ? $_POST['remote'] : null;
143
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
144
+        $name = isset($_POST['name']) ? $_POST['name'] : null;
145
+        $owner = isset($_POST['owner']) ? $_POST['owner'] : null;
146
+        $sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null;
147
+        $shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
148
+        $remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
149
+        $sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null;
150
+        $ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null;
151
+
152
+        if ($ownerFederatedId === null) {
153
+            $ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId();
154
+        }
155
+        // if the owner of the share and the initiator are the same user
156
+        // we also complete the federated share ID for the initiator
157
+        if ($sharedByFederatedId === null && $owner === $sharedBy) {
158
+            $sharedByFederatedId = $ownerFederatedId;
159
+        }
160
+
161
+        $share = $this->cloudFederationFactory->getCloudFederationShare(
162
+            $shareWith,
163
+            $name,
164
+            '',
165
+            $remoteId,
166
+            $ownerFederatedId,
167
+            $owner,
168
+            $sharedByFederatedId,
169
+            $sharedBy,
170
+            $token,
171
+            'user',
172
+            'file'
173
+        );
174
+
175
+        try {
176
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
177
+            $provider->shareReceived($share);
178
+        } catch (ProviderDoesNotExistsException $e) {
179
+            throw new OCSException('Server does not support federated cloud sharing', 503);
180
+        } catch (ProviderCouldNotAddShareException $e) {
181
+            throw new OCSException($e->getMessage(), 400);
182
+        } catch (\Exception $e) {
183
+            throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
184
+        }
185
+
186
+        return new Http\DataResponse();
187
+    }
188
+
189
+    /**
190
+     * @NoCSRFRequired
191
+     * @PublicPage
192
+     *
193
+     * create re-share on behalf of another user
194
+     *
195
+     * @param int $id
196
+     * @return Http\DataResponse
197
+     * @throws OCSBadRequestException
198
+     * @throws OCSException
199
+     * @throws OCSForbiddenException
200
+     */
201
+    public function reShare($id) {
202
+
203
+        $token = $this->request->getParam('token', null);
204
+        $shareWith = $this->request->getParam('shareWith', null);
205
+        $permission = (int)$this->request->getParam('permission', null);
206
+        $remoteId = (int)$this->request->getParam('remoteId', null);
207
+
208
+        if ($id === null ||
209
+            $token === null ||
210
+            $shareWith === null ||
211
+            $permission === null ||
212
+            $remoteId === null
213
+        ) {
214
+            throw new OCSBadRequestException();
215
+        }
216
+
217
+        $notification = [
218
+            'sharedSecret' => $token,
219
+            'shareWith' => $shareWith,
220
+            'senderId' => $remoteId,
221
+            'message' => 'Recipient of a share ask the owner to reshare the file'
222
+        ];
223
+
224
+        try {
225
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
226
+            list($newToken, $localId) = $provider->notificationReceived('REQUEST_RESHARE', $id, $notification);
227
+            return new Http\DataResponse([
228
+                'token' => $newToken,
229
+                'remoteId' => $localId
230
+            ]);
231
+        } catch (ProviderDoesNotExistsException $e) {
232
+            throw new OCSException('Server does not support federated cloud sharing', 503);
233
+        } catch (ShareNotFound $e) {
234
+            $this->logger->debug('Share not found: ' . $e->getMessage());
235
+        } catch (\Exception $e) {
236
+            $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
237
+        }
238
+
239
+        throw new OCSBadRequestException();
240
+    }
241
+
242
+
243
+    /**
244
+     * @NoCSRFRequired
245
+     * @PublicPage
246
+     *
247
+     * accept server-to-server share
248
+     *
249
+     * @param int $id
250
+     * @return Http\DataResponse
251
+     * @throws OCSException
252
+     * @throws ShareNotFound
253
+     * @throws \OC\HintException
254
+     */
255
+    public function acceptShare($id) {
256
+
257
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
258
+
259
+        $notification = [
260
+            'sharedSecret' => $token,
261
+            'message' => 'Recipient accept the share'
262
+        ];
263
+
264
+        try {
265
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
266
+            $provider->notificationReceived('SHARE_ACCEPTED', $id, $notification);
267
+        } catch (ProviderDoesNotExistsException $e) {
268
+            throw new OCSException('Server does not support federated cloud sharing', 503);
269
+        } catch (ShareNotFound $e) {
270
+            $this->logger->debug('Share not found: ' . $e->getMessage());
271
+        } catch (\Exception $e) {
272
+            $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
273
+        }
274
+
275
+        return new Http\DataResponse();
276
+    }
277
+
278
+    /**
279
+     * @NoCSRFRequired
280
+     * @PublicPage
281
+     *
282
+     * decline server-to-server share
283
+     *
284
+     * @param int $id
285
+     * @return Http\DataResponse
286
+     * @throws OCSException
287
+     */
288
+    public function declineShare($id) {
289
+
290
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
291
+
292
+        $notification = [
293
+            'sharedSecret' => $token,
294
+            'message' => 'Recipient declined the share'
295
+        ];
296
+
297
+        try {
298
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
299
+            $provider->notificationReceived('SHARE_DECLINED', $id, $notification);
300
+        } catch (ProviderDoesNotExistsException $e) {
301
+            throw new OCSException('Server does not support federated cloud sharing', 503);
302
+        } catch (ShareNotFound $e) {
303
+            $this->logger->debug('Share not found: ' . $e->getMessage());
304
+        } catch (\Exception $e) {
305
+            $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
306
+        }
307
+
308
+        return new Http\DataResponse();
309
+    }
310
+
311
+    /**
312
+     * @NoCSRFRequired
313
+     * @PublicPage
314
+     *
315
+     * remove server-to-server share if it was unshared by the owner
316
+     *
317
+     * @param int $id
318
+     * @return Http\DataResponse
319
+     * @throws OCSException
320
+     */
321
+    public function unshare($id) {
322
+
323
+        if (!$this->isS2SEnabled()) {
324
+            throw new OCSException('Server does not support federated cloud sharing', 503);
325
+        }
326
+
327
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
328
+
329
+        try {
330
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
331
+            $notification = ['sharedSecret' => $token];
332
+            $provider->notificationReceived('SHARE_UNSHARED', $id, $notification);
333
+        } catch (\Exception $e) {
334
+            $this->logger->debug('processing unshare notification failed: ' . $e->getMessage());
335
+        }
336
+
337
+        return new Http\DataResponse();
338
+    }
339
+
340
+    private function cleanupRemote($remote) {
341
+        $remote = substr($remote, strpos($remote, '://') + 3);
342
+
343
+        return rtrim($remote, '/');
344
+    }
345
+
346
+
347
+    /**
348
+     * @NoCSRFRequired
349
+     * @PublicPage
350
+     *
351
+     * federated share was revoked, either by the owner or the re-sharer
352
+     *
353
+     * @param int $id
354
+     * @return Http\DataResponse
355
+     * @throws OCSBadRequestException
356
+     */
357
+    public function revoke($id) {
358
+
359
+        $token = $this->request->getParam('token');
360
+
361
+        try {
362
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
363
+            $notification = ['sharedSecret' => $token];
364
+            $provider->notificationReceived('RESHARE_UNDO', $id, $notification);
365
+            return new Http\DataResponse();
366
+        } catch (\Exception $e) {
367
+            throw new OCSBadRequestException();
368
+        }
369
+
370
+    }
371
+
372
+    /**
373
+     * check if server-to-server sharing is enabled
374
+     *
375
+     * @param bool $incoming
376
+     * @return bool
377
+     */
378
+    private function isS2SEnabled($incoming = false) {
379
+
380
+        $result = \OCP\App::isEnabled('files_sharing');
381
+
382
+        if ($incoming) {
383
+            $result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
384
+        } else {
385
+            $result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
386
+        }
387
+
388
+        return $result;
389
+    }
390
+
391
+    /**
392
+     * @NoCSRFRequired
393
+     * @PublicPage
394
+     *
395
+     * update share information to keep federated re-shares in sync
396
+     *
397
+     * @param int $id
398
+     * @return Http\DataResponse
399
+     * @throws OCSBadRequestException
400
+     */
401
+    public function updatePermissions($id) {
402
+        $token = $this->request->getParam('token', null);
403
+        $ncPermissions = $this->request->getParam('permissions', null);
404
+
405
+        try {
406
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
407
+            $ocmPermissions = $this->ncPermissions2ocmPermissions((int)$ncPermissions);
408
+            $notification = ['sharedSecret' => $token, 'permission' => $ocmPermissions];
409
+            $provider->notificationReceived('RESHARE_CHANGE_PERMISSION', $id, $notification);
410
+        } catch (\Exception $e) {
411
+            $this->logger->debug($e->getMessage());
412
+            throw new OCSBadRequestException();
413
+        }
414
+
415
+        return new Http\DataResponse();
416
+    }
417
+
418
+    /**
419
+     * translate Nextcloud permissions to OCM Permissions
420
+     *
421
+     * @param $ncPermissions
422
+     * @return array
423
+     */
424
+    protected function ncPermissions2ocmPermissions($ncPermissions) {
425
+
426
+        $ocmPermissions = [];
427
+
428
+        if ($ncPermissions & Constants::PERMISSION_SHARE) {
429
+            $ocmPermissions[] = 'share';
430
+        }
431
+
432
+        if ($ncPermissions & Constants::PERMISSION_READ) {
433
+            $ocmPermissions[] = 'read';
434
+        }
435
+
436
+        if (($ncPermissions & Constants::PERMISSION_CREATE) ||
437
+            ($ncPermissions & Constants::PERMISSION_UPDATE)) {
438
+            $ocmPermissions[] = 'write';
439
+        }
440
+
441
+        return $ocmPermissions;
442
+
443
+    }
444
+
445
+    /**
446
+     * @NoCSRFRequired
447
+     * @PublicPage
448
+     *
449
+     * change the owner of a server-to-server share
450
+     *
451
+     * @param int $id
452
+     * @return Http\DataResponse
453
+     * @throws \InvalidArgumentException
454
+     * @throws OCSException
455
+     */
456
+    public function move($id) {
457
+
458
+        if (!$this->isS2SEnabled()) {
459
+            throw new OCSException('Server does not support federated cloud sharing', 503);
460
+        }
461
+
462
+        $token = $this->request->getParam('token');
463
+        $remote = $this->request->getParam('remote');
464
+        $newRemoteId = $this->request->getParam('remote_id', $id);
465
+        $cloudId = $this->cloudIdManager->resolveCloudId($remote);
466
+
467
+        $qb = $this->connection->getQueryBuilder();
468
+        $query = $qb->update('share_external')
469
+            ->set('remote', $qb->createNamedParameter($cloudId->getRemote()))
470
+            ->set('owner', $qb->createNamedParameter($cloudId->getUser()))
471
+            ->set('remote_id', $qb->createNamedParameter($newRemoteId))
472
+            ->where($qb->expr()->eq('remote_id', $qb->createNamedParameter($id)))
473
+            ->andWhere($qb->expr()->eq('share_token', $qb->createNamedParameter($token)));
474
+        $affected = $query->execute();
475
+
476
+        if ($affected > 0) {
477
+            return new Http\DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]);
478
+        } else {
479
+            throw new OCSBadRequestException('Share not found or token invalid');
480
+        }
481
+    }
482 482
 }
Please login to merge, or discard this patch.
apps/cloud_federation_api/lib/Controller/RequestHandlerController.php 1 patch
Indentation   +195 added lines, -195 removed lines patch added patch discarded remove patch
@@ -51,225 +51,225 @@
 block discarded – undo
51 51
  */
52 52
 class RequestHandlerController extends Controller {
53 53
 
54
-	/** @var ILogger */
55
-	private $logger;
54
+    /** @var ILogger */
55
+    private $logger;
56 56
 
57
-	/** @var IUserManager */
58
-	private $userManager;
57
+    /** @var IUserManager */
58
+    private $userManager;
59 59
 
60
-	/** @var IURLGenerator */
61
-	private $urlGenerator;
60
+    /** @var IURLGenerator */
61
+    private $urlGenerator;
62 62
 
63
-	/** @var ICloudFederationProviderManager */
64
-	private $cloudFederationProviderManager;
63
+    /** @var ICloudFederationProviderManager */
64
+    private $cloudFederationProviderManager;
65 65
 
66
-	/** @var Config */
67
-	private $config;
66
+    /** @var Config */
67
+    private $config;
68 68
 
69
-	/** @var ICloudFederationFactory */
70
-	private $factory;
69
+    /** @var ICloudFederationFactory */
70
+    private $factory;
71 71
 
72
-	/** @var ICloudIdManager */
73
-	private $cloudIdManager;
72
+    /** @var ICloudIdManager */
73
+    private $cloudIdManager;
74 74
 
75
-	public function __construct($appName,
76
-								IRequest $request,
77
-								ILogger $logger,
78
-								IUserManager $userManager,
79
-								IURLGenerator $urlGenerator,
80
-								ICloudFederationProviderManager $cloudFederationProviderManager,
81
-								Config $config,
82
-								ICloudFederationFactory $factory,
83
-								ICloudIdManager $cloudIdManager
84
-	) {
85
-		parent::__construct($appName, $request);
75
+    public function __construct($appName,
76
+                                IRequest $request,
77
+                                ILogger $logger,
78
+                                IUserManager $userManager,
79
+                                IURLGenerator $urlGenerator,
80
+                                ICloudFederationProviderManager $cloudFederationProviderManager,
81
+                                Config $config,
82
+                                ICloudFederationFactory $factory,
83
+                                ICloudIdManager $cloudIdManager
84
+    ) {
85
+        parent::__construct($appName, $request);
86 86
 
87
-		$this->logger = $logger;
88
-		$this->userManager = $userManager;
89
-		$this->urlGenerator = $urlGenerator;
90
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
91
-		$this->config = $config;
92
-		$this->factory = $factory;
93
-		$this->cloudIdManager = $cloudIdManager;
94
-	}
87
+        $this->logger = $logger;
88
+        $this->userManager = $userManager;
89
+        $this->urlGenerator = $urlGenerator;
90
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
91
+        $this->config = $config;
92
+        $this->factory = $factory;
93
+        $this->cloudIdManager = $cloudIdManager;
94
+    }
95 95
 
96
-	/**
97
-	 * add share
98
-	 *
99
-	 * @NoCSRFRequired
100
-	 * @PublicPage
101
-	 * @BruteForceProtection(action=receiveFederatedShare)
102
-	 *
103
-	 * @param string $shareWith
104
-	 * @param string $name resource name (e.g. document.odt)
105
-	 * @param string $description share description (optional)
106
-	 * @param string $providerId resource UID on the provider side
107
-	 * @param string $owner provider specific UID of the user who owns the resource
108
-	 * @param string $ownerDisplayName display name of the user who shared the item
109
-	 * @param string $sharedBy provider specific UID of the user who shared the resource
110
-	 * @param string $sharedByDisplayName display name of the user who shared the resource
111
-	 * @param array $protocol (e,.g. ['name' => 'webdav', 'options' => ['username' => 'john', 'permissions' => 31]])
112
-	 * @param string $shareType ('group' or 'user' share)
113
-	 * @param $resourceType ('file', 'calendar',...)
114
-	 * @return Http\DataResponse|JSONResponse
115
-	 *
116
-	 * Example: curl -H "Content-Type: application/json" -X POST -d '{"shareWith":"admin1@serve1","name":"welcome server2.txt","description":"desc","providerId":"2","owner":"admin2@http://localhost/server2","ownerDisplayName":"admin2 display","shareType":"user","resourceType":"file","protocol":{"name":"webdav","options":{"sharedSecret":"secret","permissions":"webdav-property"}}}' http://localhost/server/index.php/ocm/shares
117
-	 */
118
-	public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) {
96
+    /**
97
+     * add share
98
+     *
99
+     * @NoCSRFRequired
100
+     * @PublicPage
101
+     * @BruteForceProtection(action=receiveFederatedShare)
102
+     *
103
+     * @param string $shareWith
104
+     * @param string $name resource name (e.g. document.odt)
105
+     * @param string $description share description (optional)
106
+     * @param string $providerId resource UID on the provider side
107
+     * @param string $owner provider specific UID of the user who owns the resource
108
+     * @param string $ownerDisplayName display name of the user who shared the item
109
+     * @param string $sharedBy provider specific UID of the user who shared the resource
110
+     * @param string $sharedByDisplayName display name of the user who shared the resource
111
+     * @param array $protocol (e,.g. ['name' => 'webdav', 'options' => ['username' => 'john', 'permissions' => 31]])
112
+     * @param string $shareType ('group' or 'user' share)
113
+     * @param $resourceType ('file', 'calendar',...)
114
+     * @return Http\DataResponse|JSONResponse
115
+     *
116
+     * Example: curl -H "Content-Type: application/json" -X POST -d '{"shareWith":"admin1@serve1","name":"welcome server2.txt","description":"desc","providerId":"2","owner":"admin2@http://localhost/server2","ownerDisplayName":"admin2 display","shareType":"user","resourceType":"file","protocol":{"name":"webdav","options":{"sharedSecret":"secret","permissions":"webdav-property"}}}' http://localhost/server/index.php/ocm/shares
117
+     */
118
+    public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) {
119 119
 
120
-		// check if all required parameters are set
121
-		if ($shareWith === null ||
122
-			$name === null ||
123
-			$providerId === null ||
124
-			$owner === null ||
125
-			$resourceType === null ||
126
-			$shareType === null ||
127
-			!is_array($protocol) ||
128
-			!isset($protocol['name']) ||
129
-			!isset ($protocol['options']) ||
130
-			!is_array($protocol['options']) ||
131
-			!isset($protocol['options']['sharedSecret'])
132
-		) {
133
-			return new JSONResponse(
134
-				['message' => 'Missing arguments'],
135
-				Http::STATUS_BAD_REQUEST
136
-			);
137
-		}
120
+        // check if all required parameters are set
121
+        if ($shareWith === null ||
122
+            $name === null ||
123
+            $providerId === null ||
124
+            $owner === null ||
125
+            $resourceType === null ||
126
+            $shareType === null ||
127
+            !is_array($protocol) ||
128
+            !isset($protocol['name']) ||
129
+            !isset ($protocol['options']) ||
130
+            !is_array($protocol['options']) ||
131
+            !isset($protocol['options']['sharedSecret'])
132
+        ) {
133
+            return new JSONResponse(
134
+                ['message' => 'Missing arguments'],
135
+                Http::STATUS_BAD_REQUEST
136
+            );
137
+        }
138 138
 
139
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
140
-		$shareWithLocalId = $cloudId->getUser();
141
-		$shareWith = $this->mapUid($shareWithLocalId);
139
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
140
+        $shareWithLocalId = $cloudId->getUser();
141
+        $shareWith = $this->mapUid($shareWithLocalId);
142 142
 
143
-		if (!$this->userManager->userExists($shareWith)) {
144
-			return new JSONResponse(
145
-				['message' => 'User "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()],
146
-				Http::STATUS_BAD_REQUEST
147
-			);
148
-		}
143
+        if (!$this->userManager->userExists($shareWith)) {
144
+            return new JSONResponse(
145
+                ['message' => 'User "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()],
146
+                Http::STATUS_BAD_REQUEST
147
+            );
148
+        }
149 149
 
150
-		// if no explicit display name is given, we use the uid as display name
151
-		$ownerDisplayName = $ownerDisplayName === null ? $owner : $ownerDisplayName;
152
-		$sharedByDisplayName = $sharedByDisplayName === null ? $sharedBy : $sharedByDisplayName;
150
+        // if no explicit display name is given, we use the uid as display name
151
+        $ownerDisplayName = $ownerDisplayName === null ? $owner : $ownerDisplayName;
152
+        $sharedByDisplayName = $sharedByDisplayName === null ? $sharedBy : $sharedByDisplayName;
153 153
 
154
-		// sharedBy* parameter is optional, if nothing is set we assume that it is the same user as the owner
155
-		if ($sharedBy === null) {
156
-			$sharedBy = $owner;
157
-			$sharedByDisplayName = $ownerDisplayName;
158
-		}
154
+        // sharedBy* parameter is optional, if nothing is set we assume that it is the same user as the owner
155
+        if ($sharedBy === null) {
156
+            $sharedBy = $owner;
157
+            $sharedByDisplayName = $ownerDisplayName;
158
+        }
159 159
 
160
-		try {
161
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
162
-			$share = $this->factory->getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, '', $shareType, $resourceType);
163
-			$share->setProtocol($protocol);
164
-			$id = $provider->shareReceived($share);
165
-		} catch (ProviderDoesNotExistsException $e) {
166
-			return new JSONResponse(
167
-				['message' => $e->getMessage()],
168
-				Http::STATUS_NOT_IMPLEMENTED
169
-			);
170
-		} catch (ProviderCouldNotAddShareException $e) {
171
-			return new JSONResponse(
172
-				['message' => $e->getMessage()],
173
-				$e->getCode()
174
-			);
175
-		} catch (\Exception $e) {
176
-			return new JSONResponse(
177
-				['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
178
-				Http::STATUS_BAD_REQUEST
179
-			);
180
-		}
160
+        try {
161
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
162
+            $share = $this->factory->getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, '', $shareType, $resourceType);
163
+            $share->setProtocol($protocol);
164
+            $id = $provider->shareReceived($share);
165
+        } catch (ProviderDoesNotExistsException $e) {
166
+            return new JSONResponse(
167
+                ['message' => $e->getMessage()],
168
+                Http::STATUS_NOT_IMPLEMENTED
169
+            );
170
+        } catch (ProviderCouldNotAddShareException $e) {
171
+            return new JSONResponse(
172
+                ['message' => $e->getMessage()],
173
+                $e->getCode()
174
+            );
175
+        } catch (\Exception $e) {
176
+            return new JSONResponse(
177
+                ['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
178
+                Http::STATUS_BAD_REQUEST
179
+            );
180
+        }
181 181
 
182
-		$user = $this->userManager->get($shareWithLocalId);
183
-		$recipientDisplayName = '';
184
-		if($user) {
185
-			$recipientDisplayName = $user->getDisplayName();
186
-		}
182
+        $user = $this->userManager->get($shareWithLocalId);
183
+        $recipientDisplayName = '';
184
+        if($user) {
185
+            $recipientDisplayName = $user->getDisplayName();
186
+        }
187 187
 
188
-		return new JSONResponse(
189
-			['recipientDisplayName' => $recipientDisplayName],
190
-			Http::STATUS_CREATED);
188
+        return new JSONResponse(
189
+            ['recipientDisplayName' => $recipientDisplayName],
190
+            Http::STATUS_CREATED);
191 191
 
192
-	}
192
+    }
193 193
 
194
-	/**
195
-	 * receive notification about existing share
196
-	 *
197
-	 * @NoCSRFRequired
198
-	 * @PublicPage
199
-	 * @BruteForceProtection(action=receiveFederatedShareNotification)
200
-	 *
201
-	 * @param string $notificationType (notification type, e.g. SHARE_ACCEPTED)
202
-	 * @param string $resourceType (calendar, file, contact,...)
203
-	 * @param string $providerId id of the share
204
-	 * @param array $notification the actual payload of the notification
205
-	 * @return JSONResponse
206
-	 */
207
-	public function receiveNotification($notificationType, $resourceType, $providerId, array $notification) {
194
+    /**
195
+     * receive notification about existing share
196
+     *
197
+     * @NoCSRFRequired
198
+     * @PublicPage
199
+     * @BruteForceProtection(action=receiveFederatedShareNotification)
200
+     *
201
+     * @param string $notificationType (notification type, e.g. SHARE_ACCEPTED)
202
+     * @param string $resourceType (calendar, file, contact,...)
203
+     * @param string $providerId id of the share
204
+     * @param array $notification the actual payload of the notification
205
+     * @return JSONResponse
206
+     */
207
+    public function receiveNotification($notificationType, $resourceType, $providerId, array $notification) {
208 208
 
209
-		// check if all required parameters are set
210
-		if ($notificationType === null ||
211
-			$resourceType === null ||
212
-			$providerId === null ||
213
-			!is_array($notification)
214
-		) {
215
-			return new JSONResponse(
216
-				['message' => 'Missing arguments'],
217
-				Http::STATUS_BAD_REQUEST
218
-			);
219
-		}
209
+        // check if all required parameters are set
210
+        if ($notificationType === null ||
211
+            $resourceType === null ||
212
+            $providerId === null ||
213
+            !is_array($notification)
214
+        ) {
215
+            return new JSONResponse(
216
+                ['message' => 'Missing arguments'],
217
+                Http::STATUS_BAD_REQUEST
218
+            );
219
+        }
220 220
 
221
-		try {
222
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
223
-			$result = $provider->notificationReceived($notificationType, $providerId, $notification);
224
-		} catch (ProviderDoesNotExistsException $e) {
225
-			return new JSONResponse(
226
-				['message' => $e->getMessage()],
227
-				Http::STATUS_BAD_REQUEST
228
-			);
229
-		} catch (ShareNotFound $e) {
230
-			return new JSONResponse(
231
-				['message' => $e->getMessage()],
232
-				Http::STATUS_BAD_REQUEST
233
-			);
234
-		} catch (ActionNotSupportedException $e) {
235
-			return new JSONResponse(
236
-				['message' => $e->getMessage()],
237
-				Http::STATUS_NOT_IMPLEMENTED
238
-			);
239
-		} catch (BadRequestException $e) {
240
-			return new JSONResponse($e->getReturnMessage(), Http::STATUS_BAD_REQUEST);
241
-		} catch (AuthenticationFailedException $e) {
242
-			return new JSONResponse(["message" => "RESOURCE_NOT_FOUND"], Http::STATUS_FORBIDDEN);
243
-		}
244
-		catch (\Exception $e) {
245
-			return new JSONResponse(
246
-				['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
247
-				Http::STATUS_BAD_REQUEST
248
-			);
249
-		}
221
+        try {
222
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
223
+            $result = $provider->notificationReceived($notificationType, $providerId, $notification);
224
+        } catch (ProviderDoesNotExistsException $e) {
225
+            return new JSONResponse(
226
+                ['message' => $e->getMessage()],
227
+                Http::STATUS_BAD_REQUEST
228
+            );
229
+        } catch (ShareNotFound $e) {
230
+            return new JSONResponse(
231
+                ['message' => $e->getMessage()],
232
+                Http::STATUS_BAD_REQUEST
233
+            );
234
+        } catch (ActionNotSupportedException $e) {
235
+            return new JSONResponse(
236
+                ['message' => $e->getMessage()],
237
+                Http::STATUS_NOT_IMPLEMENTED
238
+            );
239
+        } catch (BadRequestException $e) {
240
+            return new JSONResponse($e->getReturnMessage(), Http::STATUS_BAD_REQUEST);
241
+        } catch (AuthenticationFailedException $e) {
242
+            return new JSONResponse(["message" => "RESOURCE_NOT_FOUND"], Http::STATUS_FORBIDDEN);
243
+        }
244
+        catch (\Exception $e) {
245
+            return new JSONResponse(
246
+                ['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
247
+                Http::STATUS_BAD_REQUEST
248
+            );
249
+        }
250 250
 
251
-		return new JSONResponse($result,Http::STATUS_CREATED);
251
+        return new JSONResponse($result,Http::STATUS_CREATED);
252 252
 
253
-	}
253
+    }
254 254
 
255
-	/**
256
-	 * map login name to internal LDAP UID if a LDAP backend is in use
257
-	 *
258
-	 * @param string $uid
259
-	 * @return string mixed
260
-	 */
261
-	private function mapUid($uid) {
262
-		\OC::$server->getURLGenerator()->linkToDocs('key');
263
-		// FIXME this should be a method in the user management instead
264
-		$this->logger->debug('shareWith before, ' . $uid, ['app' => $this->appName]);
265
-		\OCP\Util::emitHook(
266
-			'\OCA\Files_Sharing\API\Server2Server',
267
-			'preLoginNameUsedAsUserName',
268
-			array('uid' => &$uid)
269
-		);
270
-		$this->logger->debug('shareWith after, ' . $uid, ['app' => $this->appName]);
255
+    /**
256
+     * map login name to internal LDAP UID if a LDAP backend is in use
257
+     *
258
+     * @param string $uid
259
+     * @return string mixed
260
+     */
261
+    private function mapUid($uid) {
262
+        \OC::$server->getURLGenerator()->linkToDocs('key');
263
+        // FIXME this should be a method in the user management instead
264
+        $this->logger->debug('shareWith before, ' . $uid, ['app' => $this->appName]);
265
+        \OCP\Util::emitHook(
266
+            '\OCA\Files_Sharing\API\Server2Server',
267
+            'preLoginNameUsedAsUserName',
268
+            array('uid' => &$uid)
269
+        );
270
+        $this->logger->debug('shareWith after, ' . $uid, ['app' => $this->appName]);
271 271
 
272
-		return $uid;
273
-	}
272
+        return $uid;
273
+    }
274 274
 
275 275
 }
Please login to merge, or discard this patch.
apps/cloud_federation_api/lib/Config.php 1 patch
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -35,23 +35,23 @@
 block discarded – undo
35 35
  */
36 36
 class Config {
37 37
 
38
-	/** @var ICloudFederationProviderManager */
39
-	private $cloudFederationProviderManager;
40
-
41
-	public function __construct(ICloudFederationProviderManager $cloudFederationProviderManager) {
42
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
43
-	}
44
-
45
-	/**
46
-	 * get a list of supported share types
47
-	 *
48
-	 * @param string $resourceType
49
-	 * @return array
50
-	 * @throws \OCP\Federation\Exceptions\ProviderDoesNotExistsException
51
-	 */
52
-	public function getSupportedShareTypes($resourceType) {
53
-		$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
54
-		return $provider->getSupportedShareTypes();
55
-	}
38
+    /** @var ICloudFederationProviderManager */
39
+    private $cloudFederationProviderManager;
40
+
41
+    public function __construct(ICloudFederationProviderManager $cloudFederationProviderManager) {
42
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
43
+    }
44
+
45
+    /**
46
+     * get a list of supported share types
47
+     *
48
+     * @param string $resourceType
49
+     * @return array
50
+     * @throws \OCP\Federation\Exceptions\ProviderDoesNotExistsException
51
+     */
52
+    public function getSupportedShareTypes($resourceType) {
53
+        $provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
54
+        return $provider->getSupportedShareTypes();
55
+    }
56 56
 
57 57
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/External/Storage.php 1 patch
Indentation   +376 added lines, -376 removed lines patch added patch discarded remove patch
@@ -43,380 +43,380 @@
 block discarded – undo
43 43
 use OCP\Files\StorageNotAvailableException;
44 44
 
45 45
 class Storage extends DAV implements ISharedStorage {
46
-	/** @var ICloudId */
47
-	private $cloudId;
48
-	/** @var string */
49
-	private $mountPoint;
50
-	/** @var string */
51
-	private $token;
52
-	/** @var \OCP\ICacheFactory */
53
-	private $memcacheFactory;
54
-	/** @var \OCP\Http\Client\IClientService */
55
-	private $httpClient;
56
-	/** @var bool */
57
-	private $updateChecked = false;
58
-
59
-	/**
60
-	 * @var \OCA\Files_Sharing\External\Manager
61
-	 */
62
-	private $manager;
63
-
64
-	public function __construct($options) {
65
-		$this->memcacheFactory = \OC::$server->getMemCacheFactory();
66
-		$this->httpClient = $options['HttpClientService'];
67
-
68
-		$this->manager = $options['manager'];
69
-		$this->cloudId = $options['cloudId'];
70
-		$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
71
-
72
-		list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
73
-		if (strpos($remote, '/')) {
74
-			list($host, $root) = explode('/', $remote, 2);
75
-		} else {
76
-			$host = $remote;
77
-			$root = '';
78
-		}
79
-		$secure = $protocol === 'https';
80
-		$federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
81
-		$webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
82
-		$root = rtrim($root, '/') . $webDavEndpoint;
83
-		$this->mountPoint = $options['mountpoint'];
84
-		$this->token = $options['token'];
85
-
86
-		parent::__construct(array(
87
-			'secure' => $secure,
88
-			'host' => $host,
89
-			'root' => $root,
90
-			'user' => $options['token'],
91
-			'password' => (string)$options['password']
92
-		));
93
-	}
94
-
95
-	public function getWatcher($path = '', $storage = null) {
96
-		if (!$storage) {
97
-			$storage = $this;
98
-		}
99
-		if (!isset($this->watcher)) {
100
-			$this->watcher = new Watcher($storage);
101
-			$this->watcher->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE);
102
-		}
103
-		return $this->watcher;
104
-	}
105
-
106
-	public function getRemoteUser() {
107
-		return $this->cloudId->getUser();
108
-	}
109
-
110
-	public function getRemote() {
111
-		return $this->cloudId->getRemote();
112
-	}
113
-
114
-	public function getMountPoint() {
115
-		return $this->mountPoint;
116
-	}
117
-
118
-	public function getToken() {
119
-		return $this->token;
120
-	}
121
-
122
-	public function getPassword() {
123
-		return $this->password;
124
-	}
125
-
126
-	/**
127
-	 * @brief get id of the mount point
128
-	 * @return string
129
-	 */
130
-	public function getId() {
131
-		return 'shared::' . md5($this->token . '@' . $this->getRemote());
132
-	}
133
-
134
-	public function getCache($path = '', $storage = null) {
135
-		if (is_null($this->cache)) {
136
-			$this->cache = new Cache($this, $this->cloudId);
137
-		}
138
-		return $this->cache;
139
-	}
140
-
141
-	/**
142
-	 * @param string $path
143
-	 * @param \OC\Files\Storage\Storage $storage
144
-	 * @return \OCA\Files_Sharing\External\Scanner
145
-	 */
146
-	public function getScanner($path = '', $storage = null) {
147
-		if (!$storage) {
148
-			$storage = $this;
149
-		}
150
-		if (!isset($this->scanner)) {
151
-			$this->scanner = new Scanner($storage);
152
-		}
153
-		return $this->scanner;
154
-	}
155
-
156
-	/**
157
-	 * check if a file or folder has been updated since $time
158
-	 *
159
-	 * @param string $path
160
-	 * @param int $time
161
-	 * @throws \OCP\Files\StorageNotAvailableException
162
-	 * @throws \OCP\Files\StorageInvalidException
163
-	 * @return bool
164
-	 */
165
-	public function hasUpdated($path, $time) {
166
-		// since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage
167
-		// because of that we only do one check for the entire storage per request
168
-		if ($this->updateChecked) {
169
-			return false;
170
-		}
171
-		$this->updateChecked = true;
172
-		try {
173
-			return parent::hasUpdated('', $time);
174
-		} catch (StorageInvalidException $e) {
175
-			// check if it needs to be removed
176
-			$this->checkStorageAvailability();
177
-			throw $e;
178
-		} catch (StorageNotAvailableException $e) {
179
-			// check if it needs to be removed or just temp unavailable
180
-			$this->checkStorageAvailability();
181
-			throw $e;
182
-		}
183
-	}
184
-
185
-	public function test() {
186
-		try {
187
-			return parent::test();
188
-		} catch (StorageInvalidException $e) {
189
-			// check if it needs to be removed
190
-			$this->checkStorageAvailability();
191
-			throw $e;
192
-		} catch (StorageNotAvailableException $e) {
193
-			// check if it needs to be removed or just temp unavailable
194
-			$this->checkStorageAvailability();
195
-			throw $e;
196
-		}
197
-	}
198
-
199
-	/**
200
-	 * Check whether this storage is permanently or temporarily
201
-	 * unavailable
202
-	 *
203
-	 * @throws \OCP\Files\StorageNotAvailableException
204
-	 * @throws \OCP\Files\StorageInvalidException
205
-	 */
206
-	public function checkStorageAvailability() {
207
-		// see if we can find out why the share is unavailable
208
-		try {
209
-			$this->getShareInfo();
210
-		} catch (NotFoundException $e) {
211
-			// a 404 can either mean that the share no longer exists or there is no Nextcloud on the remote
212
-			if ($this->testRemote()) {
213
-				// valid Nextcloud instance means that the public share no longer exists
214
-				// since this is permanent (re-sharing the file will create a new token)
215
-				// we remove the invalid storage
216
-				$this->manager->removeShare($this->mountPoint);
217
-				$this->manager->getMountManager()->removeMount($this->mountPoint);
218
-				throw new StorageInvalidException();
219
-			} else {
220
-				// Nextcloud instance is gone, likely to be a temporary server configuration error
221
-				throw new StorageNotAvailableException();
222
-			}
223
-		} catch (ForbiddenException $e) {
224
-			// auth error, remove share for now (provide a dialog in the future)
225
-			$this->manager->removeShare($this->mountPoint);
226
-			$this->manager->getMountManager()->removeMount($this->mountPoint);
227
-			throw new StorageInvalidException();
228
-		} catch (\GuzzleHttp\Exception\ConnectException $e) {
229
-			throw new StorageNotAvailableException();
230
-		} catch (\GuzzleHttp\Exception\RequestException $e) {
231
-			throw new StorageNotAvailableException();
232
-		} catch (\Exception $e) {
233
-			throw $e;
234
-		}
235
-	}
236
-
237
-	public function file_exists($path) {
238
-		if ($path === '') {
239
-			return true;
240
-		} else {
241
-			return parent::file_exists($path);
242
-		}
243
-	}
244
-
245
-	/**
246
-	 * check if the configured remote is a valid federated share provider
247
-	 *
248
-	 * @return bool
249
-	 */
250
-	protected function testRemote() {
251
-		try {
252
-			return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
253
-				|| $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
254
-				|| $this->testRemoteUrl($this->getRemote() . '/status.php');
255
-		} catch (\Exception $e) {
256
-			return false;
257
-		}
258
-	}
259
-
260
-	/**
261
-	 * @param string $url
262
-	 * @return bool
263
-	 */
264
-	private function testRemoteUrl($url) {
265
-		$cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
266
-		if($cache->hasKey($url)) {
267
-			return (bool)$cache->get($url);
268
-		}
269
-
270
-		$client = $this->httpClient->newClient();
271
-		try {
272
-			$result = $client->get($url, [
273
-				'timeout' => 10,
274
-				'connect_timeout' => 10,
275
-			])->getBody();
276
-			$data = json_decode($result);
277
-			$returnValue = (is_object($data) && !empty($data->version));
278
-		} catch (ConnectException $e) {
279
-			$returnValue = false;
280
-		} catch (ClientException $e) {
281
-			$returnValue = false;
282
-		}
283
-
284
-		$cache->set($url, $returnValue, 60*60*24);
285
-		return $returnValue;
286
-	}
287
-
288
-	/**
289
-	 * Whether the remote is an ownCloud/Nextcloud, used since some sharing features are not
290
-	 * standardized. Let's use this to detect whether to use it.
291
-	 *
292
-	 * @return bool
293
-	 */
294
-	public function remoteIsOwnCloud() {
295
-		if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
296
-			return false;
297
-		}
298
-		return true;
299
-	}
300
-
301
-	/**
302
-	 * @return mixed
303
-	 * @throws ForbiddenException
304
-	 * @throws NotFoundException
305
-	 * @throws \Exception
306
-	 */
307
-	public function getShareInfo() {
308
-		$remote = $this->getRemote();
309
-		$token = $this->getToken();
310
-		$password = $this->getPassword();
311
-
312
-		// If remote is not an ownCloud do not try to get any share info
313
-		if(!$this->remoteIsOwnCloud()) {
314
-			return ['status' => 'unsupported'];
315
-		}
316
-
317
-		$url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
318
-
319
-		// TODO: DI
320
-		$client = \OC::$server->getHTTPClientService()->newClient();
321
-		try {
322
-			$response = $client->post($url, [
323
-				'body' => ['password' => $password],
324
-				'timeout' => 10,
325
-				'connect_timeout' => 10,
326
-			]);
327
-		} catch (\GuzzleHttp\Exception\RequestException $e) {
328
-			if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) {
329
-				throw new ForbiddenException();
330
-			}
331
-			if ($e->getCode() === Http::STATUS_NOT_FOUND) {
332
-				throw new NotFoundException();
333
-			}
334
-			// throw this to be on the safe side: the share will still be visible
335
-			// in the UI in case the failure is intermittent, and the user will
336
-			// be able to decide whether to remove it if it's really gone
337
-			throw new StorageNotAvailableException();
338
-		}
339
-
340
-		return json_decode($response->getBody(), true);
341
-	}
342
-
343
-	public function getOwner($path) {
344
-		return $this->cloudId->getDisplayId();
345
-	}
346
-
347
-	public function isSharable($path) {
348
-		if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
349
-			return false;
350
-		}
351
-		return ($this->getPermissions($path) & Constants::PERMISSION_SHARE);
352
-	}
353
-
354
-	public function getPermissions($path) {
355
-		$response = $this->propfind($path);
356
-		// old federated sharing permissions
357
-		if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
358
-			$permissions = $response['{http://open-collaboration-services.org/ns}share-permissions'];
359
-		} else if (isset($response['{http://open-cloud-mesh.org/ns}share-permissions'])) {
360
-			// permissions provided by the OCM API
361
-			$permissions = $this->ocmPermissions2ncPermissions($response['{http://open-collaboration-services.org/ns}share-permissions']);
362
-		} else {
363
-			// use default permission if remote server doesn't provide the share permissions
364
-			$permissions = $this->getDefaultPermissions($path);
365
-		}
366
-
367
-		return $permissions;
368
-	}
369
-
370
-	public function needsPartFile() {
371
-		return false;
372
-	}
373
-
374
-	/**
375
-	 * translate OCM Permissions to Nextcloud permissions
376
-	 *
377
-	 * @param string $ocmPermissions json encoded OCM permissions
378
-	 * @param string $path path to file
379
-	 * @return int
380
-	 */
381
-	protected function ocmPermissions2ncPermissions($ocmPermissions, $path) {
382
-		try {
383
-			$ocmPermissions = json_decode($ocmPermissions);
384
-			$ncPermissions = 0;
385
-			foreach($ocmPermissions as $permission) {
386
-				switch (strtolower($permission)) {
387
-					case 'read':
388
-						$ncPermissions += Constants::PERMISSION_READ;
389
-						break;
390
-					case 'write':
391
-						$ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
392
-						break;
393
-					case 'share':
394
-						$ncPermissions += Constants::PERMISSION_SHARE;
395
-						break;
396
-					default:
397
-						throw new \Exception();
398
-				}
399
-			}
400
-		} catch (\Exception $e) {
401
-			$ncPermissions = $this->getDefaultPermissions($path);
402
-		}
403
-
404
-		return $ncPermissions;
405
-	}
406
-
407
-	/**
408
-	 * calculate default permissions in case no permissions are provided
409
-	 *
410
-	 * @param $path
411
-	 * @return int
412
-	 */
413
-	protected function getDefaultPermissions($path) {
414
-		if ($this->is_dir($path)) {
415
-			$permissions = Constants::PERMISSION_ALL;
416
-		} else {
417
-			$permissions = Constants::PERMISSION_ALL & ~Constants::PERMISSION_CREATE;
418
-		}
419
-
420
-		return $permissions;
421
-	}
46
+    /** @var ICloudId */
47
+    private $cloudId;
48
+    /** @var string */
49
+    private $mountPoint;
50
+    /** @var string */
51
+    private $token;
52
+    /** @var \OCP\ICacheFactory */
53
+    private $memcacheFactory;
54
+    /** @var \OCP\Http\Client\IClientService */
55
+    private $httpClient;
56
+    /** @var bool */
57
+    private $updateChecked = false;
58
+
59
+    /**
60
+     * @var \OCA\Files_Sharing\External\Manager
61
+     */
62
+    private $manager;
63
+
64
+    public function __construct($options) {
65
+        $this->memcacheFactory = \OC::$server->getMemCacheFactory();
66
+        $this->httpClient = $options['HttpClientService'];
67
+
68
+        $this->manager = $options['manager'];
69
+        $this->cloudId = $options['cloudId'];
70
+        $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
71
+
72
+        list($protocol, $remote) = explode('://', $this->cloudId->getRemote());
73
+        if (strpos($remote, '/')) {
74
+            list($host, $root) = explode('/', $remote, 2);
75
+        } else {
76
+            $host = $remote;
77
+            $root = '';
78
+        }
79
+        $secure = $protocol === 'https';
80
+        $federatedSharingEndpoints = $discoveryService->discover($this->cloudId->getRemote(), 'FEDERATED_SHARING');
81
+        $webDavEndpoint = isset($federatedSharingEndpoints['webdav']) ? $federatedSharingEndpoints['webdav'] : '/public.php/webdav';
82
+        $root = rtrim($root, '/') . $webDavEndpoint;
83
+        $this->mountPoint = $options['mountpoint'];
84
+        $this->token = $options['token'];
85
+
86
+        parent::__construct(array(
87
+            'secure' => $secure,
88
+            'host' => $host,
89
+            'root' => $root,
90
+            'user' => $options['token'],
91
+            'password' => (string)$options['password']
92
+        ));
93
+    }
94
+
95
+    public function getWatcher($path = '', $storage = null) {
96
+        if (!$storage) {
97
+            $storage = $this;
98
+        }
99
+        if (!isset($this->watcher)) {
100
+            $this->watcher = new Watcher($storage);
101
+            $this->watcher->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE);
102
+        }
103
+        return $this->watcher;
104
+    }
105
+
106
+    public function getRemoteUser() {
107
+        return $this->cloudId->getUser();
108
+    }
109
+
110
+    public function getRemote() {
111
+        return $this->cloudId->getRemote();
112
+    }
113
+
114
+    public function getMountPoint() {
115
+        return $this->mountPoint;
116
+    }
117
+
118
+    public function getToken() {
119
+        return $this->token;
120
+    }
121
+
122
+    public function getPassword() {
123
+        return $this->password;
124
+    }
125
+
126
+    /**
127
+     * @brief get id of the mount point
128
+     * @return string
129
+     */
130
+    public function getId() {
131
+        return 'shared::' . md5($this->token . '@' . $this->getRemote());
132
+    }
133
+
134
+    public function getCache($path = '', $storage = null) {
135
+        if (is_null($this->cache)) {
136
+            $this->cache = new Cache($this, $this->cloudId);
137
+        }
138
+        return $this->cache;
139
+    }
140
+
141
+    /**
142
+     * @param string $path
143
+     * @param \OC\Files\Storage\Storage $storage
144
+     * @return \OCA\Files_Sharing\External\Scanner
145
+     */
146
+    public function getScanner($path = '', $storage = null) {
147
+        if (!$storage) {
148
+            $storage = $this;
149
+        }
150
+        if (!isset($this->scanner)) {
151
+            $this->scanner = new Scanner($storage);
152
+        }
153
+        return $this->scanner;
154
+    }
155
+
156
+    /**
157
+     * check if a file or folder has been updated since $time
158
+     *
159
+     * @param string $path
160
+     * @param int $time
161
+     * @throws \OCP\Files\StorageNotAvailableException
162
+     * @throws \OCP\Files\StorageInvalidException
163
+     * @return bool
164
+     */
165
+    public function hasUpdated($path, $time) {
166
+        // since for owncloud webdav servers we can rely on etag propagation we only need to check the root of the storage
167
+        // because of that we only do one check for the entire storage per request
168
+        if ($this->updateChecked) {
169
+            return false;
170
+        }
171
+        $this->updateChecked = true;
172
+        try {
173
+            return parent::hasUpdated('', $time);
174
+        } catch (StorageInvalidException $e) {
175
+            // check if it needs to be removed
176
+            $this->checkStorageAvailability();
177
+            throw $e;
178
+        } catch (StorageNotAvailableException $e) {
179
+            // check if it needs to be removed or just temp unavailable
180
+            $this->checkStorageAvailability();
181
+            throw $e;
182
+        }
183
+    }
184
+
185
+    public function test() {
186
+        try {
187
+            return parent::test();
188
+        } catch (StorageInvalidException $e) {
189
+            // check if it needs to be removed
190
+            $this->checkStorageAvailability();
191
+            throw $e;
192
+        } catch (StorageNotAvailableException $e) {
193
+            // check if it needs to be removed or just temp unavailable
194
+            $this->checkStorageAvailability();
195
+            throw $e;
196
+        }
197
+    }
198
+
199
+    /**
200
+     * Check whether this storage is permanently or temporarily
201
+     * unavailable
202
+     *
203
+     * @throws \OCP\Files\StorageNotAvailableException
204
+     * @throws \OCP\Files\StorageInvalidException
205
+     */
206
+    public function checkStorageAvailability() {
207
+        // see if we can find out why the share is unavailable
208
+        try {
209
+            $this->getShareInfo();
210
+        } catch (NotFoundException $e) {
211
+            // a 404 can either mean that the share no longer exists or there is no Nextcloud on the remote
212
+            if ($this->testRemote()) {
213
+                // valid Nextcloud instance means that the public share no longer exists
214
+                // since this is permanent (re-sharing the file will create a new token)
215
+                // we remove the invalid storage
216
+                $this->manager->removeShare($this->mountPoint);
217
+                $this->manager->getMountManager()->removeMount($this->mountPoint);
218
+                throw new StorageInvalidException();
219
+            } else {
220
+                // Nextcloud instance is gone, likely to be a temporary server configuration error
221
+                throw new StorageNotAvailableException();
222
+            }
223
+        } catch (ForbiddenException $e) {
224
+            // auth error, remove share for now (provide a dialog in the future)
225
+            $this->manager->removeShare($this->mountPoint);
226
+            $this->manager->getMountManager()->removeMount($this->mountPoint);
227
+            throw new StorageInvalidException();
228
+        } catch (\GuzzleHttp\Exception\ConnectException $e) {
229
+            throw new StorageNotAvailableException();
230
+        } catch (\GuzzleHttp\Exception\RequestException $e) {
231
+            throw new StorageNotAvailableException();
232
+        } catch (\Exception $e) {
233
+            throw $e;
234
+        }
235
+    }
236
+
237
+    public function file_exists($path) {
238
+        if ($path === '') {
239
+            return true;
240
+        } else {
241
+            return parent::file_exists($path);
242
+        }
243
+    }
244
+
245
+    /**
246
+     * check if the configured remote is a valid federated share provider
247
+     *
248
+     * @return bool
249
+     */
250
+    protected function testRemote() {
251
+        try {
252
+            return $this->testRemoteUrl($this->getRemote() . '/ocs-provider/index.php')
253
+                || $this->testRemoteUrl($this->getRemote() . '/ocs-provider/')
254
+                || $this->testRemoteUrl($this->getRemote() . '/status.php');
255
+        } catch (\Exception $e) {
256
+            return false;
257
+        }
258
+    }
259
+
260
+    /**
261
+     * @param string $url
262
+     * @return bool
263
+     */
264
+    private function testRemoteUrl($url) {
265
+        $cache = $this->memcacheFactory->createDistributed('files_sharing_remote_url');
266
+        if($cache->hasKey($url)) {
267
+            return (bool)$cache->get($url);
268
+        }
269
+
270
+        $client = $this->httpClient->newClient();
271
+        try {
272
+            $result = $client->get($url, [
273
+                'timeout' => 10,
274
+                'connect_timeout' => 10,
275
+            ])->getBody();
276
+            $data = json_decode($result);
277
+            $returnValue = (is_object($data) && !empty($data->version));
278
+        } catch (ConnectException $e) {
279
+            $returnValue = false;
280
+        } catch (ClientException $e) {
281
+            $returnValue = false;
282
+        }
283
+
284
+        $cache->set($url, $returnValue, 60*60*24);
285
+        return $returnValue;
286
+    }
287
+
288
+    /**
289
+     * Whether the remote is an ownCloud/Nextcloud, used since some sharing features are not
290
+     * standardized. Let's use this to detect whether to use it.
291
+     *
292
+     * @return bool
293
+     */
294
+    public function remoteIsOwnCloud() {
295
+        if(defined('PHPUNIT_RUN') || !$this->testRemoteUrl($this->getRemote() . '/status.php')) {
296
+            return false;
297
+        }
298
+        return true;
299
+    }
300
+
301
+    /**
302
+     * @return mixed
303
+     * @throws ForbiddenException
304
+     * @throws NotFoundException
305
+     * @throws \Exception
306
+     */
307
+    public function getShareInfo() {
308
+        $remote = $this->getRemote();
309
+        $token = $this->getToken();
310
+        $password = $this->getPassword();
311
+
312
+        // If remote is not an ownCloud do not try to get any share info
313
+        if(!$this->remoteIsOwnCloud()) {
314
+            return ['status' => 'unsupported'];
315
+        }
316
+
317
+        $url = rtrim($remote, '/') . '/index.php/apps/files_sharing/shareinfo?t=' . $token;
318
+
319
+        // TODO: DI
320
+        $client = \OC::$server->getHTTPClientService()->newClient();
321
+        try {
322
+            $response = $client->post($url, [
323
+                'body' => ['password' => $password],
324
+                'timeout' => 10,
325
+                'connect_timeout' => 10,
326
+            ]);
327
+        } catch (\GuzzleHttp\Exception\RequestException $e) {
328
+            if ($e->getCode() === Http::STATUS_UNAUTHORIZED || $e->getCode() === Http::STATUS_FORBIDDEN) {
329
+                throw new ForbiddenException();
330
+            }
331
+            if ($e->getCode() === Http::STATUS_NOT_FOUND) {
332
+                throw new NotFoundException();
333
+            }
334
+            // throw this to be on the safe side: the share will still be visible
335
+            // in the UI in case the failure is intermittent, and the user will
336
+            // be able to decide whether to remove it if it's really gone
337
+            throw new StorageNotAvailableException();
338
+        }
339
+
340
+        return json_decode($response->getBody(), true);
341
+    }
342
+
343
+    public function getOwner($path) {
344
+        return $this->cloudId->getDisplayId();
345
+    }
346
+
347
+    public function isSharable($path) {
348
+        if (\OCP\Util::isSharingDisabledForUser() || !\OC\Share\Share::isResharingAllowed()) {
349
+            return false;
350
+        }
351
+        return ($this->getPermissions($path) & Constants::PERMISSION_SHARE);
352
+    }
353
+
354
+    public function getPermissions($path) {
355
+        $response = $this->propfind($path);
356
+        // old federated sharing permissions
357
+        if (isset($response['{http://open-collaboration-services.org/ns}share-permissions'])) {
358
+            $permissions = $response['{http://open-collaboration-services.org/ns}share-permissions'];
359
+        } else if (isset($response['{http://open-cloud-mesh.org/ns}share-permissions'])) {
360
+            // permissions provided by the OCM API
361
+            $permissions = $this->ocmPermissions2ncPermissions($response['{http://open-collaboration-services.org/ns}share-permissions']);
362
+        } else {
363
+            // use default permission if remote server doesn't provide the share permissions
364
+            $permissions = $this->getDefaultPermissions($path);
365
+        }
366
+
367
+        return $permissions;
368
+    }
369
+
370
+    public function needsPartFile() {
371
+        return false;
372
+    }
373
+
374
+    /**
375
+     * translate OCM Permissions to Nextcloud permissions
376
+     *
377
+     * @param string $ocmPermissions json encoded OCM permissions
378
+     * @param string $path path to file
379
+     * @return int
380
+     */
381
+    protected function ocmPermissions2ncPermissions($ocmPermissions, $path) {
382
+        try {
383
+            $ocmPermissions = json_decode($ocmPermissions);
384
+            $ncPermissions = 0;
385
+            foreach($ocmPermissions as $permission) {
386
+                switch (strtolower($permission)) {
387
+                    case 'read':
388
+                        $ncPermissions += Constants::PERMISSION_READ;
389
+                        break;
390
+                    case 'write':
391
+                        $ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
392
+                        break;
393
+                    case 'share':
394
+                        $ncPermissions += Constants::PERMISSION_SHARE;
395
+                        break;
396
+                    default:
397
+                        throw new \Exception();
398
+                }
399
+            }
400
+        } catch (\Exception $e) {
401
+            $ncPermissions = $this->getDefaultPermissions($path);
402
+        }
403
+
404
+        return $ncPermissions;
405
+    }
406
+
407
+    /**
408
+     * calculate default permissions in case no permissions are provided
409
+     *
410
+     * @param $path
411
+     * @return int
412
+     */
413
+    protected function getDefaultPermissions($path) {
414
+        if ($this->is_dir($path)) {
415
+            $permissions = Constants::PERMISSION_ALL;
416
+        } else {
417
+            $permissions = Constants::PERMISSION_ALL & ~Constants::PERMISSION_CREATE;
418
+        }
419
+
420
+        return $permissions;
421
+    }
422 422
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/FilesPlugin.php 1 patch
Indentation   +436 added lines, -436 removed lines patch added patch discarded remove patch
@@ -50,444 +50,444 @@
 block discarded – undo
50 50
 
51 51
 class FilesPlugin extends ServerPlugin {
52 52
 
53
-	// namespace
54
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
55
-	const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
56
-	const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
57
-	const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
58
-	const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
59
-	const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
60
-	const OCM_SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-cloud-mesh.org/ns}share-permissions';
61
-	const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
62
-	const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
63
-	const GETETAG_PROPERTYNAME = '{DAV:}getetag';
64
-	const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
65
-	const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
66
-	const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
67
-	const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
68
-	const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
69
-	const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
70
-	const MOUNT_TYPE_PROPERTYNAME = '{http://nextcloud.org/ns}mount-type';
71
-	const IS_ENCRYPTED_PROPERTYNAME = '{http://nextcloud.org/ns}is-encrypted';
72
-
73
-	/**
74
-	 * Reference to main server object
75
-	 *
76
-	 * @var \Sabre\DAV\Server
77
-	 */
78
-	private $server;
79
-
80
-	/**
81
-	 * @var Tree
82
-	 */
83
-	private $tree;
84
-
85
-	/**
86
-	 * Whether this is public webdav.
87
-	 * If true, some returned information will be stripped off.
88
-	 *
89
-	 * @var bool
90
-	 */
91
-	private $isPublic;
92
-
93
-	/**
94
-	 * @var bool
95
-	 */
96
-	private $downloadAttachment;
97
-
98
-	/**
99
-	 * @var IConfig
100
-	 */
101
-	private $config;
102
-
103
-	/**
104
-	 * @var IRequest
105
-	 */
106
-	private $request;
107
-
108
-	/**
109
-	 * @var IPreview
110
-	 */
111
-	private $previewManager;
112
-
113
-	/**
114
-	 * @param Tree $tree
115
-	 * @param IConfig $config
116
-	 * @param IRequest $request
117
-	 * @param IPreview $previewManager
118
-	 * @param bool $isPublic
119
-	 * @param bool $downloadAttachment
120
-	 */
121
-	public function __construct(Tree $tree,
122
-								IConfig $config,
123
-								IRequest $request,
124
-								IPreview $previewManager,
125
-								$isPublic = false,
126
-								$downloadAttachment = true) {
127
-		$this->tree = $tree;
128
-		$this->config = $config;
129
-		$this->request = $request;
130
-		$this->isPublic = $isPublic;
131
-		$this->downloadAttachment = $downloadAttachment;
132
-		$this->previewManager = $previewManager;
133
-	}
134
-
135
-	/**
136
-	 * This initializes the plugin.
137
-	 *
138
-	 * This function is called by \Sabre\DAV\Server, after
139
-	 * addPlugin is called.
140
-	 *
141
-	 * This method should set up the required event subscriptions.
142
-	 *
143
-	 * @param \Sabre\DAV\Server $server
144
-	 * @return void
145
-	 */
146
-	public function initialize(\Sabre\DAV\Server $server) {
147
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
148
-		$server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
149
-		$server->protectedProperties[] = self::FILEID_PROPERTYNAME;
150
-		$server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
151
-		$server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
152
-		$server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
153
-		$server->protectedProperties[] = self::OCM_SHARE_PERMISSIONS_PROPERTYNAME;
154
-		$server->protectedProperties[] = self::SIZE_PROPERTYNAME;
155
-		$server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
156
-		$server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
157
-		$server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
158
-		$server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
159
-		$server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
160
-		$server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
161
-		$server->protectedProperties[] = self::MOUNT_TYPE_PROPERTYNAME;
162
-		$server->protectedProperties[] = self::IS_ENCRYPTED_PROPERTYNAME;
163
-
164
-		// normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
165
-		$allowedProperties = ['{DAV:}getetag'];
166
-		$server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties);
167
-
168
-		$this->server = $server;
169
-		$this->server->on('propFind', array($this, 'handleGetProperties'));
170
-		$this->server->on('propPatch', array($this, 'handleUpdateProperties'));
171
-		$this->server->on('afterBind', array($this, 'sendFileIdHeader'));
172
-		$this->server->on('afterWriteContent', array($this, 'sendFileIdHeader'));
173
-		$this->server->on('afterMethod:GET', [$this,'httpGet']);
174
-		$this->server->on('afterMethod:GET', array($this, 'handleDownloadToken'));
175
-		$this->server->on('afterResponse', function($request, ResponseInterface $response) {
176
-			$body = $response->getBody();
177
-			if (is_resource($body)) {
178
-				fclose($body);
179
-			}
180
-		});
181
-		$this->server->on('beforeMove', [$this, 'checkMove']);
182
-	}
183
-
184
-	/**
185
-	 * Plugin that checks if a move can actually be performed.
186
-	 *
187
-	 * @param string $source source path
188
-	 * @param string $destination destination path
189
-	 * @throws Forbidden
190
-	 * @throws NotFound
191
-	 */
192
-	function checkMove($source, $destination) {
193
-		$sourceNode = $this->tree->getNodeForPath($source);
194
-		if (!$sourceNode instanceof Node) {
195
-			return;
196
-		}
197
-		list($sourceDir,) = \Sabre\Uri\split($source);
198
-		list($destinationDir,) = \Sabre\Uri\split($destination);
199
-
200
-		if ($sourceDir !== $destinationDir) {
201
-			$sourceNodeFileInfo = $sourceNode->getFileInfo();
202
-			if ($sourceNodeFileInfo === null) {
203
-				throw new NotFound($source . ' does not exist');
204
- 			}
205
-
206
-			if (!$sourceNodeFileInfo->isDeletable()) {
207
-				throw new Forbidden($source . " cannot be deleted");
208
-			}
209
-		}
210
-	}
211
-
212
-	/**
213
-	 * This sets a cookie to be able to recognize the start of the download
214
-	 * the content must not be longer than 32 characters and must only contain
215
-	 * alphanumeric characters
216
-	 *
217
-	 * @param RequestInterface $request
218
-	 * @param ResponseInterface $response
219
-	 */
220
-	function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
221
-		$queryParams = $request->getQueryParameters();
222
-
223
-		/**
224
-		 * this sets a cookie to be able to recognize the start of the download
225
-		 * the content must not be longer than 32 characters and must only contain
226
-		 * alphanumeric characters
227
-		 */
228
-		if (isset($queryParams['downloadStartSecret'])) {
229
-			$token = $queryParams['downloadStartSecret'];
230
-			if (!isset($token[32])
231
-				&& preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
232
-				// FIXME: use $response->setHeader() instead
233
-				setcookie('ocDownloadStarted', $token, time() + 20, '/');
234
-			}
235
-		}
236
-	}
237
-
238
-	/**
239
-	 * Add headers to file download
240
-	 *
241
-	 * @param RequestInterface $request
242
-	 * @param ResponseInterface $response
243
-	 */
244
-	function httpGet(RequestInterface $request, ResponseInterface $response) {
245
-		// Only handle valid files
246
-		$node = $this->tree->getNodeForPath($request->getPath());
247
-		if (!($node instanceof IFile)) return;
248
-
249
-		// adds a 'Content-Disposition: attachment' header in case no disposition
250
-		// header has been set before
251
-		if ($this->downloadAttachment &&
252
-			$response->getHeader('Content-Disposition') === null) {
253
-			$filename = $node->getName();
254
-			if ($this->request->isUserAgent(
255
-				[
256
-					Request::USER_AGENT_IE,
257
-					Request::USER_AGENT_ANDROID_MOBILE_CHROME,
258
-					Request::USER_AGENT_FREEBOX,
259
-				])) {
260
-				$response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
261
-			} else {
262
-				$response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
263
-													 . '; filename="' . rawurlencode($filename) . '"');
264
-			}
265
-		}
266
-
267
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
268
-			//Add OC-Checksum header
269
-			/** @var $node File */
270
-			$checksum = $node->getChecksum();
271
-			if ($checksum !== null && $checksum !== '') {
272
-				$response->addHeader('OC-Checksum', $checksum);
273
-			}
274
-		}
275
-	}
276
-
277
-	/**
278
-	 * Adds all ownCloud-specific properties
279
-	 *
280
-	 * @param PropFind $propFind
281
-	 * @param \Sabre\DAV\INode $node
282
-	 * @return void
283
-	 */
284
-	public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
285
-
286
-		$httpRequest = $this->server->httpRequest;
287
-
288
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
289
-			/**
290
-			 * This was disabled, because it made dir listing throw an exception,
291
-			 * so users were unable to navigate into folders where one subitem
292
-			 * is blocked by the files_accesscontrol app, see:
293
-			 * https://github.com/nextcloud/files_accesscontrol/issues/65
53
+    // namespace
54
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
55
+    const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
56
+    const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
57
+    const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
58
+    const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
59
+    const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
60
+    const OCM_SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-cloud-mesh.org/ns}share-permissions';
61
+    const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
62
+    const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
63
+    const GETETAG_PROPERTYNAME = '{DAV:}getetag';
64
+    const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
65
+    const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
66
+    const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
67
+    const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
68
+    const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
69
+    const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
70
+    const MOUNT_TYPE_PROPERTYNAME = '{http://nextcloud.org/ns}mount-type';
71
+    const IS_ENCRYPTED_PROPERTYNAME = '{http://nextcloud.org/ns}is-encrypted';
72
+
73
+    /**
74
+     * Reference to main server object
75
+     *
76
+     * @var \Sabre\DAV\Server
77
+     */
78
+    private $server;
79
+
80
+    /**
81
+     * @var Tree
82
+     */
83
+    private $tree;
84
+
85
+    /**
86
+     * Whether this is public webdav.
87
+     * If true, some returned information will be stripped off.
88
+     *
89
+     * @var bool
90
+     */
91
+    private $isPublic;
92
+
93
+    /**
94
+     * @var bool
95
+     */
96
+    private $downloadAttachment;
97
+
98
+    /**
99
+     * @var IConfig
100
+     */
101
+    private $config;
102
+
103
+    /**
104
+     * @var IRequest
105
+     */
106
+    private $request;
107
+
108
+    /**
109
+     * @var IPreview
110
+     */
111
+    private $previewManager;
112
+
113
+    /**
114
+     * @param Tree $tree
115
+     * @param IConfig $config
116
+     * @param IRequest $request
117
+     * @param IPreview $previewManager
118
+     * @param bool $isPublic
119
+     * @param bool $downloadAttachment
120
+     */
121
+    public function __construct(Tree $tree,
122
+                                IConfig $config,
123
+                                IRequest $request,
124
+                                IPreview $previewManager,
125
+                                $isPublic = false,
126
+                                $downloadAttachment = true) {
127
+        $this->tree = $tree;
128
+        $this->config = $config;
129
+        $this->request = $request;
130
+        $this->isPublic = $isPublic;
131
+        $this->downloadAttachment = $downloadAttachment;
132
+        $this->previewManager = $previewManager;
133
+    }
134
+
135
+    /**
136
+     * This initializes the plugin.
137
+     *
138
+     * This function is called by \Sabre\DAV\Server, after
139
+     * addPlugin is called.
140
+     *
141
+     * This method should set up the required event subscriptions.
142
+     *
143
+     * @param \Sabre\DAV\Server $server
144
+     * @return void
145
+     */
146
+    public function initialize(\Sabre\DAV\Server $server) {
147
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
148
+        $server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
149
+        $server->protectedProperties[] = self::FILEID_PROPERTYNAME;
150
+        $server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
151
+        $server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
152
+        $server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
153
+        $server->protectedProperties[] = self::OCM_SHARE_PERMISSIONS_PROPERTYNAME;
154
+        $server->protectedProperties[] = self::SIZE_PROPERTYNAME;
155
+        $server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
156
+        $server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
157
+        $server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
158
+        $server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
159
+        $server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
160
+        $server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
161
+        $server->protectedProperties[] = self::MOUNT_TYPE_PROPERTYNAME;
162
+        $server->protectedProperties[] = self::IS_ENCRYPTED_PROPERTYNAME;
163
+
164
+        // normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
165
+        $allowedProperties = ['{DAV:}getetag'];
166
+        $server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties);
167
+
168
+        $this->server = $server;
169
+        $this->server->on('propFind', array($this, 'handleGetProperties'));
170
+        $this->server->on('propPatch', array($this, 'handleUpdateProperties'));
171
+        $this->server->on('afterBind', array($this, 'sendFileIdHeader'));
172
+        $this->server->on('afterWriteContent', array($this, 'sendFileIdHeader'));
173
+        $this->server->on('afterMethod:GET', [$this,'httpGet']);
174
+        $this->server->on('afterMethod:GET', array($this, 'handleDownloadToken'));
175
+        $this->server->on('afterResponse', function($request, ResponseInterface $response) {
176
+            $body = $response->getBody();
177
+            if (is_resource($body)) {
178
+                fclose($body);
179
+            }
180
+        });
181
+        $this->server->on('beforeMove', [$this, 'checkMove']);
182
+    }
183
+
184
+    /**
185
+     * Plugin that checks if a move can actually be performed.
186
+     *
187
+     * @param string $source source path
188
+     * @param string $destination destination path
189
+     * @throws Forbidden
190
+     * @throws NotFound
191
+     */
192
+    function checkMove($source, $destination) {
193
+        $sourceNode = $this->tree->getNodeForPath($source);
194
+        if (!$sourceNode instanceof Node) {
195
+            return;
196
+        }
197
+        list($sourceDir,) = \Sabre\Uri\split($source);
198
+        list($destinationDir,) = \Sabre\Uri\split($destination);
199
+
200
+        if ($sourceDir !== $destinationDir) {
201
+            $sourceNodeFileInfo = $sourceNode->getFileInfo();
202
+            if ($sourceNodeFileInfo === null) {
203
+                throw new NotFound($source . ' does not exist');
204
+                }
205
+
206
+            if (!$sourceNodeFileInfo->isDeletable()) {
207
+                throw new Forbidden($source . " cannot be deleted");
208
+            }
209
+        }
210
+    }
211
+
212
+    /**
213
+     * This sets a cookie to be able to recognize the start of the download
214
+     * the content must not be longer than 32 characters and must only contain
215
+     * alphanumeric characters
216
+     *
217
+     * @param RequestInterface $request
218
+     * @param ResponseInterface $response
219
+     */
220
+    function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
221
+        $queryParams = $request->getQueryParameters();
222
+
223
+        /**
224
+         * this sets a cookie to be able to recognize the start of the download
225
+         * the content must not be longer than 32 characters and must only contain
226
+         * alphanumeric characters
227
+         */
228
+        if (isset($queryParams['downloadStartSecret'])) {
229
+            $token = $queryParams['downloadStartSecret'];
230
+            if (!isset($token[32])
231
+                && preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
232
+                // FIXME: use $response->setHeader() instead
233
+                setcookie('ocDownloadStarted', $token, time() + 20, '/');
234
+            }
235
+        }
236
+    }
237
+
238
+    /**
239
+     * Add headers to file download
240
+     *
241
+     * @param RequestInterface $request
242
+     * @param ResponseInterface $response
243
+     */
244
+    function httpGet(RequestInterface $request, ResponseInterface $response) {
245
+        // Only handle valid files
246
+        $node = $this->tree->getNodeForPath($request->getPath());
247
+        if (!($node instanceof IFile)) return;
248
+
249
+        // adds a 'Content-Disposition: attachment' header in case no disposition
250
+        // header has been set before
251
+        if ($this->downloadAttachment &&
252
+            $response->getHeader('Content-Disposition') === null) {
253
+            $filename = $node->getName();
254
+            if ($this->request->isUserAgent(
255
+                [
256
+                    Request::USER_AGENT_IE,
257
+                    Request::USER_AGENT_ANDROID_MOBILE_CHROME,
258
+                    Request::USER_AGENT_FREEBOX,
259
+                ])) {
260
+                $response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
261
+            } else {
262
+                $response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
263
+                                                        . '; filename="' . rawurlencode($filename) . '"');
264
+            }
265
+        }
266
+
267
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
268
+            //Add OC-Checksum header
269
+            /** @var $node File */
270
+            $checksum = $node->getChecksum();
271
+            if ($checksum !== null && $checksum !== '') {
272
+                $response->addHeader('OC-Checksum', $checksum);
273
+            }
274
+        }
275
+    }
276
+
277
+    /**
278
+     * Adds all ownCloud-specific properties
279
+     *
280
+     * @param PropFind $propFind
281
+     * @param \Sabre\DAV\INode $node
282
+     * @return void
283
+     */
284
+    public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
285
+
286
+        $httpRequest = $this->server->httpRequest;
287
+
288
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
289
+            /**
290
+             * This was disabled, because it made dir listing throw an exception,
291
+             * so users were unable to navigate into folders where one subitem
292
+             * is blocked by the files_accesscontrol app, see:
293
+             * https://github.com/nextcloud/files_accesscontrol/issues/65
294 294
 			if (!$node->getFileInfo()->isReadable()) {
295 295
 				// avoid detecting files through this means
296 296
 				throw new NotFound();
297 297
 			}
298
-			 */
299
-
300
-			$propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
301
-				return $node->getFileId();
302
-			});
303
-
304
-			$propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
305
-				return $node->getInternalFileId();
306
-			});
307
-
308
-			$propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
309
-				$perms = $node->getDavPermissions();
310
-				if ($this->isPublic) {
311
-					// remove mount information
312
-					$perms = str_replace(['S', 'M'], '', $perms);
313
-				}
314
-				return $perms;
315
-			});
316
-
317
-			$propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
318
-				return $node->getSharePermissions(
319
-					$httpRequest->getRawServerValue('PHP_AUTH_USER')
320
-				);
321
-			});
322
-
323
-			$propFind->handle(self::OCM_SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
324
-				$ncPermissions = $node->getSharePermissions(
325
-					$httpRequest->getRawServerValue('PHP_AUTH_USER')
326
-				);
327
-				$ocmPermissions = $this->ncPermissions2ocmPermissions($ncPermissions);
328
-				return json_encode($ocmPermissions);
329
-			});
330
-
331
-			$propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
332
-				return $node->getETag();
333
-			});
334
-
335
-			$propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
336
-				$owner = $node->getOwner();
337
-				if (!$owner) {
338
-					return null;
339
-				} else {
340
-					return $owner->getUID();
341
-				}
342
-			});
343
-			$propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
344
-				$owner = $node->getOwner();
345
-				if (!$owner) {
346
-					return null;
347
-				} else {
348
-					return $owner->getDisplayName();
349
-				}
350
-			});
351
-
352
-			$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
353
-				return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
354
-			});
355
-			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
356
-				return $node->getSize();
357
-			});
358
-			$propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) {
359
-				return $node->getFileInfo()->getMountPoint()->getMountType();
360
-			});
361
-		}
362
-
363
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
364
-			$propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
365
-				return $this->config->getSystemValue('data-fingerprint', '');
366
-			});
367
-		}
368
-
369
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
370
-			$propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
371
-				/** @var $node \OCA\DAV\Connector\Sabre\File */
372
-				try {
373
-					$directDownloadUrl = $node->getDirectDownload();
374
-					if (isset($directDownloadUrl['url'])) {
375
-						return $directDownloadUrl['url'];
376
-					}
377
-				} catch (StorageNotAvailableException $e) {
378
-					return false;
379
-				} catch (ForbiddenException $e) {
380
-					return false;
381
-				}
382
-				return false;
383
-			});
384
-
385
-			$propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
386
-				$checksum = $node->getChecksum();
387
-				if ($checksum === NULL || $checksum === '') {
388
-					return null;
389
-				}
390
-
391
-				return new ChecksumList($checksum);
392
-			});
393
-
394
-		}
395
-
396
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
397
-			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
398
-				return $node->getSize();
399
-			});
400
-
401
-			$propFind->handle(self::IS_ENCRYPTED_PROPERTYNAME, function() use ($node) {
402
-				return $node->getFileInfo()->isEncrypted() ? '1' : '0';
403
-			});
404
-		}
405
-	}
406
-
407
-	/**
408
-	 * translate Nextcloud permissions to OCM Permissions
409
-	 *
410
-	 * @param $ncPermissions
411
-	 * @return array
412
-	 */
413
-	protected function ncPermissions2ocmPermissions($ncPermissions) {
414
-
415
-		$ocmPermissions = [];
416
-
417
-		if ($ncPermissions & Constants::PERMISSION_SHARE) {
418
-			$ocmPermissions[] = 'share';
419
-		}
420
-
421
-		if ($ncPermissions & Constants::PERMISSION_READ) {
422
-			$ocmPermissions[] = 'read';
423
-		}
424
-
425
-		if (($ncPermissions & Constants::PERMISSION_CREATE) ||
426
-			($ncPermissions & Constants::PERMISSION_UPDATE)) {
427
-			$ocmPermissions[] = 'write';
428
-		}
429
-
430
-		return $ocmPermissions;
431
-
432
-	}
433
-
434
-	/**
435
-	 * Update ownCloud-specific properties
436
-	 *
437
-	 * @param string $path
438
-	 * @param PropPatch $propPatch
439
-	 *
440
-	 * @return void
441
-	 */
442
-	public function handleUpdateProperties($path, PropPatch $propPatch) {
443
-		$node = $this->tree->getNodeForPath($path);
444
-		if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
445
-			return;
446
-		}
447
-
448
-		$propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function($time) use ($node) {
449
-			if (empty($time)) {
450
-				return false;
451
-			}
452
-			$node->touch($time);
453
-			return true;
454
-		});
455
-		$propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($node) {
456
-			if (empty($etag)) {
457
-				return false;
458
-			}
459
-			if ($node->setEtag($etag) !== -1) {
460
-				return true;
461
-			}
462
-			return false;
463
-		});
464
-	}
465
-
466
-	/**
467
-	 * @param string $filePath
468
-	 * @param \Sabre\DAV\INode $node
469
-	 * @throws \Sabre\DAV\Exception\BadRequest
470
-	 */
471
-	public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
472
-		// chunked upload handling
473
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
474
-			list($path, $name) = \Sabre\Uri\split($filePath);
475
-			$info = \OC_FileChunking::decodeName($name);
476
-			if (!empty($info)) {
477
-				$filePath = $path . '/' . $info['name'];
478
-			}
479
-		}
480
-
481
-		// we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
482
-		if (!$this->server->tree->nodeExists($filePath)) {
483
-			return;
484
-		}
485
-		$node = $this->server->tree->getNodeForPath($filePath);
486
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
487
-			$fileId = $node->getFileId();
488
-			if (!is_null($fileId)) {
489
-				$this->server->httpResponse->setHeader('OC-FileId', $fileId);
490
-			}
491
-		}
492
-	}
298
+             */
299
+
300
+            $propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
301
+                return $node->getFileId();
302
+            });
303
+
304
+            $propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
305
+                return $node->getInternalFileId();
306
+            });
307
+
308
+            $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
309
+                $perms = $node->getDavPermissions();
310
+                if ($this->isPublic) {
311
+                    // remove mount information
312
+                    $perms = str_replace(['S', 'M'], '', $perms);
313
+                }
314
+                return $perms;
315
+            });
316
+
317
+            $propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
318
+                return $node->getSharePermissions(
319
+                    $httpRequest->getRawServerValue('PHP_AUTH_USER')
320
+                );
321
+            });
322
+
323
+            $propFind->handle(self::OCM_SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
324
+                $ncPermissions = $node->getSharePermissions(
325
+                    $httpRequest->getRawServerValue('PHP_AUTH_USER')
326
+                );
327
+                $ocmPermissions = $this->ncPermissions2ocmPermissions($ncPermissions);
328
+                return json_encode($ocmPermissions);
329
+            });
330
+
331
+            $propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
332
+                return $node->getETag();
333
+            });
334
+
335
+            $propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
336
+                $owner = $node->getOwner();
337
+                if (!$owner) {
338
+                    return null;
339
+                } else {
340
+                    return $owner->getUID();
341
+                }
342
+            });
343
+            $propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
344
+                $owner = $node->getOwner();
345
+                if (!$owner) {
346
+                    return null;
347
+                } else {
348
+                    return $owner->getDisplayName();
349
+                }
350
+            });
351
+
352
+            $propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
353
+                return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
354
+            });
355
+            $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
356
+                return $node->getSize();
357
+            });
358
+            $propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) {
359
+                return $node->getFileInfo()->getMountPoint()->getMountType();
360
+            });
361
+        }
362
+
363
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
364
+            $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
365
+                return $this->config->getSystemValue('data-fingerprint', '');
366
+            });
367
+        }
368
+
369
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
370
+            $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
371
+                /** @var $node \OCA\DAV\Connector\Sabre\File */
372
+                try {
373
+                    $directDownloadUrl = $node->getDirectDownload();
374
+                    if (isset($directDownloadUrl['url'])) {
375
+                        return $directDownloadUrl['url'];
376
+                    }
377
+                } catch (StorageNotAvailableException $e) {
378
+                    return false;
379
+                } catch (ForbiddenException $e) {
380
+                    return false;
381
+                }
382
+                return false;
383
+            });
384
+
385
+            $propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
386
+                $checksum = $node->getChecksum();
387
+                if ($checksum === NULL || $checksum === '') {
388
+                    return null;
389
+                }
390
+
391
+                return new ChecksumList($checksum);
392
+            });
393
+
394
+        }
395
+
396
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
397
+            $propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
398
+                return $node->getSize();
399
+            });
400
+
401
+            $propFind->handle(self::IS_ENCRYPTED_PROPERTYNAME, function() use ($node) {
402
+                return $node->getFileInfo()->isEncrypted() ? '1' : '0';
403
+            });
404
+        }
405
+    }
406
+
407
+    /**
408
+     * translate Nextcloud permissions to OCM Permissions
409
+     *
410
+     * @param $ncPermissions
411
+     * @return array
412
+     */
413
+    protected function ncPermissions2ocmPermissions($ncPermissions) {
414
+
415
+        $ocmPermissions = [];
416
+
417
+        if ($ncPermissions & Constants::PERMISSION_SHARE) {
418
+            $ocmPermissions[] = 'share';
419
+        }
420
+
421
+        if ($ncPermissions & Constants::PERMISSION_READ) {
422
+            $ocmPermissions[] = 'read';
423
+        }
424
+
425
+        if (($ncPermissions & Constants::PERMISSION_CREATE) ||
426
+            ($ncPermissions & Constants::PERMISSION_UPDATE)) {
427
+            $ocmPermissions[] = 'write';
428
+        }
429
+
430
+        return $ocmPermissions;
431
+
432
+    }
433
+
434
+    /**
435
+     * Update ownCloud-specific properties
436
+     *
437
+     * @param string $path
438
+     * @param PropPatch $propPatch
439
+     *
440
+     * @return void
441
+     */
442
+    public function handleUpdateProperties($path, PropPatch $propPatch) {
443
+        $node = $this->tree->getNodeForPath($path);
444
+        if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
445
+            return;
446
+        }
447
+
448
+        $propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function($time) use ($node) {
449
+            if (empty($time)) {
450
+                return false;
451
+            }
452
+            $node->touch($time);
453
+            return true;
454
+        });
455
+        $propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($node) {
456
+            if (empty($etag)) {
457
+                return false;
458
+            }
459
+            if ($node->setEtag($etag) !== -1) {
460
+                return true;
461
+            }
462
+            return false;
463
+        });
464
+    }
465
+
466
+    /**
467
+     * @param string $filePath
468
+     * @param \Sabre\DAV\INode $node
469
+     * @throws \Sabre\DAV\Exception\BadRequest
470
+     */
471
+    public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
472
+        // chunked upload handling
473
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
474
+            list($path, $name) = \Sabre\Uri\split($filePath);
475
+            $info = \OC_FileChunking::decodeName($name);
476
+            if (!empty($info)) {
477
+                $filePath = $path . '/' . $info['name'];
478
+            }
479
+        }
480
+
481
+        // we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
482
+        if (!$this->server->tree->nodeExists($filePath)) {
483
+            return;
484
+        }
485
+        $node = $this->server->tree->getNodeForPath($filePath);
486
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
487
+            $fileId = $node->getFileId();
488
+            if (!is_null($fileId)) {
489
+                $this->server->httpResponse->setHeader('OC-FileId', $fileId);
490
+            }
491
+        }
492
+    }
493 493
 }
Please login to merge, or discard this patch.
lib/private/Federation/CloudFederationShare.php 1 patch
Indentation   +298 added lines, -298 removed lines patch added patch discarded remove patch
@@ -25,328 +25,328 @@
 block discarded – undo
25 25
 
26 26
 class CloudFederationShare implements ICloudFederationShare {
27 27
 
28
-	private $share = [
29
-		'shareWith' => '',
30
-		'shareType' => '',
31
-		'name' => '',
32
-		'resourceType' => '',
33
-		'description' => '',
34
-		'providerId' => '',
35
-		'owner' => '',
36
-		'ownerDisplayName' => '',
37
-		'sharedBy' => '',
38
-		'sharedByDisplayName' => '',
39
-		'protocol' => []
40
-	];
28
+    private $share = [
29
+        'shareWith' => '',
30
+        'shareType' => '',
31
+        'name' => '',
32
+        'resourceType' => '',
33
+        'description' => '',
34
+        'providerId' => '',
35
+        'owner' => '',
36
+        'ownerDisplayName' => '',
37
+        'sharedBy' => '',
38
+        'sharedByDisplayName' => '',
39
+        'protocol' => []
40
+    ];
41 41
 
42
-	/**
43
-	 * get a CloudFederationShare Object to prepare a share you want to send
44
-	 *
45
-	 * @param string $shareWith
46
-	 * @param string $name resource name (e.g. document.odt)
47
-	 * @param string $description share description (optional)
48
-	 * @param string $providerId resource UID on the provider side
49
-	 * @param string $owner provider specific UID of the user who owns the resource
50
-	 * @param string $ownerDisplayName display name of the user who shared the item
51
-	 * @param string $sharedBy provider specific UID of the user who shared the resource
52
-	 * @param string $sharedByDisplayName display name of the user who shared the resource
53
-	 * @param string $shareType ('group' or 'user' share)
54
-	 * @param string $resourceType ('file', 'calendar',...)
55
-	 * @param string $sharedSecret
56
-	 */
57
-	public function __construct($shareWith = '',
58
-								$name = '',
59
-								$description = '',
60
-								$providerId = '',
61
-								$owner = '',
62
-								$ownerDisplayName = '',
63
-								$sharedBy = '',
64
-								$sharedByDisplayName = '',
65
-								$shareType = '',
66
-								$resourceType = '',
67
-								$sharedSecret = ''
68
-	) {
69
-		$this->setShareWith($shareWith);
70
-		$this->setResourceName($name);
71
-		$this->setDescription($description);
72
-		$this->setProviderId($providerId);
73
-		$this->setOwner($owner);
74
-		$this->setOwnerDisplayName($ownerDisplayName);
75
-		$this->setSharedBy($sharedBy);
76
-		$this->setSharedByDisplayName($sharedByDisplayName);
77
-		$this->setProtocol([
78
-			'name' => 'webdav',
79
-			'options' => [
80
-				'sharedSecret' => $sharedSecret,
81
-				'permissions' => '{http://open-cloud-mesh.org/ns}share-permissions'
82
-			]
83
-		]);
84
-		$this->setShareType($shareType);
85
-		$this->setResourceType($resourceType);
42
+    /**
43
+     * get a CloudFederationShare Object to prepare a share you want to send
44
+     *
45
+     * @param string $shareWith
46
+     * @param string $name resource name (e.g. document.odt)
47
+     * @param string $description share description (optional)
48
+     * @param string $providerId resource UID on the provider side
49
+     * @param string $owner provider specific UID of the user who owns the resource
50
+     * @param string $ownerDisplayName display name of the user who shared the item
51
+     * @param string $sharedBy provider specific UID of the user who shared the resource
52
+     * @param string $sharedByDisplayName display name of the user who shared the resource
53
+     * @param string $shareType ('group' or 'user' share)
54
+     * @param string $resourceType ('file', 'calendar',...)
55
+     * @param string $sharedSecret
56
+     */
57
+    public function __construct($shareWith = '',
58
+                                $name = '',
59
+                                $description = '',
60
+                                $providerId = '',
61
+                                $owner = '',
62
+                                $ownerDisplayName = '',
63
+                                $sharedBy = '',
64
+                                $sharedByDisplayName = '',
65
+                                $shareType = '',
66
+                                $resourceType = '',
67
+                                $sharedSecret = ''
68
+    ) {
69
+        $this->setShareWith($shareWith);
70
+        $this->setResourceName($name);
71
+        $this->setDescription($description);
72
+        $this->setProviderId($providerId);
73
+        $this->setOwner($owner);
74
+        $this->setOwnerDisplayName($ownerDisplayName);
75
+        $this->setSharedBy($sharedBy);
76
+        $this->setSharedByDisplayName($sharedByDisplayName);
77
+        $this->setProtocol([
78
+            'name' => 'webdav',
79
+            'options' => [
80
+                'sharedSecret' => $sharedSecret,
81
+                'permissions' => '{http://open-cloud-mesh.org/ns}share-permissions'
82
+            ]
83
+        ]);
84
+        $this->setShareType($shareType);
85
+        $this->setResourceType($resourceType);
86 86
 
87
-	}
87
+    }
88 88
 
89
-	/**
90
-	 * set uid of the recipient
91
-	 *
92
-	 * @param string $user
93
-	 *
94
-	 * @since 14.0.0
95
-	 */
96
-	public function setShareWith($user) {
97
-		$this->share['shareWith'] = $user;
98
-	}
89
+    /**
90
+     * set uid of the recipient
91
+     *
92
+     * @param string $user
93
+     *
94
+     * @since 14.0.0
95
+     */
96
+    public function setShareWith($user) {
97
+        $this->share['shareWith'] = $user;
98
+    }
99 99
 
100
-	/**
101
-	 * set resource name (e.g. document.odt)
102
-	 *
103
-	 * @param string $name
104
-	 *
105
-	 * @since 14.0.0
106
-	 */
107
-	public function setResourceName($name) {
108
-		$this->share['name'] = $name;
109
-	}
100
+    /**
101
+     * set resource name (e.g. document.odt)
102
+     *
103
+     * @param string $name
104
+     *
105
+     * @since 14.0.0
106
+     */
107
+    public function setResourceName($name) {
108
+        $this->share['name'] = $name;
109
+    }
110 110
 
111
-	/**
112
-	 * set resource type (e.g. file, calendar, contact,...)
113
-	 *
114
-	 * @param string $resourceType
115
-	 *
116
-	 * @since 14.0.0
117
-	 */
118
-	public function setResourceType($resourceType) {
119
-		$this->share['resourceType'] = $resourceType;
120
-	}
111
+    /**
112
+     * set resource type (e.g. file, calendar, contact,...)
113
+     *
114
+     * @param string $resourceType
115
+     *
116
+     * @since 14.0.0
117
+     */
118
+    public function setResourceType($resourceType) {
119
+        $this->share['resourceType'] = $resourceType;
120
+    }
121 121
 
122
-	/**
123
-	 * set resource description (optional)
124
-	 *
125
-	 * @param string $description
126
-	 *
127
-	 * @since 14.0.0
128
-	 */
129
-	public function setDescription($description) {
130
-		$this->share['description'] = $description;
131
-	}
122
+    /**
123
+     * set resource description (optional)
124
+     *
125
+     * @param string $description
126
+     *
127
+     * @since 14.0.0
128
+     */
129
+    public function setDescription($description) {
130
+        $this->share['description'] = $description;
131
+    }
132 132
 
133
-	/**
134
-	 * set provider ID (e.g. file ID)
135
-	 *
136
-	 * @param string $providerId
137
-	 *
138
-	 * @since 14.0.0
139
-	 */
140
-	public function setProviderId($providerId) {
141
-		$this->share['providerId'] = $providerId;
142
-	}
133
+    /**
134
+     * set provider ID (e.g. file ID)
135
+     *
136
+     * @param string $providerId
137
+     *
138
+     * @since 14.0.0
139
+     */
140
+    public function setProviderId($providerId) {
141
+        $this->share['providerId'] = $providerId;
142
+    }
143 143
 
144
-	/**
145
-	 * set owner UID
146
-	 *
147
-	 * @param string $owner
148
-	 *
149
-	 * @since 14.0.0
150
-	 */
151
-	public function setOwner($owner) {
152
-		$this->share['owner'] = $owner;
153
-	}
144
+    /**
145
+     * set owner UID
146
+     *
147
+     * @param string $owner
148
+     *
149
+     * @since 14.0.0
150
+     */
151
+    public function setOwner($owner) {
152
+        $this->share['owner'] = $owner;
153
+    }
154 154
 
155
-	/**
156
-	 * set owner display name
157
-	 *
158
-	 * @param string $ownerDisplayName
159
-	 *
160
-	 * @since 14.0.0
161
-	 */
162
-	public function setOwnerDisplayName($ownerDisplayName) {
163
-		$this->share['ownerDisplayName'] = $ownerDisplayName;
164
-	}
155
+    /**
156
+     * set owner display name
157
+     *
158
+     * @param string $ownerDisplayName
159
+     *
160
+     * @since 14.0.0
161
+     */
162
+    public function setOwnerDisplayName($ownerDisplayName) {
163
+        $this->share['ownerDisplayName'] = $ownerDisplayName;
164
+    }
165 165
 
166
-	/**
167
-	 * set UID of the user who sends the share
168
-	 *
169
-	 * @param string $sharedBy
170
-	 *
171
-	 * @since 14.0.0
172
-	 */
173
-	public function setSharedBy($sharedBy) {
174
-		$this->share['sharedBy'] = $sharedBy;
175
-	}
166
+    /**
167
+     * set UID of the user who sends the share
168
+     *
169
+     * @param string $sharedBy
170
+     *
171
+     * @since 14.0.0
172
+     */
173
+    public function setSharedBy($sharedBy) {
174
+        $this->share['sharedBy'] = $sharedBy;
175
+    }
176 176
 
177
-	/**
178
-	 * set display name of the user who sends the share
179
-	 *
180
-	 * @param $sharedByDisplayName
181
-	 *
182
-	 * @since 14.0.0
183
-	 */
184
-	public function setSharedByDisplayName($sharedByDisplayName) {
185
-		$this->share['sharedByDisplayName'] = $sharedByDisplayName;
186
-	}
177
+    /**
178
+     * set display name of the user who sends the share
179
+     *
180
+     * @param $sharedByDisplayName
181
+     *
182
+     * @since 14.0.0
183
+     */
184
+    public function setSharedByDisplayName($sharedByDisplayName) {
185
+        $this->share['sharedByDisplayName'] = $sharedByDisplayName;
186
+    }
187 187
 
188
-	/**
189
-	 * set protocol specification
190
-	 *
191
-	 * @param array $protocol
192
-	 *
193
-	 * @since 14.0.0
194
-	 */
195
-	public function setProtocol(array $protocol) {
196
-		$this->share['protocol'] = $protocol;
197
-	}
188
+    /**
189
+     * set protocol specification
190
+     *
191
+     * @param array $protocol
192
+     *
193
+     * @since 14.0.0
194
+     */
195
+    public function setProtocol(array $protocol) {
196
+        $this->share['protocol'] = $protocol;
197
+    }
198 198
 
199
-	/**
200
-	 * share type (group or user)
201
-	 *
202
-	 * @param string $shareType
203
-	 *
204
-	 * @since 14.0.0
205
-	 */
206
-	public function setShareType($shareType) {
207
-		$this->share['shareType'] = $shareType;
208
-	}
199
+    /**
200
+     * share type (group or user)
201
+     *
202
+     * @param string $shareType
203
+     *
204
+     * @since 14.0.0
205
+     */
206
+    public function setShareType($shareType) {
207
+        $this->share['shareType'] = $shareType;
208
+    }
209 209
 
210
-	/**
211
-	 * get the whole share, ready to send out
212
-	 *
213
-	 * @return array
214
-	 *
215
-	 * @since 14.0.0
216
-	 */
217
-	public function getShare() {
218
-		return $this->share;
219
-	}
210
+    /**
211
+     * get the whole share, ready to send out
212
+     *
213
+     * @return array
214
+     *
215
+     * @since 14.0.0
216
+     */
217
+    public function getShare() {
218
+        return $this->share;
219
+    }
220 220
 
221
-	/**
222
-	 * get uid of the recipient
223
-	 *
224
-	 * @return string
225
-	 *
226
-	 * @since 14.0.0
227
-	 */
228
-	public function getShareWith() {
229
-		return $this->share['shareWith'];
230
-	}
221
+    /**
222
+     * get uid of the recipient
223
+     *
224
+     * @return string
225
+     *
226
+     * @since 14.0.0
227
+     */
228
+    public function getShareWith() {
229
+        return $this->share['shareWith'];
230
+    }
231 231
 
232
-	/**
233
-	 * get resource name (e.g. file, calendar, contact,...)
234
-	 *
235
-	 * @return string
236
-	 *
237
-	 * @since 14.0.0
238
-	 */
239
-	public function getResourceName() {
240
-		return $this->share['name'];
241
-	}
232
+    /**
233
+     * get resource name (e.g. file, calendar, contact,...)
234
+     *
235
+     * @return string
236
+     *
237
+     * @since 14.0.0
238
+     */
239
+    public function getResourceName() {
240
+        return $this->share['name'];
241
+    }
242 242
 
243
-	/**
244
-	 * get resource type (e.g. file, calendar, contact,...)
245
-	 *
246
-	 * @return string
247
-	 *
248
-	 * @since 14.0.0
249
-	 */
250
-	public function getResourceType() {
251
-		return $this->share['resourceType'];
252
-	}
243
+    /**
244
+     * get resource type (e.g. file, calendar, contact,...)
245
+     *
246
+     * @return string
247
+     *
248
+     * @since 14.0.0
249
+     */
250
+    public function getResourceType() {
251
+        return $this->share['resourceType'];
252
+    }
253 253
 
254
-	/**
255
-	 * get resource description (optional)
256
-	 *
257
-	 * @return string
258
-	 *
259
-	 * @since 14.0.0
260
-	 */
261
-	public function getDescription() {
262
-		return $this->share['description'];
263
-	}
254
+    /**
255
+     * get resource description (optional)
256
+     *
257
+     * @return string
258
+     *
259
+     * @since 14.0.0
260
+     */
261
+    public function getDescription() {
262
+        return $this->share['description'];
263
+    }
264 264
 
265
-	/**
266
-	 * get provider ID (e.g. file ID)
267
-	 *
268
-	 * @return string
269
-	 *
270
-	 * @since 14.0.0
271
-	 */
272
-	public function getProviderId() {
273
-		return $this->share['providerId'];
274
-	}
265
+    /**
266
+     * get provider ID (e.g. file ID)
267
+     *
268
+     * @return string
269
+     *
270
+     * @since 14.0.0
271
+     */
272
+    public function getProviderId() {
273
+        return $this->share['providerId'];
274
+    }
275 275
 
276
-	/**
277
-	 * get owner UID
278
-	 *
279
-	 * @return string
280
-	 *
281
-	 * @since 14.0.0
282
-	 */
283
-	public function getOwner() {
284
-		return $this->share['owner'];
285
-	}
276
+    /**
277
+     * get owner UID
278
+     *
279
+     * @return string
280
+     *
281
+     * @since 14.0.0
282
+     */
283
+    public function getOwner() {
284
+        return $this->share['owner'];
285
+    }
286 286
 
287
-	/**
288
-	 * get owner display name
289
-	 *
290
-	 * @return string
291
-	 *
292
-	 * @since 14.0.0
293
-	 */
294
-	public function getOwnerDisplayName() {
295
-		return $this->share['ownerDisplayName'];
296
-	}
287
+    /**
288
+     * get owner display name
289
+     *
290
+     * @return string
291
+     *
292
+     * @since 14.0.0
293
+     */
294
+    public function getOwnerDisplayName() {
295
+        return $this->share['ownerDisplayName'];
296
+    }
297 297
 
298
-	/**
299
-	 * get UID of the user who sends the share
300
-	 *
301
-	 * @return string
302
-	 *
303
-	 * @since 14.0.0
304
-	 */
305
-	public function getSharedBy() {
306
-		return $this->share['sharedBy'];
307
-	}
298
+    /**
299
+     * get UID of the user who sends the share
300
+     *
301
+     * @return string
302
+     *
303
+     * @since 14.0.0
304
+     */
305
+    public function getSharedBy() {
306
+        return $this->share['sharedBy'];
307
+    }
308 308
 
309
-	/**
310
-	 * get display name of the user who sends the share
311
-	 *
312
-	 * @return string
313
-	 *
314
-	 * @since 14.0.0
315
-	 */
316
-	public function getSharedByDisplayName() {
317
-		return $this->share['sharedByDisplayName'];
318
-	}
309
+    /**
310
+     * get display name of the user who sends the share
311
+     *
312
+     * @return string
313
+     *
314
+     * @since 14.0.0
315
+     */
316
+    public function getSharedByDisplayName() {
317
+        return $this->share['sharedByDisplayName'];
318
+    }
319 319
 
320
-	/**
321
-	 * get share type (group or user)
322
-	 *
323
-	 * @return string
324
-	 *
325
-	 * @since 14.0.0
326
-	 */
327
-	public function getShareType() {
328
-		return $this->share['shareType'];
329
-	}
320
+    /**
321
+     * get share type (group or user)
322
+     *
323
+     * @return string
324
+     *
325
+     * @since 14.0.0
326
+     */
327
+    public function getShareType() {
328
+        return $this->share['shareType'];
329
+    }
330 330
 
331
-	/**
332
-	 * get share Secret
333
-	 *
334
-	 * @return string
335
-	 *
336
-	 * @since 14.0.0
337
-	 */
338
-	public function getShareSecret() {
339
-		return $this->share['protocol']['options']['sharedSecret'];
340
-	}
331
+    /**
332
+     * get share Secret
333
+     *
334
+     * @return string
335
+     *
336
+     * @since 14.0.0
337
+     */
338
+    public function getShareSecret() {
339
+        return $this->share['protocol']['options']['sharedSecret'];
340
+    }
341 341
 
342
-	/**
343
-	 * get protocol specification
344
-	 *
345
-	 * @return array
346
-	 *
347
-	 * @since 14.0.0
348
-	 */
349
-	public function getProtocol() {
350
-		return $this->share['protocol'];
351
-	}
342
+    /**
343
+     * get protocol specification
344
+     *
345
+     * @return array
346
+     *
347
+     * @since 14.0.0
348
+     */
349
+    public function getProtocol() {
350
+        return $this->share['protocol'];
351
+    }
352 352
 }
Please login to merge, or discard this patch.