Passed
Push — master ( 82d4bd...54baf6 )
by Roeland
13:48 queued 16s
created
apps/federatedfilesharing/lib/FederatedShareProvider.php 1 patch
Indentation   +1063 added lines, -1063 removed lines patch added patch discarded remove patch
@@ -57,1077 +57,1077 @@
 block discarded – undo
57 57
  */
58 58
 class FederatedShareProvider implements IShareProvider {
59 59
 
60
-	const SHARE_TYPE_REMOTE = 6;
61
-
62
-	/** @var IDBConnection */
63
-	private $dbConnection;
64
-
65
-	/** @var AddressHandler */
66
-	private $addressHandler;
67
-
68
-	/** @var Notifications */
69
-	private $notifications;
70
-
71
-	/** @var TokenHandler */
72
-	private $tokenHandler;
73
-
74
-	/** @var IL10N */
75
-	private $l;
76
-
77
-	/** @var ILogger */
78
-	private $logger;
79
-
80
-	/** @var IRootFolder */
81
-	private $rootFolder;
82
-
83
-	/** @var IConfig */
84
-	private $config;
85
-
86
-	/** @var string */
87
-	private $externalShareTable = 'share_external';
88
-
89
-	/** @var IUserManager */
90
-	private $userManager;
91
-
92
-	/** @var ICloudIdManager */
93
-	private $cloudIdManager;
94
-
95
-	/** @var \OCP\GlobalScale\IConfig */
96
-	private $gsConfig;
97
-
98
-	/** @var ICloudFederationProviderManager */
99
-	private $cloudFederationProviderManager;
100
-
101
-	/** @var array list of supported share types */
102
-	private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
103
-
104
-	/**
105
-	 * DefaultShareProvider constructor.
106
-	 *
107
-	 * @param IDBConnection $connection
108
-	 * @param AddressHandler $addressHandler
109
-	 * @param Notifications $notifications
110
-	 * @param TokenHandler $tokenHandler
111
-	 * @param IL10N $l10n
112
-	 * @param ILogger $logger
113
-	 * @param IRootFolder $rootFolder
114
-	 * @param IConfig $config
115
-	 * @param IUserManager $userManager
116
-	 * @param ICloudIdManager $cloudIdManager
117
-	 * @param \OCP\GlobalScale\IConfig $globalScaleConfig
118
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
119
-	 */
120
-	public function __construct(
121
-			IDBConnection $connection,
122
-			AddressHandler $addressHandler,
123
-			Notifications $notifications,
124
-			TokenHandler $tokenHandler,
125
-			IL10N $l10n,
126
-			ILogger $logger,
127
-			IRootFolder $rootFolder,
128
-			IConfig $config,
129
-			IUserManager $userManager,
130
-			ICloudIdManager $cloudIdManager,
131
-			\OCP\GlobalScale\IConfig $globalScaleConfig,
132
-			ICloudFederationProviderManager $cloudFederationProviderManager
133
-	) {
134
-		$this->dbConnection = $connection;
135
-		$this->addressHandler = $addressHandler;
136
-		$this->notifications = $notifications;
137
-		$this->tokenHandler = $tokenHandler;
138
-		$this->l = $l10n;
139
-		$this->logger = $logger;
140
-		$this->rootFolder = $rootFolder;
141
-		$this->config = $config;
142
-		$this->userManager = $userManager;
143
-		$this->cloudIdManager = $cloudIdManager;
144
-		$this->gsConfig = $globalScaleConfig;
145
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
146
-	}
147
-
148
-	/**
149
-	 * Return the identifier of this provider.
150
-	 *
151
-	 * @return string Containing only [a-zA-Z0-9]
152
-	 */
153
-	public function identifier() {
154
-		return 'ocFederatedSharing';
155
-	}
156
-
157
-	/**
158
-	 * Share a path
159
-	 *
160
-	 * @param IShare $share
161
-	 * @return IShare The share object
162
-	 * @throws ShareNotFound
163
-	 * @throws \Exception
164
-	 */
165
-	public function create(IShare $share) {
166
-
167
-		$shareWith = $share->getSharedWith();
168
-		$itemSource = $share->getNodeId();
169
-		$itemType = $share->getNodeType();
170
-		$permissions = $share->getPermissions();
171
-		$sharedBy = $share->getSharedBy();
172
-		$shareType = $share->getShareType();
173
-
174
-		if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP &&
175
-			!$this->isOutgoingServer2serverGroupShareEnabled()
176
-		) {
177
-			$message = 'It is not allowed to send federated group shares from this server.';
178
-			$message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
179
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
180
-			throw new \Exception($message_t);
181
-		}
182
-
183
-		/*
60
+    const SHARE_TYPE_REMOTE = 6;
61
+
62
+    /** @var IDBConnection */
63
+    private $dbConnection;
64
+
65
+    /** @var AddressHandler */
66
+    private $addressHandler;
67
+
68
+    /** @var Notifications */
69
+    private $notifications;
70
+
71
+    /** @var TokenHandler */
72
+    private $tokenHandler;
73
+
74
+    /** @var IL10N */
75
+    private $l;
76
+
77
+    /** @var ILogger */
78
+    private $logger;
79
+
80
+    /** @var IRootFolder */
81
+    private $rootFolder;
82
+
83
+    /** @var IConfig */
84
+    private $config;
85
+
86
+    /** @var string */
87
+    private $externalShareTable = 'share_external';
88
+
89
+    /** @var IUserManager */
90
+    private $userManager;
91
+
92
+    /** @var ICloudIdManager */
93
+    private $cloudIdManager;
94
+
95
+    /** @var \OCP\GlobalScale\IConfig */
96
+    private $gsConfig;
97
+
98
+    /** @var ICloudFederationProviderManager */
99
+    private $cloudFederationProviderManager;
100
+
101
+    /** @var array list of supported share types */
102
+    private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
103
+
104
+    /**
105
+     * DefaultShareProvider constructor.
106
+     *
107
+     * @param IDBConnection $connection
108
+     * @param AddressHandler $addressHandler
109
+     * @param Notifications $notifications
110
+     * @param TokenHandler $tokenHandler
111
+     * @param IL10N $l10n
112
+     * @param ILogger $logger
113
+     * @param IRootFolder $rootFolder
114
+     * @param IConfig $config
115
+     * @param IUserManager $userManager
116
+     * @param ICloudIdManager $cloudIdManager
117
+     * @param \OCP\GlobalScale\IConfig $globalScaleConfig
118
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
119
+     */
120
+    public function __construct(
121
+            IDBConnection $connection,
122
+            AddressHandler $addressHandler,
123
+            Notifications $notifications,
124
+            TokenHandler $tokenHandler,
125
+            IL10N $l10n,
126
+            ILogger $logger,
127
+            IRootFolder $rootFolder,
128
+            IConfig $config,
129
+            IUserManager $userManager,
130
+            ICloudIdManager $cloudIdManager,
131
+            \OCP\GlobalScale\IConfig $globalScaleConfig,
132
+            ICloudFederationProviderManager $cloudFederationProviderManager
133
+    ) {
134
+        $this->dbConnection = $connection;
135
+        $this->addressHandler = $addressHandler;
136
+        $this->notifications = $notifications;
137
+        $this->tokenHandler = $tokenHandler;
138
+        $this->l = $l10n;
139
+        $this->logger = $logger;
140
+        $this->rootFolder = $rootFolder;
141
+        $this->config = $config;
142
+        $this->userManager = $userManager;
143
+        $this->cloudIdManager = $cloudIdManager;
144
+        $this->gsConfig = $globalScaleConfig;
145
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
146
+    }
147
+
148
+    /**
149
+     * Return the identifier of this provider.
150
+     *
151
+     * @return string Containing only [a-zA-Z0-9]
152
+     */
153
+    public function identifier() {
154
+        return 'ocFederatedSharing';
155
+    }
156
+
157
+    /**
158
+     * Share a path
159
+     *
160
+     * @param IShare $share
161
+     * @return IShare The share object
162
+     * @throws ShareNotFound
163
+     * @throws \Exception
164
+     */
165
+    public function create(IShare $share) {
166
+
167
+        $shareWith = $share->getSharedWith();
168
+        $itemSource = $share->getNodeId();
169
+        $itemType = $share->getNodeType();
170
+        $permissions = $share->getPermissions();
171
+        $sharedBy = $share->getSharedBy();
172
+        $shareType = $share->getShareType();
173
+
174
+        if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP &&
175
+            !$this->isOutgoingServer2serverGroupShareEnabled()
176
+        ) {
177
+            $message = 'It is not allowed to send federated group shares from this server.';
178
+            $message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
179
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
180
+            throw new \Exception($message_t);
181
+        }
182
+
183
+        /*
184 184
 		 * Check if file is not already shared with the remote user
185 185
 		 */
186
-		$alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
187
-		$alreadySharedGroup = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
188
-		if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
189
-			$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
190
-			$message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($share->getNode()->getName(), $shareWith));
191
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
192
-			throw new \Exception($message_t);
193
-		}
194
-
195
-
196
-		// don't allow federated shares if source and target server are the same
197
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
198
-		$currentServer = $this->addressHandler->generateRemoteURL();
199
-		$currentUser = $sharedBy;
200
-		if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
201
-			$message = 'Not allowed to create a federated share with the same user.';
202
-			$message_t = $this->l->t('Not allowed to create a federated share with the same user');
203
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
204
-			throw new \Exception($message_t);
205
-		}
206
-
207
-
208
-		$share->setSharedWith($cloudId->getId());
209
-
210
-		try {
211
-			$remoteShare = $this->getShareFromExternalShareTable($share);
212
-		} catch (ShareNotFound $e) {
213
-			$remoteShare = null;
214
-		}
215
-
216
-		if ($remoteShare) {
217
-			try {
218
-				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
219
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
220
-				$share->setId($shareId);
221
-				list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
222
-				// remote share was create successfully if we get a valid token as return
223
-				$send = is_string($token) && $token !== '';
224
-			} catch (\Exception $e) {
225
-				// fall back to old re-share behavior if the remote server
226
-				// doesn't support flat re-shares (was introduced with Nextcloud 9.1)
227
-				$this->removeShareFromTable($share);
228
-				$shareId = $this->createFederatedShare($share);
229
-			}
230
-			if ($send) {
231
-				$this->updateSuccessfulReshare($shareId, $token);
232
-				$this->storeRemoteId($shareId, $remoteId);
233
-			} else {
234
-				$this->removeShareFromTable($share);
235
-				$message_t = $this->l->t('File is already shared with %s', [$shareWith]);
236
-				throw new \Exception($message_t);
237
-			}
238
-
239
-		} else {
240
-			$shareId = $this->createFederatedShare($share);
241
-		}
242
-
243
-		$data = $this->getRawShare($shareId);
244
-		return $this->createShareObject($data);
245
-	}
246
-
247
-	/**
248
-	 * create federated share and inform the recipient
249
-	 *
250
-	 * @param IShare $share
251
-	 * @return int
252
-	 * @throws ShareNotFound
253
-	 * @throws \Exception
254
-	 */
255
-	protected function createFederatedShare(IShare $share) {
256
-		$token = $this->tokenHandler->generateToken();
257
-		$shareId = $this->addShareToDB(
258
-			$share->getNodeId(),
259
-			$share->getNodeType(),
260
-			$share->getSharedWith(),
261
-			$share->getSharedBy(),
262
-			$share->getShareOwner(),
263
-			$share->getPermissions(),
264
-			$token,
265
-			$share->getShareType()
266
-		);
267
-
268
-		$failure = false;
269
-
270
-		try {
271
-			$sharedByFederatedId = $share->getSharedBy();
272
-			if ($this->userManager->userExists($sharedByFederatedId)) {
273
-				$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
274
-				$sharedByFederatedId = $cloudId->getId();
275
-			}
276
-			$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
277
-			$send = $this->notifications->sendRemoteShare(
278
-				$token,
279
-				$share->getSharedWith(),
280
-				$share->getNode()->getName(),
281
-				$shareId,
282
-				$share->getShareOwner(),
283
-				$ownerCloudId->getId(),
284
-				$share->getSharedBy(),
285
-				$sharedByFederatedId,
286
-				$share->getShareType()
287
-			);
288
-
289
-			if ($send === false) {
290
-				$failure = true;
291
-			}
292
-		} catch (\Exception $e) {
293
-			$this->logger->logException($e, [
294
-				'message' => 'Failed to notify remote server of federated share, removing share.',
295
-				'level' => ILogger::ERROR,
296
-				'app' => 'federatedfilesharing',
297
-			]);
298
-			$failure = true;
299
-		}
300
-
301
-		if($failure) {
302
-			$this->removeShareFromTableById($shareId);
303
-			$message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
304
-				[$share->getNode()->getName(), $share->getSharedWith()]);
305
-			throw new \Exception($message_t);
306
-		}
307
-
308
-		return $shareId;
309
-
310
-	}
311
-
312
-	/**
313
-	 * @param string $shareWith
314
-	 * @param IShare $share
315
-	 * @param string $shareId internal share Id
316
-	 * @return array
317
-	 * @throws \Exception
318
-	 */
319
-	protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
320
-
321
-		$remoteShare = $this->getShareFromExternalShareTable($share);
322
-		$token = $remoteShare['share_token'];
323
-		$remoteId = $remoteShare['remote_id'];
324
-		$remote = $remoteShare['remote'];
325
-
326
-		list($token, $remoteId) = $this->notifications->requestReShare(
327
-			$token,
328
-			$remoteId,
329
-			$shareId,
330
-			$remote,
331
-			$shareWith,
332
-			$share->getPermissions(),
333
-			$share->getNode()->getName()
334
-		);
335
-
336
-		return [$token, $remoteId];
337
-	}
338
-
339
-	/**
340
-	 * get federated share from the share_external table but exclude mounted link shares
341
-	 *
342
-	 * @param IShare $share
343
-	 * @return array
344
-	 * @throws ShareNotFound
345
-	 */
346
-	protected function getShareFromExternalShareTable(IShare $share) {
347
-		$query = $this->dbConnection->getQueryBuilder();
348
-		$query->select('*')->from($this->externalShareTable)
349
-			->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
350
-			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
351
-		$result = $query->execute()->fetchAll();
352
-
353
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
354
-			return $result[0];
355
-		}
356
-
357
-		throw new ShareNotFound('share not found in share_external table');
358
-	}
359
-
360
-	/**
361
-	 * add share to the database and return the ID
362
-	 *
363
-	 * @param int $itemSource
364
-	 * @param string $itemType
365
-	 * @param string $shareWith
366
-	 * @param string $sharedBy
367
-	 * @param string $uidOwner
368
-	 * @param int $permissions
369
-	 * @param string $token
370
-	 * @param int $shareType
371
-	 * @return int
372
-	 */
373
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
374
-		$qb = $this->dbConnection->getQueryBuilder();
375
-		$qb->insert('share')
376
-			->setValue('share_type', $qb->createNamedParameter($shareType))
377
-			->setValue('item_type', $qb->createNamedParameter($itemType))
378
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
379
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
380
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
381
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
382
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
383
-			->setValue('permissions', $qb->createNamedParameter($permissions))
384
-			->setValue('token', $qb->createNamedParameter($token))
385
-			->setValue('stime', $qb->createNamedParameter(time()));
386
-
387
-		/*
186
+        $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
187
+        $alreadySharedGroup = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
188
+        if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
189
+            $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
190
+            $message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', array($share->getNode()->getName(), $shareWith));
191
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
192
+            throw new \Exception($message_t);
193
+        }
194
+
195
+
196
+        // don't allow federated shares if source and target server are the same
197
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
198
+        $currentServer = $this->addressHandler->generateRemoteURL();
199
+        $currentUser = $sharedBy;
200
+        if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
201
+            $message = 'Not allowed to create a federated share with the same user.';
202
+            $message_t = $this->l->t('Not allowed to create a federated share with the same user');
203
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
204
+            throw new \Exception($message_t);
205
+        }
206
+
207
+
208
+        $share->setSharedWith($cloudId->getId());
209
+
210
+        try {
211
+            $remoteShare = $this->getShareFromExternalShareTable($share);
212
+        } catch (ShareNotFound $e) {
213
+            $remoteShare = null;
214
+        }
215
+
216
+        if ($remoteShare) {
217
+            try {
218
+                $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
219
+                $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
220
+                $share->setId($shareId);
221
+                list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
222
+                // remote share was create successfully if we get a valid token as return
223
+                $send = is_string($token) && $token !== '';
224
+            } catch (\Exception $e) {
225
+                // fall back to old re-share behavior if the remote server
226
+                // doesn't support flat re-shares (was introduced with Nextcloud 9.1)
227
+                $this->removeShareFromTable($share);
228
+                $shareId = $this->createFederatedShare($share);
229
+            }
230
+            if ($send) {
231
+                $this->updateSuccessfulReshare($shareId, $token);
232
+                $this->storeRemoteId($shareId, $remoteId);
233
+            } else {
234
+                $this->removeShareFromTable($share);
235
+                $message_t = $this->l->t('File is already shared with %s', [$shareWith]);
236
+                throw new \Exception($message_t);
237
+            }
238
+
239
+        } else {
240
+            $shareId = $this->createFederatedShare($share);
241
+        }
242
+
243
+        $data = $this->getRawShare($shareId);
244
+        return $this->createShareObject($data);
245
+    }
246
+
247
+    /**
248
+     * create federated share and inform the recipient
249
+     *
250
+     * @param IShare $share
251
+     * @return int
252
+     * @throws ShareNotFound
253
+     * @throws \Exception
254
+     */
255
+    protected function createFederatedShare(IShare $share) {
256
+        $token = $this->tokenHandler->generateToken();
257
+        $shareId = $this->addShareToDB(
258
+            $share->getNodeId(),
259
+            $share->getNodeType(),
260
+            $share->getSharedWith(),
261
+            $share->getSharedBy(),
262
+            $share->getShareOwner(),
263
+            $share->getPermissions(),
264
+            $token,
265
+            $share->getShareType()
266
+        );
267
+
268
+        $failure = false;
269
+
270
+        try {
271
+            $sharedByFederatedId = $share->getSharedBy();
272
+            if ($this->userManager->userExists($sharedByFederatedId)) {
273
+                $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
274
+                $sharedByFederatedId = $cloudId->getId();
275
+            }
276
+            $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
277
+            $send = $this->notifications->sendRemoteShare(
278
+                $token,
279
+                $share->getSharedWith(),
280
+                $share->getNode()->getName(),
281
+                $shareId,
282
+                $share->getShareOwner(),
283
+                $ownerCloudId->getId(),
284
+                $share->getSharedBy(),
285
+                $sharedByFederatedId,
286
+                $share->getShareType()
287
+            );
288
+
289
+            if ($send === false) {
290
+                $failure = true;
291
+            }
292
+        } catch (\Exception $e) {
293
+            $this->logger->logException($e, [
294
+                'message' => 'Failed to notify remote server of federated share, removing share.',
295
+                'level' => ILogger::ERROR,
296
+                'app' => 'federatedfilesharing',
297
+            ]);
298
+            $failure = true;
299
+        }
300
+
301
+        if($failure) {
302
+            $this->removeShareFromTableById($shareId);
303
+            $message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
304
+                [$share->getNode()->getName(), $share->getSharedWith()]);
305
+            throw new \Exception($message_t);
306
+        }
307
+
308
+        return $shareId;
309
+
310
+    }
311
+
312
+    /**
313
+     * @param string $shareWith
314
+     * @param IShare $share
315
+     * @param string $shareId internal share Id
316
+     * @return array
317
+     * @throws \Exception
318
+     */
319
+    protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
320
+
321
+        $remoteShare = $this->getShareFromExternalShareTable($share);
322
+        $token = $remoteShare['share_token'];
323
+        $remoteId = $remoteShare['remote_id'];
324
+        $remote = $remoteShare['remote'];
325
+
326
+        list($token, $remoteId) = $this->notifications->requestReShare(
327
+            $token,
328
+            $remoteId,
329
+            $shareId,
330
+            $remote,
331
+            $shareWith,
332
+            $share->getPermissions(),
333
+            $share->getNode()->getName()
334
+        );
335
+
336
+        return [$token, $remoteId];
337
+    }
338
+
339
+    /**
340
+     * get federated share from the share_external table but exclude mounted link shares
341
+     *
342
+     * @param IShare $share
343
+     * @return array
344
+     * @throws ShareNotFound
345
+     */
346
+    protected function getShareFromExternalShareTable(IShare $share) {
347
+        $query = $this->dbConnection->getQueryBuilder();
348
+        $query->select('*')->from($this->externalShareTable)
349
+            ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
350
+            ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
351
+        $result = $query->execute()->fetchAll();
352
+
353
+        if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
354
+            return $result[0];
355
+        }
356
+
357
+        throw new ShareNotFound('share not found in share_external table');
358
+    }
359
+
360
+    /**
361
+     * add share to the database and return the ID
362
+     *
363
+     * @param int $itemSource
364
+     * @param string $itemType
365
+     * @param string $shareWith
366
+     * @param string $sharedBy
367
+     * @param string $uidOwner
368
+     * @param int $permissions
369
+     * @param string $token
370
+     * @param int $shareType
371
+     * @return int
372
+     */
373
+    private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
374
+        $qb = $this->dbConnection->getQueryBuilder();
375
+        $qb->insert('share')
376
+            ->setValue('share_type', $qb->createNamedParameter($shareType))
377
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
378
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
379
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
380
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
381
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
382
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
383
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
384
+            ->setValue('token', $qb->createNamedParameter($token))
385
+            ->setValue('stime', $qb->createNamedParameter(time()));
386
+
387
+        /*
388 388
 		 * Added to fix https://github.com/owncloud/core/issues/22215
389 389
 		 * Can be removed once we get rid of ajax/share.php
390 390
 		 */
