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