Passed
Push — master ( 62403d...0c3e2f )
by Joas
14:50 queued 14s
created
apps/encryption/lib/AppInfo/Application.php 1 patch
Indentation   +213 added lines, -213 removed lines patch added patch discarded remove patch
@@ -50,217 +50,217 @@
 block discarded – undo
50 50
 
51 51
 class Application extends \OCP\AppFramework\App {
52 52
 
53
-	/** @var IManager */
54
-	private $encryptionManager;
55
-	/** @var IConfig */
56
-	private $config;
57
-
58
-	/**
59
-	 * @param array $urlParams
60
-	 */
61
-	public function __construct($urlParams = []) {
62
-		parent::__construct('encryption', $urlParams);
63
-		$this->encryptionManager = \OC::$server->getEncryptionManager();
64
-		$this->config = \OC::$server->getConfig();
65
-		$this->registerServices();
66
-	}
67
-
68
-	public function setUp() {
69
-		if ($this->encryptionManager->isEnabled()) {
70
-			/** @var Setup $setup */
71
-			$setup = $this->getContainer()->query('UserSetup');
72
-			$setup->setupSystem();
73
-		}
74
-	}
75
-
76
-	/**
77
-	 * register hooks
78
-	 */
79
-	public function registerHooks() {
80
-		if (!$this->config->getSystemValueBool('maintenance')) {
81
-
82
-			$container = $this->getContainer();
83
-			$server = $container->getServer();
84
-			// Register our hooks and fire them.
85
-			$hookManager = new HookManager();
86
-
87
-			$hookManager->registerHook([
88
-				new UserHooks($container->query('KeyManager'),
89
-					$server->getUserManager(),
90
-					$server->getLogger(),
91
-					$container->query('UserSetup'),
92
-					$server->getUserSession(),
93
-					$container->query('Util'),
94
-					$container->query('Session'),
95
-					$container->query('Crypt'),
96
-					$container->query('Recovery'))
97
-			]);
98
-
99
-			$hookManager->fireHooks();
100
-
101
-		} else {
102
-			// Logout user if we are in maintenance to force re-login
103
-			$this->getContainer()->getServer()->getUserSession()->logout();
104
-		}
105
-	}
106
-
107
-	public function registerEncryptionModule() {
108
-		$container = $this->getContainer();
109
-
110
-
111
-		$this->encryptionManager->registerEncryptionModule(
112
-			Encryption::ID,
113
-			Encryption::DISPLAY_NAME,
114
-			function() use ($container) {
115
-
116
-			return new Encryption(
117
-				$container->query('Crypt'),
118
-				$container->query('KeyManager'),
119
-				$container->query('Util'),
120
-				$container->query('Session'),
121
-				$container->query('EncryptAll'),
122
-				$container->query('DecryptAll'),
123
-				$container->getServer()->getLogger(),
124
-				$container->getServer()->getL10N($container->getAppName())
125
-			);
126
-		});
127
-
128
-	}
129
-
130
-	public function registerServices() {
131
-		$container = $this->getContainer();
132
-
133
-		$container->registerService('Crypt',
134
-			function (IAppContainer $c) {
135
-				$server = $c->getServer();
136
-				return new Crypt($server->getLogger(),
137
-					$server->getUserSession(),
138
-					$server->getConfig(),
139
-					$server->getL10N($c->getAppName()));
140
-			});
141
-
142
-		$container->registerService('Session',
143
-			function (IAppContainer $c) {
144
-				$server = $c->getServer();
145
-				return new Session($server->getSession());
146
-			}
147
-		);
148
-
149
-		$container->registerService('KeyManager',
150
-			function (IAppContainer $c) {
151
-				$server = $c->getServer();
152
-
153
-				return new KeyManager($server->getEncryptionKeyStorage(),
154
-					$c->query('Crypt'),
155
-					$server->getConfig(),
156
-					$server->getUserSession(),
157
-					new Session($server->getSession()),
158
-					$server->getLogger(),
159
-					$c->query('Util')
160
-				);
161
-			});
162
-
163
-		$container->registerService('Recovery',
164
-			function (IAppContainer $c) {
165
-				$server = $c->getServer();
166
-
167
-				return new Recovery(
168
-					$server->getUserSession(),
169
-					$c->query('Crypt'),
170
-					$c->query('KeyManager'),
171
-					$server->getConfig(),
172
-					$server->getEncryptionFilesHelper(),
173
-					new View());
174
-			});
175
-
176
-		$container->registerService('RecoveryController', function (IAppContainer $c) {
177
-			$server = $c->getServer();
178
-			return new RecoveryController(
179
-				$c->getAppName(),
180
-				$server->getRequest(),
181
-				$server->getConfig(),
182
-				$server->getL10N($c->getAppName()),
183
-				$c->query('Recovery'));
184
-		});
185
-
186
-		$container->registerService('StatusController', function (IAppContainer $c) {
187
-			$server = $c->getServer();
188
-			return new StatusController(
189
-				$c->getAppName(),
190
-				$server->getRequest(),
191
-				$server->getL10N($c->getAppName()),
192
-				$c->query('Session'),
193
-				$server->getEncryptionManager()
194
-			);
195
-		});
196
-
197
-		$container->registerService('SettingsController', function (IAppContainer $c) {
198
-			$server = $c->getServer();
199
-			return new SettingsController(
200
-				$c->getAppName(),
201
-				$server->getRequest(),
202
-				$server->getL10N($c->getAppName()),
203
-				$server->getUserManager(),
204
-				$server->getUserSession(),
205
-				$c->query('KeyManager'),
206
-				$c->query('Crypt'),
207
-				$c->query('Session'),
208
-				$server->getSession(),
209
-				$c->query('Util')
210
-			);
211
-		});
212
-
213
-		$container->registerService('UserSetup',
214
-			function (IAppContainer $c) {
215
-				$server = $c->getServer();
216
-				return new Setup($server->getLogger(),
217
-					$server->getUserSession(),
218
-					$c->query('Crypt'),
219
-					$c->query('KeyManager'));
220
-			});
221
-
222
-		$container->registerService('Util',
223
-			function (IAppContainer $c) {
224
-				$server = $c->getServer();
225
-
226
-				return new Util(
227
-					new View(),
228
-					$c->query('Crypt'),
229
-					$server->getLogger(),
230
-					$server->getUserSession(),
231
-					$server->getConfig(),
232
-					$server->getUserManager());
233
-			});
234
-
235
-		$container->registerService('EncryptAll',
236
-			function (IAppContainer $c) {
237
-				$server = $c->getServer();
238
-				return new EncryptAll(
239
-					$c->query('UserSetup'),
240
-					$c->getServer()->getUserManager(),
241
-					new View(),
242
-					$c->query('KeyManager'),
243
-					$c->query('Util'),
244
-					$server->getConfig(),
245
-					$server->getMailer(),
246
-					$server->getL10N('encryption'),
247
-					new QuestionHelper(),
248
-					$server->getSecureRandom()
249
-				);
250
-			}
251
-		);
252
-
253
-		$container->registerService('DecryptAll',
254
-			function (IAppContainer $c) {
255
-				return new DecryptAll(
256
-					$c->query('Util'),
257
-					$c->query('KeyManager'),
258
-					$c->query('Crypt'),
259
-					$c->query('Session'),
260
-					new QuestionHelper()
261
-				);
262
-			}
263
-		);
264
-
265
-	}
53
+    /** @var IManager */
54
+    private $encryptionManager;
55
+    /** @var IConfig */
56
+    private $config;
57
+
58
+    /**
59
+     * @param array $urlParams
60
+     */
61
+    public function __construct($urlParams = []) {
62
+        parent::__construct('encryption', $urlParams);
63
+        $this->encryptionManager = \OC::$server->getEncryptionManager();
64
+        $this->config = \OC::$server->getConfig();
65
+        $this->registerServices();
66
+    }
67
+
68
+    public function setUp() {
69
+        if ($this->encryptionManager->isEnabled()) {
70
+            /** @var Setup $setup */
71
+            $setup = $this->getContainer()->query('UserSetup');
72
+            $setup->setupSystem();
73
+        }
74
+    }
75
+
76
+    /**
77
+     * register hooks
78
+     */
79
+    public function registerHooks() {
80
+        if (!$this->config->getSystemValueBool('maintenance')) {
81
+
82
+            $container = $this->getContainer();
83
+            $server = $container->getServer();
84
+            // Register our hooks and fire them.
85
+            $hookManager = new HookManager();
86
+
87
+            $hookManager->registerHook([
88
+                new UserHooks($container->query('KeyManager'),
89
+                    $server->getUserManager(),
90
+                    $server->getLogger(),
91
+                    $container->query('UserSetup'),
92
+                    $server->getUserSession(),
93
+                    $container->query('Util'),
94
+                    $container->query('Session'),
95
+                    $container->query('Crypt'),
96
+                    $container->query('Recovery'))
97
+            ]);
98
+
99
+            $hookManager->fireHooks();
100
+
101
+        } else {
102
+            // Logout user if we are in maintenance to force re-login
103
+            $this->getContainer()->getServer()->getUserSession()->logout();
104
+        }
105
+    }
106
+
107
+    public function registerEncryptionModule() {
108
+        $container = $this->getContainer();
109
+
110
+
111
+        $this->encryptionManager->registerEncryptionModule(
112
+            Encryption::ID,
113
+            Encryption::DISPLAY_NAME,
114
+            function() use ($container) {
115
+
116
+            return new Encryption(
117
+                $container->query('Crypt'),
118
+                $container->query('KeyManager'),
119
+                $container->query('Util'),
120
+                $container->query('Session'),
121
+                $container->query('EncryptAll'),
122
+                $container->query('DecryptAll'),
123
+                $container->getServer()->getLogger(),
124
+                $container->getServer()->getL10N($container->getAppName())
125
+            );
126
+        });
127
+
128
+    }
129
+
130
+    public function registerServices() {
131
+        $container = $this->getContainer();
132
+
133
+        $container->registerService('Crypt',
134
+            function (IAppContainer $c) {
135
+                $server = $c->getServer();
136
+                return new Crypt($server->getLogger(),
137
+                    $server->getUserSession(),
138
+                    $server->getConfig(),
139
+                    $server->getL10N($c->getAppName()));
140
+            });
141
+
142
+        $container->registerService('Session',
143
+            function (IAppContainer $c) {
144
+                $server = $c->getServer();
145
+                return new Session($server->getSession());
146
+            }
147
+        );
148
+
149
+        $container->registerService('KeyManager',
150
+            function (IAppContainer $c) {
151
+                $server = $c->getServer();
152
+
153
+                return new KeyManager($server->getEncryptionKeyStorage(),
154
+                    $c->query('Crypt'),
155
+                    $server->getConfig(),
156
+                    $server->getUserSession(),
157
+                    new Session($server->getSession()),
158
+                    $server->getLogger(),
159
+                    $c->query('Util')
160
+                );
161
+            });
162
+
163
+        $container->registerService('Recovery',
164
+            function (IAppContainer $c) {
165
+                $server = $c->getServer();
166
+
167
+                return new Recovery(
168
+                    $server->getUserSession(),
169
+                    $c->query('Crypt'),
170
+                    $c->query('KeyManager'),
171
+                    $server->getConfig(),
172
+                    $server->getEncryptionFilesHelper(),
173
+                    new View());
174
+            });
175
+
176
+        $container->registerService('RecoveryController', function (IAppContainer $c) {
177
+            $server = $c->getServer();
178
+            return new RecoveryController(
179
+                $c->getAppName(),
180
+                $server->getRequest(),
181
+                $server->getConfig(),
182
+                $server->getL10N($c->getAppName()),
183
+                $c->query('Recovery'));
184
+        });
185
+
186
+        $container->registerService('StatusController', function (IAppContainer $c) {
187
+            $server = $c->getServer();
188
+            return new StatusController(
189
+                $c->getAppName(),
190
+                $server->getRequest(),
191
+                $server->getL10N($c->getAppName()),
192
+                $c->query('Session'),
193
+                $server->getEncryptionManager()
194
+            );
195
+        });
196
+
197
+        $container->registerService('SettingsController', function (IAppContainer $c) {
198
+            $server = $c->getServer();
199
+            return new SettingsController(
200
+                $c->getAppName(),
201
+                $server->getRequest(),
202
+                $server->getL10N($c->getAppName()),
203
+                $server->getUserManager(),
204
+                $server->getUserSession(),
205
+                $c->query('KeyManager'),
206
+                $c->query('Crypt'),
207
+                $c->query('Session'),
208
+                $server->getSession(),
209
+                $c->query('Util')
210
+            );
211
+        });
212
+
213
+        $container->registerService('UserSetup',
214
+            function (IAppContainer $c) {
215
+                $server = $c->getServer();
216
+                return new Setup($server->getLogger(),
217
+                    $server->getUserSession(),
218
+                    $c->query('Crypt'),
219
+                    $c->query('KeyManager'));
220
+            });
221
+
222
+        $container->registerService('Util',
223
+            function (IAppContainer $c) {
224
+                $server = $c->getServer();
225
+
226
+                return new Util(
227
+                    new View(),
228
+                    $c->query('Crypt'),
229
+                    $server->getLogger(),
230
+                    $server->getUserSession(),
231
+                    $server->getConfig(),
232
+                    $server->getUserManager());
233
+            });
234
+
235
+        $container->registerService('EncryptAll',
236
+            function (IAppContainer $c) {
237
+                $server = $c->getServer();
238
+                return new EncryptAll(
239
+                    $c->query('UserSetup'),
240
+                    $c->getServer()->getUserManager(),
241
+                    new View(),
242
+                    $c->query('KeyManager'),
243
+                    $c->query('Util'),
244
+                    $server->getConfig(),
245
+                    $server->getMailer(),
246
+                    $server->getL10N('encryption'),
247
+                    new QuestionHelper(),
248
+                    $server->getSecureRandom()
249
+                );
250
+            }
251
+        );
252
+
253
+        $container->registerService('DecryptAll',
254
+            function (IAppContainer $c) {
255
+                return new DecryptAll(
256
+                    $c->query('Util'),
257
+                    $c->query('KeyManager'),
258
+                    $c->query('Crypt'),
259
+                    $c->query('Session'),
260
+                    new QuestionHelper()
261
+                );
262
+            }
263
+        );
264
+
265
+    }
266 266
 }
Please login to merge, or discard this patch.
apps/encryption/lib/Recovery.php 1 patch
Indentation   +273 added lines, -273 removed lines patch added patch discarded remove patch
@@ -38,279 +38,279 @@
 block discarded – undo
38 38
 class Recovery {
39 39
 
40 40
 
41
-	/**
42
-	 * @var null|IUser
43
-	 */
44
-	protected $user;
45
-	/**
46
-	 * @var Crypt
47
-	 */
48
-	protected $crypt;
49
-	/**
50
-	 * @var KeyManager
51
-	 */
52
-	private $keyManager;
53
-	/**
54
-	 * @var IConfig
55
-	 */
56
-	private $config;
57
-	/**
58
-	 * @var View
59
-	 */
60
-	private $view;
61
-	/**
62
-	 * @var IFile
63
-	 */
64
-	private $file;
65
-
66
-	/**
67
-	 * @param IUserSession $userSession
68
-	 * @param Crypt $crypt
69
-	 * @param KeyManager $keyManager
70
-	 * @param IConfig $config
71
-	 * @param IFile $file
72
-	 * @param View $view
73
-	 */
74
-	public function __construct(IUserSession $userSession,
75
-								Crypt $crypt,
76
-								KeyManager $keyManager,
77
-								IConfig $config,
78
-								IFile $file,
79
-								View $view) {
80
-		$this->user = ($userSession && $userSession->isLoggedIn()) ? $userSession->getUser() : false;
81
-		$this->crypt = $crypt;
82
-		$this->keyManager = $keyManager;
83
-		$this->config = $config;
84
-		$this->view = $view;
85
-		$this->file = $file;
86
-	}
87
-
88
-	/**
89
-	 * @param string $password
90
-	 * @return bool
91
-	 */
92
-	public function enableAdminRecovery($password) {
93
-		$appConfig = $this->config;
94
-		$keyManager = $this->keyManager;
95
-
96
-		if (!$keyManager->recoveryKeyExists()) {
97
-			$keyPair = $this->crypt->createKeyPair();
98
-			if(!is_array($keyPair)) {
99
-				return false;
100
-			}
101
-
102
-			$this->keyManager->setRecoveryKey($password, $keyPair);
103
-		}
104
-
105
-		if ($keyManager->checkRecoveryPassword($password)) {
106
-			$appConfig->setAppValue('encryption', 'recoveryAdminEnabled', 1);
107
-			return true;
108
-		}
109
-
110
-		return false;
111
-	}
112
-
113
-	/**
114
-	 * change recovery key id
115
-	 *
116
-	 * @param string $newPassword
117
-	 * @param string $oldPassword
118
-	 * @return bool
119
-	 */
120
-	public function changeRecoveryKeyPassword($newPassword, $oldPassword) {
121
-		$recoveryKey = $this->keyManager->getSystemPrivateKey($this->keyManager->getRecoveryKeyId());
122
-		$decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey, $oldPassword);
123
-		if($decryptedRecoveryKey === false) {
124
-			return false;
125
-		}
126
-		$encryptedRecoveryKey = $this->crypt->encryptPrivateKey($decryptedRecoveryKey, $newPassword);
127
-		$header = $this->crypt->generateHeader();
128
-		if ($encryptedRecoveryKey) {
129
-			$this->keyManager->setSystemPrivateKey($this->keyManager->getRecoveryKeyId(), $header . $encryptedRecoveryKey);
130
-			return true;
131
-		}
132
-		return false;
133
-	}
134
-
135
-	/**
136
-	 * @param string $recoveryPassword
137
-	 * @return bool
138
-	 */
139
-	public function disableAdminRecovery($recoveryPassword) {
140
-		$keyManager = $this->keyManager;
141
-
142
-		if ($keyManager->checkRecoveryPassword($recoveryPassword)) {
143
-			// Set recoveryAdmin as disabled
144
-			$this->config->setAppValue('encryption', 'recoveryAdminEnabled', 0);
145
-			return true;
146
-		}
147
-		return false;
148
-	}
149
-
150
-	/**
151
-	 * check if recovery is enabled for user
152
-	 *
153
-	 * @param string $user if no user is given we check the current logged-in user
154
-	 *
155
-	 * @return bool
156
-	 */
157
-	public function isRecoveryEnabledForUser($user = '') {
158
-		$uid = $user === '' ? $this->user->getUID() : $user;
159
-		$recoveryMode = $this->config->getUserValue($uid,
160
-			'encryption',
161
-			'recoveryEnabled',
162
-			0);
163
-
164
-		return ($recoveryMode === '1');
165
-	}
166
-
167
-	/**
168
-	 * check if recovery is key is enabled by the administrator
169
-	 *
170
-	 * @return bool
171
-	 */
172
-	public function isRecoveryKeyEnabled() {
173
-		$enabled = $this->config->getAppValue('encryption', 'recoveryAdminEnabled', 0);
174
-
175
-		return ($enabled === '1');
176
-	}
177
-
178
-	/**
179
-	 * @param string $value
180
-	 * @return bool
181
-	 */
182
-	public function setRecoveryForUser($value) {
183
-
184
-		try {
185
-			$this->config->setUserValue($this->user->getUID(),
186
-				'encryption',
187
-				'recoveryEnabled',
188
-				$value);
189
-
190
-			if ($value === '1') {
191
-				$this->addRecoveryKeys('/' . $this->user->getUID() . '/files/');
192
-			} else {
193
-				$this->removeRecoveryKeys('/' . $this->user->getUID() . '/files/');
194
-			}
195
-
196
-			return true;
197
-		} catch (PreConditionNotMetException $e) {
198
-			return false;
199
-		}
200
-	}
201
-
202
-	/**
203
-	 * add recovery key to all encrypted files
204
-	 * @param string $path
205
-	 */
206
-	private function addRecoveryKeys($path) {
207
-		$dirContent = $this->view->getDirectoryContent($path);
208
-		foreach ($dirContent as $item) {
209
-			$filePath = $item->getPath();
210
-			if ($item['type'] === 'dir') {
211
-				$this->addRecoveryKeys($filePath . '/');
212
-			} else {
213
-				$fileKey = $this->keyManager->getFileKey($filePath, $this->user->getUID());
214
-				if (!empty($fileKey)) {
215
-					$accessList = $this->file->getAccessList($filePath);
216
-					$publicKeys = [];
217
-					foreach ($accessList['users'] as $uid) {
218
-						$publicKeys[$uid] = $this->keyManager->getPublicKey($uid);
219
-					}
220
-
221
-					$publicKeys = $this->keyManager->addSystemKeys($accessList, $publicKeys, $this->user->getUID());
222
-
223
-					$encryptedKeyfiles = $this->crypt->multiKeyEncrypt($fileKey, $publicKeys);
224
-					$this->keyManager->setAllFileKeys($filePath, $encryptedKeyfiles);
225
-				}
226
-			}
227
-		}
228
-	}
229
-
230
-	/**
231
-	 * remove recovery key to all encrypted files
232
-	 * @param string $path
233
-	 */
234
-	private function removeRecoveryKeys($path) {
235
-		$dirContent = $this->view->getDirectoryContent($path);
236
-		foreach ($dirContent as $item) {
237
-			$filePath = $item->getPath();
238
-			if ($item['type'] === 'dir') {
239
-				$this->removeRecoveryKeys($filePath . '/');
240
-			} else {
241
-				$this->keyManager->deleteShareKey($filePath, $this->keyManager->getRecoveryKeyId());
242
-			}
243
-		}
244
-	}
245
-
246
-	/**
247
-	 * recover users files with the recovery key
248
-	 *
249
-	 * @param string $recoveryPassword
250
-	 * @param string $user
251
-	 */
252
-	public function recoverUsersFiles($recoveryPassword, $user) {
253
-		$encryptedKey = $this->keyManager->getSystemPrivateKey($this->keyManager->getRecoveryKeyId());
254
-
255
-		$privateKey = $this->crypt->decryptPrivateKey($encryptedKey, $recoveryPassword);
256
-		if($privateKey !== false) {
257
-			$this->recoverAllFiles('/' . $user . '/files/', $privateKey, $user);
258
-		}
259
-	}
260
-
261
-	/**
262
-	 * recover users files
263
-	 *
264
-	 * @param string $path
265
-	 * @param string $privateKey
266
-	 * @param string $uid
267
-	 */
268
-	private function recoverAllFiles($path, $privateKey, $uid) {
269
-		$dirContent = $this->view->getDirectoryContent($path);
270
-
271
-		foreach ($dirContent as $item) {
272
-			// Get relative path from encryption/keyfiles
273
-			$filePath = $item->getPath();
274
-			if ($this->view->is_dir($filePath)) {
275
-				$this->recoverAllFiles($filePath . '/', $privateKey, $uid);
276
-			} else {
277
-				$this->recoverFile($filePath, $privateKey, $uid);
278
-			}
279
-		}
280
-
281
-	}
282
-
283
-	/**
284
-	 * recover file
285
-	 *
286
-	 * @param string $path
287
-	 * @param string $privateKey
288
-	 * @param string $uid
289
-	 */
290
-	private function recoverFile($path, $privateKey, $uid) {
291
-		$encryptedFileKey = $this->keyManager->getEncryptedFileKey($path);
292
-		$shareKey = $this->keyManager->getShareKey($path, $this->keyManager->getRecoveryKeyId());
293
-
294
-		if ($encryptedFileKey && $shareKey && $privateKey) {
295
-			$fileKey = $this->crypt->multiKeyDecrypt($encryptedFileKey,
296
-				$shareKey,
297
-				$privateKey);
298
-		}
299
-
300
-		if (!empty($fileKey)) {
301
-			$accessList = $this->file->getAccessList($path);
302
-			$publicKeys = [];
303
-			foreach ($accessList['users'] as $user) {
304
-				$publicKeys[$user] = $this->keyManager->getPublicKey($user);
305
-			}
306
-
307
-			$publicKeys = $this->keyManager->addSystemKeys($accessList, $publicKeys, $uid);
308
-
309
-			$encryptedKeyfiles = $this->crypt->multiKeyEncrypt($fileKey, $publicKeys);
310
-			$this->keyManager->setAllFileKeys($path, $encryptedKeyfiles);
311
-		}
312
-
313
-	}
41
+    /**
42
+     * @var null|IUser
43
+     */
44
+    protected $user;
45
+    /**
46
+     * @var Crypt
47
+     */
48
+    protected $crypt;
49
+    /**
50
+     * @var KeyManager
51
+     */
52
+    private $keyManager;
53
+    /**
54
+     * @var IConfig
55
+     */
56
+    private $config;
57
+    /**
58
+     * @var View
59
+     */
60
+    private $view;
61
+    /**
62
+     * @var IFile
63
+     */
64
+    private $file;
65
+
66
+    /**
67
+     * @param IUserSession $userSession
68
+     * @param Crypt $crypt
69
+     * @param KeyManager $keyManager
70
+     * @param IConfig $config
71
+     * @param IFile $file
72
+     * @param View $view
73
+     */
74
+    public function __construct(IUserSession $userSession,
75
+                                Crypt $crypt,
76
+                                KeyManager $keyManager,
77
+                                IConfig $config,
78
+                                IFile $file,
79
+                                View $view) {
80
+        $this->user = ($userSession && $userSession->isLoggedIn()) ? $userSession->getUser() : false;
81
+        $this->crypt = $crypt;
82
+        $this->keyManager = $keyManager;
83
+        $this->config = $config;
84
+        $this->view = $view;
85
+        $this->file = $file;
86
+    }
87
+
88
+    /**
89
+     * @param string $password
90
+     * @return bool
91
+     */
92
+    public function enableAdminRecovery($password) {
93
+        $appConfig = $this->config;
94
+        $keyManager = $this->keyManager;
95
+
96
+        if (!$keyManager->recoveryKeyExists()) {
97
+            $keyPair = $this->crypt->createKeyPair();
98
+            if(!is_array($keyPair)) {
99
+                return false;
100
+            }
101
+
102
+            $this->keyManager->setRecoveryKey($password, $keyPair);
103
+        }
104
+
105
+        if ($keyManager->checkRecoveryPassword($password)) {
106
+            $appConfig->setAppValue('encryption', 'recoveryAdminEnabled', 1);
107
+            return true;
108
+        }
109
+
110
+        return false;
111
+    }
112
+
113
+    /**
114
+     * change recovery key id
115
+     *
116
+     * @param string $newPassword
117
+     * @param string $oldPassword
118
+     * @return bool
119
+     */
120
+    public function changeRecoveryKeyPassword($newPassword, $oldPassword) {
121
+        $recoveryKey = $this->keyManager->getSystemPrivateKey($this->keyManager->getRecoveryKeyId());
122
+        $decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey, $oldPassword);
123
+        if($decryptedRecoveryKey === false) {
124
+            return false;
125
+        }
126
+        $encryptedRecoveryKey = $this->crypt->encryptPrivateKey($decryptedRecoveryKey, $newPassword);
127
+        $header = $this->crypt->generateHeader();
128
+        if ($encryptedRecoveryKey) {
129
+            $this->keyManager->setSystemPrivateKey($this->keyManager->getRecoveryKeyId(), $header . $encryptedRecoveryKey);
130
+            return true;
131
+        }
132
+        return false;
133
+    }
134
+
135
+    /**
136
+     * @param string $recoveryPassword
137
+     * @return bool
138
+     */
139
+    public function disableAdminRecovery($recoveryPassword) {
140
+        $keyManager = $this->keyManager;
141
+
142
+        if ($keyManager->checkRecoveryPassword($recoveryPassword)) {
143
+            // Set recoveryAdmin as disabled
144
+            $this->config->setAppValue('encryption', 'recoveryAdminEnabled', 0);
145
+            return true;
146
+        }
147
+        return false;
148
+    }
149
+
150
+    /**
151
+     * check if recovery is enabled for user
152
+     *
153
+     * @param string $user if no user is given we check the current logged-in user
154
+     *
155
+     * @return bool
156
+     */
157
+    public function isRecoveryEnabledForUser($user = '') {
158
+        $uid = $user === '' ? $this->user->getUID() : $user;
159
+        $recoveryMode = $this->config->getUserValue($uid,
160
+            'encryption',
161
+            'recoveryEnabled',
162
+            0);
163
+
164
+        return ($recoveryMode === '1');
165
+    }
166
+
167
+    /**
168
+     * check if recovery is key is enabled by the administrator
169
+     *
170
+     * @return bool
171
+     */
172
+    public function isRecoveryKeyEnabled() {
173
+        $enabled = $this->config->getAppValue('encryption', 'recoveryAdminEnabled', 0);
174
+
175
+        return ($enabled === '1');
176
+    }
177
+
178
+    /**
179
+     * @param string $value
180
+     * @return bool
181
+     */
182
+    public function setRecoveryForUser($value) {
183
+
184
+        try {
185
+            $this->config->setUserValue($this->user->getUID(),
186
+                'encryption',
187
+                'recoveryEnabled',
188
+                $value);
189
+
190
+            if ($value === '1') {
191
+                $this->addRecoveryKeys('/' . $this->user->getUID() . '/files/');
192
+            } else {
193
+                $this->removeRecoveryKeys('/' . $this->user->getUID() . '/files/');
194
+            }
195
+
196
+            return true;
197
+        } catch (PreConditionNotMetException $e) {
198
+            return false;
199
+        }
200
+    }
201
+
202
+    /**
203
+     * add recovery key to all encrypted files
204
+     * @param string $path
205
+     */
206
+    private function addRecoveryKeys($path) {
207
+        $dirContent = $this->view->getDirectoryContent($path);
208
+        foreach ($dirContent as $item) {
209
+            $filePath = $item->getPath();
210
+            if ($item['type'] === 'dir') {
211
+                $this->addRecoveryKeys($filePath . '/');
212
+            } else {
213
+                $fileKey = $this->keyManager->getFileKey($filePath, $this->user->getUID());
214
+                if (!empty($fileKey)) {
215
+                    $accessList = $this->file->getAccessList($filePath);
216
+                    $publicKeys = [];
217
+                    foreach ($accessList['users'] as $uid) {
218
+                        $publicKeys[$uid] = $this->keyManager->getPublicKey($uid);
219
+                    }
220
+
221
+                    $publicKeys = $this->keyManager->addSystemKeys($accessList, $publicKeys, $this->user->getUID());
222
+
223
+                    $encryptedKeyfiles = $this->crypt->multiKeyEncrypt($fileKey, $publicKeys);
224
+                    $this->keyManager->setAllFileKeys($filePath, $encryptedKeyfiles);
225
+                }
226
+            }
227
+        }
228
+    }
229
+
230
+    /**
231
+     * remove recovery key to all encrypted files
232
+     * @param string $path
233
+     */
234
+    private function removeRecoveryKeys($path) {
235
+        $dirContent = $this->view->getDirectoryContent($path);
236
+        foreach ($dirContent as $item) {
237
+            $filePath = $item->getPath();
238
+            if ($item['type'] === 'dir') {
239
+                $this->removeRecoveryKeys($filePath . '/');
240
+            } else {
241
+                $this->keyManager->deleteShareKey($filePath, $this->keyManager->getRecoveryKeyId());
242
+            }
243
+        }
244
+    }
245
+
246
+    /**
247
+     * recover users files with the recovery key
248
+     *
249
+     * @param string $recoveryPassword
250
+     * @param string $user
251
+     */
252
+    public function recoverUsersFiles($recoveryPassword, $user) {
253
+        $encryptedKey = $this->keyManager->getSystemPrivateKey($this->keyManager->getRecoveryKeyId());
254
+
255
+        $privateKey = $this->crypt->decryptPrivateKey($encryptedKey, $recoveryPassword);
256
+        if($privateKey !== false) {
257
+            $this->recoverAllFiles('/' . $user . '/files/', $privateKey, $user);
258
+        }
259
+    }
260
+
261
+    /**
262
+     * recover users files
263
+     *
264
+     * @param string $path
265
+     * @param string $privateKey
266
+     * @param string $uid
267
+     */
268
+    private function recoverAllFiles($path, $privateKey, $uid) {
269
+        $dirContent = $this->view->getDirectoryContent($path);
270
+
271
+        foreach ($dirContent as $item) {
272
+            // Get relative path from encryption/keyfiles
273
+            $filePath = $item->getPath();
274
+            if ($this->view->is_dir($filePath)) {
275
+                $this->recoverAllFiles($filePath . '/', $privateKey, $uid);
276
+            } else {
277
+                $this->recoverFile($filePath, $privateKey, $uid);
278
+            }
279
+        }
280
+
281
+    }
282
+
283
+    /**
284
+     * recover file
285
+     *
286
+     * @param string $path
287
+     * @param string $privateKey
288
+     * @param string $uid
289
+     */
290
+    private function recoverFile($path, $privateKey, $uid) {
291
+        $encryptedFileKey = $this->keyManager->getEncryptedFileKey($path);
292
+        $shareKey = $this->keyManager->getShareKey($path, $this->keyManager->getRecoveryKeyId());
293
+
294
+        if ($encryptedFileKey && $shareKey && $privateKey) {
295
+            $fileKey = $this->crypt->multiKeyDecrypt($encryptedFileKey,
296
+                $shareKey,
297
+                $privateKey);
298
+        }
299
+
300
+        if (!empty($fileKey)) {
301
+            $accessList = $this->file->getAccessList($path);
302
+            $publicKeys = [];
303
+            foreach ($accessList['users'] as $user) {
304
+                $publicKeys[$user] = $this->keyManager->getPublicKey($user);
305
+            }
306
+
307
+            $publicKeys = $this->keyManager->addSystemKeys($accessList, $publicKeys, $uid);
308
+
309
+            $encryptedKeyfiles = $this->crypt->multiKeyEncrypt($fileKey, $publicKeys);
310
+            $this->keyManager->setAllFileKeys($path, $encryptedKeyfiles);
311
+        }
312
+
313
+    }
314 314
 
