Passed
Push — master ( 3749b7...a0444b )
by Julius
13:05 queued 12s
created
core/Command/Db/ConvertFilecacheBigInt.php 1 patch
Indentation   +86 added lines, -86 removed lines patch added patch discarded remove patch
@@ -40,90 +40,90 @@
 block discarded – undo
40 40
 
41 41
 class ConvertFilecacheBigInt extends Command {
42 42
 
43
-	/** @var IDBConnection */
44
-	private $connection;
45
-
46
-	/**
47
-	 * @param IDBConnection $connection
48
-	 */
49
-	public function __construct(IDBConnection $connection) {
50
-		$this->connection = $connection;
51
-		parent::__construct();
52
-	}
53
-
54
-	protected function configure() {
55
-		$this
56
-			->setName('db:convert-filecache-bigint')
57
-			->setDescription('Convert the ID columns of the filecache to BigInt');
58
-	}
59
-
60
-	protected function getColumnsByTable() {
61
-		// also update in CheckSetupController::hasBigIntConversionPendingColumns()
62
-		return [
63
-			'activity' => ['activity_id', 'object_id'],
64
-			'activity_mq' => ['mail_id'],
65
-			'authtoken' => ['id'],
66
-			'bruteforce_attempts' => ['id'],
67
-			'federated_reshares' => ['share_id'],
68
-			'filecache' => ['fileid', 'storage', 'parent', 'mimetype', 'mimepart', 'mtime', 'storage_mtime'],
69
-			'filecache_extended' => ['fileid'],
70
-			'file_locks' => ['id'],
71
-			'jobs' => ['id'],
72
-			'mimetypes' => ['id'],
73
-			'mounts' => ['id', 'storage_id', 'root_id', 'mount_id'],
74
-			'share_external' => ['id', 'parent'],
75
-			'storages' => ['numeric_id'],
76
-		];
77
-	}
78
-
79
-	protected function execute(InputInterface $input, OutputInterface $output): int {
80
-		$schema = new SchemaWrapper($this->connection);
81
-		$isSqlite = $this->connection->getDatabasePlatform() instanceof SqlitePlatform;
82
-		$updates = [];
83
-
84
-		$tables = $this->getColumnsByTable();
85
-		foreach ($tables as $tableName => $columns) {
86
-			if (!$schema->hasTable($tableName)) {
87
-				continue;
88
-			}
89
-
90
-			$table = $schema->getTable($tableName);
91
-
92
-			foreach ($columns as $columnName) {
93
-				$column = $table->getColumn($columnName);
94
-				$isAutoIncrement = $column->getAutoincrement();
95
-				$isAutoIncrementOnSqlite = $isSqlite && $isAutoIncrement;
96
-				if ($column->getType()->getName() !== Types::BIGINT && !$isAutoIncrementOnSqlite) {
97
-					$column->setType(Type::getType(Types::BIGINT));
98
-					$column->setOptions(['length' => 20]);
99
-
100
-					$updates[] = '* ' . $tableName . '.' . $columnName;
101
-				}
102
-			}
103
-		}
104
-
105
-		if (empty($updates)) {
106
-			$output->writeln('<info>All tables already up to date!</info>');
107
-			return 0;
108
-		}
109
-
110
-		$output->writeln('<comment>Following columns will be updated:</comment>');
111
-		$output->writeln('');
112
-		$output->writeln($updates);
113
-		$output->writeln('');
114
-		$output->writeln('<comment>This can take up to hours, depending on the number of files in your instance!</comment>');
115
-
116
-		if ($input->isInteractive()) {
117
-			$helper = $this->getHelper('question');
118
-			$question = new ConfirmationQuestion('Continue with the conversion (y/n)? [n] ', false);
119
-
120
-			if (!$helper->ask($input, $output, $question)) {
121
-				return 1;
122
-			}
123
-		}
124
-
125
-		$this->connection->migrateToSchema($schema->getWrappedSchema());
126
-
127
-		return 0;
128
-	}
43
+    /** @var IDBConnection */
44
+    private $connection;
45
+
46
+    /**
47
+     * @param IDBConnection $connection
48
+     */
49
+    public function __construct(IDBConnection $connection) {
50
+        $this->connection = $connection;
51
+        parent::__construct();
52
+    }
53
+
54
+    protected function configure() {
55
+        $this
56
+            ->setName('db:convert-filecache-bigint')
57
+            ->setDescription('Convert the ID columns of the filecache to BigInt');
58
+    }
59
+
60
+    protected function getColumnsByTable() {
61
+        // also update in CheckSetupController::hasBigIntConversionPendingColumns()
62
+        return [
63
+            'activity' => ['activity_id', 'object_id'],
64
+            'activity_mq' => ['mail_id'],
65
+            'authtoken' => ['id'],
66
+            'bruteforce_attempts' => ['id'],
67
+            'federated_reshares' => ['share_id'],
68
+            'filecache' => ['fileid', 'storage', 'parent', 'mimetype', 'mimepart', 'mtime', 'storage_mtime'],
69
+            'filecache_extended' => ['fileid'],
70
+            'file_locks' => ['id'],
71
+            'jobs' => ['id'],
72
+            'mimetypes' => ['id'],
73
+            'mounts' => ['id', 'storage_id', 'root_id', 'mount_id'],
74
+            'share_external' => ['id', 'parent'],
75
+            'storages' => ['numeric_id'],
76
+        ];
77
+    }
78
+
79
+    protected function execute(InputInterface $input, OutputInterface $output): int {
80
+        $schema = new SchemaWrapper($this->connection);
81
+        $isSqlite = $this->connection->getDatabasePlatform() instanceof SqlitePlatform;
82
+        $updates = [];
83
+
84
+        $tables = $this->getColumnsByTable();
85
+        foreach ($tables as $tableName => $columns) {
86
+            if (!$schema->hasTable($tableName)) {
87
+                continue;
88
+            }
89
+
90
+            $table = $schema->getTable($tableName);
91
+
92
+            foreach ($columns as $columnName) {
93
+                $column = $table->getColumn($columnName);
94
+                $isAutoIncrement = $column->getAutoincrement();
95
+                $isAutoIncrementOnSqlite = $isSqlite && $isAutoIncrement;
96
+                if ($column->getType()->getName() !== Types::BIGINT && !$isAutoIncrementOnSqlite) {
97
+                    $column->setType(Type::getType(Types::BIGINT));
98
+                    $column->setOptions(['length' => 20]);
99
+
100
+                    $updates[] = '* ' . $tableName . '.' . $columnName;
101
+                }
102
+            }
103
+        }
104
+
105
+        if (empty($updates)) {
106
+            $output->writeln('<info>All tables already up to date!</info>');
107
+            return 0;
108
+        }
109
+
110
+        $output->writeln('<comment>Following columns will be updated:</comment>');
111
+        $output->writeln('');
112
+        $output->writeln($updates);
113
+        $output->writeln('');
114
+        $output->writeln('<comment>This can take up to hours, depending on the number of files in your instance!</comment>');
115
+
116
+        if ($input->isInteractive()) {
117
+            $helper = $this->getHelper('question');
118
+            $question = new ConfirmationQuestion('Continue with the conversion (y/n)? [n] ', false);
119
+
120
+            if (!$helper->ask($input, $output, $question)) {
121
+                return 1;
122
+            }
123
+        }
124
+
125
+        $this->connection->migrateToSchema($schema->getWrappedSchema());
126
+
127
+        return 0;
128
+    }
129 129
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/FederatedShareProvider.php 1 patch
Indentation   +1061 added lines, -1061 removed lines patch added patch discarded remove patch
@@ -60,1075 +60,1075 @@
 block discarded – undo
60 60
  * @package OCA\FederatedFileSharing
61 61
  */
62 62
 class FederatedShareProvider implements IShareProvider {
63
-	public const SHARE_TYPE_REMOTE = 6;
64
-
65
-	/** @var IDBConnection */
66
-	private $dbConnection;
67
-
68
-	/** @var AddressHandler */
69
-	private $addressHandler;
70
-
71
-	/** @var Notifications */
72
-	private $notifications;
73
-
74
-	/** @var TokenHandler */
75
-	private $tokenHandler;
76
-
77
-	/** @var IL10N */
78
-	private $l;
79
-
80
-	/** @var ILogger */
81
-	private $logger;
82
-
83
-	/** @var IRootFolder */
84
-	private $rootFolder;
85
-
86
-	/** @var IConfig */
87
-	private $config;
88
-
89
-	/** @var string */
90
-	private $externalShareTable = 'share_external';
91
-
92
-	/** @var IUserManager */
93
-	private $userManager;
94
-
95
-	/** @var ICloudIdManager */
96
-	private $cloudIdManager;
97
-
98
-	/** @var \OCP\GlobalScale\IConfig */
99
-	private $gsConfig;
100
-
101
-	/** @var ICloudFederationProviderManager */
102
-	private $cloudFederationProviderManager;
103
-
104
-	/** @var array list of supported share types */
105
-	private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
106
-
107
-	/**
108
-	 * DefaultShareProvider constructor.
109
-	 *
110
-	 * @param IDBConnection $connection
111
-	 * @param AddressHandler $addressHandler
112
-	 * @param Notifications $notifications
113
-	 * @param TokenHandler $tokenHandler
114
-	 * @param IL10N $l10n
115
-	 * @param ILogger $logger
116
-	 * @param IRootFolder $rootFolder
117
-	 * @param IConfig $config
118
-	 * @param IUserManager $userManager
119
-	 * @param ICloudIdManager $cloudIdManager
120
-	 * @param \OCP\GlobalScale\IConfig $globalScaleConfig
121
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
122
-	 */
123
-	public function __construct(
124
-			IDBConnection $connection,
125
-			AddressHandler $addressHandler,
126
-			Notifications $notifications,
127
-			TokenHandler $tokenHandler,
128
-			IL10N $l10n,
129
-			ILogger $logger,
130
-			IRootFolder $rootFolder,
131
-			IConfig $config,
132
-			IUserManager $userManager,
133
-			ICloudIdManager $cloudIdManager,
134
-			\OCP\GlobalScale\IConfig $globalScaleConfig,
135
-			ICloudFederationProviderManager $cloudFederationProviderManager
136
-	) {
137
-		$this->dbConnection = $connection;
138
-		$this->addressHandler = $addressHandler;
139
-		$this->notifications = $notifications;
140
-		$this->tokenHandler = $tokenHandler;
141
-		$this->l = $l10n;
142
-		$this->logger = $logger;
143
-		$this->rootFolder = $rootFolder;
144
-		$this->config = $config;
145
-		$this->userManager = $userManager;
146
-		$this->cloudIdManager = $cloudIdManager;
147
-		$this->gsConfig = $globalScaleConfig;
148
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
149
-	}
150
-
151
-	/**
152
-	 * Return the identifier of this provider.
153
-	 *
154
-	 * @return string Containing only [a-zA-Z0-9]
155
-	 */
156
-	public function identifier() {
157
-		return 'ocFederatedSharing';
158
-	}
159
-
160
-	/**
161
-	 * Share a path
162
-	 *
163
-	 * @param IShare $share
164
-	 * @return IShare The share object
165
-	 * @throws ShareNotFound
166
-	 * @throws \Exception
167
-	 */
168
-	public function create(IShare $share) {
169
-		$shareWith = $share->getSharedWith();
170
-		$itemSource = $share->getNodeId();
171
-		$itemType = $share->getNodeType();
172
-		$permissions = $share->getPermissions();
173
-		$sharedBy = $share->getSharedBy();
174
-		$shareType = $share->getShareType();
175
-
176
-		if ($shareType === IShare::TYPE_REMOTE_GROUP &&
177
-			!$this->isOutgoingServer2serverGroupShareEnabled()
178
-		) {
179
-			$message = 'It is not allowed to send federated group shares from this server.';
180
-			$message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
181
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
182
-			throw new \Exception($message_t);
183
-		}
184
-
185
-		/*
63
+    public const SHARE_TYPE_REMOTE = 6;
64
+
65
+    /** @var IDBConnection */
66
+    private $dbConnection;
67
+
68
+    /** @var AddressHandler */
69
+    private $addressHandler;
70
+
71
+    /** @var Notifications */
72
+    private $notifications;
73
+
74
+    /** @var TokenHandler */
75
+    private $tokenHandler;
76
+
77
+    /** @var IL10N */
78
+    private $l;
79
+
80
+    /** @var ILogger */
81
+    private $logger;
82
+
83
+    /** @var IRootFolder */
84
+    private $rootFolder;
85
+
86
+    /** @var IConfig */
87
+    private $config;
88
+
89
+    /** @var string */
90
+    private $externalShareTable = 'share_external';
91
+
92
+    /** @var IUserManager */
93
+    private $userManager;
94
+
95
+    /** @var ICloudIdManager */
96
+    private $cloudIdManager;
97
+
98
+    /** @var \OCP\GlobalScale\IConfig */
99
+    private $gsConfig;
100
+
101
+    /** @var ICloudFederationProviderManager */
102
+    private $cloudFederationProviderManager;
103
+
104
+    /** @var array list of supported share types */
105
+    private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
106
+
107
+    /**
108
+     * DefaultShareProvider constructor.
109
+     *
110
+     * @param IDBConnection $connection
111
+     * @param AddressHandler $addressHandler
112
+     * @param Notifications $notifications
113
+     * @param TokenHandler $tokenHandler
114
+     * @param IL10N $l10n
115
+     * @param ILogger $logger
116
+     * @param IRootFolder $rootFolder
117
+     * @param IConfig $config
118
+     * @param IUserManager $userManager
119
+     * @param ICloudIdManager $cloudIdManager
120
+     * @param \OCP\GlobalScale\IConfig $globalScaleConfig
121
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
122
+     */
123
+    public function __construct(
124
+            IDBConnection $connection,
125
+            AddressHandler $addressHandler,
126
+            Notifications $notifications,
127
+            TokenHandler $tokenHandler,
128
+            IL10N $l10n,
129
+            ILogger $logger,
130
+            IRootFolder $rootFolder,
131
+            IConfig $config,
132
+            IUserManager $userManager,
133
+            ICloudIdManager $cloudIdManager,
134
+            \OCP\GlobalScale\IConfig $globalScaleConfig,
135
+            ICloudFederationProviderManager $cloudFederationProviderManager
136
+    ) {
137
+        $this->dbConnection = $connection;
138
+        $this->addressHandler = $addressHandler;
139
+        $this->notifications = $notifications;
140
+        $this->tokenHandler = $tokenHandler;
141
+        $this->l = $l10n;
142
+        $this->logger = $logger;
143
+        $this->rootFolder = $rootFolder;
144
+        $this->config = $config;
145
+        $this->userManager = $userManager;
146
+        $this->cloudIdManager = $cloudIdManager;
147
+        $this->gsConfig = $globalScaleConfig;
148
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
149
+    }
150
+
151
+    /**
152
+     * Return the identifier of this provider.
153
+     *
154
+     * @return string Containing only [a-zA-Z0-9]
155
+     */
156
+    public function identifier() {
157
+        return 'ocFederatedSharing';
158
+    }
159
+
160
+    /**
161
+     * Share a path
162
+     *
163
+     * @param IShare $share
164
+     * @return IShare The share object
165
+     * @throws ShareNotFound
166
+     * @throws \Exception
167
+     */
168
+    public function create(IShare $share) {
169
+        $shareWith = $share->getSharedWith();
170
+        $itemSource = $share->getNodeId();
171
+        $itemType = $share->getNodeType();
172
+        $permissions = $share->getPermissions();
173
+        $sharedBy = $share->getSharedBy();
174
+        $shareType = $share->getShareType();
175
+
176
+        if ($shareType === IShare::TYPE_REMOTE_GROUP &&
177
+            !$this->isOutgoingServer2serverGroupShareEnabled()
178
+        ) {
179
+            $message = 'It is not allowed to send federated group shares from this server.';
180
+            $message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
181
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
182
+            throw new \Exception($message_t);
183
+        }
184
+
185
+        /*
186 186
 		 * Check if file is not already shared with the remote user
187 187
 		 */
188
-		$alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE, $share->getNode(), 1, 0);
189
-		$alreadySharedGroup = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
190
-		if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
191
-			$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
192
-			$message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
193
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
194
-			throw new \Exception($message_t);
195
-		}
196
-
197
-
198
-		// don't allow federated shares if source and target server are the same
199
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
200
-		$currentServer = $this->addressHandler->generateRemoteURL();
201
-		$currentUser = $sharedBy;
202
-		if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
203
-			$message = 'Not allowed to create a federated share with the same user.';
204
-			$message_t = $this->l->t('Not allowed to create a federated share with the same user');
205
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
206
-			throw new \Exception($message_t);
207
-		}
208
-
209
-
210
-		$share->setSharedWith($cloudId->getId());
211
-
212
-		try {
213
-			$remoteShare = $this->getShareFromExternalShareTable($share);
214
-		} catch (ShareNotFound $e) {
215
-			$remoteShare = null;
216
-		}
217
-
218
-		if ($remoteShare) {
219
-			try {
220
-				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
221
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
222
-				$share->setId($shareId);
223
-				list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
224
-				// remote share was create successfully if we get a valid token as return
225
-				$send = is_string($token) && $token !== '';
226
-			} catch (\Exception $e) {
227
-				// fall back to old re-share behavior if the remote server
228
-				// doesn't support flat re-shares (was introduced with Nextcloud 9.1)
229
-				$this->removeShareFromTable($share);
230
-				$shareId = $this->createFederatedShare($share);
231
-			}
232
-			if ($send) {
233
-				$this->updateSuccessfulReshare($shareId, $token);
234
-				$this->storeRemoteId($shareId, $remoteId);
235
-			} else {
236
-				$this->removeShareFromTable($share);
237
-				$message_t = $this->l->t('File is already shared with %s', [$shareWith]);
238
-				throw new \Exception($message_t);
239
-			}
240
-		} else {
241
-			$shareId = $this->createFederatedShare($share);
242
-		}
243
-
244
-		$data = $this->getRawShare($shareId);
245
-		return $this->createShareObject($data);
246
-	}
247
-
248
-	/**
249
-	 * create federated share and inform the recipient
250
-	 *
251
-	 * @param IShare $share
252
-	 * @return int
253
-	 * @throws ShareNotFound
254
-	 * @throws \Exception
255
-	 */
256
-	protected function createFederatedShare(IShare $share) {
257
-		$token = $this->tokenHandler->generateToken();
258
-		$shareId = $this->addShareToDB(
259
-			$share->getNodeId(),
260
-			$share->getNodeType(),
261
-			$share->getSharedWith(),
262
-			$share->getSharedBy(),
263
-			$share->getShareOwner(),
264
-			$share->getPermissions(),
265
-			$token,
266
-			$share->getShareType()
267
-		);
268
-
269
-		$failure = false;
270
-
271
-		try {
272
-			$sharedByFederatedId = $share->getSharedBy();
273
-			if ($this->userManager->userExists($sharedByFederatedId)) {
274
-				$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
275
-				$sharedByFederatedId = $cloudId->getId();
276
-			}
277
-			$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
278
-			$send = $this->notifications->sendRemoteShare(
279
-				$token,
280
-				$share->getSharedWith(),
281
-				$share->getNode()->getName(),
282
-				$shareId,
283
-				$share->getShareOwner(),
284
-				$ownerCloudId->getId(),
285
-				$share->getSharedBy(),
286
-				$sharedByFederatedId,
287
-				$share->getShareType()
288
-			);
289
-
290
-			if ($send === false) {
291
-				$failure = true;
292
-			}
293
-		} catch (\Exception $e) {
294
-			$this->logger->logException($e, [
295
-				'message' => 'Failed to notify remote server of federated share, removing share.',
296
-				'level' => ILogger::ERROR,
297
-				'app' => 'federatedfilesharing',
298
-			]);
299
-			$failure = true;
300
-		}
301
-
302
-		if ($failure) {
303
-			$this->removeShareFromTableById($shareId);
304
-			$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.',
305
-				[$share->getNode()->getName(), $share->getSharedWith()]);
306
-			throw new \Exception($message_t);
307
-		}
308
-
309
-		return $shareId;
310
-	}
311
-
312
-	/**
313
-	 * @param string $shareWith
314
-	 * @param IShare $share
315
-	 * @param string $shareId internal share Id
316
-	 * @return array
317
-	 * @throws \Exception
318
-	 */
319
-	protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
320
-		$remoteShare = $this->getShareFromExternalShareTable($share);
321
-		$token = $remoteShare['share_token'];
322
-		$remoteId = $remoteShare['remote_id'];
323
-		$remote = $remoteShare['remote'];
324
-
325
-		list($token, $remoteId) = $this->notifications->requestReShare(
326
-			$token,
327
-			$remoteId,
328
-			$shareId,
329
-			$remote,
330
-			$shareWith,
331
-			$share->getPermissions(),
332
-			$share->getNode()->getName()
333
-		);
334
-
335
-		return [$token, $remoteId];
336
-	}
337
-
338
-	/**
339
-	 * get federated share from the share_external table but exclude mounted link shares
340
-	 *
341
-	 * @param IShare $share
342
-	 * @return array
343
-	 * @throws ShareNotFound
344
-	 */
345
-	protected function getShareFromExternalShareTable(IShare $share) {
346
-		$query = $this->dbConnection->getQueryBuilder();
347
-		$query->select('*')->from($this->externalShareTable)
348
-			->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
349
-			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
350
-		$qResult = $query->execute();
351
-		$result = $qResult->fetchAll();
352
-		$qResult->closeCursor();
353
-
354
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
355
-			return $result[0];
356
-		}
357
-
358
-		throw new ShareNotFound('share not found in share_external table');
359
-	}
360
-
361
-	/**
362
-	 * add share to the database and return the ID
363
-	 *
364
-	 * @param int $itemSource
365
-	 * @param string $itemType
366
-	 * @param string $shareWith
367
-	 * @param string $sharedBy
368
-	 * @param string $uidOwner
369
-	 * @param int $permissions
370
-	 * @param string $token
371
-	 * @param int $shareType
372
-	 * @return int
373
-	 */
374
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
375
-		$qb = $this->dbConnection->getQueryBuilder();
376
-		$qb->insert('share')
377
-			->setValue('share_type', $qb->createNamedParameter($shareType))
378
-			->setValue('item_type', $qb->createNamedParameter($itemType))
379
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
380
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
381
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
382
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
383
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
384
-			->setValue('permissions', $qb->createNamedParameter($permissions))
385
-			->setValue('token', $qb->createNamedParameter($token))
386
-			->setValue('stime', $qb->createNamedParameter(time()));
387
-
388
-		/*
188
+        $alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE, $share->getNode(), 1, 0);
189
+        $alreadySharedGroup = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
190
+        if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
191
+            $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
192
+            $message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
193
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
194
+            throw new \Exception($message_t);
195
+        }
196
+
197
+
198
+        // don't allow federated shares if source and target server are the same
199
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
200
+        $currentServer = $this->addressHandler->generateRemoteURL();
201
+        $currentUser = $sharedBy;
202
+        if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
203
+            $message = 'Not allowed to create a federated share with the same user.';
204
+            $message_t = $this->l->t('Not allowed to create a federated share with the same user');
205
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
206
+            throw new \Exception($message_t);
207
+        }
208
+
209
+
210
+        $share->setSharedWith($cloudId->getId());
211
+
212
+        try {
213
+            $remoteShare = $this->getShareFromExternalShareTable($share);
214
+        } catch (ShareNotFound $e) {
215
+            $remoteShare = null;
216
+        }
217
+
218
+        if ($remoteShare) {
219
+            try {
220
+                $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
221
+                $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
222
+                $share->setId($shareId);
223
+                list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
224
+                // remote share was create successfully if we get a valid token as return
225
+                $send = is_string($token) && $token !== '';
226
+            } catch (\Exception $e) {
227
+                // fall back to old re-share behavior if the remote server
228
+                // doesn't support flat re-shares (was introduced with Nextcloud 9.1)
229
+                $this->removeShareFromTable($share);
230
+                $shareId = $this->createFederatedShare($share);
231
+            }
232
+            if ($send) {
233
+                $this->updateSuccessfulReshare($shareId, $token);
234
+                $this->storeRemoteId($shareId, $remoteId);
235
+            } else {
236
+                $this->removeShareFromTable($share);
237
+                $message_t = $this->l->t('File is already shared with %s', [$shareWith]);
238
+                throw new \Exception($message_t);
239
+            }
240
+        } else {
241
+            $shareId = $this->createFederatedShare($share);
242
+        }
243
+
244
+        $data = $this->getRawShare($shareId);
245
+        return $this->createShareObject($data);
246
+    }
247
+
248
+    /**
249
+     * create federated share and inform the recipient
250
+     *
251
+     * @param IShare $share
252
+     * @return int
253
+     * @throws ShareNotFound
254
+     * @throws \Exception
255
+     */
256
+    protected function createFederatedShare(IShare $share) {
257
+        $token = $this->tokenHandler->generateToken();
258
+        $shareId = $this->addShareToDB(
259
+            $share->getNodeId(),
260
+            $share->getNodeType(),
261
+            $share->getSharedWith(),
262
+            $share->getSharedBy(),
263
+            $share->getShareOwner(),
264
+            $share->getPermissions(),
265
+            $token,
266
+            $share->getShareType()
267
+        );
268
+
269
+        $failure = false;
270
+
271
+        try {
272
+            $sharedByFederatedId = $share->getSharedBy();
273
+            if ($this->userManager->userExists($sharedByFederatedId)) {
274
+                $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
275
+                $sharedByFederatedId = $cloudId->getId();
276
+            }
277
+            $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
278
+            $send = $this->notifications->sendRemoteShare(
279
+                $token,
280
+                $share->getSharedWith(),
281
+                $share->getNode()->getName(),
282
+                $shareId,
283
+                $share->getShareOwner(),
284
+                $ownerCloudId->getId(),
285
+                $share->getSharedBy(),
286
+                $sharedByFederatedId,
287
+                $share->getShareType()
288
+            );
289
+
290
+            if ($send === false) {
291
+                $failure = true;
292
+            }
293
+        } catch (\Exception $e) {
294
+            $this->logger->logException($e, [
295
+                'message' => 'Failed to notify remote server of federated share, removing share.',
296
+                'level' => ILogger::ERROR,
297
+                'app' => 'federatedfilesharing',
298
+            ]);
299
+            $failure = true;
300
+        }
301
+
302
+        if ($failure) {
303
+            $this->removeShareFromTableById($shareId);
304
+            $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.',
305
+                [$share->getNode()->getName(), $share->getSharedWith()]);
306
+            throw new \Exception($message_t);
307
+        }
308
+
309
+        return $shareId;
310
+    }
311
+
312
+    /**
313
+     * @param string $shareWith
314
+     * @param IShare $share
315
+     * @param string $shareId internal share Id
316
+     * @return array
317
+     * @throws \Exception
318
+     */
319
+    protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
320
+        $remoteShare = $this->getShareFromExternalShareTable($share);
321
+        $token = $remoteShare['share_token'];
322
+        $remoteId = $remoteShare['remote_id'];
323
+        $remote = $remoteShare['remote'];
324
+
325
+        list($token, $remoteId) = $this->notifications->requestReShare(
326
+            $token,
327
+            $remoteId,
328
+            $shareId,
329
+            $remote,
330
+            $shareWith,
331
+            $share->getPermissions(),
332
+            $share->getNode()->getName()
333
+        );
334
+
335
+        return [$token, $remoteId];
336
+    }
337
+
338
+    /**
339
+     * get federated share from the share_external table but exclude mounted link shares
340
+     *
341
+     * @param IShare $share
342
+     * @return array
343
+     * @throws ShareNotFound
344
+     */
345
+    protected function getShareFromExternalShareTable(IShare $share) {
346
+        $query = $this->dbConnection->getQueryBuilder();
347
+        $query->select('*')->from($this->externalShareTable)
348
+            ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
349
+            ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
350
+        $qResult = $query->execute();
351
+        $result = $qResult->fetchAll();
352
+        $qResult->closeCursor();
353
+
354
+        if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
355
+            return $result[0];
356
+        }
357
+
358
+        throw new ShareNotFound('share not found in share_external table');
359
+    }
360
+
361
+    /**
362
+     * add share to the database and return the ID
363
+     *
364
+     * @param int $itemSource
365
+     * @param string $itemType
366
+     * @param string $shareWith
367
+     * @param string $sharedBy
368
+     * @param string $uidOwner
369
+     * @param int $permissions
370
+     * @param string $token
371
+     * @param int $shareType
372
+     * @return int
373
+     */
374
+    private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
375
+        $qb = $this->dbConnection->getQueryBuilder();
376
+        $qb->insert('share')
377
+            ->setValue('share_type', $qb->createNamedParameter($shareType))
378
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
379
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
380
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
381
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
382
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
383
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
384
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
385
+            ->setValue('token', $qb->createNamedParameter($token))
386
+            ->setValue('stime', $qb->createNamedParameter(time()));
387
+
388
+        /*
389 389
 		 * Added to fix https://github.com/owncloud/core/issues/22215
390 390
 		 * Can be removed once we get rid of ajax/share.php
391 391
 		 */
