Passed
Push — master ( ac893e...b07a8f )
by Roeland
14:27 queued 12s
created
apps/federatedfilesharing/lib/FederatedShareProvider.php 1 patch
Indentation   +1059 added lines, -1059 removed lines patch added patch discarded remove patch
@@ -61,1073 +61,1073 @@
 block discarded – undo
61 61
  * @package OCA\FederatedFileSharing
62 62
  */
63 63
 class FederatedShareProvider implements IShareProvider {
64
-	public const SHARE_TYPE_REMOTE = 6;
65
-
66
-	/** @var IDBConnection */
67
-	private $dbConnection;
68
-
69
-	/** @var AddressHandler */
70
-	private $addressHandler;
71
-
72
-	/** @var Notifications */
73
-	private $notifications;
74
-
75
-	/** @var TokenHandler */
76
-	private $tokenHandler;
77
-
78
-	/** @var IL10N */
79
-	private $l;
80
-
81
-	/** @var ILogger */
82
-	private $logger;
83
-
84
-	/** @var IRootFolder */
85
-	private $rootFolder;
86
-
87
-	/** @var IConfig */
88
-	private $config;
89
-
90
-	/** @var string */
91
-	private $externalShareTable = 'share_external';
92
-
93
-	/** @var IUserManager */
94
-	private $userManager;
95
-
96
-	/** @var ICloudIdManager */
97
-	private $cloudIdManager;
98
-
99
-	/** @var \OCP\GlobalScale\IConfig */
100
-	private $gsConfig;
101
-
102
-	/** @var ICloudFederationProviderManager */
103
-	private $cloudFederationProviderManager;
104
-
105
-	/** @var array list of supported share types */
106
-	private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
107
-
108
-	/**
109
-	 * DefaultShareProvider constructor.
110
-	 *
111
-	 * @param IDBConnection $connection
112
-	 * @param AddressHandler $addressHandler
113
-	 * @param Notifications $notifications
114
-	 * @param TokenHandler $tokenHandler
115
-	 * @param IL10N $l10n
116
-	 * @param ILogger $logger
117
-	 * @param IRootFolder $rootFolder
118
-	 * @param IConfig $config
119
-	 * @param IUserManager $userManager
120
-	 * @param ICloudIdManager $cloudIdManager
121
-	 * @param \OCP\GlobalScale\IConfig $globalScaleConfig
122
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
123
-	 */
124
-	public function __construct(
125
-			IDBConnection $connection,
126
-			AddressHandler $addressHandler,
127
-			Notifications $notifications,
128
-			TokenHandler $tokenHandler,
129
-			IL10N $l10n,
130
-			ILogger $logger,
131
-			IRootFolder $rootFolder,
132
-			IConfig $config,
133
-			IUserManager $userManager,
134
-			ICloudIdManager $cloudIdManager,
135
-			\OCP\GlobalScale\IConfig $globalScaleConfig,
136
-			ICloudFederationProviderManager $cloudFederationProviderManager
137
-	) {
138
-		$this->dbConnection = $connection;
139
-		$this->addressHandler = $addressHandler;
140
-		$this->notifications = $notifications;
141
-		$this->tokenHandler = $tokenHandler;
142
-		$this->l = $l10n;
143
-		$this->logger = $logger;
144
-		$this->rootFolder = $rootFolder;
145
-		$this->config = $config;
146
-		$this->userManager = $userManager;
147
-		$this->cloudIdManager = $cloudIdManager;
148
-		$this->gsConfig = $globalScaleConfig;
149
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
150
-	}
151
-
152
-	/**
153
-	 * Return the identifier of this provider.
154
-	 *
155
-	 * @return string Containing only [a-zA-Z0-9]
156
-	 */
157
-	public function identifier() {
158
-		return 'ocFederatedSharing';
159
-	}
160
-
161
-	/**
162
-	 * Share a path
163
-	 *
164
-	 * @param IShare $share
165
-	 * @return IShare The share object
166
-	 * @throws ShareNotFound
167
-	 * @throws \Exception
168
-	 */
169
-	public function create(IShare $share) {
170
-		$shareWith = $share->getSharedWith();
171
-		$itemSource = $share->getNodeId();
172
-		$itemType = $share->getNodeType();
173
-		$permissions = $share->getPermissions();
174
-		$sharedBy = $share->getSharedBy();
175
-		$shareType = $share->getShareType();
176
-
177
-		if ($shareType === IShare::TYPE_REMOTE_GROUP &&
178
-			!$this->isOutgoingServer2serverGroupShareEnabled()
179
-		) {
180
-			$message = 'It is not allowed to send federated group shares from this server.';
181
-			$message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
182
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
183
-			throw new \Exception($message_t);
184
-		}
185
-
186
-		/*
64
+    public const SHARE_TYPE_REMOTE = 6;
65
+
66
+    /** @var IDBConnection */
67
+    private $dbConnection;
68
+
69
+    /** @var AddressHandler */
70
+    private $addressHandler;
71
+
72
+    /** @var Notifications */
73
+    private $notifications;
74
+
75
+    /** @var TokenHandler */
76
+    private $tokenHandler;
77
+
78
+    /** @var IL10N */
79
+    private $l;
80
+
81
+    /** @var ILogger */
82
+    private $logger;
83
+
84
+    /** @var IRootFolder */
85
+    private $rootFolder;
86
+
87
+    /** @var IConfig */
88
+    private $config;
89
+
90
+    /** @var string */
91
+    private $externalShareTable = 'share_external';
92
+
93
+    /** @var IUserManager */
94
+    private $userManager;
95
+
96
+    /** @var ICloudIdManager */
97
+    private $cloudIdManager;
98
+
99
+    /** @var \OCP\GlobalScale\IConfig */
100
+    private $gsConfig;
101
+
102
+    /** @var ICloudFederationProviderManager */
103
+    private $cloudFederationProviderManager;
104
+
105
+    /** @var array list of supported share types */
106
+    private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
107
+
108
+    /**
109
+     * DefaultShareProvider constructor.
110
+     *
111
+     * @param IDBConnection $connection
112
+     * @param AddressHandler $addressHandler
113
+     * @param Notifications $notifications
114
+     * @param TokenHandler $tokenHandler
115
+     * @param IL10N $l10n
116
+     * @param ILogger $logger
117
+     * @param IRootFolder $rootFolder
118
+     * @param IConfig $config
119
+     * @param IUserManager $userManager
120
+     * @param ICloudIdManager $cloudIdManager
121
+     * @param \OCP\GlobalScale\IConfig $globalScaleConfig
122
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
123
+     */
124
+    public function __construct(
125
+            IDBConnection $connection,
126
+            AddressHandler $addressHandler,
127
+            Notifications $notifications,
128
+            TokenHandler $tokenHandler,
129
+            IL10N $l10n,
130
+            ILogger $logger,
131
+            IRootFolder $rootFolder,
132
+            IConfig $config,
133
+            IUserManager $userManager,
134
+            ICloudIdManager $cloudIdManager,
135
+            \OCP\GlobalScale\IConfig $globalScaleConfig,
136
+            ICloudFederationProviderManager $cloudFederationProviderManager
137
+    ) {
138
+        $this->dbConnection = $connection;
139
+        $this->addressHandler = $addressHandler;
140
+        $this->notifications = $notifications;
141
+        $this->tokenHandler = $tokenHandler;
142
+        $this->l = $l10n;
143
+        $this->logger = $logger;
144
+        $this->rootFolder = $rootFolder;
145
+        $this->config = $config;
146
+        $this->userManager = $userManager;
147
+        $this->cloudIdManager = $cloudIdManager;
148
+        $this->gsConfig = $globalScaleConfig;
149
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
150
+    }
151
+
152
+    /**
153
+     * Return the identifier of this provider.
154
+     *
155
+     * @return string Containing only [a-zA-Z0-9]
156
+     */
157
+    public function identifier() {
158
+        return 'ocFederatedSharing';
159
+    }
160
+
161
+    /**
162
+     * Share a path
163
+     *
164
+     * @param IShare $share
165
+     * @return IShare The share object
166
+     * @throws ShareNotFound
167
+     * @throws \Exception
168
+     */
169
+    public function create(IShare $share) {
170
+        $shareWith = $share->getSharedWith();
171
+        $itemSource = $share->getNodeId();
172
+        $itemType = $share->getNodeType();
173
+        $permissions = $share->getPermissions();
174
+        $sharedBy = $share->getSharedBy();
175
+        $shareType = $share->getShareType();
176
+
177
+        if ($shareType === IShare::TYPE_REMOTE_GROUP &&
178
+            !$this->isOutgoingServer2serverGroupShareEnabled()
179
+        ) {
180
+            $message = 'It is not allowed to send federated group shares from this server.';
181
+            $message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
182
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
183
+            throw new \Exception($message_t);
184
+        }
185
+
186
+        /*
187 187
 		 * Check if file is not already shared with the remote user
188 188
 		 */
189
-		$alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE, $share->getNode(), 1, 0);
190
-		$alreadySharedGroup = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
191
-		if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
192
-			$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
193
-			$message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with user %2$s', [$share->getNode()->getName(), $shareWith]);
194
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
195
-			throw new \Exception($message_t);
196
-		}
197
-
198
-
199
-		// don't allow federated shares if source and target server are the same
200
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
201
-		$currentServer = $this->addressHandler->generateRemoteURL();
202
-		$currentUser = $sharedBy;
203
-		if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
204
-			$message = 'Not allowed to create a federated share with the same user.';
205
-			$message_t = $this->l->t('Not allowed to create a federated share with the same user');
206
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
207
-			throw new \Exception($message_t);
208
-		}
209
-
210
-
211
-		$share->setSharedWith($cloudId->getId());
212
-
213
-		try {
214
-			$remoteShare = $this->getShareFromExternalShareTable($share);
215
-		} catch (ShareNotFound $e) {
216
-			$remoteShare = null;
217
-		}
218
-
219
-		if ($remoteShare) {
220
-			try {
221
-				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
222
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
223
-				$share->setId($shareId);
224
-				[$token, $remoteId] = $this->askOwnerToReShare($shareWith, $share, $shareId);
225
-				// remote share was create successfully if we get a valid token as return
226
-				$send = is_string($token) && $token !== '';
227
-			} catch (\Exception $e) {
228
-				// fall back to old re-share behavior if the remote server
229
-				// doesn't support flat re-shares (was introduced with Nextcloud 9.1)
230
-				$this->removeShareFromTable($share);
231
-				$shareId = $this->createFederatedShare($share);
232
-			}
233
-			if ($send) {
234
-				$this->updateSuccessfulReshare($shareId, $token);
235
-				$this->storeRemoteId($shareId, $remoteId);
236
-			} else {
237
-				$this->removeShareFromTable($share);
238
-				$message_t = $this->l->t('File is already shared with %s', [$shareWith]);
239
-				throw new \Exception($message_t);
240
-			}
241
-		} else {
242
-			$shareId = $this->createFederatedShare($share);
243
-		}
244
-
245
-		$data = $this->getRawShare($shareId);
246
-		return $this->createShareObject($data);
247
-	}
248
-
249
-	/**
250
-	 * create federated share and inform the recipient
251
-	 *
252
-	 * @param IShare $share
253
-	 * @return int
254
-	 * @throws ShareNotFound
255
-	 * @throws \Exception
256
-	 */
257
-	protected function createFederatedShare(IShare $share) {
258
-		$token = $this->tokenHandler->generateToken();
259
-		$shareId = $this->addShareToDB(
260
-			$share->getNodeId(),
261
-			$share->getNodeType(),
262
-			$share->getSharedWith(),
263
-			$share->getSharedBy(),
264
-			$share->getShareOwner(),
265
-			$share->getPermissions(),
266
-			$token,
267
-			$share->getShareType()
268
-		);
269
-
270
-		$failure = false;
271
-
272
-		try {
273
-			$sharedByFederatedId = $share->getSharedBy();
274
-			if ($this->userManager->userExists($sharedByFederatedId)) {
275
-				$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
276
-				$sharedByFederatedId = $cloudId->getId();
277
-			}
278
-			$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
279
-			$send = $this->notifications->sendRemoteShare(
280
-				$token,
281
-				$share->getSharedWith(),
282
-				$share->getNode()->getName(),
283
-				$shareId,
284
-				$share->getShareOwner(),
285
-				$ownerCloudId->getId(),
286
-				$share->getSharedBy(),
287
-				$sharedByFederatedId,
288
-				$share->getShareType()
289
-			);
290
-
291
-			if ($send === false) {
292
-				$failure = true;
293
-			}
294
-		} catch (\Exception $e) {
295
-			$this->logger->logException($e, [
296
-				'message' => 'Failed to notify remote server of federated share, removing share.',
297
-				'level' => ILogger::ERROR,
298
-				'app' => 'federatedfilesharing',
299
-			]);
300
-			$failure = true;
301
-		}
302
-
303
-		if ($failure) {
304
-			$this->removeShareFromTableById($shareId);
305
-			$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.',
306
-				[$share->getNode()->getName(), $share->getSharedWith()]);
307
-			throw new \Exception($message_t);
308
-		}
309
-
310
-		return $shareId;
311
-	}
312
-
313
-	/**
314
-	 * @param string $shareWith
315
-	 * @param IShare $share
316
-	 * @param string $shareId internal share Id
317
-	 * @return array
318
-	 * @throws \Exception
319
-	 */
320
-	protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
321
-		$remoteShare = $this->getShareFromExternalShareTable($share);
322
-		$token = $remoteShare['share_token'];
323
-		$remoteId = $remoteShare['remote_id'];
324
-		$remote = $remoteShare['remote'];
325
-
326
-		[$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
-		$qResult = $query->execute();
352
-		$result = $qResult->fetchAll();
353
-		$qResult->closeCursor();
354
-
355
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
356
-			return $result[0];
357
-		}
358
-
359
-		throw new ShareNotFound('share not found in share_external table');
360
-	}
361
-
362
-	/**
363
-	 * add share to the database and return the ID
364
-	 *
365
-	 * @param int $itemSource
366
-	 * @param string $itemType
367
-	 * @param string $shareWith
368
-	 * @param string $sharedBy
369
-	 * @param string $uidOwner
370
-	 * @param int $permissions
371
-	 * @param string $token
372
-	 * @param int $shareType
373
-	 * @return int
374
-	 */
375
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
376
-		$qb = $this->dbConnection->getQueryBuilder();
377
-		$qb->insert('share')
378
-			->setValue('share_type', $qb->createNamedParameter($shareType))
379
-			->setValue('item_type', $qb->createNamedParameter($itemType))
380
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
381
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
382
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
383
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
384
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
385
-			->setValue('permissions', $qb->createNamedParameter($permissions))
386
-			->setValue('token', $qb->createNamedParameter($token))
387
-			->setValue('stime', $qb->createNamedParameter(time()));
388
-
389
-		/*
189
+        $alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE, $share->getNode(), 1, 0);
190
+        $alreadySharedGroup = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
191
+        if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
192
+            $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
193
+            $message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with user %2$s', [$share->getNode()->getName(), $shareWith]);
194
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
195
+            throw new \Exception($message_t);
196
+        }
197
+
198
+
199
+        // don't allow federated shares if source and target server are the same
200
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
201
+        $currentServer = $this->addressHandler->generateRemoteURL();
202
+        $currentUser = $sharedBy;
203
+        if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
204
+            $message = 'Not allowed to create a federated share with the same user.';
205
+            $message_t = $this->l->t('Not allowed to create a federated share with the same user');
206
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
207
+            throw new \Exception($message_t);
208
+        }
209
+
210
+
211
+        $share->setSharedWith($cloudId->getId());
212
+
213
+        try {
214
+            $remoteShare = $this->getShareFromExternalShareTable($share);
215
+        } catch (ShareNotFound $e) {
216
+            $remoteShare = null;
217
+        }
218
+
219
+        if ($remoteShare) {
220
+            try {
221
+                $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
222
+                $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
223
+                $share->setId($shareId);
224
+                [$token, $remoteId] = $this->askOwnerToReShare($shareWith, $share, $shareId);
225
+                // remote share was create successfully if we get a valid token as return
226
+                $send = is_string($token) && $token !== '';
227
+            } catch (\Exception $e) {
228
+                // fall back to old re-share behavior if the remote server
229
+                // doesn't support flat re-shares (was introduced with Nextcloud 9.1)
230
+                $this->removeShareFromTable($share);
231
+                $shareId = $this->createFederatedShare($share);
232
+            }
233
+            if ($send) {
234
+                $this->updateSuccessfulReshare($shareId, $token);
235
+                $this->storeRemoteId($shareId, $remoteId);
236
+            } else {
237
+                $this->removeShareFromTable($share);
238
+                $message_t = $this->l->t('File is already shared with %s', [$shareWith]);
239
+                throw new \Exception($message_t);
240
+            }
241
+        } else {
242
+            $shareId = $this->createFederatedShare($share);
243
+        }
244
+
245
+        $data = $this->getRawShare($shareId);
246
+        return $this->createShareObject($data);
247
+    }
248
+
249
+    /**
250
+     * create federated share and inform the recipient
251
+     *
252
+     * @param IShare $share
253
+     * @return int
254
+     * @throws ShareNotFound
255
+     * @throws \Exception
256
+     */
257
+    protected function createFederatedShare(IShare $share) {
258
+        $token = $this->tokenHandler->generateToken();
259
+        $shareId = $this->addShareToDB(
260
+            $share->getNodeId(),
261
+            $share->getNodeType(),
262
+            $share->getSharedWith(),
263
+            $share->getSharedBy(),
264
+            $share->getShareOwner(),
265
+            $share->getPermissions(),
266
+            $token,
267
+            $share->getShareType()
268
+        );
269
+
270
+        $failure = false;
271
+
272
+        try {
273
+            $sharedByFederatedId = $share->getSharedBy();
274
+            if ($this->userManager->userExists($sharedByFederatedId)) {
275
+                $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
276
+                $sharedByFederatedId = $cloudId->getId();
277
+            }
278
+            $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
279
+            $send = $this->notifications->sendRemoteShare(
280
+                $token,
281
+                $share->getSharedWith(),
282
+                $share->getNode()->getName(),
283
+                $shareId,
284
+                $share->getShareOwner(),
285
+                $ownerCloudId->getId(),
286
+                $share->getSharedBy(),
287
+                $sharedByFederatedId,
288
+                $share->getShareType()
289
+            );
290
+
291
+            if ($send === false) {
292
+                $failure = true;
293
+            }
294
+        } catch (\Exception $e) {
295
+            $this->logger->logException($e, [
296
+                'message' => 'Failed to notify remote server of federated share, removing share.',
297
+                'level' => ILogger::ERROR,
298
+                'app' => 'federatedfilesharing',
299
+            ]);
300
+            $failure = true;
301
+        }
302
+
303
+        if ($failure) {
304
+            $this->removeShareFromTableById($shareId);
305
+            $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.',
306
+                [$share->getNode()->getName(), $share->getSharedWith()]);
307
+            throw new \Exception($message_t);
308
+        }
309
+
310
+        return $shareId;
311
+    }
312
+
313
+    /**
314
+     * @param string $shareWith
315
+     * @param IShare $share
316
+     * @param string $shareId internal share Id
317
+     * @return array
318
+     * @throws \Exception
319
+     */
320
+    protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
321
+        $remoteShare = $this->getShareFromExternalShareTable($share);
322
+        $token = $remoteShare['share_token'];
323
+        $remoteId = $remoteShare['remote_id'];
324
+        $remote = $remoteShare['remote'];
325
+
326
+        [$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
+        $qResult = $query->execute();
352
+        $result = $qResult->fetchAll();
353
+        $qResult->closeCursor();
354
+
355
+        if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
356
+            return $result[0];
357
+        }
358
+
359
+        throw new ShareNotFound('share not found in share_external table');
360
+    }
361
+
362
+    /**
363
+     * add share to the database and return the ID
364
+     *
365
+     * @param int $itemSource
366
+     * @param string $itemType
367
+     * @param string $shareWith
368
+     * @param string $sharedBy
369
+     * @param string $uidOwner
370
+     * @param int $permissions
371
+     * @param string $token
372
+     * @param int $shareType
373
+     * @return int
374
+     */
375
+    private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
376
+        $qb = $this->dbConnection->getQueryBuilder();
377
+        $qb->insert('share')
378
+            ->setValue('share_type', $qb->createNamedParameter($shareType))
379
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
380
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
381
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
382
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
383
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
384
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
385
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
386
+            ->setValue('token', $qb->createNamedParameter($token))
387
+            ->setValue('stime', $qb->createNamedParameter(time()));
388
+
389
+        /*
390 390
 		 * Added to fix https://github.com/owncloud/core/issues/22215
391 391
 		 * Can be removed once we get rid of ajax/share.php
392 392
 		 */