315 315
 
316 316
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php 2 patches
Indentation   +801 added lines, -801 removed lines patch added patch discarded remove patch
@@ -57,805 +57,805 @@
 block discarded – undo
57 57
 
58 58
 class CloudFederationProviderFiles implements ICloudFederationProvider {
59 59
 
60
-	/** @var IAppManager */
61
-	private $appManager;
62
-
63
-	/** @var FederatedShareProvider */
64
-	private $federatedShareProvider;
65
-
66
-	/** @var AddressHandler */
67
-	private $addressHandler;
68
-
69
-	/** @var ILogger */
70
-	private $logger;
71
-
72
-	/** @var IUserManager */
73
-	private $userManager;
74
-
75
-	/** @var IManager */
76
-	private $shareManager;
77
-
78
-	/** @var ICloudIdManager */
79
-	private $cloudIdManager;
80
-
81
-	/** @var IActivityManager */
82
-	private $activityManager;
83
-
84
-	/** @var INotificationManager */
85
-	private $notificationManager;
86
-
87
-	/** @var IURLGenerator */
88
-	private $urlGenerator;
89
-
90
-	/** @var ICloudFederationFactory */
91
-	private $cloudFederationFactory;
92
-
93
-	/** @var ICloudFederationProviderManager */
94
-	private $cloudFederationProviderManager;
95
-
96
-	/** @var IDBConnection */
97
-	private $connection;
98
-
99
-	/** @var IGroupManager */
100
-	private $groupManager;
101
-
102
-	/**
103
-	 * CloudFederationProvider constructor.
104
-	 *
105
-	 * @param IAppManager $appManager
106
-	 * @param FederatedShareProvider $federatedShareProvider
107
-	 * @param AddressHandler $addressHandler
108
-	 * @param ILogger $logger
109
-	 * @param IUserManager $userManager
110
-	 * @param IManager $shareManager
111
-	 * @param ICloudIdManager $cloudIdManager
112
-	 * @param IActivityManager $activityManager
113
-	 * @param INotificationManager $notificationManager
114
-	 * @param IURLGenerator $urlGenerator
115
-	 * @param ICloudFederationFactory $cloudFederationFactory
116
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
117
-	 * @param IDBConnection $connection
118
-	 * @param IGroupManager $groupManager
119
-	 */
120
-	public function __construct(IAppManager $appManager,
121
-								FederatedShareProvider $federatedShareProvider,
122
-								AddressHandler $addressHandler,
123
-								ILogger $logger,
124
-								IUserManager $userManager,
125
-								IManager $shareManager,
126
-								ICloudIdManager $cloudIdManager,
127
-								IActivityManager $activityManager,
128
-								INotificationManager $notificationManager,
129
-								IURLGenerator $urlGenerator,
130
-								ICloudFederationFactory $cloudFederationFactory,
131
-								ICloudFederationProviderManager $cloudFederationProviderManager,
132
-								IDBConnection $connection,
133
-								IGroupManager $groupManager
134
-	) {
135
-		$this->appManager = $appManager;
136
-		$this->federatedShareProvider = $federatedShareProvider;
137
-		$this->addressHandler = $addressHandler;
138
-		$this->logger = $logger;
139
-		$this->userManager = $userManager;
140
-		$this->shareManager = $shareManager;
141
-		$this->cloudIdManager = $cloudIdManager;
142
-		$this->activityManager = $activityManager;
143
-		$this->notificationManager = $notificationManager;
144
-		$this->urlGenerator = $urlGenerator;
145
-		$this->cloudFederationFactory = $cloudFederationFactory;
146
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
147
-		$this->connection = $connection;
148
-		$this->groupManager = $groupManager;
149
-	}
150
-
151
-
152
-
153
-	/**
154
-	 * @return string
155
-	 */
156
-	public function getShareType() {
157
-		return 'file';
158
-	}
159
-
160
-	/**
161
-	 * share received from another server
162
-	 *
163
-	 * @param ICloudFederationShare $share
164
-	 * @return string provider specific unique ID of the share
165
-	 *
166
-	 * @throws ProviderCouldNotAddShareException
167
-	 * @throws \OCP\AppFramework\QueryException
168
-	 * @throws \OC\HintException
169
-	 * @since 14.0.0
170
-	 */
171
-	public function shareReceived(ICloudFederationShare $share) {
172
-
173
-		if (!$this->isS2SEnabled(true)) {
174
-			throw new ProviderCouldNotAddShareException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
175
-		}
176
-
177
-		$protocol = $share->getProtocol();
178
-		if ($protocol['name'] !== 'webdav') {
179
-			throw new ProviderCouldNotAddShareException('Unsupported protocol for data exchange.', '', Http::STATUS_NOT_IMPLEMENTED);
180
-		}
181
-
182
-		list($ownerUid, $remote) = $this->addressHandler->splitUserRemote($share->getOwner());
183
-		// for backward compatibility make sure that the remote url stored in the
184
-		// database ends with a trailing slash
185
-		if (substr($remote, -1) !== '/') {
186
-			$remote = $remote . '/';
187
-		}
188
-
189
-		$token = $share->getShareSecret();
190
-		$name = $share->getResourceName();
191
-		$owner = $share->getOwnerDisplayName();
192
-		$sharedBy = $share->getSharedByDisplayName();
193
-		$shareWith = $share->getShareWith();
194
-		$remoteId = $share->getProviderId();
195
-		$sharedByFederatedId = $share->getSharedBy();
196
-		$ownerFederatedId = $share->getOwner();
197
-		$shareType = $this->mapShareTypeToNextcloud($share->getShareType());
198
-
199
-		// if no explicit information about the person who created the share was send
200
-		// we assume that the share comes from the owner
201
-		if ($sharedByFederatedId === null) {
202
-			$sharedBy = $owner;
203
-			$sharedByFederatedId = $ownerFederatedId;
204
-		}
205
-
206
-		if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
207
-
208
-			if (!Util::isValidFileName($name)) {
209
-				throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
210
-			}
211
-
212
-			// FIXME this should be a method in the user management instead
213
-			if ($shareType === Share::SHARE_TYPE_USER) {
214
-				$this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
215
-				Util::emitHook(
216
-					'\OCA\Files_Sharing\API\Server2Server',
217
-					'preLoginNameUsedAsUserName',
218
-					['uid' => &$shareWith]
219
-				);
220
-				$this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
221
-
222
-				if (!$this->userManager->userExists($shareWith)) {
223
-					throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
224
-				}
225
-
226
-				\OC_Util::setupFS($shareWith);
227
-			}
228
-
229
-			if ($shareType === Share::SHARE_TYPE_GROUP && !$this->groupManager->groupExists($shareWith)) {
230
-				throw new ProviderCouldNotAddShareException('Group does not exists', '',Http::STATUS_BAD_REQUEST);
231
-			}
232
-
233
-			$externalManager = new \OCA\Files_Sharing\External\Manager(
234
-				\OC::$server->getDatabaseConnection(),
235
-				Filesystem::getMountManager(),
236
-				Filesystem::getLoader(),
237
-				\OC::$server->getHTTPClientService(),
238
-				\OC::$server->getNotificationManager(),
239
-				\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
240
-				\OC::$server->getCloudFederationProviderManager(),
241
-				\OC::$server->getCloudFederationFactory(),
242
-				\OC::$server->getGroupManager(),
243
-				\OC::$server->getUserManager(),
244
-				$shareWith
245
-			);
246
-
247
-			try {
248
-				$externalManager->addShare($remote, $token, '', $name, $owner, $shareType,false, $shareWith, $remoteId);
249
-				$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
250
-
251
-				if ($shareType === Share::SHARE_TYPE_USER) {
252
-					$event = $this->activityManager->generateEvent();
253
-					$event->setApp('files_sharing')
254
-						->setType('remote_share')
255
-						->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
256
-						->setAffectedUser($shareWith)
257
-						->setObject('remote_share', (int)$shareId, $name);
258
-					\OC::$server->getActivityManager()->publish($event);
259
-					$this->notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
260
-				} else {
261
-					$groupMembers = $this->groupManager->get($shareWith)->getUsers();
262
-					foreach ($groupMembers as $user) {
263
-						$event = $this->activityManager->generateEvent();
264
-						$event->setApp('files_sharing')
265
-							->setType('remote_share')
266
-							->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
267
-							->setAffectedUser($user->getUID())
268
-							->setObject('remote_share', (int)$shareId, $name);
269
-						\OC::$server->getActivityManager()->publish($event);
270
-						$this->notifyAboutNewShare($user->getUID(), $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
271
-					}
272
-				}
273
-				return $shareId;
274
-			} catch (\Exception $e) {
275
-				$this->logger->logException($e, [
276
-					'message' => 'Server can not add remote share.',
277
-					'level' => ILogger::ERROR,
278
-					'app' => 'files_sharing'
279
-				]);
280
-				throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
281
-			}
282
-		}
283
-
284
-		throw new ProviderCouldNotAddShareException('server can not add remote share, missing parameter', '', HTTP::STATUS_BAD_REQUEST);
285
-
286
-	}
287
-
288
-	/**
289
-	 * notification received from another server
290
-	 *
291
-	 * @param string $notificationType (e.g. SHARE_ACCEPTED)
292
-	 * @param string $providerId id of the share
293
-	 * @param array $notification payload of the notification
294
-	 * @return array data send back to the sender
295
-	 *
296
-	 * @throws ActionNotSupportedException
297
-	 * @throws AuthenticationFailedException
298
-	 * @throws BadRequestException
299
-	 * @throws \OC\HintException
300
-	 * @since 14.0.0
301
-	 */
302
-	public function notificationReceived($notificationType, $providerId, array $notification) {
303
-
304
-		switch ($notificationType) {
305
-			case 'SHARE_ACCEPTED':
306
-				return $this->shareAccepted($providerId, $notification);
307
-			case 'SHARE_DECLINED':
308
-				return $this->shareDeclined($providerId, $notification);
309
-			case 'SHARE_UNSHARED':
310
-				return $this->unshare($providerId, $notification);
311
-			case 'REQUEST_RESHARE':
312
-				return $this->reshareRequested($providerId, $notification);
313
-			case 'RESHARE_UNDO':
314
-				return $this->undoReshare($providerId, $notification);
315
-			case 'RESHARE_CHANGE_PERMISSION':
316
-				return $this->updateResharePermissions($providerId, $notification);
317
-		}
318
-
319
-
320
-		throw new BadRequestException([$notificationType]);
321
-	}
322
-
323
-	/**
324
-	 * map OCM share type (strings) to Nextcloud internal share types (integer)
325
-	 *
326
-	 * @param string $shareType
327
-	 * @return int
328
-	 */
329
-	private function mapShareTypeToNextcloud($shareType) {
330
-		$result = Share::SHARE_TYPE_USER;
331
-		if ($shareType === 'group') {
332
-			$result = Share::SHARE_TYPE_GROUP;
333
-		}
334
-
335
-		return $result;
336
-	}
337
-
338
-	/**
339
-	 * notify user about new federated share
340
-	 *
341
-	 * @param $shareWith
342
-	 * @param $shareId
343
-	 * @param $ownerFederatedId
344
-	 * @param $sharedByFederatedId
345
-	 * @param $name
346
-	 */
347
-	private function notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner) {
348
-		$notification = $this->notificationManager->createNotification();
349
-		$notification->setApp('files_sharing')
350
-			->setUser($shareWith)
351
-			->setDateTime(new \DateTime())
352
-			->setObject('remote_share', $shareId)
353
-			->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/'), $sharedBy, $owner]);
354
-
355
-		$declineAction = $notification->createAction();
356
-		$declineAction->setLabel('decline')
357
-			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
358
-		$notification->addAction($declineAction);
359
-
360
-		$acceptAction = $notification->createAction();
361
-		$acceptAction->setLabel('accept')
362
-			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
363
-		$notification->addAction($acceptAction);
364
-
365
-		$this->notificationManager->notify($notification);
366
-	}
367
-
368
-	/**
369
-	 * process notification that the recipient accepted a share
370
-	 *
371
-	 * @param string $id
372
-	 * @param array $notification
373
-	 * @return array
374
-	 * @throws ActionNotSupportedException
375
-	 * @throws AuthenticationFailedException
376
-	 * @throws BadRequestException
377
-	 * @throws \OC\HintException
378
-	 */
379
-	private function shareAccepted($id, array $notification) {
380
-
381
-		if (!$this->isS2SEnabled()) {
382
-			throw new ActionNotSupportedException('Server does not support federated cloud sharing');
383
-		}
384
-
385
-		if (!isset($notification['sharedSecret'])) {
386
-			throw new BadRequestException(['sharedSecret']);
387
-		}
388
-
389
-		$token = $notification['sharedSecret'];
390
-
391
-		$share = $this->federatedShareProvider->getShareById($id);
392
-
393
-		$this->verifyShare($share, $token);
394
-		$this->executeAcceptShare($share);
395
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
396
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
397
-			$remoteId = $this->federatedShareProvider->getRemoteId($share);
398
-			$notification = $this->cloudFederationFactory->getCloudFederationNotification();
399
-			$notification->setMessage(
400
-				'SHARE_ACCEPTED',
401
-				'file',
402
-				$remoteId,
403
-				[
404
-					'sharedSecret' => $token,
405
-					'message' => 'Recipient accepted the re-share'
406
-				]
407
-
408
-			);
409
-			$this->cloudFederationProviderManager->sendNotification($remote, $notification);
410
-
411
-		}
412
-
413
-		return [];
414
-	}
415
-
416
-	/**
417
-	 * @param IShare $share
418
-	 * @throws ShareNotFound
419
-	 */
420
-	protected function executeAcceptShare(IShare $share) {
421
-		try {
422
-			$fileId = (int)$share->getNode()->getId();
423
-			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
424
-		} catch (\Exception $e) {
425
-			throw new ShareNotFound();
426
-		}
427
-
428
-		$event = $this->activityManager->generateEvent();
429
-		$event->setApp('files_sharing')
430
-			->setType('remote_share')
431
-			->setAffectedUser($this->getCorrectUid($share))
432
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
433
-			->setObject('files', $fileId, $file)
434
-			->setLink($link);
435
-		$this->activityManager->publish($event);
436
-	}
437
-
438
-	/**
439
-	 * process notification that the recipient declined a share
440
-	 *
441
-	 * @param string $id
442
-	 * @param array $notification
443
-	 * @return array
444
-	 * @throws ActionNotSupportedException
445
-	 * @throws AuthenticationFailedException
446
-	 * @throws BadRequestException
447
-	 * @throws ShareNotFound
448
-	 * @throws \OC\HintException
449
-	 *
450
-	 */
451
-	protected function shareDeclined($id, array $notification) {
452
-
453
-		if (!$this->isS2SEnabled()) {
454
-			throw new ActionNotSupportedException('Server does not support federated cloud sharing');
455
-		}
456
-
457
-		if (!isset($notification['sharedSecret'])) {
458
-			throw new BadRequestException(['sharedSecret']);
459
-		}
460
-
461
-		$token = $notification['sharedSecret'];
462
-
463
-		$share = $this->federatedShareProvider->getShareById($id);
464
-
465
-		$this->verifyShare($share, $token);
466
-
467
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
468
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
469
-			$remoteId = $this->federatedShareProvider->getRemoteId($share);
470
-			$notification = $this->cloudFederationFactory->getCloudFederationNotification();
471
-			$notification->setMessage(
472
-				'SHARE_DECLINED',
473
-				'file',
474
-				$remoteId,
475
-				[
476
-					'sharedSecret' => $token,
477
-					'message' => 'Recipient declined the re-share'
478
-				]
479
-
480
-			);
481
-			$this->cloudFederationProviderManager->sendNotification($remote, $notification);
482
-		}
483
-
484
-		$this->executeDeclineShare($share);
485
-
486
-		return [];
487
-
488
-	}
489
-
490
-	/**
491
-	 * delete declined share and create a activity
492
-	 *
493
-	 * @param IShare $share
494
-	 * @throws ShareNotFound
495
-	 */
496
-	protected function executeDeclineShare(IShare $share) {
497
-		$this->federatedShareProvider->removeShareFromTable($share);
498
-
499
-		try {
500
-			$fileId = (int)$share->getNode()->getId();
501
-			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
502
-		} catch (\Exception $e) {
503
-			throw new ShareNotFound();
504
-		}
505
-
506
-		$event = $this->activityManager->generateEvent();
507
-		$event->setApp('files_sharing')
508
-			->setType('remote_share')
509
-			->setAffectedUser($this->getCorrectUid($share))
510
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
511
-			->setObject('files', $fileId, $file)
512
-			->setLink($link);
513
-		$this->activityManager->publish($event);
514
-
515
-	}
516
-
517
-	/**
518
-	 * received the notification that the owner unshared a file from you
519
-	 *
520
-	 * @param string $id
521
-	 * @param array $notification
522
-	 * @return array
523
-	 * @throws AuthenticationFailedException
524
-	 * @throws BadRequestException
525
-	 */
526
-	private function undoReshare($id, array $notification) {
527
-		if (!isset($notification['sharedSecret'])) {
528
-			throw new BadRequestException(['sharedSecret']);
529
-		}
530
-		$token = $notification['sharedSecret'];
531
-
532
-		$share = $this->federatedShareProvider->getShareById($id);
533
-
534
-		$this->verifyShare($share, $token);
535
-		$this->federatedShareProvider->removeShareFromTable($share);
536
-		return [];
537
-	}
538
-
539
-	/**
540
-	 * unshare file from self
541
-	 *
542
-	 * @param string $id
543
-	 * @param array $notification
544
-	 * @return array
545
-	 * @throws ActionNotSupportedException
546
-	 * @throws BadRequestException
547
-	 */
548
-	private function unshare($id, array $notification) {
549
-
550
-		if (!$this->isS2SEnabled(true)) {
551
-			throw new ActionNotSupportedException("incoming shares disabled!");
552
-		}
553
-
554
-		if (!isset($notification['sharedSecret'])) {
555
-			throw new BadRequestException(['sharedSecret']);
556
-		}
557
-		$token = $notification['sharedSecret'];
558
-
559
-		$qb = $this->connection->getQueryBuilder();
560
-		$qb->select('*')
561
-			->from('share_external')
562
-			->where(
563
-				$qb->expr()->andX(
564
-					$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
565
-					$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
566
-				)
567
-			);
568
-
569
-		$result = $qb->execute();
570
-		$share = $result->fetch();
571
-		$result->closeCursor();
572
-
573
-		if ($token && $id && !empty($share)) {
574
-
575
-			$remote = $this->cleanupRemote($share['remote']);
576
-
577
-			$owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
578
-			$mountpoint = $share['mountpoint'];
579
-			$user = $share['user'];
580
-
581
-			$qb = $this->connection->getQueryBuilder();
582
-			$qb->delete('share_external')
583
-				->where(
584
-					$qb->expr()->andX(
585
-						$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
586
-						$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
587
-					)
588
-				);
589
-
590
-			$qb->execute();
591
-
592
-			// delete all child in case of a group share
593
-			$qb = $this->connection->getQueryBuilder();
594
-			$qb->delete('share_external')
595
-				->where($qb->expr()->eq('parent', $qb->createNamedParameter((int)$share['id'])));
596
-			$qb->execute();
597
-
598
-			if ((int)$share['share_type'] === Share::SHARE_TYPE_USER) {
599
-				if ($share['accepted']) {
600
-					$path = trim($mountpoint, '/');
601
-				} else {
602
-					$path = trim($share['name'], '/');
603
-				}
604
-				$notification = $this->notificationManager->createNotification();
605
-				$notification->setApp('files_sharing')
606
-					->setUser($share['user'])
607
-					->setObject('remote_share', (int)$share['id']);
608
-				$this->notificationManager->markProcessed($notification);
609
-
610
-				$event = $this->activityManager->generateEvent();
611
-				$event->setApp('files_sharing')
612
-					->setType('remote_share')
613
-					->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
614
-					->setAffectedUser($user)
615
-					->setObject('remote_share', (int)$share['id'], $path);
616
-				\OC::$server->getActivityManager()->publish($event);
617
-			}
618
-		}
619
-
620
-		return [];
621
-	}
622
-
623
-	private function cleanupRemote($remote) {
624
-		$remote = substr($remote, strpos($remote, '://') + 3);
625
-
626
-		return rtrim($remote, '/');
627
-	}
628
-
629
-	/**
630
-	 * recipient of a share request to re-share the file with another user
631
-	 *
632
-	 * @param string $id
633
-	 * @param array $notification
634
-	 * @return array
635
-	 * @throws AuthenticationFailedException
636
-	 * @throws BadRequestException
637
-	 * @throws ProviderCouldNotAddShareException
638
-	 * @throws ShareNotFound
639
-	 */
640
-	protected function reshareRequested($id, array $notification) {
641
-
642
-		if (!isset($notification['sharedSecret'])) {
643
-			throw new BadRequestException(['sharedSecret']);
644
-		}
645
-		$token = $notification['sharedSecret'];
646
-
647
-		if (!isset($notification['shareWith'])) {
648
-			throw new BadRequestException(['shareWith']);
649
-		}
650
-		$shareWith = $notification['shareWith'];
651
-
652
-		if (!isset($notification['senderId'])) {
653
-			throw new BadRequestException(['senderId']);
654
-		}
655
-		$senderId = $notification['senderId'];
656
-
657
-		$share = $this->federatedShareProvider->getShareById($id);
658
-		// don't allow to share a file back to the owner
659
-		try {
660
-			list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
661
-			$owner = $share->getShareOwner();
662
-			$currentServer = $this->addressHandler->generateRemoteURL();
663
-			if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
664
-				throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
665
-			}
666
-		} catch (\Exception $e) {
667
-			throw new ProviderCouldNotAddShareException($e->getMessage());
668
-		}
669
-
670
-		$this->verifyShare($share, $token);
671
-
672
-		// check if re-sharing is allowed
673
-		if ($share->getPermissions() & Constants::PERMISSION_SHARE) {
674
-			// the recipient of the initial share is now the initiator for the re-share
675
-			$share->setSharedBy($share->getSharedWith());
676
-			$share->setSharedWith($shareWith);
677
-			$result = $this->federatedShareProvider->create($share);
678
-			$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
679
-			return ['token' => $result->getToken(), 'providerId' => $result->getId()];
680
-		} else {
681
-			throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
682
-		}
683
-
684
-	}
685
-
686
-	/**
687
-	 * update permission of a re-share so that the share dialog shows the right
688
-	 * permission if the owner or the sender changes the permission
689
-	 *
690
-	 * @param string $id
691
-	 * @param array $notification
692
-	 * @return array
693
-	 * @throws AuthenticationFailedException
694
-	 * @throws BadRequestException
695
-	 */
696
-	protected function updateResharePermissions($id, array $notification) {
697
-
698
-		if (!isset($notification['sharedSecret'])) {
699
-			throw new BadRequestException(['sharedSecret']);
700
-		}
701
-		$token = $notification['sharedSecret'];
702
-
703
-		if (!isset($notification['permission'])) {
704
-			throw new BadRequestException(['permission']);
705
-		}
706
-		$ocmPermissions = $notification['permission'];
707
-
708
-		$share = $this->federatedShareProvider->getShareById($id);
709
-
710
-		$ncPermission = $this->ocmPermissions2ncPermissions($ocmPermissions);
711
-
712
-		$this->verifyShare($share, $token);
713
-		$this->updatePermissionsInDatabase($share, $ncPermission);
714
-
715
-		return [];
716
-	}
717
-
718
-	/**
719
-	 * translate OCM Permissions to Nextcloud permissions
720
-	 *
721
-	 * @param array $ocmPermissions
722
-	 * @return int
723
-	 * @throws BadRequestException
724
-	 */
725
-	protected function ocmPermissions2ncPermissions(array $ocmPermissions) {
726
-		$ncPermissions = 0;
727
-		foreach($ocmPermissions as $permission) {
728
-			switch (strtolower($permission)) {
729
-				case 'read':
730
-					$ncPermissions += Constants::PERMISSION_READ;
731
-					break;
732
-				case 'write':
733
-					$ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
734
-					break;
735
-				case 'share':
736
-					$ncPermissions += Constants::PERMISSION_SHARE;
737
-					break;
738
-				default:
739
-					throw new BadRequestException(['permission']);
740
-			}
741
-
742
-		}
743
-
744
-		return $ncPermissions;
745
-	}
746
-
747
-	/**
748
-	 * update permissions in database
749
-	 *
750
-	 * @param IShare $share
751
-	 * @param int $permissions
752
-	 */
753
-	protected function updatePermissionsInDatabase(IShare $share, $permissions) {
754
-		$query = $this->connection->getQueryBuilder();
755
-		$query->update('share')
756
-			->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
757
-			->set('permissions', $query->createNamedParameter($permissions))
758
-			->execute();
759
-	}
760
-
761
-
762
-	/**
763
-	 * get file
764
-	 *
765
-	 * @param string $user
766
-	 * @param int $fileSource
767
-	 * @return array with internal path of the file and a absolute link to it
768
-	 */
769
-	private function getFile($user, $fileSource) {
770
-		\OC_Util::setupFS($user);
771
-
772
-		try {
773
-			$file = Filesystem::getPath($fileSource);
774
-		} catch (NotFoundException $e) {
775
-			$file = null;
776
-		}
777
-		$args = Filesystem::is_dir($file) ? ['dir' => $file] : ['dir' => dirname($file), 'scrollto' => $file];
778
-		$link = Util::linkToAbsolute('files', 'index.php', $args);
779
-
780
-		return [$file, $link];
781
-
782
-	}
783
-
784
-	/**
785
-	 * check if we are the initiator or the owner of a re-share and return the correct UID
786
-	 *
787
-	 * @param IShare $share
788
-	 * @return string
789
-	 */
790
-	protected function getCorrectUid(IShare $share) {
791
-		if ($this->userManager->userExists($share->getShareOwner())) {
792
-			return $share->getShareOwner();
793
-		}
794
-
795
-		return $share->getSharedBy();
796
-	}
797
-
798
-
799
-
800
-	/**
801
-	 * check if we got the right share
802
-	 *
803
-	 * @param IShare $share
804
-	 * @param string $token
805
-	 * @return bool
806
-	 * @throws AuthenticationFailedException
807
-	 */
808
-	protected function verifyShare(IShare $share, $token) {
809
-		if (
810
-			$share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
811
-			$share->getToken() === $token
812
-		) {
813
-			return true;
814
-		}
815
-
816
-		if ($share->getShareType() === IShare::TYPE_CIRCLE) {
817
-			try {
818
-				$knownShare = $this->shareManager->getShareByToken($token);
819
-				if ($knownShare->getId() === $share->getId()) {
820
-					return true;
821
-				}
822
-			} catch (ShareNotFound $e) {
823
-			}
824
-		}
825
-
826
-		throw new AuthenticationFailedException();
827
-	}
828
-
829
-
830
-
831
-	/**
832
-	 * check if server-to-server sharing is enabled
833
-	 *
834
-	 * @param bool $incoming
835
-	 * @return bool
836
-	 */
837
-	private function isS2SEnabled($incoming = false) {
838
-
839
-		$result = $this->appManager->isEnabledForUser('files_sharing');
840
-
841
-		if ($incoming) {
842
-			$result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
843
-		} else {
844
-			$result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
845
-		}
846
-
847
-		return $result;
848
-	}
849
-
850
-
851
-	/**
852
-	 * get the supported share types, e.g. "user", "group", etc.
853
-	 *
854
-	 * @return array
855
-	 *
856
-	 * @since 14.0.0
857
-	 */
858
-	public function getSupportedShareTypes() {
859
-		return ['user', 'group'];
860
-	}
60
+    /** @var IAppManager */
61
+    private $appManager;
62
+
63
+    /** @var FederatedShareProvider */
64
+    private $federatedShareProvider;
65
+
66
+    /** @var AddressHandler */
67
+    private $addressHandler;
68
+
69
+    /** @var ILogger */
70
+    private $logger;
71
+
72
+    /** @var IUserManager */
73
+    private $userManager;
74
+
75
+    /** @var IManager */
76
+    private $shareManager;
77
+
78
+    /** @var ICloudIdManager */
79
+    private $cloudIdManager;
80
+
81
+    /** @var IActivityManager */
82
+    private $activityManager;
83
+
84
+    /** @var INotificationManager */
85
+    private $notificationManager;
86
+
87
+    /** @var IURLGenerator */
88
+    private $urlGenerator;
89
+
90
+    /** @var ICloudFederationFactory */
91
+    private $cloudFederationFactory;
92
+
93
+    /** @var ICloudFederationProviderManager */
94
+    private $cloudFederationProviderManager;
95
+
96
+    /** @var IDBConnection */
97
+    private $connection;
98
+
99
+    /** @var IGroupManager */
100
+    private $groupManager;
101
+
102
+    /**
103
+     * CloudFederationProvider constructor.
104
+     *
105
+     * @param IAppManager $appManager
106
+     * @param FederatedShareProvider $federatedShareProvider
107
+     * @param AddressHandler $addressHandler
108
+     * @param ILogger $logger
109
+     * @param IUserManager $userManager
110
+     * @param IManager $shareManager
111
+     * @param ICloudIdManager $cloudIdManager
112
+     * @param IActivityManager $activityManager
113
+     * @param INotificationManager $notificationManager
114
+     * @param IURLGenerator $urlGenerator
115
+     * @param ICloudFederationFactory $cloudFederationFactory
116
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
117
+     * @param IDBConnection $connection
118
+     * @param IGroupManager $groupManager
119
+     */
120
+    public function __construct(IAppManager $appManager,
121
+                                FederatedShareProvider $federatedShareProvider,
122
+                                AddressHandler $addressHandler,
123
+                                ILogger $logger,
124
+                                IUserManager $userManager,
125
+                                IManager $shareManager,
126
+                                ICloudIdManager $cloudIdManager,
127
+                                IActivityManager $activityManager,
128
+                                INotificationManager $notificationManager,
129
+                                IURLGenerator $urlGenerator,
130
+                                ICloudFederationFactory $cloudFederationFactory,
131
+                                ICloudFederationProviderManager $cloudFederationProviderManager,
132
+                                IDBConnection $connection,
133
+                                IGroupManager $groupManager
134
+    ) {
135
+        $this->appManager = $appManager;
136
+        $this->federatedShareProvider = $federatedShareProvider;
137
+        $this->addressHandler = $addressHandler;
138
+        $this->logger = $logger;
139
+        $this->userManager = $userManager;
140
+        $this->shareManager = $shareManager;
141
+        $this->cloudIdManager = $cloudIdManager;
142
+        $this->activityManager = $activityManager;
143
+        $this->notificationManager = $notificationManager;
144
+        $this->urlGenerator = $urlGenerator;
145
+        $this->cloudFederationFactory = $cloudFederationFactory;
146
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
147
+        $this->connection = $connection;
148
+        $this->groupManager = $groupManager;
149
+    }
150
+
151
+
152
+
153
+    /**
154
+     * @return string
155
+     */
156
+    public function getShareType() {
157
+        return 'file';
158
+    }
159
+
160
+    /**
161
+     * share received from another server
162
+     *
163
+     * @param ICloudFederationShare $share
164
+     * @return string provider specific unique ID of the share
165
+     *
166
+     * @throws ProviderCouldNotAddShareException
167
+     * @throws \OCP\AppFramework\QueryException
168
+     * @throws \OC\HintException
169
+     * @since 14.0.0
170
+     */
171
+    public function shareReceived(ICloudFederationShare $share) {
172
+
173
+        if (!$this->isS2SEnabled(true)) {
174
+            throw new ProviderCouldNotAddShareException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
175
+        }
176
+
177
+        $protocol = $share->getProtocol();
178
+        if ($protocol['name'] !== 'webdav') {
179
+            throw new ProviderCouldNotAddShareException('Unsupported protocol for data exchange.', '', Http::STATUS_NOT_IMPLEMENTED);
180
+        }
181
+
182
+        list($ownerUid, $remote) = $this->addressHandler->splitUserRemote($share->getOwner());
183
+        // for backward compatibility make sure that the remote url stored in the
184
+        // database ends with a trailing slash
185
+        if (substr($remote, -1) !== '/') {
186
+            $remote = $remote . '/';
187
+        }
188
+
189
+        $token = $share->getShareSecret();
190
+        $name = $share->getResourceName();
191
+        $owner = $share->getOwnerDisplayName();
192
+        $sharedBy = $share->getSharedByDisplayName();
193
+        $shareWith = $share->getShareWith();
194
+        $remoteId = $share->getProviderId();
195
+        $sharedByFederatedId = $share->getSharedBy();
196
+        $ownerFederatedId = $share->getOwner();
197
+        $shareType = $this->mapShareTypeToNextcloud($share->getShareType());
198
+
199
+        // if no explicit information about the person who created the share was send
200
+        // we assume that the share comes from the owner
201
+        if ($sharedByFederatedId === null) {
202
+            $sharedBy = $owner;
203
+            $sharedByFederatedId = $ownerFederatedId;
204
+        }
205
+
206
+        if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
207
+
208
+            if (!Util::isValidFileName($name)) {
209
+                throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
210
+            }
211
+
212
+            // FIXME this should be a method in the user management instead
213
+            if ($shareType === Share::SHARE_TYPE_USER) {
214
+                $this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
215
+                Util::emitHook(
216
+                    '\OCA\Files_Sharing\API\Server2Server',
217
+                    'preLoginNameUsedAsUserName',
218
+                    ['uid' => &$shareWith]
219
+                );
220
+                $this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
221
+
222
+                if (!$this->userManager->userExists($shareWith)) {
223
+                    throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
224
+                }
225
+
226
+                \OC_Util::setupFS($shareWith);
227
+            }
228
+
229
+            if ($shareType === Share::SHARE_TYPE_GROUP && !$this->groupManager->groupExists($shareWith)) {
230
+                throw new ProviderCouldNotAddShareException('Group does not exists', '',Http::STATUS_BAD_REQUEST);
231
+            }
232
+
233
+            $externalManager = new \OCA\Files_Sharing\External\Manager(
234
+                \OC::$server->getDatabaseConnection(),
235
+                Filesystem::getMountManager(),
236
+                Filesystem::getLoader(),
237
+                \OC::$server->getHTTPClientService(),
238
+                \OC::$server->getNotificationManager(),
239
+                \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
240
+                \OC::$server->getCloudFederationProviderManager(),
241
+                \OC::$server->getCloudFederationFactory(),
242
+                \OC::$server->getGroupManager(),
243
+                \OC::$server->getUserManager(),
244
+                $shareWith
245
+            );
246
+
247
+            try {
248
+                $externalManager->addShare($remote, $token, '', $name, $owner, $shareType,false, $shareWith, $remoteId);
249
+                $shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
250
+
251
+                if ($shareType === Share::SHARE_TYPE_USER) {
252
+                    $event = $this->activityManager->generateEvent();
253
+                    $event->setApp('files_sharing')
254
+                        ->setType('remote_share')
255
+                        ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
256
+                        ->setAffectedUser($shareWith)
257
+                        ->setObject('remote_share', (int)$shareId, $name);
258
+                    \OC::$server->getActivityManager()->publish($event);
259
+                    $this->notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
260
+                } else {
261
+                    $groupMembers = $this->groupManager->get($shareWith)->getUsers();
262
+                    foreach ($groupMembers as $user) {
263
+                        $event = $this->activityManager->generateEvent();
264
+                        $event->setApp('files_sharing')
265
+                            ->setType('remote_share')
266
+                            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
267
+                            ->setAffectedUser($user->getUID())
268
+                            ->setObject('remote_share', (int)$shareId, $name);
269
+                        \OC::$server->getActivityManager()->publish($event);
270
+                        $this->notifyAboutNewShare($user->getUID(), $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
271
+                    }
272
+                }
273
+                return $shareId;
274
+            } catch (\Exception $e) {
275
+                $this->logger->logException($e, [
276
+                    'message' => 'Server can not add remote share.',
277
+                    'level' => ILogger::ERROR,
278
+                    'app' => 'files_sharing'
279
+                ]);
280
+                throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
281
+            }
282
+        }
283
+
284
+        throw new ProviderCouldNotAddShareException('server can not add remote share, missing parameter', '', HTTP::STATUS_BAD_REQUEST);
285
+
286
+    }
287
+
288
+    /**
289
+     * notification received from another server
290
+     *
291
+     * @param string $notificationType (e.g. SHARE_ACCEPTED)
292
+     * @param string $providerId id of the share
293
+     * @param array $notification payload of the notification
294
+     * @return array data send back to the sender
295
+     *
296
+     * @throws ActionNotSupportedException
297
+     * @throws AuthenticationFailedException
298
+     * @throws BadRequestException
299
+     * @throws \OC\HintException
300
+     * @since 14.0.0
301
+     */
302
+    public function notificationReceived($notificationType, $providerId, array $notification) {
303
+
304
+        switch ($notificationType) {
305
+            case 'SHARE_ACCEPTED':
306
+                return $this->shareAccepted($providerId, $notification);
307
+            case 'SHARE_DECLINED':
308
+                return $this->shareDeclined($providerId, $notification);
309
+            case 'SHARE_UNSHARED':
310
+                return $this->unshare($providerId, $notification);
311
+            case 'REQUEST_RESHARE':
312
+                return $this->reshareRequested($providerId, $notification);
313
+            case 'RESHARE_UNDO':
314
+                return $this->undoReshare($providerId, $notification);
315
+            case 'RESHARE_CHANGE_PERMISSION':
316
+                return $this->updateResharePermissions($providerId, $notification);
317
+        }
318
+
319
+
320
+        throw new BadRequestException([$notificationType]);
321
+    }
322
+
323
+    /**
324
+     * map OCM share type (strings) to Nextcloud internal share types (integer)
325
+     *
326
+     * @param string $shareType
327
+     * @return int
328
+     */
329
+    private function mapShareTypeToNextcloud($shareType) {
330
+        $result = Share::SHARE_TYPE_USER;
331
+        if ($shareType === 'group') {
332
+            $result = Share::SHARE_TYPE_GROUP;
333
+        }
334
+
335
+        return $result;
336
+    }
337
+
338
+    /**
339
+     * notify user about new federated share
340
+     *
341
+     * @param $shareWith
342
+     * @param $shareId
343
+     * @param $ownerFederatedId
344
+     * @param $sharedByFederatedId
345
+     * @param $name
346
+     */
347
+    private function notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner) {
348
+        $notification = $this->notificationManager->createNotification();
349
+        $notification->setApp('files_sharing')
350
+            ->setUser($shareWith)
351
+            ->setDateTime(new \DateTime())
352
+            ->setObject('remote_share', $shareId)
353
+            ->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/'), $sharedBy, $owner]);
354
+
355
+        $declineAction = $notification->createAction();
356
+        $declineAction->setLabel('decline')
357
+            ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
358
+        $notification->addAction($declineAction);
359
+
360
+        $acceptAction = $notification->createAction();
361
+        $acceptAction->setLabel('accept')
362
+            ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
363
+        $notification->addAction($acceptAction);
364
+
365
+        $this->notificationManager->notify($notification);
366
+    }
367
+
368
+    /**
369
+     * process notification that the recipient accepted a share
370
+     *
371
+     * @param string $id
372
+     * @param array $notification
373
+     * @return array
374
+     * @throws ActionNotSupportedException
375
+     * @throws AuthenticationFailedException
376
+     * @throws BadRequestException
377
+     * @throws \OC\HintException
378
+     */
379
+    private function shareAccepted($id, array $notification) {
380
+
381
+        if (!$this->isS2SEnabled()) {
382
+            throw new ActionNotSupportedException('Server does not support federated cloud sharing');
383
+        }
384
+
385
+        if (!isset($notification['sharedSecret'])) {
386
+            throw new BadRequestException(['sharedSecret']);
387
+        }
388
+
389
+        $token = $notification['sharedSecret'];
390
+
391
+        $share = $this->federatedShareProvider->getShareById($id);
392
+
393
+        $this->verifyShare($share, $token);
394
+        $this->executeAcceptShare($share);
395
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
396
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
397
+            $remoteId = $this->federatedShareProvider->getRemoteId($share);
398
+            $notification = $this->cloudFederationFactory->getCloudFederationNotification();
399
+            $notification->setMessage(
400
+                'SHARE_ACCEPTED',
401
+                'file',
402
+                $remoteId,
403
+                [
404
+                    'sharedSecret' => $token,
405
+                    'message' => 'Recipient accepted the re-share'
406
+                ]
407
+
408
+            );
409
+            $this->cloudFederationProviderManager->sendNotification($remote, $notification);
410
+
411
+        }
412
+
413
+        return [];
414
+    }
415
+
416
+    /**
417
+     * @param IShare $share
418
+     * @throws ShareNotFound
419
+     */
420
+    protected function executeAcceptShare(IShare $share) {
421
+        try {
422
+            $fileId = (int)$share->getNode()->getId();
423
+            list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
424
+        } catch (\Exception $e) {
425
+            throw new ShareNotFound();
426
+        }
427
+
428
+        $event = $this->activityManager->generateEvent();
429
+        $event->setApp('files_sharing')
430
+            ->setType('remote_share')
431
+            ->setAffectedUser($this->getCorrectUid($share))
432
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
433
+            ->setObject('files', $fileId, $file)
434
+            ->setLink($link);
435
+        $this->activityManager->publish($event);
436
+    }
437
+
438
+    /**
439
+     * process notification that the recipient declined a share
440
+     *
441
+     * @param string $id
442
+     * @param array $notification
443
+     * @return array
444
+     * @throws ActionNotSupportedException
445
+     * @throws AuthenticationFailedException
446
+     * @throws BadRequestException
447
+     * @throws ShareNotFound
448
+     * @throws \OC\HintException
449
+     *
450
+     */
451
+    protected function shareDeclined($id, array $notification) {
452
+
453
+        if (!$this->isS2SEnabled()) {
454
+            throw new ActionNotSupportedException('Server does not support federated cloud sharing');
455
+        }
456
+
457
+        if (!isset($notification['sharedSecret'])) {
458
+            throw new BadRequestException(['sharedSecret']);
459
+        }
460
+
461
+        $token = $notification['sharedSecret'];
462
+
463
+        $share = $this->federatedShareProvider->getShareById($id);
464
+
465
+        $this->verifyShare($share, $token);
466
+
467
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
468
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
469
+            $remoteId = $this->federatedShareProvider->getRemoteId($share);
470
+            $notification = $this->cloudFederationFactory->getCloudFederationNotification();
471
+            $notification->setMessage(
472
+                'SHARE_DECLINED',
473
+                'file',
474
+                $remoteId,
475
+                [
476
+                    'sharedSecret' => $token,
477
+                    'message' => 'Recipient declined the re-share'
478
+                ]
479
+
480
+            );
481
+            $this->cloudFederationProviderManager->sendNotification($remote, $notification);
482
+        }
483
+
484
+        $this->executeDeclineShare($share);
485
+
486
+        return [];
487
+
488
+    }
489
+
490
+    /**
491
+     * delete declined share and create a activity
492
+     *
493
+     * @param IShare $share
494
+     * @throws ShareNotFound
495
+     */
496
+    protected function executeDeclineShare(IShare $share) {
497
+        $this->federatedShareProvider->removeShareFromTable($share);
498
+
499
+        try {
500
+            $fileId = (int)$share->getNode()->getId();
501
+            list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
502
+        } catch (\Exception $e) {
503
+            throw new ShareNotFound();
504
+        }
505
+
506
+        $event = $this->activityManager->generateEvent();
507
+        $event->setApp('files_sharing')
508
+            ->setType('remote_share')
509
+            ->setAffectedUser($this->getCorrectUid($share))
510
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
511
+            ->setObject('files', $fileId, $file)
512
+            ->setLink($link);
513
+        $this->activityManager->publish($event);
514
+
515
+    }
516
+
517
+    /**
518
+     * received the notification that the owner unshared a file from you
519
+     *
520
+     * @param string $id
521
+     * @param array $notification
522
+     * @return array
523
+     * @throws AuthenticationFailedException
524
+     * @throws BadRequestException
525
+     */
526
+    private function undoReshare($id, array $notification) {
527
+        if (!isset($notification['sharedSecret'])) {
528
+            throw new BadRequestException(['sharedSecret']);
529
+        }
530
+        $token = $notification['sharedSecret'];
531
+
532
+        $share = $this->federatedShareProvider->getShareById($id);
533
+
534
+        $this->verifyShare($share, $token);
535
+        $this->federatedShareProvider->removeShareFromTable($share);
536
+        return [];
537
+    }
538
+
539
+    /**
540
+     * unshare file from self
541
+     *
542
+     * @param string $id
543
+     * @param array $notification
544
+     * @return array
545
+     * @throws ActionNotSupportedException
546
+     * @throws BadRequestException
547
+     */
548
+    private function unshare($id, array $notification) {
549
+
550
+        if (!$this->isS2SEnabled(true)) {
551
+            throw new ActionNotSupportedException("incoming shares disabled!");
552
+        }
553
+
554
+        if (!isset($notification['sharedSecret'])) {
555
+            throw new BadRequestException(['sharedSecret']);
556
+        }
557
+        $token = $notification['sharedSecret'];
558
+
559
+        $qb = $this->connection->getQueryBuilder();
560
+        $qb->select('*')
561
+            ->from('share_external')
562
+            ->where(
563
+                $qb->expr()->andX(
564
+                    $qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
565
+                    $qb->expr()->eq('share_token', $qb->createNamedParameter($token))
566
+                )
567
+            );
568
+
569
+        $result = $qb->execute();
570
+        $share = $result->fetch();
571
+        $result->closeCursor();
572
+
573
+        if ($token && $id && !empty($share)) {
574
+
575
+            $remote = $this->cleanupRemote($share['remote']);
576
+
577
+            $owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
578
+            $mountpoint = $share['mountpoint'];
579
+            $user = $share['user'];
580
+
581
+            $qb = $this->connection->getQueryBuilder();
582
+            $qb->delete('share_external')
583
+                ->where(
584
+                    $qb->expr()->andX(
585
+                        $qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
586
+                        $qb->expr()->eq('share_token', $qb->createNamedParameter($token))
587
+                    )
588
+                );
589
+
590
+            $qb->execute();
591
+
592
+            // delete all child in case of a group share
593
+            $qb = $this->connection->getQueryBuilder();
594
+            $qb->delete('share_external')
595
+                ->where($qb->expr()->eq('parent', $qb->createNamedParameter((int)$share['id'])));
596
+            $qb->execute();
597
+
598
+            if ((int)$share['share_type'] === Share::SHARE_TYPE_USER) {
599
+                if ($share['accepted']) {
600
+                    $path = trim($mountpoint, '/');
601
+                } else {
602
+                    $path = trim($share['name'], '/');
603
+                }
604
+                $notification = $this->notificationManager->createNotification();
605
+                $notification->setApp('files_sharing')
606
+                    ->setUser($share['user'])
607
+                    ->setObject('remote_share', (int)$share['id']);
608
+                $this->notificationManager->markProcessed($notification);
609
+
610
+                $event = $this->activityManager->generateEvent();
611
+                $event->setApp('files_sharing')
612
+                    ->setType('remote_share')
613
+                    ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
614
+                    ->setAffectedUser($user)
615
+                    ->setObject('remote_share', (int)$share['id'], $path);
616
+                \OC::$server->getActivityManager()->publish($event);
617
+            }
618
+        }
619
+
620
+        return [];
621
+    }
622
+
623
+    private function cleanupRemote($remote) {
624
+        $remote = substr($remote, strpos($remote, '://') + 3);
625
+
626
+        return rtrim($remote, '/');
627
+    }
628
+
629
+    /**
630
+     * recipient of a share request to re-share the file with another user
631
+     *
632
+     * @param string $id
633
+     * @param array $notification
634
+     * @return array
635
+     * @throws AuthenticationFailedException
636
+     * @throws BadRequestException
637
+     * @throws ProviderCouldNotAddShareException
638
+     * @throws ShareNotFound
639
+     */
640
+    protected function reshareRequested($id, array $notification) {
641
+
642
+        if (!isset($notification['sharedSecret'])) {
643
+            throw new BadRequestException(['sharedSecret']);
644
+        }
645
+        $token = $notification['sharedSecret'];
646
+
647
+        if (!isset($notification['shareWith'])) {
648
+            throw new BadRequestException(['shareWith']);
649
+        }
650
+        $shareWith = $notification['shareWith'];
651
+
652
+        if (!isset($notification['senderId'])) {
653
+            throw new BadRequestException(['senderId']);
654
+        }
655
+        $senderId = $notification['senderId'];
656
+
657
+        $share = $this->federatedShareProvider->getShareById($id);
658
+        // don't allow to share a file back to the owner
659
+        try {
660
+            list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
661
+            $owner = $share->getShareOwner();
662
+            $currentServer = $this->addressHandler->generateRemoteURL();
663
+            if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
664
+                throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
665
+            }
666
+        } catch (\Exception $e) {
667
+            throw new ProviderCouldNotAddShareException($e->getMessage());
668
+        }
669
+
670
+        $this->verifyShare($share, $token);
671
+
672
+        // check if re-sharing is allowed
673
+        if ($share->getPermissions() & Constants::PERMISSION_SHARE) {
674
+            // the recipient of the initial share is now the initiator for the re-share
675
+            $share->setSharedBy($share->getSharedWith());
676
+            $share->setSharedWith($shareWith);
677
+            $result = $this->federatedShareProvider->create($share);
678
+            $this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
679
+            return ['token' => $result->getToken(), 'providerId' => $result->getId()];
680
+        } else {
681
+            throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
682
+        }
683
+
684
+    }
685
+
686
+    /**
687
+     * update permission of a re-share so that the share dialog shows the right
688
+     * permission if the owner or the sender changes the permission
689
+     *
690
+     * @param string $id
691
+     * @param array $notification
692
+     * @return array
693
+     * @throws AuthenticationFailedException
694
+     * @throws BadRequestException
695
+     */
696
+    protected function updateResharePermissions($id, array $notification) {
697
+
698
+        if (!isset($notification['sharedSecret'])) {
699
+            throw new BadRequestException(['sharedSecret']);
700
+        }
701
+        $token = $notification['sharedSecret'];
702
+
703
+        if (!isset($notification['permission'])) {
704
+            throw new BadRequestException(['permission']);
705
+        }
706
+        $ocmPermissions = $notification['permission'];
707
+
708
+        $share = $this->federatedShareProvider->getShareById($id);
709
+
710
+        $ncPermission = $this->ocmPermissions2ncPermissions($ocmPermissions);
711
+
712
+        $this->verifyShare($share, $token);
713
+        $this->updatePermissionsInDatabase($share, $ncPermission);
714
+
715
+        return [];
716
+    }
717
+
718
+    /**
719
+     * translate OCM Permissions to Nextcloud permissions
720
+     *
721
+     * @param array $ocmPermissions
722
+     * @return int
723
+     * @throws BadRequestException
724
+     */
725
+    protected function ocmPermissions2ncPermissions(array $ocmPermissions) {
726
+        $ncPermissions = 0;
727
+        foreach($ocmPermissions as $permission) {
728
+            switch (strtolower($permission)) {
729
+                case 'read':
730
+                    $ncPermissions += Constants::PERMISSION_READ;
731
+                    break;
732
+                case 'write':
733
+                    $ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
734
+                    break;
735
+                case 'share':
736
+                    $ncPermissions += Constants::PERMISSION_SHARE;
737
+                    break;
738
+                default:
739
+                    throw new BadRequestException(['permission']);
740
+            }
741
+
742
+        }
743
+
744
+        return $ncPermissions;
745
+    }
746
+
747
+    /**
748
+     * update permissions in database
749
+     *
750
+     * @param IShare $share
751
+     * @param int $permissions
752
+     */
753
+    protected function updatePermissionsInDatabase(IShare $share, $permissions) {
754
+        $query = $this->connection->getQueryBuilder();
755
+        $query->update('share')
756
+            ->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
757
+            ->set('permissions', $query->createNamedParameter($permissions))
758
+            ->execute();
759
+    }
760
+
761
+
762
+    /**
763
+     * get file
764
+     *
765
+     * @param string $user
766
+     * @param int $fileSource
767
+     * @return array with internal path of the file and a absolute link to it
768
+     */
769
+    private function getFile($user, $fileSource) {
770
+        \OC_Util::setupFS($user);
771
+
772
+        try {
773
+            $file = Filesystem::getPath($fileSource);
774
+        } catch (NotFoundException $e) {
775
+            $file = null;
776
+        }
777
+        $args = Filesystem::is_dir($file) ? ['dir' => $file] : ['dir' => dirname($file), 'scrollto' => $file];
778
+        $link = Util::linkToAbsolute('files', 'index.php', $args);
779
+
780
+        return [$file, $link];
781
+
782
+    }
783
+
784
+    /**
785
+     * check if we are the initiator or the owner of a re-share and return the correct UID
786
+     *
787
+     * @param IShare $share
788
+     * @return string
789
+     */
790
+    protected function getCorrectUid(IShare $share) {
791
+        if ($this->userManager->userExists($share->getShareOwner())) {
792
+            return $share->getShareOwner();
793
+        }
794
+
795
+        return $share->getSharedBy();
796
+    }
797
+
798
+
799
+
800
+    /**
801
+     * check if we got the right share
802
+     *
803
+     * @param IShare $share
804
+     * @param string $token
805
+     * @return bool
806
+     * @throws AuthenticationFailedException
807
+     */
808
+    protected function verifyShare(IShare $share, $token) {
809
+        if (
810
+            $share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
811
+            $share->getToken() === $token
812
+        ) {
813
+            return true;
814
+        }
815
+
816
+        if ($share->getShareType() === IShare::TYPE_CIRCLE) {
817
+            try {
818
+                $knownShare = $this->shareManager->getShareByToken($token);
819
+                if ($knownShare->getId() === $share->getId()) {
820
+                    return true;
821
+                }
822
+            } catch (ShareNotFound $e) {
823
+            }
824
+        }
825
+
826
+        throw new AuthenticationFailedException();
827
+    }
828
+
829
+
830
+
831
+    /**
832
+     * check if server-to-server sharing is enabled
833
+     *
834
+     * @param bool $incoming
835
+     * @return bool
836
+     */
837
+    private function isS2SEnabled($incoming = false) {
838
+
839
+        $result = $this->appManager->isEnabledForUser('files_sharing');
840
+
841
+        if ($incoming) {
842
+            $result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
843
+        } else {
844
+            $result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
845
+        }
846
+
847
+        return $result;
848
+    }
849
+
850
+
851
+    /**
852
+     * get the supported share types, e.g. "user", "group", etc.
853
+     *
854
+     * @return array
855
+     *
856
+     * @since 14.0.0
857
+     */
858
+    public function getSupportedShareTypes() {
859
+        return ['user', 'group'];
860
+    }
861 861
 }
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
 		// for backward compatibility make sure that the remote url stored in the