392
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
393
-
394
-		$qb->execute();
395
-		$id = $qb->getLastInsertId();
396
-
397
-		return (int)$id;
398
-	}
399
-
400
-	/**
401
-	 * Update a share
402
-	 *
403
-	 * @param IShare $share
404
-	 * @return IShare The share object
405
-	 */
406
-	public function update(IShare $share) {
407
-		/*
392
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
393
+
394
+        $qb->execute();
395
+        $id = $qb->getLastInsertId();
396
+
397
+        return (int)$id;
398
+    }
399
+
400
+    /**
401
+     * Update a share
402
+     *
403
+     * @param IShare $share
404
+     * @return IShare The share object
405
+     */
406
+    public function update(IShare $share) {
407
+        /*
408 408
 		 * We allow updating the permissions of federated shares
409 409
 		 */
410
-		$qb = $this->dbConnection->getQueryBuilder();
411
-		$qb->update('share')
412
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
413
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
414
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
415
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
416
-				->execute();
417
-
418
-		// send the updated permission to the owner/initiator, if they are not the same
419
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
420
-			$this->sendPermissionUpdate($share);
421
-		}
422
-
423
-		return $share;
424
-	}
425
-
426
-	/**
427
-	 * send the updated permission to the owner/initiator, if they are not the same
428
-	 *
429
-	 * @param IShare $share
430
-	 * @throws ShareNotFound
431
-	 * @throws \OC\HintException
432
-	 */
433
-	protected function sendPermissionUpdate(IShare $share) {
434
-		$remoteId = $this->getRemoteId($share);
435
-		// if the local user is the owner we send the permission change to the initiator
436
-		if ($this->userManager->userExists($share->getShareOwner())) {
437
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
438
-		} else { // ... if not we send the permission change to the owner
439
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
440
-		}
441
-		$this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
442
-	}
443
-
444
-
445
-	/**
446
-	 * update successful reShare with the correct token
447
-	 *
448
-	 * @param int $shareId
449
-	 * @param string $token
450
-	 */
451
-	protected function updateSuccessfulReShare($shareId, $token) {
452
-		$query = $this->dbConnection->getQueryBuilder();
453
-		$query->update('share')
454
-			->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
455
-			->set('token', $query->createNamedParameter($token))
456
-			->execute();
457
-	}
458
-
459
-	/**
460
-	 * store remote ID in federated reShare table
461
-	 *
462
-	 * @param $shareId
463
-	 * @param $remoteId
464
-	 */
465
-	public function storeRemoteId(int $shareId, string $remoteId): void {
466
-		$query = $this->dbConnection->getQueryBuilder();
467
-		$query->insert('federated_reshares')
468
-			->values(
469
-				[
470
-					'share_id' => $query->createNamedParameter($shareId),
471
-					'remote_id' => $query->createNamedParameter($remoteId),
472
-				]
473
-			);
474
-		$query->execute();
475
-	}
476
-
477
-	/**
478
-	 * get share ID on remote server for federated re-shares
479
-	 *
480
-	 * @param IShare $share
481
-	 * @return string
482
-	 * @throws ShareNotFound
483
-	 */
484
-	public function getRemoteId(IShare $share): string {
485
-		$query = $this->dbConnection->getQueryBuilder();
486
-		$query->select('remote_id')->from('federated_reshares')
487
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
488
-		$result = $query->execute();
489
-		$data = $result->fetch();
490
-		$result->closeCursor();
491
-
492
-		if (!is_array($data) || !isset($data['remote_id'])) {
493
-			throw new ShareNotFound();
494
-		}
495
-
496
-		return (string)$data['remote_id'];
497
-	}
498
-
499
-	/**
500
-	 * @inheritdoc
501
-	 */
502
-	public function move(IShare $share, $recipient) {
503
-		/*
410
+        $qb = $this->dbConnection->getQueryBuilder();
411
+        $qb->update('share')
412
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
413
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
414
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
415
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
416
+                ->execute();
417
+
418
+        // send the updated permission to the owner/initiator, if they are not the same
419
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
420
+            $this->sendPermissionUpdate($share);
421
+        }
422
+
423
+        return $share;
424
+    }
425
+
426
+    /**
427
+     * send the updated permission to the owner/initiator, if they are not the same
428
+     *
429
+     * @param IShare $share
430
+     * @throws ShareNotFound
431
+     * @throws \OC\HintException
432
+     */
433
+    protected function sendPermissionUpdate(IShare $share) {
434
+        $remoteId = $this->getRemoteId($share);
435
+        // if the local user is the owner we send the permission change to the initiator
436
+        if ($this->userManager->userExists($share->getShareOwner())) {
437
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
438
+        } else { // ... if not we send the permission change to the owner
439
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
440
+        }
441
+        $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
442
+    }
443
+
444
+
445
+    /**
446
+     * update successful reShare with the correct token
447
+     *
448
+     * @param int $shareId
449
+     * @param string $token
450
+     */
451
+    protected function updateSuccessfulReShare($shareId, $token) {
452
+        $query = $this->dbConnection->getQueryBuilder();
453
+        $query->update('share')
454
+            ->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
455
+            ->set('token', $query->createNamedParameter($token))
456
+            ->execute();
457
+    }
458
+
459
+    /**
460
+     * store remote ID in federated reShare table
461
+     *
462
+     * @param $shareId
463
+     * @param $remoteId
464
+     */
465
+    public function storeRemoteId(int $shareId, string $remoteId): void {
466
+        $query = $this->dbConnection->getQueryBuilder();
467
+        $query->insert('federated_reshares')
468
+            ->values(
469
+                [
470
+                    'share_id' => $query->createNamedParameter($shareId),
471
+                    'remote_id' => $query->createNamedParameter($remoteId),
472
+                ]
473
+            );
474
+        $query->execute();
475
+    }
476
+
477
+    /**
478
+     * get share ID on remote server for federated re-shares
479
+     *
480
+     * @param IShare $share
481
+     * @return string
482
+     * @throws ShareNotFound
483
+     */
484
+    public function getRemoteId(IShare $share): string {
485
+        $query = $this->dbConnection->getQueryBuilder();
486
+        $query->select('remote_id')->from('federated_reshares')
487
+            ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
488
+        $result = $query->execute();
489
+        $data = $result->fetch();
490
+        $result->closeCursor();
491
+
492
+        if (!is_array($data) || !isset($data['remote_id'])) {
493
+            throw new ShareNotFound();
494
+        }
495
+
496
+        return (string)$data['remote_id'];
497
+    }
498
+
499
+    /**
500
+     * @inheritdoc
501
+     */
502
+    public function move(IShare $share, $recipient) {
503
+        /*
504 504
 		 * This function does nothing yet as it is just for outgoing
505 505
 		 * federated shares.
506 506
 		 */
507
-		return $share;
508
-	}
509
-
510
-	/**
511
-	 * Get all children of this share
512
-	 *
513
-	 * @param IShare $parent
514
-	 * @return IShare[]
515
-	 */
516
-	public function getChildren(IShare $parent) {
517
-		$children = [];
518
-
519
-		$qb = $this->dbConnection->getQueryBuilder();
520
-		$qb->select('*')
521
-			->from('share')
522
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
523
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
524
-			->orderBy('id');
525
-
526
-		$cursor = $qb->execute();
527
-		while ($data = $cursor->fetch()) {
528
-			$children[] = $this->createShareObject($data);
529
-		}
530
-		$cursor->closeCursor();
531
-
532
-		return $children;
533
-	}
534
-
535
-	/**
536
-	 * Delete a share (owner unShares the file)
537
-	 *
538
-	 * @param IShare $share
539
-	 * @throws ShareNotFound
540
-	 * @throws \OC\HintException
541
-	 */
542
-	public function delete(IShare $share) {
543
-		list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
544
-
545
-		// if the local user is the owner we can send the unShare request directly...
546
-		if ($this->userManager->userExists($share->getShareOwner())) {
547
-			$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
548
-			$this->revokeShare($share, true);
549
-		} else { // ... if not we need to correct ID for the unShare request
550
-			$remoteId = $this->getRemoteId($share);
551
-			$this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
552
-			$this->revokeShare($share, false);
553
-		}
554
-
555
-		// only remove the share when all messages are send to not lose information
556
-		// about the share to early
557
-		$this->removeShareFromTable($share);
558
-	}
559
-
560
-	/**
561
-	 * in case of a re-share we need to send the other use (initiator or owner)
562
-	 * a message that the file was unshared
563
-	 *
564
-	 * @param IShare $share
565
-	 * @param bool $isOwner the user can either be the owner or the user who re-sahred it
566
-	 * @throws ShareNotFound
567
-	 * @throws \OC\HintException
568
-	 */
569
-	protected function revokeShare($share, $isOwner) {
570
-		if ($this->userManager->userExists($share->getShareOwner()) && $this->userManager->userExists($share->getSharedBy())) {
571
-			// If both the owner and the initiator of the share are local users we don't have to notify anybody else
572
-			return;
573
-		}
574
-
575
-		// also send a unShare request to the initiator, if this is a different user than the owner
576
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
577
-			if ($isOwner) {
578
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
579
-			} else {
580
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
581
-			}
582
-			$remoteId = $this->getRemoteId($share);
583
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
584
-		}
585
-	}
586
-
587
-	/**
588
-	 * remove share from table
589
-	 *
590
-	 * @param IShare $share
591
-	 */
592
-	public function removeShareFromTable(IShare $share) {
593
-		$this->removeShareFromTableById($share->getId());
594
-	}
595
-
596
-	/**
597
-	 * remove share from table
598
-	 *
599
-	 * @param string $shareId
600
-	 */
601
-	private function removeShareFromTableById($shareId) {
602
-		$qb = $this->dbConnection->getQueryBuilder();
603
-		$qb->delete('share')
604
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
605
-			->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
606
-		$qb->execute();
607
-
608
-		$qb->delete('federated_reshares')
609
-			->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
610
-		$qb->execute();
611
-	}
612
-
613
-	/**
614
-	 * @inheritdoc
615
-	 */
616
-	public function deleteFromSelf(IShare $share, $recipient) {
617
-		// nothing to do here. Technically deleteFromSelf in the context of federated
618
-		// shares is a umount of an external storage. This is handled here
619
-		// apps/files_sharing/lib/external/manager.php
620
-		// TODO move this code over to this app
621
-	}
622
-
623
-	public function restore(IShare $share, string $recipient): IShare {
624
-		throw new GenericShareException('not implemented');
625
-	}
626
-
627
-
628
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
629
-		$qb = $this->dbConnection->getQueryBuilder();
630
-		$qb->select('*')
631
-			->from('share', 's')
632
-			->andWhere($qb->expr()->orX(
633
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
634
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
635
-			))
636
-			->andWhere(
637
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
638
-			);
639
-
640
-		/**
641
-		 * Reshares for this user are shares where they are the owner.
642
-		 */
643
-		if ($reshares === false) {
644
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
645
-		} else {
646
-			$qb->andWhere(
647
-				$qb->expr()->orX(
648
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
649
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
650
-				)
651
-			);
652
-		}
653
-
654
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
655
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
656
-
657
-		$qb->orderBy('id');
658
-
659
-		$cursor = $qb->execute();
660
-		$shares = [];
661
-		while ($data = $cursor->fetch()) {
662
-			$shares[$data['fileid']][] = $this->createShareObject($data);
663
-		}
664
-		$cursor->closeCursor();
665
-
666
-		return $shares;
667
-	}
668
-
669
-	/**
670
-	 * @inheritdoc
671
-	 */
672
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
673
-		$qb = $this->dbConnection->getQueryBuilder();
674
-		$qb->select('*')
675
-			->from('share');
676
-
677
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
678
-
679
-		/**
680
-		 * Reshares for this user are shares where they are the owner.
681
-		 */
682
-		if ($reshares === false) {
683
-			//Special case for old shares created via the web UI
684
-			$or1 = $qb->expr()->andX(
685
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
686
-				$qb->expr()->isNull('uid_initiator')
687
-			);
688
-
689
-			$qb->andWhere(
690
-				$qb->expr()->orX(
691
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
692
-					$or1
693
-				)
694
-			);
695
-		} else {
696
-			$qb->andWhere(
697
-				$qb->expr()->orX(
698
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
699
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
700
-				)
701
-			);
702
-		}
703
-
704
-		if ($node !== null) {
705
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
706
-		}
707
-
708
-		if ($limit !== -1) {
709
-			$qb->setMaxResults($limit);
710
-		}
711
-
712
-		$qb->setFirstResult($offset);
713
-		$qb->orderBy('id');
714
-
715
-		$cursor = $qb->execute();
716
-		$shares = [];
717
-		while ($data = $cursor->fetch()) {
718
-			$shares[] = $this->createShareObject($data);
719
-		}
720
-		$cursor->closeCursor();
721
-
722
-		return $shares;
723
-	}
724
-
725
-	/**
726
-	 * @inheritdoc
727
-	 */
728
-	public function getShareById($id, $recipientId = null) {
729
-		$qb = $this->dbConnection->getQueryBuilder();
730
-
731
-		$qb->select('*')
732
-			->from('share')
733
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
734
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
735
-
736
-		$cursor = $qb->execute();
737
-		$data = $cursor->fetch();
738
-		$cursor->closeCursor();
739
-
740
-		if ($data === false) {
741
-			throw new ShareNotFound('Can not find share with ID: ' . $id);
742
-		}
743
-
744
-		try {
745
-			$share = $this->createShareObject($data);
746
-		} catch (InvalidShare $e) {
747
-			throw new ShareNotFound();
748
-		}
749
-
750
-		return $share;
751
-	}
752
-
753
-	/**
754
-	 * Get shares for a given path
755
-	 *
756
-	 * @param \OCP\Files\Node $path
757
-	 * @return IShare[]
758
-	 */
759
-	public function getSharesByPath(Node $path) {
760
-		$qb = $this->dbConnection->getQueryBuilder();
761
-
762
-		// get federated user shares
763
-		$cursor = $qb->select('*')
764
-			->from('share')
765
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
766
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
767
-			->execute();
768
-
769
-		$shares = [];
770
-		while ($data = $cursor->fetch()) {
771
-			$shares[] = $this->createShareObject($data);
772
-		}
773
-		$cursor->closeCursor();
774
-
775
-		return $shares;
776
-	}
777
-
778
-	/**
779
-	 * @inheritdoc
780
-	 */
781
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
782
-		/** @var IShare[] $shares */
783
-		$shares = [];
784
-
785
-		//Get shares directly with this user
786
-		$qb = $this->dbConnection->getQueryBuilder();
787
-		$qb->select('*')
788
-			->from('share');
789
-
790
-		// Order by id
791
-		$qb->orderBy('id');
792
-
793
-		// Set limit and offset
794
-		if ($limit !== -1) {
795
-			$qb->setMaxResults($limit);
796
-		}
797
-		$qb->setFirstResult($offset);
798
-
799
-		$qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
800
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
801
-
802
-		// Filter by node if provided
803
-		if ($node !== null) {
804
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
805
-		}
806
-
807
-		$cursor = $qb->execute();
808
-
809
-		while ($data = $cursor->fetch()) {
810
-			$shares[] = $this->createShareObject($data);
811
-		}
812
-		$cursor->closeCursor();
813
-
814
-
815
-		return $shares;
816
-	}
817
-
818
-	/**
819
-	 * Get a share by token
820
-	 *
821
-	 * @param string $token
822
-	 * @return IShare
823
-	 * @throws ShareNotFound
824
-	 */
825
-	public function getShareByToken($token) {
826
-		$qb = $this->dbConnection->getQueryBuilder();
827
-
828
-		$cursor = $qb->select('*')
829
-			->from('share')
830
-			->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
831
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
832
-			->execute();
833
-
834
-		$data = $cursor->fetch();
835
-
836
-		if ($data === false) {
837
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
838
-		}
839
-
840
-		try {
841
-			$share = $this->createShareObject($data);
842
-		} catch (InvalidShare $e) {
843
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
844
-		}
845
-
846
-		return $share;
847
-	}
848
-
849
-	/**
850
-	 * get database row of a give share
851
-	 *
852
-	 * @param $id
853
-	 * @return array
854
-	 * @throws ShareNotFound
855
-	 */
856
-	private function getRawShare($id) {
857
-
858
-		// Now fetch the inserted share and create a complete share object
859
-		$qb = $this->dbConnection->getQueryBuilder();
860
-		$qb->select('*')
861
-			->from('share')
862
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
863
-
864
-		$cursor = $qb->execute();
865
-		$data = $cursor->fetch();
866
-		$cursor->closeCursor();
867
-
868
-		if ($data === false) {
869
-			throw new ShareNotFound;
870
-		}
871
-
872
-		return $data;
873
-	}
874
-
875
-	/**
876
-	 * Create a share object from an database row
877
-	 *
878
-	 * @param array $data
879
-	 * @return IShare
880
-	 * @throws InvalidShare
881
-	 * @throws ShareNotFound
882
-	 */
883
-	private function createShareObject($data) {
884
-		$share = new Share($this->rootFolder, $this->userManager);
885
-		$share->setId((int)$data['id'])
886
-			->setShareType((int)$data['share_type'])
887
-			->setPermissions((int)$data['permissions'])
888
-			->setTarget($data['file_target'])
889
-			->setMailSend((bool)$data['mail_send'])
890
-			->setToken($data['token']);
891
-
892
-		$shareTime = new \DateTime();
893
-		$shareTime->setTimestamp((int)$data['stime']);
894
-		$share->setShareTime($shareTime);
895
-		$share->setSharedWith($data['share_with']);
896
-
897
-		if ($data['uid_initiator'] !== null) {
898
-			$share->setShareOwner($data['uid_owner']);
899
-			$share->setSharedBy($data['uid_initiator']);
900
-		} else {
901
-			//OLD SHARE
902
-			$share->setSharedBy($data['uid_owner']);
903
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
904
-
905
-			$owner = $path->getOwner();
906
-			$share->setShareOwner($owner->getUID());
907
-		}
908
-
909
-		$share->setNodeId((int)$data['file_source']);
910
-		$share->setNodeType($data['item_type']);
911
-
912
-		$share->setProviderId($this->identifier());
913
-
914
-		return $share;
915
-	}
916
-
917
-	/**
918
-	 * Get the node with file $id for $user
919
-	 *
920
-	 * @param string $userId
921
-	 * @param int $id
922
-	 * @return \OCP\Files\File|\OCP\Files\Folder
923
-	 * @throws InvalidShare
924
-	 */
925
-	private function getNode($userId, $id) {
926
-		try {
927
-			$userFolder = $this->rootFolder->getUserFolder($userId);
928
-		} catch (NotFoundException $e) {
929
-			throw new InvalidShare();
930
-		}
931
-
932
-		$nodes = $userFolder->getById($id);
933
-
934
-		if (empty($nodes)) {
935
-			throw new InvalidShare();
936
-		}
937
-
938
-		return $nodes[0];
939
-	}
940
-
941
-	/**
942
-	 * A user is deleted from the system
943
-	 * So clean up the relevant shares.
944
-	 *
945
-	 * @param string $uid
946
-	 * @param int $shareType
947
-	 */
948
-	public function userDeleted($uid, $shareType) {
949
-		//TODO: probabaly a good idea to send unshare info to remote servers
950
-
951
-		$qb = $this->dbConnection->getQueryBuilder();
952
-
953
-		$qb->delete('share')
954
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
955
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
956
-			->execute();
957
-	}
958
-
959
-	/**
960
-	 * This provider does not handle groups
961
-	 *
962
-	 * @param string $gid
963
-	 */
964
-	public function groupDeleted($gid) {
965
-		// We don't handle groups here
966
-	}
967
-
968
-	/**
969
-	 * This provider does not handle groups
970
-	 *
971
-	 * @param string $uid
972
-	 * @param string $gid
973
-	 */
974
-	public function userDeletedFromGroup($uid, $gid) {
975
-		// We don't handle groups here
976
-	}
977
-
978
-	/**
979
-	 * check if users from other Nextcloud instances are allowed to mount public links share by this instance
980
-	 *
981
-	 * @return bool
982
-	 */
983
-	public function isOutgoingServer2serverShareEnabled() {
984
-		if ($this->gsConfig->onlyInternalFederation()) {
985
-			return false;
986
-		}
987
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
988
-		return ($result === 'yes');
989
-	}
990
-
991
-	/**
992
-	 * check if users are allowed to mount public links from other Nextclouds
993
-	 *
994
-	 * @return bool
995
-	 */
996
-	public function isIncomingServer2serverShareEnabled() {
997
-		if ($this->gsConfig->onlyInternalFederation()) {
998
-			return false;
999
-		}
1000
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
1001
-		return ($result === 'yes');
1002
-	}
1003
-
1004
-
1005
-	/**
1006
-	 * check if users from other Nextcloud instances are allowed to send federated group shares
1007
-	 *
1008
-	 * @return bool
1009
-	 */
1010
-	public function isOutgoingServer2serverGroupShareEnabled() {
1011
-		if ($this->gsConfig->onlyInternalFederation()) {
1012
-			return false;
1013
-		}
1014
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1015
-		return ($result === 'yes');
1016
-	}
1017
-
1018
-	/**
1019
-	 * check if users are allowed to receive federated group shares
1020
-	 *
1021
-	 * @return bool
1022
-	 */
1023
-	public function isIncomingServer2serverGroupShareEnabled() {
1024
-		if ($this->gsConfig->onlyInternalFederation()) {
1025
-			return false;
1026
-		}
1027
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1028
-		return ($result === 'yes');
1029
-	}
1030
-
1031
-	/**
1032
-	 * check if federated group sharing is supported, therefore the OCM API need to be enabled
1033
-	 *
1034
-	 * @return bool
1035
-	 */
1036
-	public function isFederatedGroupSharingSupported() {
1037
-		return $this->cloudFederationProviderManager->isReady();
1038
-	}
1039
-
1040
-	/**
1041
-	 * Check if querying sharees on the lookup server is enabled
1042
-	 *
1043
-	 * @return bool
1044
-	 */
1045
-	public function isLookupServerQueriesEnabled() {
1046
-		// in a global scale setup we should always query the lookup server
1047
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1048
-			return true;
1049
-		}
1050
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes');
1051
-		return ($result === 'yes');
1052
-	}
1053
-
1054
-
1055
-	/**
1056
-	 * Check if it is allowed to publish user specific data to the lookup server
1057
-	 *
1058
-	 * @return bool
1059
-	 */
1060
-	public function isLookupServerUploadEnabled() {
1061
-		// in a global scale setup the admin is responsible to keep the lookup server up-to-date
1062
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1063
-			return false;
1064
-		}
1065
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1066
-		return ($result === 'yes');
1067
-	}
1068
-
1069
-	/**
1070
-	 * @inheritdoc
1071
-	 */
1072
-	public function getAccessList($nodes, $currentAccess) {
1073
-		$ids = [];
1074
-		foreach ($nodes as $node) {
1075
-			$ids[] = $node->getId();
1076
-		}
1077
-
1078
-		$qb = $this->dbConnection->getQueryBuilder();
1079
-		$qb->select('share_with', 'token', 'file_source')
1080
-			->from('share')
1081
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
1082
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1083
-			->andWhere($qb->expr()->orX(
1084
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1085
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1086
-			));
1087
-		$cursor = $qb->execute();
1088
-
1089
-		if ($currentAccess === false) {
1090
-			$remote = $cursor->fetch() !== false;
1091
-			$cursor->closeCursor();
1092
-
1093
-			return ['remote' => $remote];
1094
-		}
1095
-
1096
-		$remote = [];
1097
-		while ($row = $cursor->fetch()) {
1098
-			$remote[$row['share_with']] = [
1099
-				'node_id' => $row['file_source'],
1100
-				'token' => $row['token'],
1101
-			];
1102
-		}
1103
-		$cursor->closeCursor();
1104
-
1105
-		return ['remote' => $remote];
1106
-	}
1107
-
1108
-	public function getAllShares(): iterable {
1109
-		$qb = $this->dbConnection->getQueryBuilder();
1110
-
1111
-		$qb->select('*')
1112
-			->from('share')
1113
-			->where(
1114
-				$qb->expr()->orX(
1115
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
1116
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
1117
-				)
1118
-			);
1119
-
1120
-		$cursor = $qb->execute();
1121
-		while ($data = $cursor->fetch()) {
1122
-			try {
1123
-				$share = $this->createShareObject($data);
1124
-			} catch (InvalidShare $e) {
1125
-				continue;
1126
-			} catch (ShareNotFound $e) {
1127
-				continue;
1128
-			}
1129
-
1130
-			yield $share;
1131
-		}
1132
-		$cursor->closeCursor();
1133
-	}
507
+        return $share;
508
+    }
509
+
510
+    /**
511
+     * Get all children of this share
512
+     *
513
+     * @param IShare $parent
514
+     * @return IShare[]
515
+     */
516
+    public function getChildren(IShare $parent) {
517
+        $children = [];
518
+
519
+        $qb = $this->dbConnection->getQueryBuilder();
520
+        $qb->select('*')
521
+            ->from('share')
522
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
523
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
524
+            ->orderBy('id');
525
+
526
+        $cursor = $qb->execute();
527
+        while ($data = $cursor->fetch()) {
528
+            $children[] = $this->createShareObject($data);
529
+        }
530
+        $cursor->closeCursor();
531
+
532
+        return $children;
533
+    }
534
+
535
+    /**
536
+     * Delete a share (owner unShares the file)
537
+     *
538
+     * @param IShare $share
539
+     * @throws ShareNotFound
540
+     * @throws \OC\HintException
541
+     */
542
+    public function delete(IShare $share) {
543
+        list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
544
+
545
+        // if the local user is the owner we can send the unShare request directly...
546
+        if ($this->userManager->userExists($share->getShareOwner())) {
547
+            $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
548
+            $this->revokeShare($share, true);
549
+        } else { // ... if not we need to correct ID for the unShare request
550
+            $remoteId = $this->getRemoteId($share);
551
+            $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
552
+            $this->revokeShare($share, false);
553
+        }
554
+
555
+        // only remove the share when all messages are send to not lose information
556
+        // about the share to early
557
+        $this->removeShareFromTable($share);
558
+    }
559
+
560
+    /**
561
+     * in case of a re-share we need to send the other use (initiator or owner)
562
+     * a message that the file was unshared
563
+     *
564
+     * @param IShare $share
565
+     * @param bool $isOwner the user can either be the owner or the user who re-sahred it
566
+     * @throws ShareNotFound
567
+     * @throws \OC\HintException
568
+     */
569
+    protected function revokeShare($share, $isOwner) {
570
+        if ($this->userManager->userExists($share->getShareOwner()) && $this->userManager->userExists($share->getSharedBy())) {
571
+            // If both the owner and the initiator of the share are local users we don't have to notify anybody else
572
+            return;
573
+        }
574
+
575
+        // also send a unShare request to the initiator, if this is a different user than the owner
576
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
577
+            if ($isOwner) {
578
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
579
+            } else {
580
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
581
+            }
582
+            $remoteId = $this->getRemoteId($share);
583
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
584
+        }
585
+    }
586
+
587
+    /**
588
+     * remove share from table
589
+     *
590
+     * @param IShare $share
591
+     */
592
+    public function removeShareFromTable(IShare $share) {
593
+        $this->removeShareFromTableById($share->getId());
594
+    }
595
+
596
+    /**
597
+     * remove share from table
598
+     *
599
+     * @param string $shareId
600
+     */
601
+    private function removeShareFromTableById($shareId) {
602
+        $qb = $this->dbConnection->getQueryBuilder();
603
+        $qb->delete('share')
604
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
605
+            ->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
606
+        $qb->execute();
607
+
608
+        $qb->delete('federated_reshares')
609
+            ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
610
+        $qb->execute();
611
+    }
612
+
613
+    /**
614
+     * @inheritdoc
615
+     */
616
+    public function deleteFromSelf(IShare $share, $recipient) {
617
+        // nothing to do here. Technically deleteFromSelf in the context of federated
618
+        // shares is a umount of an external storage. This is handled here
619
+        // apps/files_sharing/lib/external/manager.php
620
+        // TODO move this code over to this app
621
+    }
622
+
623
+    public function restore(IShare $share, string $recipient): IShare {
624
+        throw new GenericShareException('not implemented');
625
+    }
626
+
627
+
628
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
629
+        $qb = $this->dbConnection->getQueryBuilder();
630
+        $qb->select('*')
631
+            ->from('share', 's')
632
+            ->andWhere($qb->expr()->orX(
633
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
634
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
635
+            ))
636
+            ->andWhere(
637
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
638
+            );
639
+
640
+        /**
641
+         * Reshares for this user are shares where they are the owner.
642
+         */
643
+        if ($reshares === false) {
644
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
645
+        } else {
646
+            $qb->andWhere(
647
+                $qb->expr()->orX(
648
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
649
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
650
+                )
651
+            );
652
+        }
653
+
654
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
655
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
656
+
657
+        $qb->orderBy('id');
658
+
659
+        $cursor = $qb->execute();
660
+        $shares = [];
661
+        while ($data = $cursor->fetch()) {
662
+            $shares[$data['fileid']][] = $this->createShareObject($data);
663
+        }
664
+        $cursor->closeCursor();
665
+
666
+        return $shares;
667
+    }
668
+
669
+    /**
670
+     * @inheritdoc
671
+     */
672
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
673
+        $qb = $this->dbConnection->getQueryBuilder();
674
+        $qb->select('*')
675
+            ->from('share');
676
+
677
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
678
+
679
+        /**
680
+         * Reshares for this user are shares where they are the owner.
681
+         */
682
+        if ($reshares === false) {
683
+            //Special case for old shares created via the web UI
684
+            $or1 = $qb->expr()->andX(
685
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
686
+                $qb->expr()->isNull('uid_initiator')
687
+            );
688
+
689
+            $qb->andWhere(
690
+                $qb->expr()->orX(
691
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
692
+                    $or1
693
+                )
694
+            );
695
+        } else {
696
+            $qb->andWhere(
697
+                $qb->expr()->orX(
698
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
699
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
700
+                )
701
+            );
702
+        }
703
+
704
+        if ($node !== null) {
705
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
706
+        }
707
+
708
+        if ($limit !== -1) {
709
+            $qb->setMaxResults($limit);
710
+        }
711
+
712
+        $qb->setFirstResult($offset);
713
+        $qb->orderBy('id');
714
+
715
+        $cursor = $qb->execute();
716
+        $shares = [];
717
+        while ($data = $cursor->fetch()) {
718
+            $shares[] = $this->createShareObject($data);
719
+        }
720
+        $cursor->closeCursor();
721
+
722
+        return $shares;
723
+    }
724
+
725
+    /**
726
+     * @inheritdoc
727
+     */
728
+    public function getShareById($id, $recipientId = null) {
729
+        $qb = $this->dbConnection->getQueryBuilder();
730
+
731
+        $qb->select('*')
732
+            ->from('share')
733
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
734
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
735
+
736
+        $cursor = $qb->execute();
737
+        $data = $cursor->fetch();
738
+        $cursor->closeCursor();
739
+
740
+        if ($data === false) {
741
+            throw new ShareNotFound('Can not find share with ID: ' . $id);
742
+        }
743
+
744
+        try {
745
+            $share = $this->createShareObject($data);
746
+        } catch (InvalidShare $e) {
747
+            throw new ShareNotFound();
748
+        }
749
+
750
+        return $share;
751
+    }
752
+
753
+    /**
754
+     * Get shares for a given path
755
+     *
756
+     * @param \OCP\Files\Node $path
757
+     * @return IShare[]
758
+     */
759
+    public function getSharesByPath(Node $path) {
760
+        $qb = $this->dbConnection->getQueryBuilder();
761
+
762
+        // get federated user shares
763
+        $cursor = $qb->select('*')
764
+            ->from('share')
765
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
766
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
767
+            ->execute();
768
+
769
+        $shares = [];
770
+        while ($data = $cursor->fetch()) {
771
+            $shares[] = $this->createShareObject($data);
772
+        }
773
+        $cursor->closeCursor();
774
+
775
+        return $shares;
776
+    }
777
+
778
+    /**
779
+     * @inheritdoc
780
+     */
781
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
782
+        /** @var IShare[] $shares */
783
+        $shares = [];
784
+
785
+        //Get shares directly with this user
786
+        $qb = $this->dbConnection->getQueryBuilder();
787
+        $qb->select('*')
788
+            ->from('share');
789
+
790
+        // Order by id
791
+        $qb->orderBy('id');
792
+
793
+        // Set limit and offset
794
+        if ($limit !== -1) {
795
+            $qb->setMaxResults($limit);
796
+        }
797
+        $qb->setFirstResult($offset);
798
+
799
+        $qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
800
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
801
+
802
+        // Filter by node if provided
803
+        if ($node !== null) {
804
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
805
+        }
806
+
807
+        $cursor = $qb->execute();
808
+
809
+        while ($data = $cursor->fetch()) {
810
+            $shares[] = $this->createShareObject($data);
811
+        }
812
+        $cursor->closeCursor();
813
+
814
+
815
+        return $shares;
816
+    }
817
+
818
+    /**
819
+     * Get a share by token
820
+     *
821
+     * @param string $token
822
+     * @return IShare
823
+     * @throws ShareNotFound
824
+     */
825
+    public function getShareByToken($token) {
826
+        $qb = $this->dbConnection->getQueryBuilder();
827
+
828
+        $cursor = $qb->select('*')
829
+            ->from('share')
830
+            ->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
831
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
832
+            ->execute();
833
+
834
+        $data = $cursor->fetch();
835
+
836
+        if ($data === false) {
837
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
838
+        }
839
+
840
+        try {
841
+            $share = $this->createShareObject($data);
842
+        } catch (InvalidShare $e) {
843
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
844
+        }
845
+
846
+        return $share;
847
+    }
848
+
849
+    /**
850
+     * get database row of a give share
851
+     *
852
+     * @param $id
853
+     * @return array
854
+     * @throws ShareNotFound
855
+     */
856
+    private function getRawShare($id) {
857
+
858
+        // Now fetch the inserted share and create a complete share object
859
+        $qb = $this->dbConnection->getQueryBuilder();
860
+        $qb->select('*')
861
+            ->from('share')
862
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
863
+
864
+        $cursor = $qb->execute();
865
+        $data = $cursor->fetch();
866
+        $cursor->closeCursor();
867
+
868
+        if ($data === false) {
869
+            throw new ShareNotFound;
870
+        }
871
+
872
+        return $data;
873
+    }
874
+
875
+    /**
876
+     * Create a share object from an database row
877
+     *
878
+     * @param array $data
879
+     * @return IShare
880
+     * @throws InvalidShare
881
+     * @throws ShareNotFound
882
+     */
883
+    private function createShareObject($data) {
884
+        $share = new Share($this->rootFolder, $this->userManager);
885
+        $share->setId((int)$data['id'])
886
+            ->setShareType((int)$data['share_type'])
887
+            ->setPermissions((int)$data['permissions'])
888
+            ->setTarget($data['file_target'])
889
+            ->setMailSend((bool)$data['mail_send'])
890
+            ->setToken($data['token']);
891
+
892
+        $shareTime = new \DateTime();
893
+        $shareTime->setTimestamp((int)$data['stime']);
894
+        $share->setShareTime($shareTime);
895
+        $share->setSharedWith($data['share_with']);
896
+
897
+        if ($data['uid_initiator'] !== null) {
898
+            $share->setShareOwner($data['uid_owner']);
899
+            $share->setSharedBy($data['uid_initiator']);
900
+        } else {
901
+            //OLD SHARE
902
+            $share->setSharedBy($data['uid_owner']);
903
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
904
+
905
+            $owner = $path->getOwner();
906
+            $share->setShareOwner($owner->getUID());
907
+        }
908
+
909
+        $share->setNodeId((int)$data['file_source']);
910
+        $share->setNodeType($data['item_type']);
911
+
912
+        $share->setProviderId($this->identifier());
913
+
914
+        return $share;
915
+    }
916
+
917
+    /**
918
+     * Get the node with file $id for $user
919
+     *
920
+     * @param string $userId
921
+     * @param int $id
922
+     * @return \OCP\Files\File|\OCP\Files\Folder
923
+     * @throws InvalidShare
924
+     */
925
+    private function getNode($userId, $id) {
926
+        try {
927
+            $userFolder = $this->rootFolder->getUserFolder($userId);
928
+        } catch (NotFoundException $e) {
929
+            throw new InvalidShare();
930
+        }
931
+
932
+        $nodes = $userFolder->getById($id);
933
+
934
+        if (empty($nodes)) {
935
+            throw new InvalidShare();
936
+        }
937
+
938
+        return $nodes[0];
939
+    }
940
+
941
+    /**
942
+     * A user is deleted from the system
943
+     * So clean up the relevant shares.
944
+     *
945
+     * @param string $uid
946
+     * @param int $shareType
947
+     */
948
+    public function userDeleted($uid, $shareType) {
949
+        //TODO: probabaly a good idea to send unshare info to remote servers
950
+
951
+        $qb = $this->dbConnection->getQueryBuilder();
952
+
953
+        $qb->delete('share')
954
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
955
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
956
+            ->execute();
957
+    }
958
+
959
+    /**
960
+     * This provider does not handle groups
961
+     *
962
+     * @param string $gid
963
+     */
964
+    public function groupDeleted($gid) {
965
+        // We don't handle groups here
966
+    }
967
+
968
+    /**
969
+     * This provider does not handle groups
970
+     *
971
+     * @param string $uid
972
+     * @param string $gid
973
+     */
974
+    public function userDeletedFromGroup($uid, $gid) {
975
+        // We don't handle groups here
976
+    }
977
+
978
+    /**
979
+     * check if users from other Nextcloud instances are allowed to mount public links share by this instance
980
+     *
981
+     * @return bool
982
+     */
983
+    public function isOutgoingServer2serverShareEnabled() {
984
+        if ($this->gsConfig->onlyInternalFederation()) {
985
+            return false;
986
+        }
987
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
988
+        return ($result === 'yes');
989
+    }
990
+
991
+    /**
992
+     * check if users are allowed to mount public links from other Nextclouds
993
+     *
994
+     * @return bool
995
+     */
996
+    public function isIncomingServer2serverShareEnabled() {
997
+        if ($this->gsConfig->onlyInternalFederation()) {
998
+            return false;
999
+        }
1000
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
1001
+        return ($result === 'yes');
1002
+    }
1003
+
1004
+
1005
+    /**
1006
+     * check if users from other Nextcloud instances are allowed to send federated group shares
1007
+     *
1008
+     * @return bool
1009
+     */
1010
+    public function isOutgoingServer2serverGroupShareEnabled() {
1011
+        if ($this->gsConfig->onlyInternalFederation()) {
1012
+            return false;
1013
+        }
1014
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1015
+        return ($result === 'yes');
1016
+    }
1017
+
1018
+    /**
1019
+     * check if users are allowed to receive federated group shares
1020
+     *
1021
+     * @return bool
1022
+     */
1023
+    public function isIncomingServer2serverGroupShareEnabled() {
1024
+        if ($this->gsConfig->onlyInternalFederation()) {
1025
+            return false;
1026
+        }
1027
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1028
+        return ($result === 'yes');
1029
+    }
1030
+
1031
+    /**
1032
+     * check if federated group sharing is supported, therefore the OCM API need to be enabled
1033
+     *
1034
+     * @return bool
1035
+     */
1036
+    public function isFederatedGroupSharingSupported() {
1037
+        return $this->cloudFederationProviderManager->isReady();
1038
+    }
1039
+
1040
+    /**
1041
+     * Check if querying sharees on the lookup server is enabled
1042
+     *
1043
+     * @return bool
1044
+     */
1045
+    public function isLookupServerQueriesEnabled() {
1046
+        // in a global scale setup we should always query the lookup server
1047
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1048
+            return true;
1049
+        }
1050
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes');
1051
+        return ($result === 'yes');
1052
+    }
1053
+
1054
+
1055
+    /**
1056
+     * Check if it is allowed to publish user specific data to the lookup server
1057
+     *
1058
+     * @return bool
1059
+     */
1060
+    public function isLookupServerUploadEnabled() {
1061
+        // in a global scale setup the admin is responsible to keep the lookup server up-to-date
1062
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1063
+            return false;
1064
+        }
1065
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1066
+        return ($result === 'yes');
1067
+    }
1068
+
1069
+    /**
1070
+     * @inheritdoc
1071
+     */
1072
+    public function getAccessList($nodes, $currentAccess) {
1073
+        $ids = [];
1074
+        foreach ($nodes as $node) {
1075
+            $ids[] = $node->getId();
1076
+        }
1077
+
1078
+        $qb = $this->dbConnection->getQueryBuilder();
1079
+        $qb->select('share_with', 'token', 'file_source')
1080
+            ->from('share')
1081
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
1082
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1083
+            ->andWhere($qb->expr()->orX(
1084
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1085
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1086
+            ));
1087
+        $cursor = $qb->execute();
1088
+
1089
+        if ($currentAccess === false) {
1090
+            $remote = $cursor->fetch() !== false;
1091
+            $cursor->closeCursor();
1092
+
1093
+            return ['remote' => $remote];
1094
+        }
1095
+
1096
+        $remote = [];
1097
+        while ($row = $cursor->fetch()) {
1098
+            $remote[$row['share_with']] = [
1099
+                'node_id' => $row['file_source'],
1100
+                'token' => $row['token'],
1101
+            ];
1102
+        }
1103
+        $cursor->closeCursor();
1104
+
1105
+        return ['remote' => $remote];
1106
+    }
1107
+
1108
+    public function getAllShares(): iterable {
1109
+        $qb = $this->dbConnection->getQueryBuilder();
1110
+
1111
+        $qb->select('*')
1112
+            ->from('share')
1113
+            ->where(
1114
+                $qb->expr()->orX(
1115
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
1116
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
1117
+                )
1118
+            );
1119
+
1120
+        $cursor = $qb->execute();
1121
+        while ($data = $cursor->fetch()) {
1122
+            try {
1123
+                $share = $this->createShareObject($data);
1124
+            } catch (InvalidShare $e) {
1125
+                continue;
1126
+            } catch (ShareNotFound $e) {
1127
+                continue;
1128
+            }
1129
+
1130
+            yield $share;
1131
+        }
1132
+        $cursor->closeCursor();
1133
+    }
1134 1134
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/Migration/Version1011Date20201120125158.php 1 patch
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -35,37 +35,37 @@
 block discarded – undo
