Completed
Pull Request — master (#9345)
by Björn
145:00 queued 125:48
created
apps/federatedfilesharing/lib/AppInfo/Application.php 1 patch
Indentation   +102 added lines, -102 removed lines patch added patch discarded remove patch
@@ -39,114 +39,114 @@
 block discarded – undo
39 39
 
40 40
 class Application extends App {
41 41
 
42
-	/** @var FederatedShareProvider */
43
-	protected $federatedShareProvider;
42
+    /** @var FederatedShareProvider */
43
+    protected $federatedShareProvider;
44 44
 
45
-	public function __construct() {
46
-		parent::__construct('federatedfilesharing');
45
+    public function __construct() {
46
+        parent::__construct('federatedfilesharing');
47 47
 
48
-		$container = $this->getContainer();
49
-		$server = $container->getServer();
48
+        $container = $this->getContainer();
49
+        $server = $container->getServer();
50 50
 
51
-		$cloudFederationManager = $server->getCloudFederationProviderManager();
52
-		$cloudFederationManager->addCloudFederationProvider('file',
53
-			'Federated Files Sharing',
54
-			function() use ($container) {
55
-				$server = $container->getServer();
56
-				return new CloudFederationProviderFiles(
57
-					$server->getAppManager(),
58
-					$server->query(FederatedShareProvider::class),
59
-					$server->query(AddressHandler::class),
60
-					$server->getLogger(),
61
-					$server->getUserManager(),
62
-					$server->getCloudIdManager(),
63
-					$server->getActivityManager(),
64
-					$server->getNotificationManager(),
65
-					$server->getURLGenerator(),
66
-					$server->getCloudFederationFactory(),
67
-					$server->getCloudFederationProviderManager(),
68
-					$server->getDatabaseConnection()
69
-				);
70
-			});
51
+        $cloudFederationManager = $server->getCloudFederationProviderManager();
52
+        $cloudFederationManager->addCloudFederationProvider('file',
53
+            'Federated Files Sharing',
54
+            function() use ($container) {
55
+                $server = $container->getServer();
56
+                return new CloudFederationProviderFiles(
57
+                    $server->getAppManager(),
58
+                    $server->query(FederatedShareProvider::class),
59
+                    $server->query(AddressHandler::class),
60
+                    $server->getLogger(),
61
+                    $server->getUserManager(),
62
+                    $server->getCloudIdManager(),
63
+                    $server->getActivityManager(),
64
+                    $server->getNotificationManager(),
65
+                    $server->getURLGenerator(),
66
+                    $server->getCloudFederationFactory(),
67
+                    $server->getCloudFederationProviderManager(),
68
+                    $server->getDatabaseConnection()
69
+                );
70
+            });
71 71
 
72
-		$container->registerService('RequestHandlerController', function(SimpleContainer $c) use ($server) {
73
-			$addressHandler = new AddressHandler(
74
-				$server->getURLGenerator(),
75
-				$server->getL10N('federatedfilesharing'),
76
-				$server->getCloudIdManager()
77
-			);
78
-			$notification = new Notifications(
79
-				$addressHandler,
80
-				$server->getHTTPClientService(),
81
-				$server->query(\OCP\OCS\IDiscoveryService::class),
82
-				\OC::$server->getJobList(),
83
-				\OC::$server->getCloudFederationProviderManager(),
84
-				\OC::$server->getCloudFederationFactory()
85
-			);
86
-			return new RequestHandlerController(
87
-				$c->query('AppName'),
88
-				$server->getRequest(),
89
-				$this->getFederatedShareProvider(),
90
-				$server->getDatabaseConnection(),
91
-				$server->getShareManager(),
92
-				$notification,
93
-				$addressHandler,
94
-				$server->getUserManager(),
95
-				$server->getCloudIdManager(),
96
-				$server->getLogger(),
97
-				$server->getCloudFederationFactory(),
98
-				$server->getCloudFederationProviderManager()
99
-			);
100
-		});
101
-	}
72
+        $container->registerService('RequestHandlerController', function(SimpleContainer $c) use ($server) {
73
+            $addressHandler = new AddressHandler(
74
+                $server->getURLGenerator(),
75
+                $server->getL10N('federatedfilesharing'),
76
+                $server->getCloudIdManager()
77
+            );
78
+            $notification = new Notifications(
79
+                $addressHandler,
80
+                $server->getHTTPClientService(),
81
+                $server->query(\OCP\OCS\IDiscoveryService::class),
82
+                \OC::$server->getJobList(),
83
+                \OC::$server->getCloudFederationProviderManager(),
84
+                \OC::$server->getCloudFederationFactory()
85
+            );
86
+            return new RequestHandlerController(
87
+                $c->query('AppName'),
88
+                $server->getRequest(),
89
+                $this->getFederatedShareProvider(),
90
+                $server->getDatabaseConnection(),
91
+                $server->getShareManager(),
92
+                $notification,
93
+                $addressHandler,
94
+                $server->getUserManager(),
95
+                $server->getCloudIdManager(),
96
+                $server->getLogger(),
97
+                $server->getCloudFederationFactory(),
98
+                $server->getCloudFederationProviderManager()
99
+            );
100
+        });
101
+    }
102 102
 
103
-	/**
104
-	 * get instance of federated share provider
105
-	 *
106
-	 * @return FederatedShareProvider
107
-	 */
108
-	public function getFederatedShareProvider() {
109
-		if ($this->federatedShareProvider === null) {
110
-			$this->initFederatedShareProvider();
111
-		}
112
-		return $this->federatedShareProvider;
113
-	}
103
+    /**
104
+     * get instance of federated share provider
105
+     *
106
+     * @return FederatedShareProvider
107
+     */
108
+    public function getFederatedShareProvider() {
109
+        if ($this->federatedShareProvider === null) {
110
+            $this->initFederatedShareProvider();
111
+        }
112
+        return $this->federatedShareProvider;
113
+    }
114 114
 
115
-	/**
116
-	 * initialize federated share provider
117
-	 */
118
-	protected function initFederatedShareProvider() {
119
-		$c = $this->getContainer();
120
-		$addressHandler = new \OCA\FederatedFileSharing\AddressHandler(
121
-			\OC::$server->getURLGenerator(),
122
-			\OC::$server->getL10N('federatedfilesharing'),
123
-			\OC::$server->getCloudIdManager()
124
-		);
125
-		$notifications = new \OCA\FederatedFileSharing\Notifications(
126
-			$addressHandler,
127
-			\OC::$server->getHTTPClientService(),
128
-			\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
129
-			\OC::$server->getJobList(),
130
-			\OC::$server->getCloudFederationProviderManager(),
131
-			\OC::$server->getCloudFederationFactory()
132
-		);
133
-		$tokenHandler = new \OCA\FederatedFileSharing\TokenHandler(
134
-			\OC::$server->getSecureRandom()
135
-		);
115
+    /**
116
+     * initialize federated share provider
117
+     */
118
+    protected function initFederatedShareProvider() {
119
+        $c = $this->getContainer();
120
+        $addressHandler = new \OCA\FederatedFileSharing\AddressHandler(
121
+            \OC::$server->getURLGenerator(),
122
+            \OC::$server->getL10N('federatedfilesharing'),
123
+            \OC::$server->getCloudIdManager()
124
+        );
125
+        $notifications = new \OCA\FederatedFileSharing\Notifications(
126
+            $addressHandler,
127
+            \OC::$server->getHTTPClientService(),
128
+            \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
129
+            \OC::$server->getJobList(),
130
+            \OC::$server->getCloudFederationProviderManager(),
131
+            \OC::$server->getCloudFederationFactory()
132
+        );
133
+        $tokenHandler = new \OCA\FederatedFileSharing\TokenHandler(
134
+            \OC::$server->getSecureRandom()
135
+        );
136 136
 
137
-		$this->federatedShareProvider = new \OCA\FederatedFileSharing\FederatedShareProvider(
138
-			\OC::$server->getDatabaseConnection(),
139
-			$addressHandler,
140
-			$notifications,
141
-			$tokenHandler,
142
-			\OC::$server->getL10N('federatedfilesharing'),
143
-			\OC::$server->getLogger(),
144
-			\OC::$server->getLazyRootFolder(),
145
-			\OC::$server->getConfig(),
146
-			\OC::$server->getUserManager(),
147
-			\OC::$server->getCloudIdManager(),
148
-			$c->query(IConfig::class)
149
-		);
150
-	}
137
+        $this->federatedShareProvider = new \OCA\FederatedFileSharing\FederatedShareProvider(
138
+            \OC::$server->getDatabaseConnection(),
139
+            $addressHandler,
140
+            $notifications,
141
+            $tokenHandler,
142
+            \OC::$server->getL10N('federatedfilesharing'),
143
+            \OC::$server->getLogger(),
144
+            \OC::$server->getLazyRootFolder(),
145
+            \OC::$server->getConfig(),
146
+            \OC::$server->getUserManager(),
147
+            \OC::$server->getCloudIdManager(),
148
+            $c->query(IConfig::class)
149
+        );
150
+    }
151 151
 
152 152
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/Controller/RequestHandlerController.php 1 patch
Indentation   +468 added lines, -468 removed lines patch added patch discarded remove patch
@@ -56,472 +56,472 @@
 block discarded – undo
56 56
 
57 57
 class RequestHandlerController extends OCSController {
58 58
 
59
-	/** @var FederatedShareProvider */
60
-	private $federatedShareProvider;
61
-
62
-	/** @var IDBConnection */
63
-	private $connection;
64
-
65
-	/** @var Share\IManager */
66
-	private $shareManager;
67
-
68
-	/** @var Notifications */
69
-	private $notifications;
70
-
71
-	/** @var AddressHandler */
72
-	private $addressHandler;
73
-
74
-	/** @var  IUserManager */
75
-	private $userManager;
76
-
77
-	/** @var string */
78
-	private $shareTable = 'share';
79
-
80
-	/** @var ICloudIdManager */
81
-	private $cloudIdManager;
82
-
83
-	/** @var ILogger */
84
-	private $logger;
85
-
86
-	/** @var ICloudFederationFactory */
87
-	private $cloudFederationFactory;
88
-
89
-	/** @var ICloudFederationProviderManager */
90
-	private $cloudFederationProviderManager;
91
-
92
-	/**
93
-	 * Server2Server constructor.
94
-	 *
95
-	 * @param string $appName
96
-	 * @param IRequest $request
97
-	 * @param FederatedShareProvider $federatedShareProvider
98
-	 * @param IDBConnection $connection
99
-	 * @param Share\IManager $shareManager
100
-	 * @param Notifications $notifications
101
-	 * @param AddressHandler $addressHandler
102
-	 * @param IUserManager $userManager
103
-	 * @param ICloudIdManager $cloudIdManager
104
-	 * @param ILogger $logger
105
-	 * @param ICloudFederationFactory $cloudFederationFactory
106
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
107
-	 */
108
-	public function __construct($appName,
109
-								IRequest $request,
110
-								FederatedShareProvider $federatedShareProvider,
111
-								IDBConnection $connection,
112
-								Share\IManager $shareManager,
113
-								Notifications $notifications,
114
-								AddressHandler $addressHandler,
115
-								IUserManager $userManager,
116
-								ICloudIdManager $cloudIdManager,
117
-								ILogger $logger,
118
-								ICloudFederationFactory $cloudFederationFactory,
119
-								ICloudFederationProviderManager $cloudFederationProviderManager
120
-	) {
121
-		parent::__construct($appName, $request);
122
-
123
-		$this->federatedShareProvider = $federatedShareProvider;
124
-		$this->connection = $connection;
125
-		$this->shareManager = $shareManager;
126
-		$this->notifications = $notifications;
127
-		$this->addressHandler = $addressHandler;
128
-		$this->userManager = $userManager;
129
-		$this->cloudIdManager = $cloudIdManager;
130
-		$this->logger = $logger;
131
-		$this->cloudFederationFactory = $cloudFederationFactory;
132
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
133
-	}
134
-
135
-	/**
136
-	 * @NoCSRFRequired
137
-	 * @PublicPage
138
-	 *
139
-	 * create a new share
140
-	 *
141
-	 * @return Http\DataResponse
142
-	 * @throws OCSException
143
-	 */
144
-	public function createShare() {
145
-
146
-		$remote = isset($_POST['remote']) ? $_POST['remote'] : null;
147
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
148
-		$name = isset($_POST['name']) ? $_POST['name'] : null;
149
-		$owner = isset($_POST['owner']) ? $_POST['owner'] : null;
150
-		$sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null;
151
-		$shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
152
-		$remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
153
-		$sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null;
154
-		$ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null;
155
-
156
-		if ($ownerFederatedId === null) {
157
-			$ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId();
158
-		}
159
-		// if the owner of the share and the initiator are the same user
160
-		// we also complete the federated share ID for the initiator
161
-		if ($sharedByFederatedId === null && $owner === $sharedBy) {
162
-			$sharedByFederatedId = $ownerFederatedId;
163
-		}
164
-
165
-		$share = $this->cloudFederationFactory->getCloudFederationShare(
166
-			$shareWith,
167
-			$name,
168
-			'',
169
-			$remoteId,
170
-			$ownerFederatedId,
171
-			$owner,
172
-			$sharedByFederatedId,
173
-			$sharedBy,
174
-			$token,
175
-			'user',
176
-			'file'
177
-		);
178
-
179
-		try {
180
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
181
-			$provider->shareReceived($share);
182
-		} catch (ProviderDoesNotExistsException $e) {
183
-			throw new OCSException('Server does not support federated cloud sharing', 503);
184
-		} catch (ProviderCouldNotAddShareException $e) {
185
-			throw new OCSException($e->getMessage(), $e->getCode());
186
-		} catch (\Exception $e) {
187
-			throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
188
-		}
189
-
190
-		return new Http\DataResponse();
191
-	}
192
-
193
-	/**
194
-	 * @NoCSRFRequired
195
-	 * @PublicPage
196
-	 *
197
-	 * create re-share on behalf of another user
198
-	 *
199
-	 * @param int $id
200
-	 * @return Http\DataResponse
201
-	 * @throws OCSBadRequestException
202
-	 * @throws OCSForbiddenException
203
-	 * @throws OCSNotFoundException
204
-	 */
205
-	public function reShare($id) {
206
-
207
-		$token = $this->request->getParam('token', null);
208
-		$shareWith = $this->request->getParam('shareWith', null);
209
-		$permission = (int)$this->request->getParam('permission', null);
210
-		$remoteId = (int)$this->request->getParam('remoteId', null);
211
-
212
-		if ($id === null ||
213
-			$token === null ||
214
-			$shareWith === null ||
215
-			$permission === null ||
216
-			$remoteId === null
217
-		) {
218
-			throw new OCSBadRequestException();
219
-		}
220
-
221
-		$notification = [
222
-			'sharedSecret' => $token,
223
-			'shareWith' => $shareWith,
224
-			'senderId' => $remoteId,
225
-			'message' => 'Recipient of a share ask the owner to reshare the file'
226
-		];
227
-
228
-		try {
229
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
230
-			list($newToken, $localId) = $provider->notificationReceived('REQUEST_RESHARE', $id, $notification);
231
-			return new Http\DataResponse([
232
-				'token' => $newToken,
233
-				'remoteId' => $localId
234
-			]);
235
-		} catch (ProviderDoesNotExistsException $e) {
236
-			throw new OCSException('Server does not support federated cloud sharing', 503);
237
-		} catch (ShareNotFoundException $e) {
238
-			$this->logger->debug('Share not found: ' . $e->getMessage());
239
-		} catch (ProviderCouldNotAddShareException $e) {
240
-			$this->logger->debug('Could not add reshare: ' . $e->getMessage());
241
-			throw new OCSForbiddenException();
242
-		} catch (\Exception $e) {
243
-			$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
244
-		}
245
-
246
-		throw new OCSBadRequestException();
247
-	}
248
-
249
-
250
-	/**
251
-	 * @NoCSRFRequired
252
-	 * @PublicPage
253
-	 *
254
-	 * accept server-to-server share
255
-	 *
256
-	 * @param int $id
257
-	 * @return Http\DataResponse
258
-	 * @throws OCSException
259
-	 * @throws Share\Exceptions\ShareNotFound
260
-	 * @throws \OC\HintException
261
-	 */
262
-	public function acceptShare($id) {
263
-
264
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
265
-
266
-		$notification = [
267
-			'sharedSecret' => $token,
268
-			'message' => 'Recipient accept the share'
269
-		];
270
-
271
-		try {
272
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
273
-			$provider->notificationReceived('SHARE_ACCEPTED', $id, $notification);
274
-		} catch (ProviderDoesNotExistsException $e) {
275
-			throw new OCSException('Server does not support federated cloud sharing', 503);
276
-		} catch (ShareNotFoundException $e) {
277
-			$this->logger->debug('Share not found: ' . $e->getMessage());
278
-		} catch (\Exception $e) {
279
-			$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
280
-		}
281
-
282
-		return new Http\DataResponse();
283
-	}
284
-
285
-	/**
286
-	 * @NoCSRFRequired
287
-	 * @PublicPage
288
-	 *
289
-	 * decline server-to-server share
290
-	 *
291
-	 * @param int $id
292
-	 * @return Http\DataResponse
293
-	 * @throws OCSException
294
-	 */
295
-	public function declineShare($id) {
296
-
297
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
298
-
299
-		$notification = [
300
-			'sharedSecret' => $token,
301
-			'message' => 'Recipient declined the share'
302
-		];
303
-
304
-		try {
305
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
306
-			$provider->notificationReceived('SHARE_DECLINED', $id, $notification);
307
-		} catch (ProviderDoesNotExistsException $e) {
308
-			throw new OCSException('Server does not support federated cloud sharing', 503);
309
-		} catch (ShareNotFoundException $e) {
310
-			$this->logger->debug('Share not found: ' . $e->getMessage());
311
-		} catch (\Exception $e) {
312
-			$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
313
-		}
314
-
315
-		return new Http\DataResponse();
316
-	}
317
-
318
-	/**
319
-	 * @NoCSRFRequired
320
-	 * @PublicPage
321
-	 *
322
-	 * remove server-to-server share if it was unshared by the owner
323
-	 *
324
-	 * @param int $id
325
-	 * @return Http\DataResponse
326
-	 * @throws OCSException
327
-	 */
328
-	public function unshare($id) {
329
-
330
-		if (!$this->isS2SEnabled()) {
331
-			throw new OCSException('Server does not support federated cloud sharing', 503);
332
-		}
333
-
334
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
335
-
336
-		try {
337
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
338
-			$notification = ['sharedSecret' => $token];
339
-			$provider->notificationReceived('SHARE_UNSHARED', $id, $notification);
340
-		} catch (\Exception $e) {
341
-			$this->logger->debug('processing unshare notification failed: ' . $e->getMessage());
342
-		}
343
-
344
-		return new Http\DataResponse();
345
-	}
346
-
347
-	private function cleanupRemote($remote) {
348
-		$remote = substr($remote, strpos($remote, '://') + 3);
349
-
350
-		return rtrim($remote, '/');
351
-	}
352
-
353
-
354
-	/**
355
-	 * @NoCSRFRequired
356
-	 * @PublicPage
357
-	 *
358
-	 * federated share was revoked, either by the owner or the re-sharer
359
-	 *
360
-	 * @param int $id
361
-	 * @return Http\DataResponse
362
-	 * @throws OCSBadRequestException
363
-	 */
364
-	public function revoke($id) {
365
-
366
-		$token = $this->request->getParam('token');
367
-
368
-		$notification = $this->cloudFederationFactory->getCloudFederationNotification();
369
-		$notification->setMessage(['sharedSecret' => $token]);
370
-
371
-		try {
372
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
373
-			$provider->notificationReceived('SHARE_UNSHARE', $id, $notification);
374
-			return new Http\DataResponse();
375
-		} catch (\Exception $e) {
376
-			throw new OCSBadRequestException();
377
-		}
378
-
379
-	}
380
-
381
-	/**
382
-	 * get share
383
-	 *
384
-	 * @param int $id
385
-	 * @param string $token
386
-	 * @return array|bool
387
-	 */
388
-	protected function getShare($id, $token) {
389
-		$query = $this->connection->getQueryBuilder();
390
-		$query->select('*')->from($this->shareTable)
391
-			->where($query->expr()->eq('token', $query->createNamedParameter($token)))
392
-			->andWhere($query->expr()->eq('share_type', $query->createNamedParameter(FederatedShareProvider::SHARE_TYPE_REMOTE)))
393
-			->andWhere($query->expr()->eq('id', $query->createNamedParameter($id)));
394
-
395
-		$result = $query->execute()->fetchAll();
396
-
397
-		if (!empty($result) && isset($result[0])) {
398
-			return $result[0];
399
-		}
400
-
401
-		return false;
402
-	}
403
-
404
-	/**
405
-	 * get file
406
-	 *
407
-	 * @param string $user
408
-	 * @param int $fileSource
409
-	 * @return array with internal path of the file and a absolute link to it
410
-	 */
411
-	private function getFile($user, $fileSource) {
412
-		\OC_Util::setupFS($user);
413
-
414
-		try {
415
-			$file = \OC\Files\Filesystem::getPath($fileSource);
416
-		} catch (NotFoundException $e) {
417
-			$file = null;
418
-		}
419
-		$args = \OC\Files\Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
420
-		$link = \OCP\Util::linkToAbsolute('files', 'index.php', $args);
421
-
422
-		return array($file, $link);
423
-
424
-	}
425
-
426
-	/**
427
-	 * check if server-to-server sharing is enabled
428
-	 *
429
-	 * @param bool $incoming
430
-	 * @return bool
431
-	 */
432
-	private function isS2SEnabled($incoming = false) {
433
-
434
-		$result = \OCP\App::isEnabled('files_sharing');
435
-
436
-		if ($incoming) {
437
-			$result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
438
-		} else {
439
-			$result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
440
-		}
441
-
442
-		return $result;
443
-	}
444
-
445
-	/**
446
-	 * @NoCSRFRequired
447
-	 * @PublicPage
448
-	 *
449
-	 * update share information to keep federated re-shares in sync
450
-	 *
451
-	 * @param int $id
452
-	 * @return Http\DataResponse
453
-	 * @throws OCSBadRequestException
454
-	 */
455
-	public function updatePermissions($id) {
456
-		$token = $this->request->getParam('token', null);
457
-		$permissions = $this->request->getParam('permissions', null);
458
-
459
-		try {
460
-			$share = $this->federatedShareProvider->getShareById($id);
461
-		} catch (Share\Exceptions\ShareNotFound $e) {
462
-			throw new OCSBadRequestException();
463
-		}
464
-
465
-		$validPermission = ctype_digit($permissions);
466
-		$validToken = $this->verifyShare($share, $token);
467
-		if ($validPermission && $validToken) {
468
-			$this->updatePermissionsInDatabase($share, (int)$permissions);
469
-		} else {
470
-			throw new OCSBadRequestException();
471
-		}
472
-
473
-		return new Http\DataResponse();
474
-	}
475
-
476
-	/**
477
-	 * update permissions in database
478
-	 *
479
-	 * @param IShare $share
480
-	 * @param int $permissions
481
-	 */
482
-	protected function updatePermissionsInDatabase(IShare $share, $permissions) {
483
-		$query = $this->connection->getQueryBuilder();
484
-		$query->update('share')
485
-			->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
486
-			->set('permissions', $query->createNamedParameter($permissions))
487
-			->execute();
488
-	}
489
-
490
-	/**
491
-	 * @NoCSRFRequired
492
-	 * @PublicPage
493
-	 *
494
-	 * change the owner of a server-to-server share
495
-	 *
496
-	 * @param int $id
497
-	 * @return Http\DataResponse
498
-	 * @throws \InvalidArgumentException
499
-	 * @throws OCSException
500
-	 */
501
-	public function move($id) {
502
-
503
-		if (!$this->isS2SEnabled()) {
504
-			throw new OCSException('Server does not support federated cloud sharing', 503);
505
-		}
506
-
507
-		$token = $this->request->getParam('token');
508
-		$remote = $this->request->getParam('remote');
509
-		$newRemoteId = $this->request->getParam('remote_id', $id);
510
-		$cloudId = $this->cloudIdManager->resolveCloudId($remote);
511
-
512
-		$qb = $this->connection->getQueryBuilder();
513
-		$query = $qb->update('share_external')
514
-			->set('remote', $qb->createNamedParameter($cloudId->getRemote()))
515
-			->set('owner', $qb->createNamedParameter($cloudId->getUser()))
516
-			->set('remote_id', $qb->createNamedParameter($newRemoteId))
517
-			->where($qb->expr()->eq('remote_id', $qb->createNamedParameter($id)))
518
-			->andWhere($qb->expr()->eq('share_token', $qb->createNamedParameter($token)));
519
-		$affected = $query->execute();
520
-
521
-		if ($affected > 0) {
522
-			return new Http\DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]);
523
-		} else {
524
-			throw new OCSBadRequestException('Share not found or token invalid');
525
-		}
526
-	}
59
+    /** @var FederatedShareProvider */
60
+    private $federatedShareProvider;
61
+
62
+    /** @var IDBConnection */
63
+    private $connection;
64
+
65
+    /** @var Share\IManager */
66
+    private $shareManager;
67
+
68
+    /** @var Notifications */
69
+    private $notifications;
70
+
71
+    /** @var AddressHandler */
72
+    private $addressHandler;
73
+
74
+    /** @var  IUserManager */
75
+    private $userManager;
76
+
77
+    /** @var string */
78
+    private $shareTable = 'share';
79
+
80
+    /** @var ICloudIdManager */
81
+    private $cloudIdManager;
82
+
83
+    /** @var ILogger */
84
+    private $logger;
85
+
86
+    /** @var ICloudFederationFactory */
87
+    private $cloudFederationFactory;
88
+
89
+    /** @var ICloudFederationProviderManager */
90
+    private $cloudFederationProviderManager;
91
+
92
+    /**
93
+     * Server2Server constructor.
94
+     *
95
+     * @param string $appName
96
+     * @param IRequest $request
97
+     * @param FederatedShareProvider $federatedShareProvider
98
+     * @param IDBConnection $connection
99
+     * @param Share\IManager $shareManager
100
+     * @param Notifications $notifications
101
+     * @param AddressHandler $addressHandler
102
+     * @param IUserManager $userManager
103
+     * @param ICloudIdManager $cloudIdManager
104
+     * @param ILogger $logger
105
+     * @param ICloudFederationFactory $cloudFederationFactory
106
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
107
+     */
108
+    public function __construct($appName,
109
+                                IRequest $request,
110
+                                FederatedShareProvider $federatedShareProvider,
111
+                                IDBConnection $connection,
112
+                                Share\IManager $shareManager,
113
+                                Notifications $notifications,
114
+                                AddressHandler $addressHandler,
115
+                                IUserManager $userManager,
116
+                                ICloudIdManager $cloudIdManager,
117
+                                ILogger $logger,
118
+                                ICloudFederationFactory $cloudFederationFactory,
119
+                                ICloudFederationProviderManager $cloudFederationProviderManager
120
+    ) {
121
+        parent::__construct($appName, $request);
122
+
123
+        $this->federatedShareProvider = $federatedShareProvider;
124
+        $this->connection = $connection;
125
+        $this->shareManager = $shareManager;
126
+        $this->notifications = $notifications;
127
+        $this->addressHandler = $addressHandler;
128
+        $this->userManager = $userManager;
129
+        $this->cloudIdManager = $cloudIdManager;
130
+        $this->logger = $logger;
131
+        $this->cloudFederationFactory = $cloudFederationFactory;
132
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
133
+    }
134
+
135
+    /**
136
+     * @NoCSRFRequired
137
+     * @PublicPage
138
+     *
139
+     * create a new share
140
+     *
141
+     * @return Http\DataResponse
142
+     * @throws OCSException
143
+     */
144
+    public function createShare() {
145
+
146
+        $remote = isset($_POST['remote']) ? $_POST['remote'] : null;
147
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
148
+        $name = isset($_POST['name']) ? $_POST['name'] : null;
149
+        $owner = isset($_POST['owner']) ? $_POST['owner'] : null;
150
+        $sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null;
151
+        $shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
152
+        $remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
153
+        $sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null;
154
+        $ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null;
155
+
156
+        if ($ownerFederatedId === null) {
157
+            $ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId();
158
+        }
159
+        // if the owner of the share and the initiator are the same user
160
+        // we also complete the federated share ID for the initiator
161
+        if ($sharedByFederatedId === null && $owner === $sharedBy) {
162
+            $sharedByFederatedId = $ownerFederatedId;
163
+        }
164
+
165
+        $share = $this->cloudFederationFactory->getCloudFederationShare(
166
+            $shareWith,
167
+            $name,
168
+            '',
169
+            $remoteId,
170
+            $ownerFederatedId,
171
+            $owner,
172
+            $sharedByFederatedId,
173
+            $sharedBy,
174
+            $token,
175
+            'user',
176
+            'file'
177
+        );
178
+
179
+        try {
180
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
181
+            $provider->shareReceived($share);
182
+        } catch (ProviderDoesNotExistsException $e) {
183
+            throw new OCSException('Server does not support federated cloud sharing', 503);
184
+        } catch (ProviderCouldNotAddShareException $e) {
185
+            throw new OCSException($e->getMessage(), $e->getCode());
186
+        } catch (\Exception $e) {
187
+            throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
188
+        }
189
+
190
+        return new Http\DataResponse();
191
+    }
192
+
193
+    /**
194
+     * @NoCSRFRequired
195
+     * @PublicPage
196
+     *
197
+     * create re-share on behalf of another user
198
+     *
199
+     * @param int $id
200
+     * @return Http\DataResponse
201
+     * @throws OCSBadRequestException
202
+     * @throws OCSForbiddenException
203
+     * @throws OCSNotFoundException
204
+     */
205
+    public function reShare($id) {
206
+
207
+        $token = $this->request->getParam('token', null);
208
+        $shareWith = $this->request->getParam('shareWith', null);
209
+        $permission = (int)$this->request->getParam('permission', null);
210
+        $remoteId = (int)$this->request->getParam('remoteId', null);
211
+
212
+        if ($id === null ||
213
+            $token === null ||
214
+            $shareWith === null ||
215
+            $permission === null ||
216
+            $remoteId === null
217
+        ) {
218
+            throw new OCSBadRequestException();
219
+        }
220
+
221
+        $notification = [
222
+            'sharedSecret' => $token,
223
+            'shareWith' => $shareWith,
224
+            'senderId' => $remoteId,
225
+            'message' => 'Recipient of a share ask the owner to reshare the file'
226
+        ];
227
+
228
+        try {
229
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
230
+            list($newToken, $localId) = $provider->notificationReceived('REQUEST_RESHARE', $id, $notification);
231
+            return new Http\DataResponse([
232
+                'token' => $newToken,
233
+                'remoteId' => $localId
234
+            ]);
235
+        } catch (ProviderDoesNotExistsException $e) {
236
+            throw new OCSException('Server does not support federated cloud sharing', 503);
237
+        } catch (ShareNotFoundException $e) {
238
+            $this->logger->debug('Share not found: ' . $e->getMessage());
239
+        } catch (ProviderCouldNotAddShareException $e) {
240
+            $this->logger->debug('Could not add reshare: ' . $e->getMessage());
241
+            throw new OCSForbiddenException();
242
+        } catch (\Exception $e) {
243
+            $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
244
+        }
245
+
246
+        throw new OCSBadRequestException();
247
+    }
248
+
249
+
250
+    /**
251
+     * @NoCSRFRequired
252
+     * @PublicPage
253
+     *
254
+     * accept server-to-server share
255
+     *
256
+     * @param int $id
257
+     * @return Http\DataResponse
258
+     * @throws OCSException
259
+     * @throws Share\Exceptions\ShareNotFound
260
+     * @throws \OC\HintException
261
+     */
262
+    public function acceptShare($id) {
263
+
264
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
265
+
266
+        $notification = [
267
+            'sharedSecret' => $token,
268
+            'message' => 'Recipient accept the share'
269
+        ];
270
+
271
+        try {
272
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
273
+            $provider->notificationReceived('SHARE_ACCEPTED', $id, $notification);
274
+        } catch (ProviderDoesNotExistsException $e) {
275
+            throw new OCSException('Server does not support federated cloud sharing', 503);
276
+        } catch (ShareNotFoundException $e) {
277
+            $this->logger->debug('Share not found: ' . $e->getMessage());
278
+        } catch (\Exception $e) {
279
+            $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
280
+        }
281
+
282
+        return new Http\DataResponse();
283
+    }
284
+
285
+    /**
286
+     * @NoCSRFRequired
287
+     * @PublicPage
288
+     *
289
+     * decline server-to-server share
290
+     *
291
+     * @param int $id
292
+     * @return Http\DataResponse
293
+     * @throws OCSException
294
+     */
295
+    public function declineShare($id) {
296
+
297
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
298
+
299
+        $notification = [
300
+            'sharedSecret' => $token,
301
+            'message' => 'Recipient declined the share'
302
+        ];
303
+
304
+        try {
305
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
306
+            $provider->notificationReceived('SHARE_DECLINED', $id, $notification);
307
+        } catch (ProviderDoesNotExistsException $e) {
308
+            throw new OCSException('Server does not support federated cloud sharing', 503);
309
+        } catch (ShareNotFoundException $e) {
310
+            $this->logger->debug('Share not found: ' . $e->getMessage());
311
+        } catch (\Exception $e) {
312
+            $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
313
+        }
314
+
315
+        return new Http\DataResponse();
316
+    }
317
+
318
+    /**
319
+     * @NoCSRFRequired
320
+     * @PublicPage
321
+     *
322
+     * remove server-to-server share if it was unshared by the owner
323
+     *
324
+     * @param int $id
325
+     * @return Http\DataResponse
326
+     * @throws OCSException
327
+     */
328
+    public function unshare($id) {
329
+
330
+        if (!$this->isS2SEnabled()) {
331
+            throw new OCSException('Server does not support federated cloud sharing', 503);
332
+        }
333
+
334
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
335
+
336
+        try {
337
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
338
+            $notification = ['sharedSecret' => $token];
339
+            $provider->notificationReceived('SHARE_UNSHARED', $id, $notification);
340
+        } catch (\Exception $e) {
341
+            $this->logger->debug('processing unshare notification failed: ' . $e->getMessage());
342
+        }
343
+
344
+        return new Http\DataResponse();
345
+    }
346
+
347
+    private function cleanupRemote($remote) {
348
+        $remote = substr($remote, strpos($remote, '://') + 3);
349
+
350
+        return rtrim($remote, '/');
351
+    }
352
+
353
+
354
+    /**
355
+     * @NoCSRFRequired
356
+     * @PublicPage
357
+     *
358
+     * federated share was revoked, either by the owner or the re-sharer
359
+     *
360
+     * @param int $id
361
+     * @return Http\DataResponse
362
+     * @throws OCSBadRequestException
363
+     */
364
+    public function revoke($id) {
365
+
366
+        $token = $this->request->getParam('token');
367
+
368
+        $notification = $this->cloudFederationFactory->getCloudFederationNotification();
369
+        $notification->setMessage(['sharedSecret' => $token]);
370
+
371
+        try {
372
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
373
+            $provider->notificationReceived('SHARE_UNSHARE', $id, $notification);
374
+            return new Http\DataResponse();
375
+        } catch (\Exception $e) {
376
+            throw new OCSBadRequestException();
377
+        }
378
+
379
+    }
380
+
381
+    /**
382
+     * get share
383
+     *
384
+     * @param int $id
385
+     * @param string $token
386
+     * @return array|bool
387
+     */
388
+    protected function getShare($id, $token) {
389
+        $query = $this->connection->getQueryBuilder();
390
+        $query->select('*')->from($this->shareTable)
391
+            ->where($query->expr()->eq('token', $query->createNamedParameter($token)))
392
+            ->andWhere($query->expr()->eq('share_type', $query->createNamedParameter(FederatedShareProvider::SHARE_TYPE_REMOTE)))
393
+            ->andWhere($query->expr()->eq('id', $query->createNamedParameter($id)));
394
+
395
+        $result = $query->execute()->fetchAll();
396
+
397
+        if (!empty($result) && isset($result[0])) {
398
+            return $result[0];
399
+        }
400
+
401
+        return false;
402
+    }
403
+
404
+    /**
405
+     * get file
406
+     *
407
+     * @param string $user
408
+     * @param int $fileSource
409
+     * @return array with internal path of the file and a absolute link to it
410
+     */
411
+    private function getFile($user, $fileSource) {
412
+        \OC_Util::setupFS($user);
413
+
414
+        try {
415
+            $file = \OC\Files\Filesystem::getPath($fileSource);
416
+        } catch (NotFoundException $e) {
417
+            $file = null;
418
+        }
419
+        $args = \OC\Files\Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
420
+        $link = \OCP\Util::linkToAbsolute('files', 'index.php', $args);
421
+
422
+        return array($file, $link);
423
+
424
+    }
425
+
426
+    /**
427
+     * check if server-to-server sharing is enabled
428
+     *
429
+     * @param bool $incoming
430
+     * @return bool
431
+     */
432
+    private function isS2SEnabled($incoming = false) {
433
+
434
+        $result = \OCP\App::isEnabled('files_sharing');
435
+
436
+        if ($incoming) {
437
+            $result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
438
+        } else {
439
+            $result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
440
+        }
441
+
442
+        return $result;
443
+    }
444
+
445
+    /**
446
+     * @NoCSRFRequired
447
+     * @PublicPage
448
+     *
449
+     * update share information to keep federated re-shares in sync
450
+     *
451
+     * @param int $id
452
+     * @return Http\DataResponse
453
+     * @throws OCSBadRequestException
454
+     */
455
+    public function updatePermissions($id) {
456
+        $token = $this->request->getParam('token', null);
457
+        $permissions = $this->request->getParam('permissions', null);
458
+
459
+        try {
460
+            $share = $this->federatedShareProvider->getShareById($id);
461
+        } catch (Share\Exceptions\ShareNotFound $e) {
462
+            throw new OCSBadRequestException();
463
+        }
464
+
465
+        $validPermission = ctype_digit($permissions);
466
+        $validToken = $this->verifyShare($share, $token);
467
+        if ($validPermission && $validToken) {
468
+            $this->updatePermissionsInDatabase($share, (int)$permissions);
469
+        } else {
470
+            throw new OCSBadRequestException();
471
+        }
472
+
473
+        return new Http\DataResponse();
474
+    }
475
+
476
+    /**
477
+     * update permissions in database
478
+     *
479
+     * @param IShare $share
480
+     * @param int $permissions
481
+     */
482
+    protected function updatePermissionsInDatabase(IShare $share, $permissions) {
483
+        $query = $this->connection->getQueryBuilder();
484
+        $query->update('share')
485
+            ->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
486
+            ->set('permissions', $query->createNamedParameter($permissions))
487
+            ->execute();
488
+    }
489
+
490
+    /**
491
+     * @NoCSRFRequired
492
+     * @PublicPage
493
+     *
494
+     * change the owner of a server-to-server share
495
+     *
496
+     * @param int $id
497
+     * @return Http\DataResponse
498
+     * @throws \InvalidArgumentException
499
+     * @throws OCSException
500
+     */
501
+    public function move($id) {
502
+
503
+        if (!$this->isS2SEnabled()) {
504
+            throw new OCSException('Server does not support federated cloud sharing', 503);
505
+        }
506
+
507
+        $token = $this->request->getParam('token');
508
+        $remote = $this->request->getParam('remote');
509
+        $newRemoteId = $this->request->getParam('remote_id', $id);
510
+        $cloudId = $this->cloudIdManager->resolveCloudId($remote);
511
+
512
+        $qb = $this->connection->getQueryBuilder();
513
+        $query = $qb->update('share_external')
514
+            ->set('remote', $qb->createNamedParameter($cloudId->getRemote()))
515
+            ->set('owner', $qb->createNamedParameter($cloudId->getUser()))
516
+            ->set('remote_id', $qb->createNamedParameter($newRemoteId))
517
+            ->where($qb->expr()->eq('remote_id', $qb->createNamedParameter($id)))
518
+            ->andWhere($qb->expr()->eq('share_token', $qb->createNamedParameter($token)));
519
+        $affected = $query->execute();
520
+
521
+        if ($affected > 0) {
522
+            return new Http\DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]);
523
+        } else {
524
+            throw new OCSBadRequestException('Share not found or token invalid');
525
+        }
526
+    }
527 527
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/FederatedShareProvider.php 1 patch
Indentation   +976 added lines, -976 removed lines patch added patch discarded remove patch
@@ -54,990 +54,990 @@
 block discarded – undo