393
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
394
-
395
-		$qb->execute();
396
-		return $qb->getLastInsertId();
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
-		/*
393
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
394
+
395
+        $qb->execute();
396
+        return $qb->getLastInsertId();
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
-			[, $remote] = $this->addressHandler->splitUserRemote($share->getSharedBy());
437
-		} else { // ... if not we send the permission change to the owner
438
-			[, $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(int $shareId, string $remoteId): void {
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 string
481
-	 * @throws ShareNotFound
482
-	 */
483
-	public function getRemoteId(IShare $share): string {
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
-		$result = $query->execute();
488
-		$data = $result->fetch();
489
-		$result->closeCursor();
490
-
491
-		if (!is_array($data) || !isset($data['remote_id'])) {
492
-			throw new ShareNotFound();
493
-		}
494
-
495
-		return (string)$data['remote_id'];
496
-	}
497
-
498
-	/**
499
-	 * @inheritdoc
500
-	 */
501
-	public function move(IShare $share, $recipient) {
502
-		/*
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
+            [, $remote] = $this->addressHandler->splitUserRemote($share->getSharedBy());
437
+        } else { // ... if not we send the permission change to the owner
438
+            [, $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(int $shareId, string $remoteId): void {
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 string
481
+     * @throws ShareNotFound
482
+     */
483
+    public function getRemoteId(IShare $share): string {
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
+        $result = $query->execute();
488
+        $data = $result->fetch();
489
+        $result->closeCursor();
490
+
491
+        if (!is_array($data) || !isset($data['remote_id'])) {
492
+            throw new ShareNotFound();
493
+        }
494
+
495
+        return (string)$data['remote_id'];
496
+    }
497
+
498
+    /**
499
+     * @inheritdoc
500
+     */
501
+    public function move(IShare $share, $recipient) {
502
+        /*
503 503
 		 * This function does nothing yet as it is just for outgoing
504 504
 		 * federated shares.
505 505
 		 */
506
-		return $share;
507
-	}
508
-
509
-	/**
510
-	 * Get all children of this share
511
-	 *
512
-	 * @param IShare $parent
513
-	 * @return IShare[]
514
-	 */
515
-	public function getChildren(IShare $parent) {
516
-		$children = [];
517
-
518
-		$qb = $this->dbConnection->getQueryBuilder();
519
-		$qb->select('*')
520
-			->from('share')
521
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
522
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
523
-			->orderBy('id');
524
-
525
-		$cursor = $qb->execute();
526
-		while ($data = $cursor->fetch()) {
527
-			$children[] = $this->createShareObject($data);
528
-		}
529
-		$cursor->closeCursor();
530
-
531
-		return $children;
532
-	}
533
-
534
-	/**
535
-	 * Delete a share (owner unShares the file)
536
-	 *
537
-	 * @param IShare $share
538
-	 * @throws ShareNotFound
539
-	 * @throws \OC\HintException
540
-	 */
541
-	public function delete(IShare $share) {
542
-		[, $remote] = $this->addressHandler->splitUserRemote($share->getSharedWith());
543
-
544
-		// if the local user is the owner we can send the unShare request directly...
545
-		if ($this->userManager->userExists($share->getShareOwner())) {
546
-			$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
547
-			$this->revokeShare($share, true);
548
-		} else { // ... if not we need to correct ID for the unShare request
549
-			$remoteId = $this->getRemoteId($share);
550
-			$this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
551
-			$this->revokeShare($share, false);
552
-		}
553
-
554
-		// only remove the share when all messages are send to not lose information
555
-		// about the share to early
556
-		$this->removeShareFromTable($share);
557
-	}
558
-
559
-	/**
560
-	 * in case of a re-share we need to send the other use (initiator or owner)
561
-	 * a message that the file was unshared
562
-	 *
563
-	 * @param IShare $share
564
-	 * @param bool $isOwner the user can either be the owner or the user who re-sahred it
565
-	 * @throws ShareNotFound
566
-	 * @throws \OC\HintException
567
-	 */
568
-	protected function revokeShare($share, $isOwner) {
569
-		if ($this->userManager->userExists($share->getShareOwner()) && $this->userManager->userExists($share->getSharedBy())) {
570
-			// If both the owner and the initiator of the share are local users we don't have to notify anybody else
571
-			return;
572
-		}
573
-
574
-		// also send a unShare request to the initiator, if this is a different user than the owner
575
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
576
-			if ($isOwner) {
577
-				[, $remote] = $this->addressHandler->splitUserRemote($share->getSharedBy());
578
-			} else {
579
-				[, $remote] = $this->addressHandler->splitUserRemote($share->getShareOwner());
580
-			}
581
-			$remoteId = $this->getRemoteId($share);
582
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
583
-		}
584
-	}
585
-
586
-	/**
587
-	 * remove share from table
588
-	 *
589
-	 * @param IShare $share
590
-	 */
591
-	public function removeShareFromTable(IShare $share) {
592
-		$this->removeShareFromTableById($share->getId());
593
-	}
594
-
595
-	/**
596
-	 * remove share from table
597
-	 *
598
-	 * @param string $shareId
599
-	 */
600
-	private function removeShareFromTableById($shareId) {
601
-		$qb = $this->dbConnection->getQueryBuilder();
602
-		$qb->delete('share')
603
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
604
-			->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
605
-		$qb->execute();
606
-
607
-		$qb->delete('federated_reshares')
608
-			->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
609
-		$qb->execute();
610
-	}
611
-
612
-	/**
613
-	 * @inheritdoc
614
-	 */
615
-	public function deleteFromSelf(IShare $share, $recipient) {
616
-		// nothing to do here. Technically deleteFromSelf in the context of federated
617
-		// shares is a umount of an external storage. This is handled here
618
-		// apps/files_sharing/lib/external/manager.php
619
-		// TODO move this code over to this app
620
-	}
621
-
622
-	public function restore(IShare $share, string $recipient): IShare {
623
-		throw new GenericShareException('not implemented');
624
-	}
625
-
626
-
627
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
628
-		$qb = $this->dbConnection->getQueryBuilder();
629
-		$qb->select('*')
630
-			->from('share', 's')
631
-			->andWhere($qb->expr()->orX(
632
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
633
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
634
-			))
635
-			->andWhere(
636
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
637
-			);
638
-
639
-		/**
640
-		 * Reshares for this user are shares where they are the owner.
641
-		 */
642
-		if ($reshares === false) {
643
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
644
-		} else {
645
-			$qb->andWhere(
646
-				$qb->expr()->orX(
647
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
648
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
649
-				)
650
-			);
651
-		}
652
-
653
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
654
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
655
-
656
-		$qb->orderBy('id');
657
-
658
-		$cursor = $qb->execute();
659
-		$shares = [];
660
-		while ($data = $cursor->fetch()) {
661
-			$shares[$data['fileid']][] = $this->createShareObject($data);
662
-		}
663
-		$cursor->closeCursor();
664
-
665
-		return $shares;
666
-	}
667
-
668
-	/**
669
-	 * @inheritdoc
670
-	 */
671
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
672
-		$qb = $this->dbConnection->getQueryBuilder();
673
-		$qb->select('*')
674
-			->from('share');
675
-
676
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
677
-
678
-		/**
679
-		 * Reshares for this user are shares where they are the owner.
680
-		 */
681
-		if ($reshares === false) {
682
-			//Special case for old shares created via the web UI
683
-			$or1 = $qb->expr()->andX(
684
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
685
-				$qb->expr()->isNull('uid_initiator')
686
-			);
687
-
688
-			$qb->andWhere(
689
-				$qb->expr()->orX(
690
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
691
-					$or1
692
-				)
693
-			);
694
-		} else {
695
-			$qb->andWhere(
696
-				$qb->expr()->orX(
697
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
698
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
699
-				)
700
-			);
701
-		}
702
-
703
-		if ($node !== null) {
704
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
705
-		}
706
-
707
-		if ($limit !== -1) {
708
-			$qb->setMaxResults($limit);
709
-		}
710
-
711
-		$qb->setFirstResult($offset);
712
-		$qb->orderBy('id');
713
-
714
-		$cursor = $qb->execute();
715
-		$shares = [];
716
-		while ($data = $cursor->fetch()) {
717
-			$shares[] = $this->createShareObject($data);
718
-		}
719
-		$cursor->closeCursor();
720
-
721
-		return $shares;
722
-	}
723
-
724
-	/**
725
-	 * @inheritdoc
726
-	 */
727
-	public function getShareById($id, $recipientId = null) {
728
-		$qb = $this->dbConnection->getQueryBuilder();
729
-
730
-		$qb->select('*')
731
-			->from('share')
732
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
733
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
734
-
735
-		$cursor = $qb->execute();
736
-		$data = $cursor->fetch();
737
-		$cursor->closeCursor();
738
-
739
-		if ($data === false) {
740
-			throw new ShareNotFound('Can not find share with ID: ' . $id);
741
-		}
742
-
743
-		try {
744
-			$share = $this->createShareObject($data);
745
-		} catch (InvalidShare $e) {
746
-			throw new ShareNotFound();
747
-		}
748
-
749
-		return $share;
750
-	}
751
-
752
-	/**
753
-	 * Get shares for a given path
754
-	 *
755
-	 * @param \OCP\Files\Node $path
756
-	 * @return IShare[]
757
-	 */
758
-	public function getSharesByPath(Node $path) {
759
-		$qb = $this->dbConnection->getQueryBuilder();
760
-
761
-		// get federated user shares
762
-		$cursor = $qb->select('*')
763
-			->from('share')
764
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
765
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
766
-			->execute();
767
-
768
-		$shares = [];
769
-		while ($data = $cursor->fetch()) {
770
-			$shares[] = $this->createShareObject($data);
771
-		}
772
-		$cursor->closeCursor();
773
-
774
-		return $shares;
775
-	}
776
-
777
-	/**
778
-	 * @inheritdoc
779
-	 */
780
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
781
-		/** @var IShare[] $shares */
782
-		$shares = [];
783
-
784
-		//Get shares directly with this user
785
-		$qb = $this->dbConnection->getQueryBuilder();
786
-		$qb->select('*')
787
-			->from('share');
788
-
789
-		// Order by id
790
-		$qb->orderBy('id');
791
-
792
-		// Set limit and offset
793
-		if ($limit !== -1) {
794
-			$qb->setMaxResults($limit);
795
-		}
796
-		$qb->setFirstResult($offset);
797
-
798
-		$qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
799
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
800
-
801
-		// Filter by node if provided
802
-		if ($node !== null) {
803
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
804
-		}
805
-
806
-		$cursor = $qb->execute();
807
-
808
-		while ($data = $cursor->fetch()) {
809
-			$shares[] = $this->createShareObject($data);
810
-		}
811
-		$cursor->closeCursor();
812
-
813
-
814
-		return $shares;
815
-	}
816
-
817
-	/**
818
-	 * Get a share by token
819
-	 *
820
-	 * @param string $token
821
-	 * @return IShare
822
-	 * @throws ShareNotFound
823
-	 */
824
-	public function getShareByToken($token) {
825
-		$qb = $this->dbConnection->getQueryBuilder();
826
-
827
-		$cursor = $qb->select('*')
828
-			->from('share')
829
-			->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
830
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
831
-			->execute();
832
-
833
-		$data = $cursor->fetch();
834
-
835
-		if ($data === false) {
836
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
837
-		}
838
-
839
-		try {
840
-			$share = $this->createShareObject($data);
841
-		} catch (InvalidShare $e) {
842
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
843
-		}
844
-
845
-		return $share;
846
-	}
847
-
848
-	/**
849
-	 * get database row of a give share
850
-	 *
851
-	 * @param $id
852
-	 * @return array
853
-	 * @throws ShareNotFound
854
-	 */
855
-	private function getRawShare($id) {
856
-
857
-		// Now fetch the inserted share and create a complete share object
858
-		$qb = $this->dbConnection->getQueryBuilder();
859
-		$qb->select('*')
860
-			->from('share')
861
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
862
-
863
-		$cursor = $qb->execute();
864
-		$data = $cursor->fetch();
865
-		$cursor->closeCursor();
866
-
867
-		if ($data === false) {
868
-			throw new ShareNotFound;
869
-		}
870
-
871
-		return $data;
872
-	}
873
-
874
-	/**
875
-	 * Create a share object from an database row
876
-	 *
877
-	 * @param array $data
878
-	 * @return IShare
879
-	 * @throws InvalidShare
880
-	 * @throws ShareNotFound
881
-	 */
882
-	private function createShareObject($data) {
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(IShare::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(IShare::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
-	}
506
+        return $share;
507
+    }
508
+
509
+    /**
510
+     * Get all children of this share
511
+     *
512
+     * @param IShare $parent
513
+     * @return IShare[]
514
+     */
515
+    public function getChildren(IShare $parent) {
516
+        $children = [];
517
+
518
+        $qb = $this->dbConnection->getQueryBuilder();
519
+        $qb->select('*')
520
+            ->from('share')
521
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
522
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
523
+            ->orderBy('id');
524
+
525
+        $cursor = $qb->execute();
526
+        while ($data = $cursor->fetch()) {
527
+            $children[] = $this->createShareObject($data);
528
+        }
529
+        $cursor->closeCursor();
530
+
531
+        return $children;
532
+    }
533
+
534
+    /**
535
+     * Delete a share (owner unShares the file)
536
+     *
537
+     * @param IShare $share
538
+     * @throws ShareNotFound
539
+     * @throws \OC\HintException
540
+     */
541
+    public function delete(IShare $share) {
542
+        [, $remote] = $this->addressHandler->splitUserRemote($share->getSharedWith());
543
+
544
+        // if the local user is the owner we can send the unShare request directly...
545
+        if ($this->userManager->userExists($share->getShareOwner())) {
546
+            $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
547
+            $this->revokeShare($share, true);
548
+        } else { // ... if not we need to correct ID for the unShare request
549
+            $remoteId = $this->getRemoteId($share);
550
+            $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
551
+            $this->revokeShare($share, false);
552
+        }
553
+
554
+        // only remove the share when all messages are send to not lose information
555
+        // about the share to early
556
+        $this->removeShareFromTable($share);
557
+    }
558
+
559
+    /**
560
+     * in case of a re-share we need to send the other use (initiator or owner)
561
+     * a message that the file was unshared
562
+     *
563
+     * @param IShare $share
564
+     * @param bool $isOwner the user can either be the owner or the user who re-sahred it
565
+     * @throws ShareNotFound
566
+     * @throws \OC\HintException
567
+     */
568
+    protected function revokeShare($share, $isOwner) {
569
+        if ($this->userManager->userExists($share->getShareOwner()) && $this->userManager->userExists($share->getSharedBy())) {
570
+            // If both the owner and the initiator of the share are local users we don't have to notify anybody else
571
+            return;
572
+        }
573
+
574
+        // also send a unShare request to the initiator, if this is a different user than the owner
575
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
576
+            if ($isOwner) {
577
+                [, $remote] = $this->addressHandler->splitUserRemote($share->getSharedBy());
578
+            } else {
579
+                [, $remote] = $this->addressHandler->splitUserRemote($share->getShareOwner());
580
+            }
581
+            $remoteId = $this->getRemoteId($share);
582
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
583
+        }
584
+    }
585
+
586
+    /**
587
+     * remove share from table
588
+     *
589
+     * @param IShare $share
590
+     */
591
+    public function removeShareFromTable(IShare $share) {
592
+        $this->removeShareFromTableById($share->getId());
593
+    }
594
+
595
+    /**
596
+     * remove share from table
597
+     *
598
+     * @param string $shareId
599
+     */
600
+    private function removeShareFromTableById($shareId) {
601
+        $qb = $this->dbConnection->getQueryBuilder();
602
+        $qb->delete('share')
603
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
604
+            ->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
605
+        $qb->execute();
606
+
607
+        $qb->delete('federated_reshares')
608
+            ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
609
+        $qb->execute();
610
+    }
611
+
612
+    /**
613
+     * @inheritdoc
614
+     */
615
+    public function deleteFromSelf(IShare $share, $recipient) {
616
+        // nothing to do here. Technically deleteFromSelf in the context of federated
617
+        // shares is a umount of an external storage. This is handled here
618
+        // apps/files_sharing/lib/external/manager.php
619
+        // TODO move this code over to this app
620
+    }
621
+
622
+    public function restore(IShare $share, string $recipient): IShare {
623
+        throw new GenericShareException('not implemented');
624
+    }
625
+
626
+
627
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
628
+        $qb = $this->dbConnection->getQueryBuilder();
629
+        $qb->select('*')
630
+            ->from('share', 's')
631
+            ->andWhere($qb->expr()->orX(
632
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
633
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
634
+            ))
635
+            ->andWhere(
636
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
637
+            );
638
+
639
+        /**
640
+         * Reshares for this user are shares where they are the owner.
641
+         */
642
+        if ($reshares === false) {
643
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
644
+        } else {
645
+            $qb->andWhere(
646
+                $qb->expr()->orX(
647
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
648
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
649
+                )
650
+            );
651
+        }
652
+
653
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
654
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
655
+
656
+        $qb->orderBy('id');
657
+
658
+        $cursor = $qb->execute();
659
+        $shares = [];
660
+        while ($data = $cursor->fetch()) {
661
+            $shares[$data['fileid']][] = $this->createShareObject($data);
662
+        }
663
+        $cursor->closeCursor();
664
+
665
+        return $shares;
666
+    }
667
+
668
+    /**
669
+     * @inheritdoc
670
+     */
671
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
672
+        $qb = $this->dbConnection->getQueryBuilder();
673
+        $qb->select('*')
674
+            ->from('share');
675
+
676
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
677
+
678
+        /**
679
+         * Reshares for this user are shares where they are the owner.
680
+         */
681
+        if ($reshares === false) {
682
+            //Special case for old shares created via the web UI
683
+            $or1 = $qb->expr()->andX(
684
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
685
+                $qb->expr()->isNull('uid_initiator')
686
+            );
687
+
688
+            $qb->andWhere(
689
+                $qb->expr()->orX(
690
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
691
+                    $or1
692
+                )
693
+            );
694
+        } else {
695
+            $qb->andWhere(
696
+                $qb->expr()->orX(
697
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
698
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
699
+                )
700
+            );
701
+        }
702
+
703
+        if ($node !== null) {
704
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
705
+        }
706
+
707
+        if ($limit !== -1) {
708
+            $qb->setMaxResults($limit);
709
+        }
710
+
711
+        $qb->setFirstResult($offset);
712
+        $qb->orderBy('id');
713
+
714
+        $cursor = $qb->execute();
715
+        $shares = [];
716
+        while ($data = $cursor->fetch()) {
717
+            $shares[] = $this->createShareObject($data);
718
+        }
719
+        $cursor->closeCursor();
720
+
721
+        return $shares;
722
+    }
723
+
724
+    /**
725
+     * @inheritdoc
726
+     */
727
+    public function getShareById($id, $recipientId = null) {
728
+        $qb = $this->dbConnection->getQueryBuilder();
729
+
730
+        $qb->select('*')
731
+            ->from('share')
732
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
733
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
734
+
735
+        $cursor = $qb->execute();
736
+        $data = $cursor->fetch();
737
+        $cursor->closeCursor();
738
+
739
+        if ($data === false) {
740
+            throw new ShareNotFound('Can not find share with ID: ' . $id);
741
+        }
742
+
743
+        try {
744
+            $share = $this->createShareObject($data);
745
+        } catch (InvalidShare $e) {
746
+            throw new ShareNotFound();
747
+        }
748
+
749
+        return $share;
750
+    }
751
+
752
+    /**
753
+     * Get shares for a given path
754
+     *
755
+     * @param \OCP\Files\Node $path
756
+     * @return IShare[]
757
+     */
758
+    public function getSharesByPath(Node $path) {
759
+        $qb = $this->dbConnection->getQueryBuilder();
760
+
761
+        // get federated user shares
762
+        $cursor = $qb->select('*')
763
+            ->from('share')
764
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
765
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
766
+            ->execute();
767
+
768
+        $shares = [];
769
+        while ($data = $cursor->fetch()) {
770
+            $shares[] = $this->createShareObject($data);
771
+        }
772
+        $cursor->closeCursor();
773
+
774
+        return $shares;
775
+    }
776
+
777
+    /**
778
+     * @inheritdoc
779
+     */
780
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
781
+        /** @var IShare[] $shares */
782
+        $shares = [];
783
+
784
+        //Get shares directly with this user
785
+        $qb = $this->dbConnection->getQueryBuilder();
786
+        $qb->select('*')
787
+            ->from('share');
788
+
789
+        // Order by id
790
+        $qb->orderBy('id');
791
+
792
+        // Set limit and offset
793
+        if ($limit !== -1) {
794
+            $qb->setMaxResults($limit);
795
+        }
796
+        $qb->setFirstResult($offset);
797
+
798
+        $qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
799
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
800
+
801
+        // Filter by node if provided
802
+        if ($node !== null) {
803
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
804
+        }
805
+
806
+        $cursor = $qb->execute();
807
+
808
+        while ($data = $cursor->fetch()) {
809
+            $shares[] = $this->createShareObject($data);
810
+        }
811
+        $cursor->closeCursor();
812
+
813
+
814
+        return $shares;
815
+    }
816
+
817
+    /**
818
+     * Get a share by token
819
+     *
820
+     * @param string $token
821
+     * @return IShare
822
+     * @throws ShareNotFound
823
+     */
824
+    public function getShareByToken($token) {
825
+        $qb = $this->dbConnection->getQueryBuilder();
826
+
827
+        $cursor = $qb->select('*')
828
+            ->from('share')
829
+            ->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
830
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
831
+            ->execute();
832
+
833
+        $data = $cursor->fetch();
834
+
835
+        if ($data === false) {
836
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
837
+        }
838
+
839
+        try {
840
+            $share = $this->createShareObject($data);
841
+        } catch (InvalidShare $e) {
842
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
843
+        }
844
+
845
+        return $share;
846
+    }
847
+
848
+    /**
849
+     * get database row of a give share
850
+     *
851
+     * @param $id
852
+     * @return array
853
+     * @throws ShareNotFound
854
+     */
855
+    private function getRawShare($id) {
856
+
857
+        // Now fetch the inserted share and create a complete share object
858
+        $qb = $this->dbConnection->getQueryBuilder();
859
+        $qb->select('*')
860
+            ->from('share')
861
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
862
+
863
+        $cursor = $qb->execute();
864
+        $data = $cursor->fetch();
865
+        $cursor->closeCursor();
866
+
867
+        if ($data === false) {
868
+            throw new ShareNotFound;
869
+        }
870
+
871
+        return $data;
872
+    }
873
+
874
+    /**
875
+     * Create a share object from an database row
876
+     *
877
+     * @param array $data
878
+     * @return IShare
879
+     * @throws InvalidShare
880
+     * @throws ShareNotFound
881
+     */
882
+    private function createShareObject($data) {
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(IShare::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(IShare::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.