35 35
 
36 36
 class Version1011Date20201120125158 extends SimpleMigrationStep {
37 37
 
38
-	/** @var IDBConnection */
39
-	private $connection;
38
+    /** @var IDBConnection */
39
+    private $connection;
40 40
 
41
-	public function __construct(IDBConnection $connection) {
42
-		$this->connection = $connection;
43
-	}
41
+    public function __construct(IDBConnection $connection) {
42
+        $this->connection = $connection;
43
+    }
44 44
 
45
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
46
-		/** @var ISchemaWrapper $schema */
47
-		$schema = $schemaClosure();
45
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
46
+        /** @var ISchemaWrapper $schema */
47
+        $schema = $schemaClosure();
48 48
 
49
-		if ($schema->hasTable('federated_reshares')) {
50
-			$table = $schema->getTable('federated_reshares');
51
-			$remoteIdColumn = $table->getColumn('remote_id');
52
-			if ($remoteIdColumn && $remoteIdColumn->getType()->getName() !== Types::STRING) {
53
-				$remoteIdColumn->setNotnull(false);
54
-				$remoteIdColumn->setType(Type::getType(Types::STRING));
55
-				$remoteIdColumn->setOptions(['length' => 255]);
56
-				$remoteIdColumn->setDefault('');
57
-				return $schema;
58
-			}
59
-		}
49
+        if ($schema->hasTable('federated_reshares')) {
50
+            $table = $schema->getTable('federated_reshares');
51
+            $remoteIdColumn = $table->getColumn('remote_id');
52
+            if ($remoteIdColumn && $remoteIdColumn->getType()->getName() !== Types::STRING) {
53
+                $remoteIdColumn->setNotnull(false);
54
+                $remoteIdColumn->setType(Type::getType(Types::STRING));
55
+                $remoteIdColumn->setOptions(['length' => 255]);
56
+                $remoteIdColumn->setDefault('');
57
+                return $schema;
58
+            }
59
+        }
60 60
 
61
-		return null;
62
-	}
61
+        return null;
62
+    }
63 63
 
64
-	public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
65
-		$qb = $this->connection->getQueryBuilder();
66
-		$qb->update('federated_reshares')
67
-			->set('remote_id', $qb->createNamedParameter(''))
68
-			->where($qb->expr()->eq('remote_id', $qb->createNamedParameter('-1')));
69
-		$qb->execute();
70
-	}
64
+    public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
65
+        $qb = $this->connection->getQueryBuilder();
66
+        $qb->update('federated_reshares')
67
+            ->set('remote_id', $qb->createNamedParameter(''))
68
+            ->where($qb->expr()->eq('remote_id', $qb->createNamedParameter('-1')));
69
+        $qb->execute();
70
+    }
71 71
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/Migration/Version1010Date20200630191755.php 1 patch
Indentation   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -32,29 +32,29 @@
 block discarded – undo
32 32
 use OCP\Migration\SimpleMigrationStep;
33 33
 
34 34
 class Version1010Date20200630191755 extends SimpleMigrationStep {
35
-	/**
36
-	 * @param IOutput $output
37
-	 * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
38
-	 * @param array $options
39
-	 * @return null|ISchemaWrapper
40
-	 */
41
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
42
-		/** @var ISchemaWrapper $schema */
43
-		$schema = $schemaClosure();
35
+    /**
36
+     * @param IOutput $output
37
+     * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
38
+     * @param array $options
39
+     * @return null|ISchemaWrapper
40
+     */
41
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
42
+        /** @var ISchemaWrapper $schema */
43
+        $schema = $schemaClosure();
44 44
 
45
-		if (!$schema->hasTable('federated_reshares')) {
46
-			$table = $schema->createTable('federated_reshares');
47
-			$table->addColumn('share_id', Types::BIGINT, [
48
-				'notnull' => true,
49
-			]);
50
-			$table->addColumn('remote_id', Types::STRING, [
51
-				'notnull' => false,
52
-				'length' => 255,
53
-				'default' => '',
54
-			]);
55
-			$table->setPrimaryKey(['share_id'], 'federated_res_pk');
45
+        if (!$schema->hasTable('federated_reshares')) {
46
+            $table = $schema->createTable('federated_reshares');
47
+            $table->addColumn('share_id', Types::BIGINT, [
48
+                'notnull' => true,
49
+            ]);
50
+            $table->addColumn('remote_id', Types::STRING, [
51
+                'notnull' => false,
52
+                'length' => 255,
53
+                'default' => '',
54
+            ]);
55
+            $table->setPrimaryKey(['share_id'], 'federated_res_pk');
56 56
 //			$table->addUniqueIndex(['share_id'], 'share_id_index');
57
-		}
58
-		return $schema;
59
-	}
57
+        }
58
+        return $schema;
59
+    }
60 60
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/Notifications.php 1 patch
Indentation   +399 added lines, -399 removed lines patch added patch discarded remove patch
@@ -36,403 +36,403 @@
 block discarded – undo
36 36
 use OCP\OCS\IDiscoveryService;
37 37
 