54 54
  */
55 55
 class FederatedShareProvider implements IShareProvider {
56 56
 
57
-	const SHARE_TYPE_REMOTE = 6;
58
-
59
-	/** @var IDBConnection */
60
-	private $dbConnection;
61
-
62
-	/** @var AddressHandler */
63
-	private $addressHandler;
64
-
65
-	/** @var Notifications */
66
-	private $notifications;
67
-
68
-	/** @var TokenHandler */
69
-	private $tokenHandler;
70
-
71
-	/** @var IL10N */
72
-	private $l;
73
-
74
-	/** @var ILogger */
75
-	private $logger;
76
-
77
-	/** @var IRootFolder */
78
-	private $rootFolder;
79
-
80
-	/** @var IConfig */
81
-	private $config;
82
-
83
-	/** @var string */
84
-	private $externalShareTable = 'share_external';
85
-
86
-	/** @var IUserManager */
87
-	private $userManager;
88
-
89
-	/** @var ICloudIdManager */
90
-	private $cloudIdManager;
91
-
92
-	/** @var \OCP\GlobalScale\IConfig */
93
-	private $gsConfig;
94
-
95
-	/**
96
-	 * DefaultShareProvider constructor.
97
-	 *
98
-	 * @param IDBConnection $connection
99
-	 * @param AddressHandler $addressHandler
100
-	 * @param Notifications $notifications
101
-	 * @param TokenHandler $tokenHandler
102
-	 * @param IL10N $l10n
103
-	 * @param ILogger $logger
104
-	 * @param IRootFolder $rootFolder
105
-	 * @param IConfig $config
106
-	 * @param IUserManager $userManager
107
-	 * @param ICloudIdManager $cloudIdManager
108
-	 * @param \OCP\GlobalScale\IConfig $globalScaleConfig
109
-	 */
110
-	public function __construct(
111
-			IDBConnection $connection,
112
-			AddressHandler $addressHandler,
113
-			Notifications $notifications,
114
-			TokenHandler $tokenHandler,
115
-			IL10N $l10n,
116
-			ILogger $logger,
117
-			IRootFolder $rootFolder,
118
-			IConfig $config,
119
-			IUserManager $userManager,
120
-			ICloudIdManager $cloudIdManager,
121
-			\OCP\GlobalScale\IConfig $globalScaleConfig
122
-	) {
123
-		$this->dbConnection = $connection;
124
-		$this->addressHandler = $addressHandler;
125
-		$this->notifications = $notifications;
126
-		$this->tokenHandler = $tokenHandler;
127
-		$this->l = $l10n;
128
-		$this->logger = $logger;
129
-		$this->rootFolder = $rootFolder;
130
-		$this->config = $config;
131
-		$this->userManager = $userManager;
132
-		$this->cloudIdManager = $cloudIdManager;
133
-		$this->gsConfig = $globalScaleConfig;
134
-	}
135
-
136
-	/**
137
-	 * Return the identifier of this provider.
138
-	 *
139
-	 * @return string Containing only [a-zA-Z0-9]
140
-	 */
141
-	public function identifier() {
142
-		return 'ocFederatedSharing';
143
-	}
144
-
145
-	/**
146
-	 * Share a path
147
-	 *
148
-	 * @param IShare $share
149
-	 * @return IShare The share object
150
-	 * @throws ShareNotFound
151
-	 * @throws \Exception
152
-	 */
153
-	public function create(IShare $share) {
154
-
155
-		$shareWith = $share->getSharedWith();
156
-		$itemSource = $share->getNodeId();
157
-		$itemType = $share->getNodeType();
158
-		$permissions = $share->getPermissions();
159
-		$sharedBy = $share->getSharedBy();
160
-
161
-		/*
57
+    const SHARE_TYPE_REMOTE = 6;
58
+
59
+    /** @var IDBConnection */
60
+    private $dbConnection;
61
+
62
+    /** @var AddressHandler */
63
+    private $addressHandler;
64
+
65
+    /** @var Notifications */
66
+    private $notifications;
67
+
68
+    /** @var TokenHandler */
69
+    private $tokenHandler;
70
+
71
+    /** @var IL10N */
72
+    private $l;
73
+
74
+    /** @var ILogger */
75
+    private $logger;
76
+
77
+    /** @var IRootFolder */
78
+    private $rootFolder;
79
+
80
+    /** @var IConfig */
81
+    private $config;
82
+
83
+    /** @var string */
84
+    private $externalShareTable = 'share_external';
85
+
86
+    /** @var IUserManager */
87
+    private $userManager;
88
+
89
+    /** @var ICloudIdManager */
90
+    private $cloudIdManager;
91
+
92
+    /** @var \OCP\GlobalScale\IConfig */
93
+    private $gsConfig;
94
+
95
+    /**
96
+     * DefaultShareProvider constructor.
97
+     *
98
+     * @param IDBConnection $connection
99
+     * @param AddressHandler $addressHandler
100
+     * @param Notifications $notifications
101
+     * @param TokenHandler $tokenHandler
102
+     * @param IL10N $l10n
103
+     * @param ILogger $logger
104
+     * @param IRootFolder $rootFolder
105
+     * @param IConfig $config
106
+     * @param IUserManager $userManager
107
+     * @param ICloudIdManager $cloudIdManager
108
+     * @param \OCP\GlobalScale\IConfig $globalScaleConfig
109
+     */
110
+    public function __construct(
111
+            IDBConnection $connection,
112
+            AddressHandler $addressHandler,
113
+            Notifications $notifications,
114
+            TokenHandler $tokenHandler,
115
+            IL10N $l10n,
116
+            ILogger $logger,
117
+            IRootFolder $rootFolder,
118
+            IConfig $config,
119
+            IUserManager $userManager,
120
+            ICloudIdManager $cloudIdManager,
121
+            \OCP\GlobalScale\IConfig $globalScaleConfig
122
+    ) {
123
+        $this->dbConnection = $connection;
124
+        $this->addressHandler = $addressHandler;
125
+        $this->notifications = $notifications;
126
+        $this->tokenHandler = $tokenHandler;
127
+        $this->l = $l10n;
128
+        $this->logger = $logger;
129
+        $this->rootFolder = $rootFolder;
130
+        $this->config = $config;
131
+        $this->userManager = $userManager;
132
+        $this->cloudIdManager = $cloudIdManager;
133
+        $this->gsConfig = $globalScaleConfig;
134
+    }
135
+
136
+    /**
137
+     * Return the identifier of this provider.
138
+     *
139
+     * @return string Containing only [a-zA-Z0-9]
140
+     */
141
+    public function identifier() {
142
+        return 'ocFederatedSharing';
143
+    }
144
+
145
+    /**
146
+     * Share a path
147
+     *
148
+     * @param IShare $share
149
+     * @return IShare The share object
150
+     * @throws ShareNotFound
151
+     * @throws \Exception
152
+     */
153
+    public function create(IShare $share) {
154
+
155
+        $shareWith = $share->getSharedWith();
156
+        $itemSource = $share->getNodeId();
157
+        $itemType = $share->getNodeType();
158
+        $permissions = $share->getPermissions();
159
+        $sharedBy = $share->getSharedBy();
160
+
161
+        /*
162 162
 		 * Check if file is not already shared with the remote user
163 163
 		 */
164
-		$alreadyShared = $this->getSharedWith($shareWith, self::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
165
-		if (!empty($alreadyShared)) {
166
-			$message = 'Sharing %s failed, because this item is already shared with %s';
167
-			$message_t = $this->l->t('Sharing %s failed, because this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
168
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
169
-			throw new \Exception($message_t);
170
-		}
171
-
172
-
173
-		// don't allow federated shares if source and target server are the same
174
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
175
-		$currentServer = $this->addressHandler->generateRemoteURL();
176
-		$currentUser = $sharedBy;
177
-		if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
178
-			$message = 'Not allowed to create a federated share with the same user.';
179
-			$message_t = $this->l->t('Not allowed to create a federated share with the same user');
180
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
181
-			throw new \Exception($message_t);
182
-		}
183
-
184
-
185
-		$share->setSharedWith($cloudId->getId());
186
-
187
-		try {
188
-			$remoteShare = $this->getShareFromExternalShareTable($share);
189
-		} catch (ShareNotFound $e) {
190
-			$remoteShare = null;
191
-		}
192
-
193
-		if ($remoteShare) {
194
-			try {
195
-				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
196
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time());
197
-				$share->setId($shareId);
198
-				list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
199
-				// remote share was create successfully if we get a valid token as return
200
-				$send = is_string($token) && $token !== '';
201
-			} catch (\Exception $e) {
202
-				// fall back to old re-share behavior if the remote server
203
-				// doesn't support flat re-shares (was introduced with Nextcloud 9.1)
204
-				$this->removeShareFromTable($share);
205
-				$shareId = $this->createFederatedShare($share);
206
-			}
207
-			if ($send) {
208
-				$this->updateSuccessfulReshare($shareId, $token);
209
-				$this->storeRemoteId($shareId, $remoteId);
210
-			} else {
211
-				$this->removeShareFromTable($share);
212
-				$message_t = $this->l->t('File is already shared with %s', [$shareWith]);
213
-				throw new \Exception($message_t);
214
-			}
215
-
216
-		} else {
217
-			$shareId = $this->createFederatedShare($share);
218
-		}
219
-
220
-		$data = $this->getRawShare($shareId);
221
-		return $this->createShareObject($data);
222
-	}
223
-
224
-	/**
225
-	 * create federated share and inform the recipient
226
-	 *
227
-	 * @param IShare $share
228
-	 * @return int
229
-	 * @throws ShareNotFound
230
-	 * @throws \Exception
231
-	 */
232
-	protected function createFederatedShare(IShare $share) {
233
-		$token = $this->tokenHandler->generateToken();
234
-		$shareId = $this->addShareToDB(
235
-			$share->getNodeId(),
236
-			$share->getNodeType(),
237
-			$share->getSharedWith(),
238
-			$share->getSharedBy(),
239
-			$share->getShareOwner(),
240
-			$share->getPermissions(),
241
-			$token
242
-		);
243
-
244
-		$failure = false;
245
-
246
-		try {
247
-			$sharedByFederatedId = $share->getSharedBy();
248
-			if ($this->userManager->userExists($sharedByFederatedId)) {
249
-				$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
250
-				$sharedByFederatedId = $cloudId->getId();
251
-			}
252
-			$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
253
-			$send = $this->notifications->sendRemoteShare(
254
-				$token,
255
-				$share->getSharedWith(),
256
-				$share->getNode()->getName(),
257
-				$shareId,
258
-				$share->getShareOwner(),
259
-				$ownerCloudId->getId(),
260
-				$share->getSharedBy(),
261
-				$sharedByFederatedId
262
-			);
263
-
264
-			if ($send === false) {
265
-				$failure = true;
266
-			}
267
-		} catch (\Exception $e) {
268
-			$this->logger->logException($e, [
269
-				'message' => 'Failed to notify remote server of federated share, removing share.',
270
-				'level' => ILogger::ERROR,
271
-				'app' => 'federatedfilesharing',
272
-			]);
273
-			$failure = true;
274
-		}
275
-
276
-		if($failure) {
277
-			$this->removeShareFromTableById($shareId);
278
-			$message_t = $this->l->t('Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate.',
279
-				[$share->getNode()->getName(), $share->getSharedWith()]);
280
-			throw new \Exception($message_t);
281
-		}
282
-
283
-		return $shareId;
284
-
285
-	}
286
-
287
-	/**
288
-	 * @param string $shareWith
289
-	 * @param IShare $share
290
-	 * @param string $shareId internal share Id
291
-	 * @return array
292
-	 * @throws \Exception
293
-	 */
294
-	protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
295
-
296
-		$remoteShare = $this->getShareFromExternalShareTable($share);
297
-		$token = $remoteShare['share_token'];
298
-		$remoteId = $remoteShare['remote_id'];
299
-		$remote = $remoteShare['remote'];
300
-
301
-		list($token, $remoteId) = $this->notifications->requestReShare(
302
-			$token,
303
-			$remoteId,
304
-			$shareId,
305
-			$remote,
306
-			$shareWith,
307
-			$share->getPermissions(),
308
-			$share->getNode()->getName()
309
-		);
310
-
311
-		return [$token, $remoteId];
312
-	}
313
-
314
-	/**
315
-	 * get federated share from the share_external table but exclude mounted link shares
316
-	 *
317
-	 * @param IShare $share
318
-	 * @return array
319
-	 * @throws ShareNotFound
320
-	 */
321
-	protected function getShareFromExternalShareTable(IShare $share) {
322
-		$query = $this->dbConnection->getQueryBuilder();
323
-		$query->select('*')->from($this->externalShareTable)
324
-			->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
325
-			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
326
-		$result = $query->execute()->fetchAll();
327
-
328
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
329
-			return $result[0];
330
-		}
331
-
332
-		throw new ShareNotFound('share not found in share_external table');
333
-	}
334
-
335
-	/**
336
-	 * add share to the database and return the ID
337
-	 *
338
-	 * @param int $itemSource
339
-	 * @param string $itemType
340
-	 * @param string $shareWith
341
-	 * @param string $sharedBy
342
-	 * @param string $uidOwner
343
-	 * @param int $permissions
344
-	 * @param string $token
345
-	 * @return int
346
-	 */
347
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) {
348
-		$qb = $this->dbConnection->getQueryBuilder();
349
-		$qb->insert('share')
350
-			->setValue('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))
351
-			->setValue('item_type', $qb->createNamedParameter($itemType))
352
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
353
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
354
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
355
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
356
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
357
-			->setValue('permissions', $qb->createNamedParameter($permissions))
358
-			->setValue('token', $qb->createNamedParameter($token))
359
-			->setValue('stime', $qb->createNamedParameter(time()));
360
-
361
-		/*
164
+        $alreadyShared = $this->getSharedWith($shareWith, self::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
165
+        if (!empty($alreadyShared)) {
166
+            $message = 'Sharing %s failed, because this item is already shared with %s';
167
+            $message_t = $this->l->t('Sharing %s failed, because this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
168
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
169
+            throw new \Exception($message_t);
170
+        }
171
+
172
+
173
+        // don't allow federated shares if source and target server are the same
174
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
175
+        $currentServer = $this->addressHandler->generateRemoteURL();
176
+        $currentUser = $sharedBy;
177
+        if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
178
+            $message = 'Not allowed to create a federated share with the same user.';
179
+            $message_t = $this->l->t('Not allowed to create a federated share with the same user');
180
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
181
+            throw new \Exception($message_t);
182
+        }
183
+
184
+
185
+        $share->setSharedWith($cloudId->getId());
186
+
187
+        try {
188
+            $remoteShare = $this->getShareFromExternalShareTable($share);
189
+        } catch (ShareNotFound $e) {
190
+            $remoteShare = null;
191
+        }
192
+
193
+        if ($remoteShare) {
194
+            try {
195
+                $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
196
+                $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time());
197
+                $share->setId($shareId);
198
+                list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
199
+                // remote share was create successfully if we get a valid token as return
200
+                $send = is_string($token) && $token !== '';
201
+            } catch (\Exception $e) {
202
+                // fall back to old re-share behavior if the remote server
203
+                // doesn't support flat re-shares (was introduced with Nextcloud 9.1)
204
+                $this->removeShareFromTable($share);
205
+                $shareId = $this->createFederatedShare($share);
206
+            }
207
+            if ($send) {
208
+                $this->updateSuccessfulReshare($shareId, $token);
209
+                $this->storeRemoteId($shareId, $remoteId);
210
+            } else {
211
+                $this->removeShareFromTable($share);
212
+                $message_t = $this->l->t('File is already shared with %s', [$shareWith]);
213
+                throw new \Exception($message_t);
214
+            }
215
+
216
+        } else {
217
+            $shareId = $this->createFederatedShare($share);
218
+        }
219
+
220
+        $data = $this->getRawShare($shareId);
221
+        return $this->createShareObject($data);
222
+    }
223
+
224
+    /**
225
+     * create federated share and inform the recipient
226
+     *
227
+     * @param IShare $share
228
+     * @return int
229
+     * @throws ShareNotFound
230
+     * @throws \Exception
231
+     */
232
+    protected function createFederatedShare(IShare $share) {
233
+        $token = $this->tokenHandler->generateToken();
234
+        $shareId = $this->addShareToDB(
235
+            $share->getNodeId(),
236
+            $share->getNodeType(),
237
+            $share->getSharedWith(),
238
+            $share->getSharedBy(),
239
+            $share->getShareOwner(),
240
+            $share->getPermissions(),
241
+            $token
242
+        );
243
+
244
+        $failure = false;
245
+
246
+        try {
247
+            $sharedByFederatedId = $share->getSharedBy();
248
+            if ($this->userManager->userExists($sharedByFederatedId)) {
249
+                $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
250
+                $sharedByFederatedId = $cloudId->getId();
251
+            }
252
+            $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
253
+            $send = $this->notifications->sendRemoteShare(
254
+                $token,
255
+                $share->getSharedWith(),
256
+                $share->getNode()->getName(),
257
+                $shareId,
258
+                $share->getShareOwner(),
259
+                $ownerCloudId->getId(),
260
+                $share->getSharedBy(),
261
+                $sharedByFederatedId
262
+            );
263
+
264
+            if ($send === false) {
265
+                $failure = true;
266
+            }
267
+        } catch (\Exception $e) {
268
+            $this->logger->logException($e, [
269
+                'message' => 'Failed to notify remote server of federated share, removing share.',
270
+                'level' => ILogger::ERROR,
271
+                'app' => 'federatedfilesharing',
272
+            ]);
273
+            $failure = true;
274
+        }
275
+
276
+        if($failure) {
277
+            $this->removeShareFromTableById($shareId);
278
+            $message_t = $this->l->t('Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate.',
279
+                [$share->getNode()->getName(), $share->getSharedWith()]);
280
+            throw new \Exception($message_t);
281
+        }
282
+
283
+        return $shareId;
284
+
285
+    }
286
+
287
+    /**
288
+     * @param string $shareWith
289
+     * @param IShare $share
290
+     * @param string $shareId internal share Id
291
+     * @return array
292
+     * @throws \Exception
293
+     */
294
+    protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
295
+
296
+        $remoteShare = $this->getShareFromExternalShareTable($share);
297
+        $token = $remoteShare['share_token'];
298
+        $remoteId = $remoteShare['remote_id'];
299
+        $remote = $remoteShare['remote'];
300
+
301
+        list($token, $remoteId) = $this->notifications->requestReShare(
302
+            $token,
303
+            $remoteId,
304
+            $shareId,
305
+            $remote,
306
+            $shareWith,
307
+            $share->getPermissions(),
308
+            $share->getNode()->getName()
309
+        );
310
+
311
+        return [$token, $remoteId];
312
+    }
313
+
314
+    /**
315
+     * get federated share from the share_external table but exclude mounted link shares
316
+     *
317
+     * @param IShare $share
318
+     * @return array
319
+     * @throws ShareNotFound
320
+     */
321
+    protected function getShareFromExternalShareTable(IShare $share) {
322
+        $query = $this->dbConnection->getQueryBuilder();
323
+        $query->select('*')->from($this->externalShareTable)
324
+            ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
325
+            ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
326
+        $result = $query->execute()->fetchAll();
327
+
328
+        if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
329
+            return $result[0];
330
+        }
331
+
332
+        throw new ShareNotFound('share not found in share_external table');
333
+    }
334
+
335
+    /**
336
+     * add share to the database and return the ID
337
+     *
338
+     * @param int $itemSource
339
+     * @param string $itemType
340
+     * @param string $shareWith
341
+     * @param string $sharedBy
342
+     * @param string $uidOwner
343
+     * @param int $permissions
344
+     * @param string $token
345
+     * @return int
346
+     */
347
+    private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) {
348
+        $qb = $this->dbConnection->getQueryBuilder();
349
+        $qb->insert('share')
350
+            ->setValue('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))
351
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
352
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
353
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
354
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
355
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
356
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
357
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
358
+            ->setValue('token', $qb->createNamedParameter($token))
359
+            ->setValue('stime', $qb->createNamedParameter(time()));
360
+
361
+        /*
362 362
 		 * Added to fix https://github.com/owncloud/core/issues/22215
363 363
 		 * Can be removed once we get rid of ajax/share.php
364 364
 		 */
365
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
366
-
367
-		$qb->execute();
368
-		$id = $qb->getLastInsertId();
369
-
370
-		return (int)$id;
371
-	}
372
-
373
-	/**
374
-	 * Update a share
375
-	 *
376
-	 * @param IShare $share
377
-	 * @return IShare The share object
378
-	 */
379
-	public function update(IShare $share) {
380
-		/*
365
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
366
+
367
+        $qb->execute();
368
+        $id = $qb->getLastInsertId();
369
+
370
+        return (int)$id;
371
+    }
372
+
373
+    /**
374
+     * Update a share
375
+     *
376
+     * @param IShare $share
377
+     * @return IShare The share object
378
+     */
379
+    public function update(IShare $share) {
380
+        /*
381 381
 		 * We allow updating the permissions of federated shares
382 382
 		 */
383
-		$qb = $this->dbConnection->getQueryBuilder();
384
-			$qb->update('share')
385
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
386
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
387
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
388
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
389
-				->execute();
390
-
391
-		// send the updated permission to the owner/initiator, if they are not the same
392
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
393
-			$this->sendPermissionUpdate($share);
394
-		}
395
-
396
-		return $share;
397
-	}
398
-
399
-	/**
400
-	 * send the updated permission to the owner/initiator, if they are not the same
401
-	 *
402
-	 * @param IShare $share
403
-	 * @throws ShareNotFound
404
-	 * @throws \OC\HintException
405
-	 */
406
-	protected function sendPermissionUpdate(IShare $share) {
407
-		$remoteId = $this->getRemoteId($share);
408
-		// if the local user is the owner we send the permission change to the initiator
409
-		if ($this->userManager->userExists($share->getShareOwner())) {
410
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
411
-		} else { // ... if not we send the permission change to the owner
412
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
413
-		}
414
-		$this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
415
-	}
416
-
417
-
418
-	/**
419
-	 * update successful reShare with the correct token
420
-	 *
421
-	 * @param int $shareId
422
-	 * @param string $token
423
-	 */
424
-	protected function updateSuccessfulReShare($shareId, $token) {
425
-		$query = $this->dbConnection->getQueryBuilder();
426
-		$query->update('share')
427
-			->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
428
-			->set('token', $query->createNamedParameter($token))
429
-			->execute();
430
-	}
431
-
432
-	/**
433
-	 * store remote ID in federated reShare table
434
-	 *
435
-	 * @param $shareId
436
-	 * @param $remoteId
437
-	 */
438
-	public function storeRemoteId($shareId, $remoteId) {
439
-		$query = $this->dbConnection->getQueryBuilder();
440
-		$query->insert('federated_reshares')
441
-			->values(
442
-				[
443
-					'share_id' =>  $query->createNamedParameter($shareId),
444
-					'remote_id' => $query->createNamedParameter($remoteId),
445
-				]
446
-			);
447
-		$query->execute();
448
-	}
449
-
450
-	/**
451
-	 * get share ID on remote server for federated re-shares
452
-	 *
453
-	 * @param IShare $share
454
-	 * @return int
455
-	 * @throws ShareNotFound
456
-	 */
457
-	public function getRemoteId(IShare $share) {
458
-		$query = $this->dbConnection->getQueryBuilder();
459
-		$query->select('remote_id')->from('federated_reshares')
460
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
461
-		$data = $query->execute()->fetch();
462
-
463
-		if (!is_array($data) || !isset($data['remote_id'])) {
464
-			throw new ShareNotFound();
465
-		}
466
-
467
-		return (int)$data['remote_id'];
468
-	}
469
-
470
-	/**
471
-	 * @inheritdoc
472
-	 */
473
-	public function move(IShare $share, $recipient) {
474
-		/*
383
+        $qb = $this->dbConnection->getQueryBuilder();
384
+            $qb->update('share')
385
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
386
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
387
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
388
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
389
+                ->execute();
390
+
391
+        // send the updated permission to the owner/initiator, if they are not the same
392
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
393
+            $this->sendPermissionUpdate($share);
394
+        }
395
+
396
+        return $share;
397
+    }
398
+
399
+    /**
400
+     * send the updated permission to the owner/initiator, if they are not the same
401
+     *
402
+     * @param IShare $share
403
+     * @throws ShareNotFound
404
+     * @throws \OC\HintException
405
+     */
406
+    protected function sendPermissionUpdate(IShare $share) {
407
+        $remoteId = $this->getRemoteId($share);
408
+        // if the local user is the owner we send the permission change to the initiator
409
+        if ($this->userManager->userExists($share->getShareOwner())) {
410
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
411
+        } else { // ... if not we send the permission change to the owner
412
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
413
+        }
414
+        $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
415
+    }
416
+
417
+
418
+    /**
419
+     * update successful reShare with the correct token
420
+     *
421
+     * @param int $shareId
422
+     * @param string $token
423
+     */
424
+    protected function updateSuccessfulReShare($shareId, $token) {
425
+        $query = $this->dbConnection->getQueryBuilder();
426
+        $query->update('share')
427
+            ->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
428
+            ->set('token', $query->createNamedParameter($token))
429
+            ->execute();
430
+    }
431
+
432
+    /**
433
+     * store remote ID in federated reShare table
434
+     *
435
+     * @param $shareId
436
+     * @param $remoteId
437
+     */
438
+    public function storeRemoteId($shareId, $remoteId) {
439
+        $query = $this->dbConnection->getQueryBuilder();
440
+        $query->insert('federated_reshares')
441
+            ->values(
442
+                [
443
+                    'share_id' =>  $query->createNamedParameter($shareId),
444
+                    'remote_id' => $query->createNamedParameter($remoteId),
445
+                ]
446
+            );
447
+        $query->execute();
448
+    }
449
+
450
+    /**
451
+     * get share ID on remote server for federated re-shares
452
+     *
453
+     * @param IShare $share
454
+     * @return int
455
+     * @throws ShareNotFound
456
+     */
457
+    public function getRemoteId(IShare $share) {
458
+        $query = $this->dbConnection->getQueryBuilder();
459
+        $query->select('remote_id')->from('federated_reshares')
460
+            ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
461
+        $data = $query->execute()->fetch();
462
+
463
+        if (!is_array($data) || !isset($data['remote_id'])) {
464
+            throw new ShareNotFound();
465
+        }
466
+
467
+        return (int)$data['remote_id'];
468
+    }
469
+
470
+    /**
471
+     * @inheritdoc
472
+     */
473
+    public function move(IShare $share, $recipient) {
474
+        /*
475 475
 		 * This function does nothing yet as it is just for outgoing
476 476
 		 * federated shares.
477 477
 		 */
478
-		return $share;
479
-	}
480
-
481
-	/**
482
-	 * Get all children of this share
483
-	 *
484
-	 * @param IShare $parent
485
-	 * @return IShare[]
486
-	 */
487
-	public function getChildren(IShare $parent) {
488
-		$children = [];
489
-
490
-		$qb = $this->dbConnection->getQueryBuilder();
491
-		$qb->select('*')
492
-			->from('share')
493
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
494
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
495
-			->orderBy('id');
496
-
497
-		$cursor = $qb->execute();
498
-		while($data = $cursor->fetch()) {
499
-			$children[] = $this->createShareObject($data);
500
-		}
501
-		$cursor->closeCursor();
502
-
503
-		return $children;
504
-	}
505
-
506
-	/**
507
-	 * Delete a share (owner unShares the file)
508
-	 *
509
-	 * @param IShare $share
510
-	 */
511
-	public function delete(IShare $share) {
512
-
513
-		list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
514
-
515
-		$isOwner = false;
516
-
517
-		$this->removeShareFromTable($share);
518
-
519
-		// if the local user is the owner we can send the unShare request directly...
520
-		if ($this->userManager->userExists($share->getShareOwner())) {
521
-			$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
522
-			$this->revokeShare($share, true);
523
-			$isOwner = true;
524
-		} else { // ... if not we need to correct ID for the unShare request
525
-			$remoteId = $this->getRemoteId($share);
526
-			$this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
527
-			$this->revokeShare($share, false);
528
-		}
529
-
530
-		// send revoke notification to the other user, if initiator and owner are not the same user
531
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
532
-			$remoteId = $this->getRemoteId($share);
533
-			if ($isOwner) {
534
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
535
-			} else {
536
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
537
-			}
538
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
539
-		}
540
-	}
541
-
542
-	/**
543
-	 * in case of a re-share we need to send the other use (initiator or owner)
544
-	 * a message that the file was unshared
545
-	 *
546
-	 * @param IShare $share
547
-	 * @param bool $isOwner the user can either be the owner or the user who re-sahred it
548
-	 * @throws ShareNotFound
549
-	 * @throws \OC\HintException
550
-	 */
551
-	protected function revokeShare($share, $isOwner) {
552
-		// also send a unShare request to the initiator, if this is a different user than the owner
553
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
554
-			if ($isOwner) {
555
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
556
-			} else {
557
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
558
-			}
559
-			$remoteId = $this->getRemoteId($share);
560
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
561
-		}
562
-	}
563
-
564
-	/**
565
-	 * remove share from table
566
-	 *
567
-	 * @param IShare $share
568
-	 */
569
-	public function removeShareFromTable(IShare $share) {
570
-		$this->removeShareFromTableById($share->getId());
571
-	}
572
-
573
-	/**
574
-	 * remove share from table
575
-	 *
576
-	 * @param string $shareId
577
-	 */
578
-	private function removeShareFromTableById($shareId) {
579
-		$qb = $this->dbConnection->getQueryBuilder();
580
-		$qb->delete('share')
581
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
582
-		$qb->execute();
583
-
584
-		$qb->delete('federated_reshares')
585
-			->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
586
-		$qb->execute();
587
-	}
588
-
589
-	/**
590
-	 * @inheritdoc
591
-	 */
592
-	public function deleteFromSelf(IShare $share, $recipient) {
593
-		// nothing to do here. Technically deleteFromSelf in the context of federated
594
-		// shares is a umount of a external storage. This is handled here
595
-		// apps/files_sharing/lib/external/manager.php
596
-		// TODO move this code over to this app
597
-	}
598
-
599
-
600
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
601
-		$qb = $this->dbConnection->getQueryBuilder();
602
-		$qb->select('*')
603
-			->from('share', 's')
604
-			->andWhere($qb->expr()->orX(
605
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
606
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
607
-			))
608
-			->andWhere(
609
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
610
-			);
611
-
612
-		/**
613
-		 * Reshares for this user are shares where they are the owner.
614
-		 */
615
-		if ($reshares === false) {
616
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
617
-		} else {
618
-			$qb->andWhere(
619
-				$qb->expr()->orX(
620
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
621
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
622
-				)
623
-			);
624
-		}
625
-
626
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
627
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
628
-
629
-		$qb->orderBy('id');
630
-
631
-		$cursor = $qb->execute();
632
-		$shares = [];
633
-		while ($data = $cursor->fetch()) {
634
-			$shares[$data['fileid']][] = $this->createShareObject($data);
635
-		}
636
-		$cursor->closeCursor();
637
-
638
-		return $shares;
639
-	}
640
-
641
-	/**
642
-	 * @inheritdoc
643
-	 */
644
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
645
-		$qb = $this->dbConnection->getQueryBuilder();
646
-		$qb->select('*')
647
-			->from('share');
648
-
649
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
650
-
651
-		/**
652
-		 * Reshares for this user are shares where they are the owner.
653
-		 */
654
-		if ($reshares === false) {
655
-			//Special case for old shares created via the web UI
656
-			$or1 = $qb->expr()->andX(
657
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
658
-				$qb->expr()->isNull('uid_initiator')
659
-			);
660
-
661
-			$qb->andWhere(
662
-				$qb->expr()->orX(
663
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
664
-					$or1
665
-				)
666
-			);
667
-		} else {
668
-			$qb->andWhere(
669
-				$qb->expr()->orX(
670
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
671
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
672
-				)
673
-			);
674
-		}
675
-
676
-		if ($node !== null) {
677
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
678
-		}
679
-
680
-		if ($limit !== -1) {
681
-			$qb->setMaxResults($limit);
682
-		}
683
-
684
-		$qb->setFirstResult($offset);
685
-		$qb->orderBy('id');
686
-
687
-		$cursor = $qb->execute();
688
-		$shares = [];
689
-		while($data = $cursor->fetch()) {
690
-			$shares[] = $this->createShareObject($data);
691
-		}
692
-		$cursor->closeCursor();
693
-
694
-		return $shares;
695
-	}
696
-
697
-	/**
698
-	 * @inheritdoc
699
-	 */
700
-	public function getShareById($id, $recipientId = null) {
701
-		$qb = $this->dbConnection->getQueryBuilder();
702
-
703
-		$qb->select('*')
704
-			->from('share')
705
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
706
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
707
-
708
-		$cursor = $qb->execute();
709
-		$data = $cursor->fetch();
710
-		$cursor->closeCursor();
711
-
712
-		if ($data === false) {
713
-			throw new ShareNotFoundException('Can not find share with ID: ' . $id);
714
-		}
715
-
716
-		try {
717
-			$share = $this->createShareObject($data);
718
-		} catch (InvalidShare $e) {
719
-			throw new ShareNotFoundException();
720
-		}
721
-
722
-		return $share;
723
-	}
724
-
725
-	/**
726
-	 * Get shares for a given path
727
-	 *
728
-	 * @param \OCP\Files\Node $path
729
-	 * @return IShare[]
730
-	 */
731
-	public function getSharesByPath(Node $path) {
732
-		$qb = $this->dbConnection->getQueryBuilder();
733
-
734
-		$cursor = $qb->select('*')
735
-			->from('share')
736
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
737
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
738
-			->execute();
739
-
740
-		$shares = [];
741
-		while($data = $cursor->fetch()) {
742
-			$shares[] = $this->createShareObject($data);
743
-		}
744
-		$cursor->closeCursor();
745
-
746
-		return $shares;
747
-	}
748
-
749
-	/**
750
-	 * @inheritdoc
751
-	 */
752
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
753
-		/** @var IShare[] $shares */
754
-		$shares = [];
755
-
756
-		//Get shares directly with this user
757
-		$qb = $this->dbConnection->getQueryBuilder();
758
-		$qb->select('*')
759
-			->from('share');
760
-
761
-		// Order by id
762
-		$qb->orderBy('id');
763
-
764
-		// Set limit and offset
765
-		if ($limit !== -1) {
766
-			$qb->setMaxResults($limit);
767
-		}
768
-		$qb->setFirstResult($offset);
769
-
770
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
771
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
772
-
773
-		// Filter by node if provided
774
-		if ($node !== null) {
775
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
776
-		}
777
-
778
-		$cursor = $qb->execute();
779
-
780
-		while($data = $cursor->fetch()) {
781
-			$shares[] = $this->createShareObject($data);
782
-		}
783
-		$cursor->closeCursor();
784
-
785
-
786
-		return $shares;
787
-	}
788
-
789
-	/**
790
-	 * Get a share by token
791
-	 *
792
-	 * @param string $token
793
-	 * @return IShare
794
-	 * @throws ShareNotFound
795
-	 */
796
-	public function getShareByToken($token) {
797
-		$qb = $this->dbConnection->getQueryBuilder();
798
-
799
-		$cursor = $qb->select('*')
800
-			->from('share')
801
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
802
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
803
-			->execute();
804
-
805
-		$data = $cursor->fetch();
806
-
807
-		if ($data === false) {
808
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
809
-		}
810
-
811
-		try {
812
-			$share = $this->createShareObject($data);
813
-		} catch (InvalidShare $e) {
814
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
815
-		}
816
-
817
-		return $share;
818
-	}
819
-
820
-	/**
821
-	 * get database row of a give share
822
-	 *
823
-	 * @param $id
824
-	 * @return array
825
-	 * @throws ShareNotFound
826
-	 */
827
-	private function getRawShare($id) {
828
-
829
-		// Now fetch the inserted share and create a complete share object
830
-		$qb = $this->dbConnection->getQueryBuilder();
831
-		$qb->select('*')
832
-			->from('share')
833
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
834
-
835
-		$cursor = $qb->execute();
836
-		$data = $cursor->fetch();
837
-		$cursor->closeCursor();
838
-
839
-		if ($data === false) {
840
-			throw new ShareNotFound;
841
-		}
842
-
843
-		return $data;
844
-	}
845
-
846
-	/**
847
-	 * Create a share object from an database row
848
-	 *
849
-	 * @param array $data
850
-	 * @return IShare
851
-	 * @throws InvalidShare
852
-	 * @throws ShareNotFound
853
-	 */
854
-	private function createShareObject($data) {
855
-
856
-		$share = new Share($this->rootFolder, $this->userManager);
857
-		$share->setId((int)$data['id'])
858
-			->setShareType((int)$data['share_type'])
859
-			->setPermissions((int)$data['permissions'])
860
-			->setTarget($data['file_target'])
861
-			->setMailSend((bool)$data['mail_send'])
862
-			->setToken($data['token']);
863
-
864
-		$shareTime = new \DateTime();
865
-		$shareTime->setTimestamp((int)$data['stime']);
866
-		$share->setShareTime($shareTime);
867
-		$share->setSharedWith($data['share_with']);
868
-
869
-		if ($data['uid_initiator'] !== null) {
870
-			$share->setShareOwner($data['uid_owner']);
871
-			$share->setSharedBy($data['uid_initiator']);
872
-		} else {
873
-			//OLD SHARE
874
-			$share->setSharedBy($data['uid_owner']);
875
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
876
-
877
-			$owner = $path->getOwner();
878
-			$share->setShareOwner($owner->getUID());
879
-		}
880
-
881
-		$share->setNodeId((int)$data['file_source']);
882
-		$share->setNodeType($data['item_type']);
883
-
884
-		$share->setProviderId($this->identifier());
885
-
886
-		return $share;
887
-	}
888
-
889
-	/**
890
-	 * Get the node with file $id for $user
891
-	 *
892
-	 * @param string $userId
893
-	 * @param int $id
894
-	 * @return \OCP\Files\File|\OCP\Files\Folder
895
-	 * @throws InvalidShare
896
-	 */
897
-	private function getNode($userId, $id) {
898
-		try {
899
-			$userFolder = $this->rootFolder->getUserFolder($userId);
900
-		} catch (NotFoundException $e) {
901
-			throw new InvalidShare();
902
-		}
903
-
904
-		$nodes = $userFolder->getById($id);
905
-
906
-		if (empty($nodes)) {
907
-			throw new InvalidShare();
908
-		}
909
-
910
-		return $nodes[0];
911
-	}
912
-
913
-	/**
914
-	 * A user is deleted from the system
915
-	 * So clean up the relevant shares.
916
-	 *
917
-	 * @param string $uid
918
-	 * @param int $shareType
919
-	 */
920
-	public function userDeleted($uid, $shareType) {
921
-		//TODO: probabaly a good idea to send unshare info to remote servers
922
-
923
-		$qb = $this->dbConnection->getQueryBuilder();
924
-
925
-		$qb->delete('share')
926
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
927
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
928
-			->execute();
929
-	}
930
-
931
-	/**
932
-	 * This provider does not handle groups
933
-	 *
934
-	 * @param string $gid
935
-	 */
936
-	public function groupDeleted($gid) {
937
-		// We don't handle groups here
938
-	}
939
-
940
-	/**
941
-	 * This provider does not handle groups
942
-	 *
943
-	 * @param string $uid
944
-	 * @param string $gid
945
-	 */
946
-	public function userDeletedFromGroup($uid, $gid) {
947
-		// We don't handle groups here
948
-	}
949
-
950
-	/**
951
-	 * check if users from other Nextcloud instances are allowed to mount public links share by this instance
952
-	 *
953
-	 * @return bool
954
-	 */
955
-	public function isOutgoingServer2serverShareEnabled() {
956
-		if ($this->gsConfig->onlyInternalFederation()) {
957
-			return false;
958
-		}
959
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
960
-		return ($result === 'yes');
961
-	}
962
-
963
-	/**
964
-	 * check if users are allowed to mount public links from other Nextclouds
965
-	 *
966
-	 * @return bool
967
-	 */
968
-	public function isIncomingServer2serverShareEnabled() {
969
-		if ($this->gsConfig->onlyInternalFederation()) {
970
-			return false;
971
-		}
972
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
973
-		return ($result === 'yes');
974
-	}
975
-
976
-	/**
977
-	 * Check if querying sharees on the lookup server is enabled
978
-	 *
979
-	 * @return bool
980
-	 */
981
-	public function isLookupServerQueriesEnabled() {
982
-		// in a global scale setup we should always query the lookup server
983
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
984
-			return true;
985
-		}
986
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
987
-		return ($result === 'yes');
988
-	}
989
-
990
-
991
-	/**
992
-	 * Check if it is allowed to publish user specific data to the lookup server
993
-	 *
994
-	 * @return bool
995
-	 */
996
-	public function isLookupServerUploadEnabled() {
997
-		// in a global scale setup the admin is responsible to keep the lookup server up-to-date
998
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
999
-			return false;
1000
-		}
1001
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1002
-		return ($result === 'yes');
1003
-	}
1004
-
1005
-	/**
1006
-	 * @inheritdoc
1007
-	 */
1008
-	public function getAccessList($nodes, $currentAccess) {
1009
-		$ids = [];
1010
-		foreach ($nodes as $node) {
1011
-			$ids[] = $node->getId();
1012
-		}
1013
-
1014
-		$qb = $this->dbConnection->getQueryBuilder();
1015
-		$qb->select('share_with', 'token', 'file_source')
1016
-			->from('share')
1017
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1018
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1019
-			->andWhere($qb->expr()->orX(
1020
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1021
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1022
-			));
1023
-		$cursor = $qb->execute();
1024
-
1025
-		if ($currentAccess === false) {
1026
-			$remote = $cursor->fetch() !== false;
1027
-			$cursor->closeCursor();
1028
-
1029
-			return ['remote' => $remote];
1030
-		}
1031
-
1032
-		$remote = [];
1033
-		while ($row = $cursor->fetch()) {
1034
-			$remote[$row['share_with']] = [
1035
-				'node_id' => $row['file_source'],
1036
-				'token' => $row['token'],
1037
-			];
1038
-		}
1039
-		$cursor->closeCursor();
1040
-
1041
-		return ['remote' => $remote];
1042
-	}
478
+        return $share;
479
+    }
480
+
481
+    /**
482
+     * Get all children of this share
483
+     *
484
+     * @param IShare $parent
485
+     * @return IShare[]
486
+     */
487
+    public function getChildren(IShare $parent) {
488
+        $children = [];
489
+
490
+        $qb = $this->dbConnection->getQueryBuilder();
491
+        $qb->select('*')
492
+            ->from('share')
493
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
494
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
495
+            ->orderBy('id');
496
+
497
+        $cursor = $qb->execute();
498
+        while($data = $cursor->fetch()) {
499
+            $children[] = $this->createShareObject($data);
500
+        }
501
+        $cursor->closeCursor();
502
+
503
+        return $children;
504
+    }
505
+
506
+    /**
507
+     * Delete a share (owner unShares the file)
508
+     *
509
+     * @param IShare $share
510
+     */
511
+    public function delete(IShare $share) {
512
+
513
+        list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
514
+
515
+        $isOwner = false;
516
+
517
+        $this->removeShareFromTable($share);
518
+
519
+        // if the local user is the owner we can send the unShare request directly...
520
+        if ($this->userManager->userExists($share->getShareOwner())) {
521
+            $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
522
+            $this->revokeShare($share, true);
523
+            $isOwner = true;
524
+        } else { // ... if not we need to correct ID for the unShare request
525
+            $remoteId = $this->getRemoteId($share);
526
+            $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
527
+            $this->revokeShare($share, false);
528
+        }
529
+
530
+        // send revoke notification to the other user, if initiator and owner are not the same user
531
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
532
+            $remoteId = $this->getRemoteId($share);
533
+            if ($isOwner) {
534
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
535
+            } else {
536
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
537
+            }
538
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
539
+        }
540
+    }
541
+
542
+    /**
543
+     * in case of a re-share we need to send the other use (initiator or owner)
544
+     * a message that the file was unshared
545
+     *
546
+     * @param IShare $share
547
+     * @param bool $isOwner the user can either be the owner or the user who re-sahred it
548
+     * @throws ShareNotFound
549
+     * @throws \OC\HintException
550
+     */
551
+    protected function revokeShare($share, $isOwner) {
552
+        // also send a unShare request to the initiator, if this is a different user than the owner
553
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
554
+            if ($isOwner) {
555
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
556
+            } else {
557
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
558
+            }
559
+            $remoteId = $this->getRemoteId($share);
560
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
561
+        }
562
+    }
563
+
564
+    /**
565
+     * remove share from table
566
+     *
567
+     * @param IShare $share
568
+     */
569
+    public function removeShareFromTable(IShare $share) {
570
+        $this->removeShareFromTableById($share->getId());
571
+    }
572
+
573
+    /**
574
+     * remove share from table
575
+     *
576
+     * @param string $shareId
577
+     */
578
+    private function removeShareFromTableById($shareId) {
579
+        $qb = $this->dbConnection->getQueryBuilder();
580
+        $qb->delete('share')
581
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
582
+        $qb->execute();
583
+
584
+        $qb->delete('federated_reshares')
585
+            ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
586
+        $qb->execute();
587
+    }
588
+
589
+    /**
590
+     * @inheritdoc
591
+     */
592
+    public function deleteFromSelf(IShare $share, $recipient) {
593
+        // nothing to do here. Technically deleteFromSelf in the context of federated
594
+        // shares is a umount of a external storage. This is handled here
595
+        // apps/files_sharing/lib/external/manager.php
596
+        // TODO move this code over to this app
597
+    }
598
+
599
+
600
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
601
+        $qb = $this->dbConnection->getQueryBuilder();
602
+        $qb->select('*')
603
+            ->from('share', 's')
604
+            ->andWhere($qb->expr()->orX(
605
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
606
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
607
+            ))
608
+            ->andWhere(
609
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
610
+            );
611
+
612
+        /**
613
+         * Reshares for this user are shares where they are the owner.
614
+         */
615
+        if ($reshares === false) {
616
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
617
+        } else {
618
+            $qb->andWhere(
619
+                $qb->expr()->orX(
620
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
621
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
622
+                )
623
+            );
624
+        }
625
+
626
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
627
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
628
+
629
+        $qb->orderBy('id');
630
+
631
+        $cursor = $qb->execute();
632
+        $shares = [];
633
+        while ($data = $cursor->fetch()) {
634
+            $shares[$data['fileid']][] = $this->createShareObject($data);
635
+        }
636
+        $cursor->closeCursor();
637
+
638
+        return $shares;
639
+    }
640
+
641
+    /**
642
+     * @inheritdoc
643
+     */
644
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
645
+        $qb = $this->dbConnection->getQueryBuilder();
646
+        $qb->select('*')
647
+            ->from('share');
648
+
649
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
650
+
651
+        /**
652
+         * Reshares for this user are shares where they are the owner.
653
+         */
654
+        if ($reshares === false) {
655
+            //Special case for old shares created via the web UI
656
+            $or1 = $qb->expr()->andX(
657
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
658
+                $qb->expr()->isNull('uid_initiator')
659
+            );
660
+
661
+            $qb->andWhere(
662
+                $qb->expr()->orX(
663
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
664
+                    $or1
665
+                )
666
+            );
667
+        } else {
668
+            $qb->andWhere(
669
+                $qb->expr()->orX(
670
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
671
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
672
+                )
673
+            );
674
+        }
675
+
676
+        if ($node !== null) {
677
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
678
+        }
679
+
680
+        if ($limit !== -1) {
681
+            $qb->setMaxResults($limit);
682
+        }
683
+
684
+        $qb->setFirstResult($offset);
685
+        $qb->orderBy('id');
686
+
687
+        $cursor = $qb->execute();
688
+        $shares = [];
689
+        while($data = $cursor->fetch()) {
690
+            $shares[] = $this->createShareObject($data);
691
+        }
692
+        $cursor->closeCursor();
693
+
694
+        return $shares;
695
+    }
696
+
697
+    /**
698
+     * @inheritdoc
699
+     */
700
+    public function getShareById($id, $recipientId = null) {
701
+        $qb = $this->dbConnection->getQueryBuilder();
702
+
703
+        $qb->select('*')
704
+            ->from('share')
705
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
706
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
707
+
708
+        $cursor = $qb->execute();
709
+        $data = $cursor->fetch();
710
+        $cursor->closeCursor();
711
+
712
+        if ($data === false) {
713
+            throw new ShareNotFoundException('Can not find share with ID: ' . $id);
714
+        }
715
+
716
+        try {
717
+            $share = $this->createShareObject($data);
718
+        } catch (InvalidShare $e) {
719
+            throw new ShareNotFoundException();
720
+        }
721
+
722
+        return $share;
723
+    }
724
+
725
+    /**
726
+     * Get shares for a given path
727
+     *
728
+     * @param \OCP\Files\Node $path
729
+     * @return IShare[]
730
+     */
731
+    public function getSharesByPath(Node $path) {
732
+        $qb = $this->dbConnection->getQueryBuilder();
733
+
734
+        $cursor = $qb->select('*')
735
+            ->from('share')
736
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
737
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
738
+            ->execute();
739
+
740
+        $shares = [];
741
+        while($data = $cursor->fetch()) {
742
+            $shares[] = $this->createShareObject($data);
743
+        }
744
+        $cursor->closeCursor();
745
+
746
+        return $shares;
747
+    }
748
+
749
+    /**
750
+     * @inheritdoc
751
+     */
752
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
753
+        /** @var IShare[] $shares */
754
+        $shares = [];
755
+
756
+        //Get shares directly with this user
757
+        $qb = $this->dbConnection->getQueryBuilder();
758
+        $qb->select('*')
759
+            ->from('share');
760
+
761
+        // Order by id
762
+        $qb->orderBy('id');
763
+
764
+        // Set limit and offset
765
+        if ($limit !== -1) {
766
+            $qb->setMaxResults($limit);
767
+        }
768
+        $qb->setFirstResult($offset);
769
+
770
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
771
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
772
+
773
+        // Filter by node if provided
774
+        if ($node !== null) {
775
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
776
+        }
777
+
778
+        $cursor = $qb->execute();
779
+
780
+        while($data = $cursor->fetch()) {
781
+            $shares[] = $this->createShareObject($data);
782
+        }
783
+        $cursor->closeCursor();
784
+
785
+
786
+        return $shares;
787
+    }
788
+
789
+    /**
790
+     * Get a share by token
791
+     *
792
+     * @param string $token
793
+     * @return IShare
794
+     * @throws ShareNotFound
795
+     */
796
+    public function getShareByToken($token) {
797
+        $qb = $this->dbConnection->getQueryBuilder();
798
+
799
+        $cursor = $qb->select('*')
800
+            ->from('share')
801
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
802
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
803
+            ->execute();
804
+
805
+        $data = $cursor->fetch();
806
+
807
+        if ($data === false) {
808
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
809
+        }
810
+
811
+        try {
812
+            $share = $this->createShareObject($data);
813
+        } catch (InvalidShare $e) {
814
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
815
+        }
816
+
817
+        return $share;
818
+    }
819
+
820
+    /**
821
+     * get database row of a give share
822
+     *
823
+     * @param $id
824
+     * @return array
825
+     * @throws ShareNotFound
826
+     */
827
+    private function getRawShare($id) {
828
+
829
+        // Now fetch the inserted share and create a complete share object
830
+        $qb = $this->dbConnection->getQueryBuilder();
831
+        $qb->select('*')
832
+            ->from('share')
833
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
834
+
835
+        $cursor = $qb->execute();
836
+        $data = $cursor->fetch();
837
+        $cursor->closeCursor();
838
+
839
+        if ($data === false) {
840
+            throw new ShareNotFound;
841
+        }
842
+
843
+        return $data;
844
+    }
845
+
846
+    /**
847
+     * Create a share object from an database row
848
+     *
849
+     * @param array $data
850
+     * @return IShare
851
+     * @throws InvalidShare
852
+     * @throws ShareNotFound
853
+     */
854
+    private function createShareObject($data) {
855
+
856
+        $share = new Share($this->rootFolder, $this->userManager);
857
+        $share->setId((int)$data['id'])
858
+            ->setShareType((int)$data['share_type'])
859
+            ->setPermissions((int)$data['permissions'])
860
+            ->setTarget($data['file_target'])
861
+            ->setMailSend((bool)$data['mail_send'])
862
+            ->setToken($data['token']);
863
+
864
+        $shareTime = new \DateTime();
865
+        $shareTime->setTimestamp((int)$data['stime']);
866
+        $share->setShareTime($shareTime);
867
+        $share->setSharedWith($data['share_with']);
868
+
869
+        if ($data['uid_initiator'] !== null) {
870
+            $share->setShareOwner($data['uid_owner']);
871
+            $share->setSharedBy($data['uid_initiator']);
872
+        } else {
873
+            //OLD SHARE
874
+            $share->setSharedBy($data['uid_owner']);
875
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
876
+
877
+            $owner = $path->getOwner();
878
+            $share->setShareOwner($owner->getUID());
879
+        }
880
+
881
+        $share->setNodeId((int)$data['file_source']);
882
+        $share->setNodeType($data['item_type']);
883
+
884
+        $share->setProviderId($this->identifier());
885
+
886
+        return $share;
887
+    }
888
+
889
+    /**
890
+     * Get the node with file $id for $user
891
+     *
892
+     * @param string $userId
893
+     * @param int $id
894
+     * @return \OCP\Files\File|\OCP\Files\Folder
895
+     * @throws InvalidShare
896
+     */
897
+    private function getNode($userId, $id) {
898
+        try {
899
+            $userFolder = $this->rootFolder->getUserFolder($userId);
900
+        } catch (NotFoundException $e) {
901
+            throw new InvalidShare();
902
+        }
903
+
904
+        $nodes = $userFolder->getById($id);
905
+
906
+        if (empty($nodes)) {
907
+            throw new InvalidShare();
908
+        }
909
+
910
+        return $nodes[0];
911
+    }
912
+
913
+    /**
914
+     * A user is deleted from the system
915
+     * So clean up the relevant shares.
916
+     *
917
+     * @param string $uid
918
+     * @param int $shareType
919
+     */
920
+    public function userDeleted($uid, $shareType) {
921
+        //TODO: probabaly a good idea to send unshare info to remote servers
922
+
923
+        $qb = $this->dbConnection->getQueryBuilder();
924
+
925
+        $qb->delete('share')
926
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
927
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
928
+            ->execute();
929
+    }
930
+
931
+    /**
932
+     * This provider does not handle groups
933
+     *
934
+     * @param string $gid
935
+     */
936
+    public function groupDeleted($gid) {
937
+        // We don't handle groups here
938
+    }
939
+
940
+    /**
941
+     * This provider does not handle groups
942
+     *
943
+     * @param string $uid
944
+     * @param string $gid
945
+     */
946
+    public function userDeletedFromGroup($uid, $gid) {
947
+        // We don't handle groups here
948
+    }
949
+
950
+    /**
951
+     * check if users from other Nextcloud instances are allowed to mount public links share by this instance
952
+     *
953
+     * @return bool
954
+     */
955
+    public function isOutgoingServer2serverShareEnabled() {
956
+        if ($this->gsConfig->onlyInternalFederation()) {
957
+            return false;
958
+        }
959
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
960
+        return ($result === 'yes');
961
+    }
962
+
963
+    /**
964
+     * check if users are allowed to mount public links from other Nextclouds
965
+     *
966
+     * @return bool
967
+     */
968
+    public function isIncomingServer2serverShareEnabled() {
969
+        if ($this->gsConfig->onlyInternalFederation()) {
970
+            return false;
971
+        }
972
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
973
+        return ($result === 'yes');
974
+    }
975
+
976
+    /**
977
+     * Check if querying sharees on the lookup server is enabled
978
+     *
979
+     * @return bool
980
+     */
981
+    public function isLookupServerQueriesEnabled() {
982
+        // in a global scale setup we should always query the lookup server
983
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
984
+            return true;
985
+        }
986
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
987
+        return ($result === 'yes');
988
+    }
989
+
990
+
991
+    /**
992
+     * Check if it is allowed to publish user specific data to the lookup server
993
+     *
994
+     * @return bool
995
+     */
996
+    public function isLookupServerUploadEnabled() {
997
+        // in a global scale setup the admin is responsible to keep the lookup server up-to-date
998
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
999
+            return false;
1000
+        }
1001
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1002
+        return ($result === 'yes');
1003
+    }
1004
+
1005
+    /**
1006
+     * @inheritdoc
1007
+     */
1008
+    public function getAccessList($nodes, $currentAccess) {
1009
+        $ids = [];
1010
+        foreach ($nodes as $node) {
1011
+            $ids[] = $node->getId();
1012
+        }
1013
+
1014
+        $qb = $this->dbConnection->getQueryBuilder();
1015
+        $qb->select('share_with', 'token', 'file_source')
1016
+            ->from('share')
1017
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1018
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1019
+            ->andWhere($qb->expr()->orX(
1020
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1021
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1022
+            ));
1023
+        $cursor = $qb->execute();
1024
+
1025
+        if ($currentAccess === false) {
1026
+            $remote = $cursor->fetch() !== false;
1027
+            $cursor->closeCursor();
1028
+
1029
+            return ['remote' => $remote];
1030
+        }
1031
+
1032
+        $remote = [];
1033
+        while ($row = $cursor->fetch()) {
1034
+            $remote[$row['share_with']] = [
1035
+                'node_id' => $row['file_source'],
1036
+                'token' => $row['token'],
1037
+            ];
1038
+        }
1039
+        $cursor->closeCursor();
1040
+
1041
+        return ['remote' => $remote];
1042
+    }
1043 1043
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php 1 patch
Indentation   +627 added lines, -627 removed lines patch added patch discarded remove patch
@@ -52,633 +52,633 @@
 block discarded – undo