184 184
 		// database ends with a trailing slash
185 185
 		if (substr($remote, -1) !== '/') {
186
-			$remote = $remote . '/';
186
+			$remote = $remote.'/';
187 187
 		}
188 188
 
189 189
 		$token = $share->getShareSecret();
@@ -211,23 +211,23 @@  discard block
 block discarded – undo
211 211
 
212 212
 			// FIXME this should be a method in the user management instead
213 213
 			if ($shareType === Share::SHARE_TYPE_USER) {
214
-				$this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
214
+				$this->logger->debug('shareWith before, '.$shareWith, ['app' => 'files_sharing']);
215 215
 				Util::emitHook(
216 216
 					'\OCA\Files_Sharing\API\Server2Server',
217 217
 					'preLoginNameUsedAsUserName',
218 218
 					['uid' => &$shareWith]
219 219
 				);
220
-				$this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
220
+				$this->logger->debug('shareWith after, '.$shareWith, ['app' => 'files_sharing']);
221 221
 
222 222
 				if (!$this->userManager->userExists($shareWith)) {
223
-					throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
223
+					throw new ProviderCouldNotAddShareException('User does not exists', '', Http::STATUS_BAD_REQUEST);
224 224
 				}
225 225
 
226 226
 				\OC_Util::setupFS($shareWith);
227 227
 			}