38 38
 class Notifications {
39
-	public const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
40
-
41
-	/** @var AddressHandler */
42
-	private $addressHandler;
43
-
44
-	/** @var IClientService */
45
-	private $httpClientService;
46
-
47
-	/** @var IDiscoveryService */
48
-	private $discoveryService;
49
-
50
-	/** @var IJobList  */
51
-	private $jobList;
52
-
53
-	/** @var ICloudFederationProviderManager */
54
-	private $federationProviderManager;
55
-
56
-	/** @var ICloudFederationFactory */
57
-	private $cloudFederationFactory;
58
-
59
-	/** @var IEventDispatcher */
60
-	private $eventDispatcher;
61
-
62
-	public function __construct(
63
-		AddressHandler $addressHandler,
64
-		IClientService $httpClientService,
65
-		IDiscoveryService $discoveryService,
66
-		IJobList $jobList,
67
-		ICloudFederationProviderManager $federationProviderManager,
68
-		ICloudFederationFactory $cloudFederationFactory,
69
-		IEventDispatcher $eventDispatcher
70
-	) {
71
-		$this->addressHandler = $addressHandler;
72
-		$this->httpClientService = $httpClientService;
73
-		$this->discoveryService = $discoveryService;
74
-		$this->jobList = $jobList;
75
-		$this->federationProviderManager = $federationProviderManager;
76
-		$this->cloudFederationFactory = $cloudFederationFactory;
77
-		$this->eventDispatcher = $eventDispatcher;
78
-	}
79
-
80
-	/**
81
-	 * send server-to-server share to remote server
82
-	 *
83
-	 * @param string $token
84
-	 * @param string $shareWith
85
-	 * @param string $name
86
-	 * @param string $remoteId
87
-	 * @param string $owner
88
-	 * @param string $ownerFederatedId
89
-	 * @param string $sharedBy
90
-	 * @param string $sharedByFederatedId
91
-	 * @param int $shareType (can be a remote user or group share)
92
-	 * @return bool
93
-	 * @throws \OC\HintException
94
-	 * @throws \OC\ServerNotAvailableException
95
-	 */
96
-	public function sendRemoteShare($token, $shareWith, $name, $remoteId, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId, $shareType) {
97
-		list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
98
-
99
-		if ($user && $remote) {
100
-			$local = $this->addressHandler->generateRemoteURL();
101
-
102
-			$fields = [
103
-				'shareWith' => $user,
104
-				'token' => $token,
105
-				'name' => $name,
106
-				'remoteId' => $remoteId,
107
-				'owner' => $owner,
108
-				'ownerFederatedId' => $ownerFederatedId,
109
-				'sharedBy' => $sharedBy,
110
-				'sharedByFederatedId' => $sharedByFederatedId,
111
-				'remote' => $local,
112
-				'shareType' => $shareType
113
-			];
114
-
115
-			$result = $this->tryHttpPostToShareEndpoint($remote, '', $fields);
116
-			$status = json_decode($result['result'], true);
117
-
118
-			$ocsStatus = isset($status['ocs']);
119
-			$ocsSuccess = $ocsStatus && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200);
120
-
121
-			if ($result['success'] && (!$ocsStatus || $ocsSuccess)) {
122
-				$event = new FederatedShareAddedEvent($remote);
123
-				$this->eventDispatcher->dispatchTyped($event);
124
-				return true;
125
-			}
126
-		}
127
-
128
-		return false;
129
-	}
130
-
131
-	/**
132
-	 * ask owner to re-share the file with the given user
133
-	 *
134
-	 * @param string $token
135
-	 * @param string $id remote Id
136
-	 * @param string $shareId internal share Id
137
-	 * @param string $remote remote address of the owner
138
-	 * @param string $shareWith
139
-	 * @param int $permission
140
-	 * @param string $filename
141
-	 * @return array|false
142
-	 * @throws \OC\HintException
143
-	 * @throws \OC\ServerNotAvailableException
144
-	 */
145
-	public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission, $filename) {
146
-		$fields = [
147
-			'shareWith' => $shareWith,
148
-			'token' => $token,
149
-			'permission' => $permission,
150
-			'remoteId' => $shareId,
151
-		];
152
-
153
-		$ocmFields = $fields;
154
-		$ocmFields['remoteId'] = (string)$id;
155
-		$ocmFields['localId'] = $shareId;
156
-		$ocmFields['name'] = $filename;
157
-
158
-		$ocmResult = $this->tryOCMEndPoint($remote, $ocmFields, 'reshare');
159
-		if (is_array($ocmResult) && isset($ocmResult['token']) && isset($ocmResult['providerId'])) {
160
-			return [$ocmResult['token'], $ocmResult['providerId']];
161
-		}
162
-
163
-		$result = $this->tryLegacyEndPoint(rtrim($remote, '/'), '/' . $id . '/reshare', $fields);
164
-		$status = json_decode($result['result'], true);
165
-
166
-		$httpRequestSuccessful = $result['success'];
167
-		$ocsCallSuccessful = $status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200;
168
-		$validToken = isset($status['ocs']['data']['token']) && is_string($status['ocs']['data']['token']);
169
-		$validRemoteId = isset($status['ocs']['data']['remoteId']);
170
-
171
-		if ($httpRequestSuccessful && $ocsCallSuccessful && $validToken && $validRemoteId) {
172
-			return [
173
-				$status['ocs']['data']['token'],
174
-				$status['ocs']['data']['remoteId']
175
-			];
176
-		}
177
-
178
-		return false;
179
-	}
180
-
181
-	/**
182
-	 * send server-to-server unshare to remote server
183
-	 *
184
-	 * @param string $remote url
185
-	 * @param string $id share id
186
-	 * @param string $token
187
-	 * @return bool
188
-	 */
189
-	public function sendRemoteUnShare($remote, $id, $token) {
190
-		$this->sendUpdateToRemote($remote, $id, $token, 'unshare');
191
-	}
192
-
193
-	/**
194
-	 * send server-to-server unshare to remote server
195
-	 *
196
-	 * @param string $remote url
197
-	 * @param string $id share id
198
-	 * @param string $token
199
-	 * @return bool
200
-	 */
201
-	public function sendRevokeShare($remote, $id, $token) {
202
-		$this->sendUpdateToRemote($remote, $id, $token, 'reshare_undo');
203
-	}
204
-
205
-	/**
206
-	 * send notification to remote server if the permissions was changed
207
-	 *
208
-	 * @param string $remote
209
-	 * @param string $remoteId
210
-	 * @param string $token
211
-	 * @param int $permissions
212
-	 * @return bool
213
-	 */
214
-	public function sendPermissionChange($remote, $remoteId, $token, $permissions) {
215
-		$this->sendUpdateToRemote($remote, $remoteId, $token, 'permissions', ['permissions' => $permissions]);
216
-	}
217
-
218
-	/**
219
-	 * forward accept reShare to remote server
220
-	 *
221
-	 * @param string $remote
222
-	 * @param string $remoteId
223
-	 * @param string $token
224
-	 */
225
-	public function sendAcceptShare($remote, $remoteId, $token) {
226
-		$this->sendUpdateToRemote($remote, $remoteId, $token, 'accept');
227
-	}
228
-
229
-	/**
230
-	 * forward decline reShare to remote server
231
-	 *
232
-	 * @param string $remote
233
-	 * @param string $remoteId
234
-	 * @param string $token
235
-	 */
236
-	public function sendDeclineShare($remote, $remoteId, $token) {
237
-		$this->sendUpdateToRemote($remote, $remoteId, $token, 'decline');
238
-	}
239
-
240
-	/**
241
-	 * inform remote server whether server-to-server share was accepted/declined
242
-	 *
243
-	 * @param string $remote
244
-	 * @param string $token
245
-	 * @param string $remoteId Share id on the remote host
246
-	 * @param string $action possible actions: accept, decline, unshare, revoke, permissions
247
-	 * @param array $data
248
-	 * @param int $try
249
-	 * @return boolean
250
-	 */
251
-	public function sendUpdateToRemote($remote, $remoteId, $token, $action, $data = [], $try = 0) {
252
-		$fields = [
253
-			'token' => $token,
254
-			'remoteId' => $remoteId
255
-		];
256
-		foreach ($data as $key => $value) {
257
-			$fields[$key] = $value;
258
-		}
259
-
260
-		$result = $this->tryHttpPostToShareEndpoint(rtrim($remote, '/'), '/' . $remoteId . '/' . $action, $fields, $action);
261
-		$status = json_decode($result['result'], true);
262
-
263
-		if ($result['success'] &&
264
-			($status['ocs']['meta']['statuscode'] === 100 ||
265
-				$status['ocs']['meta']['statuscode'] === 200
266
-			)
267
-		) {
268
-			return true;
269
-		} elseif ($try === 0) {
270
-			// only add new job on first try
271
-			$this->jobList->add('OCA\FederatedFileSharing\BackgroundJob\RetryJob',
272
-				[
273
-					'remote' => $remote,
274
-					'remoteId' => $remoteId,
275
-					'token' => $token,
276
-					'action' => $action,
277
-					'data' => json_encode($data),
278
-					'try' => $try,
279
-					'lastRun' => $this->getTimestamp()
280
-				]
281
-			);
282
-		}
283
-
284
-		return false;
285
-	}
286
-
287
-
288
-	/**
289
-	 * return current timestamp
290
-	 *
291
-	 * @return int
292
-	 */
293
-	protected function getTimestamp() {
294
-		return time();
295
-	}
296
-
297
-	/**
298
-	 * try http post with the given protocol, if no protocol is given we pick
299
-	 * the secure one (https)
300
-	 *
301
-	 * @param string $remoteDomain
302
-	 * @param string $urlSuffix
303
-	 * @param array $fields post parameters
304
-	 * @param string $action define the action (possible values: share, reshare, accept, decline, unshare, revoke, permissions)
305
-	 * @return array
306
-	 * @throws \Exception
307
-	 */
308
-	protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields, $action = "share") {
309
-		if ($this->addressHandler->urlContainProtocol($remoteDomain) === false) {
310
-			$remoteDomain = 'https://' . $remoteDomain;
311
-		}
312
-
313
-		$result = [
314
-			'success' => false,
315
-			'result' => '',
316
-		];
317
-
318
-		// if possible we use the new OCM API
319
-		$ocmResult = $this->tryOCMEndPoint($remoteDomain, $fields, $action);
320
-		if (is_array($ocmResult)) {
321
-			$result['success'] = true;
322
-			$result['result'] = json_encode([
323
-				'ocs' => ['meta' => ['statuscode' => 200]]]);
324
-			return $result;
325
-		}
326
-
327
-		return $this->tryLegacyEndPoint($remoteDomain, $urlSuffix, $fields);
328
-	}
329
-
330
-	/**
331
-	 * try old federated sharing API if the OCM api doesn't work
332
-	 *
333
-	 * @param $remoteDomain
334
-	 * @param $urlSuffix
335
-	 * @param array $fields
336
-	 * @return mixed
337
-	 * @throws \Exception
338
-	 */
339
-	protected function tryLegacyEndPoint($remoteDomain, $urlSuffix, array $fields) {
340
-		$result = [
341
-			'success' => false,
342
-			'result' => '',
343
-		];
344
-
345
-		// Fall back to old API
346
-		$client = $this->httpClientService->newClient();
347
-		$federationEndpoints = $this->discoveryService->discover($remoteDomain, 'FEDERATED_SHARING');
348
-		$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
349
-		try {
350
-			$response = $client->post($remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, [
351
-				'body' => $fields,
352
-				'timeout' => 10,
353
-				'connect_timeout' => 10,
354
-			]);
355
-			$result['result'] = $response->getBody();
356
-			$result['success'] = true;
357
-		} catch (\Exception $e) {
358
-			// if flat re-sharing is not supported by the remote server
359
-			// we re-throw the exception and fall back to the old behaviour.
360
-			// (flat re-shares has been introduced in Nextcloud 9.1)
361
-			if ($e->getCode() === Http::STATUS_INTERNAL_SERVER_ERROR) {
362
-				throw $e;
363
-			}
364
-		}
365
-
366
-		return $result;
367
-	}
368
-
369
-	/**
370
-	 * send action regarding federated sharing to the remote server using the OCM API
371
-	 *
372
-	 * @param $remoteDomain
373
-	 * @param $fields
374
-	 * @param $action
375
-	 *
376
-	 * @return bool
377
-	 */
378
-	protected function tryOCMEndPoint($remoteDomain, $fields, $action) {
379
-		switch ($action) {
380
-			case 'share':
381
-				$share = $this->cloudFederationFactory->getCloudFederationShare(
382
-					$fields['shareWith'] . '@' . $remoteDomain,
383
-					$fields['name'],
384
-					'',
385
-					$fields['remoteId'],
386
-					$fields['ownerFederatedId'],
387
-					$fields['owner'],
388
-					$fields['sharedByFederatedId'],
389
-					$fields['sharedBy'],
390
-					$fields['token'],
391
-					$fields['shareType'],
392
-					'file'
393
-				);
394
-				return $this->federationProviderManager->sendShare($share);
395
-			case 'reshare':
396
-				// ask owner to reshare a file
397
-				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
398
-				$notification->setMessage('REQUEST_RESHARE',
399
-					'file',
400
-					$fields['remoteId'],
401
-					[
402
-						'sharedSecret' => $fields['token'],
403
-						'shareWith' => $fields['shareWith'],
404
-						'senderId' => $fields['localId'],
405
-						'shareType' => $fields['shareType'],
406
-						'message' => 'Ask owner to reshare the file'
407
-					]
408
-				);
409
-				return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
410
-			case 'unshare':
411
-				//owner unshares the file from the recipient again
412
-				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
413
-				$notification->setMessage('SHARE_UNSHARED',
414
-					'file',
415
-					$fields['remoteId'],
416
-					[
417
-						'sharedSecret' => $fields['token'],
418
-						'messgage' => 'file is no longer shared with you'
419
-					]
420
-				);
421
-				return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
422
-			case 'reshare_undo':
423
-				// if a reshare was unshared we send the information to the initiator/owner
424
-				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
425
-				$notification->setMessage('RESHARE_UNDO',
426
-					'file',
427
-					$fields['remoteId'],
428
-					[
429
-						'sharedSecret' => $fields['token'],
430
-						'message' => 'reshare was revoked'
431
-					]
432
-				);
433
-				return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
434
-		}
435
-
436
-		return false;
437
-	}
39
+    public const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
40
+
41
+    /** @var AddressHandler */
42
+    private $addressHandler;
43
+
44
+    /** @var IClientService */
45
+    private $httpClientService;
46
+
47
+    /** @var IDiscoveryService */
48
+    private $discoveryService;
49
+
50
+    /** @var IJobList  */
51
+    private $jobList;
52
+
53
+    /** @var ICloudFederationProviderManager */
54
+    private $federationProviderManager;
55
+
56
+    /** @var ICloudFederationFactory */
57
+    private $cloudFederationFactory;
58
+
59
+    /** @var IEventDispatcher */
60
+    private $eventDispatcher;
61
+
62
+    public function __construct(
63
+        AddressHandler $addressHandler,
64
+        IClientService $httpClientService,
65
+        IDiscoveryService $discoveryService,
66
+        IJobList $jobList,
67
+        ICloudFederationProviderManager $federationProviderManager,
68
+        ICloudFederationFactory $cloudFederationFactory,
69
+        IEventDispatcher $eventDispatcher
70
+    ) {
71
+        $this->addressHandler = $addressHandler;
72
+        $this->httpClientService = $httpClientService;
73
+        $this->discoveryService = $discoveryService;
74
+        $this->jobList = $jobList;
75
+        $this->federationProviderManager = $federationProviderManager;
76
+        $this->cloudFederationFactory = $cloudFederationFactory;
77
+        $this->eventDispatcher = $eventDispatcher;
78
+    }
79
+
80
+    /**
81
+     * send server-to-server share to remote server
82
+     *
83
+     * @param string $token
84
+     * @param string $shareWith
85
+     * @param string $name
86
+     * @param string $remoteId
87
+     * @param string $owner
88
+     * @param string $ownerFederatedId
89
+     * @param string $sharedBy
90
+     * @param string $sharedByFederatedId
91
+     * @param int $shareType (can be a remote user or group share)
92
+     * @return bool
93
+     * @throws \OC\HintException
94
+     * @throws \OC\ServerNotAvailableException
95
+     */
96
+    public function sendRemoteShare($token, $shareWith, $name, $remoteId, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId, $shareType) {
97
+        list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
98
+
99
+        if ($user && $remote) {
100
+            $local = $this->addressHandler->generateRemoteURL();
101
+
102
+            $fields = [
103
+                'shareWith' => $user,
104
+                'token' => $token,
105
+                'name' => $name,
106
+                'remoteId' => $remoteId,
107
+                'owner' => $owner,
108
+                'ownerFederatedId' => $ownerFederatedId,
109
+                'sharedBy' => $sharedBy,
110
+                'sharedByFederatedId' => $sharedByFederatedId,
111
+                'remote' => $local,
112
+                'shareType' => $shareType
113
+            ];
114
+
115
+            $result = $this->tryHttpPostToShareEndpoint($remote, '', $fields);
116
+            $status = json_decode($result['result'], true);
117
+
118
+            $ocsStatus = isset($status['ocs']);
119
+            $ocsSuccess = $ocsStatus && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200);
120
+
121
+            if ($result['success'] && (!$ocsStatus || $ocsSuccess)) {
122
+                $event = new FederatedShareAddedEvent($remote);
123
+                $this->eventDispatcher->dispatchTyped($event);
124
+                return true;
125
+            }
126
+        }
127
+
128
+        return false;
129
+    }
130
+
131
+    /**
132
+     * ask owner to re-share the file with the given user
133
+     *
134
+     * @param string $token
135
+     * @param string $id remote Id
136
+     * @param string $shareId internal share Id
137
+     * @param string $remote remote address of the owner
138
+     * @param string $shareWith
139
+     * @param int $permission
140
+     * @param string $filename
141
+     * @return array|false
142
+     * @throws \OC\HintException
143
+     * @throws \OC\ServerNotAvailableException
144
+     */
145
+    public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission, $filename) {
146
+        $fields = [
147
+            'shareWith' => $shareWith,
148
+            'token' => $token,
149
+            'permission' => $permission,
150
+            'remoteId' => $shareId,
151
+        ];
152
+
153
+        $ocmFields = $fields;
154
+        $ocmFields['remoteId'] = (string)$id;
155
+        $ocmFields['localId'] = $shareId;
156
+        $ocmFields['name'] = $filename;
157
+
158
+        $ocmResult = $this->tryOCMEndPoint($remote, $ocmFields, 'reshare');
159
+        if (is_array($ocmResult) && isset($ocmResult['token']) && isset($ocmResult['providerId'])) {
160
+            return [$ocmResult['token'], $ocmResult['providerId']];
161
+        }
162
+
163
+        $result = $this->tryLegacyEndPoint(rtrim($remote, '/'), '/' . $id . '/reshare', $fields);
164
+        $status = json_decode($result['result'], true);
165
+
166
+        $httpRequestSuccessful = $result['success'];
167
+        $ocsCallSuccessful = $status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200;
168
+        $validToken = isset($status['ocs']['data']['token']) && is_string($status['ocs']['data']['token']);
169
+        $validRemoteId = isset($status['ocs']['data']['remoteId']);
170
+
171
+        if ($httpRequestSuccessful && $ocsCallSuccessful && $validToken && $validRemoteId) {
172
+            return [
173
+                $status['ocs']['data']['token'],
174
+                $status['ocs']['data']['remoteId']
175
+            ];
176
+        }
177
+
178
+        return false;
179
+    }
180
+
181
+    /**
182
+     * send server-to-server unshare to remote server
183
+     *
184
+     * @param string $remote url
185
+     * @param string $id share id
186
+     * @param string $token
187
+     * @return bool
188
+     */
189
+    public function sendRemoteUnShare($remote, $id, $token) {
190
+        $this->sendUpdateToRemote($remote, $id, $token, 'unshare');
191
+    }
192
+
193
+    /**
194
+     * send server-to-server unshare to remote server
195
+     *
196
+     * @param string $remote url
197
+     * @param string $id share id
198
+     * @param string $token
199
+     * @return bool
200
+     */
201
+    public function sendRevokeShare($remote, $id, $token) {
202
+        $this->sendUpdateToRemote($remote, $id, $token, 'reshare_undo');
203
+    }
204
+
205
+    /**
206
+     * send notification to remote server if the permissions was changed
207
+     *
208
+     * @param string $remote
209
+     * @param string $remoteId
210
+     * @param string $token
211
+     * @param int $permissions
212
+     * @return bool
213
+     */
214
+    public function sendPermissionChange($remote, $remoteId, $token, $permissions) {
215
+        $this->sendUpdateToRemote($remote, $remoteId, $token, 'permissions', ['permissions' => $permissions]);
216
+    }
217
+
218
+    /**
219
+     * forward accept reShare to remote server
220
+     *
221
+     * @param string $remote
222
+     * @param string $remoteId
223
+     * @param string $token
224
+     */
225
+    public function sendAcceptShare($remote, $remoteId, $token) {
226
+        $this->sendUpdateToRemote($remote, $remoteId, $token, 'accept');
227
+    }
228
+
229
+    /**
230
+     * forward decline reShare to remote server
231
+     *
232
+     * @param string $remote
233
+     * @param string $remoteId
234
+     * @param string $token
235
+     */
236
+    public function sendDeclineShare($remote, $remoteId, $token) {
237
+        $this->sendUpdateToRemote($remote, $remoteId, $token, 'decline');
238
+    }
239
+
240
+    /**
241
+     * inform remote server whether server-to-server share was accepted/declined
242
+     *
243
+     * @param string $remote
244
+     * @param string $token
245
+     * @param string $remoteId Share id on the remote host
246
+     * @param string $action possible actions: accept, decline, unshare, revoke, permissions
247
+     * @param array $data
248
+     * @param int $try
249
+     * @return boolean
250
+     */
251
+    public function sendUpdateToRemote($remote, $remoteId, $token, $action, $data = [], $try = 0) {
252
+        $fields = [
253
+            'token' => $token,
254
+            'remoteId' => $remoteId
255
+        ];
256
+        foreach ($data as $key => $value) {
257
+            $fields[$key] = $value;
258
+        }
259
+
260
+        $result = $this->tryHttpPostToShareEndpoint(rtrim($remote, '/'), '/' . $remoteId . '/' . $action, $fields, $action);
261
+        $status = json_decode($result['result'], true);
262
+
263
+        if ($result['success'] &&
264
+            ($status['ocs']['meta']['statuscode'] === 100 ||
265
+                $status['ocs']['meta']['statuscode'] === 200
266
+            )
267
+        ) {
268
+            return true;
269
+        } elseif ($try === 0) {
270
+            // only add new job on first try
271
+            $this->jobList->add('OCA\FederatedFileSharing\BackgroundJob\RetryJob',
272
+                [
273
+                    'remote' => $remote,
274
+                    'remoteId' => $remoteId,
275
+                    'token' => $token,
276
+                    'action' => $action,
277
+                    'data' => json_encode($data),
278
+                    'try' => $try,
279
+                    'lastRun' => $this->getTimestamp()
280
+                ]
281
+            );
282
+        }
283
+
284
+        return false;
285
+    }
286
+
287
+
288
+    /**
289
+     * return current timestamp
290
+     *
291
+     * @return int
292
+     */
293
+    protected function getTimestamp() {
294
+        return time();
295
+    }
296
+
297
+    /**
298
+     * try http post with the given protocol, if no protocol is given we pick
299
+     * the secure one (https)
300
+     *
301
+     * @param string $remoteDomain
302
+     * @param string $urlSuffix
303
+     * @param array $fields post parameters
304
+     * @param string $action define the action (possible values: share, reshare, accept, decline, unshare, revoke, permissions)
305
+     * @return array
306
+     * @throws \Exception
307
+     */
308
+    protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields, $action = "share") {
309
+        if ($this->addressHandler->urlContainProtocol($remoteDomain) === false) {
310
+            $remoteDomain = 'https://' . $remoteDomain;
311
+        }
312
+
313
+        $result = [
314
+            'success' => false,
315
+            'result' => '',
316
+        ];
317
+
318
+        // if possible we use the new OCM API
319
+        $ocmResult = $this->tryOCMEndPoint($remoteDomain, $fields, $action);
320
+        if (is_array($ocmResult)) {
321
+            $result['success'] = true;
322
+            $result['result'] = json_encode([
323
+                'ocs' => ['meta' => ['statuscode' => 200]]]);
324
+            return $result;
325
+        }
326
+
327
+        return $this->tryLegacyEndPoint($remoteDomain, $urlSuffix, $fields);
328
+    }
329
+
330
+    /**
331
+     * try old federated sharing API if the OCM api doesn't work
332
+     *
333
+     * @param $remoteDomain
334
+     * @param $urlSuffix
335
+     * @param array $fields
336
+     * @return mixed
337
+     * @throws \Exception
338
+     */
339
+    protected function tryLegacyEndPoint($remoteDomain, $urlSuffix, array $fields) {
340
+        $result = [
341
+            'success' => false,
342
+            'result' => '',
343
+        ];
344
+
345
+        // Fall back to old API
346
+        $client = $this->httpClientService->newClient();
347
+        $federationEndpoints = $this->discoveryService->discover($remoteDomain, 'FEDERATED_SHARING');
348
+        $endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
349
+        try {
350
+            $response = $client->post($remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, [
351
+                'body' => $fields,
352
+                'timeout' => 10,
353
+                'connect_timeout' => 10,
354
+            ]);
355
+            $result['result'] = $response->getBody();
356
+            $result['success'] = true;
357
+        } catch (\Exception $e) {
358
+            // if flat re-sharing is not supported by the remote server
359
+            // we re-throw the exception and fall back to the old behaviour.
360
+            // (flat re-shares has been introduced in Nextcloud 9.1)
361
+            if ($e->getCode() === Http::STATUS_INTERNAL_SERVER_ERROR) {
362
+                throw $e;
363
+            }
364
+        }
365
+
366
+        return $result;
367
+    }
368
+
369
+    /**
370
+     * send action regarding federated sharing to the remote server using the OCM API
371
+     *
372
+     * @param $remoteDomain
373
+     * @param $fields
374
+     * @param $action
375
+     *
376
+     * @return bool
377
+     */
378
+    protected function tryOCMEndPoint($remoteDomain, $fields, $action) {
379
+        switch ($action) {
380
+            case 'share':
381
+                $share = $this->cloudFederationFactory->getCloudFederationShare(
382
+                    $fields['shareWith'] . '@' . $remoteDomain,
383
+                    $fields['name'],
384
+                    '',
385
+                    $fields['remoteId'],
386
+                    $fields['ownerFederatedId'],
387
+                    $fields['owner'],
388
+                    $fields['sharedByFederatedId'],
389
+                    $fields['sharedBy'],
390
+                    $fields['token'],
391
+                    $fields['shareType'],
392
+                    'file'
393
+                );
394
+                return $this->federationProviderManager->sendShare($share);
395
+            case 'reshare':
396
+                // ask owner to reshare a file
397
+                $notification = $this->cloudFederationFactory->getCloudFederationNotification();
398
+                $notification->setMessage('REQUEST_RESHARE',
399
+                    'file',
400
+                    $fields['remoteId'],
401
+                    [
402
+                        'sharedSecret' => $fields['token'],
403
+                        'shareWith' => $fields['shareWith'],
404
+                        'senderId' => $fields['localId'],
405
+                        'shareType' => $fields['shareType'],
406
+                        'message' => 'Ask owner to reshare the file'
407
+                    ]
408
+                );
409
+                return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
410
+            case 'unshare':
411
+                //owner unshares the file from the recipient again
412
+                $notification = $this->cloudFederationFactory->getCloudFederationNotification();
413
+                $notification->setMessage('SHARE_UNSHARED',
414
+                    'file',
415
+                    $fields['remoteId'],
416
+                    [
417
+                        'sharedSecret' => $fields['token'],
418
+                        'messgage' => 'file is no longer shared with you'
419
+                    ]
420
+                );
421
+                return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
422
+            case 'reshare_undo':
423
+                // if a reshare was unshared we send the information to the initiator/owner
424
+                $notification = $this->cloudFederationFactory->getCloudFederationNotification();
425
+                $notification->setMessage('RESHARE_UNDO',
426
+                    'file',
427
+                    $fields['remoteId'],
428
+                    [
429
+                        'sharedSecret' => $fields['token'],
430
+                        'message' => 'reshare was revoked'
431
+                    ]
432
+                );
433
+                return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
434
+        }
435
+
436
+        return false;
437
+    }
438 438
 }
Please login to merge, or discard this patch.
apps/settings/lib/Controller/CheckSetupController.php 1 patch
Indentation   +671 added lines, -671 removed lines patch added patch discarded remove patch
@@ -76,295 +76,295 @@  discard block
 block discarded – undo
76 76
 use Symfony\Component\EventDispatcher\GenericEvent;
77 77
 
