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