228 228
 
229 229
 			if ($shareType === Share::SHARE_TYPE_GROUP && !$this->groupManager->groupExists($shareWith)) {
230
-				throw new ProviderCouldNotAddShareException('Group does not exists', '',Http::STATUS_BAD_REQUEST);
230
+				throw new ProviderCouldNotAddShareException('Group does not exists', '', Http::STATUS_BAD_REQUEST);
231 231
 			}
232 232
 
233 233
 			$externalManager = new \OCA\Files_Sharing\External\Manager(
@@ -245,7 +245,7 @@  discard block
 block discarded – undo
245 245
 			);
246 246
 
247 247
 			try {
248
-				$externalManager->addShare($remote, $token, '', $name, $owner, $shareType,false, $shareWith, $remoteId);
248
+				$externalManager->addShare($remote, $token, '', $name, $owner, $shareType, false, $shareWith, $remoteId);
249 249
 				$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
250 250
 
251 251
 				if ($shareType === Share::SHARE_TYPE_USER) {
@@ -254,7 +254,7 @@  discard block
 block discarded – undo
254 254
 						->setType('remote_share')
255 255
 						->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
256 256
 						->setAffectedUser($shareWith)
257
-						->setObject('remote_share', (int)$shareId, $name);
257
+						->setObject('remote_share', (int) $shareId, $name);
258 258
 					\OC::$server->getActivityManager()->publish($event);
259 259
 					$this->notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
260 260
 				} else {
@@ -265,7 +265,7 @@  discard block
 block discarded – undo
265 265
 							->setType('remote_share')
266 266
 							->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
267 267
 							->setAffectedUser($user->getUID())
268
-							->setObject('remote_share', (int)$shareId, $name);
268
+							->setObject('remote_share', (int) $shareId, $name);
269 269
 						\OC::$server->getActivityManager()->publish($event);
270 270
 						$this->notifyAboutNewShare($user->getUID(), $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
271 271
 					}
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
 					'level' => ILogger::ERROR,
278 278
 					'app' => 'files_sharing'
279 279
 				]);
280
-				throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
280
+				throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from '.$remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
281 281
 			}
282 282
 		}
283 283
 
@@ -354,12 +354,12 @@  discard block
 block discarded – undo
354 354
 
355 355
 		$declineAction = $notification->createAction();
356 356
 		$declineAction->setLabel('decline')
357
-			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
357
+			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/'.$shareId)), 'DELETE');
358 358
 		$notification->addAction($declineAction);
359 359
 
360 360
 		$acceptAction = $notification->createAction();
361 361
 		$acceptAction->setLabel('accept')
362
-			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
362
+			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/'.$shareId)), 'POST');
363 363
 		$notification->addAction($acceptAction);
364 364
 
365 365
 		$this->notificationManager->notify($notification);
@@ -419,7 +419,7 @@  discard block
 block discarded – undo
419 419
 	 */