78 78
 class CheckSetupController extends Controller {
79
-	/** @var IConfig */
80
-	private $config;
81
-	/** @var IClientService */
82
-	private $clientService;
83
-	/** @var IURLGenerator */
84
-	private $urlGenerator;
85
-	/** @var IL10N */
86
-	private $l10n;
87
-	/** @var Checker */
88
-	private $checker;
89
-	/** @var ILogger */
90
-	private $logger;
91
-	/** @var EventDispatcherInterface */
92
-	private $dispatcher;
93
-	/** @var IDBConnection|Connection */
94
-	private $db;
95
-	/** @var ILockingProvider */
96
-	private $lockingProvider;
97
-	/** @var IDateTimeFormatter */
98
-	private $dateTimeFormatter;
99
-	/** @var MemoryInfo */
100
-	private $memoryInfo;
101
-	/** @var ISecureRandom */
102
-	private $secureRandom;
103
-	/** @var IniGetWrapper */
104
-	private $iniGetWrapper;
105
-
106
-	public function __construct($AppName,
107
-								IRequest $request,
108
-								IConfig $config,
109
-								IClientService $clientService,
110
-								IURLGenerator $urlGenerator,
111
-								IL10N $l10n,
112
-								Checker $checker,
113
-								ILogger $logger,
114
-								EventDispatcherInterface $dispatcher,
115
-								IDBConnection $db,
116
-								ILockingProvider $lockingProvider,
117
-								IDateTimeFormatter $dateTimeFormatter,
118
-								MemoryInfo $memoryInfo,
119
-								ISecureRandom $secureRandom,
120
-								IniGetWrapper $iniGetWrapper) {
121
-		parent::__construct($AppName, $request);
122
-		$this->config = $config;
123
-		$this->clientService = $clientService;
124
-		$this->urlGenerator = $urlGenerator;
125
-		$this->l10n = $l10n;
126
-		$this->checker = $checker;
127
-		$this->logger = $logger;
128
-		$this->dispatcher = $dispatcher;
129
-		$this->db = $db;
130
-		$this->lockingProvider = $lockingProvider;
131
-		$this->dateTimeFormatter = $dateTimeFormatter;
132
-		$this->memoryInfo = $memoryInfo;
133
-		$this->secureRandom = $secureRandom;
134
-		$this->iniGetWrapper = $iniGetWrapper;
135
-	}
136
-
137
-	/**
138
-	 * Checks if the server can connect to the internet using HTTPS and HTTP
139
-	 * @return bool
140
-	 */
141
-	private function hasInternetConnectivityProblems(): bool {
142
-		if ($this->config->getSystemValue('has_internet_connection', true) === false) {
143
-			return false;
144
-		}
145
-
146
-		$siteArray = $this->config->getSystemValue('connectivity_check_domains', [
147
-			'www.nextcloud.com', 'www.startpage.com', 'www.eff.org', 'www.edri.org'
148
-		]);
149
-
150
-		foreach ($siteArray as $site) {
151
-			if ($this->isSiteReachable($site)) {
152
-				return false;
153
-			}
154
-		}
155
-		return true;
156
-	}
157
-
158
-	/**
159
-	 * Checks if the Nextcloud server can connect to a specific URL using both HTTPS and HTTP
160
-	 * @return bool
161
-	 */
162
-	private function isSiteReachable($sitename) {
163
-		$httpSiteName = 'http://' . $sitename . '/';
164
-		$httpsSiteName = 'https://' . $sitename . '/';
165
-
166
-		try {
167
-			$client = $this->clientService->newClient();
168
-			$client->get($httpSiteName);
169
-			$client->get($httpsSiteName);
170
-		} catch (\Exception $e) {
171
-			$this->logger->logException($e, ['app' => 'internet_connection_check']);
172
-			return false;
173
-		}
174
-		return true;
175
-	}
176
-
177
-	/**
178
-	 * Checks whether a local memcache is installed or not
179
-	 * @return bool
180
-	 */
181
-	private function isMemcacheConfigured() {
182
-		return $this->config->getSystemValue('memcache.local', null) !== null;
183
-	}
184
-
185
-	/**
186
-	 * Whether PHP can generate "secure" pseudorandom integers
187
-	 *
188
-	 * @return bool
189
-	 */
190
-	private function isRandomnessSecure() {
191
-		try {
192
-			$this->secureRandom->generate(1);
193
-		} catch (\Exception $ex) {
194
-			return false;
195
-		}
196
-		return true;
197
-	}
198
-
199
-	/**
200
-	 * Public for the sake of unit-testing
201
-	 *
202
-	 * @return array
203
-	 */
204
-	protected function getCurlVersion() {
205
-		return curl_version();
206
-	}
207
-
208
-	/**
209
-	 * Check if the used  SSL lib is outdated. Older OpenSSL and NSS versions do
210
-	 * have multiple bugs which likely lead to problems in combination with
211
-	 * functionality required by ownCloud such as SNI.
212
-	 *
213
-	 * @link https://github.com/owncloud/core/issues/17446#issuecomment-122877546
214
-	 * @link https://bugzilla.redhat.com/show_bug.cgi?id=1241172
215
-	 * @return string
216
-	 */
217
-	private function isUsedTlsLibOutdated() {
218
-		// Don't run check when:
219
-		// 1. Server has `has_internet_connection` set to false
220
-		// 2. AppStore AND S2S is disabled
221
-		if (!$this->config->getSystemValue('has_internet_connection', true)) {
222
-			return '';
223
-		}
224
-		if (!$this->config->getSystemValue('appstoreenabled', true)
225
-			&& $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'no'
226
-			&& $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'no') {
227
-			return '';
228
-		}
229
-
230
-		$versionString = $this->getCurlVersion();
231
-		if (isset($versionString['ssl_version'])) {
232
-			$versionString = $versionString['ssl_version'];
233
-		} else {
234
-			return '';
235
-		}
236
-
237
-		$features = (string)$this->l10n->t('installing and updating apps via the app store or Federated Cloud Sharing');
238
-		if (!$this->config->getSystemValue('appstoreenabled', true)) {
239
-			$features = (string)$this->l10n->t('Federated Cloud Sharing');
240
-		}
241
-
242
-		// Check if at least OpenSSL after 1.01d or 1.0.2b
243
-		if (strpos($versionString, 'OpenSSL/') === 0) {
244
-			$majorVersion = substr($versionString, 8, 5);
245
-			$patchRelease = substr($versionString, 13, 6);
246
-
247
-			if (($majorVersion === '1.0.1' && ord($patchRelease) < ord('d')) ||
248
-				($majorVersion === '1.0.2' && ord($patchRelease) < ord('b'))) {
249
-				return $this->l10n->t('cURL is using an outdated %1$s version (%2$s). Please update your operating system or features such as %3$s will not work reliably.', ['OpenSSL', $versionString, $features]);
250
-			}
251
-		}
252
-
253
-		// Check if NSS and perform heuristic check
254
-		if (strpos($versionString, 'NSS/') === 0) {
255
-			try {
256
-				$firstClient = $this->clientService->newClient();
257
-				$firstClient->get('https://nextcloud.com/');
258
-
259
-				$secondClient = $this->clientService->newClient();
260
-				$secondClient->get('https://nextcloud.com/');
261
-			} catch (ClientException $e) {
262
-				if ($e->getResponse()->getStatusCode() === 400) {
263
-					return $this->l10n->t('cURL is using an outdated %1$s version (%2$s). Please update your operating system or features such as %3$s will not work reliably.', ['NSS', $versionString, $features]);
264
-				}
265
-			} catch (\Exception $e) {
266
-				$this->logger->logException($e, ['app' => 'settings', 'level' => \OCP\ILogger::WARN]);
267
-				return $this->l10n->t('Could not determine if TLS version of cURL is outdated or not because an error happened during the HTTPS request against https://nextcloud.com. Please check the nextcloud log file for more details.');
268
-			}
269
-		}
270
-
271
-		return '';
272
-	}
273
-
274
-	/**
275
-	 * Whether the version is outdated
276
-	 *
277
-	 * @return bool
278
-	 */
279
-	protected function isPhpOutdated(): bool {
280
-		return PHP_VERSION_ID < 70300;
281
-	}
282
-
283
-	/**
284
-	 * Whether the php version is still supported (at time of release)
285
-	 * according to: https://secure.php.net/supported-versions.php
286
-	 *
287
-	 * @return array
288
-	 */
289
-	private function isPhpSupported(): array {
290
-		return ['eol' => $this->isPhpOutdated(), 'version' => PHP_VERSION];
291
-	}
292
-
293
-	/**
294
-	 * Check if the reverse proxy configuration is working as expected
295
-	 *
296
-	 * @return bool
297
-	 */
298
-	private function forwardedForHeadersWorking() {
299
-		$trustedProxies = $this->config->getSystemValue('trusted_proxies', []);
300
-		$remoteAddress = $this->request->getHeader('REMOTE_ADDR');
301
-
302
-		if (empty($trustedProxies) && $this->request->getHeader('X-Forwarded-Host') !== '') {
303
-			return false;
304
-		}
305
-
306
-		if (\is_array($trustedProxies) && \in_array($remoteAddress, $trustedProxies, true)) {
307
-			return $remoteAddress !== $this->request->getRemoteAddress();
308
-		}
309
-
310
-		// either not enabled or working correctly
311
-		return true;
312
-	}
313
-
314
-	/**
315
-	 * Checks if the correct memcache module for PHP is installed. Only
316
-	 * fails if memcached is configured and the working module is not installed.
317
-	 *
318
-	 * @return bool
319
-	 */
320
-	private function isCorrectMemcachedPHPModuleInstalled() {
321
-		if ($this->config->getSystemValue('memcache.distributed', null) !== '\OC\Memcache\Memcached') {
322
-			return true;
323
-		}
324
-
325
-		// there are two different memcached modules for PHP
326
-		// we only support memcached and not memcache
327
-		// https://code.google.com/p/memcached/wiki/PHPClientComparison
328
-		return !(!extension_loaded('memcached') && extension_loaded('memcache'));
329
-	}
330
-
331
-	/**
332
-	 * Checks if set_time_limit is not disabled.
333
-	 *
334
-	 * @return bool
335
-	 */
336
-	private function isSettimelimitAvailable() {
337
-		if (function_exists('set_time_limit')
338
-			&& strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
339
-			return true;
340
-		}
341
-
342
-		return false;
343
-	}
344
-
345
-	/**
346
-	 * @return RedirectResponse
347
-	 */
348
-	public function rescanFailedIntegrityCheck() {
349
-		$this->checker->runInstanceVerification();
350
-		return new RedirectResponse(
351
-			$this->urlGenerator->linkToRoute('settings.AdminSettings.index', ['section' => 'overview'])
352
-		);
353
-	}
354
-
355
-	/**
356
-	 * @NoCSRFRequired
357
-	 * @return DataResponse
358
-	 */
359
-	public function getFailedIntegrityCheckFiles() {
360
-		if (!$this->checker->isCodeCheckEnforced()) {
361
-			return new DataDisplayResponse('Integrity checker has been disabled. Integrity cannot be verified.');
362
-		}
363
-
364
-		$completeResults = $this->checker->getResults();
365
-
366
-		if (!empty($completeResults)) {
367
-			$formattedTextResponse = 'Technical information
79
+    /** @var IConfig */
80
+    private $config;
81
+    /** @var IClientService */
82
+    private $clientService;
83
+    /** @var IURLGenerator */
84
+    private $urlGenerator;
85
+    /** @var IL10N */
86
+    private $l10n;
87
+    /** @var Checker */
88
+    private $checker;
89
+    /** @var ILogger */
90
+    private $logger;
91
+    /** @var EventDispatcherInterface */
92
+    private $dispatcher;
93
+    /** @var IDBConnection|Connection */
94
+    private $db;
95
+    /** @var ILockingProvider */
96
+    private $lockingProvider;
97
+    /** @var IDateTimeFormatter */
98
+    private $dateTimeFormatter;
99
+    /** @var MemoryInfo */
100
+    private $memoryInfo;
101
+    /** @var ISecureRandom */
102
+    private $secureRandom;
103
+    /** @var IniGetWrapper */
104
+    private $iniGetWrapper;
105
+
106
+    public function __construct($AppName,
107
+                                IRequest $request,
108
+                                IConfig $config,
109
+                                IClientService $clientService,
110
+                                IURLGenerator $urlGenerator,
111
+                                IL10N $l10n,
112
+                                Checker $checker,
113
+                                ILogger $logger,
114
+                                EventDispatcherInterface $dispatcher,
115
+                                IDBConnection $db,
116
+                                ILockingProvider $lockingProvider,
117
+                                IDateTimeFormatter $dateTimeFormatter,
118
+                                MemoryInfo $memoryInfo,
119
+                                ISecureRandom $secureRandom,
120
+                                IniGetWrapper $iniGetWrapper) {
121
+        parent::__construct($AppName, $request);
122
+        $this->config = $config;
123
+        $this->clientService = $clientService;
124
+        $this->urlGenerator = $urlGenerator;
125
+        $this->l10n = $l10n;
126
+        $this->checker = $checker;
127
+        $this->logger = $logger;
128
+        $this->dispatcher = $dispatcher;
129
+        $this->db = $db;
130
+        $this->lockingProvider = $lockingProvider;
131
+        $this->dateTimeFormatter = $dateTimeFormatter;
132
+        $this->memoryInfo = $memoryInfo;
133
+        $this->secureRandom = $secureRandom;
134
+        $this->iniGetWrapper = $iniGetWrapper;
135
+    }
136
+
137
+    /**
138
+     * Checks if the server can connect to the internet using HTTPS and HTTP
139
+     * @return bool
140
+     */
141
+    private function hasInternetConnectivityProblems(): bool {
142
+        if ($this->config->getSystemValue('has_internet_connection', true) === false) {
143
+            return false;
144
+        }
145
+
146
+        $siteArray = $this->config->getSystemValue('connectivity_check_domains', [
147
+            'www.nextcloud.com', 'www.startpage.com', 'www.eff.org', 'www.edri.org'
148
+        ]);
149
+
150
+        foreach ($siteArray as $site) {
151
+            if ($this->isSiteReachable($site)) {
152
+                return false;
153
+            }
154
+        }
155
+        return true;
156
+    }
157
+
158
+    /**
159
+     * Checks if the Nextcloud server can connect to a specific URL using both HTTPS and HTTP
160
+     * @return bool
161
+     */
162
+    private function isSiteReachable($sitename) {
163
+        $httpSiteName = 'http://' . $sitename . '/';
164
+        $httpsSiteName = 'https://' . $sitename . '/';
165
+
166
+        try {
167
+            $client = $this->clientService->newClient();
168
+            $client->get($httpSiteName);
169
+            $client->get($httpsSiteName);
170
+        } catch (\Exception $e) {
171
+            $this->logger->logException($e, ['app' => 'internet_connection_check']);
172
+            return false;
173
+        }
174
+        return true;
175
+    }
176
+
177
+    /**
178
+     * Checks whether a local memcache is installed or not
179
+     * @return bool
180
+     */
181
+    private function isMemcacheConfigured() {
182
+        return $this->config->getSystemValue('memcache.local', null) !== null;
183
+    }
184
+
185
+    /**
186
+     * Whether PHP can generate "secure" pseudorandom integers
187
+     *
188
+     * @return bool
189
+     */
190
+    private function isRandomnessSecure() {
191
+        try {
192
+            $this->secureRandom->generate(1);
193
+        } catch (\Exception $ex) {
194
+            return false;
195
+        }
196
+        return true;
197
+    }
198
+
199
+    /**
200
+     * Public for the sake of unit-testing
201
+     *
202
+     * @return array
203
+     */
204
+    protected function getCurlVersion() {
205
+        return curl_version();
206
+    }
207
+
208
+    /**
209
+     * Check if the used  SSL lib is outdated. Older OpenSSL and NSS versions do
210
+     * have multiple bugs which likely lead to problems in combination with
211
+     * functionality required by ownCloud such as SNI.
212
+     *
213
+     * @link https://github.com/owncloud/core/issues/17446#issuecomment-122877546
214
+     * @link https://bugzilla.redhat.com/show_bug.cgi?id=1241172
215
+     * @return string
216
+     */
217
+    private function isUsedTlsLibOutdated() {
218
+        // Don't run check when:
219
+        // 1. Server has `has_internet_connection` set to false
220
+        // 2. AppStore AND S2S is disabled
221
+        if (!$this->config->getSystemValue('has_internet_connection', true)) {
222
+            return '';
223
+        }
224
+        if (!$this->config->getSystemValue('appstoreenabled', true)
225
+            && $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'no'
226
+            && $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'no') {
227
+            return '';
228
+        }
229
+
230
+        $versionString = $this->getCurlVersion();
231
+        if (isset($versionString['ssl_version'])) {
232
+            $versionString = $versionString['ssl_version'];
233
+        } else {
234
+            return '';
235
+        }
236
+
237
+        $features = (string)$this->l10n->t('installing and updating apps via the app store or Federated Cloud Sharing');
238
+        if (!$this->config->getSystemValue('appstoreenabled', true)) {
239
+            $features = (string)$this->l10n->t('Federated Cloud Sharing');
240
+        }
241
+
242
+        // Check if at least OpenSSL after 1.01d or 1.0.2b
243
+        if (strpos($versionString, 'OpenSSL/') === 0) {
244
+            $majorVersion = substr($versionString, 8, 5);
245
+            $patchRelease = substr($versionString, 13, 6);
246
+
247
+            if (($majorVersion === '1.0.1' && ord($patchRelease) < ord('d')) ||
248
+                ($majorVersion === '1.0.2' && ord($patchRelease) < ord('b'))) {
249
+                return $this->l10n->t('cURL is using an outdated %1$s version (%2$s). Please update your operating system or features such as %3$s will not work reliably.', ['OpenSSL', $versionString, $features]);
250
+            }
251
+        }
252
+
253
+        // Check if NSS and perform heuristic check
254
+        if (strpos($versionString, 'NSS/') === 0) {
255
+            try {
256
+                $firstClient = $this->clientService->newClient();
257
+                $firstClient->get('https://nextcloud.com/');
258
+
259
+                $secondClient = $this->clientService->newClient();
260
+                $secondClient->get('https://nextcloud.com/');
261
+            } catch (ClientException $e) {
262
+                if ($e->getResponse()->getStatusCode() === 400) {
263
+                    return $this->l10n->t('cURL is using an outdated %1$s version (%2$s). Please update your operating system or features such as %3$s will not work reliably.', ['NSS', $versionString, $features]);
264
+                }
265
+            } catch (\Exception $e) {
266
+                $this->logger->logException($e, ['app' => 'settings', 'level' => \OCP\ILogger::WARN]);
267
+                return $this->l10n->t('Could not determine if TLS version of cURL is outdated or not because an error happened during the HTTPS request against https://nextcloud.com. Please check the nextcloud log file for more details.');
268
+            }
269
+        }
270
+
271
+        return '';
272
+    }
273
+
274
+    /**
275
+     * Whether the version is outdated
276
+     *
277
+     * @return bool
278
+     */
279
+    protected function isPhpOutdated(): bool {
280
+        return PHP_VERSION_ID < 70300;
281
+    }
282
+
283
+    /**
284
+     * Whether the php version is still supported (at time of release)
285
+     * according to: https://secure.php.net/supported-versions.php
286
+     *
287
+     * @return array
288
+     */
289
+    private function isPhpSupported(): array {
290
+        return ['eol' => $this->isPhpOutdated(), 'version' => PHP_VERSION];
291
+    }
292
+
293
+    /**
294
+     * Check if the reverse proxy configuration is working as expected
295
+     *
296
+     * @return bool
297
+     */
298
+    private function forwardedForHeadersWorking() {
299
+        $trustedProxies = $this->config->getSystemValue('trusted_proxies', []);
300
+        $remoteAddress = $this->request->getHeader('REMOTE_ADDR');
301
+
302
+        if (empty($trustedProxies) && $this->request->getHeader('X-Forwarded-Host') !== '') {
303
+            return false;
304
+        }
305
+
306
+        if (\is_array($trustedProxies) && \in_array($remoteAddress, $trustedProxies, true)) {
307
+            return $remoteAddress !== $this->request->getRemoteAddress();
308
+        }
309
+
310
+        // either not enabled or working correctly
311
+        return true;
312
+    }
313
+
314
+    /**
315
+     * Checks if the correct memcache module for PHP is installed. Only
316
+     * fails if memcached is configured and the working module is not installed.
317
+     *
318
+     * @return bool
319
+     */
320
+    private function isCorrectMemcachedPHPModuleInstalled() {
321
+        if ($this->config->getSystemValue('memcache.distributed', null) !== '\OC\Memcache\Memcached') {
322
+            return true;
323
+        }
324
+
325
+        // there are two different memcached modules for PHP
326
+        // we only support memcached and not memcache
327
+        // https://code.google.com/p/memcached/wiki/PHPClientComparison
328
+        return !(!extension_loaded('memcached') && extension_loaded('memcache'));
329
+    }
330
+
331
+    /**
332
+     * Checks if set_time_limit is not disabled.
333
+     *
334
+     * @return bool
335
+     */
336
+    private function isSettimelimitAvailable() {
337
+        if (function_exists('set_time_limit')
338
+            && strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
339
+            return true;
340
+        }
341
+
342
+        return false;
343
+    }
344
+
345
+    /**
346
+     * @return RedirectResponse
347
+     */
348
+    public function rescanFailedIntegrityCheck() {
349
+        $this->checker->runInstanceVerification();
350
+        return new RedirectResponse(
351
+            $this->urlGenerator->linkToRoute('settings.AdminSettings.index', ['section' => 'overview'])
352
+        );
353
+    }
354
+
355
+    /**
356
+     * @NoCSRFRequired
357
+     * @return DataResponse
358
+     */
359
+    public function getFailedIntegrityCheckFiles() {
360
+        if (!$this->checker->isCodeCheckEnforced()) {
361
+            return new DataDisplayResponse('Integrity checker has been disabled. Integrity cannot be verified.');
362
+        }
363
+
364
+        $completeResults = $this->checker->getResults();
365
+
366
+        if (!empty($completeResults)) {
367
+            $formattedTextResponse = 'Technical information
368 368
 =====================
369 369
 The following list covers which files have failed the integrity check. Please read
370 370
 the previous linked documentation to learn more about the errors and how to fix
@@ -373,389 +373,389 @@  discard block
 block discarded – undo
373 373
 Results
374 374
 =======
375 375
 ';
376
-			foreach ($completeResults as $context => $contextResult) {
377
-				$formattedTextResponse .= "- $context\n";
378
-
379
-				foreach ($contextResult as $category => $result) {
380
-					$formattedTextResponse .= "\t- $category\n";
381
-					if ($category !== 'EXCEPTION') {
382
-						foreach ($result as $key => $results) {
383
-							$formattedTextResponse .= "\t\t- $key\n";
384
-						}
385
-					} else {
386
-						foreach ($result as $key => $results) {
387
-							$formattedTextResponse .= "\t\t- $results\n";
388
-						}
389
-					}
390
-				}
391
-			}
392
-
393
-			$formattedTextResponse .= '
376
+            foreach ($completeResults as $context => $contextResult) {
377
+                $formattedTextResponse .= "- $context\n";
378
+
379
+                foreach ($contextResult as $category => $result) {
380
+                    $formattedTextResponse .= "\t- $category\n";
381
+                    if ($category !== 'EXCEPTION') {
382
+                        foreach ($result as $key => $results) {
383
+                            $formattedTextResponse .= "\t\t- $key\n";
384
+                        }
385
+                    } else {
386
+                        foreach ($result as $key => $results) {
387
+                            $formattedTextResponse .= "\t\t- $results\n";
388
+                        }
389
+                    }
390
+                }
391
+            }
392
+
393
+            $formattedTextResponse .= '
394 394
 Raw output
395 395
 ==========
396 396
 ';
397
-			$formattedTextResponse .= print_r($completeResults, true);
398
-		} else {
399
-			$formattedTextResponse = 'No errors have been found.';
400
-		}
401
-
402
-
403
-		$response = new DataDisplayResponse(
404
-			$formattedTextResponse,
405
-			Http::STATUS_OK,
406
-			[
407
-				'Content-Type' => 'text/plain',
408
-			]
409
-		);
410
-
411
-		return $response;
412
-	}
413
-
414
-	/**
415
-	 * Checks whether a PHP opcache is properly set up
416
-	 * @return bool
417
-	 */
418
-	protected function isOpcacheProperlySetup() {
419
-		if (!$this->iniGetWrapper->getBool('opcache.enable')) {
420
-			return false;
421
-		}
422
-
423
-		if (!$this->iniGetWrapper->getBool('opcache.save_comments')) {
424
-			return false;
425
-		}
426
-
427
-		if ($this->iniGetWrapper->getNumeric('opcache.max_accelerated_files') < 10000) {
428
-			return false;
429
-		}
430
-
431
-		if ($this->iniGetWrapper->getNumeric('opcache.memory_consumption') < 128) {
432
-			return false;
433
-		}
434
-
435
-		if ($this->iniGetWrapper->getNumeric('opcache.interned_strings_buffer') < 8) {
436
-			return false;
437
-		}
438
-
439
-		return true;
440
-	}
441
-
442
-	/**
443
-	 * Check if the required FreeType functions are present
444
-	 * @return bool
445
-	 */
446
-	protected function hasFreeTypeSupport() {
447
-		return function_exists('imagettfbbox') && function_exists('imagettftext');
448
-	}
449
-
450
-	protected function hasMissingIndexes(): array {
451
-		$indexInfo = new MissingIndexInformation();
452
-		// Dispatch event so apps can also hint for pending index updates if needed
453
-		$event = new GenericEvent($indexInfo);
454
-		$this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_INDEXES_EVENT, $event);
455
-
456
-		return $indexInfo->getListOfMissingIndexes();
457
-	}
458
-
459
-	protected function hasMissingPrimaryKeys(): array {
460
-		$info = new MissingPrimaryKeyInformation();
461
-		// Dispatch event so apps can also hint for pending index updates if needed
462
-		$event = new GenericEvent($info);
463
-		$this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_PRIMARY_KEYS_EVENT, $event);
464
-
465
-		return $info->getListOfMissingPrimaryKeys();
466
-	}
467
-
468
-	protected function hasMissingColumns(): array {
469
-		$indexInfo = new MissingColumnInformation();
470
-		// Dispatch event so apps can also hint for pending index updates if needed
471
-		$event = new GenericEvent($indexInfo);
472
-		$this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_COLUMNS_EVENT, $event);
473
-
474
-		return $indexInfo->getListOfMissingColumns();
475
-	}
476
-
477
-	protected function isSqliteUsed() {
478
-		return strpos($this->config->getSystemValue('dbtype'), 'sqlite') !== false;
479
-	}
480
-
481
-	protected function isReadOnlyConfig(): bool {
482
-		return \OC_Helper::isReadOnlyConfigEnabled();
483
-	}
484
-
485
-	protected function hasValidTransactionIsolationLevel(): bool {
486
-		try {
487
-			if ($this->db->getDatabasePlatform() instanceof SqlitePlatform) {
488
-				return true;
489
-			}
490
-
491
-			return $this->db->getTransactionIsolation() === Connection::TRANSACTION_READ_COMMITTED;
492
-		} catch (DBALException $e) {
493
-			// ignore
494
-		}
495
-
496
-		return true;
497
-	}
498
-
499
-	protected function hasFileinfoInstalled(): bool {
500
-		return \OC_Util::fileInfoLoaded();
501
-	}
502
-
503
-	protected function hasWorkingFileLocking(): bool {
504
-		return !($this->lockingProvider instanceof NoopLockingProvider);
505
-	}
506
-
507
-	protected function getSuggestedOverwriteCliURL(): string {
508
-		$suggestedOverwriteCliUrl = '';
509
-		if ($this->config->getSystemValue('overwrite.cli.url', '') === '') {
510
-			$suggestedOverwriteCliUrl = $this->request->getServerProtocol() . '://' . $this->request->getInsecureServerHost() . \OC::$WEBROOT;
511
-			if (!$this->config->getSystemValue('config_is_read_only', false)) {
512
-				// Set the overwrite URL when it was not set yet.
513
-				$this->config->setSystemValue('overwrite.cli.url', $suggestedOverwriteCliUrl);
514
-				$suggestedOverwriteCliUrl = '';
515
-			}
516
-		}
517
-		return $suggestedOverwriteCliUrl;
518
-	}
519
-
520
-	protected function getLastCronInfo(): array {
521
-		$lastCronRun = $this->config->getAppValue('core', 'lastcron', 0);
522
-		return [
523
-			'diffInSeconds' => time() - $lastCronRun,
524
-			'relativeTime' => $this->dateTimeFormatter->formatTimeSpan($lastCronRun),
525
-			'backgroundJobsUrl' => $this->urlGenerator->linkToRoute('settings.AdminSettings.index', ['section' => 'server']) . '#backgroundjobs',
526
-		];
527
-	}
528
-
529
-	protected function getCronErrors() {
530
-		$errors = json_decode($this->config->getAppValue('core', 'cronErrors', ''), true);
531
-
532
-		if (is_array($errors)) {
533
-			return $errors;
534
-		}
535
-
536
-		return [];
537
-	}
538
-
539
-	protected function hasOpcacheLoaded(): bool {
540
-		return extension_loaded('Zend OPcache');
541
-	}
542
-
543
-	/**
544
-	 * Iterates through the configured app roots and
545
-	 * tests if the subdirectories are owned by the same user than the current user.
546
-	 *
547
-	 * @return array
548
-	 */
549
-	protected function getAppDirsWithDifferentOwner(): array {
550
-		$currentUser = posix_getuid();
551
-		$appDirsWithDifferentOwner = [[]];
552
-
553
-		foreach (OC::$APPSROOTS as $appRoot) {
554
-			if ($appRoot['writable'] === true) {
555
-				$appDirsWithDifferentOwner[] = $this->getAppDirsWithDifferentOwnerForAppRoot($currentUser, $appRoot);
556
-			}
557
-		}
558
-
559
-		$appDirsWithDifferentOwner = array_merge(...$appDirsWithDifferentOwner);
560
-		sort($appDirsWithDifferentOwner);
561
-
562
-		return $appDirsWithDifferentOwner;
563
-	}
564
-
565
-	/**
566
-	 * Tests if the directories for one apps directory are writable by the current user.
567
-	 *
568
-	 * @param int $currentUser The current user
569
-	 * @param array $appRoot The app root config
570
-	 * @return string[] The none writable directory paths inside the app root
571
-	 */
572
-	private function getAppDirsWithDifferentOwnerForAppRoot(int $currentUser, array $appRoot): array {
573
-		$appDirsWithDifferentOwner = [];
574
-		$appsPath = $appRoot['path'];
575
-		$appsDir = new DirectoryIterator($appRoot['path']);
576
-
577
-		foreach ($appsDir as $fileInfo) {
578
-			if ($fileInfo->isDir() && !$fileInfo->isDot()) {
579
-				$absAppPath = $appsPath . DIRECTORY_SEPARATOR . $fileInfo->getFilename();
580
-				$appDirUser = fileowner($absAppPath);
581
-				if ($appDirUser !== $currentUser) {
582
-					$appDirsWithDifferentOwner[] = $absAppPath;
583
-				}
584
-			}
585
-		}
586
-
587
-		return $appDirsWithDifferentOwner;
588
-	}
589
-
590
-	/**
591
-	 * Checks for potential PHP modules that would improve the instance
592
-	 *
593
-	 * @return string[] A list of PHP modules that is recommended
594
-	 */
595
-	protected function hasRecommendedPHPModules(): array {
596
-		$recommendedPHPModules = [];
597
-
598
-		if (!extension_loaded('intl')) {
599
-			$recommendedPHPModules[] = 'intl';
600
-		}
601
-
602
-		if (!extension_loaded('bcmath')) {
603
-			$recommendedPHPModules[] = 'bcmath';
604
-		}
605
-
606
-		if (!extension_loaded('gmp')) {
607
-			$recommendedPHPModules[] = 'gmp';
608
-		}
609
-
610
-		if ($this->config->getAppValue('theming', 'enabled', 'no') === 'yes') {
611
-			if (!extension_loaded('imagick')) {
612
-				$recommendedPHPModules[] = 'imagick';
613
-			}
614
-		}
615
-
616
-		return $recommendedPHPModules;
617
-	}
618
-
619
-	protected function isMysqlUsedWithoutUTF8MB4(): bool {
620
-		return ($this->config->getSystemValue('dbtype', 'sqlite') === 'mysql') && ($this->config->getSystemValue('mysql.utf8mb4', false) === false);
621
-	}
622
-
623
-	protected function hasBigIntConversionPendingColumns(): array {
624
-		// copy of ConvertFilecacheBigInt::getColumnsByTable()
625
-		$tables = [
626
-			'activity' => ['activity_id', 'object_id'],
627
-			'activity_mq' => ['mail_id'],
628
-			'authtoken' => ['id'],
629
-			'bruteforce_attempts' => ['id'],
630
-			'federated_reshares' => ['share_id'],
631
-			'filecache' => ['fileid', 'storage', 'parent', 'mimetype', 'mimepart', 'mtime', 'storage_mtime'],
632
-			'filecache_extended' => ['fileid'],
633
-			'file_locks' => ['id'],
634
-			'jobs' => ['id'],
635
-			'mimetypes' => ['id'],
636
-			'mounts' => ['id', 'storage_id', 'root_id', 'mount_id'],
637
-			'share_external' => ['id', 'parent'],
638
-			'storages' => ['numeric_id'],
639
-		];
640
-
641
-		$schema = new SchemaWrapper($this->db);
642
-		$isSqlite = $this->db->getDatabasePlatform() instanceof SqlitePlatform;
643
-		$pendingColumns = [];
644
-
645
-		foreach ($tables as $tableName => $columns) {
646
-			if (!$schema->hasTable($tableName)) {
647
-				continue;
648
-			}
649
-
650
-			$table = $schema->getTable($tableName);
651
-			foreach ($columns as $columnName) {
652
-				$column = $table->getColumn($columnName);
653
-				$isAutoIncrement = $column->getAutoincrement();
654
-				$isAutoIncrementOnSqlite = $isSqlite && $isAutoIncrement;
655
-				if ($column->getType()->getName() !== Types::BIGINT && !$isAutoIncrementOnSqlite) {
656
-					$pendingColumns[] = $tableName . '.' . $columnName;
657
-				}
658
-			}
659
-		}
660
-
661
-		return $pendingColumns;
662
-	}
663
-
664
-	protected function isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed(): bool {
665
-		$objectStore = $this->config->getSystemValue('objectstore', null);
666
-		$objectStoreMultibucket = $this->config->getSystemValue('objectstore_multibucket', null);
667
-
668
-		if (!isset($objectStoreMultibucket) && !isset($objectStore)) {
669
-			return true;
670
-		}
671
-
672
-		if (isset($objectStoreMultibucket['class']) && $objectStoreMultibucket['class'] !== 'OC\\Files\\ObjectStore\\S3') {
673
-			return true;
674
-		}
675
-
676
-		if (isset($objectStore['class']) && $objectStore['class'] !== 'OC\\Files\\ObjectStore\\S3') {
677
-			return true;
678
-		}
679
-
680
-		$tempPath = sys_get_temp_dir();
681
-		if (!is_dir($tempPath)) {
682
-			$this->logger->error('Error while checking the temporary PHP path - it was not properly set to a directory. value: ' . $tempPath);
683
-			return false;
684
-		}
685
-		$freeSpaceInTemp = disk_free_space($tempPath);
686
-		if ($freeSpaceInTemp === false) {
687
-			$this->logger->error('Error while checking the available disk space of temporary PHP path - no free disk space returned. temporary path: ' . $tempPath);
688
-			return false;
689
-		}
690
-
691
-		$freeSpaceInTempInGB = $freeSpaceInTemp / 1024 / 1024 / 1024;
692
-		if ($freeSpaceInTempInGB > 50) {
693
-			return true;
694
-		}
695
-
696
-		$this->logger->warning('Checking the available space in the temporary path resulted in ' . round($freeSpaceInTempInGB, 1) . ' GB instead of the recommended 50GB. Path: ' . $tempPath);
697
-		return false;
698
-	}
699
-
700
-	protected function imageMagickLacksSVGSupport(): bool {
701
-		return extension_loaded('imagick') && count(\Imagick::queryFormats('SVG')) === 0;
702
-	}
703
-
704
-	/**
705
-	 * @return DataResponse
706
-	 */
707
-	public function check() {
708
-		$phpDefaultCharset = new PhpDefaultCharset();
709
-		$phpOutputBuffering = new PhpOutputBuffering();
710
-		$legacySSEKeyFormat = new LegacySSEKeyFormat($this->l10n, $this->config, $this->urlGenerator);
711
-		$checkUserCertificates = new CheckUserCertificates($this->l10n, $this->config, $this->urlGenerator);
712
-
713
-		return new DataResponse(
714
-			[
715
-				'isGetenvServerWorking' => !empty(getenv('PATH')),
716
-				'isReadOnlyConfig' => $this->isReadOnlyConfig(),
717
-				'hasValidTransactionIsolationLevel' => $this->hasValidTransactionIsolationLevel(),
718
-				'hasFileinfoInstalled' => $this->hasFileinfoInstalled(),
719
-				'hasWorkingFileLocking' => $this->hasWorkingFileLocking(),
720
-				'suggestedOverwriteCliURL' => $this->getSuggestedOverwriteCliURL(),
721
-				'cronInfo' => $this->getLastCronInfo(),
722
-				'cronErrors' => $this->getCronErrors(),
723
-				'serverHasInternetConnectionProblems' => $this->hasInternetConnectivityProblems(),
724
-				'isMemcacheConfigured' => $this->isMemcacheConfigured(),
725
-				'memcacheDocs' => $this->urlGenerator->linkToDocs('admin-performance'),
726
-				'isRandomnessSecure' => $this->isRandomnessSecure(),
727
-				'securityDocs' => $this->urlGenerator->linkToDocs('admin-security'),
728
-				'isUsedTlsLibOutdated' => $this->isUsedTlsLibOutdated(),
729
-				'phpSupported' => $this->isPhpSupported(),
730
-				'forwardedForHeadersWorking' => $this->forwardedForHeadersWorking(),
731
-				'reverseProxyDocs' => $this->urlGenerator->linkToDocs('admin-reverse-proxy'),
732
-				'isCorrectMemcachedPHPModuleInstalled' => $this->isCorrectMemcachedPHPModuleInstalled(),
733
-				'hasPassedCodeIntegrityCheck' => $this->checker->hasPassedCheck(),
734
-				'codeIntegrityCheckerDocumentation' => $this->urlGenerator->linkToDocs('admin-code-integrity'),
735
-				'isOpcacheProperlySetup' => $this->isOpcacheProperlySetup(),
736
-				'hasOpcacheLoaded' => $this->hasOpcacheLoaded(),
737
-				'phpOpcacheDocumentation' => $this->urlGenerator->linkToDocs('admin-php-opcache'),
738
-				'isSettimelimitAvailable' => $this->isSettimelimitAvailable(),
739
-				'hasFreeTypeSupport' => $this->hasFreeTypeSupport(),
740
-				'missingPrimaryKeys' => $this->hasMissingPrimaryKeys(),
741
-				'missingIndexes' => $this->hasMissingIndexes(),
742
-				'missingColumns' => $this->hasMissingColumns(),
743
-				'isSqliteUsed' => $this->isSqliteUsed(),
744
-				'databaseConversionDocumentation' => $this->urlGenerator->linkToDocs('admin-db-conversion'),
745
-				'isMemoryLimitSufficient' => $this->memoryInfo->isMemoryLimitSufficient(),
746
-				'appDirsWithDifferentOwner' => $this->getAppDirsWithDifferentOwner(),
747
-				'recommendedPHPModules' => $this->hasRecommendedPHPModules(),
748
-				'pendingBigIntConversionColumns' => $this->hasBigIntConversionPendingColumns(),
749
-				'isMysqlUsedWithoutUTF8MB4' => $this->isMysqlUsedWithoutUTF8MB4(),
750
-				'isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed' => $this->isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed(),
751
-				'reverseProxyGeneratedURL' => $this->urlGenerator->getAbsoluteURL('index.php'),
752
-				'imageMagickLacksSVGSupport' => $this->imageMagickLacksSVGSupport(),
753
-				PhpDefaultCharset::class => ['pass' => $phpDefaultCharset->run(), 'description' => $phpDefaultCharset->description(), 'severity' => $phpDefaultCharset->severity()],
754
-				PhpOutputBuffering::class => ['pass' => $phpOutputBuffering->run(), 'description' => $phpOutputBuffering->description(), 'severity' => $phpOutputBuffering->severity()],
755
-				LegacySSEKeyFormat::class => ['pass' => $legacySSEKeyFormat->run(), 'description' => $legacySSEKeyFormat->description(), 'severity' => $legacySSEKeyFormat->severity(), 'linkToDocumentation' => $legacySSEKeyFormat->linkToDocumentation()],
756
-				CheckUserCertificates::class => ['pass' => $checkUserCertificates->run(), 'description' => $checkUserCertificates->description(), 'severity' => $checkUserCertificates->severity(), 'elements' => $checkUserCertificates->elements()],
757
-				'isDefaultPhoneRegionSet' => $this->config->getSystemValueString('default_phone_region', '') !== '',
758
-			]
759
-		);
760
-	}
397
+            $formattedTextResponse .= print_r($completeResults, true);
398
+        } else {
399
+            $formattedTextResponse = 'No errors have been found.';
400
+        }
401
+
402
+
403
+        $response = new DataDisplayResponse(
404
+            $formattedTextResponse,
405
+            Http::STATUS_OK,
406
+            [
407
+                'Content-Type' => 'text/plain',
408
+            ]
409
+        );
410
+
411
+        return $response;
412
+    }
413
+
414
+    /**
415
+     * Checks whether a PHP opcache is properly set up
416
+     * @return bool
417
+     */
418
+    protected function isOpcacheProperlySetup() {
419
+        if (!$this->iniGetWrapper->getBool('opcache.enable')) {
420
+            return false;
421
+        }
422
+
423
+        if (!$this->iniGetWrapper->getBool('opcache.save_comments')) {
424
+            return false;
425
+        }
426
+
427
+        if ($this->iniGetWrapper->getNumeric('opcache.max_accelerated_files') < 10000) {
428
+            return false;
429
+        }
430
+
431
+        if ($this->iniGetWrapper->getNumeric('opcache.memory_consumption') < 128) {
432
+            return false;
433
+        }
434
+
435
+        if ($this->iniGetWrapper->getNumeric('opcache.interned_strings_buffer') < 8) {
436
+            return false;
437
+        }
438
+
439
+        return true;
440
+    }
441
+
442
+    /**
443
+     * Check if the required FreeType functions are present
444
+     * @return bool
445
+     */
446
+    protected function hasFreeTypeSupport() {
447
+        return function_exists('imagettfbbox') && function_exists('imagettftext');
448
+    }
449
+
450
+    protected function hasMissingIndexes(): array {
451
+        $indexInfo = new MissingIndexInformation();
452
+        // Dispatch event so apps can also hint for pending index updates if needed
453
+        $event = new GenericEvent($indexInfo);
454
+        $this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_INDEXES_EVENT, $event);
455
+
456
+        return $indexInfo->getListOfMissingIndexes();
457
+    }
458
+
459
+    protected function hasMissingPrimaryKeys(): array {
460
+        $info = new MissingPrimaryKeyInformation();
461
+        // Dispatch event so apps can also hint for pending index updates if needed
462
+        $event = new GenericEvent($info);
463
+        $this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_PRIMARY_KEYS_EVENT, $event);
464
+
465
+        return $info->getListOfMissingPrimaryKeys();
466
+    }
467
+
468
+    protected function hasMissingColumns(): array {
469
+        $indexInfo = new MissingColumnInformation();
470
+        // Dispatch event so apps can also hint for pending index updates if needed
471
+        $event = new GenericEvent($indexInfo);
472
+        $this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_COLUMNS_EVENT, $event);
473
+
474
+        return $indexInfo->getListOfMissingColumns();
475
+    }
476
+
477
+    protected function isSqliteUsed() {
478
+        return strpos($this->config->getSystemValue('dbtype'), 'sqlite') !== false;
479
+    }
480
+
481
+    protected function isReadOnlyConfig(): bool {
482
+        return \OC_Helper::isReadOnlyConfigEnabled();
483
+    }
484
+
485
+    protected function hasValidTransactionIsolationLevel(): bool {
486
+        try {
487
+            if ($this->db->getDatabasePlatform() instanceof SqlitePlatform) {
488
+                return true;
489
+            }
490
+
491
+            return $this->db->getTransactionIsolation() === Connection::TRANSACTION_READ_COMMITTED;
492
+        } catch (DBALException $e) {
493
+            // ignore
494
+        }
495
+
496
+        return true;
497
+    }
498
+
499
+    protected function hasFileinfoInstalled(): bool {
500
+        return \OC_Util::fileInfoLoaded();
501
+    }
502
+
503
+    protected function hasWorkingFileLocking(): bool {
504
+        return !($this->lockingProvider instanceof NoopLockingProvider);
505
+    }
506
+
507
+    protected function getSuggestedOverwriteCliURL(): string {
508
+        $suggestedOverwriteCliUrl = '';
509
+        if ($this->config->getSystemValue('overwrite.cli.url', '') === '') {
510
+            $suggestedOverwriteCliUrl = $this->request->getServerProtocol() . '://' . $this->request->getInsecureServerHost() . \OC::$WEBROOT;
511
+            if (!$this->config->getSystemValue('config_is_read_only', false)) {
512
+                // Set the overwrite URL when it was not set yet.
513
+                $this->config->setSystemValue('overwrite.cli.url', $suggestedOverwriteCliUrl);
514
+                $suggestedOverwriteCliUrl = '';
515
+            }
516
+        }
517
+        return $suggestedOverwriteCliUrl;
518
+    }
519
+
520
+    protected function getLastCronInfo(): array {
521
+        $lastCronRun = $this->config->getAppValue('core', 'lastcron', 0);
522
+        return [
523
+            'diffInSeconds' => time() - $lastCronRun,
524
+            'relativeTime' => $this->dateTimeFormatter->formatTimeSpan($lastCronRun),
525
+            'backgroundJobsUrl' => $this->urlGenerator->linkToRoute('settings.AdminSettings.index', ['section' => 'server']) . '#backgroundjobs',
526
+        ];
527
+    }
528
+
529
+    protected function getCronErrors() {
530
+        $errors = json_decode($this->config->getAppValue('core', 'cronErrors', ''), true);
531
+
532
+        if (is_array($errors)) {
533
+            return $errors;
534
+        }
535
+
536
+        return [];
537
+    }
538
+
539
+    protected function hasOpcacheLoaded(): bool {
540
+        return extension_loaded('Zend OPcache');
541
+    }
542
+
543
+    /**
544
+     * Iterates through the configured app roots and
545
+     * tests if the subdirectories are owned by the same user than the current user.
546
+     *
547
+     * @return array
548
+     */
549
+    protected function getAppDirsWithDifferentOwner(): array {
550
+        $currentUser = posix_getuid();
551
+        $appDirsWithDifferentOwner = [[]];
552
+
553
+        foreach (OC::$APPSROOTS as $appRoot) {
554
+            if ($appRoot['writable'] === true) {
555
+                $appDirsWithDifferentOwner[] = $this->getAppDirsWithDifferentOwnerForAppRoot($currentUser, $appRoot);
556
+            }
557
+        }
558
+
559
+        $appDirsWithDifferentOwner = array_merge(...$appDirsWithDifferentOwner);
560
+        sort($appDirsWithDifferentOwner);
561
+
562
+        return $appDirsWithDifferentOwner;
563
+    }
564
+
565
+    /**
566
+     * Tests if the directories for one apps directory are writable by the current user.
567
+     *
568
+     * @param int $currentUser The current user
569
+     * @param array $appRoot The app root config
570
+     * @return string[] The none writable directory paths inside the app root
571
+     */
572
+    private function getAppDirsWithDifferentOwnerForAppRoot(int $currentUser, array $appRoot): array {
573
+        $appDirsWithDifferentOwner = [];
574
+        $appsPath = $appRoot['path'];
575
+        $appsDir = new DirectoryIterator($appRoot['path']);
576
+
577
+        foreach ($appsDir as $fileInfo) {
578
+            if ($fileInfo->isDir() && !$fileInfo->isDot()) {
579
+                $absAppPath = $appsPath . DIRECTORY_SEPARATOR . $fileInfo->getFilename();
580
+                $appDirUser = fileowner($absAppPath);
581
+                if ($appDirUser !== $currentUser) {
582
+                    $appDirsWithDifferentOwner[] = $absAppPath;
583
+                }
584
+            }
585
+        }
586
+
587
+        return $appDirsWithDifferentOwner;
588
+    }
589
+
590
+    /**
591
+     * Checks for potential PHP modules that would improve the instance
592
+     *
593
+     * @return string[] A list of PHP modules that is recommended
594
+     */
595
+    protected function hasRecommendedPHPModules(): array {
596
+        $recommendedPHPModules = [];
597
+
598
+        if (!extension_loaded('intl')) {
599
+            $recommendedPHPModules[] = 'intl';
600
+        }
601
+
602
+        if (!extension_loaded('bcmath')) {
603
+            $recommendedPHPModules[] = 'bcmath';
604
+        }
605
+
606
+        if (!extension_loaded('gmp')) {
607
+            $recommendedPHPModules[] = 'gmp';
608
+        }
609
+
610
+        if ($this->config->getAppValue('theming', 'enabled', 'no') === 'yes') {
611
+            if (!extension_loaded('imagick')) {
612
+                $recommendedPHPModules[] = 'imagick';
613
+            }
614
+        }
615
+
616
+        return $recommendedPHPModules;
617
+    }
618
+
619
+    protected function isMysqlUsedWithoutUTF8MB4(): bool {
620
+        return ($this->config->getSystemValue('dbtype', 'sqlite') === 'mysql') && ($this->config->getSystemValue('mysql.utf8mb4', false) === false);
621
+    }
622
+
623
+    protected function hasBigIntConversionPendingColumns(): array {
624
+        // copy of ConvertFilecacheBigInt::getColumnsByTable()
625
+        $tables = [
626
+            'activity' => ['activity_id', 'object_id'],
627
+            'activity_mq' => ['mail_id'],
628
+            'authtoken' => ['id'],
629
+            'bruteforce_attempts' => ['id'],
630
+            'federated_reshares' => ['share_id'],
631
+            'filecache' => ['fileid', 'storage', 'parent', 'mimetype', 'mimepart', 'mtime', 'storage_mtime'],
632
+            'filecache_extended' => ['fileid'],
633
+            'file_locks' => ['id'],
634
+            'jobs' => ['id'],
635
+            'mimetypes' => ['id'],
636
+            'mounts' => ['id', 'storage_id', 'root_id', 'mount_id'],
637
+            'share_external' => ['id', 'parent'],
638
+            'storages' => ['numeric_id'],
639
+        ];
640
+
641
+        $schema = new SchemaWrapper($this->db);
642
+        $isSqlite = $this->db->getDatabasePlatform() instanceof SqlitePlatform;
643
+        $pendingColumns = [];
644
+
645
+        foreach ($tables as $tableName => $columns) {
646
+            if (!$schema->hasTable($tableName)) {
647
+                continue;
648
+            }
649
+
650
+            $table = $schema->getTable($tableName);
651
+            foreach ($columns as $columnName) {
652
+                $column = $table->getColumn($columnName);
653
+                $isAutoIncrement = $column->getAutoincrement();
654
+                $isAutoIncrementOnSqlite = $isSqlite && $isAutoIncrement;
655
+                if ($column->getType()->getName() !== Types::BIGINT && !$isAutoIncrementOnSqlite) {
656
+                    $pendingColumns[] = $tableName . '.' . $columnName;
657
+                }
658
+            }
659
+        }
660
+
661
+        return $pendingColumns;
662
+    }
663
+
664
+    protected function isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed(): bool {
665
+        $objectStore = $this->config->getSystemValue('objectstore', null);
666
+        $objectStoreMultibucket = $this->config->getSystemValue('objectstore_multibucket', null);
667
+
668
+        if (!isset($objectStoreMultibucket) && !isset($objectStore)) {
669
+            return true;
670
+        }
671
+
672
+        if (isset($objectStoreMultibucket['class']) && $objectStoreMultibucket['class'] !== 'OC\\Files\\ObjectStore\\S3') {
673
+            return true;
674
+        }
675
+
676
+        if (isset($objectStore['class']) && $objectStore['class'] !== 'OC\\Files\\ObjectStore\\S3') {
677
+            return true;
678
+        }
679
+
680
+        $tempPath = sys_get_temp_dir();
681
+        if (!is_dir($tempPath)) {
682
+            $this->logger->error('Error while checking the temporary PHP path - it was not properly set to a directory. value: ' . $tempPath);
683
+            return false;
684
+        }
685
+        $freeSpaceInTemp = disk_free_space($tempPath);
686
+        if ($freeSpaceInTemp === false) {
687
+            $this->logger->error('Error while checking the available disk space of temporary PHP path - no free disk space returned. temporary path: ' . $tempPath);
688
+            return false;
689
+        }
690
+
691
+        $freeSpaceInTempInGB = $freeSpaceInTemp / 1024 / 1024 / 1024;
692
+        if ($freeSpaceInTempInGB > 50) {
693
+            return true;
694
+        }
695
+
696
+        $this->logger->warning('Checking the available space in the temporary path resulted in ' . round($freeSpaceInTempInGB, 1) . ' GB instead of the recommended 50GB. Path: ' . $tempPath);
697
+        return false;
698
+    }
699
+
700
+    protected function imageMagickLacksSVGSupport(): bool {
701
+        return extension_loaded('imagick') && count(\Imagick::queryFormats('SVG')) === 0;
702
+    }
703
+
704
+    /**
705
+     * @return DataResponse
706
+     */
707
+    public function check() {
708
+        $phpDefaultCharset = new PhpDefaultCharset();
709
+        $phpOutputBuffering = new PhpOutputBuffering();
710
+        $legacySSEKeyFormat = new LegacySSEKeyFormat($this->l10n, $this->config, $this->urlGenerator);
711
+        $checkUserCertificates = new CheckUserCertificates($this->l10n, $this->config, $this->urlGenerator);
712
+
713
+        return new DataResponse(
714
+            [
715
+                'isGetenvServerWorking' => !empty(getenv('PATH')),
716
+                'isReadOnlyConfig' => $this->isReadOnlyConfig(),
717
+                'hasValidTransactionIsolationLevel' => $this->hasValidTransactionIsolationLevel(),
718
+                'hasFileinfoInstalled' => $this->hasFileinfoInstalled(),
719
+                'hasWorkingFileLocking' => $this->hasWorkingFileLocking(),
720
+                'suggestedOverwriteCliURL' => $this->getSuggestedOverwriteCliURL(),
721
+                'cronInfo' => $this->getLastCronInfo(),
722
+                'cronErrors' => $this->getCronErrors(),
723
+                'serverHasInternetConnectionProblems' => $this->hasInternetConnectivityProblems(),
724
+                'isMemcacheConfigured' => $this->isMemcacheConfigured(),
725
+                'memcacheDocs' => $this->urlGenerator->linkToDocs('admin-performance'),
726
+                'isRandomnessSecure' => $this->isRandomnessSecure(),
727
+                'securityDocs' => $this->urlGenerator->linkToDocs('admin-security'),
728
+                'isUsedTlsLibOutdated' => $this->isUsedTlsLibOutdated(),
729
+                'phpSupported' => $this->isPhpSupported(),
730
+                'forwardedForHeadersWorking' => $this->forwardedForHeadersWorking(),
731
+                'reverseProxyDocs' => $this->urlGenerator->linkToDocs('admin-reverse-proxy'),
732
+                'isCorrectMemcachedPHPModuleInstalled' => $this->isCorrectMemcachedPHPModuleInstalled(),
733
+                'hasPassedCodeIntegrityCheck' => $this->checker->hasPassedCheck(),
734
+                'codeIntegrityCheckerDocumentation' => $this->urlGenerator->linkToDocs('admin-code-integrity'),
735
+                'isOpcacheProperlySetup' => $this->isOpcacheProperlySetup(),
736
+                'hasOpcacheLoaded' => $this->hasOpcacheLoaded(),
737
+                'phpOpcacheDocumentation' => $this->urlGenerator->linkToDocs('admin-php-opcache'),
738
+                'isSettimelimitAvailable' => $this->isSettimelimitAvailable(),
739
+                'hasFreeTypeSupport' => $this->hasFreeTypeSupport(),
740
+                'missingPrimaryKeys' => $this->hasMissingPrimaryKeys(),
741
+                'missingIndexes' => $this->hasMissingIndexes(),
742
+                'missingColumns' => $this->hasMissingColumns(),
743
+                'isSqliteUsed' => $this->isSqliteUsed(),
744
+                'databaseConversionDocumentation' => $this->urlGenerator->linkToDocs('admin-db-conversion'),
745
+                'isMemoryLimitSufficient' => $this->memoryInfo->isMemoryLimitSufficient(),
746
+                'appDirsWithDifferentOwner' => $this->getAppDirsWithDifferentOwner(),
747
+                'recommendedPHPModules' => $this->hasRecommendedPHPModules(),
748
+                'pendingBigIntConversionColumns' => $this->hasBigIntConversionPendingColumns(),
749
+                'isMysqlUsedWithoutUTF8MB4' => $this->isMysqlUsedWithoutUTF8MB4(),
750
+                'isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed' => $this->isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed(),
751
+                'reverseProxyGeneratedURL' => $this->urlGenerator->getAbsoluteURL('index.php'),
752
+                'imageMagickLacksSVGSupport' => $this->imageMagickLacksSVGSupport(),
753
+                PhpDefaultCharset::class => ['pass' => $phpDefaultCharset->run(), 'description' => $phpDefaultCharset->description(), 'severity' => $phpDefaultCharset->severity()],
754
+                PhpOutputBuffering::class => ['pass' => $phpOutputBuffering->run(), 'description' => $phpOutputBuffering->description(), 'severity' => $phpOutputBuffering->severity()],
755
+                LegacySSEKeyFormat::class => ['pass' => $legacySSEKeyFormat->run(), 'description' => $legacySSEKeyFormat->description(), 'severity' => $legacySSEKeyFormat->severity(), 'linkToDocumentation' => $legacySSEKeyFormat->linkToDocumentation()],
756
+                CheckUserCertificates::class => ['pass' => $checkUserCertificates->run(), 'description' => $checkUserCertificates->description(), 'severity' => $checkUserCertificates->severity(), 'elements' => $checkUserCertificates->elements()],
757
+                'isDefaultPhoneRegionSet' => $this->config->getSystemValueString('default_phone_region', '') !== '',
758
+            ]
759
+        );
760
+    }
761 761
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/External/Manager.php 1 patch
Indentation   +534 added lines, -534 removed lines patch added patch discarded remove patch
@@ -51,579 +51,579 @@
 block discarded – undo