391
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
392
-
393
-		$qb->execute();
394
-		$id = $qb->getLastInsertId();
395
-
396
-		return (int)$id;
397
-	}
398
-
399
-	/**
400
-	 * Update a share
401
-	 *
402
-	 * @param IShare $share
403
-	 * @return IShare The share object
404
-	 */
405
-	public function update(IShare $share) {
406
-		/*
391
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
392
+
393
+        $qb->execute();
394
+        $id = $qb->getLastInsertId();
395
+
396
+        return (int)$id;
397
+    }
398
+
399
+    /**
400
+     * Update a share
401
+     *
402
+     * @param IShare $share
403
+     * @return IShare The share object
404
+     */
405
+    public function update(IShare $share) {
406
+        /*
407 407
 		 * We allow updating the permissions of federated shares
408 408
 		 */
409
-		$qb = $this->dbConnection->getQueryBuilder();
410
-			$qb->update('share')
411
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
412
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
413
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
414
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
415
-				->execute();
416
-
417
-		// send the updated permission to the owner/initiator, if they are not the same
418
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
419
-			$this->sendPermissionUpdate($share);
420
-		}
421
-
422
-		return $share;
423
-	}
424
-
425
-	/**
426
-	 * send the updated permission to the owner/initiator, if they are not the same
427
-	 *
428
-	 * @param IShare $share
429
-	 * @throws ShareNotFound
430
-	 * @throws \OC\HintException
431
-	 */
432
-	protected function sendPermissionUpdate(IShare $share) {
433
-		$remoteId = $this->getRemoteId($share);
434
-		// if the local user is the owner we send the permission change to the initiator
435
-		if ($this->userManager->userExists($share->getShareOwner())) {
436
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
437
-		} else { // ... if not we send the permission change to the owner
438
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
439
-		}
440
-		$this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
441
-	}
442
-
443
-
444
-	/**
445
-	 * update successful reShare with the correct token
446
-	 *
447
-	 * @param int $shareId
448
-	 * @param string $token
449
-	 */
450
-	protected function updateSuccessfulReShare($shareId, $token) {
451
-		$query = $this->dbConnection->getQueryBuilder();
452
-		$query->update('share')
453
-			->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
454
-			->set('token', $query->createNamedParameter($token))
455
-			->execute();
456
-	}
457
-
458
-	/**
459
-	 * store remote ID in federated reShare table
460
-	 *
461
-	 * @param $shareId
462
-	 * @param $remoteId
463
-	 */
464
-	public function storeRemoteId($shareId, $remoteId) {
465
-		$query = $this->dbConnection->getQueryBuilder();
466
-		$query->insert('federated_reshares')
467
-			->values(
468
-				[
469
-					'share_id' =>  $query->createNamedParameter($shareId),
470
-					'remote_id' => $query->createNamedParameter($remoteId),
471
-				]
472
-			);
473
-		$query->execute();
474
-	}
475
-
476
-	/**
477
-	 * get share ID on remote server for federated re-shares
478
-	 *
479
-	 * @param IShare $share
480
-	 * @return int
481
-	 * @throws ShareNotFound
482
-	 */
483
-	public function getRemoteId(IShare $share) {
484
-		$query = $this->dbConnection->getQueryBuilder();
485
-		$query->select('remote_id')->from('federated_reshares')
486
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
487
-		$data = $query->execute()->fetch();
488
-
489
-		if (!is_array($data) || !isset($data['remote_id'])) {
490
-			throw new ShareNotFound();
491
-		}
492
-
493
-		return (int)$data['remote_id'];
494
-	}
495
-
496
-	/**
497
-	 * @inheritdoc
498
-	 */
499
-	public function move(IShare $share, $recipient) {
500
-		/*
409
+        $qb = $this->dbConnection->getQueryBuilder();
410
+            $qb->update('share')
411
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
412
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
413
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
414
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
415
+                ->execute();
416
+
417
+        // send the updated permission to the owner/initiator, if they are not the same
418
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
419
+            $this->sendPermissionUpdate($share);
420
+        }
421
+
422
+        return $share;
423
+    }
424
+
425
+    /**
426
+     * send the updated permission to the owner/initiator, if they are not the same
427
+     *
428
+     * @param IShare $share
429
+     * @throws ShareNotFound
430
+     * @throws \OC\HintException
431
+     */
432
+    protected function sendPermissionUpdate(IShare $share) {
433
+        $remoteId = $this->getRemoteId($share);
434
+        // if the local user is the owner we send the permission change to the initiator
435
+        if ($this->userManager->userExists($share->getShareOwner())) {
436
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
437
+        } else { // ... if not we send the permission change to the owner
438
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
439
+        }
440
+        $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
441
+    }
442
+
443
+
444
+    /**
445
+     * update successful reShare with the correct token
446
+     *
447
+     * @param int $shareId
448
+     * @param string $token
449
+     */
450
+    protected function updateSuccessfulReShare($shareId, $token) {
451
+        $query = $this->dbConnection->getQueryBuilder();
452
+        $query->update('share')
453
+            ->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
454
+            ->set('token', $query->createNamedParameter($token))
455
+            ->execute();
456
+    }
457
+
458
+    /**
459
+     * store remote ID in federated reShare table
460
+     *
461
+     * @param $shareId
462
+     * @param $remoteId
463
+     */
464
+    public function storeRemoteId($shareId, $remoteId) {
465
+        $query = $this->dbConnection->getQueryBuilder();
466
+        $query->insert('federated_reshares')
467
+            ->values(
468
+                [
469
+                    'share_id' =>  $query->createNamedParameter($shareId),
470
+                    'remote_id' => $query->createNamedParameter($remoteId),
471
+                ]
472
+            );
473
+        $query->execute();
474
+    }
475
+
476
+    /**
477
+     * get share ID on remote server for federated re-shares
478
+     *
479
+     * @param IShare $share
480
+     * @return int
481
+     * @throws ShareNotFound
482
+     */
483
+    public function getRemoteId(IShare $share) {
484
+        $query = $this->dbConnection->getQueryBuilder();
485
+        $query->select('remote_id')->from('federated_reshares')
486
+            ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
487
+        $data = $query->execute()->fetch();
488
+
489
+        if (!is_array($data) || !isset($data['remote_id'])) {
490
+            throw new ShareNotFound();
491
+        }
492
+
493
+        return (int)$data['remote_id'];
494
+    }
495
+
496
+    /**
497
+     * @inheritdoc
498
+     */
499
+    public function move(IShare $share, $recipient) {
500
+        /*
501 501
 		 * This function does nothing yet as it is just for outgoing
502 502
 		 * federated shares.
503 503
 		 */
504
-		return $share;
505
-	}
506
-
507
-	/**
508
-	 * Get all children of this share
509
-	 *
510
-	 * @param IShare $parent
511
-	 * @return IShare[]
512
-	 */
513
-	public function getChildren(IShare $parent) {
514
-		$children = [];
515
-
516
-		$qb = $this->dbConnection->getQueryBuilder();
517
-		$qb->select('*')
518
-			->from('share')
519
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
520
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
521
-			->orderBy('id');
522
-
523
-		$cursor = $qb->execute();
524
-		while($data = $cursor->fetch()) {
525
-			$children[] = $this->createShareObject($data);
526
-		}
527
-		$cursor->closeCursor();
528
-
529
-		return $children;
530
-	}
531
-
532
-	/**
533
-	 * Delete a share (owner unShares the file)
534
-	 *
535
-	 * @param IShare $share
536
-	 * @throws ShareNotFound
537
-	 * @throws \OC\HintException
538
-	 */
539
-	public function delete(IShare $share) {
540
-
541
-		list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
542
-
543
-		// if the local user is the owner we can send the unShare request directly...
544
-		if ($this->userManager->userExists($share->getShareOwner())) {
545
-			$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
546
-			$this->revokeShare($share, true);
547
-		} else { // ... if not we need to correct ID for the unShare request
548
-			$remoteId = $this->getRemoteId($share);
549
-			$this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
550
-			$this->revokeShare($share, false);
551
-		}
552
-
553
-		// only remove the share when all messages are send to not lose information
554
-		// about the share to early
555
-		$this->removeShareFromTable($share);
556
-	}
557
-
558
-	/**
559
-	 * in case of a re-share we need to send the other use (initiator or owner)
560
-	 * a message that the file was unshared
561
-	 *
562
-	 * @param IShare $share
563
-	 * @param bool $isOwner the user can either be the owner or the user who re-sahred it
564
-	 * @throws ShareNotFound
565
-	 * @throws \OC\HintException
566
-	 */
567
-	protected function revokeShare($share, $isOwner) {
568
-		if ($this->userManager->userExists($share->getShareOwner() && $this->userManager->userExists($share->getSharedBy()))) {
569
-			// If both the owner and the initiator of the share are local users we don't have to notify anybody else
570
-			return;
571
-		}
572
-
573
-		// also send a unShare request to the initiator, if this is a different user than the owner
574
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
575
-			if ($isOwner) {
576
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
577
-			} else {
578
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
579
-			}
580
-			$remoteId = $this->getRemoteId($share);
581
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
582
-		}
583
-	}
584
-
585
-	/**
586
-	 * remove share from table
587
-	 *
588
-	 * @param IShare $share
589
-	 */
590
-	public function removeShareFromTable(IShare $share) {
591
-		$this->removeShareFromTableById($share->getId());
592
-	}
593
-
594
-	/**
595
-	 * remove share from table
596
-	 *
597
-	 * @param string $shareId
598
-	 */
599
-	private function removeShareFromTableById($shareId) {
600
-		$qb = $this->dbConnection->getQueryBuilder();
601
-		$qb->delete('share')
602
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
603
-			->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
604
-		$qb->execute();
605
-
606
-		$qb->delete('federated_reshares')
607
-			->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
608
-		$qb->execute();
609
-	}
610
-
611
-	/**
612
-	 * @inheritdoc
613
-	 */
614
-	public function deleteFromSelf(IShare $share, $recipient) {
615
-		// nothing to do here. Technically deleteFromSelf in the context of federated
616
-		// shares is a umount of a external storage. This is handled here
617
-		// apps/files_sharing/lib/external/manager.php
618
-		// TODO move this code over to this app
619
-	}
620
-
621
-	public function restore(IShare $share, string $recipient): IShare {
622
-		throw new GenericShareException('not implemented');
623
-	}
624
-
625
-
626
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
627
-		$qb = $this->dbConnection->getQueryBuilder();
628
-		$qb->select('*')
629
-			->from('share', 's')
630
-			->andWhere($qb->expr()->orX(
631
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
632
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
633
-			))
634
-			->andWhere(
635
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
636
-			);
637
-
638
-		/**
639
-		 * Reshares for this user are shares where they are the owner.
640
-		 */
641
-		if ($reshares === false) {
642
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
643
-		} else {
644
-			$qb->andWhere(
645
-				$qb->expr()->orX(
646
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
647
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
648
-				)
649
-			);
650
-		}
651
-
652
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
653
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
654
-
655
-		$qb->orderBy('id');
656
-
657
-		$cursor = $qb->execute();
658
-		$shares = [];
659
-		while ($data = $cursor->fetch()) {
660
-			$shares[$data['fileid']][] = $this->createShareObject($data);
661
-		}
662
-		$cursor->closeCursor();
663
-
664
-		return $shares;
665
-	}
666
-
667
-	/**
668
-	 * @inheritdoc
669
-	 */
670
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
671
-		$qb = $this->dbConnection->getQueryBuilder();
672
-		$qb->select('*')
673
-			->from('share');
674
-
675
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
676
-
677
-		/**
678
-		 * Reshares for this user are shares where they are the owner.
679
-		 */
680
-		if ($reshares === false) {
681
-			//Special case for old shares created via the web UI
682
-			$or1 = $qb->expr()->andX(
683
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
684
-				$qb->expr()->isNull('uid_initiator')
685
-			);
686
-
687
-			$qb->andWhere(
688
-				$qb->expr()->orX(
689
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
690
-					$or1
691
-				)
692
-			);
693
-		} else {
694
-			$qb->andWhere(
695
-				$qb->expr()->orX(
696
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
697
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
698
-				)
699
-			);
700
-		}
701
-
702
-		if ($node !== null) {
703
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
704
-		}
705
-
706
-		if ($limit !== -1) {
707
-			$qb->setMaxResults($limit);
708
-		}
709
-
710
-		$qb->setFirstResult($offset);
711
-		$qb->orderBy('id');
712
-
713
-		$cursor = $qb->execute();
714
-		$shares = [];
715
-		while($data = $cursor->fetch()) {
716
-			$shares[] = $this->createShareObject($data);
717
-		}
718
-		$cursor->closeCursor();
719
-
720
-		return $shares;
721
-	}
722
-
723
-	/**
724
-	 * @inheritdoc
725
-	 */
726
-	public function getShareById($id, $recipientId = null) {
727
-		$qb = $this->dbConnection->getQueryBuilder();
728
-
729
-		$qb->select('*')
730
-			->from('share')
731
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
732
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
733
-
734
-		$cursor = $qb->execute();
735
-		$data = $cursor->fetch();
736
-		$cursor->closeCursor();
737
-
738
-		if ($data === false) {
739
-			throw new ShareNotFound('Can not find share with ID: ' . $id);
740
-		}
741
-
742
-		try {
743
-			$share = $this->createShareObject($data);
744
-		} catch (InvalidShare $e) {
745
-			throw new ShareNotFound();
746
-		}
747
-
748
-		return $share;
749
-	}
750
-
751
-	/**
752
-	 * Get shares for a given path
753
-	 *
754
-	 * @param \OCP\Files\Node $path
755
-	 * @return IShare[]
756
-	 */
757
-	public function getSharesByPath(Node $path) {
758
-		$qb = $this->dbConnection->getQueryBuilder();
759
-
760
-		// get federated user shares
761
-		$cursor = $qb->select('*')
762
-			->from('share')
763
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
764
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
765
-			->execute();
766
-
767
-		$shares = [];
768
-		while($data = $cursor->fetch()) {
769
-			$shares[] = $this->createShareObject($data);
770
-		}
771
-		$cursor->closeCursor();
772
-
773
-		return $shares;
774
-	}
775
-
776
-	/**
777
-	 * @inheritdoc
778
-	 */
779
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
780
-		/** @var IShare[] $shares */
781
-		$shares = [];
782
-
783
-		//Get shares directly with this user
784
-		$qb = $this->dbConnection->getQueryBuilder();
785
-		$qb->select('*')
786
-			->from('share');
787
-
788
-		// Order by id
789
-		$qb->orderBy('id');
790
-
791
-		// Set limit and offset
792
-		if ($limit !== -1) {
793
-			$qb->setMaxResults($limit);
794
-		}
795
-		$qb->setFirstResult($offset);
796
-
797
-		$qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
798
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
799
-
800
-		// Filter by node if provided
801
-		if ($node !== null) {
802
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
803
-		}
804
-
805
-		$cursor = $qb->execute();
806
-
807
-		while($data = $cursor->fetch()) {
808
-			$shares[] = $this->createShareObject($data);
809
-		}
810
-		$cursor->closeCursor();
811
-
812
-
813
-		return $shares;
814
-	}
815
-
816
-	/**
817
-	 * Get a share by token
818
-	 *
819
-	 * @param string $token
820
-	 * @return IShare
821
-	 * @throws ShareNotFound
822
-	 */
823
-	public function getShareByToken($token) {
824
-		$qb = $this->dbConnection->getQueryBuilder();
825
-
826
-		$cursor = $qb->select('*')
827
-			->from('share')
828
-			->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
829
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
830
-			->execute();
831
-
832
-		$data = $cursor->fetch();
833
-
834
-		if ($data === false) {
835
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
836
-		}
837
-
838
-		try {
839
-			$share = $this->createShareObject($data);
840
-		} catch (InvalidShare $e) {
841
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
842
-		}
843
-
844
-		return $share;
845
-	}
846
-
847
-	/**
848
-	 * get database row of a give share
849
-	 *
850
-	 * @param $id
851
-	 * @return array
852
-	 * @throws ShareNotFound
853
-	 */
854
-	private function getRawShare($id) {
855
-
856
-		// Now fetch the inserted share and create a complete share object
857
-		$qb = $this->dbConnection->getQueryBuilder();
858
-		$qb->select('*')
859
-			->from('share')
860
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
861
-
862
-		$cursor = $qb->execute();
863
-		$data = $cursor->fetch();
864
-		$cursor->closeCursor();
865
-
866
-		if ($data === false) {
867
-			throw new ShareNotFound;
868
-		}
869
-
870
-		return $data;
871
-	}
872
-
873
-	/**
874
-	 * Create a share object from an database row
875
-	 *
876
-	 * @param array $data
877
-	 * @return IShare
878
-	 * @throws InvalidShare
879
-	 * @throws ShareNotFound
880
-	 */
881
-	private function createShareObject($data) {
882
-
883
-		$share = new Share($this->rootFolder, $this->userManager);
884
-		$share->setId((int)$data['id'])
885
-			->setShareType((int)$data['share_type'])
886
-			->setPermissions((int)$data['permissions'])
887
-			->setTarget($data['file_target'])
888
-			->setMailSend((bool)$data['mail_send'])
889
-			->setToken($data['token']);
890
-
891
-		$shareTime = new \DateTime();
892
-		$shareTime->setTimestamp((int)$data['stime']);
893
-		$share->setShareTime($shareTime);
894
-		$share->setSharedWith($data['share_with']);
895
-
896
-		if ($data['uid_initiator'] !== null) {
897
-			$share->setShareOwner($data['uid_owner']);
898
-			$share->setSharedBy($data['uid_initiator']);
899
-		} else {
900
-			//OLD SHARE
901
-			$share->setSharedBy($data['uid_owner']);
902
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
903
-
904
-			$owner = $path->getOwner();
905
-			$share->setShareOwner($owner->getUID());
906
-		}
907
-
908
-		$share->setNodeId((int)$data['file_source']);
909
-		$share->setNodeType($data['item_type']);
910
-
911
-		$share->setProviderId($this->identifier());
912
-
913
-		return $share;
914
-	}
915
-
916
-	/**
917
-	 * Get the node with file $id for $user
918
-	 *
919
-	 * @param string $userId
920
-	 * @param int $id
921
-	 * @return \OCP\Files\File|\OCP\Files\Folder
922
-	 * @throws InvalidShare
923
-	 */
924
-	private function getNode($userId, $id) {
925
-		try {
926
-			$userFolder = $this->rootFolder->getUserFolder($userId);
927
-		} catch (NotFoundException $e) {
928
-			throw new InvalidShare();
929
-		}
930
-
931
-		$nodes = $userFolder->getById($id);
932
-
933
-		if (empty($nodes)) {
934
-			throw new InvalidShare();
935
-		}
936
-
937
-		return $nodes[0];
938
-	}
939
-
940
-	/**
941
-	 * A user is deleted from the system
942
-	 * So clean up the relevant shares.
943
-	 *
944
-	 * @param string $uid
945
-	 * @param int $shareType
946
-	 */
947
-	public function userDeleted($uid, $shareType) {
948
-		//TODO: probabaly a good idea to send unshare info to remote servers
949
-
950
-		$qb = $this->dbConnection->getQueryBuilder();
951
-
952
-		$qb->delete('share')
953
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
954
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
955
-			->execute();
956
-	}
957
-
958
-	/**
959
-	 * This provider does not handle groups
960
-	 *
961
-	 * @param string $gid
962
-	 */
963
-	public function groupDeleted($gid) {
964
-		// We don't handle groups here
965
-	}
966
-
967
-	/**
968
-	 * This provider does not handle groups
969
-	 *
970
-	 * @param string $uid
971
-	 * @param string $gid
972
-	 */
973
-	public function userDeletedFromGroup($uid, $gid) {
974
-		// We don't handle groups here
975
-	}
976
-
977
-	/**
978
-	 * check if users from other Nextcloud instances are allowed to mount public links share by this instance
979
-	 *
980
-	 * @return bool
981
-	 */
982
-	public function isOutgoingServer2serverShareEnabled() {
983
-		if ($this->gsConfig->onlyInternalFederation()) {
984
-			return false;
985
-		}
986
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
987
-		return ($result === 'yes');
988
-	}
989
-
990
-	/**
991
-	 * check if users are allowed to mount public links from other Nextclouds
992
-	 *
993
-	 * @return bool
994
-	 */
995
-	public function isIncomingServer2serverShareEnabled() {
996
-		if ($this->gsConfig->onlyInternalFederation()) {
997
-			return false;
998
-		}
999
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
1000
-		return ($result === 'yes');
1001
-	}
1002
-
1003
-
1004
-	/**
1005
-	 * check if users from other Nextcloud instances are allowed to send federated group shares
1006
-	 *
1007
-	 * @return bool
1008
-	 */
1009
-	public function isOutgoingServer2serverGroupShareEnabled() {
1010
-		if ($this->gsConfig->onlyInternalFederation()) {
1011
-			return false;
1012
-		}
1013
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1014
-		return ($result === 'yes');
1015
-	}
1016
-
1017
-	/**
1018
-	 * check if users are allowed to receive federated group shares
1019
-	 *
1020
-	 * @return bool
1021
-	 */
1022
-	public function isIncomingServer2serverGroupShareEnabled() {
1023
-		if ($this->gsConfig->onlyInternalFederation()) {
1024
-			return false;
1025
-		}
1026
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1027
-		return ($result === 'yes');
1028
-	}
1029
-
1030
-	/**
1031
-	 * check if federated group sharing is supported, therefore the OCM API need to be enabled
1032
-	 *
1033
-	 * @return bool
1034
-	 */
1035
-	public function isFederatedGroupSharingSupported() {
1036
-		return $this->cloudFederationProviderManager->isReady();
1037
-	}
1038
-
1039
-	/**
1040
-	 * Check if querying sharees on the lookup server is enabled
1041
-	 *
1042
-	 * @return bool
1043
-	 */
1044
-	public function isLookupServerQueriesEnabled() {
1045
-		// in a global scale setup we should always query the lookup server
1046
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1047
-			return true;
1048
-		}
1049
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes');
1050
-		return ($result === 'yes');
1051
-	}
1052
-
1053
-
1054
-	/**
1055
-	 * Check if it is allowed to publish user specific data to the lookup server
1056
-	 *
1057
-	 * @return bool
1058
-	 */
1059
-	public function isLookupServerUploadEnabled() {
1060
-		// in a global scale setup the admin is responsible to keep the lookup server up-to-date
1061
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1062
-			return false;
1063
-		}
1064
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1065
-		return ($result === 'yes');
1066
-	}
1067
-
1068
-	/**
1069
-	 * @inheritdoc
1070
-	 */
1071
-	public function getAccessList($nodes, $currentAccess) {
1072
-		$ids = [];
1073
-		foreach ($nodes as $node) {
1074
-			$ids[] = $node->getId();
1075
-		}
1076
-
1077
-		$qb = $this->dbConnection->getQueryBuilder();
1078
-		$qb->select('share_with', 'token', 'file_source')
1079
-			->from('share')
1080
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1081
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1082
-			->andWhere($qb->expr()->orX(
1083
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1084
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1085
-			));
1086
-		$cursor = $qb->execute();
1087
-
1088
-		if ($currentAccess === false) {
1089
-			$remote = $cursor->fetch() !== false;
1090
-			$cursor->closeCursor();
1091
-
1092
-			return ['remote' => $remote];
1093
-		}
1094
-
1095
-		$remote = [];
1096
-		while ($row = $cursor->fetch()) {
1097
-			$remote[$row['share_with']] = [
1098
-				'node_id' => $row['file_source'],
1099
-				'token' => $row['token'],
1100
-			];
1101
-		}
1102
-		$cursor->closeCursor();
1103
-
1104
-		return ['remote' => $remote];
1105
-	}
1106
-
1107
-	public function getAllShares(): iterable {
1108
-		$qb = $this->dbConnection->getQueryBuilder();
1109
-
1110
-		$qb->select('*')
1111
-			->from('share')
1112
-			->where(
1113
-				$qb->expr()->orX(
1114
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
1115
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
1116
-				)
1117
-			);
1118
-
1119
-		$cursor = $qb->execute();
1120
-		while($data = $cursor->fetch()) {
1121
-			try {
1122
-				$share = $this->createShareObject($data);
1123
-			} catch (InvalidShare $e) {
1124
-				continue;
1125
-			} catch (ShareNotFound $e) {
1126
-				continue;
1127
-			}
1128
-
1129
-			yield $share;
1130
-		}
1131
-		$cursor->closeCursor();
1132
-	}
504
+        return $share;
505
+    }
506
+
507
+    /**
508
+     * Get all children of this share
509
+     *
510
+     * @param IShare $parent
511
+     * @return IShare[]
512
+     */
513
+    public function getChildren(IShare $parent) {
514
+        $children = [];
515
+
516
+        $qb = $this->dbConnection->getQueryBuilder();
517
+        $qb->select('*')
518
+            ->from('share')
519
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
520
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
521
+            ->orderBy('id');
522
+
523
+        $cursor = $qb->execute();
524
+        while($data = $cursor->fetch()) {
525
+            $children[] = $this->createShareObject($data);
526
+        }
527
+        $cursor->closeCursor();
528
+
529
+        return $children;
530
+    }
531
+
532
+    /**
533
+     * Delete a share (owner unShares the file)
534
+     *
535
+     * @param IShare $share
536
+     * @throws ShareNotFound
537
+     * @throws \OC\HintException
538
+     */
539
+    public function delete(IShare $share) {
540
+
541
+        list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
542
+
543
+        // if the local user is the owner we can send the unShare request directly...
544
+        if ($this->userManager->userExists($share->getShareOwner())) {
545
+            $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
546
+            $this->revokeShare($share, true);
547
+        } else { // ... if not we need to correct ID for the unShare request
548
+            $remoteId = $this->getRemoteId($share);
549
+            $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
550
+            $this->revokeShare($share, false);
551
+        }
552
+
553
+        // only remove the share when all messages are send to not lose information
554
+        // about the share to early
555
+        $this->removeShareFromTable($share);
556
+    }
557
+
558
+    /**
559
+     * in case of a re-share we need to send the other use (initiator or owner)
560
+     * a message that the file was unshared
561
+     *
562
+     * @param IShare $share
563
+     * @param bool $isOwner the user can either be the owner or the user who re-sahred it
564
+     * @throws ShareNotFound
565
+     * @throws \OC\HintException
566
+     */
567
+    protected function revokeShare($share, $isOwner) {
568
+        if ($this->userManager->userExists($share->getShareOwner() && $this->userManager->userExists($share->getSharedBy()))) {
569
+            // If both the owner and the initiator of the share are local users we don't have to notify anybody else
570
+            return;
571
+        }
572
+
573
+        // also send a unShare request to the initiator, if this is a different user than the owner
574
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
575
+            if ($isOwner) {
576
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
577
+            } else {
578
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
579
+            }
580
+            $remoteId = $this->getRemoteId($share);
581
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
582
+        }
583
+    }
584
+
585
+    /**
586
+     * remove share from table
587
+     *
588
+     * @param IShare $share
589
+     */
590
+    public function removeShareFromTable(IShare $share) {
591
+        $this->removeShareFromTableById($share->getId());
592
+    }
593
+
594
+    /**
595
+     * remove share from table
596
+     *
597
+     * @param string $shareId
598
+     */
599
+    private function removeShareFromTableById($shareId) {
600
+        $qb = $this->dbConnection->getQueryBuilder();
601
+        $qb->delete('share')
602
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
603
+            ->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
604
+        $qb->execute();
605
+
606
+        $qb->delete('federated_reshares')
607
+            ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
608
+        $qb->execute();
609
+    }
610
+
611
+    /**
612
+     * @inheritdoc
613
+     */
614
+    public function deleteFromSelf(IShare $share, $recipient) {
615
+        // nothing to do here. Technically deleteFromSelf in the context of federated
616
+        // shares is a umount of a external storage. This is handled here
617
+        // apps/files_sharing/lib/external/manager.php
618
+        // TODO move this code over to this app
619
+    }
620
+
621
+    public function restore(IShare $share, string $recipient): IShare {
622
+        throw new GenericShareException('not implemented');
623
+    }
624
+
625
+
626
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
627
+        $qb = $this->dbConnection->getQueryBuilder();
628
+        $qb->select('*')
629
+            ->from('share', 's')
630
+            ->andWhere($qb->expr()->orX(
631
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
632
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
633
+            ))
634
+            ->andWhere(
635
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
636
+            );
637
+
638
+        /**
639
+         * Reshares for this user are shares where they are the owner.
640
+         */
641
+        if ($reshares === false) {
642
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
643
+        } else {
644
+            $qb->andWhere(
645
+                $qb->expr()->orX(
646
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
647
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
648
+                )
649
+            );
650
+        }
651
+
652
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
653
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
654
+
655
+        $qb->orderBy('id');
656
+
657
+        $cursor = $qb->execute();
658
+        $shares = [];
659
+        while ($data = $cursor->fetch()) {
660
+            $shares[$data['fileid']][] = $this->createShareObject($data);
661
+        }
662
+        $cursor->closeCursor();
663
+
664
+        return $shares;
665
+    }
666
+
667
+    /**
668
+     * @inheritdoc
669
+     */
670
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
671
+        $qb = $this->dbConnection->getQueryBuilder();
672
+        $qb->select('*')
673
+            ->from('share');
674
+
675
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
676
+
677
+        /**
678
+         * Reshares for this user are shares where they are the owner.
679
+         */
680
+        if ($reshares === false) {
681
+            //Special case for old shares created via the web UI
682
+            $or1 = $qb->expr()->andX(
683
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
684
+                $qb->expr()->isNull('uid_initiator')
685
+            );
686
+
687
+            $qb->andWhere(
688
+                $qb->expr()->orX(
689
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
690
+                    $or1
691
+                )
692
+            );
693
+        } else {
694
+            $qb->andWhere(
695
+                $qb->expr()->orX(
696
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
697
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
698
+                )
699
+            );
700
+        }
701
+
702
+        if ($node !== null) {
703
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
704
+        }
705
+
706
+        if ($limit !== -1) {
707
+            $qb->setMaxResults($limit);
708
+        }
709
+
710
+        $qb->setFirstResult($offset);
711
+        $qb->orderBy('id');
712
+
713
+        $cursor = $qb->execute();
714
+        $shares = [];
715
+        while($data = $cursor->fetch()) {
716
+            $shares[] = $this->createShareObject($data);
717
+        }
718
+        $cursor->closeCursor();
719
+
720
+        return $shares;
721
+    }
722
+
723
+    /**
724
+     * @inheritdoc
725
+     */
726
+    public function getShareById($id, $recipientId = null) {
727
+        $qb = $this->dbConnection->getQueryBuilder();
728
+
729
+        $qb->select('*')
730
+            ->from('share')
731
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
732
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
733
+
734
+        $cursor = $qb->execute();
735
+        $data = $cursor->fetch();
736
+        $cursor->closeCursor();
737
+
738
+        if ($data === false) {
739
+            throw new ShareNotFound('Can not find share with ID: ' . $id);
740
+        }
741
+
742
+        try {
743
+            $share = $this->createShareObject($data);
744
+        } catch (InvalidShare $e) {
745
+            throw new ShareNotFound();
746
+        }
747
+
748
+        return $share;
749
+    }
750
+
751
+    /**
752
+     * Get shares for a given path
753
+     *
754
+     * @param \OCP\Files\Node $path
755
+     * @return IShare[]
756
+     */
757
+    public function getSharesByPath(Node $path) {
758
+        $qb = $this->dbConnection->getQueryBuilder();
759
+
760
+        // get federated user shares
761
+        $cursor = $qb->select('*')
762
+            ->from('share')
763
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
764
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
765
+            ->execute();
766
+
767
+        $shares = [];
768
+        while($data = $cursor->fetch()) {
769
+            $shares[] = $this->createShareObject($data);
770
+        }
771
+        $cursor->closeCursor();
772
+
773
+        return $shares;
774
+    }
775
+
776
+    /**
777
+     * @inheritdoc
778
+     */
779
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
780
+        /** @var IShare[] $shares */
781
+        $shares = [];
782
+
783
+        //Get shares directly with this user
784
+        $qb = $this->dbConnection->getQueryBuilder();
785
+        $qb->select('*')
786
+            ->from('share');
787
+
788
+        // Order by id
789
+        $qb->orderBy('id');
790
+
791
+        // Set limit and offset
792
+        if ($limit !== -1) {
793
+            $qb->setMaxResults($limit);
794
+        }
795
+        $qb->setFirstResult($offset);
796
+
797
+        $qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
798
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
799
+
800
+        // Filter by node if provided
801
+        if ($node !== null) {
802
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
803
+        }
804
+
805
+        $cursor = $qb->execute();
806
+
807
+        while($data = $cursor->fetch()) {
808
+            $shares[] = $this->createShareObject($data);
809
+        }
810
+        $cursor->closeCursor();
811
+
812
+
813
+        return $shares;
814
+    }
815
+
816
+    /**
817
+     * Get a share by token
818
+     *
819
+     * @param string $token
820
+     * @return IShare
821
+     * @throws ShareNotFound
822
+     */
823
+    public function getShareByToken($token) {
824
+        $qb = $this->dbConnection->getQueryBuilder();
825
+
826
+        $cursor = $qb->select('*')
827
+            ->from('share')
828
+            ->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
829
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
830
+            ->execute();
831
+
832
+        $data = $cursor->fetch();
833
+
834
+        if ($data === false) {
835
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
836
+        }
837
+
838
+        try {
839
+            $share = $this->createShareObject($data);
840
+        } catch (InvalidShare $e) {
841
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
842
+        }
843
+
844
+        return $share;
845
+    }
846
+
847
+    /**
848
+     * get database row of a give share
849
+     *
850
+     * @param $id
851
+     * @return array
852
+     * @throws ShareNotFound
853
+     */
854
+    private function getRawShare($id) {
855
+
856
+        // Now fetch the inserted share and create a complete share object
857
+        $qb = $this->dbConnection->getQueryBuilder();
858
+        $qb->select('*')
859
+            ->from('share')
860
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
861
+
862
+        $cursor = $qb->execute();
863
+        $data = $cursor->fetch();
864
+        $cursor->closeCursor();
865
+
866
+        if ($data === false) {
867
+            throw new ShareNotFound;
868
+        }
869
+
870
+        return $data;
871
+    }
872
+
873
+    /**
874
+     * Create a share object from an database row
875
+     *
876
+     * @param array $data
877
+     * @return IShare
878
+     * @throws InvalidShare
879
+     * @throws ShareNotFound
880
+     */
881
+    private function createShareObject($data) {
882
+
883
+        $share = new Share($this->rootFolder, $this->userManager);
884
+        $share->setId((int)$data['id'])
885
+            ->setShareType((int)$data['share_type'])
886
+            ->setPermissions((int)$data['permissions'])
887
+            ->setTarget($data['file_target'])
888
+            ->setMailSend((bool)$data['mail_send'])
889
+            ->setToken($data['token']);
890
+
891
+        $shareTime = new \DateTime();
892
+        $shareTime->setTimestamp((int)$data['stime']);
893
+        $share->setShareTime($shareTime);
894
+        $share->setSharedWith($data['share_with']);
895
+
896
+        if ($data['uid_initiator'] !== null) {
897
+            $share->setShareOwner($data['uid_owner']);
898
+            $share->setSharedBy($data['uid_initiator']);
899
+        } else {
900
+            //OLD SHARE
901
+            $share->setSharedBy($data['uid_owner']);
902
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
903
+
904
+            $owner = $path->getOwner();
905
+            $share->setShareOwner($owner->getUID());
906
+        }
907
+
908
+        $share->setNodeId((int)$data['file_source']);
909
+        $share->setNodeType($data['item_type']);
910
+
911
+        $share->setProviderId($this->identifier());
912
+
913
+        return $share;
914
+    }
915
+
916
+    /**
917
+     * Get the node with file $id for $user
918
+     *
919
+     * @param string $userId
920
+     * @param int $id
921
+     * @return \OCP\Files\File|\OCP\Files\Folder
922
+     * @throws InvalidShare
923
+     */
924
+    private function getNode($userId, $id) {
925
+        try {
926
+            $userFolder = $this->rootFolder->getUserFolder($userId);
927
+        } catch (NotFoundException $e) {
928
+            throw new InvalidShare();
929
+        }
930
+
931
+        $nodes = $userFolder->getById($id);
932
+
933
+        if (empty($nodes)) {
934
+            throw new InvalidShare();
935
+        }
936
+
937
+        return $nodes[0];
938
+    }
939
+
940
+    /**
941
+     * A user is deleted from the system
942
+     * So clean up the relevant shares.
943
+     *
944
+     * @param string $uid
945
+     * @param int $shareType
946
+     */
947
+    public function userDeleted($uid, $shareType) {
948
+        //TODO: probabaly a good idea to send unshare info to remote servers
949
+
950
+        $qb = $this->dbConnection->getQueryBuilder();
951
+
952
+        $qb->delete('share')
953
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
954
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
955
+            ->execute();
956
+    }
957
+
958
+    /**
959
+     * This provider does not handle groups
960
+     *
961
+     * @param string $gid
962
+     */
963
+    public function groupDeleted($gid) {
964
+        // We don't handle groups here
965
+    }
966
+
967
+    /**
968
+     * This provider does not handle groups
969
+     *
970
+     * @param string $uid
971
+     * @param string $gid
972
+     */
973
+    public function userDeletedFromGroup($uid, $gid) {
974
+        // We don't handle groups here
975
+    }
976
+
977
+    /**
978
+     * check if users from other Nextcloud instances are allowed to mount public links share by this instance
979
+     *
980
+     * @return bool
981
+     */
982
+    public function isOutgoingServer2serverShareEnabled() {
983
+        if ($this->gsConfig->onlyInternalFederation()) {
984
+            return false;
985
+        }
986
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
987
+        return ($result === 'yes');
988
+    }
989
+
990
+    /**
991
+     * check if users are allowed to mount public links from other Nextclouds
992
+     *
993
+     * @return bool
994
+     */
995
+    public function isIncomingServer2serverShareEnabled() {
996
+        if ($this->gsConfig->onlyInternalFederation()) {
997
+            return false;
998
+        }
999
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
1000
+        return ($result === 'yes');
1001
+    }
1002
+
1003
+
1004
+    /**
1005
+     * check if users from other Nextcloud instances are allowed to send federated group shares
1006
+     *
1007
+     * @return bool
1008
+     */
1009
+    public function isOutgoingServer2serverGroupShareEnabled() {
1010
+        if ($this->gsConfig->onlyInternalFederation()) {
1011
+            return false;
1012
+        }
1013
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1014
+        return ($result === 'yes');
1015
+    }
1016
+
1017
+    /**
1018
+     * check if users are allowed to receive federated group shares
1019
+     *
1020
+     * @return bool
1021
+     */
1022
+    public function isIncomingServer2serverGroupShareEnabled() {
1023
+        if ($this->gsConfig->onlyInternalFederation()) {
1024
+            return false;
1025
+        }
1026
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1027
+        return ($result === 'yes');
1028
+    }
1029
+
1030
+    /**
1031
+     * check if federated group sharing is supported, therefore the OCM API need to be enabled
1032
+     *
1033
+     * @return bool
1034
+     */
1035
+    public function isFederatedGroupSharingSupported() {
1036
+        return $this->cloudFederationProviderManager->isReady();
1037
+    }
1038
+
1039
+    /**
1040
+     * Check if querying sharees on the lookup server is enabled
1041
+     *
1042
+     * @return bool
1043
+     */
1044
+    public function isLookupServerQueriesEnabled() {
1045
+        // in a global scale setup we should always query the lookup server
1046
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1047
+            return true;
1048
+        }
1049
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes');
1050
+        return ($result === 'yes');
1051
+    }
1052
+
1053
+
1054
+    /**
1055
+     * Check if it is allowed to publish user specific data to the lookup server
1056
+     *
1057
+     * @return bool
1058
+     */
1059
+    public function isLookupServerUploadEnabled() {
1060
+        // in a global scale setup the admin is responsible to keep the lookup server up-to-date
1061
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1062
+            return false;
1063
+        }
1064
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1065
+        return ($result === 'yes');
1066
+    }
1067
+
1068
+    /**
1069
+     * @inheritdoc
1070
+     */
1071
+    public function getAccessList($nodes, $currentAccess) {
1072
+        $ids = [];
1073
+        foreach ($nodes as $node) {
1074
+            $ids[] = $node->getId();
1075
+        }
1076
+
1077
+        $qb = $this->dbConnection->getQueryBuilder();
1078
+        $qb->select('share_with', 'token', 'file_source')
1079
+            ->from('share')
1080
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1081
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1082
+            ->andWhere($qb->expr()->orX(
1083
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1084
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1085
+            ));
1086
+        $cursor = $qb->execute();
1087
+
1088
+        if ($currentAccess === false) {
1089
+            $remote = $cursor->fetch() !== false;
1090
+            $cursor->closeCursor();
1091
+
1092
+            return ['remote' => $remote];
1093
+        }
1094
+
1095
+        $remote = [];
1096
+        while ($row = $cursor->fetch()) {
1097
+            $remote[$row['share_with']] = [
1098
+                'node_id' => $row['file_source'],
1099
+                'token' => $row['token'],
1100
+            ];
1101
+        }
1102
+        $cursor->closeCursor();
1103
+
1104
+        return ['remote' => $remote];
1105
+    }
1106
+
1107
+    public function getAllShares(): iterable {
1108
+        $qb = $this->dbConnection->getQueryBuilder();
1109
+
1110
+        $qb->select('*')
1111
+            ->from('share')
1112
+            ->where(
1113
+                $qb->expr()->orX(
1114
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
1115
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
1116
+                )
1117
+            );
1118
+
1119
+        $cursor = $qb->execute();
1120
+        while($data = $cursor->fetch()) {
1121
+            try {
1122
+                $share = $this->createShareObject($data);
1123
+            } catch (InvalidShare $e) {
1124
+                continue;
1125
+            } catch (ShareNotFound $e) {
1126
+                continue;
1127
+            }
1128
+
1129
+            yield $share;
1130
+        }
1131
+        $cursor->closeCursor();
1132
+    }
1133 1133
 }
Please login to merge, or discard this patch.