420 420
 	protected function executeAcceptShare(IShare $share) {
421 421
 		try {
422
-			$fileId = (int)$share->getNode()->getId();
422
+			$fileId = (int) $share->getNode()->getId();
423 423
 			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
424 424
 		} catch (\Exception $e) {
425 425
 			throw new ShareNotFound();
@@ -497,7 +497,7 @@  discard block
 block discarded – undo
497 497
 		$this->federatedShareProvider->removeShareFromTable($share);
498 498
 
499 499
 		try {
500
-			$fileId = (int)$share->getNode()->getId();
500
+			$fileId = (int) $share->getNode()->getId();
501 501
 			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
502 502
 		} catch (\Exception $e) {
503 503
 			throw new ShareNotFound();
@@ -592,10 +592,10 @@  discard block
 block discarded – undo
592 592
 			// delete all child in case of a group share
593 593
 			$qb = $this->connection->getQueryBuilder();
594 594
 			$qb->delete('share_external')
595
-				->where($qb->expr()->eq('parent', $qb->createNamedParameter((int)$share['id'])));
595
+				->where($qb->expr()->eq('parent', $qb->createNamedParameter((int) $share['id'])));
596 596
 			$qb->execute();
597 597
 
598
-			if ((int)$share['share_type'] === Share::SHARE_TYPE_USER) {
598
+			if ((int) $share['share_type'] === Share::SHARE_TYPE_USER) {
599 599
 				if ($share['accepted']) {
600 600
 					$path = trim($mountpoint, '/');
601 601
 				} else {
@@ -604,7 +604,7 @@  discard block
 block discarded – undo
604 604
 				$notification = $this->notificationManager->createNotification();
605 605
 				$notification->setApp('files_sharing')
606 606
 					->setUser($share['user'])
607
-					->setObject('remote_share', (int)$share['id']);
607
+					->setObject('remote_share', (int) $share['id']);
608 608
 				$this->notificationManager->markProcessed($notification);
609 609
 
610 610
 				$event = $this->activityManager->generateEvent();
@@ -612,7 +612,7 @@  discard block
 block discarded – undo
612 612
 					->setType('remote_share')
613 613
 					->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
614 614
 					->setAffectedUser($user)
615
-					->setObject('remote_share', (int)$share['id'], $path);
615
+					->setObject('remote_share', (int) $share['id'], $path);
616 616
 				\OC::$server->getActivityManager()->publish($event);
617 617
 			}
618 618
 		}
@@ -661,7 +661,7 @@  discard block
 block discarded – undo
661 661
 			$owner = $share->getShareOwner();
662 662
 			$currentServer = $this->addressHandler->generateRemoteURL();
663 663
 			if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
664
-				throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
664
+				throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: '.$id);
665 665
 			}
666 666
 		} catch (\Exception $e) {
667 667
 			throw new ProviderCouldNotAddShareException($e->getMessage());
@@ -675,10 +675,10 @@  discard block
 block discarded – undo
675 675
 			$share->setSharedBy($share->getSharedWith());
676 676
 			$share->setSharedWith($shareWith);
677 677
 			$result = $this->federatedShareProvider->create($share);
678
-			$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
678
+			$this->federatedShareProvider->storeRemoteId((int) $result->getId(), $senderId);
679 679
 			return ['token' => $result->getToken(), 'providerId' => $result->getId()];
680 680
 		} else {
681
-			throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
681
+			throw new ProviderCouldNotAddShareException('resharing not allowed for share: '.$id);
682 682
 		}
683 683
 
684 684
 	}
@@ -724,7 +724,7 @@  discard block
 block discarded – undo
724 724
 	 */
725 725
 	protected function ocmPermissions2ncPermissions(array $ocmPermissions) {
726 726
 		$ncPermissions = 0;
727
-		foreach($ocmPermissions as $permission) {
727
+		foreach ($ocmPermissions as $permission) {
728 728
 			switch (strtolower($permission)) {
729 729
 				case 'read':
730 730
 					$ncPermissions += Constants::PERMISSION_READ;
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/AddressHandler.php 1 patch
Indentation   +117 added lines, -117 removed lines patch added patch discarded remove patch
@@ -36,121 +36,121 @@
 block discarded – undo
36 36
  */
37 37
 class AddressHandler {
38 38
 
39
-	/** @var IL10N */
40
-	private $l;
41
-
42
-	/** @var IURLGenerator */
43
-	private $urlGenerator;
44
-
45
-	/** @var ICloudIdManager */
46
-	private $cloudIdManager;
47
-
48
-	/**
49
-	 * AddressHandler constructor.
50
-	 *
51
-	 * @param IURLGenerator $urlGenerator
52
-	 * @param IL10N $il10n
53
-	 * @param ICloudIdManager $cloudIdManager
54
-	 */
55
-	public function __construct(
56
-		IURLGenerator $urlGenerator,
57
-		IL10N $il10n,
58
-		ICloudIdManager $cloudIdManager
59
-	) {
60
-		$this->l = $il10n;
61
-		$this->urlGenerator = $urlGenerator;
62
-		$this->cloudIdManager = $cloudIdManager;
63
-	}
64
-
65
-	/**
66
-	 * split user and remote from federated cloud id
67
-	 *
68
-	 * @param string $address federated share address
69
-	 * @return array [user, remoteURL]
70
-	 * @throws HintException
71
-	 */
72
-	public function splitUserRemote($address) {
73
-		try {
74
-			$cloudId = $this->cloudIdManager->resolveCloudId($address);
75
-			return [$cloudId->getUser(), $cloudId->getRemote()];
76
-		} catch (\InvalidArgumentException $e) {
77
-			$hint = $this->l->t('Invalid Federated Cloud ID');
78
-			throw new HintException('Invalid Federated Cloud ID', $hint, 0, $e);
79
-		}
80
-	}
81
-
82
-	/**
83
-	 * generate remote URL part of federated ID
84
-	 *
85
-	 * @return string url of the current server
86
-	 */
87
-	public function generateRemoteURL() {
88
-		return $this->urlGenerator->getAbsoluteURL('/');
89
-	}
90
-
91
-	/**
92
-	 * check if two federated cloud IDs refer to the same user
93
-	 *
94
-	 * @param string $user1
95
-	 * @param string $server1
96
-	 * @param string $user2
97
-	 * @param string $server2
98
-	 * @return bool true if both users and servers are the same
99
-	 */
100
-	public function compareAddresses($user1, $server1, $user2, $server2) {
101
-		$normalizedServer1 = strtolower($this->removeProtocolFromUrl($server1));
102
-		$normalizedServer2 = strtolower($this->removeProtocolFromUrl($server2));
103
-
104
-		if (rtrim($normalizedServer1, '/') === rtrim($normalizedServer2, '/')) {
105
-			// FIXME this should be a method in the user management instead
106
-			\OCP\Util::emitHook(
107
-				'\OCA\Files_Sharing\API\Server2Server',
108
-				'preLoginNameUsedAsUserName',
109
-				['uid' => &$user1]
110
-			);
111
-			\OCP\Util::emitHook(
112
-				'\OCA\Files_Sharing\API\Server2Server',
113
-				'preLoginNameUsedAsUserName',
114
-				['uid' => &$user2]
115
-			);
116
-
117
-			if ($user1 === $user2) {
118
-				return true;
119
-			}
120
-		}
121
-
122
-		return false;
123
-	}
124
-
125
-	/**
126
-	 * remove protocol from URL
127
-	 *
128
-	 * @param string $url
129
-	 * @return string
130
-	 */
131
-	public function removeProtocolFromUrl($url) {
132
-		if (strpos($url, 'https://') === 0) {
133
-			return substr($url, strlen('https://'));
134
-		} else if (strpos($url, 'http://') === 0) {
135
-			return substr($url, strlen('http://'));
136
-		}
137
-
138
-		return $url;
139
-	}
140
-
141
-	/**
142
-	 * check if the url contain the protocol (http or https)
143
-	 *
144
-	 * @param string $url
145
-	 * @return bool
146
-	 */
147
-	public function urlContainProtocol($url) {
148
-		if (strpos($url, 'https://') === 0 ||
149
-			strpos($url, 'http://') === 0) {
150
-
151
-			return true;
152
-		}
153
-
154
-		return false;
155
-	}
39
+    /** @var IL10N */
40
+    private $l;
41
+
42
+    /** @var IURLGenerator */
43
+    private $urlGenerator;
44
+
45
+    /** @var ICloudIdManager */
46
+    private $cloudIdManager;
47
+
48
+    /**
49
+     * AddressHandler constructor.
50
+     *
51
+     * @param IURLGenerator $urlGenerator
52
+     * @param IL10N $il10n
53
+     * @param ICloudIdManager $cloudIdManager
54
+     */
55
+    public function __construct(
56
+        IURLGenerator $urlGenerator,
57
+        IL10N $il10n,
58
+        ICloudIdManager $cloudIdManager
59
+    ) {
60
+        $this->l = $il10n;
61
+        $this->urlGenerator = $urlGenerator;
62
+        $this->cloudIdManager = $cloudIdManager;
63
+    }
64
+
65
+    /**
66
+     * split user and remote from federated cloud id
67
+     *
68
+     * @param string $address federated share address
69
+     * @return array [user, remoteURL]
70
+     * @throws HintException
71
+     */
72
+    public function splitUserRemote($address) {
73
+        try {
74
+            $cloudId = $this->cloudIdManager->resolveCloudId($address);
75
+            return [$cloudId->getUser(), $cloudId->getRemote()];
76
+        } catch (\InvalidArgumentException $e) {
77
+            $hint = $this->l->t('Invalid Federated Cloud ID');
78
+            throw new HintException('Invalid Federated Cloud ID', $hint, 0, $e);
79
+        }
80
+    }
81
+
82
+    /**
83
+     * generate remote URL part of federated ID
84
+     *
85
+     * @return string url of the current server
86
+     */
87
+    public function generateRemoteURL() {
88
+        return $this->urlGenerator->getAbsoluteURL('/');
89
+    }
90
+
91
+    /**
92
+     * check if two federated cloud IDs refer to the same user
93
+     *
94
+     * @param string $user1
95
+     * @param string $server1
96
+     * @param string $user2
97
+     * @param string $server2
98
+     * @return bool true if both users and servers are the same
99
+     */
100
+    public function compareAddresses($user1, $server1, $user2, $server2) {
101
+        $normalizedServer1 = strtolower($this->removeProtocolFromUrl($server1));
102
+        $normalizedServer2 = strtolower($this->removeProtocolFromUrl($server2));
103
+
104
+        if (rtrim($normalizedServer1, '/') === rtrim($normalizedServer2, '/')) {
105
+            // FIXME this should be a method in the user management instead
106
+            \OCP\Util::emitHook(
107
+                '\OCA\Files_Sharing\API\Server2Server',
108
+                'preLoginNameUsedAsUserName',
109
+                ['uid' => &$user1]
110
+            );
111
+            \OCP\Util::emitHook(
112
+                '\OCA\Files_Sharing\API\Server2Server',
113
+                'preLoginNameUsedAsUserName',
114
+                ['uid' => &$user2]
115
+            );
116
+
117
+            if ($user1 === $user2) {
118
+                return true;
119
+            }
120
+        }
121
+
122
+        return false;
123
+    }
124
+
125
+    /**
126
+     * remove protocol from URL
127
+     *
128
+     * @param string $url
129
+     * @return string
130
+     */
131
+    public function removeProtocolFromUrl($url) {
132
+        if (strpos($url, 'https://') === 0) {
133
+            return substr($url, strlen('https://'));
134
+        } else if (strpos($url, 'http://') === 0) {
135
+            return substr($url, strlen('http://'));
136
+        }
137
+
138
+        return $url;
139
+    }
140
+
141
+    /**
142
+     * check if the url contain the protocol (http or https)
143
+     *
144
+     * @param string $url
145
+     * @return bool
146
+     */
147
+    public function urlContainProtocol($url) {
148
+        if (strpos($url, 'https://') === 0 ||
149
+            strpos($url, 'http://') === 0) {
150
+
151
+            return true;
152
+        }
153
+
154
+        return false;
155
+    }
156 156
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/FederatedShareProvider.php 1 patch
Indentation   +1063 added lines, -1063 removed lines patch added patch discarded remove patch
@@ -57,1077 +57,1077 @@
 block discarded – undo
57 57
  */
58 58
 class FederatedShareProvider implements IShareProvider {
59 59
 
60
-	const SHARE_TYPE_REMOTE = 6;
61
-
62
-	/** @var IDBConnection */
63
-	private $dbConnection;
64
-
65
-	/** @var AddressHandler */
66
-	private $addressHandler;
67
-
68
-	/** @var Notifications */
69
-	private $notifications;
70
-
71
-	/** @var TokenHandler */
72
-	private $tokenHandler;
73
-
74
-	/** @var IL10N */
75
-	private $l;
76
-
77
-	/** @var ILogger */
78
-	private $logger;
79
-
80
-	/** @var IRootFolder */
81
-	private $rootFolder;
82
-
83
-	/** @var IConfig */
84
-	private $config;
85
-
86
-	/** @var string */
87
-	private $externalShareTable = 'share_external';
88
-
89
-	/** @var IUserManager */
90
-	private $userManager;
91
-
92
-	/** @var ICloudIdManager */
93
-	private $cloudIdManager;
94
-
95
-	/** @var \OCP\GlobalScale\IConfig */
96
-	private $gsConfig;
97
-
98
-	/** @var ICloudFederationProviderManager */
99
-	private $cloudFederationProviderManager;
100
-
101
-	/** @var array list of supported share types */
102
-	private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
103
-
104
-	/**
105
-	 * DefaultShareProvider constructor.
106
-	 *
107
-	 * @param IDBConnection $connection
108
-	 * @param AddressHandler $addressHandler
109
-	 * @param Notifications $notifications
110
-	 * @param TokenHandler $tokenHandler
111
-	 * @param IL10N $l10n
112
-	 * @param ILogger $logger
113
-	 * @param IRootFolder $rootFolder
114
-	 * @param IConfig $config
115
-	 * @param IUserManager $userManager
116
-	 * @param ICloudIdManager $cloudIdManager
117
-	 * @param \OCP\GlobalScale\IConfig $globalScaleConfig
118
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
119
-	 */
120
-	public function __construct(
121
-			IDBConnection $connection,
122
-			AddressHandler $addressHandler,
123
-			Notifications $notifications,
124
-			TokenHandler $tokenHandler,
125
-			IL10N $l10n,
126
-			ILogger $logger,
127
-			IRootFolder $rootFolder,
128
-			IConfig $config,
129
-			IUserManager $userManager,
130
-			ICloudIdManager $cloudIdManager,
131
-			\OCP\GlobalScale\IConfig $globalScaleConfig,
132
-			ICloudFederationProviderManager $cloudFederationProviderManager
133
-	) {
134
-		$this->dbConnection = $connection;
135
-		$this->addressHandler = $addressHandler;
136
-		$this->notifications = $notifications;
137
-		$this->tokenHandler = $tokenHandler;
138
-		$this->l = $l10n;
139
-		$this->logger = $logger;
140
-		$this->rootFolder = $rootFolder;
141
-		$this->config = $config;
142
-		$this->userManager = $userManager;
143
-		$this->cloudIdManager = $cloudIdManager;
144
-		$this->gsConfig = $globalScaleConfig;
145
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
146
-	}
147
-
148
-	/**
149
-	 * Return the identifier of this provider.
150
-	 *
151
-	 * @return string Containing only [a-zA-Z0-9]
152
-	 */
153
-	public function identifier() {
154
-		return 'ocFederatedSharing';
155
-	}
156
-
157
-	/**
158
-	 * Share a path
159
-	 *
160
-	 * @param IShare $share
161
-	 * @return IShare The share object
162
-	 * @throws ShareNotFound
163
-	 * @throws \Exception
164
-	 */
165
-	public function create(IShare $share) {
166
-
167
-		$shareWith = $share->getSharedWith();
168
-		$itemSource = $share->getNodeId();
169
-		$itemType = $share->getNodeType();
170
-		$permissions = $share->getPermissions();
171
-		$sharedBy = $share->getSharedBy();
172
-		$shareType = $share->getShareType();
173
-
174
-		if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP &&
175
-			!$this->isOutgoingServer2serverGroupShareEnabled()
176
-		) {
177
-			$message = 'It is not allowed to send federated group shares from this server.';
178
-			$message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
179
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
180
-			throw new \Exception($message_t);
181
-		}
182
-
183
-		/*
60
+    const SHARE_TYPE_REMOTE = 6;
61
+
62
+    /** @var IDBConnection */
63
+    private $dbConnection;
64
+
65
+    /** @var AddressHandler */
66
+    private $addressHandler;
67
+
68
+    /** @var Notifications */
69
+    private $notifications;
70
+
71
+    /** @var TokenHandler */
72
+    private $tokenHandler;
73
+
74
+    /** @var IL10N */
75
+    private $l;
76
+
77
+    /** @var ILogger */
78
+    private $logger;
79
+
80
+    /** @var IRootFolder */
81
+    private $rootFolder;
82
+
83
+    /** @var IConfig */
84
+    private $config;
85
+
86
+    /** @var string */
87
+    private $externalShareTable = 'share_external';
88
+
89
+    /** @var IUserManager */
90
+    private $userManager;
91
+
92
+    /** @var ICloudIdManager */
93
+    private $cloudIdManager;
94
+
95
+    /** @var \OCP\GlobalScale\IConfig */
96
+    private $gsConfig;
97
+
98
+    /** @var ICloudFederationProviderManager */
99
+    private $cloudFederationProviderManager;
100
+
101
+    /** @var array list of supported share types */
102
+    private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
103
+
104
+    /**
105
+     * DefaultShareProvider constructor.
106
+     *
107
+     * @param IDBConnection $connection
108
+     * @param AddressHandler $addressHandler
109
+     * @param Notifications $notifications
110
+     * @param TokenHandler $tokenHandler
111
+     * @param IL10N $l10n
112
+     * @param ILogger $logger
113
+     * @param IRootFolder $rootFolder
114
+     * @param IConfig $config
115
+     * @param IUserManager $userManager
116
+     * @param ICloudIdManager $cloudIdManager
117
+     * @param \OCP\GlobalScale\IConfig $globalScaleConfig
118
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
119
+     */
120
+    public function __construct(
121
+            IDBConnection $connection,
122
+            AddressHandler $addressHandler,
123
+            Notifications $notifications,
124
+            TokenHandler $tokenHandler,
125
+            IL10N $l10n,
126
+            ILogger $logger,
127
+            IRootFolder $rootFolder,
128
+            IConfig $config,
129
+            IUserManager $userManager,
130
+            ICloudIdManager $cloudIdManager,
131
+            \OCP\GlobalScale\IConfig $globalScaleConfig,
132
+            ICloudFederationProviderManager $cloudFederationProviderManager
133
+    ) {
134
+        $this->dbConnection = $connection;
135
+        $this->addressHandler = $addressHandler;
136
+        $this->notifications = $notifications;
137
+        $this->tokenHandler = $tokenHandler;
138
+        $this->l = $l10n;
139
+        $this->logger = $logger;
140
+        $this->rootFolder = $rootFolder;
141
+        $this->config = $config;
142
+        $this->userManager = $userManager;
143
+        $this->cloudIdManager = $cloudIdManager;
144
+        $this->gsConfig = $globalScaleConfig;
145
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
146
+    }
147
+
148
+    /**
149
+     * Return the identifier of this provider.
150
+     *
151
+     * @return string Containing only [a-zA-Z0-9]
152
+     */
153
+    public function identifier() {
154
+        return 'ocFederatedSharing';
155
+    }
156
+
157
+    /**
158
+     * Share a path
159
+     *
160
+     * @param IShare $share
161
+     * @return IShare The share object
162
+     * @throws ShareNotFound
163
+     * @throws \Exception
164
+     */
165
+    public function create(IShare $share) {
166
+
167
+        $shareWith = $share->getSharedWith();
168
+        $itemSource = $share->getNodeId();
169
+        $itemType = $share->getNodeType();
170
+        $permissions = $share->getPermissions();
171
+        $sharedBy = $share->getSharedBy();
172
+        $shareType = $share->getShareType();
173
+
174
+        if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP &&
175
+            !$this->isOutgoingServer2serverGroupShareEnabled()
176
+        ) {
177
+            $message = 'It is not allowed to send federated group shares from this server.';
178
+            $message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
179
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
180
+            throw new \Exception($message_t);
181
+        }
182
+
183
+        /*
184 184
 		 * Check if file is not already shared with the remote user
185 185
 		 */
186
-		$alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
187
-		$alreadySharedGroup = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
188
-		if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
189
-			$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
190
-			$message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
191
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
192
-			throw new \Exception($message_t);
193
-		}
194
-
195
-
196
-		// don't allow federated shares if source and target server are the same
197
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
198
-		$currentServer = $this->addressHandler->generateRemoteURL();
199
-		$currentUser = $sharedBy;
200
-		if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
201
-			$message = 'Not allowed to create a federated share with the same user.';
202
-			$message_t = $this->l->t('Not allowed to create a federated share with the same user');
203
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
204
-			throw new \Exception($message_t);
205
-		}
206
-
207
-
208
-		$share->setSharedWith($cloudId->getId());
209
-
210
-		try {
211
-			$remoteShare = $this->getShareFromExternalShareTable($share);
212
-		} catch (ShareNotFound $e) {
213
-			$remoteShare = null;
214
-		}
215
-
216
-		if ($remoteShare) {
217
-			try {
218
-				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
219
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
220
-				$share->setId($shareId);
221
-				list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
222
-				// remote share was create successfully if we get a valid token as return
223
-				$send = is_string($token) && $token !== '';
224
-			} catch (\Exception $e) {
225
-				// fall back to old re-share behavior if the remote server
226
-				// doesn't support flat re-shares (was introduced with Nextcloud 9.1)
227
-				$this->removeShareFromTable($share);
228
-				$shareId = $this->createFederatedShare($share);
229
-			}
230
-			if ($send) {
231
-				$this->updateSuccessfulReshare($shareId, $token);
232
-				$this->storeRemoteId($shareId, $remoteId);
233
-			} else {
234
-				$this->removeShareFromTable($share);
235
-				$message_t = $this->l->t('File is already shared with %s', [$shareWith]);
236
-				throw new \Exception($message_t);
237
-			}
238
-
239
-		} else {
240
-			$shareId = $this->createFederatedShare($share);
241
-		}
242
-
243
-		$data = $this->getRawShare($shareId);
244
-		return $this->createShareObject($data);
245
-	}
246
-
247
-	/**
248
-	 * create federated share and inform the recipient
249
-	 *
250
-	 * @param IShare $share
251
-	 * @return int
252
-	 * @throws ShareNotFound
253
-	 * @throws \Exception
254
-	 */
255
-	protected function createFederatedShare(IShare $share) {
256
-		$token = $this->tokenHandler->generateToken();
257
-		$shareId = $this->addShareToDB(
258
-			$share->getNodeId(),
259
-			$share->getNodeType(),
260
-			$share->getSharedWith(),
261
-			$share->getSharedBy(),
262
-			$share->getShareOwner(),
263
-			$share->getPermissions(),
264
-			$token,
265
-			$share->getShareType()
266
-		);
267
-
268
-		$failure = false;
269
-
270
-		try {
271
-			$sharedByFederatedId = $share->getSharedBy();
272
-			if ($this->userManager->userExists($sharedByFederatedId)) {
273
-				$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
274
-				$sharedByFederatedId = $cloudId->getId();
275
-			}
276
-			$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
277
-			$send = $this->notifications->sendRemoteShare(
278
-				$token,
279
-				$share->getSharedWith(),
280
-				$share->getNode()->getName(),
281
-				$shareId,
282
-				$share->getShareOwner(),
283
-				$ownerCloudId->getId(),
284
-				$share->getSharedBy(),
285
-				$sharedByFederatedId,
286
-				$share->getShareType()
287
-			);
288
-
289
-			if ($send === false) {
290
-				$failure = true;
291
-			}
292
-		} catch (\Exception $e) {
293
-			$this->logger->logException($e, [
294
-				'message' => 'Failed to notify remote server of federated share, removing share.',
295
-				'level' => ILogger::ERROR,
296
-				'app' => 'federatedfilesharing',
297
-			]);
298
-			$failure = true;
299
-		}
300
-
301
-		if($failure) {
302
-			$this->removeShareFromTableById($shareId);
303
-			$message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
304
-				[$share->getNode()->getName(), $share->getSharedWith()]);
305
-			throw new \Exception($message_t);
306
-		}
307
-
308
-		return $shareId;
309
-
310
-	}
311
-
312
-	/**
313
-	 * @param string $shareWith
314
-	 * @param IShare $share
315
-	 * @param string $shareId internal share Id
316
-	 * @return array
317
-	 * @throws \Exception
318
-	 */
319
-	protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
320
-
321
-		$remoteShare = $this->getShareFromExternalShareTable($share);
322
-		$token = $remoteShare['share_token'];
323
-		$remoteId = $remoteShare['remote_id'];
324
-		$remote = $remoteShare['remote'];
325
-
326
-		list($token, $remoteId) = $this->notifications->requestReShare(
327
-			$token,
328
-			$remoteId,
329
-			$shareId,
330
-			$remote,
331
-			$shareWith,
332
-			$share->getPermissions(),
333
-			$share->getNode()->getName()
334
-		);
335
-
336
-		return [$token, $remoteId];
337
-	}
338
-
339
-	/**
340
-	 * get federated share from the share_external table but exclude mounted link shares
341
-	 *
342
-	 * @param IShare $share
343
-	 * @return array
344
-	 * @throws ShareNotFound
345
-	 */
346
-	protected function getShareFromExternalShareTable(IShare $share) {
347
-		$query = $this->dbConnection->getQueryBuilder();
348
-		$query->select('*')->from($this->externalShareTable)
349
-			->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
350
-			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
351
-		$result = $query->execute()->fetchAll();
352
-
353
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
354
-			return $result[0];
355
-		}
356
-
357
-		throw new ShareNotFound('share not found in share_external table');
358
-	}
359
-
360
-	/**
361
-	 * add share to the database and return the ID
362
-	 *
363
-	 * @param int $itemSource
364
-	 * @param string $itemType
365
-	 * @param string $shareWith
366
-	 * @param string $sharedBy
367
-	 * @param string $uidOwner
368
-	 * @param int $permissions
369
-	 * @param string $token
370
-	 * @param int $shareType
371
-	 * @return int
372
-	 */
373
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
374
-		$qb = $this->dbConnection->getQueryBuilder();
375
-		$qb->insert('share')
376
-			->setValue('share_type', $qb->createNamedParameter($shareType))
377
-			->setValue('item_type', $qb->createNamedParameter($itemType))
378
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
379
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
380
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
381
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
382
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
383
-			->setValue('permissions', $qb->createNamedParameter($permissions))
384
-			->setValue('token', $qb->createNamedParameter($token))
385
-			->setValue('stime', $qb->createNamedParameter(time()));
386
-
387
-		/*
186
+        $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
187
+        $alreadySharedGroup = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
188
+        if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
189
+            $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
190
+            $message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
191
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
192
+            throw new \Exception($message_t);
193
+        }
194
+
195
+
196
+        // don't allow federated shares if source and target server are the same
197
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
198
+        $currentServer = $this->addressHandler->generateRemoteURL();
199
+        $currentUser = $sharedBy;
200
+        if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
201
+            $message = 'Not allowed to create a federated share with the same user.';
202
+            $message_t = $this->l->t('Not allowed to create a federated share with the same user');
203
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
204
+            throw new \Exception($message_t);
205
+        }
206
+
207
+
208
+        $share->setSharedWith($cloudId->getId());
209
+
210
+        try {
211
+            $remoteShare = $this->getShareFromExternalShareTable($share);
212
+        } catch (ShareNotFound $e) {
213
+            $remoteShare = null;
214
+        }
215
+
216
+        if ($remoteShare) {
217
+            try {
218
+                $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
219
+                $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
220
+                $share->setId($shareId);
221
+                list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
222
+                // remote share was create successfully if we get a valid token as return
223
+                $send = is_string($token) && $token !== '';
224
+            } catch (\Exception $e) {
225
+                // fall back to old re-share behavior if the remote server
226
+                // doesn't support flat re-shares (was introduced with Nextcloud 9.1)
227
+                $this->removeShareFromTable($share);
228
+                $shareId = $this->createFederatedShare($share);
229
+            }
230
+            if ($send) {
231
+                $this->updateSuccessfulReshare($shareId, $token);
232
+                $this->storeRemoteId($shareId, $remoteId);
233
+            } else {
234
+                $this->removeShareFromTable($share);
235
+                $message_t = $this->l->t('File is already shared with %s', [$shareWith]);
236
+                throw new \Exception($message_t);
237
+            }
238
+
239
+        } else {
240
+            $shareId = $this->createFederatedShare($share);
241
+        }
242
+
243
+        $data = $this->getRawShare($shareId);
244
+        return $this->createShareObject($data);
245
+    }
246
+
247
+    /**
248
+     * create federated share and inform the recipient
249
+     *
250
+     * @param IShare $share
251
+     * @return int
252
+     * @throws ShareNotFound
253
+     * @throws \Exception
254
+     */
255
+    protected function createFederatedShare(IShare $share) {
256
+        $token = $this->tokenHandler->generateToken();
257
+        $shareId = $this->addShareToDB(
258
+            $share->getNodeId(),
259
+            $share->getNodeType(),
260
+            $share->getSharedWith(),
261
+            $share->getSharedBy(),
262
+            $share->getShareOwner(),
263
+            $share->getPermissions(),
264
+            $token,
265
+            $share->getShareType()
266
+        );
267
+
268
+        $failure = false;
269
+
270
+        try {
271
+            $sharedByFederatedId = $share->getSharedBy();
272
+            if ($this->userManager->userExists($sharedByFederatedId)) {
273
+                $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
274
+                $sharedByFederatedId = $cloudId->getId();
275
+            }
276
+            $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
277
+            $send = $this->notifications->sendRemoteShare(
278
+                $token,
279
+                $share->getSharedWith(),
280
+                $share->getNode()->getName(),
281
+                $shareId,
282
+                $share->getShareOwner(),
283
+                $ownerCloudId->getId(),
284
+                $share->getSharedBy(),
285
+                $sharedByFederatedId,
286
+                $share->getShareType()
287
+            );
288
+
289
+            if ($send === false) {
290
+                $failure = true;
291
+            }
292
+        } catch (\Exception $e) {
293
+            $this->logger->logException($e, [
294
+                'message' => 'Failed to notify remote server of federated share, removing share.',
295
+                'level' => ILogger::ERROR,
296
+                'app' => 'federatedfilesharing',
297
+            ]);
298
+            $failure = true;
299
+        }
300
+
301
+        if($failure) {
302
+            $this->removeShareFromTableById($shareId);
303
+            $message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
304
+                [$share->getNode()->getName(), $share->getSharedWith()]);
305
+            throw new \Exception($message_t);
306
+        }
307
+
308
+        return $shareId;
309
+
310
+    }
311
+
312
+    /**
313
+     * @param string $shareWith
314
+     * @param IShare $share
315
+     * @param string $shareId internal share Id
316
+     * @return array
317
+     * @throws \Exception
318
+     */
319
+    protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
320
+
321
+        $remoteShare = $this->getShareFromExternalShareTable($share);
322
+        $token = $remoteShare['share_token'];
323
+        $remoteId = $remoteShare['remote_id'];
324
+        $remote = $remoteShare['remote'];
325
+
326
+        list($token, $remoteId) = $this->notifications->requestReShare(
327
+            $token,
328
+            $remoteId,
329
+            $shareId,
330
+            $remote,
331
+            $shareWith,
332
+            $share->getPermissions(),
333
+            $share->getNode()->getName()
334
+        );
335
+
336
+        return [$token, $remoteId];
337
+    }
338
+
339
+    /**
340
+     * get federated share from the share_external table but exclude mounted link shares
341
+     *
342
+     * @param IShare $share
343
+     * @return array
344
+     * @throws ShareNotFound
345
+     */
346
+    protected function getShareFromExternalShareTable(IShare $share) {
347
+        $query = $this->dbConnection->getQueryBuilder();
348
+        $query->select('*')->from($this->externalShareTable)
349
+            ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
350
+            ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
351
+        $result = $query->execute()->fetchAll();
352
+
353
+        if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
354
+            return $result[0];
355
+        }
356
+
357
+        throw new ShareNotFound('share not found in share_external table');
358
+    }
359
+
360
+    /**
361
+     * add share to the database and return the ID
362
+     *
363
+     * @param int $itemSource
364
+     * @param string $itemType
365
+     * @param string $shareWith
366
+     * @param string $sharedBy
367
+     * @param string $uidOwner
368
+     * @param int $permissions
369
+     * @param string $token
370
+     * @param int $shareType
371
+     * @return int
372
+     */
373
+    private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
374
+        $qb = $this->dbConnection->getQueryBuilder();
375
+        $qb->insert('share')
376
+            ->setValue('share_type', $qb->createNamedParameter($shareType))
377
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
378
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
379
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
380
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
381
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
382
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
383
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
384
+            ->setValue('token', $qb->createNamedParameter($token))
385
+            ->setValue('stime', $qb->createNamedParameter(time()));
386
+
387
+        /*
388 388
 		 * Added to fix https://github.com/owncloud/core/issues/22215
389 389
 		 * Can be removed once we get rid of ajax/share.php
390 390
 		 */