51 51
 use OCP\Share\IShare;
52 52
 
53 53
 class Manager {
54
-	public const STORAGE = '\OCA\Files_Sharing\External\Storage';
55
-
56
-	/** @var string|null */
57
-	private $uid;
58
-
59
-	/** @var IDBConnection */
60
-	private $connection;
61
-
62
-	/** @var \OC\Files\Mount\Manager */
63
-	private $mountManager;
64
-
65
-	/** @var IStorageFactory */
66
-	private $storageLoader;
67
-
68
-	/** @var IClientService */
69
-	private $clientService;
70
-
71
-	/** @var IManager */
72
-	private $notificationManager;
73
-
74
-	/** @var IDiscoveryService */
75
-	private $discoveryService;
76
-
77
-	/** @var ICloudFederationProviderManager */
78
-	private $cloudFederationProviderManager;
79
-
80
-	/** @var ICloudFederationFactory */
81
-	private $cloudFederationFactory;
82
-
83
-	/** @var IGroupManager  */
84
-	private $groupManager;
85
-
86
-	/** @var IUserManager */
87
-	private $userManager;
88
-
89
-	/** @var IEventDispatcher */
90
-	private $eventDispatcher;
91
-
92
-	public function __construct(IDBConnection $connection,
93
-								\OC\Files\Mount\Manager $mountManager,
94
-								IStorageFactory $storageLoader,
95
-								IClientService $clientService,
96
-								IManager $notificationManager,
97
-								IDiscoveryService $discoveryService,
98
-								ICloudFederationProviderManager $cloudFederationProviderManager,
99
-								ICloudFederationFactory $cloudFederationFactory,
100
-								IGroupManager $groupManager,
101
-								IUserManager $userManager,
102
-								?string $uid,
103
-								IEventDispatcher $eventDispatcher) {
104
-		$this->connection = $connection;
105
-		$this->mountManager = $mountManager;
106
-		$this->storageLoader = $storageLoader;
107
-		$this->clientService = $clientService;
108
-		$this->uid = $uid;
109
-		$this->notificationManager = $notificationManager;
110
-		$this->discoveryService = $discoveryService;
111
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
112
-		$this->cloudFederationFactory = $cloudFederationFactory;
113
-		$this->groupManager = $groupManager;
114
-		$this->userManager = $userManager;
115
-		$this->eventDispatcher = $eventDispatcher;
116
-	}
117
-
118
-	/**
119
-	 * add new server-to-server share
120
-	 *
121
-	 * @param string $remote
122
-	 * @param string $token
123
-	 * @param string $password
124
-	 * @param string $name
125
-	 * @param string $owner
126
-	 * @param int $shareType
127
-	 * @param boolean $accepted
128
-	 * @param string $user
129
-	 * @param string $remoteId
130
-	 * @param int $parent
131
-	 * @return Mount|null
132
-	 * @throws \Doctrine\DBAL\DBALException
133
-	 */
134
-	public function addShare($remote, $token, $password, $name, $owner, $shareType, $accepted = false, $user = null, $remoteId = '', $parent = -1) {
135
-		$user = $user ? $user : $this->uid;
136
-		$accepted = $accepted ? IShare::STATUS_ACCEPTED : IShare::STATUS_PENDING;
137
-		$name = Filesystem::normalizePath('/' . $name);
138
-
139
-		if ($accepted !== IShare::STATUS_ACCEPTED) {
140
-			// To avoid conflicts with the mount point generation later,
141
-			// we only use a temporary mount point name here. The real
142
-			// mount point name will be generated when accepting the share,
143
-			// using the original share item name.
144
-			$tmpMountPointName = '{{TemporaryMountPointName#' . $name . '}}';
145
-			$mountPoint = $tmpMountPointName;
146
-			$hash = md5($tmpMountPointName);
147
-			$data = [
148
-				'remote' => $remote,
149
-				'share_token' => $token,
150
-				'password' => $password,
151
-				'name' => $name,
152
-				'owner' => $owner,
153
-				'user' => $user,
154
-				'mountpoint' => $mountPoint,
155
-				'mountpoint_hash' => $hash,
156
-				'accepted' => $accepted,
157
-				'remote_id' => $remoteId,
158
-				'share_type' => $shareType,
159
-			];
160
-
161
-			$i = 1;
162
-			while (!$this->connection->insertIfNotExist('*PREFIX*share_external', $data, ['user', 'mountpoint_hash'])) {
163
-				// The external share already exists for the user
164
-				$data['mountpoint'] = $tmpMountPointName . '-' . $i;
165
-				$data['mountpoint_hash'] = md5($data['mountpoint']);
166
-				$i++;
167
-			}
168
-			return null;
169
-		}
170
-
171
-		$mountPoint = Files::buildNotExistingFileName('/', $name);
172
-		$mountPoint = Filesystem::normalizePath('/' . $mountPoint);
173
-		$hash = md5($mountPoint);
174
-
175
-		$this->writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType);
176
-
177
-		$options = [
178
-			'remote' => $remote,
179
-			'token' => $token,
180
-			'password' => $password,
181
-			'mountpoint' => $mountPoint,
182
-			'owner' => $owner
183
-		];
184
-		return $this->mountShare($options);
185
-	}
186
-
187
-	/**
188
-	 * write remote share to the database
189
-	 *
190
-	 * @param $remote
191
-	 * @param $token
192
-	 * @param $password
193
-	 * @param $name
194
-	 * @param $owner
195
-	 * @param $user
196
-	 * @param $mountPoint
197
-	 * @param $hash
198
-	 * @param $accepted
199
-	 * @param $remoteId
200
-	 * @param $parent
201
-	 * @param $shareType
202
-	 * @return bool
203
-	 */
204
-	private function writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType) {
205
-		$query = $this->connection->prepare('
54
+    public const STORAGE = '\OCA\Files_Sharing\External\Storage';
55
+
56
+    /** @var string|null */
57
+    private $uid;
58
+
59
+    /** @var IDBConnection */
60
+    private $connection;
61
+
62
+    /** @var \OC\Files\Mount\Manager */
63
+    private $mountManager;
64
+
65
+    /** @var IStorageFactory */
66
+    private $storageLoader;
67
+
68
+    /** @var IClientService */
69
+    private $clientService;
70
+
71
+    /** @var IManager */
72
+    private $notificationManager;
73
+
74
+    /** @var IDiscoveryService */
75
+    private $discoveryService;
76
+
77
+    /** @var ICloudFederationProviderManager */
78
+    private $cloudFederationProviderManager;
79
+
80
+    /** @var ICloudFederationFactory */
81
+    private $cloudFederationFactory;
82
+
83
+    /** @var IGroupManager  */
84
+    private $groupManager;
85
+
86
+    /** @var IUserManager */
87
+    private $userManager;
88
+
89
+    /** @var IEventDispatcher */
90
+    private $eventDispatcher;
91
+
92
+    public function __construct(IDBConnection $connection,
93
+                                \OC\Files\Mount\Manager $mountManager,
94
+                                IStorageFactory $storageLoader,
95
+                                IClientService $clientService,
96
+                                IManager $notificationManager,
97
+                                IDiscoveryService $discoveryService,
98
+                                ICloudFederationProviderManager $cloudFederationProviderManager,
99
+                                ICloudFederationFactory $cloudFederationFactory,
100
+                                IGroupManager $groupManager,
101
+                                IUserManager $userManager,
102
+                                ?string $uid,
103
+                                IEventDispatcher $eventDispatcher) {
104
+        $this->connection = $connection;
105
+        $this->mountManager = $mountManager;
106
+        $this->storageLoader = $storageLoader;
107
+        $this->clientService = $clientService;
108
+        $this->uid = $uid;
109
+        $this->notificationManager = $notificationManager;
110
+        $this->discoveryService = $discoveryService;
111
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
112
+        $this->cloudFederationFactory = $cloudFederationFactory;
113
+        $this->groupManager = $groupManager;
114
+        $this->userManager = $userManager;
115
+        $this->eventDispatcher = $eventDispatcher;
116
+    }
117
+
118
+    /**
119
+     * add new server-to-server share
120
+     *
121
+     * @param string $remote
122
+     * @param string $token
123
+     * @param string $password
124
+     * @param string $name
125
+     * @param string $owner
126
+     * @param int $shareType
127
+     * @param boolean $accepted
128
+     * @param string $user
129
+     * @param string $remoteId
130
+     * @param int $parent
131
+     * @return Mount|null
132
+     * @throws \Doctrine\DBAL\DBALException
133
+     */
134
+    public function addShare($remote, $token, $password, $name, $owner, $shareType, $accepted = false, $user = null, $remoteId = '', $parent = -1) {
135
+        $user = $user ? $user : $this->uid;
136
+        $accepted = $accepted ? IShare::STATUS_ACCEPTED : IShare::STATUS_PENDING;
137
+        $name = Filesystem::normalizePath('/' . $name);
138
+
139
+        if ($accepted !== IShare::STATUS_ACCEPTED) {
140
+            // To avoid conflicts with the mount point generation later,
141
+            // we only use a temporary mount point name here. The real
142
+            // mount point name will be generated when accepting the share,
143
+            // using the original share item name.
144
+            $tmpMountPointName = '{{TemporaryMountPointName#' . $name . '}}';
145
+            $mountPoint = $tmpMountPointName;
146
+            $hash = md5($tmpMountPointName);
147
+            $data = [
148
+                'remote' => $remote,
149
+                'share_token' => $token,
150
+                'password' => $password,
151
+                'name' => $name,
152
+                'owner' => $owner,
153
+                'user' => $user,
154
+                'mountpoint' => $mountPoint,
155
+                'mountpoint_hash' => $hash,
156
+                'accepted' => $accepted,
157
+                'remote_id' => $remoteId,
158
+                'share_type' => $shareType,
159
+            ];
160
+
161
+            $i = 1;
162
+            while (!$this->connection->insertIfNotExist('*PREFIX*share_external', $data, ['user', 'mountpoint_hash'])) {
163
+                // The external share already exists for the user
164
+                $data['mountpoint'] = $tmpMountPointName . '-' . $i;
165
+                $data['mountpoint_hash'] = md5($data['mountpoint']);
166
+                $i++;
167
+            }
168
+            return null;
169
+        }
170
+
171
+        $mountPoint = Files::buildNotExistingFileName('/', $name);
172
+        $mountPoint = Filesystem::normalizePath('/' . $mountPoint);
173
+        $hash = md5($mountPoint);
174
+
175
+        $this->writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType);
176
+
177
+        $options = [
178
+            'remote' => $remote,
179
+            'token' => $token,
180
+            'password' => $password,
181
+            'mountpoint' => $mountPoint,
182
+            'owner' => $owner
183
+        ];
184
+        return $this->mountShare($options);
185
+    }
186
+
187
+    /**
188
+     * write remote share to the database
189
+     *
190
+     * @param $remote
191
+     * @param $token
192
+     * @param $password
193
+     * @param $name
194
+     * @param $owner
195
+     * @param $user
196
+     * @param $mountPoint
197
+     * @param $hash
198
+     * @param $accepted
199
+     * @param $remoteId
200
+     * @param $parent
201
+     * @param $shareType
202
+     * @return bool
203
+     */
204
+    private function writeShareToDb($remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType) {
205
+        $query = $this->connection->prepare('
206 206
 				INSERT INTO `*PREFIX*share_external`
207 207
 					(`remote`, `share_token`, `password`, `name`, `owner`, `user`, `mountpoint`, `mountpoint_hash`, `accepted`, `remote_id`, `parent`, `share_type`)
208 208
 				VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
209 209
 			');
210
-		return $query->execute([$remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType]);
211
-	}
212
-
213
-	/**
214
-	 * get share
215
-	 *
216
-	 * @param int $id share id
217
-	 * @return mixed share of false
218
-	 */
219
-	public function getShare($id) {
220
-		$getShare = $this->connection->prepare('
210
+        return $query->execute([$remote, $token, $password, $name, $owner, $user, $mountPoint, $hash, $accepted, $remoteId, $parent, $shareType]);
211
+    }
212
+
213
+    /**
214
+     * get share
215
+     *
216
+     * @param int $id share id
217
+     * @return mixed share of false
218
+     */
219
+    public function getShare($id) {
220
+        $getShare = $this->connection->prepare('
221 221
 			SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted`, `parent`, `share_type`, `password`, `mountpoint_hash`
222 222
 			FROM  `*PREFIX*share_external`
223 223
 			WHERE `id` = ?');
224
-		$result = $getShare->execute([$id]);
225
-
226
-		$share = $result ? $getShare->fetch() : [];
227
-
228
-		$validShare = is_array($share) && isset($share['share_type']) && isset($share['user']);
229
-
230
-		// check if the user is allowed to access it
231
-		if ($validShare && (int)$share['share_type'] === IShare::TYPE_USER && $share['user'] === $this->uid) {
232
-			return $share;
233
-		} elseif ($validShare && (int)$share['share_type'] === IShare::TYPE_GROUP) {
234
-			$user = $this->userManager->get($this->uid);
235
-			if ($this->groupManager->get($share['user'])->inGroup($user)) {
236
-				return $share;
237
-			}
238
-		}
239
-
240
-		return false;
241
-	}
242
-
243
-	/**
244
-	 * accept server-to-server share
245
-	 *
246
-	 * @param int $id
247
-	 * @return bool True if the share could be accepted, false otherwise
248
-	 */
249
-	public function acceptShare($id) {
250
-		$share = $this->getShare($id);
251
-		$result = false;
252
-
253
-		if ($share) {
254
-			\OC_Util::setupFS($this->uid);
255
-			$shareFolder = Helper::getShareFolder();
256
-			$mountPoint = Files::buildNotExistingFileName($shareFolder, $share['name']);
257
-			$mountPoint = Filesystem::normalizePath($mountPoint);
258
-			$hash = md5($mountPoint);
259
-			$userShareAccepted = false;
260
-
261
-			if ((int)$share['share_type'] === IShare::TYPE_USER) {
262
-				$acceptShare = $this->connection->prepare('
224
+        $result = $getShare->execute([$id]);
225
+
226
+        $share = $result ? $getShare->fetch() : [];
227
+
228
+        $validShare = is_array($share) && isset($share['share_type']) && isset($share['user']);
229
+
230
+        // check if the user is allowed to access it
231
+        if ($validShare && (int)$share['share_type'] === IShare::TYPE_USER && $share['user'] === $this->uid) {
232
+            return $share;
233
+        } elseif ($validShare && (int)$share['share_type'] === IShare::TYPE_GROUP) {
234
+            $user = $this->userManager->get($this->uid);
235
+            if ($this->groupManager->get($share['user'])->inGroup($user)) {
236
+                return $share;
237
+            }
238
+        }
239
+
240
+        return false;
241
+    }
242
+
243
+    /**
244
+     * accept server-to-server share
245
+     *
246
+     * @param int $id
247
+     * @return bool True if the share could be accepted, false otherwise
248
+     */
249
+    public function acceptShare($id) {
250
+        $share = $this->getShare($id);
251
+        $result = false;
252
+
253
+        if ($share) {
254
+            \OC_Util::setupFS($this->uid);
255
+            $shareFolder = Helper::getShareFolder();
256
+            $mountPoint = Files::buildNotExistingFileName($shareFolder, $share['name']);
257
+            $mountPoint = Filesystem::normalizePath($mountPoint);
258
+            $hash = md5($mountPoint);
259
+            $userShareAccepted = false;
260
+
261
+            if ((int)$share['share_type'] === IShare::TYPE_USER) {
262
+                $acceptShare = $this->connection->prepare('
263 263
 				UPDATE `*PREFIX*share_external`
264 264
 				SET `accepted` = ?,
265 265
 					`mountpoint` = ?,
266 266
 					`mountpoint_hash` = ?
267 267
 				WHERE `id` = ? AND `user` = ?');
268
-				$userShareAccepted = $acceptShare->execute([1, $mountPoint, $hash, $id, $this->uid]);
269
-			} else {
270
-				$result = $this->writeShareToDb(
271
-					$share['remote'],
272
-					$share['share_token'],
273
-					$share['password'],
274
-					$share['name'],
275
-					$share['owner'],
276
-					$this->uid,
277
-					$mountPoint, $hash, 1,
278
-					$share['remote_id'],
279
-					$id,
280
-					$share['share_type']);
281
-			}
282
-			if ($userShareAccepted === true) {
283
-				$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept');
284
-				$event = new FederatedShareAddedEvent($share['remote']);
285
-				$this->eventDispatcher->dispatchTyped($event);
286
-				$result = true;
287
-			}
288
-		}
289
-
290
-		// Make sure the user has no notification for something that does not exist anymore.
291
-		$this->processNotification($id);
292
-
293
-		return $result;
294
-	}
295
-
296
-	/**
297
-	 * decline server-to-server share
298
-	 *
299
-	 * @param int $id
300
-	 * @return bool True if the share could be declined, false otherwise
301
-	 */
302
-	public function declineShare($id) {
303
-		$share = $this->getShare($id);
304
-		$result = false;
305
-
306
-		if ($share && (int)$share['share_type'] === IShare::TYPE_USER) {
307
-			$removeShare = $this->connection->prepare('
268
+                $userShareAccepted = $acceptShare->execute([1, $mountPoint, $hash, $id, $this->uid]);
269
+            } else {
270
+                $result = $this->writeShareToDb(
271
+                    $share['remote'],
272
+                    $share['share_token'],
273
+                    $share['password'],
274
+                    $share['name'],
275
+                    $share['owner'],
276
+                    $this->uid,
277
+                    $mountPoint, $hash, 1,
278
+                    $share['remote_id'],
279
+                    $id,
280
+                    $share['share_type']);
281
+            }
282
+            if ($userShareAccepted === true) {
283
+                $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept');
284
+                $event = new FederatedShareAddedEvent($share['remote']);
285
+                $this->eventDispatcher->dispatchTyped($event);
286
+                $result = true;
287
+            }
288
+        }
289
+
290
+        // Make sure the user has no notification for something that does not exist anymore.
291
+        $this->processNotification($id);
292
+
293
+        return $result;
294
+    }
295
+
296
+    /**
297
+     * decline server-to-server share
298
+     *
299
+     * @param int $id
300
+     * @return bool True if the share could be declined, false otherwise
301
+     */
302
+    public function declineShare($id) {
303
+        $share = $this->getShare($id);
304
+        $result = false;
305
+
306
+        if ($share && (int)$share['share_type'] === IShare::TYPE_USER) {
307
+            $removeShare = $this->connection->prepare('
308 308
 				DELETE FROM `*PREFIX*share_external` WHERE `id` = ? AND `user` = ?');
309
-			$removeShare->execute([$id, $this->uid]);
310
-			$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
311
-
312
-			$this->processNotification($id);
313
-			$result = true;
314
-		} elseif ($share && (int)$share['share_type'] === IShare::TYPE_GROUP) {
315
-			$result = $this->writeShareToDb(
316
-				$share['remote'],
317
-				$share['share_token'],
318
-				$share['password'],
319
-				$share['name'],
320
-				$share['owner'],
321
-				$this->uid,
322
-				$share['mountpoint'],
323
-				$share['mountpoint_hash'],
324
-				0,
325
-				$share['remote_id'],
326
-				$id,
327
-				$share['share_type']);
328
-			$this->processNotification($id);
329
-		}
330
-
331
-		return $result;
332
-	}
333
-
334
-	/**
335
-	 * @param int $remoteShare
336
-	 */
337
-	public function processNotification($remoteShare) {
338
-		$filter = $this->notificationManager->createNotification();
339
-		$filter->setApp('files_sharing')
340
-			->setUser($this->uid)
341
-			->setObject('remote_share', (int) $remoteShare);
342
-		$this->notificationManager->markProcessed($filter);
343
-	}
344
-
345
-	/**
346
-	 * inform remote server whether server-to-server share was accepted/declined
347
-	 *
348
-	 * @param string $remote
349
-	 * @param string $token
350
-	 * @param string $remoteId Share id on the remote host
351
-	 * @param string $feedback
352
-	 * @return boolean
353
-	 */
354
-	private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) {
355
-		$result = $this->tryOCMEndPoint($remote, $token, $remoteId, $feedback);
356
-
357
-		if ($result === true) {
358
-			return true;
359
-		}
360
-
361
-		$federationEndpoints = $this->discoveryService->discover($remote, 'FEDERATED_SHARING');
362
-		$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
363
-
364
-		$url = rtrim($remote, '/') . $endpoint . '/' . $remoteId . '/' . $feedback . '?format=' . Share::RESPONSE_FORMAT;
365
-		$fields = ['token' => $token];
366
-
367
-		$client = $this->clientService->newClient();
368
-
369
-		try {
370
-			$response = $client->post(
371
-				$url,
372
-				[
373
-					'body' => $fields,
374
-					'connect_timeout' => 10,
375
-				]
376
-			);
377
-		} catch (\Exception $e) {
378
-			return false;
379
-		}
380
-
381
-		$status = json_decode($response->getBody(), true);
382
-
383
-		return ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200);
384
-	}
385
-
386
-	/**
387
-	 * try send accept message to ocm end-point
388
-	 *
389
-	 * @param string $remoteDomain
390
-	 * @param string $token
391
-	 * @param string $remoteId id of the share
392
-	 * @param string $feedback
393
-	 * @return bool
394
-	 */
395
-	protected function tryOCMEndPoint($remoteDomain, $token, $remoteId, $feedback) {
396
-		switch ($feedback) {
397
-			case 'accept':
398
-				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
399
-				$notification->setMessage(
400
-					'SHARE_ACCEPTED',
401
-					'file',
402
-					$remoteId,
403
-					[
404
-						'sharedSecret' => $token,
405
-						'message' => 'Recipient accept the share'
406
-					]
407
-
408
-				);
409
-				return $this->cloudFederationProviderManager->sendNotification($remoteDomain, $notification);
410
-			case 'decline':
411
-				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
412
-				$notification->setMessage(
413
-					'SHARE_DECLINED',
414
-					'file',
415
-					$remoteId,
416
-					[
417
-						'sharedSecret' => $token,
418
-						'message' => 'Recipient declined the share'
419
-					]
420
-
421
-				);
422
-				return $this->cloudFederationProviderManager->sendNotification($remoteDomain, $notification);
423
-		}
424
-
425
-		return false;
426
-	}
427
-
428
-
429
-	/**
430
-	 * remove '/user/files' from the path and trailing slashes
431
-	 *
432
-	 * @param string $path
433
-	 * @return string
434
-	 */
435
-	protected function stripPath($path) {
436
-		$prefix = '/' . $this->uid . '/files';
437
-		return rtrim(substr($path, strlen($prefix)), '/');
438
-	}
439
-
440
-	public function getMount($data) {
441
-		$data['manager'] = $this;
442
-		$mountPoint = '/' . $this->uid . '/files' . $data['mountpoint'];
443
-		$data['mountpoint'] = $mountPoint;
444
-		$data['certificateManager'] = \OC::$server->getCertificateManager();
445
-		return new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader);
446
-	}
447
-
448
-	/**
449
-	 * @param array $data
450
-	 * @return Mount
451
-	 */
452
-	protected function mountShare($data) {
453
-		$mount = $this->getMount($data);
454
-		$this->mountManager->addMount($mount);
455
-		return $mount;
456
-	}
457
-
458
-	/**
459
-	 * @return \OC\Files\Mount\Manager
460
-	 */
461
-	public function getMountManager() {
462
-		return $this->mountManager;
463
-	}
464
-
465
-	/**
466
-	 * @param string $source
467
-	 * @param string $target
468
-	 * @return bool
469
-	 */
470
-	public function setMountPoint($source, $target) {
471
-		$source = $this->stripPath($source);
472
-		$target = $this->stripPath($target);
473
-		$sourceHash = md5($source);
474
-		$targetHash = md5($target);
475
-
476
-		$query = $this->connection->prepare('
309
+            $removeShare->execute([$id, $this->uid]);
310
+            $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
311
+
312
+            $this->processNotification($id);
313
+            $result = true;
314
+        } elseif ($share && (int)$share['share_type'] === IShare::TYPE_GROUP) {
315
+            $result = $this->writeShareToDb(
316
+                $share['remote'],
317
+                $share['share_token'],
318
+                $share['password'],
319
+                $share['name'],
320
+                $share['owner'],
321
+                $this->uid,
322
+                $share['mountpoint'],
323
+                $share['mountpoint_hash'],
324
+                0,
325
+                $share['remote_id'],
326
+                $id,
327
+                $share['share_type']);
328
+            $this->processNotification($id);
329
+        }
330
+
331
+        return $result;
332
+    }
333
+
334
+    /**
335
+     * @param int $remoteShare
336
+     */
337
+    public function processNotification($remoteShare) {
338
+        $filter = $this->notificationManager->createNotification();
339
+        $filter->setApp('files_sharing')
340
+            ->setUser($this->uid)
341
+            ->setObject('remote_share', (int) $remoteShare);
342
+        $this->notificationManager->markProcessed($filter);
343
+    }
344
+
345
+    /**
346
+     * inform remote server whether server-to-server share was accepted/declined
347
+     *
348
+     * @param string $remote
349
+     * @param string $token
350
+     * @param string $remoteId Share id on the remote host
351
+     * @param string $feedback
352
+     * @return boolean
353
+     */
354
+    private function sendFeedbackToRemote($remote, $token, $remoteId, $feedback) {
355
+        $result = $this->tryOCMEndPoint($remote, $token, $remoteId, $feedback);
356
+
357
+        if ($result === true) {
358
+            return true;
359
+        }
360
+
361
+        $federationEndpoints = $this->discoveryService->discover($remote, 'FEDERATED_SHARING');
362
+        $endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
363
+
364
+        $url = rtrim($remote, '/') . $endpoint . '/' . $remoteId . '/' . $feedback . '?format=' . Share::RESPONSE_FORMAT;
365
+        $fields = ['token' => $token];
366
+
367
+        $client = $this->clientService->newClient();
368
+
369
+        try {
370
+            $response = $client->post(
371
+                $url,
372
+                [
373
+                    'body' => $fields,
374
+                    'connect_timeout' => 10,
375
+                ]
376
+            );
377
+        } catch (\Exception $e) {
378
+            return false;
379
+        }
380
+
381
+        $status = json_decode($response->getBody(), true);
382
+
383
+        return ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200);
384
+    }
385
+
386
+    /**
387
+     * try send accept message to ocm end-point
388
+     *
389
+     * @param string $remoteDomain
390
+     * @param string $token
391
+     * @param string $remoteId id of the share
392
+     * @param string $feedback
393
+     * @return bool
394
+     */
395
+    protected function tryOCMEndPoint($remoteDomain, $token, $remoteId, $feedback) {
396
+        switch ($feedback) {
397
+            case 'accept':
398
+                $notification = $this->cloudFederationFactory->getCloudFederationNotification();
399
+                $notification->setMessage(
400
+                    'SHARE_ACCEPTED',
401
+                    'file',
402
+                    $remoteId,
403
+                    [
404
+                        'sharedSecret' => $token,
405
+                        'message' => 'Recipient accept the share'
406
+                    ]
407
+
408
+                );
409
+                return $this->cloudFederationProviderManager->sendNotification($remoteDomain, $notification);
410
+            case 'decline':
411
+                $notification = $this->cloudFederationFactory->getCloudFederationNotification();
412
+                $notification->setMessage(
413
+                    'SHARE_DECLINED',
414
+                    'file',
415
+                    $remoteId,
416
+                    [
417
+                        'sharedSecret' => $token,
418
+                        'message' => 'Recipient declined the share'
419
+                    ]
420
+
421
+                );
422
+                return $this->cloudFederationProviderManager->sendNotification($remoteDomain, $notification);
423
+        }
424
+
425
+        return false;
426
+    }
427
+
428
+
429
+    /**
430
+     * remove '/user/files' from the path and trailing slashes
431
+     *
432
+     * @param string $path
433
+     * @return string
434
+     */
435
+    protected function stripPath($path) {
436
+        $prefix = '/' . $this->uid . '/files';
437
+        return rtrim(substr($path, strlen($prefix)), '/');
438
+    }
439
+
440
+    public function getMount($data) {
441
+        $data['manager'] = $this;
442
+        $mountPoint = '/' . $this->uid . '/files' . $data['mountpoint'];
443
+        $data['mountpoint'] = $mountPoint;
444
+        $data['certificateManager'] = \OC::$server->getCertificateManager();
445
+        return new Mount(self::STORAGE, $mountPoint, $data, $this, $this->storageLoader);
446
+    }
447
+
448
+    /**
449
+     * @param array $data
450
+     * @return Mount
451
+     */
452
+    protected function mountShare($data) {
453
+        $mount = $this->getMount($data);
454
+        $this->mountManager->addMount($mount);
455
+        return $mount;
456
+    }
457
+
458
+    /**
459
+     * @return \OC\Files\Mount\Manager
460
+     */
461
+    public function getMountManager() {
462
+        return $this->mountManager;
463
+    }
464
+
465
+    /**
466
+     * @param string $source
467
+     * @param string $target
468
+     * @return bool
469
+     */
470
+    public function setMountPoint($source, $target) {
471
+        $source = $this->stripPath($source);
472
+        $target = $this->stripPath($target);
473
+        $sourceHash = md5($source);
474
+        $targetHash = md5($target);
475
+
476
+        $query = $this->connection->prepare('
477 477
 			UPDATE `*PREFIX*share_external`
478 478
 			SET `mountpoint` = ?, `mountpoint_hash` = ?
479 479
 			WHERE `mountpoint_hash` = ?
480 480
 			AND `user` = ?
481 481
 		');
482
-		$result = (bool)$query->execute([$target, $targetHash, $sourceHash, $this->uid]);
482
+        $result = (bool)$query->execute([$target, $targetHash, $sourceHash, $this->uid]);
483 483
 
484
-		return $result;
485
-	}
484
+        return $result;
485
+    }
486 486
 
487
-	public function removeShare($mountPoint) {
488
-		$mountPointObj = $this->mountManager->find($mountPoint);
489
-		$id = $mountPointObj->getStorage()->getCache()->getId('');
487
+    public function removeShare($mountPoint) {
488
+        $mountPointObj = $this->mountManager->find($mountPoint);
489
+        $id = $mountPointObj->getStorage()->getCache()->getId('');
490 490
 
491
-		$mountPoint = $this->stripPath($mountPoint);
492
-		$hash = md5($mountPoint);
491
+        $mountPoint = $this->stripPath($mountPoint);
492
+        $hash = md5($mountPoint);
493 493
 
494
-		$getShare = $this->connection->prepare('
494
+        $getShare = $this->connection->prepare('
495 495
 			SELECT `remote`, `share_token`, `remote_id`, `share_type`, `id`
496 496
 			FROM  `*PREFIX*share_external`
497 497
 			WHERE `mountpoint_hash` = ? AND `user` = ?');
498
-		$result = $getShare->execute([$hash, $this->uid]);
499
-
500
-		$share = $getShare->fetch();
501
-		$getShare->closeCursor();
502
-		if ($result && $share !== false && (int)$share['share_type'] === IShare::TYPE_USER) {
503
-			try {
504
-				$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
505
-			} catch (\Throwable $e) {
506
-				// if we fail to notify the remote (probably cause the remote is down)
507
-				// we still want the share to be gone to prevent undeletable remotes
508
-			}
509
-
510
-			$query = $this->connection->prepare('
498
+        $result = $getShare->execute([$hash, $this->uid]);
499
+
500
+        $share = $getShare->fetch();
501
+        $getShare->closeCursor();
502
+        if ($result && $share !== false && (int)$share['share_type'] === IShare::TYPE_USER) {
503
+            try {
504
+                $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
505
+            } catch (\Throwable $e) {
506
+                // if we fail to notify the remote (probably cause the remote is down)
507
+                // we still want the share to be gone to prevent undeletable remotes
508
+            }
509
+
510
+            $query = $this->connection->prepare('
511 511
 			DELETE FROM `*PREFIX*share_external`
512 512
 			WHERE `id` = ?
513 513
 			');
514
-			$result = (bool)$query->execute([(int)$share['id']]);
515
-		} elseif ($result && $share !== false && (int)$share['share_type'] === IShare::TYPE_GROUP) {
516
-			$query = $this->connection->prepare('
514
+            $result = (bool)$query->execute([(int)$share['id']]);
515
+        } elseif ($result && $share !== false && (int)$share['share_type'] === IShare::TYPE_GROUP) {
516
+            $query = $this->connection->prepare('
517 517
 				UPDATE `*PREFIX*share_external`
518 518
 				SET `accepted` = ?
519 519
 				WHERE `id` = ?');
520
-			$result = (bool)$query->execute([0, (int)$share['id']]);
521
-		}
522
-
523
-		if ($result) {
524
-			$this->removeReShares($id);
525
-		}
526
-
527
-		return $result;
528
-	}
529
-
530
-	/**
531
-	 * remove re-shares from share table and mapping in the federated_reshares table
532
-	 *
533
-	 * @param $mountPointId
534
-	 */
535
-	protected function removeReShares($mountPointId) {
536
-		$selectQuery = $this->connection->getQueryBuilder();
537
-		$query = $this->connection->getQueryBuilder();
538
-		$selectQuery->select('id')->from('share')
539
-			->where($selectQuery->expr()->eq('file_source', $query->createNamedParameter($mountPointId)));
540
-		$select = $selectQuery->getSQL();
541
-
542
-
543
-		$query->delete('federated_reshares')
544
-			->where($query->expr()->in('share_id', $query->createFunction('(' . $select . ')')));
545
-		$query->execute();
546
-
547
-		$deleteReShares = $this->connection->getQueryBuilder();
548
-		$deleteReShares->delete('share')
549
-			->where($deleteReShares->expr()->eq('file_source', $deleteReShares->createNamedParameter($mountPointId)));
550
-		$deleteReShares->execute();
551
-	}
552
-
553
-	/**
554
-	 * remove all shares for user $uid if the user was deleted
555
-	 *
556
-	 * @param string $uid
557
-	 * @return bool
558
-	 */
559
-	public function removeUserShares($uid) {
560
-		$getShare = $this->connection->prepare('
520
+            $result = (bool)$query->execute([0, (int)$share['id']]);
521
+        }
522
+
523
+        if ($result) {
524
+            $this->removeReShares($id);
525
+        }
526
+
527
+        return $result;
528
+    }
529
+
530
+    /**
531
+     * remove re-shares from share table and mapping in the federated_reshares table
532
+     *
533
+     * @param $mountPointId
534
+     */
535
+    protected function removeReShares($mountPointId) {
536
+        $selectQuery = $this->connection->getQueryBuilder();
537
+        $query = $this->connection->getQueryBuilder();
538
+        $selectQuery->select('id')->from('share')
539
+            ->where($selectQuery->expr()->eq('file_source', $query->createNamedParameter($mountPointId)));
540
+        $select = $selectQuery->getSQL();
541
+
542
+
543
+        $query->delete('federated_reshares')
544
+            ->where($query->expr()->in('share_id', $query->createFunction('(' . $select . ')')));
545
+        $query->execute();
546
+
547
+        $deleteReShares = $this->connection->getQueryBuilder();
548
+        $deleteReShares->delete('share')
549
+            ->where($deleteReShares->expr()->eq('file_source', $deleteReShares->createNamedParameter($mountPointId)));
550
+        $deleteReShares->execute();
551
+    }
552
+
553
+    /**
554
+     * remove all shares for user $uid if the user was deleted
555
+     *
556
+     * @param string $uid
557
+     * @return bool
558
+     */
559
+    public function removeUserShares($uid) {
560
+        $getShare = $this->connection->prepare('
561 561
 			SELECT `remote`, `share_token`, `remote_id`
562 562
 			FROM  `*PREFIX*share_external`
563 563
 			WHERE `user` = ?');
564
-		$result = $getShare->execute([$uid]);
564
+        $result = $getShare->execute([$uid]);
565 565
 
566
-		if ($result) {
567
-			$shares = $getShare->fetchAll();
568
-			foreach ($shares as $share) {
569
-				$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
570
-			}
571
-		}
566
+        if ($result) {
567
+            $shares = $getShare->fetchAll();
568
+            foreach ($shares as $share) {
569
+                $this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
570
+            }
571
+        }
572 572
 
573
-		$query = $this->connection->prepare('
573
+        $query = $this->connection->prepare('
574 574
 			DELETE FROM `*PREFIX*share_external`
575 575
 			WHERE `user` = ?
576 576
 		');
577
-		return (bool)$query->execute([$uid]);
578
-	}
579
-
580
-	/**
581
-	 * return a list of shares which are not yet accepted by the user
582
-	 *
583
-	 * @return array list of open server-to-server shares
584
-	 */
585
-	public function getOpenShares() {
586
-		return $this->getShares(false);
587
-	}
588
-
589
-	/**
590
-	 * return a list of shares which are accepted by the user
591
-	 *
592
-	 * @return array list of accepted server-to-server shares
593
-	 */
594
-	public function getAcceptedShares() {
595
-		return $this->getShares(true);
596
-	}
597
-
598
-	/**
599
-	 * return a list of shares for the user
600
-	 *
601
-	 * @param bool|null $accepted True for accepted only,
602
-	 *                            false for not accepted,
603
-	 *                            null for all shares of the user
604
-	 * @return array list of open server-to-server shares
605
-	 */
606
-	private function getShares($accepted) {
607
-		$user = $this->userManager->get($this->uid);
608
-		$groups = $this->groupManager->getUserGroups($user);
609
-		$userGroups = [];
610
-		foreach ($groups as $group) {
611
-			$userGroups[] = $group->getGID();
612
-		}
613
-
614
-		$query = 'SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted`
577
+        return (bool)$query->execute([$uid]);
578
+    }
579
+
580
+    /**
581
+     * return a list of shares which are not yet accepted by the user
582
+     *
583
+     * @return array list of open server-to-server shares
584
+     */
585
+    public function getOpenShares() {
586
+        return $this->getShares(false);
587
+    }
588
+
589
+    /**
590
+     * return a list of shares which are accepted by the user
591
+     *
592
+     * @return array list of accepted server-to-server shares
593
+     */
594
+    public function getAcceptedShares() {
595
+        return $this->getShares(true);
596
+    }
597
+
598
+    /**
599
+     * return a list of shares for the user
600
+     *
601
+     * @param bool|null $accepted True for accepted only,
602
+     *                            false for not accepted,
603
+     *                            null for all shares of the user
604
+     * @return array list of open server-to-server shares
605
+     */
606
+    private function getShares($accepted) {
607
+        $user = $this->userManager->get($this->uid);
608
+        $groups = $this->groupManager->getUserGroups($user);
609
+        $userGroups = [];
610
+        foreach ($groups as $group) {
611
+            $userGroups[] = $group->getGID();
612
+        }
613
+
614
+        $query = 'SELECT `id`, `remote`, `remote_id`, `share_token`, `name`, `owner`, `user`, `mountpoint`, `accepted`
615 615
 		          FROM `*PREFIX*share_external`
616 616
 				  WHERE (`user` = ? OR `user` IN (?))';
617
-		$parameters = [$this->uid, implode(',',$userGroups)];
618
-		if (!is_null($accepted)) {
619
-			$query .= ' AND `accepted` = ?';
620
-			$parameters[] = (int) $accepted;
621
-		}
622
-		$query .= ' ORDER BY `id` ASC';
623
-
624
-		$shares = $this->connection->prepare($query);
625
-		$result = $shares->execute($parameters);
626
-
627
-		return $result ? $shares->fetchAll() : [];
628
-	}
617
+        $parameters = [$this->uid, implode(',',$userGroups)];
618
+        if (!is_null($accepted)) {
619
+            $query .= ' AND `accepted` = ?';
620
+            $parameters[] = (int) $accepted;
621
+        }
622
+        $query .= ' ORDER BY `id` ASC';
623
+
624
+        $shares = $this->connection->prepare($query);
625
+        $result = $shares->execute($parameters);
626
+
627
+        return $result ? $shares->fetchAll() : [];
628
+    }
629 629
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Migration/Version11300Date20201120141438.php 1 patch
Indentation   +86 added lines, -86 removed lines patch added patch discarded remove patch
@@ -37,95 +37,95 @@
 block discarded – undo
37 37
 
38 38
 class Version11300Date20201120141438 extends SimpleMigrationStep {
39 39
 
40
-	/** @var IDBConnection */
41
-	private $connection;
40
+    /** @var IDBConnection */
41
+    private $connection;
42 42
 
43
-	public function __construct(IDBConnection $connection) {
44
-		$this->connection = $connection;
45
-	}
43
+    public function __construct(IDBConnection $connection) {
44
+        $this->connection = $connection;
45
+    }
46 46
 
47
-	public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
48
-		/** @var ISchemaWrapper $schema */
49
-		$schema = $schemaClosure();
47
+    public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
48
+        /** @var ISchemaWrapper $schema */
49
+        $schema = $schemaClosure();
50 50
 
51
-		if (!$schema->hasTable('share_external')) {
52
-			$table = $schema->createTable('share_external');
53
-			$table->addColumn('id', Types::BIGINT, [
54
-				'autoincrement' => true,
55
-				'notnull' => true,
56
-			]);
57
-			$table->addColumn('parent', Types::BIGINT, [
58
-				'notnull' => false,
59
-				'default' => -1,
60
-			]);
61
-			$table->addColumn('share_type', Types::INTEGER, [
62
-				'notnull' => false,
63
-				'length' => 4,
64
-			]);
65
-			$table->addColumn('remote', Types::STRING, [
66
-				'notnull' => true,
67
-				'length' => 512,
68
-			]);
69
-			$table->addColumn('remote_id', Types::STRING, [
70
-				'notnull' => false,
71
-				'length' => 255,
72
-				'default' => '',
73
-			]);
74
-			$table->addColumn('share_token', Types::STRING, [
75
-				'notnull' => true,
76
-				'length' => 64,
77
-			]);
78
-			$table->addColumn('password', Types::STRING, [
79
-				'notnull' => false,
80
-				'length' => 64,
81
-			]);
82
-			$table->addColumn('name', Types::STRING, [
83
-				'notnull' => true,
84
-				'length' => 64,
85
-			]);
86
-			$table->addColumn('owner', Types::STRING, [
87
-				'notnull' => true,
88
-				'length' => 64,
89
-			]);
90
-			$table->addColumn('user', Types::STRING, [
91
-				'notnull' => true,
92
-				'length' => 64,
93
-			]);
94
-			$table->addColumn('mountpoint', Types::STRING, [
95
-				'notnull' => true,
96
-				'length' => 4000,
97
-			]);
98
-			$table->addColumn('mountpoint_hash', Types::STRING, [
99
-				'notnull' => true,
100
-				'length' => 32,
101
-			]);
102
-			$table->addColumn('accepted', Types::INTEGER, [
103
-				'notnull' => true,
104
-				'length' => 4,
105
-				'default' => 0,
106
-			]);
107
-			$table->setPrimaryKey(['id']);
108
-			$table->addIndex(['user'], 'sh_external_user');
109
-			$table->addUniqueIndex(['user', 'mountpoint_hash'], 'sh_external_mp');
110
-		} else {
111
-			$table = $schema->getTable('share_external');
112
-			$remoteIdColumn = $table->getColumn('remote_id');
113
-			if ($remoteIdColumn && $remoteIdColumn->getType()->getName() !== Types::STRING) {
114
-				$remoteIdColumn->setNotnull(false);
115
-				$remoteIdColumn->setType(Type::getType(Types::STRING));
116
-				$remoteIdColumn->setOptions(['length' => 255]);
117
-				$remoteIdColumn->setDefault('');
118
-			}
119
-		}
51
+        if (!$schema->hasTable('share_external')) {
52
+            $table = $schema->createTable('share_external');
53
+            $table->addColumn('id', Types::BIGINT, [
54
+                'autoincrement' => true,
55
+                'notnull' => true,
56
+            ]);
57
+            $table->addColumn('parent', Types::BIGINT, [
58
+                'notnull' => false,
59
+                'default' => -1,
60
+            ]);
61
+            $table->addColumn('share_type', Types::INTEGER, [
62
+                'notnull' => false,
63
+                'length' => 4,
64
+            ]);
65
+            $table->addColumn('remote', Types::STRING, [
66
+                'notnull' => true,
67
+                'length' => 512,
68
+            ]);
69
+            $table->addColumn('remote_id', Types::STRING, [
70
+                'notnull' => false,
71
+                'length' => 255,
72
+                'default' => '',
73
+            ]);
74
+            $table->addColumn('share_token', Types::STRING, [
75
+                'notnull' => true,
76
+                'length' => 64,
77
+            ]);
78
+            $table->addColumn('password', Types::STRING, [
79
+                'notnull' => false,
80
+                'length' => 64,
81
+            ]);
82
+            $table->addColumn('name', Types::STRING, [
83
+                'notnull' => true,
84
+                'length' => 64,
85
+            ]);
86
+            $table->addColumn('owner', Types::STRING, [
87
+                'notnull' => true,
88
+                'length' => 64,
89
+            ]);
90
+            $table->addColumn('user', Types::STRING, [
91
+                'notnull' => true,
92
+                'length' => 64,
93
+            ]);
94
+            $table->addColumn('mountpoint', Types::STRING, [
95
+                'notnull' => true,
96
+                'length' => 4000,
97
+            ]);
98
+            $table->addColumn('mountpoint_hash', Types::STRING, [
99
+                'notnull' => true,
100
+                'length' => 32,
101
+            ]);
102
+            $table->addColumn('accepted', Types::INTEGER, [
103
+                'notnull' => true,
104
+                'length' => 4,
105
+                'default' => 0,
106
+            ]);
107
+            $table->setPrimaryKey(['id']);
108
+            $table->addIndex(['user'], 'sh_external_user');
109
+            $table->addUniqueIndex(['user', 'mountpoint_hash'], 'sh_external_mp');
110
+        } else {
111
+            $table = $schema->getTable('share_external');
112
+            $remoteIdColumn = $table->getColumn('remote_id');
113
+            if ($remoteIdColumn && $remoteIdColumn->getType()->getName() !== Types::STRING) {
114
+                $remoteIdColumn->setNotnull(false);
115
+                $remoteIdColumn->setType(Type::getType(Types::STRING));
116
+                $remoteIdColumn->setOptions(['length' => 255]);
117
+                $remoteIdColumn->setDefault('');
118
+            }
119
+        }
120 120
 
121
-		return $schema;
122
-	}
121
+        return $schema;
122
+    }
123 123
 
124
-	public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
125
-		$qb = $this->connection->getQueryBuilder();
126
-		$qb->update('share_external')
127
-			->set('remote_id', $qb->createNamedParameter(''))
128
-			->where($qb->expr()->eq('remote_id', $qb->createNamedParameter('-1')));
129
-		$qb->execute();
130
-	}
124
+    public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
125
+        $qb = $this->connection->getQueryBuilder();
126
+        $qb->update('share_external')
127
+            ->set('remote_id', $qb->createNamedParameter(''))
128
+            ->where($qb->expr()->eq('remote_id', $qb->createNamedParameter('-1')));
129
+        $qb->execute();
130
+    }
131 131
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/AppInfo/Application.php 1 patch
Indentation   +175 added lines, -175 removed lines patch added patch discarded remove patch
@@ -63,179 +63,179 @@
 block discarded – undo