52 52
 
53 53
 class CloudFederationProviderFiles implements ICloudFederationProvider {
54 54
 
55
-	/** @var IAppManager */
56
-	private $appManager;
57
-
58
-	/** @var FederatedShareProvider */
59
-	private $federatedShareProvider;
60
-
61
-	/** @var AddressHandler */
62
-	private $addressHandler;
63
-
64
-	/** @var ILogger */
65
-	private $logger;
66
-
67
-	/** @var IUserManager */
68
-	private $userManager;
69
-
70
-	/** @var ICloudIdManager */
71
-	private $cloudIdManager;
72
-
73
-	/** @var IActivityManager */
74
-	private $activityManager;
75
-
76
-	/** @var INotificationManager */
77
-	private $notificationManager;
78
-
79
-	/** @var IURLGenerator */
80
-	private $urlGenerator;
81
-
82
-	/** @var ICloudFederationFactory */
83
-	private $cloudFederationFactory;
84
-
85
-	/** @var ICloudFederationProviderManager */
86
-	private $cloudFederationProviderManager;
87
-
88
-	/** @var IDBConnection */
89
-	private $connection;
90
-
91
-	/**
92
-	 * CloudFederationProvider constructor.
93
-	 *
94
-	 * @param IAppManager $appManager
95
-	 * @param FederatedShareProvider $federatedShareProvider
96
-	 * @param AddressHandler $addressHandler
97
-	 * @param ILogger $logger
98
-	 * @param IUserManager $userManager
99
-	 * @param ICloudIdManager $cloudIdManager
100
-	 * @param IActivityManager $activityManager
101
-	 * @param INotificationManager $notificationManager
102
-	 * @param IURLGenerator $urlGenerator
103
-	 * @param ICloudFederationFactory $cloudFederationFactory
104
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
105
-	 * @param IDBConnection $connection
106
-	 */
107
-	public function __construct(IAppManager $appManager,
108
-								FederatedShareProvider $federatedShareProvider,
109
-								AddressHandler $addressHandler,
110
-								ILogger $logger,
111
-								IUserManager $userManager,
112
-								ICloudIdManager $cloudIdManager,
113
-								IActivityManager $activityManager,
114
-								INotificationManager $notificationManager,
115
-								IURLGenerator $urlGenerator,
116
-								ICloudFederationFactory $cloudFederationFactory,
117
-								ICloudFederationProviderManager $cloudFederationProviderManager,
118
-								IDBConnection $connection
119
-	) {
120
-		$this->appManager = $appManager;
121
-		$this->federatedShareProvider = $federatedShareProvider;
122
-		$this->addressHandler = $addressHandler;
123
-		$this->logger = $logger;
124
-		$this->userManager = $userManager;
125
-		$this->cloudIdManager = $cloudIdManager;
126
-		$this->activityManager = $activityManager;
127
-		$this->notificationManager = $notificationManager;
128
-		$this->urlGenerator = $urlGenerator;
129
-		$this->cloudFederationFactory = $cloudFederationFactory;
130
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
131
-		$this->connection = $connection;
132
-	}
133
-
134
-
135
-
136
-	/**
137
-	 * @return string
138
-	 */
139
-	public function getShareType() {
140
-		return 'file';
141
-	}
142
-
143
-	/**
144
-	 * share received from another server
145
-	 *
146
-	 * @param ICloudFederationShare $share
147
-	 * @return string provider specific unique ID of the share
148
-	 *
149
-	 * @throws ProviderCouldNotAddShareException
150
-	 * @throws \OCP\AppFramework\QueryException
151
-	 * @throws \OC\HintException
152
-	 * @since 14.0.0
153
-	 */
154
-	public function shareReceived(ICloudFederationShare $share) {
155
-
156
-		if (!$this->isS2SEnabled(true)) {
157
-			throw new ProviderCouldNotAddShareException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
158
-		}
159
-
160
-		$protocol = $share->getProtocol();
161
-		if ($protocol['name'] !== 'webdav') {
162
-			throw new ProviderCouldNotAddShareException('Unsupported protocol for data exchange.', '', Http::STATUS_NOT_IMPLEMENTED);
163
-		}
164
-
165
-		list($ownerUid, $remote) = $this->addressHandler->splitUserRemote($share->getOwner());
166
-
167
-		$remote = $remote;
168
-		$token = $share->getShareSecret();
169
-		$name = $share->getResourceName();
170
-		$owner = $share->getOwnerDisplayName();
171
-		$sharedBy = $share->getSharedByDisplayName();
172
-		$shareWith = $share->getShareWith();
173
-		$remoteId = $share->getProviderId();
174
-		$sharedByFederatedId = $share->getSharedBy();
175
-		$ownerFederatedId = $share->getOwner();
176
-
177
-		// if no explicit information about the person who created the share was send
178
-		// we assume that the share comes from the owner
179
-		if ($sharedByFederatedId === null) {
180
-			$sharedBy = $owner;
181
-			$sharedByFederatedId = $ownerFederatedId;
182
-		}
183
-
184
-		if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
185
-
186
-			if (!Util::isValidFileName($name)) {
187
-				throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
188
-			}
189
-
190
-			// FIXME this should be a method in the user management instead
191
-			$this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
192
-			Util::emitHook(
193
-				'\OCA\Files_Sharing\API\Server2Server',
194
-				'preLoginNameUsedAsUserName',
195
-				array('uid' => &$shareWith)
196
-			);
197
-			$this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
198
-
199
-			if (!$this->userManager->userExists($shareWith)) {
200
-				throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
201
-			}
202
-
203
-			\OC_Util::setupFS($shareWith);
204
-
205
-			$externalManager = new \OCA\Files_Sharing\External\Manager(
206
-				\OC::$server->getDatabaseConnection(),
207
-				Filesystem::getMountManager(),
208
-				Filesystem::getLoader(),
209
-				\OC::$server->getHTTPClientService(),
210
-				\OC::$server->getNotificationManager(),
211
-				\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
212
-				\OC::$server->getCloudFederationProviderManager(),
213
-				\OC::$server->getCloudFederationFactory(),
214
-				$shareWith
215
-			);
216
-
217
-			try {
218
-				$externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId);
219
-				$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
220
-
221
-				$event = $this->activityManager->generateEvent();
222
-				$event->setApp('files_sharing')
223
-					->setType('remote_share')
224
-					->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
225
-					->setAffectedUser($shareWith)
226
-					->setObject('remote_share', (int)$shareId, $name);
227
-				\OC::$server->getActivityManager()->publish($event);
228
-
229
-				$notification = $this->notificationManager->createNotification();
230
-				$notification->setApp('files_sharing')
231
-					->setUser($shareWith)
232
-					->setDateTime(new \DateTime())
233
-					->setObject('remote_share', $shareId)
234
-					->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/')]);
235
-
236
-				$declineAction = $notification->createAction();
237
-				$declineAction->setLabel('decline')
238
-					->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
239
-				$notification->addAction($declineAction);
240
-
241
-				$acceptAction = $notification->createAction();
242
-				$acceptAction->setLabel('accept')
243
-					->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
244
-				$notification->addAction($acceptAction);
245
-
246
-				$this->notificationManager->notify($notification);
247
-
248
-				return $shareId;
249
-			} catch (\Exception $e) {
250
-				$this->logger->logException($e, [
251
-					'message' => 'Server can not add remote share.',
252
-					'level' => Util::ERROR,
253
-					'app' => 'files_sharing'
254
-				]);
255
-				throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
256
-			}
257
-		}
258
-
259
-		throw new ProviderCouldNotAddShareException('server can not add remote share, missing parameter', '', HTTP::STATUS_BAD_REQUEST);
260
-
261
-	}
262
-
263
-	/**
264
-	 * notification received from another server
265
-	 *
266
-	 * @param string $notificationType (e.g. SHARE_ACCEPTED)
267
-	 * @param string $providerId id of the share
268
-	 * @param array $notification payload of the notification
269
-	 * @return array data send back to the sender
270
-	 *
271
-	 * @throws ActionNotSupportedException
272
-	 * @throws AuthenticationFailedException
273
-	 * @throws BadRequestException
274
-	 * @throws ShareNotFoundException
275
-	 * @throws \OC\HintException
276
-	 * @since 14.0.0
277
-	 */
278
-	public function notificationReceived($notificationType, $providerId, array $notification) {
279
-
280
-		switch ($notificationType) {
281
-			case 'SHARE_ACCEPTED':
282
-				return $this->shareAccepted($providerId, $notification);
283
-			case 'SHARE_DECLINED':
284
-				return $this->shareDeclined($providerId, $notification);
285
-			case 'SHARE_UNSHARED':
286
-				return $this->unshare($providerId, $notification);
287
-			case 'REQUEST_RESHARE':
288
-				return $this->reshareRequested($providerId, $notification);
289
-			case 'RESHARE_UNDO':
290
-				return $this->undoReshare($providerId, $notification);
291
-		}
292
-
293
-
294
-		throw new BadRequestException([$notificationType]);
295
-	}
296
-
297
-	/**
298
-	 * process notification that the recipient accepted a share
299
-	 *
300
-	 * @param string $id
301
-	 * @param array $notification
302
-	 * @return array
303
-	 * @throws ActionNotSupportedException
304
-	 * @throws AuthenticationFailedException
305
-	 * @throws BadRequestException
306
-	 * @throws ShareNotFoundException
307
-	 * @throws \OC\HintException
308
-	 */
309
-	private function shareAccepted($id, $notification) {
310
-
311
-		if (!$this->isS2SEnabled()) {
312
-			throw new ActionNotSupportedException('Server does not support federated cloud sharing');
313
-		}
314
-
315
-		if (!isset($notification['sharedSecret'])) {
316
-			throw new BadRequestException(['sharedSecret']);
317
-		}
318
-
319
-		$token = $notification['sharedSecret'];
320
-
321
-		$share = $this->federatedShareProvider->getShareById($id);
322
-
323
-		$this->verifyShare($share, $token);
324
-		$this->executeAcceptShare($share);
325
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
326
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
327
-			$remoteId = $this->federatedShareProvider->getRemoteId($share);
328
-			$notification = $this->cloudFederationFactory->getCloudFederationNotification();
329
-			$notification->setMessage(
330
-				'SHARE_ACCEPTED',
331
-				'file',
332
-				$remoteId,
333
-				[
334
-					'sharedSecret' => $token,
335
-					'message' => 'Recipient accepted the re-share'
336
-				]
337
-
338
-			);
339
-			$this->cloudFederationProviderManager->sendNotification($remote, $notification);
340
-
341
-		}
342
-
343
-		return [];
344
-	}
345
-
346
-	/**
347
-	 * @param IShare $share
348
-	 * @throws ShareNotFoundException
349
-	 */
350
-	protected function executeAcceptShare(IShare $share) {
351
-		try {
352
-			$fileId = (int)$share->getNode()->getId();
353
-			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
354
-		} catch (\Exception $e) {
355
-			throw new ShareNotFoundException();
356
-		}
357
-
358
-		$event = $this->activityManager->generateEvent();
359
-		$event->setApp('files_sharing')
360
-			->setType('remote_share')
361
-			->setAffectedUser($this->getCorrectUid($share))
362
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
363
-			->setObject('files', $fileId, $file)
364
-			->setLink($link);
365
-		$this->activityManager->publish($event);
366
-	}
367
-
368
-	/**
369
-	 * process notification that the recipient declined a share
370
-	 *
371
-	 * @param string $id
372
-	 * @param array $notification
373
-	 * @return array
374
-	 * @throws ActionNotSupportedException
375
-	 * @throws AuthenticationFailedException
376
-	 * @throws BadRequestException
377
-	 * @throws ShareNotFound
378
-	 * @throws ShareNotFoundException
379
-	 * @throws \OC\HintException
380
-	 *
381
-	 */
382
-	protected function shareDeclined($id, $notification) {
383
-
384
-		if (!$this->isS2SEnabled()) {
385
-			throw new ActionNotSupportedException('Server does not support federated cloud sharing');
386
-		}
387
-
388
-		if (!isset($notification['sharedSecret'])) {
389
-			throw new BadRequestException(['sharedSecret']);
390
-		}
391
-
392
-		$token = $notification['sharedSecret'];
393
-
394
-		$share = $this->federatedShareProvider->getShareById($id);
395
-
396
-		$this->verifyShare($share, $token);
397
-
398
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
399
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
400
-			$remoteId = $this->federatedShareProvider->getRemoteId($share);
401
-			$notification = $this->cloudFederationFactory->getCloudFederationNotification();
402
-			$notification->setMessage(
403
-				'SHARE_DECLINED',
404
-				'file',
405
-				$remoteId,
406
-				[
407
-					'sharedSecret' => $token,
408
-					'message' => 'Recipient declined the re-share'
409
-				]
410
-
411
-			);
412
-			$this->cloudFederationProviderManager->sendNotification($remote, $notification);
413
-		}
414
-
415
-		$this->executeDeclineShare($share);
416
-
417
-		return [];
418
-
419
-	}
420
-
421
-	/**
422
-	 * delete declined share and create a activity
423
-	 *
424
-	 * @param IShare $share
425
-	 * @throws ShareNotFoundException
426
-	 */
427
-	protected function executeDeclineShare(IShare $share) {
428
-		$this->federatedShareProvider->removeShareFromTable($share);
429
-
430
-		try {
431
-			$fileId = (int)$share->getNode()->getId();
432
-			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
433
-		} catch (\Exception $e) {
434
-			throw new ShareNotFoundException();
435
-		}
436
-
437
-		$event = $this->activityManager->generateEvent();
438
-		$event->setApp('files_sharing')
439
-			->setType('remote_share')
440
-			->setAffectedUser($this->getCorrectUid($share))
441
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
442
-			->setObject('files', $fileId, $file)
443
-			->setLink($link);
444
-		$this->activityManager->publish($event);
445
-
446
-	}
447
-
448
-	/**
449
-	 * received the notification that the owner unshared a file from you
450
-	 *
451
-	 * @param string $id
452
-	 * @param string $notification
453
-	 * @return array
454
-	 * @throws AuthenticationFailedException
455
-	 * @throws BadRequestException
456
-	 * @throws ShareNotFoundException
457
-	 */
458
-	private function undoReshare($id, $notification) {
459
-
460
-		if (!isset($notification['sharedSecret'])) {
461
-			throw new BadRequestException(['sharedSecret']);
462
-		}
463
-		$token = $notification['sharedSecret'];
464
-
465
-		$share = $this->federatedShareProvider->getShareById($id);
466
-
467
-		$this->verifyShare($share, $token);
468
-		$this->federatedShareProvider->removeShareFromTable($share);
469
-		return [];
470
-	}
471
-
472
-	private function unshare($id, $notification) {
473
-		error_log("new unshare!");
474
-		if (!$this->isS2SEnabled(true)) {
475
-			throw new ActionNotSupportedException("incoming shares disabled!");
476
-		}
477
-
478
-		if (!isset($notification['sharedSecret'])) {
479
-			throw new BadRequestException(['sharedSecret']);
480
-		}
481
-		$token = $notification['sharedSecret'];
482
-
483
-		$qb = $this->connection->getQueryBuilder();
484
-		$qb->select('*')
485
-			->from('share_external')
486
-			->where(
487
-				$qb->expr()->andX(
488
-					$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
489
-					$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
490
-				)
491
-			);
492
-
493
-		$result = $qb->execute();
494
-		$share = $result->fetch();
495
-		$result->closeCursor();
496
-
497
-		if ($token && $id && !empty($share)) {
498
-
499
-			$remote = $this->cleanupRemote($share['remote']);
500
-
501
-			$owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
502
-			$mountpoint = $share['mountpoint'];
503
-			$user = $share['user'];
504
-
505
-			$qb = $this->connection->getQueryBuilder();
506
-			$qb->delete('share_external')
507
-				->where(
508
-					$qb->expr()->andX(
509
-						$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
510
-						$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
511
-					)
512
-				);
513
-
514
-			$qb->execute();
515
-
516
-			if ($share['accepted']) {
517
-				$path = trim($mountpoint, '/');
518
-			} else {
519
-				$path = trim($share['name'], '/');
520
-			}
521
-
522
-			$notification = $this->notificationManager->createNotification();
523
-			$notification->setApp('files_sharing')
524
-				->setUser($share['user'])
525
-				->setObject('remote_share', (int)$share['id']);
526
-			$this->notificationManager->markProcessed($notification);
527
-
528
-			$event = $this->activityManager->generateEvent();
529
-			$event->setApp('files_sharing')
530
-				->setType('remote_share')
531
-				->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
532
-				->setAffectedUser($user)
533
-				->setObject('remote_share', (int)$share['id'], $path);
534
-			\OC::$server->getActivityManager()->publish($event);
535
-		}
536
-
537
-		return [];
538
-	}
539
-
540
-	private function cleanupRemote($remote) {
541
-		$remote = substr($remote, strpos($remote, '://') + 3);
542
-
543
-		return rtrim($remote, '/');
544
-	}
545
-
546
-	/**
547
-	 * recipient of a share request to re-share the file with another user
548
-	 *
549
-	 * @param $id
550
-	 * @param $notification
551
-	 * @return array
552
-	 * @throws AuthenticationFailedException
553
-	 * @throws BadRequestException
554
-	 * @throws ProviderCouldNotAddShareException
555
-	 * @throws ShareNotFoundException
556
-	 * @throws ShareNotFound
557
-	 */
558
-	protected function reshareRequested($id, $notification) {
559
-
560
-		if (!isset($notification['sharedSecret'])) {
561
-			throw new BadRequestException(['sharedSecret']);
562
-		}
563
-		$token = $notification['sharedSecret'];
564
-
565
-		if (!isset($notification['shareWith'])) {
566
-			throw new BadRequestException(['shareWith']);
567
-		}
568
-		$shareWith = $notification['shareWith'];
569
-
570
-		if (!isset($notification['senderId'])) {
571
-			throw new BadRequestException(['senderId']);
572
-		}
573
-		$senderId = $notification['senderId'];
574
-
575
-		$share = $this->federatedShareProvider->getShareById($id);
576
-		// don't allow to share a file back to the owner
577
-		try {
578
-			list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
579
-			$owner = $share->getShareOwner();
580
-			$currentServer = $this->addressHandler->generateRemoteURL();
581
-			if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
582
-				throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
583
-			}
584
-		} catch (\Exception $e) {
585
-			throw new ProviderCouldNotAddShareException($e->getMessage());
586
-		}
587
-
588
-		$this->verifyShare($share, $token);
589
-
590
-		// check if re-sharing is allowed
591
-		if ($share->getPermissions() | ~Constants::PERMISSION_SHARE) {
592
-			// the recipient of the initial share is now the initiator for the re-share
593
-			$share->setSharedBy($share->getSharedWith());
594
-			$share->setSharedWith($shareWith);
595
-			$result = $this->federatedShareProvider->create($share);
596
-			$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
597
-			return ['token' => $result->getToken(), 'providerId' => $result->getId()];
598
-		} else {
599
-			throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
600
-		}
601
-
602
-		throw new BadRequestException([]);
603
-	}
604
-
605
-	/**
606
-	 * get file
607
-	 *
608
-	 * @param string $user
609
-	 * @param int $fileSource
610
-	 * @return array with internal path of the file and a absolute link to it
611
-	 */
612
-	private function getFile($user, $fileSource) {
613
-		\OC_Util::setupFS($user);
614
-
615
-		try {
616
-			$file = Filesystem::getPath($fileSource);
617
-		} catch (NotFoundException $e) {
618
-			$file = null;
619
-		}
620
-		$args = Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
621
-		$link = Util::linkToAbsolute('files', 'index.php', $args);
622
-
623
-		return array($file, $link);
624
-
625
-	}
626
-
627
-	/**
628
-	 * check if we are the initiator or the owner of a re-share and return the correct UID
629
-	 *
630
-	 * @param IShare $share
631
-	 * @return string
632
-	 */
633
-	protected function getCorrectUid(IShare $share) {
634
-		if ($this->userManager->userExists($share->getShareOwner())) {
635
-			return $share->getShareOwner();
636
-		}
637
-
638
-		return $share->getSharedBy();
639
-	}
640
-
641
-
642
-
643
-	/**
644
-	 * check if we got the right share
645
-	 *
646
-	 * @param IShare $share
647
-	 * @param string $token
648
-	 * @return bool
649
-	 * @throws AuthenticationFailedException
650
-	 */
651
-	protected function verifyShare(IShare $share, $token) {
652
-		if (
653
-			$share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
654
-			$share->getToken() === $token
655
-		) {
656
-			return true;
657
-		}
658
-
659
-		throw new AuthenticationFailedException();
660
-	}
661
-
662
-
663
-
664
-	/**
665
-	 * check if server-to-server sharing is enabled
666
-	 *
667
-	 * @param bool $incoming
668
-	 * @return bool
669
-	 */
670
-	private function isS2SEnabled($incoming = false) {
671
-
672
-		$result = $this->appManager->isEnabledForUser('files_sharing');
673
-
674
-		if ($incoming) {
675
-			$result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
676
-		} else {
677
-			$result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
678
-		}
679
-
680
-		return $result;
681
-	}
55
+    /** @var IAppManager */
56
+    private $appManager;
57
+
58
+    /** @var FederatedShareProvider */
59
+    private $federatedShareProvider;
60
+
61
+    /** @var AddressHandler */
62
+    private $addressHandler;
63
+
64
+    /** @var ILogger */
65
+    private $logger;
66
+
67
+    /** @var IUserManager */
68
+    private $userManager;
69
+
70
+    /** @var ICloudIdManager */
71
+    private $cloudIdManager;
72
+
73
+    /** @var IActivityManager */
74
+    private $activityManager;
75
+
76
+    /** @var INotificationManager */
77
+    private $notificationManager;
78
+
79
+    /** @var IURLGenerator */
80
+    private $urlGenerator;
81
+
82
+    /** @var ICloudFederationFactory */
83
+    private $cloudFederationFactory;
84
+
85
+    /** @var ICloudFederationProviderManager */
86
+    private $cloudFederationProviderManager;
87
+
88
+    /** @var IDBConnection */
89
+    private $connection;
90
+
91
+    /**
92
+     * CloudFederationProvider constructor.
93
+     *
94
+     * @param IAppManager $appManager
95
+     * @param FederatedShareProvider $federatedShareProvider
96
+     * @param AddressHandler $addressHandler
97
+     * @param ILogger $logger
98
+     * @param IUserManager $userManager
99
+     * @param ICloudIdManager $cloudIdManager
100
+     * @param IActivityManager $activityManager
101
+     * @param INotificationManager $notificationManager
102
+     * @param IURLGenerator $urlGenerator
103
+     * @param ICloudFederationFactory $cloudFederationFactory
104
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
105
+     * @param IDBConnection $connection
106
+     */
107
+    public function __construct(IAppManager $appManager,
108
+                                FederatedShareProvider $federatedShareProvider,
109
+                                AddressHandler $addressHandler,
110
+                                ILogger $logger,
111
+                                IUserManager $userManager,
112
+                                ICloudIdManager $cloudIdManager,
113
+                                IActivityManager $activityManager,
114
+                                INotificationManager $notificationManager,
115
+                                IURLGenerator $urlGenerator,
116
+                                ICloudFederationFactory $cloudFederationFactory,
117
+                                ICloudFederationProviderManager $cloudFederationProviderManager,
118
+                                IDBConnection $connection
119
+    ) {
120
+        $this->appManager = $appManager;
121
+        $this->federatedShareProvider = $federatedShareProvider;
122
+        $this->addressHandler = $addressHandler;
123
+        $this->logger = $logger;
124
+        $this->userManager = $userManager;
125
+        $this->cloudIdManager = $cloudIdManager;
126
+        $this->activityManager = $activityManager;
127
+        $this->notificationManager = $notificationManager;
128
+        $this->urlGenerator = $urlGenerator;
129
+        $this->cloudFederationFactory = $cloudFederationFactory;
130
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
131
+        $this->connection = $connection;
132
+    }
133
+
134
+
135
+
136
+    /**
137
+     * @return string
138
+     */
139
+    public function getShareType() {
140
+        return 'file';
141
+    }
142
+
143
+    /**
144
+     * share received from another server
145
+     *
146
+     * @param ICloudFederationShare $share
147
+     * @return string provider specific unique ID of the share
148
+     *
149
+     * @throws ProviderCouldNotAddShareException
150
+     * @throws \OCP\AppFramework\QueryException
151
+     * @throws \OC\HintException
152
+     * @since 14.0.0
153
+     */
154
+    public function shareReceived(ICloudFederationShare $share) {
155
+
156
+        if (!$this->isS2SEnabled(true)) {
157
+            throw new ProviderCouldNotAddShareException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
158
+        }
159
+
160
+        $protocol = $share->getProtocol();
161
+        if ($protocol['name'] !== 'webdav') {
162
+            throw new ProviderCouldNotAddShareException('Unsupported protocol for data exchange.', '', Http::STATUS_NOT_IMPLEMENTED);
163
+        }
164
+
165
+        list($ownerUid, $remote) = $this->addressHandler->splitUserRemote($share->getOwner());
166
+
167
+        $remote = $remote;
168
+        $token = $share->getShareSecret();
169
+        $name = $share->getResourceName();
170
+        $owner = $share->getOwnerDisplayName();
171
+        $sharedBy = $share->getSharedByDisplayName();
172
+        $shareWith = $share->getShareWith();
173
+        $remoteId = $share->getProviderId();
174
+        $sharedByFederatedId = $share->getSharedBy();
175
+        $ownerFederatedId = $share->getOwner();
176
+
177
+        // if no explicit information about the person who created the share was send
178
+        // we assume that the share comes from the owner
179
+        if ($sharedByFederatedId === null) {
180
+            $sharedBy = $owner;
181
+            $sharedByFederatedId = $ownerFederatedId;
182
+        }
183
+
184
+        if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
185
+
186
+            if (!Util::isValidFileName($name)) {
187
+                throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
188
+            }
189
+
190
+            // FIXME this should be a method in the user management instead
191
+            $this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
192
+            Util::emitHook(
193
+                '\OCA\Files_Sharing\API\Server2Server',
194
+                'preLoginNameUsedAsUserName',
195
+                array('uid' => &$shareWith)
196
+            );
197
+            $this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
198
+
199
+            if (!$this->userManager->userExists($shareWith)) {
200
+                throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
201
+            }
202
+
203
+            \OC_Util::setupFS($shareWith);
204
+
205
+            $externalManager = new \OCA\Files_Sharing\External\Manager(
206
+                \OC::$server->getDatabaseConnection(),
207
+                Filesystem::getMountManager(),
208
+                Filesystem::getLoader(),
209
+                \OC::$server->getHTTPClientService(),
210
+                \OC::$server->getNotificationManager(),
211
+                \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
212
+                \OC::$server->getCloudFederationProviderManager(),
213
+                \OC::$server->getCloudFederationFactory(),
214
+                $shareWith
215
+            );
216
+
217
+            try {
218
+                $externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId);
219
+                $shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
220
+
221
+                $event = $this->activityManager->generateEvent();
222
+                $event->setApp('files_sharing')
223
+                    ->setType('remote_share')
224
+                    ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
225
+                    ->setAffectedUser($shareWith)
226
+                    ->setObject('remote_share', (int)$shareId, $name);
227
+                \OC::$server->getActivityManager()->publish($event);
228
+
229
+                $notification = $this->notificationManager->createNotification();
230
+                $notification->setApp('files_sharing')
231
+                    ->setUser($shareWith)
232
+                    ->setDateTime(new \DateTime())
233
+                    ->setObject('remote_share', $shareId)
234
+                    ->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/')]);
235
+
236
+                $declineAction = $notification->createAction();
237
+                $declineAction->setLabel('decline')
238
+                    ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
239
+                $notification->addAction($declineAction);
240
+
241
+                $acceptAction = $notification->createAction();
242
+                $acceptAction->setLabel('accept')
243
+                    ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
244
+                $notification->addAction($acceptAction);
245
+
246
+                $this->notificationManager->notify($notification);
247
+
248
+                return $shareId;
249
+            } catch (\Exception $e) {
250
+                $this->logger->logException($e, [
251
+                    'message' => 'Server can not add remote share.',
252
+                    'level' => Util::ERROR,
253
+                    'app' => 'files_sharing'
254
+                ]);
255
+                throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
256
+            }
257
+        }
258
+
259
+        throw new ProviderCouldNotAddShareException('server can not add remote share, missing parameter', '', HTTP::STATUS_BAD_REQUEST);
260
+
261
+    }
262
+
263
+    /**
264
+     * notification received from another server
265
+     *
266
+     * @param string $notificationType (e.g. SHARE_ACCEPTED)
267
+     * @param string $providerId id of the share
268
+     * @param array $notification payload of the notification
269
+     * @return array data send back to the sender
270
+     *
271
+     * @throws ActionNotSupportedException
272
+     * @throws AuthenticationFailedException
273
+     * @throws BadRequestException
274
+     * @throws ShareNotFoundException
275
+     * @throws \OC\HintException
276
+     * @since 14.0.0
277
+     */
278
+    public function notificationReceived($notificationType, $providerId, array $notification) {
279
+
280
+        switch ($notificationType) {
281
+            case 'SHARE_ACCEPTED':
282
+                return $this->shareAccepted($providerId, $notification);
283
+            case 'SHARE_DECLINED':
284
+                return $this->shareDeclined($providerId, $notification);
285
+            case 'SHARE_UNSHARED':
286
+                return $this->unshare($providerId, $notification);
287
+            case 'REQUEST_RESHARE':
288
+                return $this->reshareRequested($providerId, $notification);
289
+            case 'RESHARE_UNDO':
290
+                return $this->undoReshare($providerId, $notification);
291
+        }
292
+
293
+
294
+        throw new BadRequestException([$notificationType]);
295
+    }
296
+
297
+    /**
298
+     * process notification that the recipient accepted a share
299
+     *
300
+     * @param string $id
301
+     * @param array $notification
302
+     * @return array
303
+     * @throws ActionNotSupportedException
304
+     * @throws AuthenticationFailedException
305
+     * @throws BadRequestException
306
+     * @throws ShareNotFoundException
307
+     * @throws \OC\HintException
308
+     */
309
+    private function shareAccepted($id, $notification) {
310
+
311
+        if (!$this->isS2SEnabled()) {
312
+            throw new ActionNotSupportedException('Server does not support federated cloud sharing');
313
+        }
314
+
315
+        if (!isset($notification['sharedSecret'])) {
316
+            throw new BadRequestException(['sharedSecret']);
317
+        }
318
+
319
+        $token = $notification['sharedSecret'];
320
+
321
+        $share = $this->federatedShareProvider->getShareById($id);
322
+
323
+        $this->verifyShare($share, $token);
324
+        $this->executeAcceptShare($share);
325
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
326
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
327
+            $remoteId = $this->federatedShareProvider->getRemoteId($share);
328
+            $notification = $this->cloudFederationFactory->getCloudFederationNotification();
329
+            $notification->setMessage(
330
+                'SHARE_ACCEPTED',
331
+                'file',
332
+                $remoteId,
333
+                [
334
+                    'sharedSecret' => $token,
335
+                    'message' => 'Recipient accepted the re-share'
336
+                ]
337
+
338
+            );
339
+            $this->cloudFederationProviderManager->sendNotification($remote, $notification);
340
+
341
+        }
342
+
343
+        return [];
344
+    }
345
+
346
+    /**
347
+     * @param IShare $share
348
+     * @throws ShareNotFoundException
349
+     */
350
+    protected function executeAcceptShare(IShare $share) {
351
+        try {
352
+            $fileId = (int)$share->getNode()->getId();
353
+            list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
354
+        } catch (\Exception $e) {
355
+            throw new ShareNotFoundException();
356
+        }
357
+
358
+        $event = $this->activityManager->generateEvent();
359
+        $event->setApp('files_sharing')
360
+            ->setType('remote_share')
361
+            ->setAffectedUser($this->getCorrectUid($share))
362
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
363
+            ->setObject('files', $fileId, $file)
364
+            ->setLink($link);
365
+        $this->activityManager->publish($event);
366
+    }
367
+
368
+    /**
369
+     * process notification that the recipient declined a share
370
+     *
371
+     * @param string $id
372
+     * @param array $notification
373
+     * @return array
374
+     * @throws ActionNotSupportedException
375
+     * @throws AuthenticationFailedException
376
+     * @throws BadRequestException
377
+     * @throws ShareNotFound
378
+     * @throws ShareNotFoundException
379
+     * @throws \OC\HintException
380
+     *
381
+     */
382
+    protected function shareDeclined($id, $notification) {
383
+
384
+        if (!$this->isS2SEnabled()) {
385
+            throw new ActionNotSupportedException('Server does not support federated cloud sharing');
386
+        }
387
+
388
+        if (!isset($notification['sharedSecret'])) {
389
+            throw new BadRequestException(['sharedSecret']);
390
+        }
391
+
392
+        $token = $notification['sharedSecret'];
393
+
394
+        $share = $this->federatedShareProvider->getShareById($id);
395
+
396
+        $this->verifyShare($share, $token);
397
+
398
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
399
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
400
+            $remoteId = $this->federatedShareProvider->getRemoteId($share);
401
+            $notification = $this->cloudFederationFactory->getCloudFederationNotification();
402
+            $notification->setMessage(
403
+                'SHARE_DECLINED',
404
+                'file',
405
+                $remoteId,
406
+                [
407
+                    'sharedSecret' => $token,
408
+                    'message' => 'Recipient declined the re-share'
409
+                ]
410
+
411
+            );
412
+            $this->cloudFederationProviderManager->sendNotification($remote, $notification);
413
+        }
414
+
415
+        $this->executeDeclineShare($share);
416
+
417
+        return [];
418
+
419
+    }
420
+
421
+    /**
422
+     * delete declined share and create a activity
423
+     *
424
+     * @param IShare $share
425
+     * @throws ShareNotFoundException
426
+     */
427
+    protected function executeDeclineShare(IShare $share) {
428
+        $this->federatedShareProvider->removeShareFromTable($share);
429
+
430
+        try {
431
+            $fileId = (int)$share->getNode()->getId();
432
+            list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
433
+        } catch (\Exception $e) {
434
+            throw new ShareNotFoundException();
435
+        }
436
+
437
+        $event = $this->activityManager->generateEvent();
438
+        $event->setApp('files_sharing')
439
+            ->setType('remote_share')
440
+            ->setAffectedUser($this->getCorrectUid($share))
441
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
442
+            ->setObject('files', $fileId, $file)
443
+            ->setLink($link);
444
+        $this->activityManager->publish($event);
445
+
446
+    }
447
+
448
+    /**
449
+     * received the notification that the owner unshared a file from you
450
+     *
451
+     * @param string $id
452
+     * @param string $notification
453
+     * @return array
454
+     * @throws AuthenticationFailedException
455
+     * @throws BadRequestException
456
+     * @throws ShareNotFoundException
457
+     */
458
+    private function undoReshare($id, $notification) {
459
+
460
+        if (!isset($notification['sharedSecret'])) {
461
+            throw new BadRequestException(['sharedSecret']);
462
+        }
463
+        $token = $notification['sharedSecret'];
464
+
465
+        $share = $this->federatedShareProvider->getShareById($id);
466
+
467
+        $this->verifyShare($share, $token);
468
+        $this->federatedShareProvider->removeShareFromTable($share);
469
+        return [];
470
+    }
471
+
472
+    private function unshare($id, $notification) {
473
+        error_log("new unshare!");
474
+        if (!$this->isS2SEnabled(true)) {
475
+            throw new ActionNotSupportedException("incoming shares disabled!");
476
+        }
477
+
478
+        if (!isset($notification['sharedSecret'])) {
479
+            throw new BadRequestException(['sharedSecret']);
480
+        }
481
+        $token = $notification['sharedSecret'];
482
+
483
+        $qb = $this->connection->getQueryBuilder();
484
+        $qb->select('*')
485
+            ->from('share_external')
486
+            ->where(
487
+                $qb->expr()->andX(
488
+                    $qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
489
+                    $qb->expr()->eq('share_token', $qb->createNamedParameter($token))
490
+                )
491
+            );
492
+
493
+        $result = $qb->execute();
494
+        $share = $result->fetch();
495
+        $result->closeCursor();
496
+
497
+        if ($token && $id && !empty($share)) {
498
+
499
+            $remote = $this->cleanupRemote($share['remote']);
500
+
501
+            $owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
502
+            $mountpoint = $share['mountpoint'];
503
+            $user = $share['user'];
504
+
505
+            $qb = $this->connection->getQueryBuilder();
506
+            $qb->delete('share_external')
507
+                ->where(
508
+                    $qb->expr()->andX(
509
+                        $qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
510
+                        $qb->expr()->eq('share_token', $qb->createNamedParameter($token))
511
+                    )
512
+                );
513
+
514
+            $qb->execute();
515
+
516
+            if ($share['accepted']) {
517
+                $path = trim($mountpoint, '/');
518
+            } else {
519
+                $path = trim($share['name'], '/');
520
+            }
521
+
522
+            $notification = $this->notificationManager->createNotification();
523
+            $notification->setApp('files_sharing')
524
+                ->setUser($share['user'])
525
+                ->setObject('remote_share', (int)$share['id']);
526
+            $this->notificationManager->markProcessed($notification);
527
+
528
+            $event = $this->activityManager->generateEvent();
529
+            $event->setApp('files_sharing')
530
+                ->setType('remote_share')
531
+                ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
532
+                ->setAffectedUser($user)
533
+                ->setObject('remote_share', (int)$share['id'], $path);
534
+            \OC::$server->getActivityManager()->publish($event);
535
+        }
536
+
537
+        return [];
538
+    }
539
+
540
+    private function cleanupRemote($remote) {
541
+        $remote = substr($remote, strpos($remote, '://') + 3);
542
+
543
+        return rtrim($remote, '/');
544
+    }
545
+
546
+    /**
547
+     * recipient of a share request to re-share the file with another user
548
+     *
549
+     * @param $id
550
+     * @param $notification
551
+     * @return array
552
+     * @throws AuthenticationFailedException
553
+     * @throws BadRequestException
554
+     * @throws ProviderCouldNotAddShareException
555
+     * @throws ShareNotFoundException
556
+     * @throws ShareNotFound
557
+     */
558
+    protected function reshareRequested($id, $notification) {
559
+
560
+        if (!isset($notification['sharedSecret'])) {
561
+            throw new BadRequestException(['sharedSecret']);
562
+        }
563
+        $token = $notification['sharedSecret'];
564
+
565
+        if (!isset($notification['shareWith'])) {
566
+            throw new BadRequestException(['shareWith']);
567
+        }
568
+        $shareWith = $notification['shareWith'];
569
+
570
+        if (!isset($notification['senderId'])) {
571
+            throw new BadRequestException(['senderId']);
572
+        }
573
+        $senderId = $notification['senderId'];
574
+
575
+        $share = $this->federatedShareProvider->getShareById($id);
576
+        // don't allow to share a file back to the owner
577
+        try {
578
+            list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
579
+            $owner = $share->getShareOwner();
580
+            $currentServer = $this->addressHandler->generateRemoteURL();
581
+            if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
582
+                throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
583
+            }
584
+        } catch (\Exception $e) {
585
+            throw new ProviderCouldNotAddShareException($e->getMessage());
586
+        }
587
+
588
+        $this->verifyShare($share, $token);
589
+
590
+        // check if re-sharing is allowed
591
+        if ($share->getPermissions() | ~Constants::PERMISSION_SHARE) {
592
+            // the recipient of the initial share is now the initiator for the re-share
593
+            $share->setSharedBy($share->getSharedWith());
594
+            $share->setSharedWith($shareWith);
595
+            $result = $this->federatedShareProvider->create($share);
596
+            $this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
597
+            return ['token' => $result->getToken(), 'providerId' => $result->getId()];
598
+        } else {
599
+            throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
600
+        }
601
+
602
+        throw new BadRequestException([]);
603
+    }
604
+
605
+    /**
606
+     * get file
607
+     *
608
+     * @param string $user
609
+     * @param int $fileSource
610
+     * @return array with internal path of the file and a absolute link to it
611
+     */
612
+    private function getFile($user, $fileSource) {
613
+        \OC_Util::setupFS($user);
614
+
615
+        try {
616
+            $file = Filesystem::getPath($fileSource);
617
+        } catch (NotFoundException $e) {
618
+            $file = null;
619
+        }
620
+        $args = Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
621
+        $link = Util::linkToAbsolute('files', 'index.php', $args);
622
+
623
+        return array($file, $link);
624
+
625
+    }
626
+
627
+    /**
628
+     * check if we are the initiator or the owner of a re-share and return the correct UID
629
+     *
630
+     * @param IShare $share
631
+     * @return string
632
+     */
633
+    protected function getCorrectUid(IShare $share) {
634
+        if ($this->userManager->userExists($share->getShareOwner())) {
635
+            return $share->getShareOwner();
636
+        }
637
+
638
+        return $share->getSharedBy();
639
+    }
640
+
641
+
642
+
643
+    /**
644
+     * check if we got the right share
645
+     *
646
+     * @param IShare $share
647
+     * @param string $token
648
+     * @return bool
649
+     * @throws AuthenticationFailedException
650
+     */
651
+    protected function verifyShare(IShare $share, $token) {
652
+        if (
653
+            $share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
654
+            $share->getToken() === $token
655
+        ) {
656
+            return true;
657
+        }
658
+
659
+        throw new AuthenticationFailedException();
660
+    }
661
+
662
+
663
+
664
+    /**
665
+     * check if server-to-server sharing is enabled
666
+     *
667
+     * @param bool $incoming
668
+     * @return bool
669
+     */
670
+    private function isS2SEnabled($incoming = false) {
671
+
672
+        $result = $this->appManager->isEnabledForUser('files_sharing');
673
+
674
+        if ($incoming) {
675
+            $result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
676
+        } else {
677
+            $result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
678
+        }
679
+
680
+        return $result;
681
+    }
682 682
 
683 683
 
684 684
 }
Please login to merge, or discard this patch.