391
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
392
-
393
-		$qb->execute();
394
-		$id = $qb->getLastInsertId();
395
-
396
-		return (int)$id;
397
-	}
398
-
399
-	/**
400
-	 * Update a share
401
-	 *
402
-	 * @param IShare $share
403
-	 * @return IShare The share object
404
-	 */
405
-	public function update(IShare $share) {
406
-		/*
391
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
392
+
393
+        $qb->execute();
394
+        $id = $qb->getLastInsertId();
395
+
396
+        return (int)$id;
397
+    }
398
+
399
+    /**
400
+     * Update a share
401
+     *
402
+     * @param IShare $share
403
+     * @return IShare The share object
404
+     */
405
+    public function update(IShare $share) {
406
+        /*
407 407
 		 * We allow updating the permissions of federated shares
408 408
 		 */
409
-		$qb = $this->dbConnection->getQueryBuilder();
410
-			$qb->update('share')
411
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
412
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
413
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
414
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
415
-				->execute();
416
-
417
-		// send the updated permission to the owner/initiator, if they are not the same
418
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
419
-			$this->sendPermissionUpdate($share);
420
-		}
421
-
422
-		return $share;
423
-	}
424
-
425
-	/**
426
-	 * send the updated permission to the owner/initiator, if they are not the same
427
-	 *
428
-	 * @param IShare $share
429
-	 * @throws ShareNotFound
430
-	 * @throws \OC\HintException
431
-	 */
432
-	protected function sendPermissionUpdate(IShare $share) {
433
-		$remoteId = $this->getRemoteId($share);
434
-		// if the local user is the owner we send the permission change to the initiator
435
-		if ($this->userManager->userExists($share->getShareOwner())) {
436
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
437
-		} else { // ... if not we send the permission change to the owner
438
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
439
-		}
440
-		$this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
441
-	}
442
-
443
-
444
-	/**
445
-	 * update successful reShare with the correct token
446
-	 *
447
-	 * @param int $shareId
448
-	 * @param string $token
449
-	 */
450
-	protected function updateSuccessfulReShare($shareId, $token) {
451
-		$query = $this->dbConnection->getQueryBuilder();
452
-		$query->update('share')
453
-			->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
454
-			->set('token', $query->createNamedParameter($token))
455
-			->execute();
456
-	}
457
-
458
-	/**
459
-	 * store remote ID in federated reShare table
460
-	 *
461
-	 * @param $shareId
462
-	 * @param $remoteId
463
-	 */
464
-	public function storeRemoteId($shareId, $remoteId) {
465
-		$query = $this->dbConnection->getQueryBuilder();
466
-		$query->insert('federated_reshares')
467
-			->values(
468
-				[
469
-					'share_id' =>  $query->createNamedParameter($shareId),
470
-					'remote_id' => $query->createNamedParameter($remoteId),
471
-				]
472
-			);
473
-		$query->execute();
474
-	}
475
-
476
-	/**
477
-	 * get share ID on remote server for federated re-shares
478
-	 *
479
-	 * @param IShare $share
480
-	 * @return int
481
-	 * @throws ShareNotFound
482
-	 */
483
-	public function getRemoteId(IShare $share) {
484
-		$query = $this->dbConnection->getQueryBuilder();
485
-		$query->select('remote_id')->from('federated_reshares')
486
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
487
-		$data = $query->execute()->fetch();
488
-
489
-		if (!is_array($data) || !isset($data['remote_id'])) {
490
-			throw new ShareNotFound();
491
-		}
492
-
493
-		return (int)$data['remote_id'];
494
-	}
495
-
496
-	/**
497
-	 * @inheritdoc
498
-	 */
499
-	public function move(IShare $share, $recipient) {
500
-		/*
409
+        $qb = $this->dbConnection->getQueryBuilder();
410
+            $qb->update('share')
411
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
412
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
413
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
414
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
415
+                ->execute();
416
+
417
+        // send the updated permission to the owner/initiator, if they are not the same
418
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
419
+            $this->sendPermissionUpdate($share);
420
+        }
421
+
422
+        return $share;
423
+    }
424
+
425
+    /**
426
+     * send the updated permission to the owner/initiator, if they are not the same
427
+     *
428
+     * @param IShare $share
429
+     * @throws ShareNotFound
430
+     * @throws \OC\HintException
431
+     */
432
+    protected function sendPermissionUpdate(IShare $share) {
433
+        $remoteId = $this->getRemoteId($share);
434
+        // if the local user is the owner we send the permission change to the initiator
435
+        if ($this->userManager->userExists($share->getShareOwner())) {
436
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
437
+        } else { // ... if not we send the permission change to the owner
438
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
439
+        }
440
+        $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
441
+    }
442
+
443
+
444
+    /**
445
+     * update successful reShare with the correct token
446
+     *
447
+     * @param int $shareId
448
+     * @param string $token
449
+     */
450
+    protected function updateSuccessfulReShare($shareId, $token) {
451
+        $query = $this->dbConnection->getQueryBuilder();
452
+        $query->update('share')
453
+            ->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
454
+            ->set('token', $query->createNamedParameter($token))
455
+            ->execute();
456
+    }
457
+
458
+    /**
459
+     * store remote ID in federated reShare table
460
+     *
461
+     * @param $shareId
462
+     * @param $remoteId
463
+     */
464
+    public function storeRemoteId($shareId, $remoteId) {
465
+        $query = $this->dbConnection->getQueryBuilder();
466
+        $query->insert('federated_reshares')
467
+            ->values(
468
+                [
469
+                    'share_id' =>  $query->createNamedParameter($shareId),
470
+                    'remote_id' => $query->createNamedParameter($remoteId),
471
+                ]
472
+            );
473
+        $query->execute();
474
+    }
475
+
476
+    /**
477
+     * get share ID on remote server for federated re-shares
478
+     *
479
+     * @param IShare $share
480
+     * @return int
481
+     * @throws ShareNotFound
482
+     */
483
+    public function getRemoteId(IShare $share) {
484
+        $query = $this->dbConnection->getQueryBuilder();
485
+        $query->select('remote_id')->from('federated_reshares')
486
+            ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
487
+        $data = $query->execute()->fetch();
488
+
489
+        if (!is_array($data) || !isset($data['remote_id'])) {
490
+            throw new ShareNotFound();
491
+        }
492
+
493
+        return (int)$data['remote_id'];
494
+    }
495
+
496
+    /**
497
+     * @inheritdoc
498
+     */
499
+    public function move(IShare $share, $recipient) {
500
+        /*
501 501
 		 * This function does nothing yet as it is just for outgoing
502 502
 		 * federated shares.
503 503
 		 */
504
-		return $share;
505
-	}
506
-
507
-	/**
508
-	 * Get all children of this share
509
-	 *
510
-	 * @param IShare $parent
511
-	 * @return IShare[]
512
-	 */
513
-	public function getChildren(IShare $parent) {
514
-		$children = [];
515
-
516
-		$qb = $this->dbConnection->getQueryBuilder();
517
-		$qb->select('*')
518
-			->from('share')
519
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
520
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
521
-			->orderBy('id');
522
-
523
-		$cursor = $qb->execute();
524
-		while($data = $cursor->fetch()) {
525
-			$children[] = $this->createShareObject($data);
526
-		}
527
-		$cursor->closeCursor();
528
-
529
-		return $children;
530
-	}
531
-
532
-	/**
533
-	 * Delete a share (owner unShares the file)
534
-	 *
535
-	 * @param IShare $share
536
-	 * @throws ShareNotFound
537
-	 * @throws \OC\HintException
538
-	 */
539
-	public function delete(IShare $share) {
540
-
541
-		list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
542
-
543
-		// if the local user is the owner we can send the unShare request directly...
544
-		if ($this->userManager->userExists($share->getShareOwner())) {
545
-			$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
546
-			$this->revokeShare($share, true);
547
-		} else { // ... if not we need to correct ID for the unShare request
548
-			$remoteId = $this->getRemoteId($share);
549
-			$this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
550
-			$this->revokeShare($share, false);
551
-		}
552
-
553
-		// only remove the share when all messages are send to not lose information
554
-		// about the share to early
555
-		$this->removeShareFromTable($share);
556
-	}
557
-
558
-	/**
559
-	 * in case of a re-share we need to send the other use (initiator or owner)
560
-	 * a message that the file was unshared
561
-	 *
562
-	 * @param IShare $share
563
-	 * @param bool $isOwner the user can either be the owner or the user who re-sahred it
564
-	 * @throws ShareNotFound
565
-	 * @throws \OC\HintException
566
-	 */
567
-	protected function revokeShare($share, $isOwner) {
568
-		if ($this->userManager->userExists($share->getShareOwner() && $this->userManager->userExists($share->getSharedBy()))) {
569
-			// If both the owner and the initiator of the share are local users we don't have to notify anybody else
570
-			return;
571
-		}
572
-
573
-		// also send a unShare request to the initiator, if this is a different user than the owner
574
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
575
-			if ($isOwner) {
576
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
577
-			} else {
578
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
579
-			}
580
-			$remoteId = $this->getRemoteId($share);
581
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
582
-		}
583
-	}
584
-
585
-	/**
586
-	 * remove share from table
587
-	 *
588
-	 * @param IShare $share
589
-	 */
590
-	public function removeShareFromTable(IShare $share) {
591
-		$this->removeShareFromTableById($share->getId());
592
-	}
593
-
594
-	/**
595
-	 * remove share from table
596
-	 *
597
-	 * @param string $shareId
598
-	 */
599
-	private function removeShareFromTableById($shareId) {
600
-		$qb = $this->dbConnection->getQueryBuilder();
601
-		$qb->delete('share')
602
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
603
-			->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
604
-		$qb->execute();
605
-
606
-		$qb->delete('federated_reshares')
607
-			->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
608
-		$qb->execute();
609
-	}
610
-
611
-	/**
612
-	 * @inheritdoc
613
-	 */
614
-	public function deleteFromSelf(IShare $share, $recipient) {
615
-		// nothing to do here. Technically deleteFromSelf in the context of federated
616
-		// shares is a umount of a external storage. This is handled here
617
-		// apps/files_sharing/lib/external/manager.php
618
-		// TODO move this code over to this app
619
-	}
620
-
621
-	public function restore(IShare $share, string $recipient): IShare {
622
-		throw new GenericShareException('not implemented');
623
-	}
624
-
625
-
626
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
627
-		$qb = $this->dbConnection->getQueryBuilder();
628
-		$qb->select('*')
629
-			->from('share', 's')
630
-			->andWhere($qb->expr()->orX(
631
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
632
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
633
-			))
634
-			->andWhere(
635
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
636
-			);
637
-
638
-		/**
639
-		 * Reshares for this user are shares where they are the owner.
640
-		 */
641
-		if ($reshares === false) {
642
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
643
-		} else {
644
-			$qb->andWhere(
645
-				$qb->expr()->orX(
646
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
647
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
648
-				)
649
-			);
650
-		}
651
-
652
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
653
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
654
-
655
-		$qb->orderBy('id');
656
-
657
-		$cursor = $qb->execute();
658
-		$shares = [];
659
-		while ($data = $cursor->fetch()) {
660
-			$shares[$data['fileid']][] = $this->createShareObject($data);
661
-		}
662
-		$cursor->closeCursor();
663
-
664
-		return $shares;
665
-	}
666
-
667
-	/**
668
-	 * @inheritdoc
669
-	 */
670
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
671
-		$qb = $this->dbConnection->getQueryBuilder();
672
-		$qb->select('*')
673
-			->from('share');
674
-
675
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
676
-
677
-		/**
678
-		 * Reshares for this user are shares where they are the owner.
679
-		 */
680
-		if ($reshares === false) {
681
-			//Special case for old shares created via the web UI
682
-			$or1 = $qb->expr()->andX(
683
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
684
-				$qb->expr()->isNull('uid_initiator')
685
-			);
686
-
687
-			$qb->andWhere(
688
-				$qb->expr()->orX(
689
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
690
-					$or1
691
-				)
692
-			);
693
-		} else {
694
-			$qb->andWhere(
695
-				$qb->expr()->orX(
696
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
697
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
698
-				)
699
-			);
700
-		}
701
-
702
-		if ($node !== null) {
703
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
704
-		}
705
-
706
-		if ($limit !== -1) {
707
-			$qb->setMaxResults($limit);
708
-		}
709
-
710
-		$qb->setFirstResult($offset);
711
-		$qb->orderBy('id');
712
-
713
-		$cursor = $qb->execute();
714
-		$shares = [];
715
-		while($data = $cursor->fetch()) {
716
-			$shares[] = $this->createShareObject($data);
717
-		}
718
-		$cursor->closeCursor();
719
-
720
-		return $shares;
721
-	}
722
-
723
-	/**
724
-	 * @inheritdoc
725
-	 */
726
-	public function getShareById($id, $recipientId = null) {
727
-		$qb = $this->dbConnection->getQueryBuilder();
728
-
729
-		$qb->select('*')
730
-			->from('share')
731
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
732
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
733
-
734
-		$cursor = $qb->execute();
735
-		$data = $cursor->fetch();
736
-		$cursor->closeCursor();
737
-
738
-		if ($data === false) {
739
-			throw new ShareNotFound('Can not find share with ID: ' . $id);
740
-		}
741
-
742
-		try {
743
-			$share = $this->createShareObject($data);
744
-		} catch (InvalidShare $e) {
745
-			throw new ShareNotFound();
746
-		}
747
-
748
-		return $share;
749
-	}
750
-
751
-	/**
752
-	 * Get shares for a given path
753
-	 *
754
-	 * @param \OCP\Files\Node $path
755
-	 * @return IShare[]
756
-	 */
757
-	public function getSharesByPath(Node $path) {
758
-		$qb = $this->dbConnection->getQueryBuilder();
759
-
760
-		// get federated user shares
761
-		$cursor = $qb->select('*')
762
-			->from('share')
763
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
764
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
765
-			->execute();
766
-
767
-		$shares = [];
768
-		while($data = $cursor->fetch()) {
769
-			$shares[] = $this->createShareObject($data);
770
-		}
771
-		$cursor->closeCursor();
772
-
773
-		return $shares;
774
-	}
775
-
776
-	/**
777
-	 * @inheritdoc
778
-	 */
779
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
780
-		/** @var IShare[] $shares */
781
-		$shares = [];
782
-
783
-		//Get shares directly with this user
784
-		$qb = $this->dbConnection->getQueryBuilder();
785
-		$qb->select('*')
786
-			->from('share');
787
-
788
-		// Order by id
789
-		$qb->orderBy('id');
790
-
791
-		// Set limit and offset
792
-		if ($limit !== -1) {
793
-			$qb->setMaxResults($limit);
794
-		}
795
-		$qb->setFirstResult($offset);
796
-
797
-		$qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
798
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
799
-
800
-		// Filter by node if provided
801
-		if ($node !== null) {
802
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
803
-		}
804
-
805
-		$cursor = $qb->execute();
806
-
807
-		while($data = $cursor->fetch()) {
808
-			$shares[] = $this->createShareObject($data);
809
-		}
810
-		$cursor->closeCursor();
811
-
812
-
813
-		return $shares;
814
-	}
815
-
816
-	/**
817
-	 * Get a share by token
818
-	 *
819
-	 * @param string $token
820
-	 * @return IShare
821
-	 * @throws ShareNotFound
822
-	 */
823
-	public function getShareByToken($token) {
824
-		$qb = $this->dbConnection->getQueryBuilder();
825
-
826
-		$cursor = $qb->select('*')
827
-			->from('share')
828
-			->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
829
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
830
-			->execute();
831
-
832
-		$data = $cursor->fetch();
833
-
834
-		if ($data === false) {
835
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
836
-		}
837
-
838
-		try {
839
-			$share = $this->createShareObject($data);
840
-		} catch (InvalidShare $e) {
841
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
842
-		}
843
-
844
-		return $share;
845
-	}
846
-
847
-	/**
848
-	 * get database row of a give share
849
-	 *
850
-	 * @param $id
851
-	 * @return array
852
-	 * @throws ShareNotFound
853
-	 */
854
-	private function getRawShare($id) {
855
-
856
-		// Now fetch the inserted share and create a complete share object
857
-		$qb = $this->dbConnection->getQueryBuilder();
858
-		$qb->select('*')
859
-			->from('share')
860
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
861
-
862
-		$cursor = $qb->execute();
863
-		$data = $cursor->fetch();
864
-		$cursor->closeCursor();
865
-
866
-		if ($data === false) {
867
-			throw new ShareNotFound;
868
-		}
869
-
870
-		return $data;
871
-	}
872
-
873
-	/**
874
-	 * Create a share object from an database row
875
-	 *
876
-	 * @param array $data
877
-	 * @return IShare
878
-	 * @throws InvalidShare
879
-	 * @throws ShareNotFound
880
-	 */
881
-	private function createShareObject($data) {
882
-
883
-		$share = new Share($this->rootFolder, $this->userManager);
884
-		$share->setId((int)$data['id'])
885
-			->setShareType((int)$data['share_type'])
886
-			->setPermissions((int)$data['permissions'])
887
-			->setTarget($data['file_target'])
888
-			->setMailSend((bool)$data['mail_send'])
889
-			->setToken($data['token']);
890
-
891
-		$shareTime = new \DateTime();
892
-		$shareTime->setTimestamp((int)$data['stime']);
893
-		$share->setShareTime($shareTime);
894
-		$share->setSharedWith($data['share_with']);
895
-
896
-		if ($data['uid_initiator'] !== null) {
897
-			$share->setShareOwner($data['uid_owner']);
898
-			$share->setSharedBy($data['uid_initiator']);
899
-		} else {
900
-			//OLD SHARE
901
-			$share->setSharedBy($data['uid_owner']);
902
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
903
-
904
-			$owner = $path->getOwner();
905
-			$share->setShareOwner($owner->getUID());
906
-		}
907
-
908
-		$share->setNodeId((int)$data['file_source']);
909
-		$share->setNodeType($data['item_type']);
910
-
911
-		$share->setProviderId($this->identifier());
912
-
913
-		return $share;
914
-	}
915
-
916
-	/**
917
-	 * Get the node with file $id for $user
918
-	 *
919
-	 * @param string $userId
920
-	 * @param int $id
921
-	 * @return \OCP\Files\File|\OCP\Files\Folder
922
-	 * @throws InvalidShare
923
-	 */
924
-	private function getNode($userId, $id) {
925
-		try {
926
-			$userFolder = $this->rootFolder->getUserFolder($userId);
927
-		} catch (NotFoundException $e) {
928
-			throw new InvalidShare();
929
-		}
930
-
931
-		$nodes = $userFolder->getById($id);
932
-
933
-		if (empty($nodes)) {
934
-			throw new InvalidShare();
935
-		}
936
-
937
-		return $nodes[0];
938
-	}
939
-
940
-	/**
941
-	 * A user is deleted from the system
942
-	 * So clean up the relevant shares.
943
-	 *
944
-	 * @param string $uid
945
-	 * @param int $shareType
946
-	 */
947
-	public function userDeleted($uid, $shareType) {
948
-		//TODO: probabaly a good idea to send unshare info to remote servers
949
-
950
-		$qb = $this->dbConnection->getQueryBuilder();
951
-
952
-		$qb->delete('share')
953
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
954
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
955
-			->execute();
956
-	}
957
-
958
-	/**
959
-	 * This provider does not handle groups
960
-	 *
961
-	 * @param string $gid
962
-	 */
963
-	public function groupDeleted($gid) {
964
-		// We don't handle groups here
965
-	}
966
-
967
-	/**
968
-	 * This provider does not handle groups
969
-	 *
970
-	 * @param string $uid
971
-	 * @param string $gid
972
-	 */
973
-	public function userDeletedFromGroup($uid, $gid) {
974
-		// We don't handle groups here
975
-	}
976
-
977
-	/**
978
-	 * check if users from other Nextcloud instances are allowed to mount public links share by this instance
979
-	 *
980
-	 * @return bool
981
-	 */
982
-	public function isOutgoingServer2serverShareEnabled() {
983
-		if ($this->gsConfig->onlyInternalFederation()) {
984
-			return false;
985
-		}
986
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
987
-		return ($result === 'yes');
988
-	}
989
-
990
-	/**
991
-	 * check if users are allowed to mount public links from other Nextclouds
992
-	 *
993
-	 * @return bool
994
-	 */
995
-	public function isIncomingServer2serverShareEnabled() {
996
-		if ($this->gsConfig->onlyInternalFederation()) {
997
-			return false;
998
-		}
999
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
1000
-		return ($result === 'yes');
1001
-	}
1002
-
1003
-
1004
-	/**
1005
-	 * check if users from other Nextcloud instances are allowed to send federated group shares
1006
-	 *
1007
-	 * @return bool
1008
-	 */
1009
-	public function isOutgoingServer2serverGroupShareEnabled() {
1010
-		if ($this->gsConfig->onlyInternalFederation()) {
1011
-			return false;
1012
-		}
1013
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1014
-		return ($result === 'yes');
1015
-	}
1016
-
1017
-	/**
1018
-	 * check if users are allowed to receive federated group shares
1019
-	 *
1020
-	 * @return bool
1021
-	 */
1022
-	public function isIncomingServer2serverGroupShareEnabled() {
1023
-		if ($this->gsConfig->onlyInternalFederation()) {
1024
-			return false;
1025
-		}
1026
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1027
-		return ($result === 'yes');
1028
-	}
1029
-
1030
-	/**
1031
-	 * check if federated group sharing is supported, therefore the OCM API need to be enabled
1032
-	 *
1033
-	 * @return bool
1034
-	 */
1035
-	public function isFederatedGroupSharingSupported() {
1036
-		return $this->cloudFederationProviderManager->isReady();
1037
-	}
1038
-
1039
-	/**
1040
-	 * Check if querying sharees on the lookup server is enabled
1041
-	 *
1042
-	 * @return bool
1043
-	 */
1044
-	public function isLookupServerQueriesEnabled() {
1045
-		// in a global scale setup we should always query the lookup server
1046
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1047
-			return true;
1048
-		}
1049
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes');
1050
-		return ($result === 'yes');
1051
-	}
1052
-
1053
-
1054
-	/**
1055
-	 * Check if it is allowed to publish user specific data to the lookup server
1056
-	 *
1057
-	 * @return bool
1058
-	 */
1059
-	public function isLookupServerUploadEnabled() {
1060
-		// in a global scale setup the admin is responsible to keep the lookup server up-to-date
1061
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1062
-			return false;
1063
-		}
1064
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1065
-		return ($result === 'yes');
1066
-	}
1067
-
1068
-	/**
1069
-	 * @inheritdoc
1070
-	 */
1071
-	public function getAccessList($nodes, $currentAccess) {
1072
-		$ids = [];
1073
-		foreach ($nodes as $node) {
1074
-			$ids[] = $node->getId();
1075
-		}
1076
-
1077
-		$qb = $this->dbConnection->getQueryBuilder();
1078
-		$qb->select('share_with', 'token', 'file_source')
1079
-			->from('share')
1080
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1081
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1082
-			->andWhere($qb->expr()->orX(
1083
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1084
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1085
-			));
1086
-		$cursor = $qb->execute();
1087
-
1088
-		if ($currentAccess === false) {
1089
-			$remote = $cursor->fetch() !== false;
1090
-			$cursor->closeCursor();
1091
-
1092
-			return ['remote' => $remote];
1093
-		}
1094
-
1095
-		$remote = [];
1096
-		while ($row = $cursor->fetch()) {
1097
-			$remote[$row['share_with']] = [
1098
-				'node_id' => $row['file_source'],
1099
-				'token' => $row['token'],
1100
-			];
1101
-		}
1102
-		$cursor->closeCursor();
1103
-
1104
-		return ['remote' => $remote];
1105
-	}
1106
-
1107
-	public function getAllShares(): iterable {
1108
-		$qb = $this->dbConnection->getQueryBuilder();
1109
-
1110
-		$qb->select('*')
1111
-			->from('share')
1112
-			->where(
1113
-				$qb->expr()->orX(
1114
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
1115
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
1116
-				)
1117
-			);
1118
-
1119
-		$cursor = $qb->execute();
1120
-		while($data = $cursor->fetch()) {
1121
-			try {
1122
-				$share = $this->createShareObject($data);
1123
-			} catch (InvalidShare $e) {
1124
-				continue;
1125
-			} catch (ShareNotFound $e) {
1126
-				continue;
1127
-			}
1128
-
1129
-			yield $share;
1130
-		}
1131
-		$cursor->closeCursor();
1132
-	}
504
+        return $share;
505
+    }
506
+
507
+    /**
508
+     * Get all children of this share
509
+     *
510
+     * @param IShare $parent
511
+     * @return IShare[]
512
+     */
513
+    public function getChildren(IShare $parent) {
514
+        $children = [];
515
+
516
+        $qb = $this->dbConnection->getQueryBuilder();
517
+        $qb->select('*')
518
+            ->from('share')
519
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
520
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
521
+            ->orderBy('id');
522
+
523
+        $cursor = $qb->execute();
524
+        while($data = $cursor->fetch()) {
525
+            $children[] = $this->createShareObject($data);
526
+        }
527
+        $cursor->closeCursor();
528
+
529
+        return $children;
530
+    }
531
+
532
+    /**
533
+     * Delete a share (owner unShares the file)
534
+     *
535
+     * @param IShare $share
536
+     * @throws ShareNotFound
537
+     * @throws \OC\HintException
538
+     */
539
+    public function delete(IShare $share) {
540
+
541
+        list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
542
+
543
+        // if the local user is the owner we can send the unShare request directly...
544
+        if ($this->userManager->userExists($share->getShareOwner())) {
545
+            $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
546
+            $this->revokeShare($share, true);
547
+        } else { // ... if not we need to correct ID for the unShare request
548
+            $remoteId = $this->getRemoteId($share);
549
+            $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
550
+            $this->revokeShare($share, false);
551
+        }
552
+
553
+        // only remove the share when all messages are send to not lose information
554
+        // about the share to early
555
+        $this->removeShareFromTable($share);
556
+    }
557
+
558
+    /**
559
+     * in case of a re-share we need to send the other use (initiator or owner)
560
+     * a message that the file was unshared
561
+     *
562
+     * @param IShare $share
563
+     * @param bool $isOwner the user can either be the owner or the user who re-sahred it
564
+     * @throws ShareNotFound
565
+     * @throws \OC\HintException
566
+     */
567
+    protected function revokeShare($share, $isOwner) {
568
+        if ($this->userManager->userExists($share->getShareOwner() && $this->userManager->userExists($share->getSharedBy()))) {
569
+            // If both the owner and the initiator of the share are local users we don't have to notify anybody else
570
+            return;
571
+        }
572
+
573
+        // also send a unShare request to the initiator, if this is a different user than the owner
574
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
575
+            if ($isOwner) {
576
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
577
+            } else {
578
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
579
+            }
580
+            $remoteId = $this->getRemoteId($share);
581
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
582
+        }
583
+    }
584
+
585
+    /**
586
+     * remove share from table
587
+     *
588
+     * @param IShare $share
589
+     */
590
+    public function removeShareFromTable(IShare $share) {
591
+        $this->removeShareFromTableById($share->getId());
592
+    }
593
+
594
+    /**
595
+     * remove share from table
596
+     *
597
+     * @param string $shareId
598
+     */
599
+    private function removeShareFromTableById($shareId) {
600
+        $qb = $this->dbConnection->getQueryBuilder();
601
+        $qb->delete('share')
602
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
603
+            ->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
604
+        $qb->execute();
605
+
606
+        $qb->delete('federated_reshares')
607
+            ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
608
+        $qb->execute();
609
+    }
610
+
611
+    /**
612
+     * @inheritdoc
613
+     */
614
+    public function deleteFromSelf(IShare $share, $recipient) {
615
+        // nothing to do here. Technically deleteFromSelf in the context of federated
616
+        // shares is a umount of a external storage. This is handled here
617
+        // apps/files_sharing/lib/external/manager.php
618
+        // TODO move this code over to this app
619
+    }
620
+
621
+    public function restore(IShare $share, string $recipient): IShare {
622
+        throw new GenericShareException('not implemented');
623
+    }
624
+
625
+
626
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
627
+        $qb = $this->dbConnection->getQueryBuilder();
628
+        $qb->select('*')
629
+            ->from('share', 's')
630
+            ->andWhere($qb->expr()->orX(
631
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
632
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
633
+            ))
634
+            ->andWhere(
635
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
636
+            );
637
+
638
+        /**
639
+         * Reshares for this user are shares where they are the owner.
640
+         */
641
+        if ($reshares === false) {
642
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
643
+        } else {
644
+            $qb->andWhere(
645
+                $qb->expr()->orX(
646
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
647
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
648
+                )
649
+            );
650
+        }
651
+
652
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
653
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
654
+
655
+        $qb->orderBy('id');
656
+
657
+        $cursor = $qb->execute();
658
+        $shares = [];
659
+        while ($data = $cursor->fetch()) {
660
+            $shares[$data['fileid']][] = $this->createShareObject($data);
661
+        }
662
+        $cursor->closeCursor();
663
+
664
+        return $shares;
665
+    }
666
+
667
+    /**
668
+     * @inheritdoc
669
+     */
670
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
671
+        $qb = $this->dbConnection->getQueryBuilder();
672
+        $qb->select('*')
673
+            ->from('share');
674
+
675
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
676
+
677
+        /**
678
+         * Reshares for this user are shares where they are the owner.
679
+         */
680
+        if ($reshares === false) {
681
+            //Special case for old shares created via the web UI
682
+            $or1 = $qb->expr()->andX(
683
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
684
+                $qb->expr()->isNull('uid_initiator')
685
+            );
686
+
687
+            $qb->andWhere(
688
+                $qb->expr()->orX(
689
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
690
+                    $or1
691
+                )
692
+            );
693
+        } else {
694
+            $qb->andWhere(
695
+                $qb->expr()->orX(
696
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
697
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
698
+                )
699
+            );
700
+        }
701
+
702
+        if ($node !== null) {
703
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
704
+        }
705
+
706
+        if ($limit !== -1) {
707
+            $qb->setMaxResults($limit);
708
+        }
709
+
710
+        $qb->setFirstResult($offset);
711
+        $qb->orderBy('id');
712
+
713
+        $cursor = $qb->execute();
714
+        $shares = [];
715
+        while($data = $cursor->fetch()) {
716
+            $shares[] = $this->createShareObject($data);
717
+        }
718
+        $cursor->closeCursor();
719
+
720
+        return $shares;
721
+    }
722
+
723
+    /**
724
+     * @inheritdoc
725
+     */
726
+    public function getShareById($id, $recipientId = null) {
727
+        $qb = $this->dbConnection->getQueryBuilder();
728
+
729
+        $qb->select('*')
730
+            ->from('share')
731
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
732
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
733
+
734
+        $cursor = $qb->execute();
735
+        $data = $cursor->fetch();
736
+        $cursor->closeCursor();
737
+
738
+        if ($data === false) {
739
+            throw new ShareNotFound('Can not find share with ID: ' . $id);
740
+        }
741
+
742
+        try {
743
+            $share = $this->createShareObject($data);
744
+        } catch (InvalidShare $e) {
745
+            throw new ShareNotFound();
746
+        }
747
+
748
+        return $share;
749
+    }
750
+
751
+    /**
752
+     * Get shares for a given path
753
+     *
754
+     * @param \OCP\Files\Node $path
755
+     * @return IShare[]
756
+     */
757
+    public function getSharesByPath(Node $path) {
758
+        $qb = $this->dbConnection->getQueryBuilder();
759
+
760
+        // get federated user shares
761
+        $cursor = $qb->select('*')
762
+            ->from('share')
763
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
764
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
765
+            ->execute();
766
+
767
+        $shares = [];
768
+        while($data = $cursor->fetch()) {
769
+            $shares[] = $this->createShareObject($data);
770
+        }
771
+        $cursor->closeCursor();
772
+
773
+        return $shares;
774
+    }
775
+
776
+    /**
777
+     * @inheritdoc
778
+     */
779
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
780
+        /** @var IShare[] $shares */
781
+        $shares = [];
782
+
783
+        //Get shares directly with this user
784
+        $qb = $this->dbConnection->getQueryBuilder();
785
+        $qb->select('*')
786
+            ->from('share');
787
+
788
+        // Order by id
789
+        $qb->orderBy('id');
790
+
791
+        // Set limit and offset
792
+        if ($limit !== -1) {
793
+            $qb->setMaxResults($limit);
794
+        }
795
+        $qb->setFirstResult($offset);
796
+
797
+        $qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
798
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
799
+
800
+        // Filter by node if provided
801
+        if ($node !== null) {
802
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
803
+        }
804
+
805
+        $cursor = $qb->execute();
806
+
807
+        while($data = $cursor->fetch()) {
808
+            $shares[] = $this->createShareObject($data);
809
+        }
810
+        $cursor->closeCursor();
811
+
812
+
813
+        return $shares;
814
+    }
815
+
816
+    /**
817
+     * Get a share by token
818
+     *
819
+     * @param string $token
820
+     * @return IShare
821
+     * @throws ShareNotFound
822
+     */
823
+    public function getShareByToken($token) {
824
+        $qb = $this->dbConnection->getQueryBuilder();
825
+
826
+        $cursor = $qb->select('*')
827
+            ->from('share')
828
+            ->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
829
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
830
+            ->execute();
831
+
832
+        $data = $cursor->fetch();
833
+
834
+        if ($data === false) {
835
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
836
+        }
837
+
838
+        try {
839
+            $share = $this->createShareObject($data);
840
+        } catch (InvalidShare $e) {
841
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
842
+        }
843
+
844
+        return $share;
845
+    }
846
+
847
+    /**
848
+     * get database row of a give share
849
+     *
850
+     * @param $id
851
+     * @return array
852
+     * @throws ShareNotFound
853
+     */
854
+    private function getRawShare($id) {
855
+
856
+        // Now fetch the inserted share and create a complete share object
857
+        $qb = $this->dbConnection->getQueryBuilder();
858
+        $qb->select('*')
859
+            ->from('share')
860
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
861
+
862
+        $cursor = $qb->execute();
863
+        $data = $cursor->fetch();
864
+        $cursor->closeCursor();
865
+
866
+        if ($data === false) {
867
+            throw new ShareNotFound;
868
+        }
869
+
870
+        return $data;
871
+    }
872
+
873
+    /**
874
+     * Create a share object from an database row
875
+     *
876
+     * @param array $data
877
+     * @return IShare
878
+     * @throws InvalidShare
879
+     * @throws ShareNotFound
880
+     */
881
+    private function createShareObject($data) {
882
+
883
+        $share = new Share($this->rootFolder, $this->userManager);
884
+        $share->setId((int)$data['id'])
885
+            ->setShareType((int)$data['share_type'])
886
+            ->setPermissions((int)$data['permissions'])
887
+            ->setTarget($data['file_target'])
888
+            ->setMailSend((bool)$data['mail_send'])
889
+            ->setToken($data['token']);
890
+
891
+        $shareTime = new \DateTime();
892
+        $shareTime->setTimestamp((int)$data['stime']);
893
+        $share->setShareTime($shareTime);
894
+        $share->setSharedWith($data['share_with']);
895
+
896
+        if ($data['uid_initiator'] !== null) {
897
+            $share->setShareOwner($data['uid_owner']);
898
+            $share->setSharedBy($data['uid_initiator']);
899
+        } else {
900
+            //OLD SHARE
901
+            $share->setSharedBy($data['uid_owner']);
902
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
903
+
904
+            $owner = $path->getOwner();
905
+            $share->setShareOwner($owner->getUID());
906
+        }
907
+
908
+        $share->setNodeId((int)$data['file_source']);
909
+        $share->setNodeType($data['item_type']);
910
+
911
+        $share->setProviderId($this->identifier());
912
+
913
+        return $share;
914
+    }
915
+
916
+    /**
917
+     * Get the node with file $id for $user
918
+     *
919
+     * @param string $userId
920
+     * @param int $id
921
+     * @return \OCP\Files\File|\OCP\Files\Folder
922
+     * @throws InvalidShare
923
+     */
924
+    private function getNode($userId, $id) {
925
+        try {
926
+            $userFolder = $this->rootFolder->getUserFolder($userId);
927
+        } catch (NotFoundException $e) {
928
+            throw new InvalidShare();
929
+        }
930
+
931
+        $nodes = $userFolder->getById($id);
932
+
933
+        if (empty($nodes)) {
934
+            throw new InvalidShare();
935
+        }
936
+
937
+        return $nodes[0];
938
+    }
939
+
940
+    /**
941
+     * A user is deleted from the system
942
+     * So clean up the relevant shares.
943
+     *
944
+     * @param string $uid
945
+     * @param int $shareType
946
+     */
947
+    public function userDeleted($uid, $shareType) {
948
+        //TODO: probabaly a good idea to send unshare info to remote servers
949
+
950
+        $qb = $this->dbConnection->getQueryBuilder();
951
+
952
+        $qb->delete('share')
953
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
954
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
955
+            ->execute();
956
+    }
957
+
958
+    /**
959
+     * This provider does not handle groups
960
+     *
961
+     * @param string $gid
962
+     */
963
+    public function groupDeleted($gid) {
964
+        // We don't handle groups here
965
+    }
966
+
967
+    /**
968
+     * This provider does not handle groups
969
+     *
970
+     * @param string $uid
971
+     * @param string $gid
972
+     */
973
+    public function userDeletedFromGroup($uid, $gid) {
974
+        // We don't handle groups here
975
+    }
976
+
977
+    /**
978
+     * check if users from other Nextcloud instances are allowed to mount public links share by this instance
979
+     *
980
+     * @return bool
981
+     */
982
+    public function isOutgoingServer2serverShareEnabled() {
983
+        if ($this->gsConfig->onlyInternalFederation()) {
984
+            return false;
985
+        }
986
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
987
+        return ($result === 'yes');
988
+    }
989
+
990
+    /**
991
+     * check if users are allowed to mount public links from other Nextclouds
992
+     *
993
+     * @return bool
994
+     */
995
+    public function isIncomingServer2serverShareEnabled() {
996
+        if ($this->gsConfig->onlyInternalFederation()) {
997
+            return false;
998
+        }
999
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
1000
+        return ($result === 'yes');
1001
+    }
1002
+
1003
+
1004
+    /**
1005
+     * check if users from other Nextcloud instances are allowed to send federated group shares
1006
+     *
1007
+     * @return bool
1008
+     */
1009
+    public function isOutgoingServer2serverGroupShareEnabled() {
1010
+        if ($this->gsConfig->onlyInternalFederation()) {
1011
+            return false;
1012
+        }
1013
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1014
+        return ($result === 'yes');
1015
+    }
1016
+
1017
+    /**
1018
+     * check if users are allowed to receive federated group shares
1019
+     *
1020
+     * @return bool
1021
+     */
1022
+    public function isIncomingServer2serverGroupShareEnabled() {
1023
+        if ($this->gsConfig->onlyInternalFederation()) {
1024
+            return false;
1025
+        }
1026
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1027
+        return ($result === 'yes');
1028
+    }
1029
+
1030
+    /**
1031
+     * check if federated group sharing is supported, therefore the OCM API need to be enabled
1032
+     *
1033
+     * @return bool
1034
+     */
1035
+    public function isFederatedGroupSharingSupported() {
1036
+        return $this->cloudFederationProviderManager->isReady();
1037
+    }
1038
+
1039
+    /**
1040
+     * Check if querying sharees on the lookup server is enabled
1041
+     *
1042
+     * @return bool
1043
+     */
1044
+    public function isLookupServerQueriesEnabled() {
1045
+        // in a global scale setup we should always query the lookup server
1046
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1047
+            return true;
1048
+        }
1049
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes');
1050
+        return ($result === 'yes');
1051
+    }
1052
+
1053
+
1054
+    /**
1055
+     * Check if it is allowed to publish user specific data to the lookup server
1056
+     *
1057
+     * @return bool
1058
+     */
1059
+    public function isLookupServerUploadEnabled() {
1060
+        // in a global scale setup the admin is responsible to keep the lookup server up-to-date
1061
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1062
+            return false;
1063
+        }
1064
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1065
+        return ($result === 'yes');
1066
+    }
1067
+
1068
+    /**
1069
+     * @inheritdoc
1070
+     */
1071
+    public function getAccessList($nodes, $currentAccess) {
1072
+        $ids = [];
1073
+        foreach ($nodes as $node) {
1074
+            $ids[] = $node->getId();
1075
+        }
1076
+
1077
+        $qb = $this->dbConnection->getQueryBuilder();
1078
+        $qb->select('share_with', 'token', 'file_source')
1079
+            ->from('share')
1080
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1081
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1082
+            ->andWhere($qb->expr()->orX(
1083
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1084
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1085
+            ));
1086
+        $cursor = $qb->execute();
1087
+
1088
+        if ($currentAccess === false) {
1089
+            $remote = $cursor->fetch() !== false;
1090
+            $cursor->closeCursor();
1091
+
1092
+            return ['remote' => $remote];
1093
+        }
1094
+
1095
+        $remote = [];
1096
+        while ($row = $cursor->fetch()) {
1097
+            $remote[$row['share_with']] = [
1098
+                'node_id' => $row['file_source'],
1099
+                'token' => $row['token'],
1100
+            ];
1101
+        }
1102
+        $cursor->closeCursor();
1103
+
1104
+        return ['remote' => $remote];
1105
+    }
1106
+
1107
+    public function getAllShares(): iterable {
1108
+        $qb = $this->dbConnection->getQueryBuilder();
1109
+
1110
+        $qb->select('*')
1111
+            ->from('share')
1112
+            ->where(
1113
+                $qb->expr()->orX(
1114
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
1115
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
1116
+                )
1117
+            );
1118
+
1119
+        $cursor = $qb->execute();
1120
+        while($data = $cursor->fetch()) {
1121
+            try {
1122
+                $share = $this->createShareObject($data);
1123
+            } catch (InvalidShare $e) {
1124
+                continue;
1125
+            } catch (ShareNotFound $e) {
1126
+                continue;
1127
+            }
1128
+
1129
+            yield $share;
1130
+        }
1131
+        $cursor->closeCursor();
1132
+    }
1133 1133
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/Notifications.php 1 patch
Indentation   +409 added lines, -409 removed lines patch added patch discarded remove patch
@@ -32,413 +32,413 @@
 block discarded – undo