63 63
 use Symfony\Component\EventDispatcher\GenericEvent;
64 64
 
65 65
 class Application extends App {
66
-	public const APP_ID = 'files_sharing';
67
-
68
-	public function __construct(array $urlParams = []) {
69
-		parent::__construct(self::APP_ID, $urlParams);
70
-
71
-		$container = $this->getContainer();
72
-
73
-		/** @var IServerContainer $server */
74
-		$server = $container->getServer();
75
-
76
-		/** @var IEventDispatcher $dispatcher */
77
-		$dispatcher = $container->query(IEventDispatcher::class);
78
-		$oldDispatcher = $container->getServer()->getEventDispatcher();
79
-		$mountProviderCollection = $server->getMountProviderCollection();
80
-		$notifications = $server->getNotificationManager();
81
-
82
-		/**
83
-		 * Core class wrappers
84
-		 */
85
-		$container->registerService(Manager::class, function (SimpleContainer $c) use ($server) {
86
-			$user = $server->getUserSession()->getUser();
87
-			$uid = $user ? $user->getUID() : null;
88
-			return new \OCA\Files_Sharing\External\Manager(
89
-				$server->getDatabaseConnection(),
90
-				\OC\Files\Filesystem::getMountManager(),
91
-				\OC\Files\Filesystem::getLoader(),
92
-				$server->getHTTPClientService(),
93
-				$server->getNotificationManager(),
94
-				$server->query(\OCP\OCS\IDiscoveryService::class),
95
-				$server->getCloudFederationProviderManager(),
96
-				$server->getCloudFederationFactory(),
97
-				$server->getGroupManager(),
98
-				$server->getUserManager(),
99
-				$uid,
100
-				$server->query(IEventDispatcher::class)
101
-			);
102
-		});
103
-
104
-		/**
105
-		 * Middleware
106
-		 */
107
-		$container->registerMiddleWare(SharingCheckMiddleware::class);
108
-		$container->registerMiddleWare(OCSShareAPIMiddleware::class);
109
-		$container->registerMiddleWare(ShareInfoMiddleware::class);
110
-
111
-		$container->registerService('ExternalMountProvider', function (ContainerInterface $c) {
112
-			return new \OCA\Files_Sharing\External\MountProvider(
113
-				$c->get(IDBConnection::class),
114
-				function () use ($c) {
115
-					return $c->get(Manager::class);
116
-				},
117
-				$c->get(ICloudIdManager::class)
118
-			);
119
-		});
120
-
121
-		/**
122
-		 * Register capabilities
123
-		 */
124
-		$container->registerCapability(Capabilities::class);
125
-
126
-		$notifications->registerNotifierService(Notifier::class);
127
-
128
-		$this->registerMountProviders($mountProviderCollection);
129
-		$this->registerEventsScripts($dispatcher, $oldDispatcher);
130
-		$this->setupSharingMenus();
131
-
132
-		/**
133
-		 * Always add main sharing script
134
-		 */
135
-		Util::addScript(self::APP_ID, 'dist/main');
136
-	}
137
-
138
-	protected function registerMountProviders(IMountProviderCollection $mountProviderCollection) {
139
-		$mountProviderCollection->registerProvider($this->getContainer()->query(MountProvider::class));
140
-		$mountProviderCollection->registerProvider($this->getContainer()->query('ExternalMountProvider'));
141
-	}
142
-
143
-	protected function registerEventsScripts(IEventDispatcher $dispatcher, EventDispatcherInterface $oldDispatcher) {
144
-		// sidebar and files scripts
145
-		$dispatcher->addServiceListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class);
146
-		$dispatcher->addServiceListener(BeforeTemplateRenderedEvent::class, LegacyBeforeTemplateRenderedListener::class);
147
-		$dispatcher->addServiceListener(LoadSidebar::class, LoadSidebarListener::class);
148
-		$dispatcher->addServiceListener(ShareCreatedEvent::class, ShareInteractionListener::class);
149
-		$dispatcher->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', function () {
150
-			\OCP\Util::addScript('files_sharing', 'dist/collaboration');
151
-		});
152
-		$dispatcher->addServiceListener(ShareCreatedEvent::class, UserShareAcceptanceListener::class);
153
-		$dispatcher->addServiceListener(UserAddedEvent::class, UserAddedToGroupListener::class);
154
-
155
-		// notifications api to accept incoming user shares
156
-		$oldDispatcher->addListener('OCP\Share::postShare', function (GenericEvent $event) {
157
-			/** @var Listener $listener */
158
-			$listener = $this->getContainer()->query(Listener::class);
159
-			$listener->shareNotification($event);
160
-		});
161
-		$oldDispatcher->addListener(IGroup::class . '::postAddUser', function (GenericEvent $event) {
162
-			/** @var Listener $listener */
163
-			$listener = $this->getContainer()->query(Listener::class);
164
-			$listener->userAddedToGroup($event);
165
-		});
166
-	}
167
-
168
-	protected function setupSharingMenus() {
169
-		$config = \OC::$server->getConfig();
170
-
171
-		if ($config->getAppValue('core', 'shareapi_enabled', 'yes') !== 'yes' || !class_exists('\OCA\Files\App')) {
172
-			return;
173
-		}
174
-
175
-		// show_Quick_Access stored as string
176
-		\OCA\Files\App::getNavigationManager()->add(function () {
177
-			$config = \OC::$server->getConfig();
178
-			$l = \OC::$server->getL10N('files_sharing');
179
-
180
-			$sharingSublistArray = [];
181
-
182
-			if (\OCP\Util::isSharingDisabledForUser() === false) {
183
-				$sharingSublistArray[] = [
184
-					'id' => 'sharingout',
185
-					'appname' => 'files_sharing',
186
-					'script' => 'list.php',
187
-					'order' => 16,
188
-					'name' => $l->t('Shared with others'),
189
-				];
190
-			}
191
-
192
-			$sharingSublistArray[] = [
193
-				'id' => 'sharingin',
194
-				'appname' => 'files_sharing',
195
-				'script' => 'list.php',
196
-				'order' => 15,
197
-				'name' => $l->t('Shared with you'),
198
-			];
199
-
200
-			if (\OCP\Util::isSharingDisabledForUser() === false) {
201
-				// Check if sharing by link is enabled
202
-				if ($config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes') {
203
-					$sharingSublistArray[] = [
204
-						'id' => 'sharinglinks',
205
-						'appname' => 'files_sharing',
206
-						'script' => 'list.php',
207
-						'order' => 17,
208
-						'name' => $l->t('Shared by link'),
209
-					];
210
-				}
211
-			}
212
-
213
-			$sharingSublistArray[] = [
214
-				'id' => 'deletedshares',
215
-				'appname' => 'files_sharing',
216
-				'script' => 'list.php',
217
-				'order' => 19,
218
-				'name' => $l->t('Deleted shares'),
219
-			];
220
-
221
-			$sharingSublistArray[] = [
222
-				'id' => 'pendingshares',
223
-				'appname' => 'files_sharing',
224
-				'script' => 'list.php',
225
-				'order' => 19,
226
-				'name' => $l->t('Pending shares'),
227
-			];
228
-
229
-			return [
230
-				'id' => 'shareoverview',
231
-				'appname' => 'files_sharing',
232
-				'script' => 'list.php',
233
-				'order' => 18,
234
-				'name' => $l->t('Shares'),
235
-				'classes' => 'collapsible',
236
-				'sublist' => $sharingSublistArray,
237
-				'expandedState' => 'show_sharing_menu'
238
-			];
239
-		});
240
-	}
66
+    public const APP_ID = 'files_sharing';
67
+
68
+    public function __construct(array $urlParams = []) {
69
+        parent::__construct(self::APP_ID, $urlParams);
70
+
71
+        $container = $this->getContainer();
72
+
73
+        /** @var IServerContainer $server */
74
+        $server = $container->getServer();
75
+
76
+        /** @var IEventDispatcher $dispatcher */
77
+        $dispatcher = $container->query(IEventDispatcher::class);
78
+        $oldDispatcher = $container->getServer()->getEventDispatcher();
79
+        $mountProviderCollection = $server->getMountProviderCollection();
80
+        $notifications = $server->getNotificationManager();
81
+
82
+        /**
83
+         * Core class wrappers
84
+         */
85
+        $container->registerService(Manager::class, function (SimpleContainer $c) use ($server) {
86
+            $user = $server->getUserSession()->getUser();
87
+            $uid = $user ? $user->getUID() : null;
88
+            return new \OCA\Files_Sharing\External\Manager(
89
+                $server->getDatabaseConnection(),
90
+                \OC\Files\Filesystem::getMountManager(),
91
+                \OC\Files\Filesystem::getLoader(),
92
+                $server->getHTTPClientService(),
93
+                $server->getNotificationManager(),
94
+                $server->query(\OCP\OCS\IDiscoveryService::class),
95
+                $server->getCloudFederationProviderManager(),
96
+                $server->getCloudFederationFactory(),
97
+                $server->getGroupManager(),
98
+                $server->getUserManager(),
99
+                $uid,
100
+                $server->query(IEventDispatcher::class)
101
+            );
102
+        });
103
+
104
+        /**
105
+         * Middleware
106
+         */
107
+        $container->registerMiddleWare(SharingCheckMiddleware::class);
108
+        $container->registerMiddleWare(OCSShareAPIMiddleware::class);
109
+        $container->registerMiddleWare(ShareInfoMiddleware::class);
110
+
111
+        $container->registerService('ExternalMountProvider', function (ContainerInterface $c) {
112
+            return new \OCA\Files_Sharing\External\MountProvider(
113
+                $c->get(IDBConnection::class),
114
+                function () use ($c) {
115
+                    return $c->get(Manager::class);
116
+                },
117
+                $c->get(ICloudIdManager::class)
118
+            );
119
+        });
120
+
121
+        /**
122
+         * Register capabilities
123
+         */
124
+        $container->registerCapability(Capabilities::class);
125
+
126
+        $notifications->registerNotifierService(Notifier::class);
127
+
128
+        $this->registerMountProviders($mountProviderCollection);
129
+        $this->registerEventsScripts($dispatcher, $oldDispatcher);
130
+        $this->setupSharingMenus();
131
+
132
+        /**
133
+         * Always add main sharing script
134
+         */
135
+        Util::addScript(self::APP_ID, 'dist/main');
136
+    }
137
+
138
+    protected function registerMountProviders(IMountProviderCollection $mountProviderCollection) {
139
+        $mountProviderCollection->registerProvider($this->getContainer()->query(MountProvider::class));
140
+        $mountProviderCollection->registerProvider($this->getContainer()->query('ExternalMountProvider'));
141
+    }
142
+
143
+    protected function registerEventsScripts(IEventDispatcher $dispatcher, EventDispatcherInterface $oldDispatcher) {
144
+        // sidebar and files scripts
145
+        $dispatcher->addServiceListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class);
146
+        $dispatcher->addServiceListener(BeforeTemplateRenderedEvent::class, LegacyBeforeTemplateRenderedListener::class);
147
+        $dispatcher->addServiceListener(LoadSidebar::class, LoadSidebarListener::class);
148
+        $dispatcher->addServiceListener(ShareCreatedEvent::class, ShareInteractionListener::class);
149
+        $dispatcher->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', function () {
150
+            \OCP\Util::addScript('files_sharing', 'dist/collaboration');
151
+        });
152
+        $dispatcher->addServiceListener(ShareCreatedEvent::class, UserShareAcceptanceListener::class);
153
+        $dispatcher->addServiceListener(UserAddedEvent::class, UserAddedToGroupListener::class);
154
+
155
+        // notifications api to accept incoming user shares
156
+        $oldDispatcher->addListener('OCP\Share::postShare', function (GenericEvent $event) {
157
+            /** @var Listener $listener */
158
+            $listener = $this->getContainer()->query(Listener::class);
159
+            $listener->shareNotification($event);
160
+        });
161
+        $oldDispatcher->addListener(IGroup::class . '::postAddUser', function (GenericEvent $event) {
162
+            /** @var Listener $listener */
163
+            $listener = $this->getContainer()->query(Listener::class);
164
+            $listener->userAddedToGroup($event);
165
+        });
166
+    }
167
+
168
+    protected function setupSharingMenus() {
169
+        $config = \OC::$server->getConfig();
170
+
171
+        if ($config->getAppValue('core', 'shareapi_enabled', 'yes') !== 'yes' || !class_exists('\OCA\Files\App')) {
172
+            return;
173
+        }
174
+
175
+        // show_Quick_Access stored as string
176
+        \OCA\Files\App::getNavigationManager()->add(function () {
177
+            $config = \OC::$server->getConfig();
178
+            $l = \OC::$server->getL10N('files_sharing');
179
+
180
+            $sharingSublistArray = [];
181
+
182
+            if (\OCP\Util::isSharingDisabledForUser() === false) {
183
+                $sharingSublistArray[] = [
184
+                    'id' => 'sharingout',
185
+                    'appname' => 'files_sharing',
186
+                    'script' => 'list.php',
187
+                    'order' => 16,
188
+                    'name' => $l->t('Shared with others'),
189
+                ];
190
+            }
191
+
192
+            $sharingSublistArray[] = [
193
+                'id' => 'sharingin',
194
+                'appname' => 'files_sharing',
195
+                'script' => 'list.php',
196
+                'order' => 15,
197
+                'name' => $l->t('Shared with you'),
198
+            ];
199
+
200
+            if (\OCP\Util::isSharingDisabledForUser() === false) {
201
+                // Check if sharing by link is enabled
202
+                if ($config->getAppValue('core', 'shareapi_allow_links', 'yes') === 'yes') {
203
+                    $sharingSublistArray[] = [
204
+                        'id' => 'sharinglinks',
205
+                        'appname' => 'files_sharing',
206
+                        'script' => 'list.php',
207
+                        'order' => 17,
208
+                        'name' => $l->t('Shared by link'),
209
+                    ];
210
+                }
211
+            }
212
+
213
+            $sharingSublistArray[] = [
214
+                'id' => 'deletedshares',
215
+                'appname' => 'files_sharing',
216
+                'script' => 'list.php',
217
+                'order' => 19,
218
+                'name' => $l->t('Deleted shares'),
219
+            ];
220
+
221
+            $sharingSublistArray[] = [
222
+                'id' => 'pendingshares',
223
+                'appname' => 'files_sharing',
224
+                'script' => 'list.php',
225
+                'order' => 19,
226
+                'name' => $l->t('Pending shares'),
227
+            ];
228
+
229
+            return [
230
+                'id' => 'shareoverview',
231
+                'appname' => 'files_sharing',
232
+                'script' => 'list.php',
233
+                'order' => 18,
234
+                'name' => $l->t('Shares'),
235
+                'classes' => 'collapsible',
236
+                'sublist' => $sharingSublistArray,
237
+                'expandedState' => 'show_sharing_menu'
238
+            ];
239
+        });
240
+    }
241 241
 }
Please login to merge, or discard this patch.