32 32
 use OCP\OCS\IDiscoveryService;
33 33
 
34 34
 class Notifications {
35
-	const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
36
-
37
-	/** @var AddressHandler */
38
-	private $addressHandler;
39
-
40
-	/** @var IClientService */
41
-	private $httpClientService;
42
-
43
-	/** @var IDiscoveryService */
44
-	private $discoveryService;
45
-
46
-	/** @var IJobList  */
47
-	private $jobList;
48
-
49
-	/** @var ICloudFederationProviderManager */
50
-	private $federationProviderManager;
51
-
52
-	/** @var ICloudFederationFactory */
53
-	private $cloudFederationFactory;
54
-
55
-	/**
56
-	 * @param AddressHandler $addressHandler
57
-	 * @param IClientService $httpClientService
58
-	 * @param IDiscoveryService $discoveryService
59
-	 * @param IJobList $jobList
60
-	 * @param ICloudFederationProviderManager $federationProviderManager
61
-	 * @param ICloudFederationFactory $cloudFederationFactory
62
-	 */
63
-	public function __construct(
64
-		AddressHandler $addressHandler,
65
-		IClientService $httpClientService,
66
-		IDiscoveryService $discoveryService,
67
-		IJobList $jobList,
68
-		ICloudFederationProviderManager $federationProviderManager,
69
-		ICloudFederationFactory $cloudFederationFactory
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
-	}
78
-
79
-	/**
80
-	 * send server-to-server share to remote server
81
-	 *
82
-	 * @param string $token
83
-	 * @param string $shareWith
84
-	 * @param string $name
85
-	 * @param int $remote_id
86
-	 * @param string $owner
87
-	 * @param string $ownerFederatedId
88
-	 * @param string $sharedBy
89
-	 * @param string $sharedByFederatedId
90
-	 * @param int $shareType (can be a remote user or group share)
91
-	 * @return bool
92
-	 * @throws \OC\HintException
93
-	 * @throws \OC\ServerNotAvailableException
94
-	 */
95
-	public function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId, $shareType) {
96
-
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' => $remote_id,
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
-				\OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $remote]);
123
-				return true;
124
-			}
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 int $id remote Id
136
-	 * @param int $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 bool
142
-	 * @throws \OC\HintException
143
-	 * @throws \OC\ServerNotAvailableException
144
-	 */
145
-	public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission, $filename) {
146
-
147
-		$fields = [
148
-			'shareWith' => $shareWith,
149
-			'token' => $token,
150
-			'permission' => $permission,
151
-			'remoteId' => $shareId,
152
-		];
153
-
154
-		$ocmFields = $fields;
155
-		$ocmFields['remoteId'] = $id;
156
-		$ocmFields['localId'] = $shareId;
157
-		$ocmFields['name'] = $filename;
158
-
159
-		$ocmResult = $this->tryOCMEndPoint($remote, $ocmFields, 'reshare');
160
-		if (is_array($ocmResult) && isset($ocmResult['token']) && isset($ocmResult['providerId'])) {
161
-			return [$ocmResult['token'], $ocmResult['providerId']];
162
-		}
163
-
164
-		$result = $this->tryLegacyEndPoint(rtrim($remote, '/'), '/' . $id . '/reshare', $fields);
165
-		$status = json_decode($result['result'], true);
166
-
167
-		$httpRequestSuccessful = $result['success'];
168
-		$ocsCallSuccessful = $status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200;
169
-		$validToken = isset($status['ocs']['data']['token']) && is_string($status['ocs']['data']['token']);
170
-		$validRemoteId = isset($status['ocs']['data']['remoteId']);
171
-
172
-		if ($httpRequestSuccessful && $ocsCallSuccessful && $validToken && $validRemoteId) {
173
-			return [
174
-				$status['ocs']['data']['token'],
175
-				(int)$status['ocs']['data']['remoteId']
176
-			];
177
-		}
178
-
179
-		return false;
180
-	}
181
-
182
-	/**
183
-	 * send server-to-server unshare to remote server
184
-	 *
185
-	 * @param string $remote url
186
-	 * @param int $id share id
187
-	 * @param string $token
188
-	 * @return bool
189
-	 */
190
-	public function sendRemoteUnShare($remote, $id, $token) {
191
-		$this->sendUpdateToRemote($remote, $id, $token, 'unshare');
192
-	}
193
-
194
-	/**
195
-	 * send server-to-server unshare to remote server
196
-	 *
197
-	 * @param string $remote url
198
-	 * @param int $id share id
199
-	 * @param string $token
200
-	 * @return bool
201
-	 */
202
-	public function sendRevokeShare($remote, $id, $token) {
203
-		$this->sendUpdateToRemote($remote, $id, $token, 'reshare_undo');
204
-	}
205
-
206
-	/**
207
-	 * send notification to remote server if the permissions was changed
208
-	 *
209
-	 * @param string $remote
210
-	 * @param int $remoteId
211
-	 * @param string $token
212
-	 * @param int $permissions
213
-	 * @return bool
214
-	 */
215
-	public function sendPermissionChange($remote, $remoteId, $token, $permissions) {
216
-		$this->sendUpdateToRemote($remote, $remoteId, $token, 'permissions', ['permissions' => $permissions]);
217
-	}
218
-
219
-	/**
220
-	 * forward accept reShare to remote server
221
-	 *
222
-	 * @param string $remote
223
-	 * @param int $remoteId
224
-	 * @param string $token
225
-	 */
226
-	public function sendAcceptShare($remote, $remoteId, $token) {
227
-		$this->sendUpdateToRemote($remote, $remoteId, $token, 'accept');
228
-	}
229
-
230
-	/**
231
-	 * forward decline reShare to remote server
232
-	 *
233
-	 * @param string $remote
234
-	 * @param int $remoteId
235
-	 * @param string $token
236
-	 */
237
-	public function sendDeclineShare($remote, $remoteId, $token) {
238
-		$this->sendUpdateToRemote($remote, $remoteId, $token, 'decline');
239
-	}
240
-
241
-	/**
242
-	 * inform remote server whether server-to-server share was accepted/declined
243
-	 *
244
-	 * @param string $remote
245
-	 * @param string $token
246
-	 * @param int $remoteId Share id on the remote host
247
-	 * @param string $action possible actions: accept, decline, unshare, revoke, permissions
248
-	 * @param array $data
249
-	 * @param int $try
250
-	 * @return boolean
251
-	 */
252
-	public function sendUpdateToRemote($remote, $remoteId, $token, $action, $data = [], $try = 0) {
253
-
254
-		$fields = [
255
-			'token' => $token,
256
-			'remoteId' => $remoteId
257
-			];
258
-		foreach ($data as $key => $value) {
259
-			$fields[$key] = $value;
260
-		}
261
-
262
-		$result = $this->tryHttpPostToShareEndpoint(rtrim($remote, '/'), '/' . $remoteId . '/' . $action, $fields, $action);
263
-		$status = json_decode($result['result'], true);
264
-
265
-		if ($result['success'] &&
266
-			($status['ocs']['meta']['statuscode'] === 100 ||
267
-				$status['ocs']['meta']['statuscode'] === 200
268
-			)
269
-		) {
270
-			return true;
271
-		} elseif ($try === 0) {
272
-			// only add new job on first try
273
-			$this->jobList->add('OCA\FederatedFileSharing\BackgroundJob\RetryJob',
274
-				[
275
-					'remote' => $remote,
276
-					'remoteId' => $remoteId,
277
-					'token' => $token,
278
-					'action' => $action,
279
-					'data' => json_encode($data),
280
-					'try' => $try,
281
-					'lastRun' => $this->getTimestamp()
282
-				]
283
-			);
284
-		}
285
-
286
-		return false;
287
-	}
288
-
289
-
290
-	/**
291
-	 * return current timestamp
292
-	 *
293
-	 * @return int
294
-	 */
295
-	protected function getTimestamp() {
296
-		return time();
297
-	}
298
-
299
-	/**
300
-	 * try http post with the given protocol, if no protocol is given we pick
301
-	 * the secure one (https)
302
-	 *
303
-	 * @param string $remoteDomain
304
-	 * @param string $urlSuffix
305
-	 * @param array $fields post parameters
306
-	 * @param string $action define the action (possible values: share, reshare, accept, decline, unshare, revoke, permissions)
307
-	 * @return array
308
-	 * @throws \Exception
309
-	 */
310
-	protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields, $action="share") {
311
-
312
-		if ($this->addressHandler->urlContainProtocol($remoteDomain) === false) {
313
-			$remoteDomain = 'https://' . $remoteDomain;
314
-		}
315
-
316
-		$result = [
317
-			'success' => false,
318
-			'result' => '',
319
-		];
320
-
321
-		// if possible we use the new OCM API
322
-		$ocmResult = $this->tryOCMEndPoint($remoteDomain, $fields, $action);
323
-		if (is_array($ocmResult)) {
324
-			$result['success'] = true;
325
-			$result['result'] = json_encode([
326
-				'ocs' => ['meta' => ['statuscode' => 200]]]);
327
-			return $result;
328
-		}
329
-
330
-		return $this->tryLegacyEndPoint($remoteDomain, $urlSuffix, $fields);
331
-	}
332
-
333
-	/**
334
-	 * try old federated sharing API if the OCM api doesn't work
335
-	 *
336
-	 * @param $remoteDomain
337
-	 * @param $urlSuffix
338
-	 * @param array $fields
339
-	 * @return mixed
340
-	 * @throws \Exception
341
-	 */
342
-	protected function tryLegacyEndPoint($remoteDomain, $urlSuffix, array $fields) {
343
-
344
-		$result = [
345
-			'success' => false,
346
-			'result' => '',
347
-		];
348
-
349
-		// Fall back to old API
350
-		$client = $this->httpClientService->newClient();
351
-		$federationEndpoints = $this->discoveryService->discover($remoteDomain, 'FEDERATED_SHARING');
352
-		$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
353
-		try {
354
-			$response = $client->post($remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, [
355
-				'body' => $fields,
356
-				'timeout' => 10,
357
-				'connect_timeout' => 10,
358
-			]);
359
-			$result['result'] = $response->getBody();
360
-			$result['success'] = true;
361
-		} catch (\Exception $e) {
362
-			// if flat re-sharing is not supported by the remote server
363
-			// we re-throw the exception and fall back to the old behaviour.
364
-			// (flat re-shares has been introduced in Nextcloud 9.1)
365
-			if ($e->getCode() === Http::STATUS_INTERNAL_SERVER_ERROR) {
366
-				throw $e;
367
-			}
368
-		}
369
-
370
-		return $result;
371
-
372
-	}
373
-
374
-	/**
375
-	 * send action regarding federated sharing to the remote server using the OCM API
376
-	 *
377
-	 * @param $remoteDomain
378
-	 * @param $fields
379
-	 * @param $action
380
-	 *
381
-	 * @return bool
382
-	 */
383
-	protected function tryOCMEndPoint($remoteDomain, $fields, $action) {
384
-		switch ($action) {
385
-			case 'share':
386
-				$share = $this->cloudFederationFactory->getCloudFederationShare(
387
-					$fields['shareWith'] . '@' . $remoteDomain,
388
-					$fields['name'],
389
-					'',
390
-					$fields['remoteId'],
391
-					$fields['ownerFederatedId'],
392
-					$fields['owner'],
393
-					$fields['sharedByFederatedId'],
394
-					$fields['sharedBy'],
395
-					$fields['token'],
396
-					$fields['shareType'],
397
-					'file'
398
-				);
399
-				return $this->federationProviderManager->sendShare($share);
400
-			case 'reshare':
401
-				// ask owner to reshare a file
402
-				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
403
-				$notification->setMessage('REQUEST_RESHARE',
404
-					'file',
405
-					$fields['remoteId'],
406
-					[
407
-						'sharedSecret' => $fields['token'],
408
-						'shareWith' => $fields['shareWith'],
409
-						'senderId' => $fields['localId'],
410
-						'shareType' => $fields['shareType'],
411
-						'message' => 'Ask owner to reshare the file'
412
-					]
413
-				);
414
-				return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
415
-			case 'unshare':
416
-				//owner unshares the file from the recipient again
417
-				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
418
-				$notification->setMessage('SHARE_UNSHARED',
419
-					'file',
420
-					$fields['remoteId'],
421
-					[
422
-						'sharedSecret' => $fields['token'],
423
-						'messgage' => 'file is no longer shared with you'
424
-					]
425
-				);
426
-				return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
427
-			case 'reshare_undo':
428
-				// if a reshare was unshared we send the information to the initiator/owner
429
-				$notification = $this->cloudFederationFactory->getCloudFederationNotification();
430
-				$notification->setMessage('RESHARE_UNDO',
431
-					'file',
432
-					$fields['remoteId'],
433
-					[
434
-						'sharedSecret' => $fields['token'],
435
-						'message' => 'reshare was revoked'
436
-					]
437
-				);
438
-				return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
439
-		}
440
-
441
-		return false;
442
-
443
-	}
35
+    const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
36
+
37
+    /** @var AddressHandler */
38
+    private $addressHandler;
39
+
40
+    /** @var IClientService */
41
+    private $httpClientService;
42
+
43
+    /** @var IDiscoveryService */
44
+    private $discoveryService;
45
+
46
+    /** @var IJobList  */
47
+    private $jobList;
48
+
49
+    /** @var ICloudFederationProviderManager */
50
+    private $federationProviderManager;
51
+
52
+    /** @var ICloudFederationFactory */
53
+    private $cloudFederationFactory;
54
+
55
+    /**
56
+     * @param AddressHandler $addressHandler
57
+     * @param IClientService $httpClientService
58
+     * @param IDiscoveryService $discoveryService
59
+     * @param IJobList $jobList
60
+     * @param ICloudFederationProviderManager $federationProviderManager
61
+     * @param ICloudFederationFactory $cloudFederationFactory
62
+     */
63
+    public function __construct(
64
+        AddressHandler $addressHandler,
65
+        IClientService $httpClientService,
66
+        IDiscoveryService $discoveryService,
67
+        IJobList $jobList,
68
+        ICloudFederationProviderManager $federationProviderManager,
69
+        ICloudFederationFactory $cloudFederationFactory
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
+    }
78
+
79
+    /**
80
+     * send server-to-server share to remote server
81
+     *
82
+     * @param string $token
83
+     * @param string $shareWith
84
+     * @param string $name
85
+     * @param int $remote_id
86
+     * @param string $owner
87
+     * @param string $ownerFederatedId
88
+     * @param string $sharedBy
89
+     * @param string $sharedByFederatedId
90
+     * @param int $shareType (can be a remote user or group share)
91
+     * @return bool
92
+     * @throws \OC\HintException
93
+     * @throws \OC\ServerNotAvailableException
94
+     */
95
+    public function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId, $shareType) {
96
+
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' => $remote_id,
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
+                \OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $remote]);
123
+                return true;
124
+            }
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 int $id remote Id
136
+     * @param int $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 bool
142
+     * @throws \OC\HintException
143
+     * @throws \OC\ServerNotAvailableException
144
+     */
145
+    public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission, $filename) {
146
+
147
+        $fields = [
148
+            'shareWith' => $shareWith,
149
+            'token' => $token,
150
+            'permission' => $permission,
151
+            'remoteId' => $shareId,
152
+        ];
153
+
154
+        $ocmFields = $fields;
155
+        $ocmFields['remoteId'] = $id;
156
+        $ocmFields['localId'] = $shareId;
157
+        $ocmFields['name'] = $filename;
158
+
159
+        $ocmResult = $this->tryOCMEndPoint($remote, $ocmFields, 'reshare');
160
+        if (is_array($ocmResult) && isset($ocmResult['token']) && isset($ocmResult['providerId'])) {
161
+            return [$ocmResult['token'], $ocmResult['providerId']];
162
+        }
163
+
164
+        $result = $this->tryLegacyEndPoint(rtrim($remote, '/'), '/' . $id . '/reshare', $fields);
165
+        $status = json_decode($result['result'], true);
166
+
167
+        $httpRequestSuccessful = $result['success'];
168
+        $ocsCallSuccessful = $status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200;
169
+        $validToken = isset($status['ocs']['data']['token']) && is_string($status['ocs']['data']['token']);
170
+        $validRemoteId = isset($status['ocs']['data']['remoteId']);
171
+
172
+        if ($httpRequestSuccessful && $ocsCallSuccessful && $validToken && $validRemoteId) {
173
+            return [
174
+                $status['ocs']['data']['token'],
175
+                (int)$status['ocs']['data']['remoteId']
176
+            ];
177
+        }
178
+
179
+        return false;
180
+    }
181
+
182
+    /**
183
+     * send server-to-server unshare to remote server
184
+     *
185
+     * @param string $remote url
186
+     * @param int $id share id
187
+     * @param string $token
188
+     * @return bool
189
+     */
190
+    public function sendRemoteUnShare($remote, $id, $token) {
191
+        $this->sendUpdateToRemote($remote, $id, $token, 'unshare');
192
+    }
193
+
194
+    /**
195
+     * send server-to-server unshare to remote server
196
+     *
197
+     * @param string $remote url
198
+     * @param int $id share id
199
+     * @param string $token
200
+     * @return bool
201
+     */
202
+    public function sendRevokeShare($remote, $id, $token) {
203
+        $this->sendUpdateToRemote($remote, $id, $token, 'reshare_undo');
204
+    }
205
+
206
+    /**
207
+     * send notification to remote server if the permissions was changed
208
+     *
209
+     * @param string $remote
210
+     * @param int $remoteId
211
+     * @param string $token
212
+     * @param int $permissions
213
+     * @return bool
214
+     */
215
+    public function sendPermissionChange($remote, $remoteId, $token, $permissions) {
216
+        $this->sendUpdateToRemote($remote, $remoteId, $token, 'permissions', ['permissions' => $permissions]);
217
+    }
218
+
219
+    /**
220
+     * forward accept reShare to remote server
221
+     *
222
+     * @param string $remote
223
+     * @param int $remoteId
224
+     * @param string $token
225
+     */
226
+    public function sendAcceptShare($remote, $remoteId, $token) {
227
+        $this->sendUpdateToRemote($remote, $remoteId, $token, 'accept');
228
+    }
229
+
230
+    /**
231
+     * forward decline reShare to remote server
232
+     *
233
+     * @param string $remote
234
+     * @param int $remoteId
235
+     * @param string $token
236
+     */
237
+    public function sendDeclineShare($remote, $remoteId, $token) {
238
+        $this->sendUpdateToRemote($remote, $remoteId, $token, 'decline');
239
+    }
240
+
241
+    /**
242
+     * inform remote server whether server-to-server share was accepted/declined
243
+     *
244
+     * @param string $remote
245
+     * @param string $token
246
+     * @param int $remoteId Share id on the remote host
247
+     * @param string $action possible actions: accept, decline, unshare, revoke, permissions
248
+     * @param array $data
249
+     * @param int $try
250
+     * @return boolean
251
+     */
252
+    public function sendUpdateToRemote($remote, $remoteId, $token, $action, $data = [], $try = 0) {
253
+
254
+        $fields = [
255
+            'token' => $token,
256
+            'remoteId' => $remoteId
257
+            ];
258
+        foreach ($data as $key => $value) {
259
+            $fields[$key] = $value;
260
+        }
261
+
262
+        $result = $this->tryHttpPostToShareEndpoint(rtrim($remote, '/'), '/' . $remoteId . '/' . $action, $fields, $action);
263
+        $status = json_decode($result['result'], true);
264
+
265
+        if ($result['success'] &&
266
+            ($status['ocs']['meta']['statuscode'] === 100 ||
267
+                $status['ocs']['meta']['statuscode'] === 200
268
+            )
269
+        ) {
270
+            return true;
271
+        } elseif ($try === 0) {
272
+            // only add new job on first try
273
+            $this->jobList->add('OCA\FederatedFileSharing\BackgroundJob\RetryJob',
274
+                [
275
+                    'remote' => $remote,
276
+                    'remoteId' => $remoteId,
277
+                    'token' => $token,
278
+                    'action' => $action,
279
+                    'data' => json_encode($data),
280
+                    'try' => $try,
281
+                    'lastRun' => $this->getTimestamp()
282
+                ]
283
+            );
284
+        }
285
+
286
+        return false;
287
+    }
288
+
289
+
290
+    /**
291
+     * return current timestamp
292
+     *
293
+     * @return int
294
+     */
295
+    protected function getTimestamp() {
296
+        return time();
297
+    }
298
+
299
+    /**
300
+     * try http post with the given protocol, if no protocol is given we pick
301
+     * the secure one (https)
302
+     *
303
+     * @param string $remoteDomain
304
+     * @param string $urlSuffix
305
+     * @param array $fields post parameters
306
+     * @param string $action define the action (possible values: share, reshare, accept, decline, unshare, revoke, permissions)
307
+     * @return array
308
+     * @throws \Exception
309
+     */
310
+    protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields, $action="share") {
311
+
312
+        if ($this->addressHandler->urlContainProtocol($remoteDomain) === false) {
313
+            $remoteDomain = 'https://' . $remoteDomain;
314
+        }
315
+
316
+        $result = [
317
+            'success' => false,
318
+            'result' => '',
319
+        ];
320
+
321
+        // if possible we use the new OCM API
322
+        $ocmResult = $this->tryOCMEndPoint($remoteDomain, $fields, $action);
323
+        if (is_array($ocmResult)) {
324
+            $result['success'] = true;
325
+            $result['result'] = json_encode([
326
+                'ocs' => ['meta' => ['statuscode' => 200]]]);
327
+            return $result;
328
+        }
329
+
330
+        return $this->tryLegacyEndPoint($remoteDomain, $urlSuffix, $fields);
331
+    }
332
+
333
+    /**
334
+     * try old federated sharing API if the OCM api doesn't work
335
+     *
336
+     * @param $remoteDomain
337
+     * @param $urlSuffix
338
+     * @param array $fields
339
+     * @return mixed
340
+     * @throws \Exception
341
+     */
342
+    protected function tryLegacyEndPoint($remoteDomain, $urlSuffix, array $fields) {
343
+
344
+        $result = [
345
+            'success' => false,
346
+            'result' => '',
347
+        ];
348
+
349
+        // Fall back to old API
350
+        $client = $this->httpClientService->newClient();
351
+        $federationEndpoints = $this->discoveryService->discover($remoteDomain, 'FEDERATED_SHARING');
352
+        $endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
353
+        try {
354
+            $response = $client->post($remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, [
355
+                'body' => $fields,
356
+                'timeout' => 10,
357
+                'connect_timeout' => 10,
358
+            ]);
359
+            $result['result'] = $response->getBody();
360
+            $result['success'] = true;
361
+        } catch (\Exception $e) {
362
+            // if flat re-sharing is not supported by the remote server
363
+            // we re-throw the exception and fall back to the old behaviour.
364
+            // (flat re-shares has been introduced in Nextcloud 9.1)
365
+            if ($e->getCode() === Http::STATUS_INTERNAL_SERVER_ERROR) {
366
+                throw $e;
367
+            }
368
+        }
369
+
370
+        return $result;
371
+
372
+    }
373
+
374
+    /**
375
+     * send action regarding federated sharing to the remote server using the OCM API
376
+     *
377
+     * @param $remoteDomain
378
+     * @param $fields
379
+     * @param $action
380
+     *
381
+     * @return bool
382
+     */
383
+    protected function tryOCMEndPoint($remoteDomain, $fields, $action) {
384
+        switch ($action) {
385
+            case 'share':
386
+                $share = $this->cloudFederationFactory->getCloudFederationShare(
387
+                    $fields['shareWith'] . '@' . $remoteDomain,
388
+                    $fields['name'],
389
+                    '',
390
+                    $fields['remoteId'],
391
+                    $fields['ownerFederatedId'],
392
+                    $fields['owner'],
393
+                    $fields['sharedByFederatedId'],
394
+                    $fields['sharedBy'],
395
+                    $fields['token'],
396
+                    $fields['shareType'],
397
+                    'file'
398
+                );
399
+                return $this->federationProviderManager->sendShare($share);
400
+            case 'reshare':
401
+                // ask owner to reshare a file
402
+                $notification = $this->cloudFederationFactory->getCloudFederationNotification();
403
+                $notification->setMessage('REQUEST_RESHARE',
404
+                    'file',
405
+                    $fields['remoteId'],
406
+                    [
407
+                        'sharedSecret' => $fields['token'],
408
+                        'shareWith' => $fields['shareWith'],
409
+                        'senderId' => $fields['localId'],
410
+                        'shareType' => $fields['shareType'],
411
+                        'message' => 'Ask owner to reshare the file'
412
+                    ]
413
+                );
414
+                return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
415
+            case 'unshare':
416
+                //owner unshares the file from the recipient again
417
+                $notification = $this->cloudFederationFactory->getCloudFederationNotification();
418
+                $notification->setMessage('SHARE_UNSHARED',
419
+                    'file',
420
+                    $fields['remoteId'],
421
+                    [
422
+                        'sharedSecret' => $fields['token'],
423
+                        'messgage' => 'file is no longer shared with you'
424
+                    ]
425
+                );
426
+                return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
427
+            case 'reshare_undo':
428
+                // if a reshare was unshared we send the information to the initiator/owner
429
+                $notification = $this->cloudFederationFactory->getCloudFederationNotification();
430
+                $notification->setMessage('RESHARE_UNDO',
431
+                    'file',
432
+                    $fields['remoteId'],
433
+                    [
434
+                        'sharedSecret' => $fields['token'],
435
+                        'message' => 'reshare was revoked'
436
+                    ]
437
+                );
438
+                return $this->federationProviderManager->sendNotification($remoteDomain, $notification);
439
+        }
440
+
441
+        return false;
442
+
443
+    }
444 444
 }
Please login to merge, or discard this patch.
apps/accessibility/lib/AccessibilityProvider.php 1 patch
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -32,62 +32,62 @@
 block discarded – undo
32 32
 
33 33
 class AccessibilityProvider {
34 34
 
35
-	/** @var string */
36
-	protected $appName;
35
+    /** @var string */
36
+    protected $appName;
37 37
 
38
-	/** @var IURLGenerator */
39
-	private $urlGenerator;
38
+    /** @var IURLGenerator */
39
+    private $urlGenerator;
40 40
 
41
-	/** @var IL10N */
42
-	private $l;
41
+    /** @var IL10N */
42
+    private $l;
43 43
 
44
-	/**
45
-	 * Account constructor.
46
-	 *
47
-	 * @param string $appName
48
-	 * @param IURLGenerator $urlGenerator
49
-	 * @param IL10N $l
50
-	 */
51
-	public function __construct(string $appName,
52
-								IURLGenerator $urlGenerator,
53
-								IL10N $l) {
54
-		$this->appName      = $appName;
55
-		$this->urlGenerator = $urlGenerator;
56
-		$this->l            = $l;
57
-	}
44
+    /**
45
+     * Account constructor.
46
+     *
47
+     * @param string $appName
48
+     * @param IURLGenerator $urlGenerator
49
+     * @param IL10N $l
50
+     */
51
+    public function __construct(string $appName,
52
+                                IURLGenerator $urlGenerator,
53
+                                IL10N $l) {
54
+        $this->appName      = $appName;
55
+        $this->urlGenerator = $urlGenerator;
56
+        $this->l            = $l;
57
+    }
58 58
 
59
-	public function getThemes() {
60
-		return [
61
-			[
62
-				'id'    => 'dark',
63
-				'img'   => $this->urlGenerator->imagePath($this->appName, 'theme-dark.jpg'),
64
-				'title' => $this->l->t('Dark theme'),
65
-				'enableLabel' => $this->l->t('Enable dark theme'),
66
-				'text'  => $this->l->t('A dark theme to ease your eyes by reducing the overall luminosity and brightness. It is still under development, so please report any issues you may find.')
67
-			]
68
-		];
69
-	}
59
+    public function getThemes() {
60
+        return [
61
+            [
62
+                'id'    => 'dark',
63
+                'img'   => $this->urlGenerator->imagePath($this->appName, 'theme-dark.jpg'),
64
+                'title' => $this->l->t('Dark theme'),
65
+                'enableLabel' => $this->l->t('Enable dark theme'),
66
+                'text'  => $this->l->t('A dark theme to ease your eyes by reducing the overall luminosity and brightness. It is still under development, so please report any issues you may find.')
67
+            ]
68
+        ];
69
+    }
70 70
 
71
-	public function getHighContrast() {
72
-		return [
73
-				'id'    => 'highcontrast',
74
-				'img'   => $this->urlGenerator->imagePath($this->appName, 'mode-highcontrast.jpg'),
75
-				'title' => $this->l->t('High contrast mode'),
76
-				'enableLabel' => $this->l->t('Enable high contrast mode'),
77
-				'text'  => $this->l->t('A high contrast mode to ease your navigation. Visual quality will be reduced but clarity will be increased.')
78
-			];
79
-	}
71
+    public function getHighContrast() {
72
+        return [
73
+                'id'    => 'highcontrast',
74
+                'img'   => $this->urlGenerator->imagePath($this->appName, 'mode-highcontrast.jpg'),
75
+                'title' => $this->l->t('High contrast mode'),
76
+                'enableLabel' => $this->l->t('Enable high contrast mode'),
77
+                'text'  => $this->l->t('A high contrast mode to ease your navigation. Visual quality will be reduced but clarity will be increased.')
78
+            ];
79
+    }
80 80
 
81
-	public function getFonts() {
82
-		return [
83
-			[
84
-				'id'    => 'fontdyslexic',
85
-				'img'   => $this->urlGenerator->imagePath($this->appName, 'font-opendyslexic.jpg'),
86
-				'title' => $this->l->t('Dyslexia font'),
87
-				'enableLabel' => $this->l->t('Enable dyslexia font'),
88
-				'text'  => $this->l->t('OpenDyslexic is a free typeface/font designed to mitigate some of the common reading errors caused by dyslexia.')
89
-			]
90
-		];
91
-	}
81
+    public function getFonts() {
82
+        return [
83
+            [
84
+                'id'    => 'fontdyslexic',
85
+                'img'   => $this->urlGenerator->imagePath($this->appName, 'font-opendyslexic.jpg'),
86
+                'title' => $this->l->t('Dyslexia font'),
87
+                'enableLabel' => $this->l->t('Enable dyslexia font'),
88
+                'text'  => $this->l->t('OpenDyslexic is a free typeface/font designed to mitigate some of the common reading errors caused by dyslexia.')
89
+            ]
90
+        ];
91
+    }
92 92
 
93 93
 }
Please login to merge, or discard this patch.
apps/accessibility/lib/Controller/ConfigController.php 1 patch
Indentation   +116 added lines, -116 removed lines patch added patch discarded remove patch
@@ -40,121 +40,121 @@
 block discarded – undo
40 40
 
41 41
 class ConfigController extends OCSController {
42 42
 
43
-	/** @var string */
44
-	protected $appName;
45
-
46
-	/** @var string */
47
-	protected $userId;
48
-
49
-	/** @var string */
50
-	protected $serverRoot;
51
-
52
-	/** @var IConfig */
53
-	private $config;
54
-
55
-	/** @var IUserSession */
56
-	private $userSession;
57
-
58
-	/** @var AccessibilityProvider */
59
-	private $accessibilityProvider;
60
-
61
-	/**
62
-	 * Config constructor.
63
-	 *
64
-	 * @param string $appName
65
-	 * @param IRequest $request
66
-	 * @param IConfig $config
67
-	 * @param IUserSession $userSession
68
-	 * @param AccessibilityProvider $accessibilityProvider
69
-	 */
70
-	public function __construct(string $appName,
71
-								IRequest $request,
72
-								IConfig $config,
73
-								IUserSession $userSession,
74
-								AccessibilityProvider $accessibilityProvider) {
75
-		parent::__construct($appName, $request);
76
-		$this->appName               = $appName;
77
-		$this->config                = $config;
78
-		$this->userSession           = $userSession;
79
-		$this->accessibilityProvider = $accessibilityProvider;
80
-		$this->userId				 = $userSession->getUser()->getUID();
81
-	}
82
-
83
-	/**
84
-	 * @NoAdminRequired
85
-	 *
86
-	 * Get user accessibility config
87
-	 *
88
-	 * @param string $key theme or font
89
-	 * @return DataResponse
90
-	 */
91
-	public function getConfig(): DataResponse {
92
-		return new DataResponse([
93
-			'highcontrast' => $this->config->getUserValue($this->userId, $this->appName, 'highcontrast', false),
94
-			'theme' => $this->config->getUserValue($this->userId, $this->appName, 'theme', false),
95
-			'font' => $this->config->getUserValue($this->userId, $this->appName, 'font', false)
96
-		]);
97
-	}
98
-
99
-	/**
100
-	 * @NoAdminRequired
101
-	 *
102
-	 * Set theme or font config
103
-	 *
104
-	 * @param string $key theme or font
105
-	 * @return DataResponse
106
-	 * @throws Exception
107
-	 */
108
-	public function setConfig(string $key, $value): DataResponse {
109
-		if ($key === 'theme' || $key === 'font' || $key === 'highcontrast') {
110
-
111
-			if ($value === false || $value === '') {
112
-				throw new OCSBadRequestException('Invalid value: ' . $value);
113
-			}
114
-
115
-			$themes = $this->accessibilityProvider->getThemes();
116
-			$highcontrast = [$this->accessibilityProvider->getHighContrast()];
117
-			$fonts  = $this->accessibilityProvider->getFonts();
118
-
119
-			$availableOptions = array_map(function($option) {
120
-				return $option['id'];
121
-			}, array_merge($themes, $highcontrast, $fonts));
122
-
123
-			if (in_array($value, $availableOptions)) {
124
-				$this->config->setUserValue($this->userId, $this->appName, $key, $value);
125
-				return new DataResponse();
126
-			}
127
-
128
-			throw new OCSBadRequestException('Invalid value: ' . $value);
129
-		}
130
-
131
-		throw new OCSBadRequestException('Invalid key: ' . $key);
132
-	}
133
-
134
-	/**
135
-	 * @NoAdminRequired
136
-	 *
137
-	 * Unset theme or font config
138
-	 *
139
-	 * @param string $key theme or font
140
-	 * @return DataResponse
141
-	 * @throws Exception
142
-	 */
143
-	public function deleteConfig(string $key): DataResponse {
144
-		if ($key === 'theme' || $key === 'font' || $key === 'highcontrast') {
145
-
146
-			$this->config->deleteUserValue($this->userId, $this->appName, $key);
147
-			$userValues = $this->config->getUserKeys($this->userId, $this->appName);
148
-
149
-			// remove hash if no settings selected
150
-			if (count($userValues) === 1 && $userValues[0] === 'icons-css') {
151
-				$this->config->deleteUserValue($this->userId, $this->appName, 'icons-css');
152
-			}
153
-
154
-			return new DataResponse();
155
-		}
156
-
157
-		throw new OCSBadRequestException('Invalid key: ' . $key);
158
-	}
43
+    /** @var string */
44
+    protected $appName;
45
+
46
+    /** @var string */
47
+    protected $userId;
48
+
49
+    /** @var string */
50
+    protected $serverRoot;
51
+
52
+    /** @var IConfig */
53
+    private $config;
54
+
55
+    /** @var IUserSession */
56
+    private $userSession;
57
+
58
+    /** @var AccessibilityProvider */
59
+    private $accessibilityProvider;
60
+
61
+    /**
62
+     * Config constructor.
63
+     *
64
+     * @param string $appName
65
+     * @param IRequest $request
66
+     * @param IConfig $config
67
+     * @param IUserSession $userSession
68
+     * @param AccessibilityProvider $accessibilityProvider
69
+     */
70
+    public function __construct(string $appName,
71
+                                IRequest $request,
72
+                                IConfig $config,
73
+                                IUserSession $userSession,
74
+                                AccessibilityProvider $accessibilityProvider) {
75
+        parent::__construct($appName, $request);
76
+        $this->appName               = $appName;
77
+        $this->config                = $config;
78
+        $this->userSession           = $userSession;
79
+        $this->accessibilityProvider = $accessibilityProvider;
80
+        $this->userId				 = $userSession->getUser()->getUID();
81
+    }
82
+
83
+    /**
84
+     * @NoAdminRequired
85
+     *
86
+     * Get user accessibility config
87
+     *
88
+     * @param string $key theme or font
89
+     * @return DataResponse
90
+     */
91
+    public function getConfig(): DataResponse {
92
+        return new DataResponse([
93
+            'highcontrast' => $this->config->getUserValue($this->userId, $this->appName, 'highcontrast', false),
94
+            'theme' => $this->config->getUserValue($this->userId, $this->appName, 'theme', false),
95
+            'font' => $this->config->getUserValue($this->userId, $this->appName, 'font', false)
96
+        ]);
97
+    }
98
+
99
+    /**
100
+     * @NoAdminRequired
101
+     *
102
+     * Set theme or font config
103
+     *
104
+     * @param string $key theme or font
105
+     * @return DataResponse
106
+     * @throws Exception
107
+     */
108
+    public function setConfig(string $key, $value): DataResponse {
109
+        if ($key === 'theme' || $key === 'font' || $key === 'highcontrast') {
110
+
111
+            if ($value === false || $value === '') {
112
+                throw new OCSBadRequestException('Invalid value: ' . $value);
113
+            }
114
+
115
+            $themes = $this->accessibilityProvider->getThemes();
116
+            $highcontrast = [$this->accessibilityProvider->getHighContrast()];
117
+            $fonts  = $this->accessibilityProvider->getFonts();
118
+
119
+            $availableOptions = array_map(function($option) {
120
+                return $option['id'];
121
+            }, array_merge($themes, $highcontrast, $fonts));
122
+
123
+            if (in_array($value, $availableOptions)) {
124
+                $this->config->setUserValue($this->userId, $this->appName, $key, $value);
125
+                return new DataResponse();
126
+            }
127
+
128
+            throw new OCSBadRequestException('Invalid value: ' . $value);
129
+        }
130
+
131
+        throw new OCSBadRequestException('Invalid key: ' . $key);
132
+    }
133
+
134
+    /**
135
+     * @NoAdminRequired
136
+     *
137
+     * Unset theme or font config
138
+     *
139
+     * @param string $key theme or font
140
+     * @return DataResponse
141
+     * @throws Exception
142
+     */
143
+    public function deleteConfig(string $key): DataResponse {
144
+        if ($key === 'theme' || $key === 'font' || $key === 'highcontrast') {
145
+
146
+            $this->config->deleteUserValue($this->userId, $this->appName, $key);
147
+            $userValues = $this->config->getUserKeys($this->userId, $this->appName);
148
+
149
+            // remove hash if no settings selected
150
+            if (count($userValues) === 1 && $userValues[0] === 'icons-css') {
151
+                $this->config->deleteUserValue($this->userId, $this->appName, 'icons-css');
152
+            }
153
+
154
+            return new DataResponse();
155
+        }
156
+
157
+        throw new OCSBadRequestException('Invalid key: ' . $key);
158
+    }
159 159
 
160 160
 }
Please login to merge, or discard this patch.
apps/files_sharing/public.php 2 patches
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -28,15 +28,15 @@
 block discarded – undo
28 28
 $route = isset($_GET['download']) ? 'files_sharing.sharecontroller.downloadShare' : 'files_sharing.sharecontroller.showShare';
29 29
 
30 30
 if ($token !== '') {
31
-	$protocol = \OC::$server->getRequest()->getHttpProtocol();
32
-	if ($protocol == 'HTTP/1.0') {
33
-		http_response_code(302);
34
-	} else {
35
-		http_response_code(307);
36
-	}
37
-	header('Location: ' . $urlGenerator->linkToRoute($route, ['token' => $token]));
31
+    $protocol = \OC::$server->getRequest()->getHttpProtocol();
32
+    if ($protocol == 'HTTP/1.0') {
33
+        http_response_code(302);
34
+    } else {
35
+        http_response_code(307);
36
+    }
37
+    header('Location: ' . $urlGenerator->linkToRoute($route, ['token' => $token]));
38 38
 } else {
39
-	http_response_code(404);
40
-	$tmpl = new OCP\Template('', '404', 'guest');
41
-	print_unescaped($tmpl->fetchPage());
39
+    http_response_code(404);
40
+    $tmpl = new OCP\Template('', '404', 'guest');
41
+    print_unescaped($tmpl->fetchPage());
42 42
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -34,7 +34,7 @@
 block discarded – undo
34 34
 	} else {
35 35
 		http_response_code(307);
36 36
 	}
37
-	header('Location: ' . $urlGenerator->linkToRoute($route, ['token' => $token]));
37
+	header('Location: '.$urlGenerator->linkToRoute($route, ['token' => $token]));
38 38
 } else {
39 39
 	http_response_code(404);
40 40
 	$tmpl = new OCP\Template('', '404', 'guest');
Please login to merge, or discard this patch.