Completed
Pull Request — master (#7918)
by Morris
14:16
created
apps/files_trashbin/lib/Storage.php 2 patches
Indentation   +280 added lines, -280 removed lines patch added patch discarded remove patch
@@ -40,285 +40,285 @@
 block discarded – undo
40 40
 
41 41
 class Storage extends Wrapper {
42 42
 
43
-	private $mountPoint;
44
-	// remember already deleted files to avoid infinite loops if the trash bin
45
-	// move files across storages
46
-	private $deletedFiles = array();
47
-
48
-	/**
49
-	 * Disable trash logic
50
-	 *
51
-	 * @var bool
52
-	 */
53
-	private static $disableTrash = false;
54
-
55
-	/**
56
-	 * remember which file/folder was moved out of s shared folder
57
-	 * in this case we want to add a copy to the owners trash bin
58
-	 *
59
-	 * @var array
60
-	 */
61
-	private static $moveOutOfSharedFolder = [];
62
-
63
-	/** @var  IUserManager */
64
-	private $userManager;
65
-
66
-	/** @var ILogger */
67
-	private $logger;
68
-
69
-	/** @var EventDispatcher */
70
-	private $eventDispatcher;
71
-
72
-	/** @var IRootFolder */
73
-	private $rootFolder;
74
-
75
-	/**
76
-	 * Storage constructor.
77
-	 *
78
-	 * @param array $parameters
79
-	 * @param IUserManager|null $userManager
80
-	 * @param ILogger|null $logger
81
-	 * @param EventDispatcher|null $eventDispatcher
82
-	 * @param IRootFolder|null $rootFolder
83
-	 */
84
-	public function __construct($parameters,
85
-								IUserManager $userManager = null,
86
-								ILogger $logger = null,
87
-								EventDispatcher $eventDispatcher = null,
88
-								IRootFolder $rootFolder = null) {
89
-		$this->mountPoint = $parameters['mountPoint'];
90
-		$this->userManager = $userManager;
91
-		$this->logger = $logger;
92
-		$this->eventDispatcher = $eventDispatcher;
93
-		$this->rootFolder = $rootFolder;
94
-		parent::__construct($parameters);
95
-	}
96
-
97
-	/**
98
-	 * @internal
99
-	 */
100
-	public static function preRenameHook($params) {
101
-		// in cross-storage cases, a rename is a copy + unlink,
102
-		// that last unlink must not go to trash, only exception:
103
-		// if the file was moved from a shared storage to a local folder,
104
-		// in this case the owner should get a copy in his trash bin so that
105
-		// they can restore the files again
106
-
107
-		$oldPath = $params['oldpath'];
108
-		$newPath = dirname($params['newpath']);
109
-		$currentUser = \OC::$server->getUserSession()->getUser();
110
-
111
-		$fileMovedOutOfSharedFolder = false;
112
-
113
-		try {
114
-			if ($currentUser) {
115
-				$currentUserId = $currentUser->getUID();
116
-
117
-				$view = new View($currentUserId . '/files');
118
-				$fileInfo = $view->getFileInfo($oldPath);
119
-				if ($fileInfo) {
120
-					$sourceStorage = $fileInfo->getStorage();
121
-					$sourceOwner = $view->getOwner($oldPath);
122
-					$targetOwner = $view->getOwner($newPath);
123
-
124
-					if ($sourceOwner !== $targetOwner
125
-						&& $sourceStorage->instanceOfStorage('OCA\Files_Sharing\SharedStorage')
126
-					) {
127
-						$fileMovedOutOfSharedFolder = true;
128
-					}
129
-				}
130
-			}
131
-		} catch (\Exception $e) {
132
-			// do nothing, in this case we just disable the trashbin and continue
133
-			\OC::$server->getLogger()->logException($e, [
134
-				'message' => 'Trashbin storage could not check if a file was moved out of a shared folder.',
135
-				'level' => \OCP\Util::DEBUG,
136
-				'app' => 'files_trashbin',
137
-			]);
138
-		}
139
-
140
-		if($fileMovedOutOfSharedFolder) {
141
-			self::$moveOutOfSharedFolder['/' . $currentUserId . '/files' . $oldPath] = true;
142
-		} else {
143
-			self::$disableTrash = true;
144
-		}
145
-
146
-	}
147
-
148
-	/**
149
-	 * @internal
150
-	 */
151
-	public static function postRenameHook($params) {
152
-		self::$disableTrash = false;
153
-	}
154
-
155
-	/**
156
-	 * Rename path1 to path2 by calling the wrapped storage.
157
-	 *
158
-	 * @param string $path1 first path
159
-	 * @param string $path2 second path
160
-	 * @return bool
161
-	 */
162
-	public function rename($path1, $path2) {
163
-		$result = $this->storage->rename($path1, $path2);
164
-		if ($result === false) {
165
-			// when rename failed, the post_rename hook isn't triggered,
166
-			// but we still want to reenable the trash logic
167
-			self::$disableTrash = false;
168
-		}
169
-		return $result;
170
-	}
171
-
172
-	/**
173
-	 * Deletes the given file by moving it into the trashbin.
174
-	 *
175
-	 * @param string $path path of file or folder to delete
176
-	 *
177
-	 * @return bool true if the operation succeeded, false otherwise
178
-	 */
179
-	public function unlink($path) {
180
-		try {
181
-			if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
182
-				$result = $this->doDelete($path, 'unlink', true);
183
-				unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
184
-			} else {
185
-				$result = $this->doDelete($path, 'unlink');
186
-			}
187
-		} catch (GenericEncryptionException $e) {
188
-			// in case of a encryption exception we delete the file right away
189
-			$this->logger->info(
190
-				"Can't move file" .  $path .
191
-				"to the trash bin, therefore it was deleted right away");
192
-
193
-			$result = $this->storage->unlink($path);
194
-		}
195
-
196
-		return $result;
197
-	}
198
-
199
-	/**
200
-	 * Deletes the given folder by moving it into the trashbin.
201
-	 *
202
-	 * @param string $path path of folder to delete
203
-	 *
204
-	 * @return bool true if the operation succeeded, false otherwise
205
-	 */
206
-	public function rmdir($path) {
207
-		if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
208
-			$result = $this->doDelete($path, 'rmdir', true);
209
-			unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
210
-		} else {
211
-			$result = $this->doDelete($path, 'rmdir');
212
-		}
213
-
214
-		return $result;
215
-	}
216
-
217
-	/**
218
-	 * check if it is a file located in data/user/files only files in the
219
-	 * 'files' directory should be moved to the trash
220
-	 *
221
-	 * @param $path
222
-	 * @return bool
223
-	 */
224
-	protected function shouldMoveToTrash($path){
225
-
226
-		// check if there is a app which want to disable the trash bin for this file
227
-		$fileId = $this->storage->getCache()->getId($path);
228
-		$nodes = $this->rootFolder->getById($fileId);
229
-		foreach ($nodes as $node) {
230
-			$event = $this->createMoveToTrashEvent($node);
231
-			$this->eventDispatcher->dispatch('OCA\Files_Trashbin::moveToTrash', $event);
232
-			if ($event->shouldMoveToTrashBin() === false) {
233
-				return false;
234
-			}
235
-		}
236
-
237
-		$normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path);
238
-		$parts = explode('/', $normalized);
239
-		if (count($parts) < 4) {
240
-			return false;
241
-		}
242
-
243
-		if ($parts[2] === 'files' && $this->userManager->userExists($parts[1])) {
244
-			return true;
245
-		}
246
-
247
-		return false;
248
-	}
249
-
250
-	/**
251
-	 * get move to trash event
252
-	 *
253
-	 * @param Node $node
254
-	 * @return MoveToTrashEvent
255
-	 */
256
-	protected function createMoveToTrashEvent(Node $node) {
257
-		$event = new MoveToTrashEvent($node);
258
-		return $event;
259
-	}
260
-
261
-	/**
262
-	 * Run the delete operation with the given method
263
-	 *
264
-	 * @param string $path path of file or folder to delete
265
-	 * @param string $method either "unlink" or "rmdir"
266
-	 * @param bool $ownerOnly delete for owner only (if file gets moved out of a shared folder)
267
-	 *
268
-	 * @return bool true if the operation succeeded, false otherwise
269
-	 */
270
-	private function doDelete($path, $method, $ownerOnly = false) {
271
-		if (self::$disableTrash
272
-			|| !\OC_App::isEnabled('files_trashbin')
273
-			|| (pathinfo($path, PATHINFO_EXTENSION) === 'part')
274
-			|| $this->shouldMoveToTrash($path) === false
275
-		) {
276
-			return call_user_func_array([$this->storage, $method], [$path]);
277
-		}
278
-
279
-		// check permissions before we continue, this is especially important for
280
-		// shared files
281
-		if (!$this->isDeletable($path)) {
282
-			return false;
283
-		}
284
-
285
-		$normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path, true, false, true);
286
-		$result = true;
287
-		$view = Filesystem::getView();
288
-		if (!isset($this->deletedFiles[$normalized]) && $view instanceof View) {
289
-			$this->deletedFiles[$normalized] = $normalized;
290
-			if ($filesPath = $view->getRelativePath($normalized)) {
291
-				$filesPath = trim($filesPath, '/');
292
-				$result = \OCA\Files_Trashbin\Trashbin::move2trash($filesPath, $ownerOnly);
293
-				// in cross-storage cases the file will be copied
294
-				// but not deleted, so we delete it here
295
-				if ($result) {
296
-					call_user_func_array([$this->storage, $method], [$path]);
297
-				}
298
-			} else {
299
-				$result = call_user_func_array([$this->storage, $method], [$path]);
300
-			}
301
-			unset($this->deletedFiles[$normalized]);
302
-		} else if ($this->storage->file_exists($path)) {
303
-			$result = call_user_func_array([$this->storage, $method], [$path]);
304
-		}
305
-
306
-		return $result;
307
-	}
308
-
309
-	/**
310
-	 * Setup the storate wrapper callback
311
-	 */
312
-	public static function setupStorage() {
313
-		\OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function ($mountPoint, $storage) {
314
-			return new \OCA\Files_Trashbin\Storage(
315
-				array('storage' => $storage, 'mountPoint' => $mountPoint),
316
-				\OC::$server->getUserManager(),
317
-				\OC::$server->getLogger(),
318
-				\OC::$server->getEventDispatcher(),
319
-				\OC::$server->getLazyRootFolder()
320
-			);
321
-		}, 1);
322
-	}
43
+    private $mountPoint;
44
+    // remember already deleted files to avoid infinite loops if the trash bin
45
+    // move files across storages
46
+    private $deletedFiles = array();
47
+
48
+    /**
49
+     * Disable trash logic
50
+     *
51
+     * @var bool
52
+     */
53
+    private static $disableTrash = false;
54
+
55
+    /**
56
+     * remember which file/folder was moved out of s shared folder
57
+     * in this case we want to add a copy to the owners trash bin
58
+     *
59
+     * @var array
60
+     */
61
+    private static $moveOutOfSharedFolder = [];
62
+
63
+    /** @var  IUserManager */
64
+    private $userManager;
65
+
66
+    /** @var ILogger */
67
+    private $logger;
68
+
69
+    /** @var EventDispatcher */
70
+    private $eventDispatcher;
71
+
72
+    /** @var IRootFolder */
73
+    private $rootFolder;
74
+
75
+    /**
76
+     * Storage constructor.
77
+     *
78
+     * @param array $parameters
79
+     * @param IUserManager|null $userManager
80
+     * @param ILogger|null $logger
81
+     * @param EventDispatcher|null $eventDispatcher
82
+     * @param IRootFolder|null $rootFolder
83
+     */
84
+    public function __construct($parameters,
85
+                                IUserManager $userManager = null,
86
+                                ILogger $logger = null,
87
+                                EventDispatcher $eventDispatcher = null,
88
+                                IRootFolder $rootFolder = null) {
89
+        $this->mountPoint = $parameters['mountPoint'];
90
+        $this->userManager = $userManager;
91
+        $this->logger = $logger;
92
+        $this->eventDispatcher = $eventDispatcher;
93
+        $this->rootFolder = $rootFolder;
94
+        parent::__construct($parameters);
95
+    }
96
+
97
+    /**
98
+     * @internal
99
+     */
100
+    public static function preRenameHook($params) {
101
+        // in cross-storage cases, a rename is a copy + unlink,
102
+        // that last unlink must not go to trash, only exception:
103
+        // if the file was moved from a shared storage to a local folder,
104
+        // in this case the owner should get a copy in his trash bin so that
105
+        // they can restore the files again
106
+
107
+        $oldPath = $params['oldpath'];
108
+        $newPath = dirname($params['newpath']);
109
+        $currentUser = \OC::$server->getUserSession()->getUser();
110
+
111
+        $fileMovedOutOfSharedFolder = false;
112
+
113
+        try {
114
+            if ($currentUser) {
115
+                $currentUserId = $currentUser->getUID();
116
+
117
+                $view = new View($currentUserId . '/files');
118
+                $fileInfo = $view->getFileInfo($oldPath);
119
+                if ($fileInfo) {
120
+                    $sourceStorage = $fileInfo->getStorage();
121
+                    $sourceOwner = $view->getOwner($oldPath);
122
+                    $targetOwner = $view->getOwner($newPath);
123
+
124
+                    if ($sourceOwner !== $targetOwner
125
+                        && $sourceStorage->instanceOfStorage('OCA\Files_Sharing\SharedStorage')
126
+                    ) {
127
+                        $fileMovedOutOfSharedFolder = true;
128
+                    }
129
+                }
130
+            }
131
+        } catch (\Exception $e) {
132
+            // do nothing, in this case we just disable the trashbin and continue
133
+            \OC::$server->getLogger()->logException($e, [
134
+                'message' => 'Trashbin storage could not check if a file was moved out of a shared folder.',
135
+                'level' => \OCP\Util::DEBUG,
136
+                'app' => 'files_trashbin',
137
+            ]);
138
+        }
139
+
140
+        if($fileMovedOutOfSharedFolder) {
141
+            self::$moveOutOfSharedFolder['/' . $currentUserId . '/files' . $oldPath] = true;
142
+        } else {
143
+            self::$disableTrash = true;
144
+        }
145
+
146
+    }
147
+
148
+    /**
149
+     * @internal
150
+     */
151
+    public static function postRenameHook($params) {
152
+        self::$disableTrash = false;
153
+    }
154
+
155
+    /**
156
+     * Rename path1 to path2 by calling the wrapped storage.
157
+     *
158
+     * @param string $path1 first path
159
+     * @param string $path2 second path
160
+     * @return bool
161
+     */
162
+    public function rename($path1, $path2) {
163
+        $result = $this->storage->rename($path1, $path2);
164
+        if ($result === false) {
165
+            // when rename failed, the post_rename hook isn't triggered,
166
+            // but we still want to reenable the trash logic
167
+            self::$disableTrash = false;
168
+        }
169
+        return $result;
170
+    }
171
+
172
+    /**
173
+     * Deletes the given file by moving it into the trashbin.
174
+     *
175
+     * @param string $path path of file or folder to delete
176
+     *
177
+     * @return bool true if the operation succeeded, false otherwise
178
+     */
179
+    public function unlink($path) {
180
+        try {
181
+            if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
182
+                $result = $this->doDelete($path, 'unlink', true);
183
+                unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
184
+            } else {
185
+                $result = $this->doDelete($path, 'unlink');
186
+            }
187
+        } catch (GenericEncryptionException $e) {
188
+            // in case of a encryption exception we delete the file right away
189
+            $this->logger->info(
190
+                "Can't move file" .  $path .
191
+                "to the trash bin, therefore it was deleted right away");
192
+
193
+            $result = $this->storage->unlink($path);
194
+        }
195
+
196
+        return $result;
197
+    }
198
+
199
+    /**
200
+     * Deletes the given folder by moving it into the trashbin.
201
+     *
202
+     * @param string $path path of folder to delete
203
+     *
204
+     * @return bool true if the operation succeeded, false otherwise
205
+     */
206
+    public function rmdir($path) {
207
+        if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
208
+            $result = $this->doDelete($path, 'rmdir', true);
209
+            unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
210
+        } else {
211
+            $result = $this->doDelete($path, 'rmdir');
212
+        }
213
+
214
+        return $result;
215
+    }
216
+
217
+    /**
218
+     * check if it is a file located in data/user/files only files in the
219
+     * 'files' directory should be moved to the trash
220
+     *
221
+     * @param $path
222
+     * @return bool
223
+     */
224
+    protected function shouldMoveToTrash($path){
225
+
226
+        // check if there is a app which want to disable the trash bin for this file
227
+        $fileId = $this->storage->getCache()->getId($path);
228
+        $nodes = $this->rootFolder->getById($fileId);
229
+        foreach ($nodes as $node) {
230
+            $event = $this->createMoveToTrashEvent($node);
231
+            $this->eventDispatcher->dispatch('OCA\Files_Trashbin::moveToTrash', $event);
232
+            if ($event->shouldMoveToTrashBin() === false) {
233
+                return false;
234
+            }
235
+        }
236
+
237
+        $normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path);
238
+        $parts = explode('/', $normalized);
239
+        if (count($parts) < 4) {
240
+            return false;
241
+        }
242
+
243
+        if ($parts[2] === 'files' && $this->userManager->userExists($parts[1])) {
244
+            return true;
245
+        }
246
+
247
+        return false;
248
+    }
249
+
250
+    /**
251
+     * get move to trash event
252
+     *
253
+     * @param Node $node
254
+     * @return MoveToTrashEvent
255
+     */
256
+    protected function createMoveToTrashEvent(Node $node) {
257
+        $event = new MoveToTrashEvent($node);
258
+        return $event;
259
+    }
260
+
261
+    /**
262
+     * Run the delete operation with the given method
263
+     *
264
+     * @param string $path path of file or folder to delete
265
+     * @param string $method either "unlink" or "rmdir"
266
+     * @param bool $ownerOnly delete for owner only (if file gets moved out of a shared folder)
267
+     *
268
+     * @return bool true if the operation succeeded, false otherwise
269
+     */
270
+    private function doDelete($path, $method, $ownerOnly = false) {
271
+        if (self::$disableTrash
272
+            || !\OC_App::isEnabled('files_trashbin')
273
+            || (pathinfo($path, PATHINFO_EXTENSION) === 'part')
274
+            || $this->shouldMoveToTrash($path) === false
275
+        ) {
276
+            return call_user_func_array([$this->storage, $method], [$path]);
277
+        }
278
+
279
+        // check permissions before we continue, this is especially important for
280
+        // shared files
281
+        if (!$this->isDeletable($path)) {
282
+            return false;
283
+        }
284
+
285
+        $normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path, true, false, true);
286
+        $result = true;
287
+        $view = Filesystem::getView();
288
+        if (!isset($this->deletedFiles[$normalized]) && $view instanceof View) {
289
+            $this->deletedFiles[$normalized] = $normalized;
290
+            if ($filesPath = $view->getRelativePath($normalized)) {
291
+                $filesPath = trim($filesPath, '/');
292
+                $result = \OCA\Files_Trashbin\Trashbin::move2trash($filesPath, $ownerOnly);
293
+                // in cross-storage cases the file will be copied
294
+                // but not deleted, so we delete it here
295
+                if ($result) {
296
+                    call_user_func_array([$this->storage, $method], [$path]);
297
+                }
298
+            } else {
299
+                $result = call_user_func_array([$this->storage, $method], [$path]);
300
+            }
301
+            unset($this->deletedFiles[$normalized]);
302
+        } else if ($this->storage->file_exists($path)) {
303
+            $result = call_user_func_array([$this->storage, $method], [$path]);
304
+        }
305
+
306
+        return $result;
307
+    }
308
+
309
+    /**
310
+     * Setup the storate wrapper callback
311
+     */
312
+    public static function setupStorage() {
313
+        \OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function ($mountPoint, $storage) {
314
+            return new \OCA\Files_Trashbin\Storage(
315
+                array('storage' => $storage, 'mountPoint' => $mountPoint),
316
+                \OC::$server->getUserManager(),
317
+                \OC::$server->getLogger(),
318
+                \OC::$server->getEventDispatcher(),
319
+                \OC::$server->getLazyRootFolder()
320
+            );
321
+        }, 1);
322
+    }
323 323
 
324 324
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
 			if ($currentUser) {
115 115
 				$currentUserId = $currentUser->getUID();
116 116
 
117
-				$view = new View($currentUserId . '/files');
117
+				$view = new View($currentUserId.'/files');
118 118
 				$fileInfo = $view->getFileInfo($oldPath);
119 119
 				if ($fileInfo) {
120 120
 					$sourceStorage = $fileInfo->getStorage();
@@ -137,8 +137,8 @@  discard block
 block discarded – undo
137 137
 			]);
138 138
 		}
139 139
 
140
-		if($fileMovedOutOfSharedFolder) {
141
-			self::$moveOutOfSharedFolder['/' . $currentUserId . '/files' . $oldPath] = true;
140
+		if ($fileMovedOutOfSharedFolder) {
141
+			self::$moveOutOfSharedFolder['/'.$currentUserId.'/files'.$oldPath] = true;
142 142
 		} else {
143 143
 			self::$disableTrash = true;
144 144
 		}
@@ -178,16 +178,16 @@  discard block
 block discarded – undo
178 178
 	 */
179 179
 	public function unlink($path) {
180 180
 		try {
181
-			if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
181
+			if (isset(self::$moveOutOfSharedFolder[$this->mountPoint.$path])) {
182 182
 				$result = $this->doDelete($path, 'unlink', true);
183
-				unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
183
+				unset(self::$moveOutOfSharedFolder[$this->mountPoint.$path]);
184 184
 			} else {
185 185
 				$result = $this->doDelete($path, 'unlink');
186 186
 			}
187 187
 		} catch (GenericEncryptionException $e) {
188 188
 			// in case of a encryption exception we delete the file right away
189 189
 			$this->logger->info(
190
-				"Can't move file" .  $path .
190
+				"Can't move file".$path.
191 191
 				"to the trash bin, therefore it was deleted right away");
192 192
 
193 193
 			$result = $this->storage->unlink($path);
@@ -204,9 +204,9 @@  discard block
 block discarded – undo
204 204
 	 * @return bool true if the operation succeeded, false otherwise
205 205
 	 */
206 206
 	public function rmdir($path) {
207
-		if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
207
+		if (isset(self::$moveOutOfSharedFolder[$this->mountPoint.$path])) {
208 208
 			$result = $this->doDelete($path, 'rmdir', true);
209
-			unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
209
+			unset(self::$moveOutOfSharedFolder[$this->mountPoint.$path]);
210 210
 		} else {
211 211
 			$result = $this->doDelete($path, 'rmdir');
212 212
 		}
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
 	 * @param $path
222 222
 	 * @return bool
223 223
 	 */
224
-	protected function shouldMoveToTrash($path){
224
+	protected function shouldMoveToTrash($path) {
225 225
 
226 226
 		// check if there is a app which want to disable the trash bin for this file
227 227
 		$fileId = $this->storage->getCache()->getId($path);
@@ -234,7 +234,7 @@  discard block
 block discarded – undo
234 234
 			}
235 235
 		}
236 236
 
237
-		$normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path);
237
+		$normalized = Filesystem::normalizePath($this->mountPoint.'/'.$path);
238 238
 		$parts = explode('/', $normalized);
239 239
 		if (count($parts) < 4) {
240 240
 			return false;
@@ -282,7 +282,7 @@  discard block
 block discarded – undo
282 282
 			return false;
283 283
 		}
284 284
 
285
-		$normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path, true, false, true);
285
+		$normalized = Filesystem::normalizePath($this->mountPoint.'/'.$path, true, false, true);
286 286
 		$result = true;
287 287
 		$view = Filesystem::getView();
288 288
 		if (!isset($this->deletedFiles[$normalized]) && $view instanceof View) {
@@ -310,7 +310,7 @@  discard block
 block discarded – undo
310 310
 	 * Setup the storate wrapper callback
311 311
 	 */
312 312
 	public static function setupStorage() {
313
-		\OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function ($mountPoint, $storage) {
313
+		\OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function($mountPoint, $storage) {
314 314
 			return new \OCA\Files_Trashbin\Storage(
315 315
 				array('storage' => $storage, 'mountPoint' => $mountPoint),
316 316
 				\OC::$server->getUserManager(),
Please login to merge, or discard this patch.
apps/user_ldap/lib/User/User.php 2 patches
Indentation   +645 added lines, -645 removed lines patch added patch discarded remove patch
@@ -46,655 +46,655 @@
 block discarded – undo
46 46
  * represents an LDAP user, gets and holds user-specific information from LDAP
47 47
  */
48 48
 class User {
49
-	/**
50
-	 * @var IUserTools
51
-	 */
52
-	protected $access;
53
-	/**
54
-	 * @var Connection
55
-	 */
56
-	protected $connection;
57
-	/**
58
-	 * @var IConfig
59
-	 */
60
-	protected $config;
61
-	/**
62
-	 * @var FilesystemHelper
63
-	 */
64
-	protected $fs;
65
-	/**
66
-	 * @var Image
67
-	 */
68
-	protected $image;
69
-	/**
70
-	 * @var LogWrapper
71
-	 */
72
-	protected $log;
73
-	/**
74
-	 * @var IAvatarManager
75
-	 */
76
-	protected $avatarManager;
77
-	/**
78
-	 * @var IUserManager
79
-	 */
80
-	protected $userManager;
81
-	/**
82
-	 * @var INotificationManager
83
-	 */
84
-	protected $notificationManager;
85
-	/**
86
-	 * @var string
87
-	 */
88
-	protected $dn;
89
-	/**
90
-	 * @var string
91
-	 */
92
-	protected $uid;
93
-	/**
94
-	 * @var string[]
95
-	 */
96
-	protected $refreshedFeatures = array();
97
-	/**
98
-	 * @var string
99
-	 */
100
-	protected $avatarImage;
101
-
102
-	/**
103
-	 * DB config keys for user preferences
104
-	 */
105
-	const USER_PREFKEY_FIRSTLOGIN  = 'firstLoginAccomplished';
106
-	const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh';
107
-
108
-	/**
109
-	 * @brief constructor, make sure the subclasses call this one!
110
-	 * @param string $username the internal username
111
-	 * @param string $dn the LDAP DN
112
-	 * @param IUserTools $access an instance that implements IUserTools for
113
-	 * LDAP interaction
114
-	 * @param IConfig $config
115
-	 * @param FilesystemHelper $fs
116
-	 * @param Image $image any empty instance
117
-	 * @param LogWrapper $log
118
-	 * @param IAvatarManager $avatarManager
119
-	 * @param IUserManager $userManager
120
-	 * @param INotificationManager $notificationManager
121
-	 */
122
-	public function __construct($username, $dn, IUserTools $access,
123
-		IConfig $config, FilesystemHelper $fs, Image $image,
124
-		LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager,
125
-		INotificationManager $notificationManager) {
49
+    /**
50
+     * @var IUserTools
51
+     */
52
+    protected $access;
53
+    /**
54
+     * @var Connection
55
+     */
56
+    protected $connection;
57
+    /**
58
+     * @var IConfig
59
+     */
60
+    protected $config;
61
+    /**
62
+     * @var FilesystemHelper
63
+     */
64
+    protected $fs;
65
+    /**
66
+     * @var Image
67
+     */
68
+    protected $image;
69
+    /**
70
+     * @var LogWrapper
71
+     */
72
+    protected $log;
73
+    /**
74
+     * @var IAvatarManager
75
+     */
76
+    protected $avatarManager;
77
+    /**
78
+     * @var IUserManager
79
+     */
80
+    protected $userManager;
81
+    /**
82
+     * @var INotificationManager
83
+     */
84
+    protected $notificationManager;
85
+    /**
86
+     * @var string
87
+     */
88
+    protected $dn;
89
+    /**
90
+     * @var string
91
+     */
92
+    protected $uid;
93
+    /**
94
+     * @var string[]
95
+     */
96
+    protected $refreshedFeatures = array();
97
+    /**
98
+     * @var string
99
+     */
100
+    protected $avatarImage;
101
+
102
+    /**
103
+     * DB config keys for user preferences
104
+     */
105
+    const USER_PREFKEY_FIRSTLOGIN  = 'firstLoginAccomplished';
106
+    const USER_PREFKEY_LASTREFRESH = 'lastFeatureRefresh';
107
+
108
+    /**
109
+     * @brief constructor, make sure the subclasses call this one!
110
+     * @param string $username the internal username
111
+     * @param string $dn the LDAP DN
112
+     * @param IUserTools $access an instance that implements IUserTools for
113
+     * LDAP interaction
114
+     * @param IConfig $config
115
+     * @param FilesystemHelper $fs
116
+     * @param Image $image any empty instance
117
+     * @param LogWrapper $log
118
+     * @param IAvatarManager $avatarManager
119
+     * @param IUserManager $userManager
120
+     * @param INotificationManager $notificationManager
121
+     */
122
+    public function __construct($username, $dn, IUserTools $access,
123
+        IConfig $config, FilesystemHelper $fs, Image $image,
124
+        LogWrapper $log, IAvatarManager $avatarManager, IUserManager $userManager,
125
+        INotificationManager $notificationManager) {
126 126
 	
127
-		if ($username === null) {
128
-			$log->log("uid for '$dn' must not be null!", Util::ERROR);
129
-			throw new \InvalidArgumentException('uid must not be null!');
130
-		} else if ($username === '') {
131
-			$log->log("uid for '$dn' must not be an empty string", Util::ERROR);
132
-			throw new \InvalidArgumentException('uid must not be an empty string!');
133
-		}
134
-
135
-		$this->access              = $access;
136
-		$this->connection          = $access->getConnection();
137
-		$this->config              = $config;
138
-		$this->fs                  = $fs;
139
-		$this->dn                  = $dn;
140
-		$this->uid                 = $username;
141
-		$this->image               = $image;
142
-		$this->log                 = $log;
143
-		$this->avatarManager       = $avatarManager;
144
-		$this->userManager         = $userManager;
145
-		$this->notificationManager = $notificationManager;
146
-
147
-		\OCP\Util::connectHook('OC_User', 'post_login', $this, 'handlePasswordExpiry');
148
-	}
149
-
150
-	/**
151
-	 * @brief updates properties like email, quota or avatar provided by LDAP
152
-	 * @return null
153
-	 */
154
-	public function update() {
155
-		if(is_null($this->dn)) {
156
-			return null;
157
-		}
158
-
159
-		$hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
160
-				self::USER_PREFKEY_FIRSTLOGIN, 0);
161
-
162
-		if($this->needsRefresh()) {
163
-			$this->updateEmail();
164
-			$this->updateQuota();
165
-			if($hasLoggedIn !== 0) {
166
-				//we do not need to try it, when the user has not been logged in
167
-				//before, because the file system will not be ready.
168
-				$this->updateAvatar();
169
-				//in order to get an avatar as soon as possible, mark the user
170
-				//as refreshed only when updating the avatar did happen
171
-				$this->markRefreshTime();
172
-			}
173
-		}
174
-	}
175
-
176
-	/**
177
-	 * processes results from LDAP for attributes as returned by getAttributesToRead()
178
-	 * @param array $ldapEntry the user entry as retrieved from LDAP
179
-	 */
180
-	public function processAttributes($ldapEntry) {
181
-		$this->markRefreshTime();
182
-		//Quota
183
-		$attr = strtolower($this->connection->ldapQuotaAttribute);
184
-		if(isset($ldapEntry[$attr])) {
185
-			$this->updateQuota($ldapEntry[$attr][0]);
186
-		} else {
187
-			if ($this->connection->ldapQuotaDefault !== '') {
188
-				$this->updateQuota();
189
-			}
190
-		}
191
-		unset($attr);
192
-
193
-		//displayName
194
-		$displayName = $displayName2 = '';
195
-		$attr = strtolower($this->connection->ldapUserDisplayName);
196
-		if(isset($ldapEntry[$attr])) {
197
-			$displayName = strval($ldapEntry[$attr][0]);
198
-		}
199
-		$attr = strtolower($this->connection->ldapUserDisplayName2);
200
-		if(isset($ldapEntry[$attr])) {
201
-			$displayName2 = strval($ldapEntry[$attr][0]);
202
-		}
203
-		if ($displayName !== '') {
204
-			$this->composeAndStoreDisplayName($displayName);
205
-			$this->access->cacheUserDisplayName(
206
-				$this->getUsername(),
207
-				$displayName,
208
-				$displayName2
209
-			);
210
-		}
211
-		unset($attr);
212
-
213
-		//Email
214
-		//email must be stored after displayname, because it would cause a user
215
-		//change event that will trigger fetching the display name again
216
-		$attr = strtolower($this->connection->ldapEmailAttribute);
217
-		if(isset($ldapEntry[$attr])) {
218
-			$this->updateEmail($ldapEntry[$attr][0]);
219
-		}
220
-		unset($attr);
221
-
222
-		// LDAP Username, needed for s2s sharing
223
-		if(isset($ldapEntry['uid'])) {
224
-			$this->storeLDAPUserName($ldapEntry['uid'][0]);
225
-		} else if(isset($ldapEntry['samaccountname'])) {
226
-			$this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
227
-		}
228
-
229
-		//homePath
230
-		if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
231
-			$attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
232
-			if(isset($ldapEntry[$attr])) {
233
-				$this->access->cacheUserHome(
234
-					$this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
235
-			}
236
-		}
237
-
238
-		//memberOf groups
239
-		$cacheKey = 'getMemberOf'.$this->getUsername();
240
-		$groups = false;
241
-		if(isset($ldapEntry['memberof'])) {
242
-			$groups = $ldapEntry['memberof'];
243
-		}
244
-		$this->connection->writeToCache($cacheKey, $groups);
245
-
246
-		//Avatar
247
-		$attrs = array('jpegphoto', 'thumbnailphoto');
248
-		foreach ($attrs as $attr)  {
249
-			if(isset($ldapEntry[$attr])) {
250
-				$this->avatarImage = $ldapEntry[$attr][0];
251
-				// the call to the method that saves the avatar in the file
252
-				// system must be postponed after the login. It is to ensure
253
-				// external mounts are mounted properly (e.g. with login
254
-				// credentials from the session).
255
-				\OCP\Util::connectHook('OC_User', 'post_login', $this, 'updateAvatarPostLogin');
256
-				break;
257
-			}
258
-		}
259
-	}
260
-
261
-	/**
262
-	 * @brief returns the LDAP DN of the user
263
-	 * @return string
264
-	 */
265
-	public function getDN() {
266
-		return $this->dn;
267
-	}
268
-
269
-	/**
270
-	 * @brief returns the Nextcloud internal username of the user
271
-	 * @return string
272
-	 */
273
-	public function getUsername() {
274
-		return $this->uid;
275
-	}
276
-
277
-	/**
278
-	 * returns the home directory of the user if specified by LDAP settings
279
-	 * @param string $valueFromLDAP
280
-	 * @return bool|string
281
-	 * @throws \Exception
282
-	 */
283
-	public function getHomePath($valueFromLDAP = null) {
284
-		$path = strval($valueFromLDAP);
285
-		$attr = null;
286
-
287
-		if (is_null($valueFromLDAP)
288
-		   && strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0
289
-		   && $this->access->connection->homeFolderNamingRule !== 'attr:')
290
-		{
291
-			$attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
292
-			$homedir = $this->access->readAttribute(
293
-				$this->access->username2dn($this->getUsername()), $attr);
294
-			if ($homedir && isset($homedir[0])) {
295
-				$path = $homedir[0];
296
-			}
297
-		}
298
-
299
-		if ($path !== '') {
300
-			//if attribute's value is an absolute path take this, otherwise append it to data dir
301
-			//check for / at the beginning or pattern c:\ resp. c:/
302
-			if(   '/' !== $path[0]
303
-			   && !(3 < strlen($path) && ctype_alpha($path[0])
304
-			       && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
305
-			) {
306
-				$path = $this->config->getSystemValue('datadirectory',
307
-						\OC::$SERVERROOT.'/data' ) . '/' . $path;
308
-			}
309
-			//we need it to store it in the DB as well in case a user gets
310
-			//deleted so we can clean up afterwards
311
-			$this->config->setUserValue(
312
-				$this->getUsername(), 'user_ldap', 'homePath', $path
313
-			);
314
-			return $path;
315
-		}
316
-
317
-		if(    !is_null($attr)
318
-			&& $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
319
-		) {
320
-			// a naming rule attribute is defined, but it doesn't exist for that LDAP user
321
-			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
322
-		}
323
-
324
-		//false will apply default behaviour as defined and done by OC_User
325
-		$this->config->setUserValue($this->getUsername(), 'user_ldap', 'homePath', '');
326
-		return false;
327
-	}
328
-
329
-	public function getMemberOfGroups() {
330
-		$cacheKey = 'getMemberOf'.$this->getUsername();
331
-		$memberOfGroups = $this->connection->getFromCache($cacheKey);
332
-		if(!is_null($memberOfGroups)) {
333
-			return $memberOfGroups;
334
-		}
335
-		$groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
336
-		$this->connection->writeToCache($cacheKey, $groupDNs);
337
-		return $groupDNs;
338
-	}
339
-
340
-	/**
341
-	 * @brief reads the image from LDAP that shall be used as Avatar
342
-	 * @return string data (provided by LDAP) | false
343
-	 */
344
-	public function getAvatarImage() {
345
-		if(!is_null($this->avatarImage)) {
346
-			return $this->avatarImage;
347
-		}
348
-
349
-		$this->avatarImage = false;
350
-		$attributes = array('jpegPhoto', 'thumbnailPhoto');
351
-		foreach($attributes as $attribute) {
352
-			$result = $this->access->readAttribute($this->dn, $attribute);
353
-			if($result !== false && is_array($result) && isset($result[0])) {
354
-				$this->avatarImage = $result[0];
355
-				break;
356
-			}
357
-		}
358
-
359
-		return $this->avatarImage;
360
-	}
361
-
362
-	/**
363
-	 * @brief marks the user as having logged in at least once
364
-	 * @return null
365
-	 */
366
-	public function markLogin() {
367
-		$this->config->setUserValue(
368
-			$this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1);
369
-	}
370
-
371
-	/**
372
-	 * @brief marks the time when user features like email have been updated
373
-	 * @return null
374
-	 */
375
-	public function markRefreshTime() {
376
-		$this->config->setUserValue(
377
-			$this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time());
378
-	}
379
-
380
-	/**
381
-	 * @brief checks whether user features needs to be updated again by
382
-	 * comparing the difference of time of the last refresh to now with the
383
-	 * desired interval
384
-	 * @return bool
385
-	 */
386
-	private function needsRefresh() {
387
-		$lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
388
-			self::USER_PREFKEY_LASTREFRESH, 0);
389
-
390
-		if((time() - intval($lastChecked)) < intval($this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) ) {
391
-			return false;
392
-		}
393
-		return  true;
394
-	}
395
-
396
-	/**
397
-	 * Stores a key-value pair in relation to this user
398
-	 *
399
-	 * @param string $key
400
-	 * @param string $value
401
-	 */
402
-	private function store($key, $value) {
403
-		$this->config->setUserValue($this->uid, 'user_ldap', $key, $value);
404
-	}
405
-
406
-	/**
407
-	 * Composes the display name and stores it in the database. The final
408
-	 * display name is returned.
409
-	 *
410
-	 * @param string $displayName
411
-	 * @param string $displayName2
412
-	 * @returns string the effective display name
413
-	 */
414
-	public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
415
-		$displayName2 = strval($displayName2);
416
-		if($displayName2 !== '') {
417
-			$displayName .= ' (' . $displayName2 . ')';
418
-		}
419
-		$this->store('displayName', $displayName);
420
-		return $displayName;
421
-	}
422
-
423
-	/**
424
-	 * Stores the LDAP Username in the Database
425
-	 * @param string $userName
426
-	 */
427
-	public function storeLDAPUserName($userName) {
428
-		$this->store('uid', $userName);
429
-	}
430
-
431
-	/**
432
-	 * @brief checks whether an update method specified by feature was run
433
-	 * already. If not, it will marked like this, because it is expected that
434
-	 * the method will be run, when false is returned.
435
-	 * @param string $feature email | quota | avatar (can be extended)
436
-	 * @return bool
437
-	 */
438
-	private function wasRefreshed($feature) {
439
-		if(isset($this->refreshedFeatures[$feature])) {
440
-			return true;
441
-		}
442
-		$this->refreshedFeatures[$feature] = 1;
443
-		return false;
444
-	}
445
-
446
-	/**
447
-	 * fetches the email from LDAP and stores it as Nextcloud user value
448
-	 * @param string $valueFromLDAP if known, to save an LDAP read request
449
-	 * @return null
450
-	 */
451
-	public function updateEmail($valueFromLDAP = null) {
452
-		if($this->wasRefreshed('email')) {
453
-			return;
454
-		}
455
-		$email = strval($valueFromLDAP);
456
-		if(is_null($valueFromLDAP)) {
457
-			$emailAttribute = $this->connection->ldapEmailAttribute;
458
-			if ($emailAttribute !== '') {
459
-				$aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
460
-				if(is_array($aEmail) && (count($aEmail) > 0)) {
461
-					$email = strval($aEmail[0]);
462
-				}
463
-			}
464
-		}
465
-		if ($email !== '') {
466
-			$user = $this->userManager->get($this->uid);
467
-			if (!is_null($user)) {
468
-				$currentEmail = strval($user->getEMailAddress());
469
-				if ($currentEmail !== $email) {
470
-					$user->setEMailAddress($email);
471
-				}
472
-			}
473
-		}
474
-	}
475
-
476
-	/**
477
-	 * Overall process goes as follow:
478
-	 * 1. fetch the quota from LDAP and check if it's parseable with the "verifyQuotaValue" function
479
-	 * 2. if the value can't be fetched, is empty or not parseable, use the default LDAP quota
480
-	 * 3. if the default LDAP quota can't be parsed, use the Nextcloud's default quota (use 'default')
481
-	 * 4. check if the target user exists and set the quota for the user.
482
-	 *
483
-	 * In order to improve performance and prevent an unwanted extra LDAP call, the $valueFromLDAP
484
-	 * parameter can be passed with the value of the attribute. This value will be considered as the
485
-	 * quota for the user coming from the LDAP server (step 1 of the process) It can be useful to
486
-	 * fetch all the user's attributes in one call and use the fetched values in this function.
487
-	 * The expected value for that parameter is a string describing the quota for the user. Valid
488
-	 * values are 'none' (unlimited), 'default' (the Nextcloud's default quota), '1234' (quota in
489
-	 * bytes), '1234 MB' (quota in MB - check the \OC_Helper::computerFileSize method for more info)
490
-	 *
491
-	 * fetches the quota from LDAP and stores it as Nextcloud user value
492
-	 * @param string $valueFromLDAP the quota attribute's value can be passed,
493
-	 * to save the readAttribute request
494
-	 * @return null
495
-	 */
496
-	public function updateQuota($valueFromLDAP = null) {
497
-		if($this->wasRefreshed('quota')) {
498
-			return;
499
-		}
500
-
501
-		$quota = false;
502
-		if(is_null($valueFromLDAP)) {
503
-			$quotaAttribute = $this->connection->ldapQuotaAttribute;
504
-			if ($quotaAttribute !== '') {
505
-				$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
506
-				if($aQuota && (count($aQuota) > 0)) {
507
-					if ($this->verifyQuotaValue($aQuota[0])) {
508
-						$quota = $aQuota[0];
509
-					} else {
510
-						$this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', \OCP\Util::WARN);
511
-					}
512
-				}
513
-			}
514
-		} else {
515
-			if ($this->verifyQuotaValue($valueFromLDAP)) {
516
-				$quota = $valueFromLDAP;
517
-			} else {
518
-				$this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', \OCP\Util::WARN);
519
-			}
520
-		}
521
-
522
-		if ($quota === false) {
523
-			// quota not found using the LDAP attribute (or not parseable). Try the default quota
524
-			$defaultQuota = $this->connection->ldapQuotaDefault;
525
-			if ($this->verifyQuotaValue($defaultQuota)) {
526
-				$quota = $defaultQuota;
527
-			}
528
-		}
529
-
530
-		$targetUser = $this->userManager->get($this->uid);
531
-		if ($targetUser) {
532
-			if($quota !== false) {
533
-				$targetUser->setQuota($quota);
534
-			} else {
535
-				$this->log->log('not suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', \OCP\Util::WARN);
536
-			}
537
-		} else {
538
-			$this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', \OCP\Util::ERROR);
539
-		}
540
-	}
541
-
542
-	private function verifyQuotaValue($quotaValue) {
543
-		return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
544
-	}
545
-
546
-	/**
547
-	 * called by a post_login hook to save the avatar picture
548
-	 *
549
-	 * @param array $params
550
-	 */
551
-	public function updateAvatarPostLogin($params) {
552
-		if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
553
-			$this->updateAvatar();
554
-		}
555
-	}
556
-
557
-	/**
558
-	 * @brief attempts to get an image from LDAP and sets it as Nextcloud avatar
559
-	 * @return null
560
-	 */
561
-	public function updateAvatar() {
562
-		if($this->wasRefreshed('avatar')) {
563
-			return;
564
-		}
565
-		$avatarImage = $this->getAvatarImage();
566
-		if($avatarImage === false) {
567
-			//not set, nothing left to do;
568
-			return;
569
-		}
570
-		$this->image->loadFromBase64(base64_encode($avatarImage));
571
-		$this->setOwnCloudAvatar();
572
-	}
573
-
574
-	/**
575
-	 * @brief sets an image as Nextcloud avatar
576
-	 * @return null
577
-	 */
578
-	private function setOwnCloudAvatar() {
579
-		if(!$this->image->valid()) {
580
-			$this->log->log('jpegPhoto data invalid for '.$this->dn, \OCP\Util::ERROR);
581
-			return;
582
-		}
583
-		//make sure it is a square and not bigger than 128x128
584
-		$size = min(array($this->image->width(), $this->image->height(), 128));
585
-		if(!$this->image->centerCrop($size)) {
586
-			$this->log->log('croping image for avatar failed for '.$this->dn, \OCP\Util::ERROR);
587
-			return;
588
-		}
589
-
590
-		if(!$this->fs->isLoaded()) {
591
-			$this->fs->setup($this->uid);
592
-		}
593
-
594
-		try {
595
-			$avatar = $this->avatarManager->getAvatar($this->uid);
596
-			$avatar->set($this->image);
597
-		} catch (\Exception $e) {
598
-			\OC::$server->getLogger()->logException($e, [
599
-				'message' => 'Could not set avatar for ' . $this->dn,
600
-				'level' => \OCP\Util::INFO,
601
-				'app' => 'user_ldap',
602
-			]);
603
-		}
604
-	}
605
-
606
-	/**
607
-	 * called by a post_login hook to handle password expiry
608
-	 *
609
-	 * @param array $params
610
-	 */
611
-	public function handlePasswordExpiry($params) {
612
-		$ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
613
-		if (empty($ppolicyDN) || (intval($this->connection->turnOnPasswordChange) !== 1)) {
614
-			return;//password expiry handling disabled
615
-		}
616
-		$uid = $params['uid'];
617
-		if(isset($uid) && $uid === $this->getUsername()) {
618
-			//retrieve relevant user attributes
619
-			$result = $this->access->search('objectclass=*', $this->dn, ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
127
+        if ($username === null) {
128
+            $log->log("uid for '$dn' must not be null!", Util::ERROR);
129
+            throw new \InvalidArgumentException('uid must not be null!');
130
+        } else if ($username === '') {
131
+            $log->log("uid for '$dn' must not be an empty string", Util::ERROR);
132
+            throw new \InvalidArgumentException('uid must not be an empty string!');
133
+        }
134
+
135
+        $this->access              = $access;
136
+        $this->connection          = $access->getConnection();
137
+        $this->config              = $config;
138
+        $this->fs                  = $fs;
139
+        $this->dn                  = $dn;
140
+        $this->uid                 = $username;
141
+        $this->image               = $image;
142
+        $this->log                 = $log;
143
+        $this->avatarManager       = $avatarManager;
144
+        $this->userManager         = $userManager;
145
+        $this->notificationManager = $notificationManager;
146
+
147
+        \OCP\Util::connectHook('OC_User', 'post_login', $this, 'handlePasswordExpiry');
148
+    }
149
+
150
+    /**
151
+     * @brief updates properties like email, quota or avatar provided by LDAP
152
+     * @return null
153
+     */
154
+    public function update() {
155
+        if(is_null($this->dn)) {
156
+            return null;
157
+        }
158
+
159
+        $hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
160
+                self::USER_PREFKEY_FIRSTLOGIN, 0);
161
+
162
+        if($this->needsRefresh()) {
163
+            $this->updateEmail();
164
+            $this->updateQuota();
165
+            if($hasLoggedIn !== 0) {
166
+                //we do not need to try it, when the user has not been logged in
167
+                //before, because the file system will not be ready.
168
+                $this->updateAvatar();
169
+                //in order to get an avatar as soon as possible, mark the user
170
+                //as refreshed only when updating the avatar did happen
171
+                $this->markRefreshTime();
172
+            }
173
+        }
174
+    }
175
+
176
+    /**
177
+     * processes results from LDAP for attributes as returned by getAttributesToRead()
178
+     * @param array $ldapEntry the user entry as retrieved from LDAP
179
+     */
180
+    public function processAttributes($ldapEntry) {
181
+        $this->markRefreshTime();
182
+        //Quota
183
+        $attr = strtolower($this->connection->ldapQuotaAttribute);
184
+        if(isset($ldapEntry[$attr])) {
185
+            $this->updateQuota($ldapEntry[$attr][0]);
186
+        } else {
187
+            if ($this->connection->ldapQuotaDefault !== '') {
188
+                $this->updateQuota();
189
+            }
190
+        }
191
+        unset($attr);
192
+
193
+        //displayName
194
+        $displayName = $displayName2 = '';
195
+        $attr = strtolower($this->connection->ldapUserDisplayName);
196
+        if(isset($ldapEntry[$attr])) {
197
+            $displayName = strval($ldapEntry[$attr][0]);
198
+        }
199
+        $attr = strtolower($this->connection->ldapUserDisplayName2);
200
+        if(isset($ldapEntry[$attr])) {
201
+            $displayName2 = strval($ldapEntry[$attr][0]);
202
+        }
203
+        if ($displayName !== '') {
204
+            $this->composeAndStoreDisplayName($displayName);
205
+            $this->access->cacheUserDisplayName(
206
+                $this->getUsername(),
207
+                $displayName,
208
+                $displayName2
209
+            );
210
+        }
211
+        unset($attr);
212
+
213
+        //Email
214
+        //email must be stored after displayname, because it would cause a user
215
+        //change event that will trigger fetching the display name again
216
+        $attr = strtolower($this->connection->ldapEmailAttribute);
217
+        if(isset($ldapEntry[$attr])) {
218
+            $this->updateEmail($ldapEntry[$attr][0]);
219
+        }
220
+        unset($attr);
221
+
222
+        // LDAP Username, needed for s2s sharing
223
+        if(isset($ldapEntry['uid'])) {
224
+            $this->storeLDAPUserName($ldapEntry['uid'][0]);
225
+        } else if(isset($ldapEntry['samaccountname'])) {
226
+            $this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
227
+        }
228
+
229
+        //homePath
230
+        if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
231
+            $attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
232
+            if(isset($ldapEntry[$attr])) {
233
+                $this->access->cacheUserHome(
234
+                    $this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
235
+            }
236
+        }
237
+
238
+        //memberOf groups
239
+        $cacheKey = 'getMemberOf'.$this->getUsername();
240
+        $groups = false;
241
+        if(isset($ldapEntry['memberof'])) {
242
+            $groups = $ldapEntry['memberof'];
243
+        }
244
+        $this->connection->writeToCache($cacheKey, $groups);
245
+
246
+        //Avatar
247
+        $attrs = array('jpegphoto', 'thumbnailphoto');
248
+        foreach ($attrs as $attr)  {
249
+            if(isset($ldapEntry[$attr])) {
250
+                $this->avatarImage = $ldapEntry[$attr][0];
251
+                // the call to the method that saves the avatar in the file
252
+                // system must be postponed after the login. It is to ensure
253
+                // external mounts are mounted properly (e.g. with login
254
+                // credentials from the session).
255
+                \OCP\Util::connectHook('OC_User', 'post_login', $this, 'updateAvatarPostLogin');
256
+                break;
257
+            }
258
+        }
259
+    }
260
+
261
+    /**
262
+     * @brief returns the LDAP DN of the user
263
+     * @return string
264
+     */
265
+    public function getDN() {
266
+        return $this->dn;
267
+    }
268
+
269
+    /**
270
+     * @brief returns the Nextcloud internal username of the user
271
+     * @return string
272
+     */
273
+    public function getUsername() {
274
+        return $this->uid;
275
+    }
276
+
277
+    /**
278
+     * returns the home directory of the user if specified by LDAP settings
279
+     * @param string $valueFromLDAP
280
+     * @return bool|string
281
+     * @throws \Exception
282
+     */
283
+    public function getHomePath($valueFromLDAP = null) {
284
+        $path = strval($valueFromLDAP);
285
+        $attr = null;
286
+
287
+        if (is_null($valueFromLDAP)
288
+           && strpos($this->access->connection->homeFolderNamingRule, 'attr:') === 0
289
+           && $this->access->connection->homeFolderNamingRule !== 'attr:')
290
+        {
291
+            $attr = substr($this->access->connection->homeFolderNamingRule, strlen('attr:'));
292
+            $homedir = $this->access->readAttribute(
293
+                $this->access->username2dn($this->getUsername()), $attr);
294
+            if ($homedir && isset($homedir[0])) {
295
+                $path = $homedir[0];
296
+            }
297
+        }
298
+
299
+        if ($path !== '') {
300
+            //if attribute's value is an absolute path take this, otherwise append it to data dir
301
+            //check for / at the beginning or pattern c:\ resp. c:/
302
+            if(   '/' !== $path[0]
303
+               && !(3 < strlen($path) && ctype_alpha($path[0])
304
+                   && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
305
+            ) {
306
+                $path = $this->config->getSystemValue('datadirectory',
307
+                        \OC::$SERVERROOT.'/data' ) . '/' . $path;
308
+            }
309
+            //we need it to store it in the DB as well in case a user gets
310
+            //deleted so we can clean up afterwards
311
+            $this->config->setUserValue(
312
+                $this->getUsername(), 'user_ldap', 'homePath', $path
313
+            );
314
+            return $path;
315
+        }
316
+
317
+        if(    !is_null($attr)
318
+            && $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
319
+        ) {
320
+            // a naming rule attribute is defined, but it doesn't exist for that LDAP user
321
+            throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
322
+        }
323
+
324
+        //false will apply default behaviour as defined and done by OC_User
325
+        $this->config->setUserValue($this->getUsername(), 'user_ldap', 'homePath', '');
326
+        return false;
327
+    }
328
+
329
+    public function getMemberOfGroups() {
330
+        $cacheKey = 'getMemberOf'.$this->getUsername();
331
+        $memberOfGroups = $this->connection->getFromCache($cacheKey);
332
+        if(!is_null($memberOfGroups)) {
333
+            return $memberOfGroups;
334
+        }
335
+        $groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
336
+        $this->connection->writeToCache($cacheKey, $groupDNs);
337
+        return $groupDNs;
338
+    }
339
+
340
+    /**
341
+     * @brief reads the image from LDAP that shall be used as Avatar
342
+     * @return string data (provided by LDAP) | false
343
+     */
344
+    public function getAvatarImage() {
345
+        if(!is_null($this->avatarImage)) {
346
+            return $this->avatarImage;
347
+        }
348
+
349
+        $this->avatarImage = false;
350
+        $attributes = array('jpegPhoto', 'thumbnailPhoto');
351
+        foreach($attributes as $attribute) {
352
+            $result = $this->access->readAttribute($this->dn, $attribute);
353
+            if($result !== false && is_array($result) && isset($result[0])) {
354
+                $this->avatarImage = $result[0];
355
+                break;
356
+            }
357
+        }
358
+
359
+        return $this->avatarImage;
360
+    }
361
+
362
+    /**
363
+     * @brief marks the user as having logged in at least once
364
+     * @return null
365
+     */
366
+    public function markLogin() {
367
+        $this->config->setUserValue(
368
+            $this->uid, 'user_ldap', self::USER_PREFKEY_FIRSTLOGIN, 1);
369
+    }
370
+
371
+    /**
372
+     * @brief marks the time when user features like email have been updated
373
+     * @return null
374
+     */
375
+    public function markRefreshTime() {
376
+        $this->config->setUserValue(
377
+            $this->uid, 'user_ldap', self::USER_PREFKEY_LASTREFRESH, time());
378
+    }
379
+
380
+    /**
381
+     * @brief checks whether user features needs to be updated again by
382
+     * comparing the difference of time of the last refresh to now with the
383
+     * desired interval
384
+     * @return bool
385
+     */
386
+    private function needsRefresh() {
387
+        $lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
388
+            self::USER_PREFKEY_LASTREFRESH, 0);
389
+
390
+        if((time() - intval($lastChecked)) < intval($this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) ) {
391
+            return false;
392
+        }
393
+        return  true;
394
+    }
395
+
396
+    /**
397
+     * Stores a key-value pair in relation to this user
398
+     *
399
+     * @param string $key
400
+     * @param string $value
401
+     */
402
+    private function store($key, $value) {
403
+        $this->config->setUserValue($this->uid, 'user_ldap', $key, $value);
404
+    }
405
+
406
+    /**
407
+     * Composes the display name and stores it in the database. The final
408
+     * display name is returned.
409
+     *
410
+     * @param string $displayName
411
+     * @param string $displayName2
412
+     * @returns string the effective display name
413
+     */
414
+    public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
415
+        $displayName2 = strval($displayName2);
416
+        if($displayName2 !== '') {
417
+            $displayName .= ' (' . $displayName2 . ')';
418
+        }
419
+        $this->store('displayName', $displayName);
420
+        return $displayName;
421
+    }
422
+
423
+    /**
424
+     * Stores the LDAP Username in the Database
425
+     * @param string $userName
426
+     */
427
+    public function storeLDAPUserName($userName) {
428
+        $this->store('uid', $userName);
429
+    }
430
+
431
+    /**
432
+     * @brief checks whether an update method specified by feature was run
433
+     * already. If not, it will marked like this, because it is expected that
434
+     * the method will be run, when false is returned.
435
+     * @param string $feature email | quota | avatar (can be extended)
436
+     * @return bool
437
+     */
438
+    private function wasRefreshed($feature) {
439
+        if(isset($this->refreshedFeatures[$feature])) {
440
+            return true;
441
+        }
442
+        $this->refreshedFeatures[$feature] = 1;
443
+        return false;
444
+    }
445
+
446
+    /**
447
+     * fetches the email from LDAP and stores it as Nextcloud user value
448
+     * @param string $valueFromLDAP if known, to save an LDAP read request
449
+     * @return null
450
+     */
451
+    public function updateEmail($valueFromLDAP = null) {
452
+        if($this->wasRefreshed('email')) {
453
+            return;
454
+        }
455
+        $email = strval($valueFromLDAP);
456
+        if(is_null($valueFromLDAP)) {
457
+            $emailAttribute = $this->connection->ldapEmailAttribute;
458
+            if ($emailAttribute !== '') {
459
+                $aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
460
+                if(is_array($aEmail) && (count($aEmail) > 0)) {
461
+                    $email = strval($aEmail[0]);
462
+                }
463
+            }
464
+        }
465
+        if ($email !== '') {
466
+            $user = $this->userManager->get($this->uid);
467
+            if (!is_null($user)) {
468
+                $currentEmail = strval($user->getEMailAddress());
469
+                if ($currentEmail !== $email) {
470
+                    $user->setEMailAddress($email);
471
+                }
472
+            }
473
+        }
474
+    }
475
+
476
+    /**
477
+     * Overall process goes as follow:
478
+     * 1. fetch the quota from LDAP and check if it's parseable with the "verifyQuotaValue" function
479
+     * 2. if the value can't be fetched, is empty or not parseable, use the default LDAP quota
480
+     * 3. if the default LDAP quota can't be parsed, use the Nextcloud's default quota (use 'default')
481
+     * 4. check if the target user exists and set the quota for the user.
482
+     *
483
+     * In order to improve performance and prevent an unwanted extra LDAP call, the $valueFromLDAP
484
+     * parameter can be passed with the value of the attribute. This value will be considered as the
485
+     * quota for the user coming from the LDAP server (step 1 of the process) It can be useful to
486
+     * fetch all the user's attributes in one call and use the fetched values in this function.
487
+     * The expected value for that parameter is a string describing the quota for the user. Valid
488
+     * values are 'none' (unlimited), 'default' (the Nextcloud's default quota), '1234' (quota in
489
+     * bytes), '1234 MB' (quota in MB - check the \OC_Helper::computerFileSize method for more info)
490
+     *
491
+     * fetches the quota from LDAP and stores it as Nextcloud user value
492
+     * @param string $valueFromLDAP the quota attribute's value can be passed,
493
+     * to save the readAttribute request
494
+     * @return null
495
+     */
496
+    public function updateQuota($valueFromLDAP = null) {
497
+        if($this->wasRefreshed('quota')) {
498
+            return;
499
+        }
500
+
501
+        $quota = false;
502
+        if(is_null($valueFromLDAP)) {
503
+            $quotaAttribute = $this->connection->ldapQuotaAttribute;
504
+            if ($quotaAttribute !== '') {
505
+                $aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
506
+                if($aQuota && (count($aQuota) > 0)) {
507
+                    if ($this->verifyQuotaValue($aQuota[0])) {
508
+                        $quota = $aQuota[0];
509
+                    } else {
510
+                        $this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', \OCP\Util::WARN);
511
+                    }
512
+                }
513
+            }
514
+        } else {
515
+            if ($this->verifyQuotaValue($valueFromLDAP)) {
516
+                $quota = $valueFromLDAP;
517
+            } else {
518
+                $this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', \OCP\Util::WARN);
519
+            }
520
+        }
521
+
522
+        if ($quota === false) {
523
+            // quota not found using the LDAP attribute (or not parseable). Try the default quota
524
+            $defaultQuota = $this->connection->ldapQuotaDefault;
525
+            if ($this->verifyQuotaValue($defaultQuota)) {
526
+                $quota = $defaultQuota;
527
+            }
528
+        }
529
+
530
+        $targetUser = $this->userManager->get($this->uid);
531
+        if ($targetUser) {
532
+            if($quota !== false) {
533
+                $targetUser->setQuota($quota);
534
+            } else {
535
+                $this->log->log('not suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', \OCP\Util::WARN);
536
+            }
537
+        } else {
538
+            $this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', \OCP\Util::ERROR);
539
+        }
540
+    }
541
+
542
+    private function verifyQuotaValue($quotaValue) {
543
+        return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
544
+    }
545
+
546
+    /**
547
+     * called by a post_login hook to save the avatar picture
548
+     *
549
+     * @param array $params
550
+     */
551
+    public function updateAvatarPostLogin($params) {
552
+        if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
553
+            $this->updateAvatar();
554
+        }
555
+    }
556
+
557
+    /**
558
+     * @brief attempts to get an image from LDAP and sets it as Nextcloud avatar
559
+     * @return null
560
+     */
561
+    public function updateAvatar() {
562
+        if($this->wasRefreshed('avatar')) {
563
+            return;
564
+        }
565
+        $avatarImage = $this->getAvatarImage();
566
+        if($avatarImage === false) {
567
+            //not set, nothing left to do;
568
+            return;
569
+        }
570
+        $this->image->loadFromBase64(base64_encode($avatarImage));
571
+        $this->setOwnCloudAvatar();
572
+    }
573
+
574
+    /**
575
+     * @brief sets an image as Nextcloud avatar
576
+     * @return null
577
+     */
578
+    private function setOwnCloudAvatar() {
579
+        if(!$this->image->valid()) {
580
+            $this->log->log('jpegPhoto data invalid for '.$this->dn, \OCP\Util::ERROR);
581
+            return;
582
+        }
583
+        //make sure it is a square and not bigger than 128x128
584
+        $size = min(array($this->image->width(), $this->image->height(), 128));
585
+        if(!$this->image->centerCrop($size)) {
586
+            $this->log->log('croping image for avatar failed for '.$this->dn, \OCP\Util::ERROR);
587
+            return;
588
+        }
589
+
590
+        if(!$this->fs->isLoaded()) {
591
+            $this->fs->setup($this->uid);
592
+        }
593
+
594
+        try {
595
+            $avatar = $this->avatarManager->getAvatar($this->uid);
596
+            $avatar->set($this->image);
597
+        } catch (\Exception $e) {
598
+            \OC::$server->getLogger()->logException($e, [
599
+                'message' => 'Could not set avatar for ' . $this->dn,
600
+                'level' => \OCP\Util::INFO,
601
+                'app' => 'user_ldap',
602
+            ]);
603
+        }
604
+    }
605
+
606
+    /**
607
+     * called by a post_login hook to handle password expiry
608
+     *
609
+     * @param array $params
610
+     */
611
+    public function handlePasswordExpiry($params) {
612
+        $ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
613
+        if (empty($ppolicyDN) || (intval($this->connection->turnOnPasswordChange) !== 1)) {
614
+            return;//password expiry handling disabled
615
+        }
616
+        $uid = $params['uid'];
617
+        if(isset($uid) && $uid === $this->getUsername()) {
618
+            //retrieve relevant user attributes
619
+            $result = $this->access->search('objectclass=*', $this->dn, ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
620 620
 			
621
-			if(array_key_exists('pwdpolicysubentry', $result[0])) {
622
-				$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
623
-				if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
624
-					$ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
625
-				}
626
-			}
621
+            if(array_key_exists('pwdpolicysubentry', $result[0])) {
622
+                $pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
623
+                if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
624
+                    $ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
625
+                }
626
+            }
627 627
 			
628
-			$pwdGraceUseTime = array_key_exists('pwdgraceusetime', $result[0]) ? $result[0]['pwdgraceusetime'] : null;
629
-			$pwdReset = array_key_exists('pwdreset', $result[0]) ? $result[0]['pwdreset'] : null;
630
-			$pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
628
+            $pwdGraceUseTime = array_key_exists('pwdgraceusetime', $result[0]) ? $result[0]['pwdgraceusetime'] : null;
629
+            $pwdReset = array_key_exists('pwdreset', $result[0]) ? $result[0]['pwdreset'] : null;
630
+            $pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
631 631
 			
632
-			//retrieve relevant password policy attributes
633
-			$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
634
-			$result = $this->connection->getFromCache($cacheKey);
635
-			if(is_null($result)) {
636
-				$result = $this->access->search('objectclass=*', $ppolicyDN, ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
637
-				$this->connection->writeToCache($cacheKey, $result);
638
-			}
632
+            //retrieve relevant password policy attributes
633
+            $cacheKey = 'ppolicyAttributes' . $ppolicyDN;
634
+            $result = $this->connection->getFromCache($cacheKey);
635
+            if(is_null($result)) {
636
+                $result = $this->access->search('objectclass=*', $ppolicyDN, ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
637
+                $this->connection->writeToCache($cacheKey, $result);
638
+            }
639 639
 			
640
-			$pwdGraceAuthNLimit = array_key_exists('pwdgraceauthnlimit', $result[0]) ? $result[0]['pwdgraceauthnlimit'] : null;
641
-			$pwdMaxAge = array_key_exists('pwdmaxage', $result[0]) ? $result[0]['pwdmaxage'] : null;
642
-			$pwdExpireWarning = array_key_exists('pwdexpirewarning', $result[0]) ? $result[0]['pwdexpirewarning'] : null;
640
+            $pwdGraceAuthNLimit = array_key_exists('pwdgraceauthnlimit', $result[0]) ? $result[0]['pwdgraceauthnlimit'] : null;
641
+            $pwdMaxAge = array_key_exists('pwdmaxage', $result[0]) ? $result[0]['pwdmaxage'] : null;
642
+            $pwdExpireWarning = array_key_exists('pwdexpirewarning', $result[0]) ? $result[0]['pwdexpirewarning'] : null;
643 643
 			
644
-			//handle grace login
645
-			$pwdGraceUseTimeCount = count($pwdGraceUseTime);
646
-			if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
647
-				if($pwdGraceAuthNLimit 
648
-					&& (count($pwdGraceAuthNLimit) > 0)
649
-					&&($pwdGraceUseTimeCount < intval($pwdGraceAuthNLimit[0]))) { //at least one more grace login available?
650
-					$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
651
-					header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
652
-					'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
653
-				} else { //no more grace login available
654
-					header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
655
-					'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
656
-				}
657
-				exit();
658
-			}
659
-			//handle pwdReset attribute
660
-			if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
661
-				$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
662
-				header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
663
-				'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
664
-				exit();
665
-			}
666
-			//handle password expiry warning
667
-			if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
668
-				if($pwdMaxAge && (count($pwdMaxAge) > 0)
669
-					&& $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
670
-					$pwdMaxAgeInt = intval($pwdMaxAge[0]);
671
-					$pwdExpireWarningInt = intval($pwdExpireWarning[0]);
672
-					if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
673
-						$pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
674
-						$pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
675
-						$currentDateTime = new \DateTime();
676
-						$secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
677
-						if($secondsToExpiry <= $pwdExpireWarningInt) {
678
-							//remove last password expiry warning if any
679
-							$notification = $this->notificationManager->createNotification();
680
-							$notification->setApp('user_ldap')
681
-								->setUser($uid)
682
-								->setObject('pwd_exp_warn', $uid)
683
-							;
684
-							$this->notificationManager->markProcessed($notification);
685
-							//create new password expiry warning
686
-							$notification = $this->notificationManager->createNotification();
687
-							$notification->setApp('user_ldap')
688
-								->setUser($uid)
689
-								->setDateTime($currentDateTime)
690
-								->setObject('pwd_exp_warn', $uid) 
691
-								->setSubject('pwd_exp_warn_days', [(int) ceil($secondsToExpiry / 60 / 60 / 24)])
692
-							;
693
-							$this->notificationManager->notify($notification);
694
-						}
695
-					}
696
-				}
697
-			}
698
-		}
699
-	}
644
+            //handle grace login
645
+            $pwdGraceUseTimeCount = count($pwdGraceUseTime);
646
+            if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
647
+                if($pwdGraceAuthNLimit 
648
+                    && (count($pwdGraceAuthNLimit) > 0)
649
+                    &&($pwdGraceUseTimeCount < intval($pwdGraceAuthNLimit[0]))) { //at least one more grace login available?
650
+                    $this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
651
+                    header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
652
+                    'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
653
+                } else { //no more grace login available
654
+                    header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
655
+                    'user_ldap.renewPassword.showLoginFormInvalidPassword', array('user' => $uid)));
656
+                }
657
+                exit();
658
+            }
659
+            //handle pwdReset attribute
660
+            if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
661
+                $this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
662
+                header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
663
+                'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
664
+                exit();
665
+            }
666
+            //handle password expiry warning
667
+            if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
668
+                if($pwdMaxAge && (count($pwdMaxAge) > 0)
669
+                    && $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
670
+                    $pwdMaxAgeInt = intval($pwdMaxAge[0]);
671
+                    $pwdExpireWarningInt = intval($pwdExpireWarning[0]);
672
+                    if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
673
+                        $pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
674
+                        $pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
675
+                        $currentDateTime = new \DateTime();
676
+                        $secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
677
+                        if($secondsToExpiry <= $pwdExpireWarningInt) {
678
+                            //remove last password expiry warning if any
679
+                            $notification = $this->notificationManager->createNotification();
680
+                            $notification->setApp('user_ldap')
681
+                                ->setUser($uid)
682
+                                ->setObject('pwd_exp_warn', $uid)
683
+                            ;
684
+                            $this->notificationManager->markProcessed($notification);
685
+                            //create new password expiry warning
686
+                            $notification = $this->notificationManager->createNotification();
687
+                            $notification->setApp('user_ldap')
688
+                                ->setUser($uid)
689
+                                ->setDateTime($currentDateTime)
690
+                                ->setObject('pwd_exp_warn', $uid) 
691
+                                ->setSubject('pwd_exp_warn_days', [(int) ceil($secondsToExpiry / 60 / 60 / 24)])
692
+                            ;
693
+                            $this->notificationManager->notify($notification);
694
+                        }
695
+                    }
696
+                }
697
+            }
698
+        }
699
+    }
700 700
 }
Please login to merge, or discard this patch.
Spacing   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -152,17 +152,17 @@  discard block
 block discarded – undo
152 152
 	 * @return null
153 153
 	 */
154 154
 	public function update() {
155
-		if(is_null($this->dn)) {
155
+		if (is_null($this->dn)) {
156 156
 			return null;
157 157
 		}
158 158
 
159 159
 		$hasLoggedIn = $this->config->getUserValue($this->uid, 'user_ldap',
160 160
 				self::USER_PREFKEY_FIRSTLOGIN, 0);
161 161
 
162
-		if($this->needsRefresh()) {
162
+		if ($this->needsRefresh()) {
163 163
 			$this->updateEmail();
164 164
 			$this->updateQuota();
165
-			if($hasLoggedIn !== 0) {
165
+			if ($hasLoggedIn !== 0) {
166 166
 				//we do not need to try it, when the user has not been logged in
167 167
 				//before, because the file system will not be ready.
168 168
 				$this->updateAvatar();
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
 		$this->markRefreshTime();
182 182
 		//Quota
183 183
 		$attr = strtolower($this->connection->ldapQuotaAttribute);
184
-		if(isset($ldapEntry[$attr])) {
184
+		if (isset($ldapEntry[$attr])) {
185 185
 			$this->updateQuota($ldapEntry[$attr][0]);
186 186
 		} else {
187 187
 			if ($this->connection->ldapQuotaDefault !== '') {
@@ -193,11 +193,11 @@  discard block
 block discarded – undo
193 193
 		//displayName
194 194
 		$displayName = $displayName2 = '';
195 195
 		$attr = strtolower($this->connection->ldapUserDisplayName);
196
-		if(isset($ldapEntry[$attr])) {
196
+		if (isset($ldapEntry[$attr])) {
197 197
 			$displayName = strval($ldapEntry[$attr][0]);
198 198
 		}
199 199
 		$attr = strtolower($this->connection->ldapUserDisplayName2);
200
-		if(isset($ldapEntry[$attr])) {
200
+		if (isset($ldapEntry[$attr])) {
201 201
 			$displayName2 = strval($ldapEntry[$attr][0]);
202 202
 		}
203 203
 		if ($displayName !== '') {
@@ -214,22 +214,22 @@  discard block
 block discarded – undo
214 214
 		//email must be stored after displayname, because it would cause a user
215 215
 		//change event that will trigger fetching the display name again
216 216
 		$attr = strtolower($this->connection->ldapEmailAttribute);
217
-		if(isset($ldapEntry[$attr])) {
217
+		if (isset($ldapEntry[$attr])) {
218 218
 			$this->updateEmail($ldapEntry[$attr][0]);
219 219
 		}
220 220
 		unset($attr);
221 221
 
222 222
 		// LDAP Username, needed for s2s sharing
223
-		if(isset($ldapEntry['uid'])) {
223
+		if (isset($ldapEntry['uid'])) {
224 224
 			$this->storeLDAPUserName($ldapEntry['uid'][0]);
225
-		} else if(isset($ldapEntry['samaccountname'])) {
225
+		} else if (isset($ldapEntry['samaccountname'])) {
226 226
 			$this->storeLDAPUserName($ldapEntry['samaccountname'][0]);
227 227
 		}
228 228
 
229 229
 		//homePath
230
-		if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
230
+		if (strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
231 231
 			$attr = strtolower(substr($this->connection->homeFolderNamingRule, strlen('attr:')));
232
-			if(isset($ldapEntry[$attr])) {
232
+			if (isset($ldapEntry[$attr])) {
233 233
 				$this->access->cacheUserHome(
234 234
 					$this->getUsername(), $this->getHomePath($ldapEntry[$attr][0]));
235 235
 			}
@@ -238,15 +238,15 @@  discard block
 block discarded – undo
238 238
 		//memberOf groups
239 239
 		$cacheKey = 'getMemberOf'.$this->getUsername();
240 240
 		$groups = false;
241
-		if(isset($ldapEntry['memberof'])) {
241
+		if (isset($ldapEntry['memberof'])) {
242 242
 			$groups = $ldapEntry['memberof'];
243 243
 		}
244 244
 		$this->connection->writeToCache($cacheKey, $groups);
245 245
 
246 246
 		//Avatar
247 247
 		$attrs = array('jpegphoto', 'thumbnailphoto');
248
-		foreach ($attrs as $attr)  {
249
-			if(isset($ldapEntry[$attr])) {
248
+		foreach ($attrs as $attr) {
249
+			if (isset($ldapEntry[$attr])) {
250 250
 				$this->avatarImage = $ldapEntry[$attr][0];
251 251
 				// the call to the method that saves the avatar in the file
252 252
 				// system must be postponed after the login. It is to ensure
@@ -299,12 +299,12 @@  discard block
 block discarded – undo
299 299
 		if ($path !== '') {
300 300
 			//if attribute's value is an absolute path take this, otherwise append it to data dir
301 301
 			//check for / at the beginning or pattern c:\ resp. c:/
302
-			if(   '/' !== $path[0]
302
+			if ('/' !== $path[0]
303 303
 			   && !(3 < strlen($path) && ctype_alpha($path[0])
304 304
 			       && $path[1] === ':' && ('\\' === $path[2] || '/' === $path[2]))
305 305
 			) {
306 306
 				$path = $this->config->getSystemValue('datadirectory',
307
-						\OC::$SERVERROOT.'/data' ) . '/' . $path;
307
+						\OC::$SERVERROOT.'/data').'/'.$path;
308 308
 			}
309 309
 			//we need it to store it in the DB as well in case a user gets
310 310
 			//deleted so we can clean up afterwards
@@ -314,11 +314,11 @@  discard block
 block discarded – undo
314 314
 			return $path;
315 315
 		}
316 316
 
317
-		if(    !is_null($attr)
317
+		if (!is_null($attr)
318 318
 			&& $this->config->getAppValue('user_ldap', 'enforce_home_folder_naming_rule', true)
319 319
 		) {
320 320
 			// a naming rule attribute is defined, but it doesn't exist for that LDAP user
321
-			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: ' . $this->getUsername());
321
+			throw new \Exception('Home dir attribute can\'t be read from LDAP for uid: '.$this->getUsername());
322 322
 		}
323 323
 
324 324
 		//false will apply default behaviour as defined and done by OC_User
@@ -329,7 +329,7 @@  discard block
 block discarded – undo
329 329
 	public function getMemberOfGroups() {
330 330
 		$cacheKey = 'getMemberOf'.$this->getUsername();
331 331
 		$memberOfGroups = $this->connection->getFromCache($cacheKey);
332
-		if(!is_null($memberOfGroups)) {
332
+		if (!is_null($memberOfGroups)) {
333 333
 			return $memberOfGroups;
334 334
 		}
335 335
 		$groupDNs = $this->access->readAttribute($this->getDN(), 'memberOf');
@@ -342,15 +342,15 @@  discard block
 block discarded – undo
342 342
 	 * @return string data (provided by LDAP) | false
343 343
 	 */
344 344
 	public function getAvatarImage() {
345
-		if(!is_null($this->avatarImage)) {
345
+		if (!is_null($this->avatarImage)) {
346 346
 			return $this->avatarImage;
347 347
 		}
348 348
 
349 349
 		$this->avatarImage = false;
350 350
 		$attributes = array('jpegPhoto', 'thumbnailPhoto');
351
-		foreach($attributes as $attribute) {
351
+		foreach ($attributes as $attribute) {
352 352
 			$result = $this->access->readAttribute($this->dn, $attribute);
353
-			if($result !== false && is_array($result) && isset($result[0])) {
353
+			if ($result !== false && is_array($result) && isset($result[0])) {
354 354
 				$this->avatarImage = $result[0];
355 355
 				break;
356 356
 			}
@@ -387,7 +387,7 @@  discard block
 block discarded – undo
387 387
 		$lastChecked = $this->config->getUserValue($this->uid, 'user_ldap',
388 388
 			self::USER_PREFKEY_LASTREFRESH, 0);
389 389
 
390
-		if((time() - intval($lastChecked)) < intval($this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400)) ) {
390
+		if ((time() - intval($lastChecked)) < intval($this->config->getAppValue('user_ldap', 'updateAttributesInterval', 86400))) {
391 391
 			return false;
392 392
 		}
393 393
 		return  true;
@@ -413,8 +413,8 @@  discard block
 block discarded – undo
413 413
 	 */
414 414
 	public function composeAndStoreDisplayName($displayName, $displayName2 = '') {
415 415
 		$displayName2 = strval($displayName2);
416
-		if($displayName2 !== '') {
417
-			$displayName .= ' (' . $displayName2 . ')';
416
+		if ($displayName2 !== '') {
417
+			$displayName .= ' ('.$displayName2.')';
418 418
 		}
419 419
 		$this->store('displayName', $displayName);
420 420
 		return $displayName;
@@ -436,7 +436,7 @@  discard block
 block discarded – undo
436 436
 	 * @return bool
437 437
 	 */
438 438
 	private function wasRefreshed($feature) {
439
-		if(isset($this->refreshedFeatures[$feature])) {
439
+		if (isset($this->refreshedFeatures[$feature])) {
440 440
 			return true;
441 441
 		}
442 442
 		$this->refreshedFeatures[$feature] = 1;
@@ -449,15 +449,15 @@  discard block
 block discarded – undo
449 449
 	 * @return null
450 450
 	 */
451 451
 	public function updateEmail($valueFromLDAP = null) {
452
-		if($this->wasRefreshed('email')) {
452
+		if ($this->wasRefreshed('email')) {
453 453
 			return;
454 454
 		}
455 455
 		$email = strval($valueFromLDAP);
456
-		if(is_null($valueFromLDAP)) {
456
+		if (is_null($valueFromLDAP)) {
457 457
 			$emailAttribute = $this->connection->ldapEmailAttribute;
458 458
 			if ($emailAttribute !== '') {
459 459
 				$aEmail = $this->access->readAttribute($this->dn, $emailAttribute);
460
-				if(is_array($aEmail) && (count($aEmail) > 0)) {
460
+				if (is_array($aEmail) && (count($aEmail) > 0)) {
461 461
 					$email = strval($aEmail[0]);
462 462
 				}
463 463
 			}
@@ -494,20 +494,20 @@  discard block
 block discarded – undo
494 494
 	 * @return null
495 495
 	 */
496 496
 	public function updateQuota($valueFromLDAP = null) {
497
-		if($this->wasRefreshed('quota')) {
497
+		if ($this->wasRefreshed('quota')) {
498 498
 			return;
499 499
 		}
500 500
 
501 501
 		$quota = false;
502
-		if(is_null($valueFromLDAP)) {
502
+		if (is_null($valueFromLDAP)) {
503 503
 			$quotaAttribute = $this->connection->ldapQuotaAttribute;
504 504
 			if ($quotaAttribute !== '') {
505 505
 				$aQuota = $this->access->readAttribute($this->dn, $quotaAttribute);
506
-				if($aQuota && (count($aQuota) > 0)) {
506
+				if ($aQuota && (count($aQuota) > 0)) {
507 507
 					if ($this->verifyQuotaValue($aQuota[0])) {
508 508
 						$quota = $aQuota[0];
509 509
 					} else {
510
-						$this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $aQuota[0] . ']', \OCP\Util::WARN);
510
+						$this->log->log('not suitable LDAP quota found for user '.$this->uid.': ['.$aQuota[0].']', \OCP\Util::WARN);
511 511
 					}
512 512
 				}
513 513
 			}
@@ -515,7 +515,7 @@  discard block
 block discarded – undo
515 515
 			if ($this->verifyQuotaValue($valueFromLDAP)) {
516 516
 				$quota = $valueFromLDAP;
517 517
 			} else {
518
-				$this->log->log('not suitable LDAP quota found for user ' . $this->uid . ': [' . $valueFromLDAP . ']', \OCP\Util::WARN);
518
+				$this->log->log('not suitable LDAP quota found for user '.$this->uid.': ['.$valueFromLDAP.']', \OCP\Util::WARN);
519 519
 			}
520 520
 		}
521 521
 
@@ -529,13 +529,13 @@  discard block
 block discarded – undo
529 529
 
530 530
 		$targetUser = $this->userManager->get($this->uid);
531 531
 		if ($targetUser) {
532
-			if($quota !== false) {
532
+			if ($quota !== false) {
533 533
 				$targetUser->setQuota($quota);
534 534
 			} else {
535
-				$this->log->log('not suitable default quota found for user ' . $this->uid . ': [' . $defaultQuota . ']', \OCP\Util::WARN);
535
+				$this->log->log('not suitable default quota found for user '.$this->uid.': ['.$defaultQuota.']', \OCP\Util::WARN);
536 536
 			}
537 537
 		} else {
538
-			$this->log->log('trying to set a quota for user ' . $this->uid . ' but the user is missing', \OCP\Util::ERROR);
538
+			$this->log->log('trying to set a quota for user '.$this->uid.' but the user is missing', \OCP\Util::ERROR);
539 539
 		}
540 540
 	}
541 541
 
@@ -549,7 +549,7 @@  discard block
 block discarded – undo
549 549
 	 * @param array $params
550 550
 	 */
551 551
 	public function updateAvatarPostLogin($params) {
552
-		if(isset($params['uid']) && $params['uid'] === $this->getUsername()) {
552
+		if (isset($params['uid']) && $params['uid'] === $this->getUsername()) {
553 553
 			$this->updateAvatar();
554 554
 		}
555 555
 	}
@@ -559,11 +559,11 @@  discard block
 block discarded – undo
559 559
 	 * @return null
560 560
 	 */
561 561
 	public function updateAvatar() {
562
-		if($this->wasRefreshed('avatar')) {
562
+		if ($this->wasRefreshed('avatar')) {
563 563
 			return;
564 564
 		}
565 565
 		$avatarImage = $this->getAvatarImage();
566
-		if($avatarImage === false) {
566
+		if ($avatarImage === false) {
567 567
 			//not set, nothing left to do;
568 568
 			return;
569 569
 		}
@@ -576,18 +576,18 @@  discard block
 block discarded – undo
576 576
 	 * @return null
577 577
 	 */
578 578
 	private function setOwnCloudAvatar() {
579
-		if(!$this->image->valid()) {
579
+		if (!$this->image->valid()) {
580 580
 			$this->log->log('jpegPhoto data invalid for '.$this->dn, \OCP\Util::ERROR);
581 581
 			return;
582 582
 		}
583 583
 		//make sure it is a square and not bigger than 128x128
584 584
 		$size = min(array($this->image->width(), $this->image->height(), 128));
585
-		if(!$this->image->centerCrop($size)) {
585
+		if (!$this->image->centerCrop($size)) {
586 586
 			$this->log->log('croping image for avatar failed for '.$this->dn, \OCP\Util::ERROR);
587 587
 			return;
588 588
 		}
589 589
 
590
-		if(!$this->fs->isLoaded()) {
590
+		if (!$this->fs->isLoaded()) {
591 591
 			$this->fs->setup($this->uid);
592 592
 		}
593 593
 
@@ -596,7 +596,7 @@  discard block
 block discarded – undo
596 596
 			$avatar->set($this->image);
597 597
 		} catch (\Exception $e) {
598 598
 			\OC::$server->getLogger()->logException($e, [
599
-				'message' => 'Could not set avatar for ' . $this->dn,
599
+				'message' => 'Could not set avatar for '.$this->dn,
600 600
 				'level' => \OCP\Util::INFO,
601 601
 				'app' => 'user_ldap',
602 602
 			]);
@@ -611,17 +611,17 @@  discard block
 block discarded – undo
611 611
 	public function handlePasswordExpiry($params) {
612 612
 		$ppolicyDN = $this->connection->ldapDefaultPPolicyDN;
613 613
 		if (empty($ppolicyDN) || (intval($this->connection->turnOnPasswordChange) !== 1)) {
614
-			return;//password expiry handling disabled
614
+			return; //password expiry handling disabled
615 615
 		}
616 616
 		$uid = $params['uid'];
617
-		if(isset($uid) && $uid === $this->getUsername()) {
617
+		if (isset($uid) && $uid === $this->getUsername()) {
618 618
 			//retrieve relevant user attributes
619 619
 			$result = $this->access->search('objectclass=*', $this->dn, ['pwdpolicysubentry', 'pwdgraceusetime', 'pwdreset', 'pwdchangedtime']);
620 620
 			
621
-			if(array_key_exists('pwdpolicysubentry', $result[0])) {
621
+			if (array_key_exists('pwdpolicysubentry', $result[0])) {
622 622
 				$pwdPolicySubentry = $result[0]['pwdpolicysubentry'];
623
-				if($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)){
624
-					$ppolicyDN = $pwdPolicySubentry[0];//custom ppolicy DN
623
+				if ($pwdPolicySubentry && (count($pwdPolicySubentry) > 0)) {
624
+					$ppolicyDN = $pwdPolicySubentry[0]; //custom ppolicy DN
625 625
 				}
626 626
 			}
627 627
 			
@@ -630,9 +630,9 @@  discard block
 block discarded – undo
630 630
 			$pwdChangedTime = array_key_exists('pwdchangedtime', $result[0]) ? $result[0]['pwdchangedtime'] : null;
631 631
 			
632 632
 			//retrieve relevant password policy attributes
633
-			$cacheKey = 'ppolicyAttributes' . $ppolicyDN;
633
+			$cacheKey = 'ppolicyAttributes'.$ppolicyDN;
634 634
 			$result = $this->connection->getFromCache($cacheKey);
635
-			if(is_null($result)) {
635
+			if (is_null($result)) {
636 636
 				$result = $this->access->search('objectclass=*', $ppolicyDN, ['pwdgraceauthnlimit', 'pwdmaxage', 'pwdexpirewarning']);
637 637
 				$this->connection->writeToCache($cacheKey, $result);
638 638
 			}
@@ -643,8 +643,8 @@  discard block
 block discarded – undo
643 643
 			
644 644
 			//handle grace login
645 645
 			$pwdGraceUseTimeCount = count($pwdGraceUseTime);
646
-			if($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
647
-				if($pwdGraceAuthNLimit 
646
+			if ($pwdGraceUseTime && $pwdGraceUseTimeCount > 0) { //was this a grace login?
647
+				if ($pwdGraceAuthNLimit 
648 648
 					&& (count($pwdGraceAuthNLimit) > 0)
649 649
 					&&($pwdGraceUseTimeCount < intval($pwdGraceAuthNLimit[0]))) { //at least one more grace login available?
650 650
 					$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
@@ -657,24 +657,24 @@  discard block
 block discarded – undo
657 657
 				exit();
658 658
 			}
659 659
 			//handle pwdReset attribute
660
-			if($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
660
+			if ($pwdReset && (count($pwdReset) > 0) && $pwdReset[0] === 'TRUE') { //user must change his password
661 661
 				$this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
662 662
 				header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
663 663
 				'user_ldap.renewPassword.showRenewPasswordForm', array('user' => $uid)));
664 664
 				exit();
665 665
 			}
666 666
 			//handle password expiry warning
667
-			if($pwdChangedTime && (count($pwdChangedTime) > 0)) {
668
-				if($pwdMaxAge && (count($pwdMaxAge) > 0)
667
+			if ($pwdChangedTime && (count($pwdChangedTime) > 0)) {
668
+				if ($pwdMaxAge && (count($pwdMaxAge) > 0)
669 669
 					&& $pwdExpireWarning && (count($pwdExpireWarning) > 0)) {
670 670
 					$pwdMaxAgeInt = intval($pwdMaxAge[0]);
671 671
 					$pwdExpireWarningInt = intval($pwdExpireWarning[0]);
672
-					if($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0){
672
+					if ($pwdMaxAgeInt > 0 && $pwdExpireWarningInt > 0) {
673 673
 						$pwdChangedTimeDt = \DateTime::createFromFormat('YmdHisZ', $pwdChangedTime[0]);
674 674
 						$pwdChangedTimeDt->add(new \DateInterval('PT'.$pwdMaxAgeInt.'S'));
675 675
 						$currentDateTime = new \DateTime();
676 676
 						$secondsToExpiry = $pwdChangedTimeDt->getTimestamp() - $currentDateTime->getTimestamp();
677
-						if($secondsToExpiry <= $pwdExpireWarningInt) {
677
+						if ($secondsToExpiry <= $pwdExpireWarningInt) {
678 678
 							//remove last password expiry warning if any
679 679
 							$notification = $this->notificationManager->createNotification();
680 680
 							$notification->setApp('user_ldap')
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/FederatedShareProvider.php 2 patches
Indentation   +978 added lines, -978 removed lines patch added patch discarded remove patch
@@ -53,992 +53,992 @@
 block discarded – undo
53 53
  */
54 54
 class FederatedShareProvider implements IShareProvider {
55 55
 
56
-	const SHARE_TYPE_REMOTE = 6;
57
-
58
-	/** @var IDBConnection */
59
-	private $dbConnection;
60
-
61
-	/** @var AddressHandler */
62
-	private $addressHandler;
63
-
64
-	/** @var Notifications */
65
-	private $notifications;
66
-
67
-	/** @var TokenHandler */
68
-	private $tokenHandler;
69
-
70
-	/** @var IL10N */
71
-	private $l;
72
-
73
-	/** @var ILogger */
74
-	private $logger;
75
-
76
-	/** @var IRootFolder */
77
-	private $rootFolder;
78
-
79
-	/** @var IConfig */
80
-	private $config;
81
-
82
-	/** @var string */
83
-	private $externalShareTable = 'share_external';
84
-
85
-	/** @var IUserManager */
86
-	private $userManager;
87
-
88
-	/** @var ICloudIdManager */
89
-	private $cloudIdManager;
90
-
91
-	/** @var \OCP\GlobalScale\IConfig */
92
-	private $gsConfig;
93
-
94
-	/**
95
-	 * DefaultShareProvider constructor.
96
-	 *
97
-	 * @param IDBConnection $connection
98
-	 * @param AddressHandler $addressHandler
99
-	 * @param Notifications $notifications
100
-	 * @param TokenHandler $tokenHandler
101
-	 * @param IL10N $l10n
102
-	 * @param ILogger $logger
103
-	 * @param IRootFolder $rootFolder
104
-	 * @param IConfig $config
105
-	 * @param IUserManager $userManager
106
-	 * @param ICloudIdManager $cloudIdManager
107
-	 * @param \OCP\GlobalScale\IConfig $globalScaleConfig
108
-	 */
109
-	public function __construct(
110
-			IDBConnection $connection,
111
-			AddressHandler $addressHandler,
112
-			Notifications $notifications,
113
-			TokenHandler $tokenHandler,
114
-			IL10N $l10n,
115
-			ILogger $logger,
116
-			IRootFolder $rootFolder,
117
-			IConfig $config,
118
-			IUserManager $userManager,
119
-			ICloudIdManager $cloudIdManager,
120
-			\OCP\GlobalScale\IConfig $globalScaleConfig
121
-	) {
122
-		$this->dbConnection = $connection;
123
-		$this->addressHandler = $addressHandler;
124
-		$this->notifications = $notifications;
125
-		$this->tokenHandler = $tokenHandler;
126
-		$this->l = $l10n;
127
-		$this->logger = $logger;
128
-		$this->rootFolder = $rootFolder;
129
-		$this->config = $config;
130
-		$this->userManager = $userManager;
131
-		$this->cloudIdManager = $cloudIdManager;
132
-		$this->gsConfig = $globalScaleConfig;
133
-	}
134
-
135
-	/**
136
-	 * Return the identifier of this provider.
137
-	 *
138
-	 * @return string Containing only [a-zA-Z0-9]
139
-	 */
140
-	public function identifier() {
141
-		return 'ocFederatedSharing';
142
-	}
143
-
144
-	/**
145
-	 * Share a path
146
-	 *
147
-	 * @param IShare $share
148
-	 * @return IShare The share object
149
-	 * @throws ShareNotFound
150
-	 * @throws \Exception
151
-	 */
152
-	public function create(IShare $share) {
153
-
154
-		$shareWith = $share->getSharedWith();
155
-		$itemSource = $share->getNodeId();
156
-		$itemType = $share->getNodeType();
157
-		$permissions = $share->getPermissions();
158
-		$sharedBy = $share->getSharedBy();
159
-
160
-		/*
56
+    const SHARE_TYPE_REMOTE = 6;
57
+
58
+    /** @var IDBConnection */
59
+    private $dbConnection;
60
+
61
+    /** @var AddressHandler */
62
+    private $addressHandler;
63
+
64
+    /** @var Notifications */
65
+    private $notifications;
66
+
67
+    /** @var TokenHandler */
68
+    private $tokenHandler;
69
+
70
+    /** @var IL10N */
71
+    private $l;
72
+
73
+    /** @var ILogger */
74
+    private $logger;
75
+
76
+    /** @var IRootFolder */
77
+    private $rootFolder;
78
+
79
+    /** @var IConfig */
80
+    private $config;
81
+
82
+    /** @var string */
83
+    private $externalShareTable = 'share_external';
84
+
85
+    /** @var IUserManager */
86
+    private $userManager;
87
+
88
+    /** @var ICloudIdManager */
89
+    private $cloudIdManager;
90
+
91
+    /** @var \OCP\GlobalScale\IConfig */
92
+    private $gsConfig;
93
+
94
+    /**
95
+     * DefaultShareProvider constructor.
96
+     *
97
+     * @param IDBConnection $connection
98
+     * @param AddressHandler $addressHandler
99
+     * @param Notifications $notifications
100
+     * @param TokenHandler $tokenHandler
101
+     * @param IL10N $l10n
102
+     * @param ILogger $logger
103
+     * @param IRootFolder $rootFolder
104
+     * @param IConfig $config
105
+     * @param IUserManager $userManager
106
+     * @param ICloudIdManager $cloudIdManager
107
+     * @param \OCP\GlobalScale\IConfig $globalScaleConfig
108
+     */
109
+    public function __construct(
110
+            IDBConnection $connection,
111
+            AddressHandler $addressHandler,
112
+            Notifications $notifications,
113
+            TokenHandler $tokenHandler,
114
+            IL10N $l10n,
115
+            ILogger $logger,
116
+            IRootFolder $rootFolder,
117
+            IConfig $config,
118
+            IUserManager $userManager,
119
+            ICloudIdManager $cloudIdManager,
120
+            \OCP\GlobalScale\IConfig $globalScaleConfig
121
+    ) {
122
+        $this->dbConnection = $connection;
123
+        $this->addressHandler = $addressHandler;
124
+        $this->notifications = $notifications;
125
+        $this->tokenHandler = $tokenHandler;
126
+        $this->l = $l10n;
127
+        $this->logger = $logger;
128
+        $this->rootFolder = $rootFolder;
129
+        $this->config = $config;
130
+        $this->userManager = $userManager;
131
+        $this->cloudIdManager = $cloudIdManager;
132
+        $this->gsConfig = $globalScaleConfig;
133
+    }
134
+
135
+    /**
136
+     * Return the identifier of this provider.
137
+     *
138
+     * @return string Containing only [a-zA-Z0-9]
139
+     */
140
+    public function identifier() {
141
+        return 'ocFederatedSharing';
142
+    }
143
+
144
+    /**
145
+     * Share a path
146
+     *
147
+     * @param IShare $share
148
+     * @return IShare The share object
149
+     * @throws ShareNotFound
150
+     * @throws \Exception
151
+     */
152
+    public function create(IShare $share) {
153
+
154
+        $shareWith = $share->getSharedWith();
155
+        $itemSource = $share->getNodeId();
156
+        $itemType = $share->getNodeType();
157
+        $permissions = $share->getPermissions();
158
+        $sharedBy = $share->getSharedBy();
159
+
160
+        /*
161 161
 		 * Check if file is not already shared with the remote user
162 162
 		 */
163
-		$alreadyShared = $this->getSharedWith($shareWith, self::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
164
-		if (!empty($alreadyShared)) {
165
-			$message = 'Sharing %s failed, because this item is already shared with %s';
166
-			$message_t = $this->l->t('Sharing %s failed, because this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
167
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
168
-			throw new \Exception($message_t);
169
-		}
170
-
171
-
172
-		// don't allow federated shares if source and target server are the same
173
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
174
-		$currentServer = $this->addressHandler->generateRemoteURL();
175
-		$currentUser = $sharedBy;
176
-		if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
177
-			$message = 'Not allowed to create a federated share with the same user.';
178
-			$message_t = $this->l->t('Not allowed to create a federated share with the same user');
179
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
180
-			throw new \Exception($message_t);
181
-		}
182
-
183
-
184
-		$share->setSharedWith($cloudId->getId());
185
-
186
-		try {
187
-			$remoteShare = $this->getShareFromExternalShareTable($share);
188
-		} catch (ShareNotFound $e) {
189
-			$remoteShare = null;
190
-		}
191
-
192
-		if ($remoteShare) {
193
-			try {
194
-				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
195
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time());
196
-				$share->setId($shareId);
197
-				list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
198
-				// remote share was create successfully if we get a valid token as return
199
-				$send = is_string($token) && $token !== '';
200
-			} catch (\Exception $e) {
201
-				// fall back to old re-share behavior if the remote server
202
-				// doesn't support flat re-shares (was introduced with Nextcloud 9.1)
203
-				$this->removeShareFromTable($share);
204
-				$shareId = $this->createFederatedShare($share);
205
-			}
206
-			if ($send) {
207
-				$this->updateSuccessfulReshare($shareId, $token);
208
-				$this->storeRemoteId($shareId, $remoteId);
209
-			} else {
210
-				$this->removeShareFromTable($share);
211
-				$message_t = $this->l->t('File is already shared with %s', [$shareWith]);
212
-				throw new \Exception($message_t);
213
-			}
214
-
215
-		} else {
216
-			$shareId = $this->createFederatedShare($share);
217
-		}
218
-
219
-		$data = $this->getRawShare($shareId);
220
-		return $this->createShareObject($data);
221
-	}
222
-
223
-	/**
224
-	 * create federated share and inform the recipient
225
-	 *
226
-	 * @param IShare $share
227
-	 * @return int
228
-	 * @throws ShareNotFound
229
-	 * @throws \Exception
230
-	 */
231
-	protected function createFederatedShare(IShare $share) {
232
-		$token = $this->tokenHandler->generateToken();
233
-		$shareId = $this->addShareToDB(
234
-			$share->getNodeId(),
235
-			$share->getNodeType(),
236
-			$share->getSharedWith(),
237
-			$share->getSharedBy(),
238
-			$share->getShareOwner(),
239
-			$share->getPermissions(),
240
-			$token
241
-		);
242
-
243
-		$failure = false;
244
-
245
-		try {
246
-			$sharedByFederatedId = $share->getSharedBy();
247
-			if ($this->userManager->userExists($sharedByFederatedId)) {
248
-				$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
249
-				$sharedByFederatedId = $cloudId->getId();
250
-			}
251
-			$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
252
-			$send = $this->notifications->sendRemoteShare(
253
-				$token,
254
-				$share->getSharedWith(),
255
-				$share->getNode()->getName(),
256
-				$shareId,
257
-				$share->getShareOwner(),
258
-				$ownerCloudId->getId(),
259
-				$share->getSharedBy(),
260
-				$sharedByFederatedId
261
-			);
262
-
263
-			if ($send === false) {
264
-				$failure = true;
265
-			}
266
-		} catch (\Exception $e) {
267
-			$this->logger->logException($e, [
268
-				'message' => 'Failed to notify remote server of federated share, removing share.',
269
-				'level' => \OCP\Util::ERROR,
270
-				'app' => 'federatedfilesharing',
271
-			]);
272
-			$failure = true;
273
-		}
274
-
275
-		if($failure) {
276
-			$this->removeShareFromTableById($shareId);
277
-			$message_t = $this->l->t('Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate.',
278
-				[$share->getNode()->getName(), $share->getSharedWith()]);
279
-			throw new \Exception($message_t);
280
-		}
281
-
282
-		return $shareId;
283
-
284
-	}
285
-
286
-	/**
287
-	 * @param string $shareWith
288
-	 * @param IShare $share
289
-	 * @param string $shareId internal share Id
290
-	 * @return array
291
-	 * @throws \Exception
292
-	 */
293
-	protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
294
-
295
-		$remoteShare = $this->getShareFromExternalShareTable($share);
296
-		$token = $remoteShare['share_token'];
297
-		$remoteId = $remoteShare['remote_id'];
298
-		$remote = $remoteShare['remote'];
299
-
300
-		list($token, $remoteId) = $this->notifications->requestReShare(
301
-			$token,
302
-			$remoteId,
303
-			$shareId,
304
-			$remote,
305
-			$shareWith,
306
-			$share->getPermissions()
307
-		);
308
-
309
-		return [$token, $remoteId];
310
-	}
311
-
312
-	/**
313
-	 * get federated share from the share_external table but exclude mounted link shares
314
-	 *
315
-	 * @param IShare $share
316
-	 * @return array
317
-	 * @throws ShareNotFound
318
-	 */
319
-	protected function getShareFromExternalShareTable(IShare $share) {
320
-		$query = $this->dbConnection->getQueryBuilder();
321
-		$query->select('*')->from($this->externalShareTable)
322
-			->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
323
-			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
324
-		$result = $query->execute()->fetchAll();
325
-
326
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
327
-			return $result[0];
328
-		}
329
-
330
-		throw new ShareNotFound('share not found in share_external table');
331
-	}
332
-
333
-	/**
334
-	 * add share to the database and return the ID
335
-	 *
336
-	 * @param int $itemSource
337
-	 * @param string $itemType
338
-	 * @param string $shareWith
339
-	 * @param string $sharedBy
340
-	 * @param string $uidOwner
341
-	 * @param int $permissions
342
-	 * @param string $token
343
-	 * @return int
344
-	 */
345
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) {
346
-		$qb = $this->dbConnection->getQueryBuilder();
347
-		$qb->insert('share')
348
-			->setValue('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))
349
-			->setValue('item_type', $qb->createNamedParameter($itemType))
350
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
351
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
352
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
353
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
354
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
355
-			->setValue('permissions', $qb->createNamedParameter($permissions))
356
-			->setValue('token', $qb->createNamedParameter($token))
357
-			->setValue('stime', $qb->createNamedParameter(time()));
358
-
359
-		/*
163
+        $alreadyShared = $this->getSharedWith($shareWith, self::SHARE_TYPE_REMOTE, $share->getNode(), 1, 0);
164
+        if (!empty($alreadyShared)) {
165
+            $message = 'Sharing %s failed, because this item is already shared with %s';
166
+            $message_t = $this->l->t('Sharing %s failed, because this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
167
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
168
+            throw new \Exception($message_t);
169
+        }
170
+
171
+
172
+        // don't allow federated shares if source and target server are the same
173
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
174
+        $currentServer = $this->addressHandler->generateRemoteURL();
175
+        $currentUser = $sharedBy;
176
+        if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
177
+            $message = 'Not allowed to create a federated share with the same user.';
178
+            $message_t = $this->l->t('Not allowed to create a federated share with the same user');
179
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
180
+            throw new \Exception($message_t);
181
+        }
182
+
183
+
184
+        $share->setSharedWith($cloudId->getId());
185
+
186
+        try {
187
+            $remoteShare = $this->getShareFromExternalShareTable($share);
188
+        } catch (ShareNotFound $e) {
189
+            $remoteShare = null;
190
+        }
191
+
192
+        if ($remoteShare) {
193
+            try {
194
+                $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
195
+                $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time());
196
+                $share->setId($shareId);
197
+                list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
198
+                // remote share was create successfully if we get a valid token as return
199
+                $send = is_string($token) && $token !== '';
200
+            } catch (\Exception $e) {
201
+                // fall back to old re-share behavior if the remote server
202
+                // doesn't support flat re-shares (was introduced with Nextcloud 9.1)
203
+                $this->removeShareFromTable($share);
204
+                $shareId = $this->createFederatedShare($share);
205
+            }
206
+            if ($send) {
207
+                $this->updateSuccessfulReshare($shareId, $token);
208
+                $this->storeRemoteId($shareId, $remoteId);
209
+            } else {
210
+                $this->removeShareFromTable($share);
211
+                $message_t = $this->l->t('File is already shared with %s', [$shareWith]);
212
+                throw new \Exception($message_t);
213
+            }
214
+
215
+        } else {
216
+            $shareId = $this->createFederatedShare($share);
217
+        }
218
+
219
+        $data = $this->getRawShare($shareId);
220
+        return $this->createShareObject($data);
221
+    }
222
+
223
+    /**
224
+     * create federated share and inform the recipient
225
+     *
226
+     * @param IShare $share
227
+     * @return int
228
+     * @throws ShareNotFound
229
+     * @throws \Exception
230
+     */
231
+    protected function createFederatedShare(IShare $share) {
232
+        $token = $this->tokenHandler->generateToken();
233
+        $shareId = $this->addShareToDB(
234
+            $share->getNodeId(),
235
+            $share->getNodeType(),
236
+            $share->getSharedWith(),
237
+            $share->getSharedBy(),
238
+            $share->getShareOwner(),
239
+            $share->getPermissions(),
240
+            $token
241
+        );
242
+
243
+        $failure = false;
244
+
245
+        try {
246
+            $sharedByFederatedId = $share->getSharedBy();
247
+            if ($this->userManager->userExists($sharedByFederatedId)) {
248
+                $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
249
+                $sharedByFederatedId = $cloudId->getId();
250
+            }
251
+            $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
252
+            $send = $this->notifications->sendRemoteShare(
253
+                $token,
254
+                $share->getSharedWith(),
255
+                $share->getNode()->getName(),
256
+                $shareId,
257
+                $share->getShareOwner(),
258
+                $ownerCloudId->getId(),
259
+                $share->getSharedBy(),
260
+                $sharedByFederatedId
261
+            );
262
+
263
+            if ($send === false) {
264
+                $failure = true;
265
+            }
266
+        } catch (\Exception $e) {
267
+            $this->logger->logException($e, [
268
+                'message' => 'Failed to notify remote server of federated share, removing share.',
269
+                'level' => \OCP\Util::ERROR,
270
+                'app' => 'federatedfilesharing',
271
+            ]);
272
+            $failure = true;
273
+        }
274
+
275
+        if($failure) {
276
+            $this->removeShareFromTableById($shareId);
277
+            $message_t = $this->l->t('Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate.',
278
+                [$share->getNode()->getName(), $share->getSharedWith()]);
279
+            throw new \Exception($message_t);
280
+        }
281
+
282
+        return $shareId;
283
+
284
+    }
285
+
286
+    /**
287
+     * @param string $shareWith
288
+     * @param IShare $share
289
+     * @param string $shareId internal share Id
290
+     * @return array
291
+     * @throws \Exception
292
+     */
293
+    protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
294
+
295
+        $remoteShare = $this->getShareFromExternalShareTable($share);
296
+        $token = $remoteShare['share_token'];
297
+        $remoteId = $remoteShare['remote_id'];
298
+        $remote = $remoteShare['remote'];
299
+
300
+        list($token, $remoteId) = $this->notifications->requestReShare(
301
+            $token,
302
+            $remoteId,
303
+            $shareId,
304
+            $remote,
305
+            $shareWith,
306
+            $share->getPermissions()
307
+        );
308
+
309
+        return [$token, $remoteId];
310
+    }
311
+
312
+    /**
313
+     * get federated share from the share_external table but exclude mounted link shares
314
+     *
315
+     * @param IShare $share
316
+     * @return array
317
+     * @throws ShareNotFound
318
+     */
319
+    protected function getShareFromExternalShareTable(IShare $share) {
320
+        $query = $this->dbConnection->getQueryBuilder();
321
+        $query->select('*')->from($this->externalShareTable)
322
+            ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
323
+            ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
324
+        $result = $query->execute()->fetchAll();
325
+
326
+        if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
327
+            return $result[0];
328
+        }
329
+
330
+        throw new ShareNotFound('share not found in share_external table');
331
+    }
332
+
333
+    /**
334
+     * add share to the database and return the ID
335
+     *
336
+     * @param int $itemSource
337
+     * @param string $itemType
338
+     * @param string $shareWith
339
+     * @param string $sharedBy
340
+     * @param string $uidOwner
341
+     * @param int $permissions
342
+     * @param string $token
343
+     * @return int
344
+     */
345
+    private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token) {
346
+        $qb = $this->dbConnection->getQueryBuilder();
347
+        $qb->insert('share')
348
+            ->setValue('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE))
349
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
350
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
351
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
352
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
353
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
354
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
355
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
356
+            ->setValue('token', $qb->createNamedParameter($token))
357
+            ->setValue('stime', $qb->createNamedParameter(time()));
358
+
359
+        /*
360 360
 		 * Added to fix https://github.com/owncloud/core/issues/22215
361 361
 		 * Can be removed once we get rid of ajax/share.php
362 362
 		 */
363
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
364
-
365
-		$qb->execute();
366
-		$id = $qb->getLastInsertId();
367
-
368
-		return (int)$id;
369
-	}
370
-
371
-	/**
372
-	 * Update a share
373
-	 *
374
-	 * @param IShare $share
375
-	 * @return IShare The share object
376
-	 */
377
-	public function update(IShare $share) {
378
-		/*
363
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
364
+
365
+        $qb->execute();
366
+        $id = $qb->getLastInsertId();
367
+
368
+        return (int)$id;
369
+    }
370
+
371
+    /**
372
+     * Update a share
373
+     *
374
+     * @param IShare $share
375
+     * @return IShare The share object
376
+     */
377
+    public function update(IShare $share) {
378
+        /*
379 379
 		 * We allow updating the permissions of federated shares
380 380
 		 */
381
-		$qb = $this->dbConnection->getQueryBuilder();
382
-			$qb->update('share')
383
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
384
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
385
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
386
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
387
-				->execute();
388
-
389
-		// send the updated permission to the owner/initiator, if they are not the same
390
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
391
-			$this->sendPermissionUpdate($share);
392
-		}
393
-
394
-		return $share;
395
-	}
396
-
397
-	/**
398
-	 * send the updated permission to the owner/initiator, if they are not the same
399
-	 *
400
-	 * @param IShare $share
401
-	 * @throws ShareNotFound
402
-	 * @throws \OC\HintException
403
-	 */
404
-	protected function sendPermissionUpdate(IShare $share) {
405
-		$remoteId = $this->getRemoteId($share);
406
-		// if the local user is the owner we send the permission change to the initiator
407
-		if ($this->userManager->userExists($share->getShareOwner())) {
408
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
409
-		} else { // ... if not we send the permission change to the owner
410
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
411
-		}
412
-		$this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
413
-	}
414
-
415
-
416
-	/**
417
-	 * update successful reShare with the correct token
418
-	 *
419
-	 * @param int $shareId
420
-	 * @param string $token
421
-	 */
422
-	protected function updateSuccessfulReShare($shareId, $token) {
423
-		$query = $this->dbConnection->getQueryBuilder();
424
-		$query->update('share')
425
-			->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
426
-			->set('token', $query->createNamedParameter($token))
427
-			->execute();
428
-	}
429
-
430
-	/**
431
-	 * store remote ID in federated reShare table
432
-	 *
433
-	 * @param $shareId
434
-	 * @param $remoteId
435
-	 */
436
-	public function storeRemoteId($shareId, $remoteId) {
437
-		$query = $this->dbConnection->getQueryBuilder();
438
-		$query->insert('federated_reshares')
439
-			->values(
440
-				[
441
-					'share_id' =>  $query->createNamedParameter($shareId),
442
-					'remote_id' => $query->createNamedParameter($remoteId),
443
-				]
444
-			);
445
-		$query->execute();
446
-	}
447
-
448
-	/**
449
-	 * get share ID on remote server for federated re-shares
450
-	 *
451
-	 * @param IShare $share
452
-	 * @return int
453
-	 * @throws ShareNotFound
454
-	 */
455
-	public function getRemoteId(IShare $share) {
456
-		$query = $this->dbConnection->getQueryBuilder();
457
-		$query->select('remote_id')->from('federated_reshares')
458
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
459
-		$data = $query->execute()->fetch();
460
-
461
-		if (!is_array($data) || !isset($data['remote_id'])) {
462
-			throw new ShareNotFound();
463
-		}
464
-
465
-		return (int)$data['remote_id'];
466
-	}
467
-
468
-	/**
469
-	 * @inheritdoc
470
-	 */
471
-	public function move(IShare $share, $recipient) {
472
-		/*
381
+        $qb = $this->dbConnection->getQueryBuilder();
382
+            $qb->update('share')
383
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
384
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
385
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
386
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
387
+                ->execute();
388
+
389
+        // send the updated permission to the owner/initiator, if they are not the same
390
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
391
+            $this->sendPermissionUpdate($share);
392
+        }
393
+
394
+        return $share;
395
+    }
396
+
397
+    /**
398
+     * send the updated permission to the owner/initiator, if they are not the same
399
+     *
400
+     * @param IShare $share
401
+     * @throws ShareNotFound
402
+     * @throws \OC\HintException
403
+     */
404
+    protected function sendPermissionUpdate(IShare $share) {
405
+        $remoteId = $this->getRemoteId($share);
406
+        // if the local user is the owner we send the permission change to the initiator
407
+        if ($this->userManager->userExists($share->getShareOwner())) {
408
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
409
+        } else { // ... if not we send the permission change to the owner
410
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
411
+        }
412
+        $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
413
+    }
414
+
415
+
416
+    /**
417
+     * update successful reShare with the correct token
418
+     *
419
+     * @param int $shareId
420
+     * @param string $token
421
+     */
422
+    protected function updateSuccessfulReShare($shareId, $token) {
423
+        $query = $this->dbConnection->getQueryBuilder();
424
+        $query->update('share')
425
+            ->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
426
+            ->set('token', $query->createNamedParameter($token))
427
+            ->execute();
428
+    }
429
+
430
+    /**
431
+     * store remote ID in federated reShare table
432
+     *
433
+     * @param $shareId
434
+     * @param $remoteId
435
+     */
436
+    public function storeRemoteId($shareId, $remoteId) {
437
+        $query = $this->dbConnection->getQueryBuilder();
438
+        $query->insert('federated_reshares')
439
+            ->values(
440
+                [
441
+                    'share_id' =>  $query->createNamedParameter($shareId),
442
+                    'remote_id' => $query->createNamedParameter($remoteId),
443
+                ]
444
+            );
445
+        $query->execute();
446
+    }
447
+
448
+    /**
449
+     * get share ID on remote server for federated re-shares
450
+     *
451
+     * @param IShare $share
452
+     * @return int
453
+     * @throws ShareNotFound
454
+     */
455
+    public function getRemoteId(IShare $share) {
456
+        $query = $this->dbConnection->getQueryBuilder();
457
+        $query->select('remote_id')->from('federated_reshares')
458
+            ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
459
+        $data = $query->execute()->fetch();
460
+
461
+        if (!is_array($data) || !isset($data['remote_id'])) {
462
+            throw new ShareNotFound();
463
+        }
464
+
465
+        return (int)$data['remote_id'];
466
+    }
467
+
468
+    /**
469
+     * @inheritdoc
470
+     */
471
+    public function move(IShare $share, $recipient) {
472
+        /*
473 473
 		 * This function does nothing yet as it is just for outgoing
474 474
 		 * federated shares.
475 475
 		 */
476
-		return $share;
477
-	}
478
-
479
-	/**
480
-	 * Get all children of this share
481
-	 *
482
-	 * @param IShare $parent
483
-	 * @return IShare[]
484
-	 */
485
-	public function getChildren(IShare $parent) {
486
-		$children = [];
487
-
488
-		$qb = $this->dbConnection->getQueryBuilder();
489
-		$qb->select('*')
490
-			->from('share')
491
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
492
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
493
-			->orderBy('id');
494
-
495
-		$cursor = $qb->execute();
496
-		while($data = $cursor->fetch()) {
497
-			$children[] = $this->createShareObject($data);
498
-		}
499
-		$cursor->closeCursor();
500
-
501
-		return $children;
502
-	}
503
-
504
-	/**
505
-	 * Delete a share (owner unShares the file)
506
-	 *
507
-	 * @param IShare $share
508
-	 */
509
-	public function delete(IShare $share) {
510
-
511
-		list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
512
-
513
-		$isOwner = false;
514
-
515
-		$this->removeShareFromTable($share);
516
-
517
-		// if the local user is the owner we can send the unShare request directly...
518
-		if ($this->userManager->userExists($share->getShareOwner())) {
519
-			$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
520
-			$this->revokeShare($share, true);
521
-			$isOwner = true;
522
-		} else { // ... if not we need to correct ID for the unShare request
523
-			$remoteId = $this->getRemoteId($share);
524
-			$this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
525
-			$this->revokeShare($share, false);
526
-		}
527
-
528
-		// send revoke notification to the other user, if initiator and owner are not the same user
529
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
530
-			$remoteId = $this->getRemoteId($share);
531
-			if ($isOwner) {
532
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
533
-			} else {
534
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
535
-			}
536
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
537
-		}
538
-	}
539
-
540
-	/**
541
-	 * in case of a re-share we need to send the other use (initiator or owner)
542
-	 * a message that the file was unshared
543
-	 *
544
-	 * @param IShare $share
545
-	 * @param bool $isOwner the user can either be the owner or the user who re-sahred it
546
-	 * @throws ShareNotFound
547
-	 * @throws \OC\HintException
548
-	 */
549
-	protected function revokeShare($share, $isOwner) {
550
-		// also send a unShare request to the initiator, if this is a different user than the owner
551
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
552
-			if ($isOwner) {
553
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
554
-			} else {
555
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
556
-			}
557
-			$remoteId = $this->getRemoteId($share);
558
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
559
-		}
560
-	}
561
-
562
-	/**
563
-	 * remove share from table
564
-	 *
565
-	 * @param IShare $share
566
-	 */
567
-	public function removeShareFromTable(IShare $share) {
568
-		$this->removeShareFromTableById($share->getId());
569
-	}
570
-
571
-	/**
572
-	 * remove share from table
573
-	 *
574
-	 * @param string $shareId
575
-	 */
576
-	private function removeShareFromTableById($shareId) {
577
-		$qb = $this->dbConnection->getQueryBuilder();
578
-		$qb->delete('share')
579
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
580
-		$qb->execute();
581
-
582
-		$qb->delete('federated_reshares')
583
-			->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
584
-		$qb->execute();
585
-	}
586
-
587
-	/**
588
-	 * @inheritdoc
589
-	 */
590
-	public function deleteFromSelf(IShare $share, $recipient) {
591
-		// nothing to do here. Technically deleteFromSelf in the context of federated
592
-		// shares is a umount of a external storage. This is handled here
593
-		// apps/files_sharing/lib/external/manager.php
594
-		// TODO move this code over to this app
595
-		return;
596
-	}
597
-
598
-
599
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
600
-		$qb = $this->dbConnection->getQueryBuilder();
601
-		$qb->select('*')
602
-			->from('share', 's')
603
-			->andWhere($qb->expr()->orX(
604
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
605
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
606
-			))
607
-			->andWhere(
608
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
609
-			);
610
-
611
-		/**
612
-		 * Reshares for this user are shares where they are the owner.
613
-		 */
614
-		if ($reshares === false) {
615
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
616
-		} else {
617
-			$qb->andWhere(
618
-				$qb->expr()->orX(
619
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
620
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
621
-				)
622
-			);
623
-		}
624
-
625
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
626
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
627
-
628
-		$qb->orderBy('id');
629
-
630
-		$cursor = $qb->execute();
631
-		$shares = [];
632
-		while ($data = $cursor->fetch()) {
633
-			$shares[$data['fileid']][] = $this->createShareObject($data);
634
-		}
635
-		$cursor->closeCursor();
636
-
637
-		return $shares;
638
-	}
639
-
640
-	/**
641
-	 * @inheritdoc
642
-	 */
643
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
644
-		$qb = $this->dbConnection->getQueryBuilder();
645
-		$qb->select('*')
646
-			->from('share');
647
-
648
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
649
-
650
-		/**
651
-		 * Reshares for this user are shares where they are the owner.
652
-		 */
653
-		if ($reshares === false) {
654
-			//Special case for old shares created via the web UI
655
-			$or1 = $qb->expr()->andX(
656
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
657
-				$qb->expr()->isNull('uid_initiator')
658
-			);
659
-
660
-			$qb->andWhere(
661
-				$qb->expr()->orX(
662
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
663
-					$or1
664
-				)
665
-			);
666
-		} else {
667
-			$qb->andWhere(
668
-				$qb->expr()->orX(
669
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
670
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
671
-				)
672
-			);
673
-		}
674
-
675
-		if ($node !== null) {
676
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
677
-		}
678
-
679
-		if ($limit !== -1) {
680
-			$qb->setMaxResults($limit);
681
-		}
682
-
683
-		$qb->setFirstResult($offset);
684
-		$qb->orderBy('id');
685
-
686
-		$cursor = $qb->execute();
687
-		$shares = [];
688
-		while($data = $cursor->fetch()) {
689
-			$shares[] = $this->createShareObject($data);
690
-		}
691
-		$cursor->closeCursor();
692
-
693
-		return $shares;
694
-	}
695
-
696
-	/**
697
-	 * @inheritdoc
698
-	 */
699
-	public function getShareById($id, $recipientId = null) {
700
-		$qb = $this->dbConnection->getQueryBuilder();
701
-
702
-		$qb->select('*')
703
-			->from('share')
704
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
705
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
706
-
707
-		$cursor = $qb->execute();
708
-		$data = $cursor->fetch();
709
-		$cursor->closeCursor();
710
-
711
-		if ($data === false) {
712
-			throw new ShareNotFound();
713
-		}
714
-
715
-		try {
716
-			$share = $this->createShareObject($data);
717
-		} catch (InvalidShare $e) {
718
-			throw new ShareNotFound();
719
-		}
720
-
721
-		return $share;
722
-	}
723
-
724
-	/**
725
-	 * Get shares for a given path
726
-	 *
727
-	 * @param \OCP\Files\Node $path
728
-	 * @return IShare[]
729
-	 */
730
-	public function getSharesByPath(Node $path) {
731
-		$qb = $this->dbConnection->getQueryBuilder();
732
-
733
-		$cursor = $qb->select('*')
734
-			->from('share')
735
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
736
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
737
-			->execute();
738
-
739
-		$shares = [];
740
-		while($data = $cursor->fetch()) {
741
-			$shares[] = $this->createShareObject($data);
742
-		}
743
-		$cursor->closeCursor();
744
-
745
-		return $shares;
746
-	}
747
-
748
-	/**
749
-	 * @inheritdoc
750
-	 */
751
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
752
-		/** @var IShare[] $shares */
753
-		$shares = [];
754
-
755
-		//Get shares directly with this user
756
-		$qb = $this->dbConnection->getQueryBuilder();
757
-		$qb->select('*')
758
-			->from('share');
759
-
760
-		// Order by id
761
-		$qb->orderBy('id');
762
-
763
-		// Set limit and offset
764
-		if ($limit !== -1) {
765
-			$qb->setMaxResults($limit);
766
-		}
767
-		$qb->setFirstResult($offset);
768
-
769
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
770
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
771
-
772
-		// Filter by node if provided
773
-		if ($node !== null) {
774
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
775
-		}
776
-
777
-		$cursor = $qb->execute();
778
-
779
-		while($data = $cursor->fetch()) {
780
-			$shares[] = $this->createShareObject($data);
781
-		}
782
-		$cursor->closeCursor();
783
-
784
-
785
-		return $shares;
786
-	}
787
-
788
-	/**
789
-	 * Get a share by token
790
-	 *
791
-	 * @param string $token
792
-	 * @return IShare
793
-	 * @throws ShareNotFound
794
-	 */
795
-	public function getShareByToken($token) {
796
-		$qb = $this->dbConnection->getQueryBuilder();
797
-
798
-		$cursor = $qb->select('*')
799
-			->from('share')
800
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
801
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
802
-			->execute();
803
-
804
-		$data = $cursor->fetch();
805
-
806
-		if ($data === false) {
807
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
808
-		}
809
-
810
-		try {
811
-			$share = $this->createShareObject($data);
812
-		} catch (InvalidShare $e) {
813
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
814
-		}
815
-
816
-		return $share;
817
-	}
818
-
819
-	/**
820
-	 * get database row of a give share
821
-	 *
822
-	 * @param $id
823
-	 * @return array
824
-	 * @throws ShareNotFound
825
-	 */
826
-	private function getRawShare($id) {
827
-
828
-		// Now fetch the inserted share and create a complete share object
829
-		$qb = $this->dbConnection->getQueryBuilder();
830
-		$qb->select('*')
831
-			->from('share')
832
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
833
-
834
-		$cursor = $qb->execute();
835
-		$data = $cursor->fetch();
836
-		$cursor->closeCursor();
837
-
838
-		if ($data === false) {
839
-			throw new ShareNotFound;
840
-		}
841
-
842
-		return $data;
843
-	}
844
-
845
-	/**
846
-	 * Create a share object from an database row
847
-	 *
848
-	 * @param array $data
849
-	 * @return IShare
850
-	 * @throws InvalidShare
851
-	 * @throws ShareNotFound
852
-	 */
853
-	private function createShareObject($data) {
854
-
855
-		$share = new Share($this->rootFolder, $this->userManager);
856
-		$share->setId((int)$data['id'])
857
-			->setShareType((int)$data['share_type'])
858
-			->setPermissions((int)$data['permissions'])
859
-			->setTarget($data['file_target'])
860
-			->setMailSend((bool)$data['mail_send'])
861
-			->setToken($data['token']);
862
-
863
-		$shareTime = new \DateTime();
864
-		$shareTime->setTimestamp((int)$data['stime']);
865
-		$share->setShareTime($shareTime);
866
-		$share->setSharedWith($data['share_with']);
867
-
868
-		if ($data['uid_initiator'] !== null) {
869
-			$share->setShareOwner($data['uid_owner']);
870
-			$share->setSharedBy($data['uid_initiator']);
871
-		} else {
872
-			//OLD SHARE
873
-			$share->setSharedBy($data['uid_owner']);
874
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
875
-
876
-			$owner = $path->getOwner();
877
-			$share->setShareOwner($owner->getUID());
878
-		}
879
-
880
-		$share->setNodeId((int)$data['file_source']);
881
-		$share->setNodeType($data['item_type']);
882
-
883
-		$share->setProviderId($this->identifier());
884
-
885
-		return $share;
886
-	}
887
-
888
-	/**
889
-	 * Get the node with file $id for $user
890
-	 *
891
-	 * @param string $userId
892
-	 * @param int $id
893
-	 * @return \OCP\Files\File|\OCP\Files\Folder
894
-	 * @throws InvalidShare
895
-	 */
896
-	private function getNode($userId, $id) {
897
-		try {
898
-			$userFolder = $this->rootFolder->getUserFolder($userId);
899
-		} catch (NotFoundException $e) {
900
-			throw new InvalidShare();
901
-		}
902
-
903
-		$nodes = $userFolder->getById($id);
904
-
905
-		if (empty($nodes)) {
906
-			throw new InvalidShare();
907
-		}
908
-
909
-		return $nodes[0];
910
-	}
911
-
912
-	/**
913
-	 * A user is deleted from the system
914
-	 * So clean up the relevant shares.
915
-	 *
916
-	 * @param string $uid
917
-	 * @param int $shareType
918
-	 */
919
-	public function userDeleted($uid, $shareType) {
920
-		//TODO: probabaly a good idea to send unshare info to remote servers
921
-
922
-		$qb = $this->dbConnection->getQueryBuilder();
923
-
924
-		$qb->delete('share')
925
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
926
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
927
-			->execute();
928
-	}
929
-
930
-	/**
931
-	 * This provider does not handle groups
932
-	 *
933
-	 * @param string $gid
934
-	 */
935
-	public function groupDeleted($gid) {
936
-		// We don't handle groups here
937
-		return;
938
-	}
939
-
940
-	/**
941
-	 * This provider does not handle groups
942
-	 *
943
-	 * @param string $uid
944
-	 * @param string $gid
945
-	 */
946
-	public function userDeletedFromGroup($uid, $gid) {
947
-		// We don't handle groups here
948
-		return;
949
-	}
950
-
951
-	/**
952
-	 * check if users from other Nextcloud instances are allowed to mount public links share by this instance
953
-	 *
954
-	 * @return bool
955
-	 */
956
-	public function isOutgoingServer2serverShareEnabled() {
957
-		if ($this->gsConfig->onlyInternalFederation()) {
958
-			return false;
959
-		}
960
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
961
-		return ($result === 'yes');
962
-	}
963
-
964
-	/**
965
-	 * check if users are allowed to mount public links from other Nextclouds
966
-	 *
967
-	 * @return bool
968
-	 */
969
-	public function isIncomingServer2serverShareEnabled() {
970
-		if ($this->gsConfig->onlyInternalFederation()) {
971
-			return false;
972
-		}
973
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
974
-		return ($result === 'yes');
975
-	}
976
-
977
-	/**
978
-	 * Check if querying sharees on the lookup server is enabled
979
-	 *
980
-	 * @return bool
981
-	 */
982
-	public function isLookupServerQueriesEnabled() {
983
-		// in a global scale setup we should always query the lookup server
984
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
985
-			return true;
986
-		}
987
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
988
-		return ($result === 'yes');
989
-	}
990
-
991
-
992
-	/**
993
-	 * Check if it is allowed to publish user specific data to the lookup server
994
-	 *
995
-	 * @return bool
996
-	 */
997
-	public function isLookupServerUploadEnabled() {
998
-		// in a global scale setup the admin is responsible to keep the lookup server up-to-date
999
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1000
-			return false;
1001
-		}
1002
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1003
-		return ($result === 'yes');
1004
-	}
1005
-
1006
-	/**
1007
-	 * @inheritdoc
1008
-	 */
1009
-	public function getAccessList($nodes, $currentAccess) {
1010
-		$ids = [];
1011
-		foreach ($nodes as $node) {
1012
-			$ids[] = $node->getId();
1013
-		}
1014
-
1015
-		$qb = $this->dbConnection->getQueryBuilder();
1016
-		$qb->select('share_with', 'token', 'file_source')
1017
-			->from('share')
1018
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1019
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1020
-			->andWhere($qb->expr()->orX(
1021
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1022
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1023
-			));
1024
-		$cursor = $qb->execute();
1025
-
1026
-		if ($currentAccess === false) {
1027
-			$remote = $cursor->fetch() !== false;
1028
-			$cursor->closeCursor();
1029
-
1030
-			return ['remote' => $remote];
1031
-		}
1032
-
1033
-		$remote = [];
1034
-		while ($row = $cursor->fetch()) {
1035
-			$remote[$row['share_with']] = [
1036
-				'node_id' => $row['file_source'],
1037
-				'token' => $row['token'],
1038
-			];
1039
-		}
1040
-		$cursor->closeCursor();
1041
-
1042
-		return ['remote' => $remote];
1043
-	}
476
+        return $share;
477
+    }
478
+
479
+    /**
480
+     * Get all children of this share
481
+     *
482
+     * @param IShare $parent
483
+     * @return IShare[]
484
+     */
485
+    public function getChildren(IShare $parent) {
486
+        $children = [];
487
+
488
+        $qb = $this->dbConnection->getQueryBuilder();
489
+        $qb->select('*')
490
+            ->from('share')
491
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
492
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
493
+            ->orderBy('id');
494
+
495
+        $cursor = $qb->execute();
496
+        while($data = $cursor->fetch()) {
497
+            $children[] = $this->createShareObject($data);
498
+        }
499
+        $cursor->closeCursor();
500
+
501
+        return $children;
502
+    }
503
+
504
+    /**
505
+     * Delete a share (owner unShares the file)
506
+     *
507
+     * @param IShare $share
508
+     */
509
+    public function delete(IShare $share) {
510
+
511
+        list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
512
+
513
+        $isOwner = false;
514
+
515
+        $this->removeShareFromTable($share);
516
+
517
+        // if the local user is the owner we can send the unShare request directly...
518
+        if ($this->userManager->userExists($share->getShareOwner())) {
519
+            $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
520
+            $this->revokeShare($share, true);
521
+            $isOwner = true;
522
+        } else { // ... if not we need to correct ID for the unShare request
523
+            $remoteId = $this->getRemoteId($share);
524
+            $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
525
+            $this->revokeShare($share, false);
526
+        }
527
+
528
+        // send revoke notification to the other user, if initiator and owner are not the same user
529
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
530
+            $remoteId = $this->getRemoteId($share);
531
+            if ($isOwner) {
532
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
533
+            } else {
534
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
535
+            }
536
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
537
+        }
538
+    }
539
+
540
+    /**
541
+     * in case of a re-share we need to send the other use (initiator or owner)
542
+     * a message that the file was unshared
543
+     *
544
+     * @param IShare $share
545
+     * @param bool $isOwner the user can either be the owner or the user who re-sahred it
546
+     * @throws ShareNotFound
547
+     * @throws \OC\HintException
548
+     */
549
+    protected function revokeShare($share, $isOwner) {
550
+        // also send a unShare request to the initiator, if this is a different user than the owner
551
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
552
+            if ($isOwner) {
553
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
554
+            } else {
555
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
556
+            }
557
+            $remoteId = $this->getRemoteId($share);
558
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
559
+        }
560
+    }
561
+
562
+    /**
563
+     * remove share from table
564
+     *
565
+     * @param IShare $share
566
+     */
567
+    public function removeShareFromTable(IShare $share) {
568
+        $this->removeShareFromTableById($share->getId());
569
+    }
570
+
571
+    /**
572
+     * remove share from table
573
+     *
574
+     * @param string $shareId
575
+     */
576
+    private function removeShareFromTableById($shareId) {
577
+        $qb = $this->dbConnection->getQueryBuilder();
578
+        $qb->delete('share')
579
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
580
+        $qb->execute();
581
+
582
+        $qb->delete('federated_reshares')
583
+            ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
584
+        $qb->execute();
585
+    }
586
+
587
+    /**
588
+     * @inheritdoc
589
+     */
590
+    public function deleteFromSelf(IShare $share, $recipient) {
591
+        // nothing to do here. Technically deleteFromSelf in the context of federated
592
+        // shares is a umount of a external storage. This is handled here
593
+        // apps/files_sharing/lib/external/manager.php
594
+        // TODO move this code over to this app
595
+        return;
596
+    }
597
+
598
+
599
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
600
+        $qb = $this->dbConnection->getQueryBuilder();
601
+        $qb->select('*')
602
+            ->from('share', 's')
603
+            ->andWhere($qb->expr()->orX(
604
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
605
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
606
+            ))
607
+            ->andWhere(
608
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
609
+            );
610
+
611
+        /**
612
+         * Reshares for this user are shares where they are the owner.
613
+         */
614
+        if ($reshares === false) {
615
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
616
+        } else {
617
+            $qb->andWhere(
618
+                $qb->expr()->orX(
619
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
620
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
621
+                )
622
+            );
623
+        }
624
+
625
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
626
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
627
+
628
+        $qb->orderBy('id');
629
+
630
+        $cursor = $qb->execute();
631
+        $shares = [];
632
+        while ($data = $cursor->fetch()) {
633
+            $shares[$data['fileid']][] = $this->createShareObject($data);
634
+        }
635
+        $cursor->closeCursor();
636
+
637
+        return $shares;
638
+    }
639
+
640
+    /**
641
+     * @inheritdoc
642
+     */
643
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
644
+        $qb = $this->dbConnection->getQueryBuilder();
645
+        $qb->select('*')
646
+            ->from('share');
647
+
648
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
649
+
650
+        /**
651
+         * Reshares for this user are shares where they are the owner.
652
+         */
653
+        if ($reshares === false) {
654
+            //Special case for old shares created via the web UI
655
+            $or1 = $qb->expr()->andX(
656
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
657
+                $qb->expr()->isNull('uid_initiator')
658
+            );
659
+
660
+            $qb->andWhere(
661
+                $qb->expr()->orX(
662
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
663
+                    $or1
664
+                )
665
+            );
666
+        } else {
667
+            $qb->andWhere(
668
+                $qb->expr()->orX(
669
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
670
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
671
+                )
672
+            );
673
+        }
674
+
675
+        if ($node !== null) {
676
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
677
+        }
678
+
679
+        if ($limit !== -1) {
680
+            $qb->setMaxResults($limit);
681
+        }
682
+
683
+        $qb->setFirstResult($offset);
684
+        $qb->orderBy('id');
685
+
686
+        $cursor = $qb->execute();
687
+        $shares = [];
688
+        while($data = $cursor->fetch()) {
689
+            $shares[] = $this->createShareObject($data);
690
+        }
691
+        $cursor->closeCursor();
692
+
693
+        return $shares;
694
+    }
695
+
696
+    /**
697
+     * @inheritdoc
698
+     */
699
+    public function getShareById($id, $recipientId = null) {
700
+        $qb = $this->dbConnection->getQueryBuilder();
701
+
702
+        $qb->select('*')
703
+            ->from('share')
704
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
705
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
706
+
707
+        $cursor = $qb->execute();
708
+        $data = $cursor->fetch();
709
+        $cursor->closeCursor();
710
+
711
+        if ($data === false) {
712
+            throw new ShareNotFound();
713
+        }
714
+
715
+        try {
716
+            $share = $this->createShareObject($data);
717
+        } catch (InvalidShare $e) {
718
+            throw new ShareNotFound();
719
+        }
720
+
721
+        return $share;
722
+    }
723
+
724
+    /**
725
+     * Get shares for a given path
726
+     *
727
+     * @param \OCP\Files\Node $path
728
+     * @return IShare[]
729
+     */
730
+    public function getSharesByPath(Node $path) {
731
+        $qb = $this->dbConnection->getQueryBuilder();
732
+
733
+        $cursor = $qb->select('*')
734
+            ->from('share')
735
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
736
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
737
+            ->execute();
738
+
739
+        $shares = [];
740
+        while($data = $cursor->fetch()) {
741
+            $shares[] = $this->createShareObject($data);
742
+        }
743
+        $cursor->closeCursor();
744
+
745
+        return $shares;
746
+    }
747
+
748
+    /**
749
+     * @inheritdoc
750
+     */
751
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
752
+        /** @var IShare[] $shares */
753
+        $shares = [];
754
+
755
+        //Get shares directly with this user
756
+        $qb = $this->dbConnection->getQueryBuilder();
757
+        $qb->select('*')
758
+            ->from('share');
759
+
760
+        // Order by id
761
+        $qb->orderBy('id');
762
+
763
+        // Set limit and offset
764
+        if ($limit !== -1) {
765
+            $qb->setMaxResults($limit);
766
+        }
767
+        $qb->setFirstResult($offset);
768
+
769
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
770
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
771
+
772
+        // Filter by node if provided
773
+        if ($node !== null) {
774
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
775
+        }
776
+
777
+        $cursor = $qb->execute();
778
+
779
+        while($data = $cursor->fetch()) {
780
+            $shares[] = $this->createShareObject($data);
781
+        }
782
+        $cursor->closeCursor();
783
+
784
+
785
+        return $shares;
786
+    }
787
+
788
+    /**
789
+     * Get a share by token
790
+     *
791
+     * @param string $token
792
+     * @return IShare
793
+     * @throws ShareNotFound
794
+     */
795
+    public function getShareByToken($token) {
796
+        $qb = $this->dbConnection->getQueryBuilder();
797
+
798
+        $cursor = $qb->select('*')
799
+            ->from('share')
800
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
801
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
802
+            ->execute();
803
+
804
+        $data = $cursor->fetch();
805
+
806
+        if ($data === false) {
807
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
808
+        }
809
+
810
+        try {
811
+            $share = $this->createShareObject($data);
812
+        } catch (InvalidShare $e) {
813
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
814
+        }
815
+
816
+        return $share;
817
+    }
818
+
819
+    /**
820
+     * get database row of a give share
821
+     *
822
+     * @param $id
823
+     * @return array
824
+     * @throws ShareNotFound
825
+     */
826
+    private function getRawShare($id) {
827
+
828
+        // Now fetch the inserted share and create a complete share object
829
+        $qb = $this->dbConnection->getQueryBuilder();
830
+        $qb->select('*')
831
+            ->from('share')
832
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
833
+
834
+        $cursor = $qb->execute();
835
+        $data = $cursor->fetch();
836
+        $cursor->closeCursor();
837
+
838
+        if ($data === false) {
839
+            throw new ShareNotFound;
840
+        }
841
+
842
+        return $data;
843
+    }
844
+
845
+    /**
846
+     * Create a share object from an database row
847
+     *
848
+     * @param array $data
849
+     * @return IShare
850
+     * @throws InvalidShare
851
+     * @throws ShareNotFound
852
+     */
853
+    private function createShareObject($data) {
854
+
855
+        $share = new Share($this->rootFolder, $this->userManager);
856
+        $share->setId((int)$data['id'])
857
+            ->setShareType((int)$data['share_type'])
858
+            ->setPermissions((int)$data['permissions'])
859
+            ->setTarget($data['file_target'])
860
+            ->setMailSend((bool)$data['mail_send'])
861
+            ->setToken($data['token']);
862
+
863
+        $shareTime = new \DateTime();
864
+        $shareTime->setTimestamp((int)$data['stime']);
865
+        $share->setShareTime($shareTime);
866
+        $share->setSharedWith($data['share_with']);
867
+
868
+        if ($data['uid_initiator'] !== null) {
869
+            $share->setShareOwner($data['uid_owner']);
870
+            $share->setSharedBy($data['uid_initiator']);
871
+        } else {
872
+            //OLD SHARE
873
+            $share->setSharedBy($data['uid_owner']);
874
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
875
+
876
+            $owner = $path->getOwner();
877
+            $share->setShareOwner($owner->getUID());
878
+        }
879
+
880
+        $share->setNodeId((int)$data['file_source']);
881
+        $share->setNodeType($data['item_type']);
882
+
883
+        $share->setProviderId($this->identifier());
884
+
885
+        return $share;
886
+    }
887
+
888
+    /**
889
+     * Get the node with file $id for $user
890
+     *
891
+     * @param string $userId
892
+     * @param int $id
893
+     * @return \OCP\Files\File|\OCP\Files\Folder
894
+     * @throws InvalidShare
895
+     */
896
+    private function getNode($userId, $id) {
897
+        try {
898
+            $userFolder = $this->rootFolder->getUserFolder($userId);
899
+        } catch (NotFoundException $e) {
900
+            throw new InvalidShare();
901
+        }
902
+
903
+        $nodes = $userFolder->getById($id);
904
+
905
+        if (empty($nodes)) {
906
+            throw new InvalidShare();
907
+        }
908
+
909
+        return $nodes[0];
910
+    }
911
+
912
+    /**
913
+     * A user is deleted from the system
914
+     * So clean up the relevant shares.
915
+     *
916
+     * @param string $uid
917
+     * @param int $shareType
918
+     */
919
+    public function userDeleted($uid, $shareType) {
920
+        //TODO: probabaly a good idea to send unshare info to remote servers
921
+
922
+        $qb = $this->dbConnection->getQueryBuilder();
923
+
924
+        $qb->delete('share')
925
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
926
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
927
+            ->execute();
928
+    }
929
+
930
+    /**
931
+     * This provider does not handle groups
932
+     *
933
+     * @param string $gid
934
+     */
935
+    public function groupDeleted($gid) {
936
+        // We don't handle groups here
937
+        return;
938
+    }
939
+
940
+    /**
941
+     * This provider does not handle groups
942
+     *
943
+     * @param string $uid
944
+     * @param string $gid
945
+     */
946
+    public function userDeletedFromGroup($uid, $gid) {
947
+        // We don't handle groups here
948
+        return;
949
+    }
950
+
951
+    /**
952
+     * check if users from other Nextcloud instances are allowed to mount public links share by this instance
953
+     *
954
+     * @return bool
955
+     */
956
+    public function isOutgoingServer2serverShareEnabled() {
957
+        if ($this->gsConfig->onlyInternalFederation()) {
958
+            return false;
959
+        }
960
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
961
+        return ($result === 'yes');
962
+    }
963
+
964
+    /**
965
+     * check if users are allowed to mount public links from other Nextclouds
966
+     *
967
+     * @return bool
968
+     */
969
+    public function isIncomingServer2serverShareEnabled() {
970
+        if ($this->gsConfig->onlyInternalFederation()) {
971
+            return false;
972
+        }
973
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
974
+        return ($result === 'yes');
975
+    }
976
+
977
+    /**
978
+     * Check if querying sharees on the lookup server is enabled
979
+     *
980
+     * @return bool
981
+     */
982
+    public function isLookupServerQueriesEnabled() {
983
+        // in a global scale setup we should always query the lookup server
984
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
985
+            return true;
986
+        }
987
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
988
+        return ($result === 'yes');
989
+    }
990
+
991
+
992
+    /**
993
+     * Check if it is allowed to publish user specific data to the lookup server
994
+     *
995
+     * @return bool
996
+     */
997
+    public function isLookupServerUploadEnabled() {
998
+        // in a global scale setup the admin is responsible to keep the lookup server up-to-date
999
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1000
+            return false;
1001
+        }
1002
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1003
+        return ($result === 'yes');
1004
+    }
1005
+
1006
+    /**
1007
+     * @inheritdoc
1008
+     */
1009
+    public function getAccessList($nodes, $currentAccess) {
1010
+        $ids = [];
1011
+        foreach ($nodes as $node) {
1012
+            $ids[] = $node->getId();
1013
+        }
1014
+
1015
+        $qb = $this->dbConnection->getQueryBuilder();
1016
+        $qb->select('share_with', 'token', 'file_source')
1017
+            ->from('share')
1018
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1019
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1020
+            ->andWhere($qb->expr()->orX(
1021
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1022
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1023
+            ));
1024
+        $cursor = $qb->execute();
1025
+
1026
+        if ($currentAccess === false) {
1027
+            $remote = $cursor->fetch() !== false;
1028
+            $cursor->closeCursor();
1029
+
1030
+            return ['remote' => $remote];
1031
+        }
1032
+
1033
+        $remote = [];
1034
+        while ($row = $cursor->fetch()) {
1035
+            $remote[$row['share_with']] = [
1036
+                'node_id' => $row['file_source'],
1037
+                'token' => $row['token'],
1038
+            ];
1039
+        }
1040
+        $cursor->closeCursor();
1041
+
1042
+        return ['remote' => $remote];
1043
+    }
1044 1044
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
 		if ($remoteShare) {
193 193
 			try {
194 194
 				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
195
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time());
195
+				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_'.time());
196 196
 				$share->setId($shareId);
197 197
 				list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
198 198
 				// remote share was create successfully if we get a valid token as return
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
 			$failure = true;
273 273
 		}
274 274
 
275
-		if($failure) {
275
+		if ($failure) {
276 276
 			$this->removeShareFromTableById($shareId);
277 277
 			$message_t = $this->l->t('Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate.',
278 278
 				[$share->getNode()->getName(), $share->getSharedWith()]);
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
 			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
324 324
 		$result = $query->execute()->fetchAll();
325 325
 
326
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
326
+		if (isset($result[0]) && (int) $result[0]['remote_id'] > 0) {
327 327
 			return $result[0];
328 328
 		}
329 329
 
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
 		$qb->execute();
366 366
 		$id = $qb->getLastInsertId();
367 367
 
368
-		return (int)$id;
368
+		return (int) $id;
369 369
 	}
370 370
 
371 371
 	/**
@@ -455,14 +455,14 @@  discard block
 block discarded – undo
455 455
 	public function getRemoteId(IShare $share) {
456 456
 		$query = $this->dbConnection->getQueryBuilder();
457 457
 		$query->select('remote_id')->from('federated_reshares')
458
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
458
+			->where($query->expr()->eq('share_id', $query->createNamedParameter((int) $share->getId())));
459 459
 		$data = $query->execute()->fetch();
460 460
 
461 461
 		if (!is_array($data) || !isset($data['remote_id'])) {
462 462
 			throw new ShareNotFound();
463 463
 		}
464 464
 
465
-		return (int)$data['remote_id'];
465
+		return (int) $data['remote_id'];
466 466
 	}
467 467
 
468 468
 	/**
@@ -493,7 +493,7 @@  discard block
 block discarded – undo
493 493
 			->orderBy('id');
494 494
 
495 495
 		$cursor = $qb->execute();
496
-		while($data = $cursor->fetch()) {
496
+		while ($data = $cursor->fetch()) {
497 497
 			$children[] = $this->createShareObject($data);
498 498
 		}
499 499
 		$cursor->closeCursor();
@@ -622,7 +622,7 @@  discard block
 block discarded – undo
622 622
 			);
623 623
 		}
624 624
 
625
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
625
+		$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
626 626
 		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
627 627
 
628 628
 		$qb->orderBy('id');
@@ -685,7 +685,7 @@  discard block
 block discarded – undo
685 685
 
686 686
 		$cursor = $qb->execute();
687 687
 		$shares = [];
688
-		while($data = $cursor->fetch()) {
688
+		while ($data = $cursor->fetch()) {
689 689
 			$shares[] = $this->createShareObject($data);
690 690
 		}
691 691
 		$cursor->closeCursor();
@@ -737,7 +737,7 @@  discard block
 block discarded – undo
737 737
 			->execute();
738 738
 
739 739
 		$shares = [];
740
-		while($data = $cursor->fetch()) {
740
+		while ($data = $cursor->fetch()) {
741 741
 			$shares[] = $this->createShareObject($data);
742 742
 		}
743 743
 		$cursor->closeCursor();
@@ -776,7 +776,7 @@  discard block
 block discarded – undo
776 776
 
777 777
 		$cursor = $qb->execute();
778 778
 
779
-		while($data = $cursor->fetch()) {
779
+		while ($data = $cursor->fetch()) {
780 780
 			$shares[] = $this->createShareObject($data);
781 781
 		}
782 782
 		$cursor->closeCursor();
@@ -853,15 +853,15 @@  discard block
 block discarded – undo
853 853
 	private function createShareObject($data) {
854 854
 
855 855
 		$share = new Share($this->rootFolder, $this->userManager);
856
-		$share->setId((int)$data['id'])
857
-			->setShareType((int)$data['share_type'])
858
-			->setPermissions((int)$data['permissions'])
856
+		$share->setId((int) $data['id'])
857
+			->setShareType((int) $data['share_type'])
858
+			->setPermissions((int) $data['permissions'])
859 859
 			->setTarget($data['file_target'])
860
-			->setMailSend((bool)$data['mail_send'])
860
+			->setMailSend((bool) $data['mail_send'])
861 861
 			->setToken($data['token']);
862 862
 
863 863
 		$shareTime = new \DateTime();
864
-		$shareTime->setTimestamp((int)$data['stime']);
864
+		$shareTime->setTimestamp((int) $data['stime']);
865 865
 		$share->setShareTime($shareTime);
866 866
 		$share->setSharedWith($data['share_with']);
867 867
 
@@ -871,13 +871,13 @@  discard block
 block discarded – undo
871 871
 		} else {
872 872
 			//OLD SHARE
873 873
 			$share->setSharedBy($data['uid_owner']);
874
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
874
+			$path = $this->getNode($share->getSharedBy(), (int) $data['file_source']);
875 875
 
876 876
 			$owner = $path->getOwner();
877 877
 			$share->setShareOwner($owner->getUID());
878 878
 		}
879 879
 
880
-		$share->setNodeId((int)$data['file_source']);
880
+		$share->setNodeId((int) $data['file_source']);
881 881
 		$share->setNodeType($data['item_type']);
882 882
 
883 883
 		$share->setProviderId($this->identifier());
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php 2 patches
Indentation   +284 added lines, -284 removed lines patch added patch discarded remove patch
@@ -57,289 +57,289 @@
 block discarded – undo
57 57
  */
58 58
 class MountPublicLinkController extends Controller {
59 59
 
60
-	/** @var FederatedShareProvider */
61
-	private $federatedShareProvider;
62
-
63
-	/** @var AddressHandler */
64
-	private $addressHandler;
65
-
66
-	/** @var IManager  */
67
-	private $shareManager;
68
-
69
-	/** @var  ISession */
70
-	private $session;
71
-
72
-	/** @var IL10N */
73
-	private $l;
74
-
75
-	/** @var IUserSession */
76
-	private $userSession;
77
-
78
-	/** @var IClientService */
79
-	private $clientService;
80
-
81
-	/** @var ICloudIdManager  */
82
-	private $cloudIdManager;
83
-
84
-	/**
85
-	 * MountPublicLinkController constructor.
86
-	 *
87
-	 * @param string $appName
88
-	 * @param IRequest $request
89
-	 * @param FederatedShareProvider $federatedShareProvider
90
-	 * @param IManager $shareManager
91
-	 * @param AddressHandler $addressHandler
92
-	 * @param ISession $session
93
-	 * @param IL10N $l
94
-	 * @param IUserSession $userSession
95
-	 * @param IClientService $clientService
96
-	 * @param ICloudIdManager $cloudIdManager
97
-	 */
98
-	public function __construct($appName,
99
-								IRequest $request,
100
-								FederatedShareProvider $federatedShareProvider,
101
-								IManager $shareManager,
102
-								AddressHandler $addressHandler,
103
-								ISession $session,
104
-								IL10N $l,
105
-								IUserSession $userSession,
106
-								IClientService $clientService,
107
-								ICloudIdManager $cloudIdManager
108
-	) {
109
-		parent::__construct($appName, $request);
110
-
111
-		$this->federatedShareProvider = $federatedShareProvider;
112
-		$this->shareManager = $shareManager;
113
-		$this->addressHandler = $addressHandler;
114
-		$this->session = $session;
115
-		$this->l = $l;
116
-		$this->userSession = $userSession;
117
-		$this->clientService = $clientService;
118
-		$this->cloudIdManager = $cloudIdManager;
119
-	}
120
-
121
-	/**
122
-	 * send federated share to a user of a public link
123
-	 *
124
-	 * @NoCSRFRequired
125
-	 * @PublicPage
126
-	 * @BruteForceProtection(action=publicLink2FederatedShare)
127
-	 *
128
-	 * @param string $shareWith
129
-	 * @param string $token
130
-	 * @param string $password
131
-	 * @return JSONResponse
132
-	 */
133
-	public function createFederatedShare($shareWith, $token, $password = '') {
134
-
135
-		if (!$this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
136
-			return new JSONResponse(
137
-				['message' => 'This server doesn\'t support outgoing federated shares'],
138
-				Http::STATUS_BAD_REQUEST
139
-			);
140
-		}
141
-
142
-		try {
143
-			list(, $server) = $this->addressHandler->splitUserRemote($shareWith);
144
-			$share = $this->shareManager->getShareByToken($token);
145
-		} catch (HintException $e) {
146
-			return new JSONResponse(['message' => $e->getHint()], Http::STATUS_BAD_REQUEST);
147
-		}
148
-
149
-		// make sure that user is authenticated in case of a password protected link
150
-		$storedPassword = $share->getPassword();
151
-		$authenticated = $this->session->get('public_link_authenticated') === $share->getId() ||
152
-			$this->shareManager->checkPassword($share, $password);
153
-		if (!empty($storedPassword) && !$authenticated ) {
154
-			$response = new JSONResponse(
155
-				['message' => 'No permission to access the share'],
156
-				Http::STATUS_BAD_REQUEST
157
-			);
158
-			$response->throttle();
159
-			return $response;
160
-		}
161
-
162
-		$share->setSharedWith($shareWith);
163
-
164
-		try {
165
-			$this->federatedShareProvider->create($share);
166
-		} catch (\Exception $e) {
167
-			\OC::$server->getLogger()->logException($e, [
168
-				'level' => \OCP\Util::WARN,
169
-				'app' => 'federatedfilesharing',
170
-			]);
171
-			return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
172
-		}
173
-
174
-		return new JSONResponse(['remoteUrl' => $server]);
175
-	}
176
-
177
-	/**
178
-	 * ask other server to get a federated share
179
-	 *
180
-	 * @NoAdminRequired
181
-	 *
182
-	 * @param string $token
183
-	 * @param string $remote
184
-	 * @param string $password
185
-	 * @param string $owner (only for legacy reasons, can be removed with legacyMountPublicLink())
186
-	 * @param string $ownerDisplayName (only for legacy reasons, can be removed with legacyMountPublicLink())
187
-	 * @param string $name (only for legacy reasons, can be removed with legacyMountPublicLink())
188
-	 * @return JSONResponse
189
-	 */
190
-	public function askForFederatedShare($token, $remote, $password = '', $owner = '', $ownerDisplayName = '', $name = '') {
191
-		// check if server admin allows to mount public links from other servers
192
-		if ($this->federatedShareProvider->isIncomingServer2serverShareEnabled() === false) {
193
-			return new JSONResponse(['message' => $this->l->t('Server to server sharing is not enabled on this server')], Http::STATUS_BAD_REQUEST);
194
-		}
195
-
196
-		$cloudId = $this->cloudIdManager->getCloudId($this->userSession->getUser()->getUID(), $this->addressHandler->generateRemoteURL());
197
-
198
-		$httpClient = $this->clientService->newClient();
199
-
200
-		try {
201
-			$response = $httpClient->post($remote . '/index.php/apps/federatedfilesharing/createFederatedShare',
202
-				[
203
-					'body' =>
204
-						[
205
-							'token' => $token,
206
-							'shareWith' => rtrim($cloudId->getId(), '/'),
207
-							'password' => $password
208
-						],
209
-					'connect_timeout' => 10,
210
-				]
211
-			);
212
-		} catch (\Exception $e) {
213
-			if (empty($password)) {
214
-				$message = $this->l->t("Couldn't establish a federated share.");
215
-			} else {
216
-				$message = $this->l->t("Couldn't establish a federated share, maybe the password was wrong.");
217
-			}
218
-			return new JSONResponse(['message' => $message], Http::STATUS_BAD_REQUEST);
219
-		}
220
-
221
-		$body = $response->getBody();
222
-		$result = json_decode($body, true);
223
-
224
-		if (is_array($result) && isset($result['remoteUrl'])) {
225
-			return new JSONResponse(['message' => $this->l->t('Federated Share request sent, you will receive an invitation. Check your notifications.')]);
226
-		}
227
-
228
-		// if we doesn't get the expected response we assume that we try to add
229
-		// a federated share from a Nextcloud <= 9 server
230
-		return $this->legacyMountPublicLink($token, $remote, $password, $name, $owner, $ownerDisplayName);
231
-	}
232
-
233
-	/**
234
-	 * Allow Nextcloud to mount a public link directly
235
-	 *
236
-	 * This code was copied from the apps/files_sharing/ajax/external.php with
237
-	 * minimal changes, just to guarantee backward compatibility
238
-	 *
239
-	 * ToDo: Remove this method once Nextcloud 9 reaches end of life
240
-	 *
241
-	 * @param string $token
242
-	 * @param string $remote
243
-	 * @param string $password
244
-	 * @param string $name
245
-	 * @param string $owner
246
-	 * @param string $ownerDisplayName
247
-	 * @return JSONResponse
248
-	 */
249
-	private function legacyMountPublicLink($token, $remote, $password, $name, $owner, $ownerDisplayName) {
250
-
251
-		// Check for invalid name
252
-		if (!Util::isValidFileName($name)) {
253
-			return new JSONResponse(['message' => $this->l->t('The mountpoint name contains invalid characters.')], Http::STATUS_BAD_REQUEST);
254
-		}
255
-		$currentUser = $this->userSession->getUser()->getUID();
256
-		$currentServer = $this->addressHandler->generateRemoteURL();
257
-		if (Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer)) {
258
-			return new JSONResponse(['message' => $this->l->t('Not allowed to create a federated share with the owner.')], Http::STATUS_BAD_REQUEST);
259
-		}
260
-		$externalManager = new Manager(
261
-			\OC::$server->getDatabaseConnection(),
262
-			Filesystem::getMountManager(),
263
-			Filesystem::getLoader(),
264
-			\OC::$server->getHTTPClientService(),
265
-			\OC::$server->getNotificationManager(),
266
-			\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
267
-			\OC::$server->getUserSession()->getUser()->getUID()
268
-		);
269
-
270
-		// check for ssl cert
271
-
272
-		if (strpos($remote, 'https') === 0) {
273
-			try {
274
-				$client = $this->clientService->newClient();
275
-				$client->get($remote, [
276
-					'timeout' => 10,
277
-					'connect_timeout' => 10,
278
-				])->getBody();
279
-			} catch (\Exception $e) {
280
-				return new JSONResponse(['message' => $this->l->t('Invalid or untrusted SSL certificate')], Http::STATUS_BAD_REQUEST);
281
-			}
282
-		}
283
-		$mount = $externalManager->addShare($remote, $token, $password, $name, $ownerDisplayName, true);
284
-		/**
285
-		 * @var \OCA\Files_Sharing\External\Storage $storage
286
-		 */
287
-		$storage = $mount->getStorage();
288
-		try {
289
-			// check if storage exists
290
-			$storage->checkStorageAvailability();
291
-		} catch (StorageInvalidException $e) {
292
-			// note: checkStorageAvailability will already remove the invalid share
293
-			\OC::$server->getLogger()->logException($e, [
294
-				'message' => 'Invalid remote storage.',
295
-				'level' => \OCP\Util::DEBUG,
296
-				'app' => 'federatedfilesharing'
297
-			]);
298
-			return new JSONResponse(['message' => $this->l->t('Could not authenticate to remote share, password might be wrong')], Http::STATUS_BAD_REQUEST);
299
-		} catch (\Exception $e) {
300
-			\OC::$server->getLogger()->logException($e, [
301
-				'message' => 'Invalid remote storage.',
302
-				'level' => \OCP\Util::DEBUG,
303
-				'app' => 'federatedfilesharing'
304
-			]);
305
-			$externalManager->removeShare($mount->getMountPoint());
306
-			return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST);
307
-		}
308
-		$result = $storage->file_exists('');
309
-		if ($result) {
310
-			try {
311
-				$storage->getScanner()->scanAll();
312
-				return new JSONResponse(
313
-					[
314
-						'message' => $this->l->t('Federated share added'),
315
-						'legacyMount' => '1'
316
-					]
317
-				);
318
-			} catch (StorageInvalidException $e) {
319
-				\OC::$server->getLogger()->logException($e, [
320
-					'message' => 'Invalid remote storage.',
321
-					'level' => \OCP\Util::DEBUG,
322
-					'app' => 'federatedfilesharing'
323
-				]);
324
-				return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST);
325
-			} catch (\Exception $e) {
326
-				\OC::$server->getLogger()->logException($e, [
327
-					'message' => 'Invalid remote storage.',
328
-					'level' => \OCP\Util::DEBUG,
329
-					'app' => 'federatedfilesharing'
330
-				]);
331
-				return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST);
332
-			}
333
-		} else {
334
-			$externalManager->removeShare($mount->getMountPoint());
335
-			Util::writeLog(
336
-				'federatedfilesharing',
337
-				'Couldn\'t add remote share',
338
-				Util::DEBUG
339
-			);
340
-			return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST);
341
-		}
342
-
343
-	}
60
+    /** @var FederatedShareProvider */
61
+    private $federatedShareProvider;
62
+
63
+    /** @var AddressHandler */
64
+    private $addressHandler;
65
+
66
+    /** @var IManager  */
67
+    private $shareManager;
68
+
69
+    /** @var  ISession */
70
+    private $session;
71
+
72
+    /** @var IL10N */
73
+    private $l;
74
+
75
+    /** @var IUserSession */
76
+    private $userSession;
77
+
78
+    /** @var IClientService */
79
+    private $clientService;
80
+
81
+    /** @var ICloudIdManager  */
82
+    private $cloudIdManager;
83
+
84
+    /**
85
+     * MountPublicLinkController constructor.
86
+     *
87
+     * @param string $appName
88
+     * @param IRequest $request
89
+     * @param FederatedShareProvider $federatedShareProvider
90
+     * @param IManager $shareManager
91
+     * @param AddressHandler $addressHandler
92
+     * @param ISession $session
93
+     * @param IL10N $l
94
+     * @param IUserSession $userSession
95
+     * @param IClientService $clientService
96
+     * @param ICloudIdManager $cloudIdManager
97
+     */
98
+    public function __construct($appName,
99
+                                IRequest $request,
100
+                                FederatedShareProvider $federatedShareProvider,
101
+                                IManager $shareManager,
102
+                                AddressHandler $addressHandler,
103
+                                ISession $session,
104
+                                IL10N $l,
105
+                                IUserSession $userSession,
106
+                                IClientService $clientService,
107
+                                ICloudIdManager $cloudIdManager
108
+    ) {
109
+        parent::__construct($appName, $request);
110
+
111
+        $this->federatedShareProvider = $federatedShareProvider;
112
+        $this->shareManager = $shareManager;
113
+        $this->addressHandler = $addressHandler;
114
+        $this->session = $session;
115
+        $this->l = $l;
116
+        $this->userSession = $userSession;
117
+        $this->clientService = $clientService;
118
+        $this->cloudIdManager = $cloudIdManager;
119
+    }
120
+
121
+    /**
122
+     * send federated share to a user of a public link
123
+     *
124
+     * @NoCSRFRequired
125
+     * @PublicPage
126
+     * @BruteForceProtection(action=publicLink2FederatedShare)
127
+     *
128
+     * @param string $shareWith
129
+     * @param string $token
130
+     * @param string $password
131
+     * @return JSONResponse
132
+     */
133
+    public function createFederatedShare($shareWith, $token, $password = '') {
134
+
135
+        if (!$this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
136
+            return new JSONResponse(
137
+                ['message' => 'This server doesn\'t support outgoing federated shares'],
138
+                Http::STATUS_BAD_REQUEST
139
+            );
140
+        }
141
+
142
+        try {
143
+            list(, $server) = $this->addressHandler->splitUserRemote($shareWith);
144
+            $share = $this->shareManager->getShareByToken($token);
145
+        } catch (HintException $e) {
146
+            return new JSONResponse(['message' => $e->getHint()], Http::STATUS_BAD_REQUEST);
147
+        }
148
+
149
+        // make sure that user is authenticated in case of a password protected link
150
+        $storedPassword = $share->getPassword();
151
+        $authenticated = $this->session->get('public_link_authenticated') === $share->getId() ||
152
+            $this->shareManager->checkPassword($share, $password);
153
+        if (!empty($storedPassword) && !$authenticated ) {
154
+            $response = new JSONResponse(
155
+                ['message' => 'No permission to access the share'],
156
+                Http::STATUS_BAD_REQUEST
157
+            );
158
+            $response->throttle();
159
+            return $response;
160
+        }
161
+
162
+        $share->setSharedWith($shareWith);
163
+
164
+        try {
165
+            $this->federatedShareProvider->create($share);
166
+        } catch (\Exception $e) {
167
+            \OC::$server->getLogger()->logException($e, [
168
+                'level' => \OCP\Util::WARN,
169
+                'app' => 'federatedfilesharing',
170
+            ]);
171
+            return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
172
+        }
173
+
174
+        return new JSONResponse(['remoteUrl' => $server]);
175
+    }
176
+
177
+    /**
178
+     * ask other server to get a federated share
179
+     *
180
+     * @NoAdminRequired
181
+     *
182
+     * @param string $token
183
+     * @param string $remote
184
+     * @param string $password
185
+     * @param string $owner (only for legacy reasons, can be removed with legacyMountPublicLink())
186
+     * @param string $ownerDisplayName (only for legacy reasons, can be removed with legacyMountPublicLink())
187
+     * @param string $name (only for legacy reasons, can be removed with legacyMountPublicLink())
188
+     * @return JSONResponse
189
+     */
190
+    public function askForFederatedShare($token, $remote, $password = '', $owner = '', $ownerDisplayName = '', $name = '') {
191
+        // check if server admin allows to mount public links from other servers
192
+        if ($this->federatedShareProvider->isIncomingServer2serverShareEnabled() === false) {
193
+            return new JSONResponse(['message' => $this->l->t('Server to server sharing is not enabled on this server')], Http::STATUS_BAD_REQUEST);
194
+        }
195
+
196
+        $cloudId = $this->cloudIdManager->getCloudId($this->userSession->getUser()->getUID(), $this->addressHandler->generateRemoteURL());
197
+
198
+        $httpClient = $this->clientService->newClient();
199
+
200
+        try {
201
+            $response = $httpClient->post($remote . '/index.php/apps/federatedfilesharing/createFederatedShare',
202
+                [
203
+                    'body' =>
204
+                        [
205
+                            'token' => $token,
206
+                            'shareWith' => rtrim($cloudId->getId(), '/'),
207
+                            'password' => $password
208
+                        ],
209
+                    'connect_timeout' => 10,
210
+                ]
211
+            );
212
+        } catch (\Exception $e) {
213
+            if (empty($password)) {
214
+                $message = $this->l->t("Couldn't establish a federated share.");
215
+            } else {
216
+                $message = $this->l->t("Couldn't establish a federated share, maybe the password was wrong.");
217
+            }
218
+            return new JSONResponse(['message' => $message], Http::STATUS_BAD_REQUEST);
219
+        }
220
+
221
+        $body = $response->getBody();
222
+        $result = json_decode($body, true);
223
+
224
+        if (is_array($result) && isset($result['remoteUrl'])) {
225
+            return new JSONResponse(['message' => $this->l->t('Federated Share request sent, you will receive an invitation. Check your notifications.')]);
226
+        }
227
+
228
+        // if we doesn't get the expected response we assume that we try to add
229
+        // a federated share from a Nextcloud <= 9 server
230
+        return $this->legacyMountPublicLink($token, $remote, $password, $name, $owner, $ownerDisplayName);
231
+    }
232
+
233
+    /**
234
+     * Allow Nextcloud to mount a public link directly
235
+     *
236
+     * This code was copied from the apps/files_sharing/ajax/external.php with
237
+     * minimal changes, just to guarantee backward compatibility
238
+     *
239
+     * ToDo: Remove this method once Nextcloud 9 reaches end of life
240
+     *
241
+     * @param string $token
242
+     * @param string $remote
243
+     * @param string $password
244
+     * @param string $name
245
+     * @param string $owner
246
+     * @param string $ownerDisplayName
247
+     * @return JSONResponse
248
+     */
249
+    private function legacyMountPublicLink($token, $remote, $password, $name, $owner, $ownerDisplayName) {
250
+
251
+        // Check for invalid name
252
+        if (!Util::isValidFileName($name)) {
253
+            return new JSONResponse(['message' => $this->l->t('The mountpoint name contains invalid characters.')], Http::STATUS_BAD_REQUEST);
254
+        }
255
+        $currentUser = $this->userSession->getUser()->getUID();
256
+        $currentServer = $this->addressHandler->generateRemoteURL();
257
+        if (Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer)) {
258
+            return new JSONResponse(['message' => $this->l->t('Not allowed to create a federated share with the owner.')], Http::STATUS_BAD_REQUEST);
259
+        }
260
+        $externalManager = new Manager(
261
+            \OC::$server->getDatabaseConnection(),
262
+            Filesystem::getMountManager(),
263
+            Filesystem::getLoader(),
264
+            \OC::$server->getHTTPClientService(),
265
+            \OC::$server->getNotificationManager(),
266
+            \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
267
+            \OC::$server->getUserSession()->getUser()->getUID()
268
+        );
269
+
270
+        // check for ssl cert
271
+
272
+        if (strpos($remote, 'https') === 0) {
273
+            try {
274
+                $client = $this->clientService->newClient();
275
+                $client->get($remote, [
276
+                    'timeout' => 10,
277
+                    'connect_timeout' => 10,
278
+                ])->getBody();
279
+            } catch (\Exception $e) {
280
+                return new JSONResponse(['message' => $this->l->t('Invalid or untrusted SSL certificate')], Http::STATUS_BAD_REQUEST);
281
+            }
282
+        }
283
+        $mount = $externalManager->addShare($remote, $token, $password, $name, $ownerDisplayName, true);
284
+        /**
285
+         * @var \OCA\Files_Sharing\External\Storage $storage
286
+         */
287
+        $storage = $mount->getStorage();
288
+        try {
289
+            // check if storage exists
290
+            $storage->checkStorageAvailability();
291
+        } catch (StorageInvalidException $e) {
292
+            // note: checkStorageAvailability will already remove the invalid share
293
+            \OC::$server->getLogger()->logException($e, [
294
+                'message' => 'Invalid remote storage.',
295
+                'level' => \OCP\Util::DEBUG,
296
+                'app' => 'federatedfilesharing'
297
+            ]);
298
+            return new JSONResponse(['message' => $this->l->t('Could not authenticate to remote share, password might be wrong')], Http::STATUS_BAD_REQUEST);
299
+        } catch (\Exception $e) {
300
+            \OC::$server->getLogger()->logException($e, [
301
+                'message' => 'Invalid remote storage.',
302
+                'level' => \OCP\Util::DEBUG,
303
+                'app' => 'federatedfilesharing'
304
+            ]);
305
+            $externalManager->removeShare($mount->getMountPoint());
306
+            return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST);
307
+        }
308
+        $result = $storage->file_exists('');
309
+        if ($result) {
310
+            try {
311
+                $storage->getScanner()->scanAll();
312
+                return new JSONResponse(
313
+                    [
314
+                        'message' => $this->l->t('Federated share added'),
315
+                        'legacyMount' => '1'
316
+                    ]
317
+                );
318
+            } catch (StorageInvalidException $e) {
319
+                \OC::$server->getLogger()->logException($e, [
320
+                    'message' => 'Invalid remote storage.',
321
+                    'level' => \OCP\Util::DEBUG,
322
+                    'app' => 'federatedfilesharing'
323
+                ]);
324
+                return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST);
325
+            } catch (\Exception $e) {
326
+                \OC::$server->getLogger()->logException($e, [
327
+                    'message' => 'Invalid remote storage.',
328
+                    'level' => \OCP\Util::DEBUG,
329
+                    'app' => 'federatedfilesharing'
330
+                ]);
331
+                return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST);
332
+            }
333
+        } else {
334
+            $externalManager->removeShare($mount->getMountPoint());
335
+            Util::writeLog(
336
+                'federatedfilesharing',
337
+                'Couldn\'t add remote share',
338
+                Util::DEBUG
339
+            );
340
+            return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST);
341
+        }
342
+
343
+    }
344 344
 
345 345
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -150,7 +150,7 @@  discard block
 block discarded – undo
150 150
 		$storedPassword = $share->getPassword();
151 151
 		$authenticated = $this->session->get('public_link_authenticated') === $share->getId() ||
152 152
 			$this->shareManager->checkPassword($share, $password);
153
-		if (!empty($storedPassword) && !$authenticated ) {
153
+		if (!empty($storedPassword) && !$authenticated) {
154 154
 			$response = new JSONResponse(
155 155
 				['message' => 'No permission to access the share'],
156 156
 				Http::STATUS_BAD_REQUEST
@@ -198,7 +198,7 @@  discard block
 block discarded – undo
198 198
 		$httpClient = $this->clientService->newClient();
199 199
 
200 200
 		try {
201
-			$response = $httpClient->post($remote . '/index.php/apps/federatedfilesharing/createFederatedShare',
201
+			$response = $httpClient->post($remote.'/index.php/apps/federatedfilesharing/createFederatedShare',
202 202
 				[
203 203
 					'body' =>
204 204
 						[
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/Controller/RequestHandlerController.php 2 patches
Indentation   +611 added lines, -611 removed lines patch added patch discarded remove patch
@@ -50,615 +50,615 @@
 block discarded – undo
50 50
 
51 51
 class RequestHandlerController extends OCSController {
52 52
 
53
-	/** @var FederatedShareProvider */
54
-	private $federatedShareProvider;
55
-
56
-	/** @var IDBConnection */
57
-	private $connection;
58
-
59
-	/** @var Share\IManager */
60
-	private $shareManager;
61
-
62
-	/** @var Notifications */
63
-	private $notifications;
64
-
65
-	/** @var AddressHandler */
66
-	private $addressHandler;
67
-
68
-	/** @var  IUserManager */
69
-	private $userManager;
70
-
71
-	/** @var string */
72
-	private $shareTable = 'share';
73
-
74
-	/** @var ICloudIdManager */
75
-	private $cloudIdManager;
76
-
77
-	/**
78
-	 * Server2Server constructor.
79
-	 *
80
-	 * @param string $appName
81
-	 * @param IRequest $request
82
-	 * @param FederatedShareProvider $federatedShareProvider
83
-	 * @param IDBConnection $connection
84
-	 * @param Share\IManager $shareManager
85
-	 * @param Notifications $notifications
86
-	 * @param AddressHandler $addressHandler
87
-	 * @param IUserManager $userManager
88
-	 * @param ICloudIdManager $cloudIdManager
89
-	 */
90
-	public function __construct($appName,
91
-								IRequest $request,
92
-								FederatedShareProvider $federatedShareProvider,
93
-								IDBConnection $connection,
94
-								Share\IManager $shareManager,
95
-								Notifications $notifications,
96
-								AddressHandler $addressHandler,
97
-								IUserManager $userManager,
98
-								ICloudIdManager $cloudIdManager
99
-	) {
100
-		parent::__construct($appName, $request);
101
-
102
-		$this->federatedShareProvider = $federatedShareProvider;
103
-		$this->connection = $connection;
104
-		$this->shareManager = $shareManager;
105
-		$this->notifications = $notifications;
106
-		$this->addressHandler = $addressHandler;
107
-		$this->userManager = $userManager;
108
-		$this->cloudIdManager = $cloudIdManager;
109
-	}
110
-
111
-	/**
112
-	 * @NoCSRFRequired
113
-	 * @PublicPage
114
-	 *
115
-	 * create a new share
116
-	 *
117
-	 * @return Http\DataResponse
118
-	 * @throws OCSException
119
-	 */
120
-	public function createShare() {
121
-
122
-		if (!$this->isS2SEnabled(true)) {
123
-			throw new OCSException('Server does not support federated cloud sharing', 503);
124
-		}
125
-
126
-		$remote = isset($_POST['remote']) ? $_POST['remote'] : null;
127
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
128
-		$name = isset($_POST['name']) ? $_POST['name'] : null;
129
-		$owner = isset($_POST['owner']) ? $_POST['owner'] : null;
130
-		$sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null;
131
-		$shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
132
-		$remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
133
-		$sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null;
134
-		$ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null;
135
-
136
-		if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
137
-
138
-			if (!\OCP\Util::isValidFileName($name)) {
139
-				throw new OCSException('The mountpoint name contains invalid characters.', 400);
140
-			}
141
-
142
-			// FIXME this should be a method in the user management instead
143
-			\OCP\Util::writeLog('files_sharing', 'shareWith before, ' . $shareWith, \OCP\Util::DEBUG);
144
-			\OCP\Util::emitHook(
145
-				'\OCA\Files_Sharing\API\Server2Server',
146
-				'preLoginNameUsedAsUserName',
147
-				array('uid' => &$shareWith)
148
-			);
149
-			\OCP\Util::writeLog('files_sharing', 'shareWith after, ' . $shareWith, \OCP\Util::DEBUG);
150
-
151
-			if (!\OC::$server->getUserManager()->userExists($shareWith)) {
152
-				throw new OCSException('User does not exists', 400);
153
-			}
154
-
155
-			\OC_Util::setupFS($shareWith);
156
-
157
-			$externalManager = new \OCA\Files_Sharing\External\Manager(
158
-					\OC::$server->getDatabaseConnection(),
159
-					\OC\Files\Filesystem::getMountManager(),
160
-					\OC\Files\Filesystem::getLoader(),
161
-					\OC::$server->getHTTPClientService(),
162
-					\OC::$server->getNotificationManager(),
163
-					\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
164
-					$shareWith
165
-				);
166
-
167
-			try {
168
-				$externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId);
169
-				$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
170
-
171
-				if ($ownerFederatedId === null) {
172
-					$ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId();
173
-				}
174
-				// if the owner of the share and the initiator are the same user
175
-				// we also complete the federated share ID for the initiator
176
-				if ($sharedByFederatedId === null && $owner === $sharedBy) {
177
-					$sharedByFederatedId = $ownerFederatedId;
178
-				}
179
-
180
-				$event = \OC::$server->getActivityManager()->generateEvent();
181
-				$event->setApp('files_sharing')
182
-					->setType('remote_share')
183
-					->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
184
-					->setAffectedUser($shareWith)
185
-					->setObject('remote_share', (int)$shareId, $name);
186
-				\OC::$server->getActivityManager()->publish($event);
187
-
188
-				$urlGenerator = \OC::$server->getURLGenerator();
189
-
190
-				$notificationManager = \OC::$server->getNotificationManager();
191
-				$notification = $notificationManager->createNotification();
192
-				$notification->setApp('files_sharing')
193
-					->setUser($shareWith)
194
-					->setDateTime(new \DateTime())
195
-					->setObject('remote_share', $shareId)
196
-					->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/')]);
197
-
198
-				$declineAction = $notification->createAction();
199
-				$declineAction->setLabel('decline')
200
-					->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
201
-				$notification->addAction($declineAction);
202
-
203
-				$acceptAction = $notification->createAction();
204
-				$acceptAction->setLabel('accept')
205
-					->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
206
-				$notification->addAction($acceptAction);
207
-
208
-				$notificationManager->notify($notification);
209
-
210
-				return new Http\DataResponse();
211
-			} catch (\Exception $e) {
212
-				\OC::$server->getLogger()->logException($e, [
213
-					'message' => 'Server can not add remote share.',
214
-					'level' => \OCP\Util::ERROR,
215
-					'app' => 'files_sharing'
216
-				]);
217
-				throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
218
-			}
219
-		}
220
-
221
-		throw new OCSException('server can not add remote share, missing parameter', 400);
222
-	}
223
-
224
-	/**
225
-	 * @NoCSRFRequired
226
-	 * @PublicPage
227
-	 *
228
-	 * create re-share on behalf of another user
229
-	 *
230
-	 * @param int $id
231
-	 * @return Http\DataResponse
232
-	 * @throws OCSBadRequestException
233
-	 * @throws OCSForbiddenException
234
-	 * @throws OCSNotFoundException
235
-	 */
236
-	public function reShare($id) {
237
-
238
-		$token = $this->request->getParam('token', null);
239
-		$shareWith = $this->request->getParam('shareWith', null);
240
-		$permission = (int)$this->request->getParam('permission', null);
241
-		$remoteId = (int)$this->request->getParam('remoteId', null);
242
-
243
-		if ($id === null ||
244
-			$token === null ||
245
-			$shareWith === null ||
246
-			$permission === null ||
247
-			$remoteId === null
248
-		) {
249
-			throw new OCSBadRequestException();
250
-		}
251
-
252
-		try {
253
-			$share = $this->federatedShareProvider->getShareById($id);
254
-		} catch (Share\Exceptions\ShareNotFound $e) {
255
-			throw new OCSNotFoundException();
256
-		}
257
-
258
-		// don't allow to share a file back to the owner
259
-		list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
260
-		$owner = $share->getShareOwner();
261
-		$currentServer = $this->addressHandler->generateRemoteURL();
262
-		if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
263
-			throw new OCSForbiddenException();
264
-		}
265
-
266
-		if ($this->verifyShare($share, $token)) {
267
-
268
-			// check if re-sharing is allowed
269
-			if ($share->getPermissions() | ~Constants::PERMISSION_SHARE) {
270
-				$share->setPermissions($share->getPermissions() & $permission);
271
-				// the recipient of the initial share is now the initiator for the re-share
272
-				$share->setSharedBy($share->getSharedWith());
273
-				$share->setSharedWith($shareWith);
274
-				try {
275
-					$result = $this->federatedShareProvider->create($share);
276
-					$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $remoteId);
277
-					return new Http\DataResponse([
278
-						'token' => $result->getToken(),
279
-						'remoteId' => $result->getId()
280
-					]);
281
-				} catch (\Exception $e) {
282
-					throw new OCSBadRequestException();
283
-				}
284
-			} else {
285
-				throw new OCSForbiddenException();
286
-			}
287
-		}
288
-		throw new OCSBadRequestException();
289
-	}
290
-
291
-	/**
292
-	 * @NoCSRFRequired
293
-	 * @PublicPage
294
-	 *
295
-	 * accept server-to-server share
296
-	 *
297
-	 * @param int $id
298
-	 * @return Http\DataResponse
299
-	 * @throws OCSException
300
-	 */
301
-	public function acceptShare($id) {
302
-
303
-		if (!$this->isS2SEnabled()) {
304
-			throw new OCSException('Server does not support federated cloud sharing', 503);
305
-		}
306
-
307
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
308
-
309
-		try {
310
-			$share = $this->federatedShareProvider->getShareById($id);
311
-		} catch (Share\Exceptions\ShareNotFound $e) {
312
-			return new Http\DataResponse();
313
-		}
314
-
315
-		if ($this->verifyShare($share, $token)) {
316
-			$this->executeAcceptShare($share);
317
-			if ($share->getShareOwner() !== $share->getSharedBy()) {
318
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
319
-				$remoteId = $this->federatedShareProvider->getRemoteId($share);
320
-				$this->notifications->sendAcceptShare($remote, $remoteId, $share->getToken());
321
-			}
322
-		}
323
-
324
-		return new Http\DataResponse();
325
-	}
326
-
327
-	protected function executeAcceptShare(Share\IShare $share) {
328
-		$fileId = (int) $share->getNode()->getId();
329
-		list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
330
-
331
-		$event = \OC::$server->getActivityManager()->generateEvent();
332
-		$event->setApp('files_sharing')
333
-			->setType('remote_share')
334
-			->setAffectedUser($this->getCorrectUid($share))
335
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
336
-			->setObject('files', $fileId, $file)
337
-			->setLink($link);
338
-		\OC::$server->getActivityManager()->publish($event);
339
-	}
340
-
341
-	/**
342
-	 * @NoCSRFRequired
343
-	 * @PublicPage
344
-	 *
345
-	 * decline server-to-server share
346
-	 *
347
-	 * @param int $id
348
-	 * @return Http\DataResponse
349
-	 * @throws OCSException
350
-	 */
351
-	public function declineShare($id) {
352
-
353
-		if (!$this->isS2SEnabled()) {
354
-			throw new OCSException('Server does not support federated cloud sharing', 503);
355
-		}
356
-
357
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
358
-
359
-		try {
360
-			$share = $this->federatedShareProvider->getShareById($id);
361
-		} catch (Share\Exceptions\ShareNotFound $e) {
362
-			return new Http\DataResponse();
363
-		}
364
-
365
-		if ($this->verifyShare($share, $token)) {
366
-			if ($share->getShareOwner() !== $share->getSharedBy()) {
367
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
368
-				$remoteId = $this->federatedShareProvider->getRemoteId($share);
369
-				$this->notifications->sendDeclineShare($remote, $remoteId, $share->getToken());
370
-			}
371
-			$this->executeDeclineShare($share);
372
-		}
373
-
374
-		return new Http\DataResponse();
375
-	}
376
-
377
-	/**
378
-	 * delete declined share and create a activity
379
-	 *
380
-	 * @param Share\IShare $share
381
-	 */
382
-	protected function executeDeclineShare(Share\IShare $share) {
383
-		$this->federatedShareProvider->removeShareFromTable($share);
384
-		$fileId = (int) $share->getNode()->getId();
385
-		list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
386
-
387
-		$event = \OC::$server->getActivityManager()->generateEvent();
388
-		$event->setApp('files_sharing')
389
-			->setType('remote_share')
390
-			->setAffectedUser($this->getCorrectUid($share))
391
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
392
-			->setObject('files', $fileId, $file)
393
-			->setLink($link);
394
-		\OC::$server->getActivityManager()->publish($event);
395
-
396
-	}
397
-
398
-	/**
399
-	 * check if we are the initiator or the owner of a re-share and return the correct UID
400
-	 *
401
-	 * @param Share\IShare $share
402
-	 * @return string
403
-	 */
404
-	protected function getCorrectUid(Share\IShare $share) {
405
-		if ($this->userManager->userExists($share->getShareOwner())) {
406
-			return $share->getShareOwner();
407
-		}
408
-
409
-		return $share->getSharedBy();
410
-	}
411
-
412
-	/**
413
-	 * @NoCSRFRequired
414
-	 * @PublicPage
415
-	 *
416
-	 * remove server-to-server share if it was unshared by the owner
417
-	 *
418
-	 * @param int $id
419
-	 * @return Http\DataResponse
420
-	 * @throws OCSException
421
-	 */
422
-	public function unshare($id) {
423
-
424
-		if (!$this->isS2SEnabled()) {
425
-			throw new OCSException('Server does not support federated cloud sharing', 503);
426
-		}
427
-
428
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
429
-
430
-		$query = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share_external` WHERE `remote_id` = ? AND `share_token` = ?');
431
-		$query->execute(array($id, $token));
432
-		$share = $query->fetchRow();
433
-
434
-		if ($token && $id && !empty($share)) {
435
-
436
-			$remote = $this->cleanupRemote($share['remote']);
437
-
438
-			$owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
439
-			$mountpoint = $share['mountpoint'];
440
-			$user = $share['user'];
441
-
442
-			$query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share_external` WHERE `remote_id` = ? AND `share_token` = ?');
443
-			$query->execute(array($id, $token));
444
-
445
-			if ($share['accepted']) {
446
-				$path = trim($mountpoint, '/');
447
-			} else {
448
-				$path = trim($share['name'], '/');
449
-			}
450
-
451
-			$notificationManager = \OC::$server->getNotificationManager();
452
-			$notification = $notificationManager->createNotification();
453
-			$notification->setApp('files_sharing')
454
-				->setUser($share['user'])
455
-				->setObject('remote_share', (int)$share['id']);
456
-			$notificationManager->markProcessed($notification);
457
-
458
-			$event = \OC::$server->getActivityManager()->generateEvent();
459
-			$event->setApp('files_sharing')
460
-				->setType('remote_share')
461
-				->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
462
-				->setAffectedUser($user)
463
-				->setObject('remote_share', (int)$share['id'], $path);
464
-			\OC::$server->getActivityManager()->publish($event);
465
-		}
466
-
467
-		return new Http\DataResponse();
468
-	}
469
-
470
-	private function cleanupRemote($remote) {
471
-		$remote = substr($remote, strpos($remote, '://') + 3);
472
-
473
-		return rtrim($remote, '/');
474
-	}
475
-
476
-
477
-	/**
478
-	 * @NoCSRFRequired
479
-	 * @PublicPage
480
-	 *
481
-	 * federated share was revoked, either by the owner or the re-sharer
482
-	 *
483
-	 * @param int $id
484
-	 * @return Http\DataResponse
485
-	 * @throws OCSBadRequestException
486
-	 */
487
-	public function revoke($id) {
488
-		$token = $this->request->getParam('token');
489
-
490
-		$share = $this->federatedShareProvider->getShareById($id);
491
-
492
-		if ($this->verifyShare($share, $token)) {
493
-			$this->federatedShareProvider->removeShareFromTable($share);
494
-			return new Http\DataResponse();
495
-		}
496
-
497
-		throw new OCSBadRequestException();
498
-	}
499
-
500
-	/**
501
-	 * get share
502
-	 *
503
-	 * @param int $id
504
-	 * @param string $token
505
-	 * @return array|bool
506
-	 */
507
-	protected function getShare($id, $token) {
508
-		$query = $this->connection->getQueryBuilder();
509
-		$query->select('*')->from($this->shareTable)
510
-			->where($query->expr()->eq('token', $query->createNamedParameter($token)))
511
-			->andWhere($query->expr()->eq('share_type', $query->createNamedParameter(FederatedShareProvider::SHARE_TYPE_REMOTE)))
512
-			->andWhere($query->expr()->eq('id', $query->createNamedParameter($id)));
513
-
514
-		$result = $query->execute()->fetchAll();
515
-
516
-		if (!empty($result) && isset($result[0])) {
517
-			return $result[0];
518
-		}
519
-
520
-		return false;
521
-	}
522
-
523
-	/**
524
-	 * get file
525
-	 *
526
-	 * @param string $user
527
-	 * @param int $fileSource
528
-	 * @return array with internal path of the file and a absolute link to it
529
-	 */
530
-	private function getFile($user, $fileSource) {
531
-		\OC_Util::setupFS($user);
532
-
533
-		try {
534
-			$file = \OC\Files\Filesystem::getPath($fileSource);
535
-		} catch (NotFoundException $e) {
536
-			$file = null;
537
-		}
538
-		$args = \OC\Files\Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
539
-		$link = \OCP\Util::linkToAbsolute('files', 'index.php', $args);
540
-
541
-		return array($file, $link);
542
-
543
-	}
544
-
545
-	/**
546
-	 * check if server-to-server sharing is enabled
547
-	 *
548
-	 * @param bool $incoming
549
-	 * @return bool
550
-	 */
551
-	private function isS2SEnabled($incoming = false) {
552
-
553
-		$result = \OCP\App::isEnabled('files_sharing');
554
-
555
-		if ($incoming) {
556
-			$result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
557
-		} else {
558
-			$result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
559
-		}
560
-
561
-		return $result;
562
-	}
563
-
564
-	/**
565
-	 * check if we got the right share
566
-	 *
567
-	 * @param Share\IShare $share
568
-	 * @param string $token
569
-	 * @return bool
570
-	 */
571
-	protected function verifyShare(Share\IShare $share, $token) {
572
-		if (
573
-			$share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
574
-			$share->getToken() === $token
575
-		) {
576
-			return true;
577
-		}
578
-
579
-		return false;
580
-	}
581
-
582
-	/**
583
-	 * @NoCSRFRequired
584
-	 * @PublicPage
585
-	 *
586
-	 * update share information to keep federated re-shares in sync
587
-	 *
588
-	 * @param int $id
589
-	 * @return Http\DataResponse
590
-	 * @throws OCSBadRequestException
591
-	 */
592
-	public function updatePermissions($id) {
593
-		$token = $this->request->getParam('token', null);
594
-		$permissions = $this->request->getParam('permissions', null);
595
-
596
-		try {
597
-			$share = $this->federatedShareProvider->getShareById($id);
598
-		} catch (Share\Exceptions\ShareNotFound $e) {
599
-			throw new OCSBadRequestException();
600
-		}
601
-
602
-		$validPermission = ctype_digit($permissions);
603
-		$validToken = $this->verifyShare($share, $token);
604
-		if ($validPermission && $validToken) {
605
-			$this->updatePermissionsInDatabase($share, (int)$permissions);
606
-		} else {
607
-			throw new OCSBadRequestException();
608
-		}
609
-
610
-		return new Http\DataResponse();
611
-	}
612
-
613
-	/**
614
-	 * update permissions in database
615
-	 *
616
-	 * @param IShare $share
617
-	 * @param int $permissions
618
-	 */
619
-	protected function updatePermissionsInDatabase(IShare $share, $permissions) {
620
-		$query = $this->connection->getQueryBuilder();
621
-		$query->update('share')
622
-			->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
623
-			->set('permissions', $query->createNamedParameter($permissions))
624
-			->execute();
625
-	}
626
-
627
-	/**
628
-	 * @NoCSRFRequired
629
-	 * @PublicPage
630
-	 *
631
-	 * change the owner of a server-to-server share
632
-	 *
633
-	 * @param int $id
634
-	 * @return Http\DataResponse
635
-	 * @throws \InvalidArgumentException
636
-	 * @throws OCSException
637
-	 */
638
-	public function move($id) {
639
-
640
-		if (!$this->isS2SEnabled()) {
641
-			throw new OCSException('Server does not support federated cloud sharing', 503);
642
-		}
643
-
644
-		$token = $this->request->getParam('token');
645
-		$remote = $this->request->getParam('remote');
646
-		$newRemoteId = $this->request->getParam('remote_id', $id);
647
-		$cloudId = $this->cloudIdManager->resolveCloudId($remote);
648
-
649
-		$qb = $this->connection->getQueryBuilder();
650
-		$query = $qb->update('share_external')
651
-			->set('remote', $qb->createNamedParameter($cloudId->getRemote()))
652
-			->set('owner', $qb->createNamedParameter($cloudId->getUser()))
653
-			->set('remote_id', $qb->createNamedParameter($newRemoteId))
654
-			->where($qb->expr()->eq('remote_id', $qb->createNamedParameter($id)))
655
-			->andWhere($qb->expr()->eq('share_token', $qb->createNamedParameter($token)));
656
-		$affected = $query->execute();
657
-
658
-		if ($affected > 0) {
659
-			return new Http\DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]);
660
-		} else {
661
-			throw new OCSBadRequestException('Share not found or token invalid');
662
-		}
663
-	}
53
+    /** @var FederatedShareProvider */
54
+    private $federatedShareProvider;
55
+
56
+    /** @var IDBConnection */
57
+    private $connection;
58
+
59
+    /** @var Share\IManager */
60
+    private $shareManager;
61
+
62
+    /** @var Notifications */
63
+    private $notifications;
64
+
65
+    /** @var AddressHandler */
66
+    private $addressHandler;
67
+
68
+    /** @var  IUserManager */
69
+    private $userManager;
70
+
71
+    /** @var string */
72
+    private $shareTable = 'share';
73
+
74
+    /** @var ICloudIdManager */
75
+    private $cloudIdManager;
76
+
77
+    /**
78
+     * Server2Server constructor.
79
+     *
80
+     * @param string $appName
81
+     * @param IRequest $request
82
+     * @param FederatedShareProvider $federatedShareProvider
83
+     * @param IDBConnection $connection
84
+     * @param Share\IManager $shareManager
85
+     * @param Notifications $notifications
86
+     * @param AddressHandler $addressHandler
87
+     * @param IUserManager $userManager
88
+     * @param ICloudIdManager $cloudIdManager
89
+     */
90
+    public function __construct($appName,
91
+                                IRequest $request,
92
+                                FederatedShareProvider $federatedShareProvider,
93
+                                IDBConnection $connection,
94
+                                Share\IManager $shareManager,
95
+                                Notifications $notifications,
96
+                                AddressHandler $addressHandler,
97
+                                IUserManager $userManager,
98
+                                ICloudIdManager $cloudIdManager
99
+    ) {
100
+        parent::__construct($appName, $request);
101
+
102
+        $this->federatedShareProvider = $federatedShareProvider;
103
+        $this->connection = $connection;
104
+        $this->shareManager = $shareManager;
105
+        $this->notifications = $notifications;
106
+        $this->addressHandler = $addressHandler;
107
+        $this->userManager = $userManager;
108
+        $this->cloudIdManager = $cloudIdManager;
109
+    }
110
+
111
+    /**
112
+     * @NoCSRFRequired
113
+     * @PublicPage
114
+     *
115
+     * create a new share
116
+     *
117
+     * @return Http\DataResponse
118
+     * @throws OCSException
119
+     */
120
+    public function createShare() {
121
+
122
+        if (!$this->isS2SEnabled(true)) {
123
+            throw new OCSException('Server does not support federated cloud sharing', 503);
124
+        }
125
+
126
+        $remote = isset($_POST['remote']) ? $_POST['remote'] : null;
127
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
128
+        $name = isset($_POST['name']) ? $_POST['name'] : null;
129
+        $owner = isset($_POST['owner']) ? $_POST['owner'] : null;
130
+        $sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null;
131
+        $shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
132
+        $remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
133
+        $sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null;
134
+        $ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null;
135
+
136
+        if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
137
+
138
+            if (!\OCP\Util::isValidFileName($name)) {
139
+                throw new OCSException('The mountpoint name contains invalid characters.', 400);
140
+            }
141
+
142
+            // FIXME this should be a method in the user management instead
143
+            \OCP\Util::writeLog('files_sharing', 'shareWith before, ' . $shareWith, \OCP\Util::DEBUG);
144
+            \OCP\Util::emitHook(
145
+                '\OCA\Files_Sharing\API\Server2Server',
146
+                'preLoginNameUsedAsUserName',
147
+                array('uid' => &$shareWith)
148
+            );
149
+            \OCP\Util::writeLog('files_sharing', 'shareWith after, ' . $shareWith, \OCP\Util::DEBUG);
150
+
151
+            if (!\OC::$server->getUserManager()->userExists($shareWith)) {
152
+                throw new OCSException('User does not exists', 400);
153
+            }
154
+
155
+            \OC_Util::setupFS($shareWith);
156
+
157
+            $externalManager = new \OCA\Files_Sharing\External\Manager(
158
+                    \OC::$server->getDatabaseConnection(),
159
+                    \OC\Files\Filesystem::getMountManager(),
160
+                    \OC\Files\Filesystem::getLoader(),
161
+                    \OC::$server->getHTTPClientService(),
162
+                    \OC::$server->getNotificationManager(),
163
+                    \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
164
+                    $shareWith
165
+                );
166
+
167
+            try {
168
+                $externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId);
169
+                $shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
170
+
171
+                if ($ownerFederatedId === null) {
172
+                    $ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId();
173
+                }
174
+                // if the owner of the share and the initiator are the same user
175
+                // we also complete the federated share ID for the initiator
176
+                if ($sharedByFederatedId === null && $owner === $sharedBy) {
177
+                    $sharedByFederatedId = $ownerFederatedId;
178
+                }
179
+
180
+                $event = \OC::$server->getActivityManager()->generateEvent();
181
+                $event->setApp('files_sharing')
182
+                    ->setType('remote_share')
183
+                    ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
184
+                    ->setAffectedUser($shareWith)
185
+                    ->setObject('remote_share', (int)$shareId, $name);
186
+                \OC::$server->getActivityManager()->publish($event);
187
+
188
+                $urlGenerator = \OC::$server->getURLGenerator();
189
+
190
+                $notificationManager = \OC::$server->getNotificationManager();
191
+                $notification = $notificationManager->createNotification();
192
+                $notification->setApp('files_sharing')
193
+                    ->setUser($shareWith)
194
+                    ->setDateTime(new \DateTime())
195
+                    ->setObject('remote_share', $shareId)
196
+                    ->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/')]);
197
+
198
+                $declineAction = $notification->createAction();
199
+                $declineAction->setLabel('decline')
200
+                    ->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
201
+                $notification->addAction($declineAction);
202
+
203
+                $acceptAction = $notification->createAction();
204
+                $acceptAction->setLabel('accept')
205
+                    ->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
206
+                $notification->addAction($acceptAction);
207
+
208
+                $notificationManager->notify($notification);
209
+
210
+                return new Http\DataResponse();
211
+            } catch (\Exception $e) {
212
+                \OC::$server->getLogger()->logException($e, [
213
+                    'message' => 'Server can not add remote share.',
214
+                    'level' => \OCP\Util::ERROR,
215
+                    'app' => 'files_sharing'
216
+                ]);
217
+                throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
218
+            }
219
+        }
220
+
221
+        throw new OCSException('server can not add remote share, missing parameter', 400);
222
+    }
223
+
224
+    /**
225
+     * @NoCSRFRequired
226
+     * @PublicPage
227
+     *
228
+     * create re-share on behalf of another user
229
+     *
230
+     * @param int $id
231
+     * @return Http\DataResponse
232
+     * @throws OCSBadRequestException
233
+     * @throws OCSForbiddenException
234
+     * @throws OCSNotFoundException
235
+     */
236
+    public function reShare($id) {
237
+
238
+        $token = $this->request->getParam('token', null);
239
+        $shareWith = $this->request->getParam('shareWith', null);
240
+        $permission = (int)$this->request->getParam('permission', null);
241
+        $remoteId = (int)$this->request->getParam('remoteId', null);
242
+
243
+        if ($id === null ||
244
+            $token === null ||
245
+            $shareWith === null ||
246
+            $permission === null ||
247
+            $remoteId === null
248
+        ) {
249
+            throw new OCSBadRequestException();
250
+        }
251
+
252
+        try {
253
+            $share = $this->federatedShareProvider->getShareById($id);
254
+        } catch (Share\Exceptions\ShareNotFound $e) {
255
+            throw new OCSNotFoundException();
256
+        }
257
+
258
+        // don't allow to share a file back to the owner
259
+        list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
260
+        $owner = $share->getShareOwner();
261
+        $currentServer = $this->addressHandler->generateRemoteURL();
262
+        if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
263
+            throw new OCSForbiddenException();
264
+        }
265
+
266
+        if ($this->verifyShare($share, $token)) {
267
+
268
+            // check if re-sharing is allowed
269
+            if ($share->getPermissions() | ~Constants::PERMISSION_SHARE) {
270
+                $share->setPermissions($share->getPermissions() & $permission);
271
+                // the recipient of the initial share is now the initiator for the re-share
272
+                $share->setSharedBy($share->getSharedWith());
273
+                $share->setSharedWith($shareWith);
274
+                try {
275
+                    $result = $this->federatedShareProvider->create($share);
276
+                    $this->federatedShareProvider->storeRemoteId((int)$result->getId(), $remoteId);
277
+                    return new Http\DataResponse([
278
+                        'token' => $result->getToken(),
279
+                        'remoteId' => $result->getId()
280
+                    ]);
281
+                } catch (\Exception $e) {
282
+                    throw new OCSBadRequestException();
283
+                }
284
+            } else {
285
+                throw new OCSForbiddenException();
286
+            }
287
+        }
288
+        throw new OCSBadRequestException();
289
+    }
290
+
291
+    /**
292
+     * @NoCSRFRequired
293
+     * @PublicPage
294
+     *
295
+     * accept server-to-server share
296
+     *
297
+     * @param int $id
298
+     * @return Http\DataResponse
299
+     * @throws OCSException
300
+     */
301
+    public function acceptShare($id) {
302
+
303
+        if (!$this->isS2SEnabled()) {
304
+            throw new OCSException('Server does not support federated cloud sharing', 503);
305
+        }
306
+
307
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
308
+
309
+        try {
310
+            $share = $this->federatedShareProvider->getShareById($id);
311
+        } catch (Share\Exceptions\ShareNotFound $e) {
312
+            return new Http\DataResponse();
313
+        }
314
+
315
+        if ($this->verifyShare($share, $token)) {
316
+            $this->executeAcceptShare($share);
317
+            if ($share->getShareOwner() !== $share->getSharedBy()) {
318
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
319
+                $remoteId = $this->federatedShareProvider->getRemoteId($share);
320
+                $this->notifications->sendAcceptShare($remote, $remoteId, $share->getToken());
321
+            }
322
+        }
323
+
324
+        return new Http\DataResponse();
325
+    }
326
+
327
+    protected function executeAcceptShare(Share\IShare $share) {
328
+        $fileId = (int) $share->getNode()->getId();
329
+        list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
330
+
331
+        $event = \OC::$server->getActivityManager()->generateEvent();
332
+        $event->setApp('files_sharing')
333
+            ->setType('remote_share')
334
+            ->setAffectedUser($this->getCorrectUid($share))
335
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
336
+            ->setObject('files', $fileId, $file)
337
+            ->setLink($link);
338
+        \OC::$server->getActivityManager()->publish($event);
339
+    }
340
+
341
+    /**
342
+     * @NoCSRFRequired
343
+     * @PublicPage
344
+     *
345
+     * decline server-to-server share
346
+     *
347
+     * @param int $id
348
+     * @return Http\DataResponse
349
+     * @throws OCSException
350
+     */
351
+    public function declineShare($id) {
352
+
353
+        if (!$this->isS2SEnabled()) {
354
+            throw new OCSException('Server does not support federated cloud sharing', 503);
355
+        }
356
+
357
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
358
+
359
+        try {
360
+            $share = $this->federatedShareProvider->getShareById($id);
361
+        } catch (Share\Exceptions\ShareNotFound $e) {
362
+            return new Http\DataResponse();
363
+        }
364
+
365
+        if ($this->verifyShare($share, $token)) {
366
+            if ($share->getShareOwner() !== $share->getSharedBy()) {
367
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
368
+                $remoteId = $this->federatedShareProvider->getRemoteId($share);
369
+                $this->notifications->sendDeclineShare($remote, $remoteId, $share->getToken());
370
+            }
371
+            $this->executeDeclineShare($share);
372
+        }
373
+
374
+        return new Http\DataResponse();
375
+    }
376
+
377
+    /**
378
+     * delete declined share and create a activity
379
+     *
380
+     * @param Share\IShare $share
381
+     */
382
+    protected function executeDeclineShare(Share\IShare $share) {
383
+        $this->federatedShareProvider->removeShareFromTable($share);
384
+        $fileId = (int) $share->getNode()->getId();
385
+        list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
386
+
387
+        $event = \OC::$server->getActivityManager()->generateEvent();
388
+        $event->setApp('files_sharing')
389
+            ->setType('remote_share')
390
+            ->setAffectedUser($this->getCorrectUid($share))
391
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
392
+            ->setObject('files', $fileId, $file)
393
+            ->setLink($link);
394
+        \OC::$server->getActivityManager()->publish($event);
395
+
396
+    }
397
+
398
+    /**
399
+     * check if we are the initiator or the owner of a re-share and return the correct UID
400
+     *
401
+     * @param Share\IShare $share
402
+     * @return string
403
+     */
404
+    protected function getCorrectUid(Share\IShare $share) {
405
+        if ($this->userManager->userExists($share->getShareOwner())) {
406
+            return $share->getShareOwner();
407
+        }
408
+
409
+        return $share->getSharedBy();
410
+    }
411
+
412
+    /**
413
+     * @NoCSRFRequired
414
+     * @PublicPage
415
+     *
416
+     * remove server-to-server share if it was unshared by the owner
417
+     *
418
+     * @param int $id
419
+     * @return Http\DataResponse
420
+     * @throws OCSException
421
+     */
422
+    public function unshare($id) {
423
+
424
+        if (!$this->isS2SEnabled()) {
425
+            throw new OCSException('Server does not support federated cloud sharing', 503);
426
+        }
427
+
428
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
429
+
430
+        $query = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share_external` WHERE `remote_id` = ? AND `share_token` = ?');
431
+        $query->execute(array($id, $token));
432
+        $share = $query->fetchRow();
433
+
434
+        if ($token && $id && !empty($share)) {
435
+
436
+            $remote = $this->cleanupRemote($share['remote']);
437
+
438
+            $owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
439
+            $mountpoint = $share['mountpoint'];
440
+            $user = $share['user'];
441
+
442
+            $query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share_external` WHERE `remote_id` = ? AND `share_token` = ?');
443
+            $query->execute(array($id, $token));
444
+
445
+            if ($share['accepted']) {
446
+                $path = trim($mountpoint, '/');
447
+            } else {
448
+                $path = trim($share['name'], '/');
449
+            }
450
+
451
+            $notificationManager = \OC::$server->getNotificationManager();
452
+            $notification = $notificationManager->createNotification();
453
+            $notification->setApp('files_sharing')
454
+                ->setUser($share['user'])
455
+                ->setObject('remote_share', (int)$share['id']);
456
+            $notificationManager->markProcessed($notification);
457
+
458
+            $event = \OC::$server->getActivityManager()->generateEvent();
459
+            $event->setApp('files_sharing')
460
+                ->setType('remote_share')
461
+                ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
462
+                ->setAffectedUser($user)
463
+                ->setObject('remote_share', (int)$share['id'], $path);
464
+            \OC::$server->getActivityManager()->publish($event);
465
+        }
466
+
467
+        return new Http\DataResponse();
468
+    }
469
+
470
+    private function cleanupRemote($remote) {
471
+        $remote = substr($remote, strpos($remote, '://') + 3);
472
+
473
+        return rtrim($remote, '/');
474
+    }
475
+
476
+
477
+    /**
478
+     * @NoCSRFRequired
479
+     * @PublicPage
480
+     *
481
+     * federated share was revoked, either by the owner or the re-sharer
482
+     *
483
+     * @param int $id
484
+     * @return Http\DataResponse
485
+     * @throws OCSBadRequestException
486
+     */
487
+    public function revoke($id) {
488
+        $token = $this->request->getParam('token');
489
+
490
+        $share = $this->federatedShareProvider->getShareById($id);
491
+
492
+        if ($this->verifyShare($share, $token)) {
493
+            $this->federatedShareProvider->removeShareFromTable($share);
494
+            return new Http\DataResponse();
495
+        }
496
+
497
+        throw new OCSBadRequestException();
498
+    }
499
+
500
+    /**
501
+     * get share
502
+     *
503
+     * @param int $id
504
+     * @param string $token
505
+     * @return array|bool
506
+     */
507
+    protected function getShare($id, $token) {
508
+        $query = $this->connection->getQueryBuilder();
509
+        $query->select('*')->from($this->shareTable)
510
+            ->where($query->expr()->eq('token', $query->createNamedParameter($token)))
511
+            ->andWhere($query->expr()->eq('share_type', $query->createNamedParameter(FederatedShareProvider::SHARE_TYPE_REMOTE)))
512
+            ->andWhere($query->expr()->eq('id', $query->createNamedParameter($id)));
513
+
514
+        $result = $query->execute()->fetchAll();
515
+
516
+        if (!empty($result) && isset($result[0])) {
517
+            return $result[0];
518
+        }
519
+
520
+        return false;
521
+    }
522
+
523
+    /**
524
+     * get file
525
+     *
526
+     * @param string $user
527
+     * @param int $fileSource
528
+     * @return array with internal path of the file and a absolute link to it
529
+     */
530
+    private function getFile($user, $fileSource) {
531
+        \OC_Util::setupFS($user);
532
+
533
+        try {
534
+            $file = \OC\Files\Filesystem::getPath($fileSource);
535
+        } catch (NotFoundException $e) {
536
+            $file = null;
537
+        }
538
+        $args = \OC\Files\Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
539
+        $link = \OCP\Util::linkToAbsolute('files', 'index.php', $args);
540
+
541
+        return array($file, $link);
542
+
543
+    }
544
+
545
+    /**
546
+     * check if server-to-server sharing is enabled
547
+     *
548
+     * @param bool $incoming
549
+     * @return bool
550
+     */
551
+    private function isS2SEnabled($incoming = false) {
552
+
553
+        $result = \OCP\App::isEnabled('files_sharing');
554
+
555
+        if ($incoming) {
556
+            $result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
557
+        } else {
558
+            $result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
559
+        }
560
+
561
+        return $result;
562
+    }
563
+
564
+    /**
565
+     * check if we got the right share
566
+     *
567
+     * @param Share\IShare $share
568
+     * @param string $token
569
+     * @return bool
570
+     */
571
+    protected function verifyShare(Share\IShare $share, $token) {
572
+        if (
573
+            $share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
574
+            $share->getToken() === $token
575
+        ) {
576
+            return true;
577
+        }
578
+
579
+        return false;
580
+    }
581
+
582
+    /**
583
+     * @NoCSRFRequired
584
+     * @PublicPage
585
+     *
586
+     * update share information to keep federated re-shares in sync
587
+     *
588
+     * @param int $id
589
+     * @return Http\DataResponse
590
+     * @throws OCSBadRequestException
591
+     */
592
+    public function updatePermissions($id) {
593
+        $token = $this->request->getParam('token', null);
594
+        $permissions = $this->request->getParam('permissions', null);
595
+
596
+        try {
597
+            $share = $this->federatedShareProvider->getShareById($id);
598
+        } catch (Share\Exceptions\ShareNotFound $e) {
599
+            throw new OCSBadRequestException();
600
+        }
601
+
602
+        $validPermission = ctype_digit($permissions);
603
+        $validToken = $this->verifyShare($share, $token);
604
+        if ($validPermission && $validToken) {
605
+            $this->updatePermissionsInDatabase($share, (int)$permissions);
606
+        } else {
607
+            throw new OCSBadRequestException();
608
+        }
609
+
610
+        return new Http\DataResponse();
611
+    }
612
+
613
+    /**
614
+     * update permissions in database
615
+     *
616
+     * @param IShare $share
617
+     * @param int $permissions
618
+     */
619
+    protected function updatePermissionsInDatabase(IShare $share, $permissions) {
620
+        $query = $this->connection->getQueryBuilder();
621
+        $query->update('share')
622
+            ->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
623
+            ->set('permissions', $query->createNamedParameter($permissions))
624
+            ->execute();
625
+    }
626
+
627
+    /**
628
+     * @NoCSRFRequired
629
+     * @PublicPage
630
+     *
631
+     * change the owner of a server-to-server share
632
+     *
633
+     * @param int $id
634
+     * @return Http\DataResponse
635
+     * @throws \InvalidArgumentException
636
+     * @throws OCSException
637
+     */
638
+    public function move($id) {
639
+
640
+        if (!$this->isS2SEnabled()) {
641
+            throw new OCSException('Server does not support federated cloud sharing', 503);
642
+        }
643
+
644
+        $token = $this->request->getParam('token');
645
+        $remote = $this->request->getParam('remote');
646
+        $newRemoteId = $this->request->getParam('remote_id', $id);
647
+        $cloudId = $this->cloudIdManager->resolveCloudId($remote);
648
+
649
+        $qb = $this->connection->getQueryBuilder();
650
+        $query = $qb->update('share_external')
651
+            ->set('remote', $qb->createNamedParameter($cloudId->getRemote()))
652
+            ->set('owner', $qb->createNamedParameter($cloudId->getUser()))
653
+            ->set('remote_id', $qb->createNamedParameter($newRemoteId))
654
+            ->where($qb->expr()->eq('remote_id', $qb->createNamedParameter($id)))
655
+            ->andWhere($qb->expr()->eq('share_token', $qb->createNamedParameter($token)));
656
+        $affected = $query->execute();
657
+
658
+        if ($affected > 0) {
659
+            return new Http\DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]);
660
+        } else {
661
+            throw new OCSBadRequestException('Share not found or token invalid');
662
+        }
663
+    }
664 664
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
 		$owner = isset($_POST['owner']) ? $_POST['owner'] : null;
130 130
 		$sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null;
131 131
 		$shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
132
-		$remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
132
+		$remoteId = isset($_POST['remoteId']) ? (int) $_POST['remoteId'] : null;
133 133
 		$sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null;
134 134
 		$ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null;
135 135
 
@@ -140,13 +140,13 @@  discard block
 block discarded – undo
140 140
 			}
141 141
 
142 142
 			// FIXME this should be a method in the user management instead
143
-			\OCP\Util::writeLog('files_sharing', 'shareWith before, ' . $shareWith, \OCP\Util::DEBUG);
143
+			\OCP\Util::writeLog('files_sharing', 'shareWith before, '.$shareWith, \OCP\Util::DEBUG);
144 144
 			\OCP\Util::emitHook(
145 145
 				'\OCA\Files_Sharing\API\Server2Server',
146 146
 				'preLoginNameUsedAsUserName',
147 147
 				array('uid' => &$shareWith)
148 148
 			);
149
-			\OCP\Util::writeLog('files_sharing', 'shareWith after, ' . $shareWith, \OCP\Util::DEBUG);
149
+			\OCP\Util::writeLog('files_sharing', 'shareWith after, '.$shareWith, \OCP\Util::DEBUG);
150 150
 
151 151
 			if (!\OC::$server->getUserManager()->userExists($shareWith)) {
152 152
 				throw new OCSException('User does not exists', 400);
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
 					->setType('remote_share')
183 183
 					->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
184 184
 					->setAffectedUser($shareWith)
185
-					->setObject('remote_share', (int)$shareId, $name);
185
+					->setObject('remote_share', (int) $shareId, $name);
186 186
 				\OC::$server->getActivityManager()->publish($event);
187 187
 
188 188
 				$urlGenerator = \OC::$server->getURLGenerator();
@@ -197,12 +197,12 @@  discard block
 block discarded – undo
197 197
 
198 198
 				$declineAction = $notification->createAction();
199 199
 				$declineAction->setLabel('decline')
200
-					->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
200
+					->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/'.$shareId)), 'DELETE');
201 201
 				$notification->addAction($declineAction);
202 202
 
203 203
 				$acceptAction = $notification->createAction();
204 204
 				$acceptAction->setLabel('accept')
205
-					->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
205
+					->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/'.$shareId)), 'POST');
206 206
 				$notification->addAction($acceptAction);
207 207
 
208 208
 				$notificationManager->notify($notification);
@@ -214,7 +214,7 @@  discard block
 block discarded – undo
214 214
 					'level' => \OCP\Util::ERROR,
215 215
 					'app' => 'files_sharing'
216 216
 				]);
217
-				throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
217
+				throw new OCSException('internal server error, was not able to add share from '.$remote, 500);
218 218
 			}
219 219
 		}
220 220
 
@@ -237,8 +237,8 @@  discard block
 block discarded – undo
237 237
 
238 238
 		$token = $this->request->getParam('token', null);
239 239
 		$shareWith = $this->request->getParam('shareWith', null);
240
-		$permission = (int)$this->request->getParam('permission', null);
241
-		$remoteId = (int)$this->request->getParam('remoteId', null);
240
+		$permission = (int) $this->request->getParam('permission', null);
241
+		$remoteId = (int) $this->request->getParam('remoteId', null);
242 242
 
243 243
 		if ($id === null ||
244 244
 			$token === null ||
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
 				$share->setSharedWith($shareWith);
274 274
 				try {
275 275
 					$result = $this->federatedShareProvider->create($share);
276
-					$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $remoteId);
276
+					$this->federatedShareProvider->storeRemoteId((int) $result->getId(), $remoteId);
277 277
 					return new Http\DataResponse([
278 278
 						'token' => $result->getToken(),
279 279
 						'remoteId' => $result->getId()
@@ -452,7 +452,7 @@  discard block
 block discarded – undo
452 452
 			$notification = $notificationManager->createNotification();
453 453
 			$notification->setApp('files_sharing')
454 454
 				->setUser($share['user'])
455
-				->setObject('remote_share', (int)$share['id']);
455
+				->setObject('remote_share', (int) $share['id']);
456 456
 			$notificationManager->markProcessed($notification);
457 457
 
458 458
 			$event = \OC::$server->getActivityManager()->generateEvent();
@@ -460,7 +460,7 @@  discard block
 block discarded – undo
460 460
 				->setType('remote_share')
461 461
 				->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
462 462
 				->setAffectedUser($user)
463
-				->setObject('remote_share', (int)$share['id'], $path);
463
+				->setObject('remote_share', (int) $share['id'], $path);
464 464
 			\OC::$server->getActivityManager()->publish($event);
465 465
 		}
466 466
 
@@ -602,7 +602,7 @@  discard block
 block discarded – undo
602 602
 		$validPermission = ctype_digit($permissions);
603 603
 		$validToken = $this->verifyShare($share, $token);
604 604
 		if ($validPermission && $validToken) {
605
-			$this->updatePermissionsInDatabase($share, (int)$permissions);
605
+			$this->updatePermissionsInDatabase($share, (int) $permissions);
606 606
 		} else {
607 607
 			throw new OCSBadRequestException();
608 608
 		}
Please login to merge, or discard this patch.
apps/sharebymail/lib/ShareByMailProvider.php 2 patches
Indentation   +1021 added lines, -1021 removed lines patch added patch discarded remove patch
@@ -53,1039 +53,1039 @@
 block discarded – undo
53 53
  */
54 54
 class ShareByMailProvider implements IShareProvider {
55 55
 
56
-	/** @var  IDBConnection */
57
-	private $dbConnection;
58
-
59
-	/** @var ILogger */
60
-	private $logger;
61
-
62
-	/** @var ISecureRandom */
63
-	private $secureRandom;
64
-
65
-	/** @var IUserManager */
66
-	private $userManager;
67
-
68
-	/** @var IRootFolder */
69
-	private $rootFolder;
70
-
71
-	/** @var IL10N */
72
-	private $l;
73
-
74
-	/** @var IMailer */
75
-	private $mailer;
76
-
77
-	/** @var IURLGenerator */
78
-	private $urlGenerator;
79
-
80
-	/** @var IManager  */
81
-	private $activityManager;
82
-
83
-	/** @var SettingsManager */
84
-	private $settingsManager;
85
-
86
-	/** @var Defaults */
87
-	private $defaults;
88
-
89
-	/** @var IHasher */
90
-	private $hasher;
91
-
92
-	/** @var  CapabilitiesManager */
93
-	private $capabilitiesManager;
94
-
95
-	/**
96
-	 * Return the identifier of this provider.
97
-	 *
98
-	 * @return string Containing only [a-zA-Z0-9]
99
-	 */
100
-	public function identifier() {
101
-		return 'ocMailShare';
102
-	}
103
-
104
-	/**
105
-	 * DefaultShareProvider constructor.
106
-	 *
107
-	 * @param IDBConnection $connection
108
-	 * @param ISecureRandom $secureRandom
109
-	 * @param IUserManager $userManager
110
-	 * @param IRootFolder $rootFolder
111
-	 * @param IL10N $l
112
-	 * @param ILogger $logger
113
-	 * @param IMailer $mailer
114
-	 * @param IURLGenerator $urlGenerator
115
-	 * @param IManager $activityManager
116
-	 * @param SettingsManager $settingsManager
117
-	 * @param Defaults $defaults
118
-	 * @param IHasher $hasher
119
-	 * @param CapabilitiesManager $capabilitiesManager
120
-	 */
121
-	public function __construct(
122
-		IDBConnection $connection,
123
-		ISecureRandom $secureRandom,
124
-		IUserManager $userManager,
125
-		IRootFolder $rootFolder,
126
-		IL10N $l,
127
-		ILogger $logger,
128
-		IMailer $mailer,
129
-		IURLGenerator $urlGenerator,
130
-		IManager $activityManager,
131
-		SettingsManager $settingsManager,
132
-		Defaults $defaults,
133
-		IHasher $hasher,
134
-		CapabilitiesManager $capabilitiesManager
135
-	) {
136
-		$this->dbConnection = $connection;
137
-		$this->secureRandom = $secureRandom;
138
-		$this->userManager = $userManager;
139
-		$this->rootFolder = $rootFolder;
140
-		$this->l = $l;
141
-		$this->logger = $logger;
142
-		$this->mailer = $mailer;
143
-		$this->urlGenerator = $urlGenerator;
144
-		$this->activityManager = $activityManager;
145
-		$this->settingsManager = $settingsManager;
146
-		$this->defaults = $defaults;
147
-		$this->hasher = $hasher;
148
-		$this->capabilitiesManager = $capabilitiesManager;
149
-	}
150
-
151
-	/**
152
-	 * Share a path
153
-	 *
154
-	 * @param IShare $share
155
-	 * @return IShare The share object
156
-	 * @throws ShareNotFound
157
-	 * @throws \Exception
158
-	 */
159
-	public function create(IShare $share) {
160
-
161
-		$shareWith = $share->getSharedWith();
162
-		/*
56
+    /** @var  IDBConnection */
57
+    private $dbConnection;
58
+
59
+    /** @var ILogger */
60
+    private $logger;
61
+
62
+    /** @var ISecureRandom */
63
+    private $secureRandom;
64
+
65
+    /** @var IUserManager */
66
+    private $userManager;
67
+
68
+    /** @var IRootFolder */
69
+    private $rootFolder;
70
+
71
+    /** @var IL10N */
72
+    private $l;
73
+
74
+    /** @var IMailer */
75
+    private $mailer;
76
+
77
+    /** @var IURLGenerator */
78
+    private $urlGenerator;
79
+
80
+    /** @var IManager  */
81
+    private $activityManager;
82
+
83
+    /** @var SettingsManager */
84
+    private $settingsManager;
85
+
86
+    /** @var Defaults */
87
+    private $defaults;
88
+
89
+    /** @var IHasher */
90
+    private $hasher;
91
+
92
+    /** @var  CapabilitiesManager */
93
+    private $capabilitiesManager;
94
+
95
+    /**
96
+     * Return the identifier of this provider.
97
+     *
98
+     * @return string Containing only [a-zA-Z0-9]
99
+     */
100
+    public function identifier() {
101
+        return 'ocMailShare';
102
+    }
103
+
104
+    /**
105
+     * DefaultShareProvider constructor.
106
+     *
107
+     * @param IDBConnection $connection
108
+     * @param ISecureRandom $secureRandom
109
+     * @param IUserManager $userManager
110
+     * @param IRootFolder $rootFolder
111
+     * @param IL10N $l
112
+     * @param ILogger $logger
113
+     * @param IMailer $mailer
114
+     * @param IURLGenerator $urlGenerator
115
+     * @param IManager $activityManager
116
+     * @param SettingsManager $settingsManager
117
+     * @param Defaults $defaults
118
+     * @param IHasher $hasher
119
+     * @param CapabilitiesManager $capabilitiesManager
120
+     */
121
+    public function __construct(
122
+        IDBConnection $connection,
123
+        ISecureRandom $secureRandom,
124
+        IUserManager $userManager,
125
+        IRootFolder $rootFolder,
126
+        IL10N $l,
127
+        ILogger $logger,
128
+        IMailer $mailer,
129
+        IURLGenerator $urlGenerator,
130
+        IManager $activityManager,
131
+        SettingsManager $settingsManager,
132
+        Defaults $defaults,
133
+        IHasher $hasher,
134
+        CapabilitiesManager $capabilitiesManager
135
+    ) {
136
+        $this->dbConnection = $connection;
137
+        $this->secureRandom = $secureRandom;
138
+        $this->userManager = $userManager;
139
+        $this->rootFolder = $rootFolder;
140
+        $this->l = $l;
141
+        $this->logger = $logger;
142
+        $this->mailer = $mailer;
143
+        $this->urlGenerator = $urlGenerator;
144
+        $this->activityManager = $activityManager;
145
+        $this->settingsManager = $settingsManager;
146
+        $this->defaults = $defaults;
147
+        $this->hasher = $hasher;
148
+        $this->capabilitiesManager = $capabilitiesManager;
149
+    }
150
+
151
+    /**
152
+     * Share a path
153
+     *
154
+     * @param IShare $share
155
+     * @return IShare The share object
156
+     * @throws ShareNotFound
157
+     * @throws \Exception
158
+     */
159
+    public function create(IShare $share) {
160
+
161
+        $shareWith = $share->getSharedWith();
162
+        /*
163 163
 		 * Check if file is not already shared with the remote user
164 164
 		 */
165
-		$alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);
166
-		if (!empty($alreadyShared)) {
167
-			$message = 'Sharing %s failed, this item is already shared with %s';
168
-			$message_t = $this->l->t('Sharing %s failed, this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
169
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
170
-			throw new \Exception($message_t);
171
-		}
172
-
173
-		// if the admin enforces a password for all mail shares we create a
174
-		// random password and send it to the recipient
175
-		$password = '';
176
-		$passwordEnforced = $this->settingsManager->enforcePasswordProtection();
177
-		if ($passwordEnforced) {
178
-			$password = $this->autoGeneratePassword($share);
179
-		}
180
-
181
-		$shareId = $this->createMailShare($share);
182
-		$send = $this->sendPassword($share, $password);
183
-		if ($passwordEnforced && $send === false) {
184
-			$this->sendPasswordToOwner($share, $password);
185
-		}
186
-
187
-		$this->createShareActivity($share);
188
-		$data = $this->getRawShare($shareId);
189
-
190
-		return $this->createShareObject($data);
191
-
192
-	}
193
-
194
-	/**
195
-	 * auto generate password in case of password enforcement on mail shares
196
-	 *
197
-	 * @param IShare $share
198
-	 * @return string
199
-	 * @throws \Exception
200
-	 */
201
-	protected function autoGeneratePassword($share) {
202
-		$initiatorUser = $this->userManager->get($share->getSharedBy());
203
-		$initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
204
-		$allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
205
-
206
-		if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
207
-			throw new \Exception(
208
-				$this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
209
-			);
210
-		}
211
-
212
-		$passwordPolicy = $this->getPasswordPolicy();
213
-		$passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
214
-		$passwordLength = 8;
215
-		if (!empty($passwordPolicy)) {
216
-			$passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
217
-			$passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
218
-		}
219
-
220
-		$password = $this->secureRandom->generate($passwordLength, $passwordCharset);
221
-
222
-		$share->setPassword($this->hasher->hash($password));
223
-
224
-		return $password;
225
-	}
226
-
227
-	/**
228
-	 * get password policy
229
-	 *
230
-	 * @return array
231
-	 */
232
-	protected function getPasswordPolicy() {
233
-		$capabilities = $this->capabilitiesManager->getCapabilities();
234
-		if (isset($capabilities['password_policy'])) {
235
-			return $capabilities['password_policy'];
236
-		}
237
-
238
-		return [];
239
-	}
240
-
241
-	/**
242
-	 * create activity if a file/folder was shared by mail
243
-	 *
244
-	 * @param IShare $share
245
-	 */
246
-	protected function createShareActivity(IShare $share) {
247
-
248
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
249
-
250
-		$this->publishActivity(
251
-			Activity::SUBJECT_SHARED_EMAIL_SELF,
252
-			[$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
253
-			$share->getSharedBy(),
254
-			$share->getNode()->getId(),
255
-			$userFolder->getRelativePath($share->getNode()->getPath())
256
-		);
257
-
258
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
259
-			$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
260
-			$fileId = $share->getNode()->getId();
261
-			$nodes = $ownerFolder->getById($fileId);
262
-			$ownerPath = $nodes[0]->getPath();
263
-			$this->publishActivity(
264
-				Activity::SUBJECT_SHARED_EMAIL_BY,
265
-				[$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
266
-				$share->getShareOwner(),
267
-				$fileId,
268
-				$ownerFolder->getRelativePath($ownerPath)
269
-			);
270
-		}
271
-
272
-	}
273
-
274
-	/**
275
-	 * create activity if a file/folder was shared by mail
276
-	 *
277
-	 * @param IShare $share
278
-	 * @param string $sharedWith
279
-	 * @param bool $sendToSelf
280
-	 */
281
-	protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
282
-
283
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
284
-
285
-		if ($sendToSelf) {
286
-			$this->publishActivity(
287
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
288
-				[$userFolder->getRelativePath($share->getNode()->getPath())],
289
-				$share->getSharedBy(),
290
-				$share->getNode()->getId(),
291
-				$userFolder->getRelativePath($share->getNode()->getPath())
292
-			);
293
-		} else {
294
-			$this->publishActivity(
295
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
296
-				[$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
297
-				$share->getSharedBy(),
298
-				$share->getNode()->getId(),
299
-				$userFolder->getRelativePath($share->getNode()->getPath())
300
-			);
301
-		}
302
-	}
303
-
304
-
305
-	/**
306
-	 * publish activity if a file/folder was shared by mail
307
-	 *
308
-	 * @param $subject
309
-	 * @param $parameters
310
-	 * @param $affectedUser
311
-	 * @param $fileId
312
-	 * @param $filePath
313
-	 */
314
-	protected function publishActivity($subject, $parameters, $affectedUser, $fileId, $filePath) {
315
-		$event = $this->activityManager->generateEvent();
316
-		$event->setApp('sharebymail')
317
-			->setType('shared')
318
-			->setSubject($subject, $parameters)
319
-			->setAffectedUser($affectedUser)
320
-			->setObject('files', $fileId, $filePath);
321
-		$this->activityManager->publish($event);
322
-
323
-	}
324
-
325
-	/**
326
-	 * @param IShare $share
327
-	 * @return int
328
-	 * @throws \Exception
329
-	 */
330
-	protected function createMailShare(IShare $share) {
331
-		$share->setToken($this->generateToken());
332
-		$shareId = $this->addShareToDB(
333
-			$share->getNodeId(),
334
-			$share->getNodeType(),
335
-			$share->getSharedWith(),
336
-			$share->getSharedBy(),
337
-			$share->getShareOwner(),
338
-			$share->getPermissions(),
339
-			$share->getToken(),
340
-			$share->getPassword()
341
-		);
342
-
343
-		try {
344
-			$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
345
-				['token' => $share->getToken()]);
346
-			$this->sendMailNotification(
347
-				$share->getNode()->getName(),
348
-				$link,
349
-				$share->getSharedBy(),
350
-				$share->getSharedWith(),
351
-				$share->getExpirationDate()
352
-			);
353
-		} catch (HintException $hintException) {
354
-			$this->logger->logException($hintException, [
355
-				'message' => 'Failed to send share by mail.',
356
-				'level' => \OCP\Util::ERROR,
357
-				'app' => 'sharebymail',
358
-			]);
359
-			$this->removeShareFromTable($shareId);
360
-			throw $hintException;
361
-		} catch (\Exception $e) {
362
-			$this->logger->logException($e, [
363
-				'message' => 'Failed to send share by mail.',
364
-				'level' => \OCP\Util::ERROR,
365
-				'app' => 'sharebymail',
366
-			]);
367
-			$this->removeShareFromTable($shareId);
368
-			throw new HintException('Failed to send share by mail',
369
-				$this->l->t('Failed to send share by email'));
370
-		}
371
-
372
-		return $shareId;
373
-
374
-	}
375
-
376
-	/**
377
-	 * @param string $filename
378
-	 * @param string $link
379
-	 * @param string $initiator
380
-	 * @param string $shareWith
381
-	 * @param \DateTime|null $expiration
382
-	 * @throws \Exception If mail couldn't be sent
383
-	 */
384
-	protected function sendMailNotification($filename,
385
-											$link,
386
-											$initiator,
387
-											$shareWith,
388
-											\DateTime $expiration = null) {
389
-		$initiatorUser = $this->userManager->get($initiator);
390
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
391
-		$message = $this->mailer->createMessage();
392
-
393
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
394
-			'filename' => $filename,
395
-			'link' => $link,
396
-			'initiator' => $initiatorDisplayName,
397
-			'expiration' => $expiration,
398
-			'shareWith' => $shareWith,
399
-		]);
400
-
401
-		$emailTemplate->setSubject($this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename)));
402
-		$emailTemplate->addHeader();
403
-		$emailTemplate->addHeading($this->l->t('%s shared »%s« with you', [$initiatorDisplayName, $filename]), false);
404
-		$text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
405
-
406
-		$emailTemplate->addBodyText(
407
-			$text . ' ' . $this->l->t('Click the button below to open it.'),
408
-			$text
409
-		);
410
-		$emailTemplate->addBodyButton(
411
-			$this->l->t('Open »%s«', [$filename]),
412
-			$link
413
-		);
414
-
415
-		$message->setTo([$shareWith]);
416
-
417
-		// The "From" contains the sharers name
418
-		$instanceName = $this->defaults->getName();
419
-		$senderName = $this->l->t(
420
-			'%s via %s',
421
-			[
422
-				$initiatorDisplayName,
423
-				$instanceName
424
-			]
425
-		);
426
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
427
-
428
-		// The "Reply-To" is set to the sharer if an mail address is configured
429
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
430
-		$initiatorEmail = $initiatorUser->getEMailAddress();
431
-		if($initiatorEmail !== null) {
432
-			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
433
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
434
-		} else {
435
-			$emailTemplate->addFooter();
436
-		}
437
-
438
-		$message->useTemplate($emailTemplate);
439
-		$this->mailer->send($message);
440
-	}
441
-
442
-	/**
443
-	 * send password to recipient of a mail share
444
-	 *
445
-	 * @param IShare $share
446
-	 * @param string $password
447
-	 * @return bool
448
-	 */
449
-	protected function sendPassword(IShare $share, $password) {
450
-
451
-		$filename = $share->getNode()->getName();
452
-		$initiator = $share->getSharedBy();
453
-		$shareWith = $share->getSharedWith();
454
-
455
-		if ($password === '' || $this->settingsManager->sendPasswordByMail() === false) {
456
-			return false;
457
-		}
458
-
459
-		$initiatorUser = $this->userManager->get($initiator);
460
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
461
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
462
-
463
-		$plainBodyPart = $this->l->t("%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
464
-		$htmlBodyPart = $this->l->t('%s shared »%s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
465
-
466
-		$message = $this->mailer->createMessage();
467
-
468
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
469
-			'filename' => $filename,
470
-			'password' => $password,
471
-			'initiator' => $initiatorDisplayName,
472
-			'initiatorEmail' => $initiatorEmailAddress,
473
-			'shareWith' => $shareWith,
474
-		]);
475
-
476
-		$emailTemplate->setSubject($this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName]));
477
-		$emailTemplate->addHeader();
478
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
479
-		$emailTemplate->addBodyText($htmlBodyPart, $plainBodyPart);
480
-		$emailTemplate->addBodyText($this->l->t('It is protected with the following password: %s', [$password]));
481
-
482
-		// The "From" contains the sharers name
483
-		$instanceName = $this->defaults->getName();
484
-		$senderName = $this->l->t(
485
-			'%s via %s',
486
-			[
487
-				$initiatorDisplayName,
488
-				$instanceName
489
-			]
490
-		);
491
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
492
-		if ($initiatorEmailAddress !== null) {
493
-			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
494
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
495
-		} else {
496
-			$emailTemplate->addFooter();
497
-		}
498
-
499
-		$message->setTo([$shareWith]);
500
-		$message->useTemplate($emailTemplate);
501
-		$this->mailer->send($message);
502
-
503
-		$this->createPasswordSendActivity($share, $shareWith, false);
504
-
505
-		return true;
506
-	}
507
-
508
-	/**
509
-	 * send auto generated password to the owner. This happens if the admin enforces
510
-	 * a password for mail shares and forbid to send the password by mail to the recipient
511
-	 *
512
-	 * @param IShare $share
513
-	 * @param string $password
514
-	 * @return bool
515
-	 * @throws \Exception
516
-	 */
517
-	protected function sendPasswordToOwner(IShare $share, $password) {
518
-
519
-		$filename = $share->getNode()->getName();
520
-		$initiator = $this->userManager->get($share->getSharedBy());
521
-		$initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
522
-		$initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
523
-		$shareWith = $share->getSharedWith();
524
-
525
-		if ($initiatorEMailAddress === null) {
526
-			throw new \Exception(
527
-				$this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
528
-			);
529
-		}
530
-
531
-		$bodyPart = $this->l->t("You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.", [$filename, $shareWith, $this->defaults->getName()]);
532
-
533
-		$message = $this->mailer->createMessage();
534
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
535
-			'filename' => $filename,
536
-			'password' => $password,
537
-			'initiator' => $initiatorDisplayName,
538
-			'initiatorEmail' => $initiatorEMailAddress,
539
-			'shareWith' => $shareWith,
540
-		]);
541
-
542
-		$emailTemplate->setSubject($this->l->t('Password to access »%s« shared with %s', [$filename, $shareWith]));
543
-		$emailTemplate->addHeader();
544
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
545
-		$emailTemplate->addBodyText($bodyPart);
546
-		$emailTemplate->addBodyText($this->l->t('This is the password: %s', [$password]));
547
-		$emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
548
-		$emailTemplate->addFooter();
549
-
550
-		if ($initiatorEMailAddress) {
551
-			$message->setFrom([$initiatorEMailAddress => $initiatorDisplayName]);
552
-		}
553
-		$message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
554
-		$message->useTemplate($emailTemplate);
555
-		$this->mailer->send($message);
556
-
557
-		$this->createPasswordSendActivity($share, $shareWith, true);
558
-
559
-		return true;
560
-	}
561
-
562
-	/**
563
-	 * generate share token
564
-	 *
565
-	 * @return string
566
-	 */
567
-	protected function generateToken($size = 15) {
568
-		$token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
569
-		return $token;
570
-	}
571
-
572
-	/**
573
-	 * Get all children of this share
574
-	 *
575
-	 * @param IShare $parent
576
-	 * @return IShare[]
577
-	 */
578
-	public function getChildren(IShare $parent) {
579
-		$children = [];
580
-
581
-		$qb = $this->dbConnection->getQueryBuilder();
582
-		$qb->select('*')
583
-			->from('share')
584
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
585
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
586
-			->orderBy('id');
587
-
588
-		$cursor = $qb->execute();
589
-		while($data = $cursor->fetch()) {
590
-			$children[] = $this->createShareObject($data);
591
-		}
592
-		$cursor->closeCursor();
593
-
594
-		return $children;
595
-	}
596
-
597
-	/**
598
-	 * add share to the database and return the ID
599
-	 *
600
-	 * @param int $itemSource
601
-	 * @param string $itemType
602
-	 * @param string $shareWith
603
-	 * @param string $sharedBy
604
-	 * @param string $uidOwner
605
-	 * @param int $permissions
606
-	 * @param string $token
607
-	 * @return int
608
-	 */
609
-	protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password) {
610
-		$qb = $this->dbConnection->getQueryBuilder();
611
-		$qb->insert('share')
612
-			->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
613
-			->setValue('item_type', $qb->createNamedParameter($itemType))
614
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
615
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
616
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
617
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
618
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
619
-			->setValue('permissions', $qb->createNamedParameter($permissions))
620
-			->setValue('token', $qb->createNamedParameter($token))
621
-			->setValue('password', $qb->createNamedParameter($password))
622
-			->setValue('stime', $qb->createNamedParameter(time()));
623
-
624
-		/*
165
+        $alreadyShared = $this->getSharedWith($shareWith, \OCP\Share::SHARE_TYPE_EMAIL, $share->getNode(), 1, 0);
166
+        if (!empty($alreadyShared)) {
167
+            $message = 'Sharing %s failed, this item is already shared with %s';
168
+            $message_t = $this->l->t('Sharing %s failed, this item is already shared with %s', array($share->getNode()->getName(), $shareWith));
169
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
170
+            throw new \Exception($message_t);
171
+        }
172
+
173
+        // if the admin enforces a password for all mail shares we create a
174
+        // random password and send it to the recipient
175
+        $password = '';
176
+        $passwordEnforced = $this->settingsManager->enforcePasswordProtection();
177
+        if ($passwordEnforced) {
178
+            $password = $this->autoGeneratePassword($share);
179
+        }
180
+
181
+        $shareId = $this->createMailShare($share);
182
+        $send = $this->sendPassword($share, $password);
183
+        if ($passwordEnforced && $send === false) {
184
+            $this->sendPasswordToOwner($share, $password);
185
+        }
186
+
187
+        $this->createShareActivity($share);
188
+        $data = $this->getRawShare($shareId);
189
+
190
+        return $this->createShareObject($data);
191
+
192
+    }
193
+
194
+    /**
195
+     * auto generate password in case of password enforcement on mail shares
196
+     *
197
+     * @param IShare $share
198
+     * @return string
199
+     * @throws \Exception
200
+     */
201
+    protected function autoGeneratePassword($share) {
202
+        $initiatorUser = $this->userManager->get($share->getSharedBy());
203
+        $initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
204
+        $allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
205
+
206
+        if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
207
+            throw new \Exception(
208
+                $this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
209
+            );
210
+        }
211
+
212
+        $passwordPolicy = $this->getPasswordPolicy();
213
+        $passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
214
+        $passwordLength = 8;
215
+        if (!empty($passwordPolicy)) {
216
+            $passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
217
+            $passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
218
+        }
219
+
220
+        $password = $this->secureRandom->generate($passwordLength, $passwordCharset);
221
+
222
+        $share->setPassword($this->hasher->hash($password));
223
+
224
+        return $password;
225
+    }
226
+
227
+    /**
228
+     * get password policy
229
+     *
230
+     * @return array
231
+     */
232
+    protected function getPasswordPolicy() {
233
+        $capabilities = $this->capabilitiesManager->getCapabilities();
234
+        if (isset($capabilities['password_policy'])) {
235
+            return $capabilities['password_policy'];
236
+        }
237
+
238
+        return [];
239
+    }
240
+
241
+    /**
242
+     * create activity if a file/folder was shared by mail
243
+     *
244
+     * @param IShare $share
245
+     */
246
+    protected function createShareActivity(IShare $share) {
247
+
248
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
249
+
250
+        $this->publishActivity(
251
+            Activity::SUBJECT_SHARED_EMAIL_SELF,
252
+            [$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
253
+            $share->getSharedBy(),
254
+            $share->getNode()->getId(),
255
+            $userFolder->getRelativePath($share->getNode()->getPath())
256
+        );
257
+
258
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
259
+            $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
260
+            $fileId = $share->getNode()->getId();
261
+            $nodes = $ownerFolder->getById($fileId);
262
+            $ownerPath = $nodes[0]->getPath();
263
+            $this->publishActivity(
264
+                Activity::SUBJECT_SHARED_EMAIL_BY,
265
+                [$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
266
+                $share->getShareOwner(),
267
+                $fileId,
268
+                $ownerFolder->getRelativePath($ownerPath)
269
+            );
270
+        }
271
+
272
+    }
273
+
274
+    /**
275
+     * create activity if a file/folder was shared by mail
276
+     *
277
+     * @param IShare $share
278
+     * @param string $sharedWith
279
+     * @param bool $sendToSelf
280
+     */
281
+    protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
282
+
283
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
284
+
285
+        if ($sendToSelf) {
286
+            $this->publishActivity(
287
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
288
+                [$userFolder->getRelativePath($share->getNode()->getPath())],
289
+                $share->getSharedBy(),
290
+                $share->getNode()->getId(),
291
+                $userFolder->getRelativePath($share->getNode()->getPath())
292
+            );
293
+        } else {
294
+            $this->publishActivity(
295
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
296
+                [$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
297
+                $share->getSharedBy(),
298
+                $share->getNode()->getId(),
299
+                $userFolder->getRelativePath($share->getNode()->getPath())
300
+            );
301
+        }
302
+    }
303
+
304
+
305
+    /**
306
+     * publish activity if a file/folder was shared by mail
307
+     *
308
+     * @param $subject
309
+     * @param $parameters
310
+     * @param $affectedUser
311
+     * @param $fileId
312
+     * @param $filePath
313
+     */
314
+    protected function publishActivity($subject, $parameters, $affectedUser, $fileId, $filePath) {
315
+        $event = $this->activityManager->generateEvent();
316
+        $event->setApp('sharebymail')
317
+            ->setType('shared')
318
+            ->setSubject($subject, $parameters)
319
+            ->setAffectedUser($affectedUser)
320
+            ->setObject('files', $fileId, $filePath);
321
+        $this->activityManager->publish($event);
322
+
323
+    }
324
+
325
+    /**
326
+     * @param IShare $share
327
+     * @return int
328
+     * @throws \Exception
329
+     */
330
+    protected function createMailShare(IShare $share) {
331
+        $share->setToken($this->generateToken());
332
+        $shareId = $this->addShareToDB(
333
+            $share->getNodeId(),
334
+            $share->getNodeType(),
335
+            $share->getSharedWith(),
336
+            $share->getSharedBy(),
337
+            $share->getShareOwner(),
338
+            $share->getPermissions(),
339
+            $share->getToken(),
340
+            $share->getPassword()
341
+        );
342
+
343
+        try {
344
+            $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
345
+                ['token' => $share->getToken()]);
346
+            $this->sendMailNotification(
347
+                $share->getNode()->getName(),
348
+                $link,
349
+                $share->getSharedBy(),
350
+                $share->getSharedWith(),
351
+                $share->getExpirationDate()
352
+            );
353
+        } catch (HintException $hintException) {
354
+            $this->logger->logException($hintException, [
355
+                'message' => 'Failed to send share by mail.',
356
+                'level' => \OCP\Util::ERROR,
357
+                'app' => 'sharebymail',
358
+            ]);
359
+            $this->removeShareFromTable($shareId);
360
+            throw $hintException;
361
+        } catch (\Exception $e) {
362
+            $this->logger->logException($e, [
363
+                'message' => 'Failed to send share by mail.',
364
+                'level' => \OCP\Util::ERROR,
365
+                'app' => 'sharebymail',
366
+            ]);
367
+            $this->removeShareFromTable($shareId);
368
+            throw new HintException('Failed to send share by mail',
369
+                $this->l->t('Failed to send share by email'));
370
+        }
371
+
372
+        return $shareId;
373
+
374
+    }
375
+
376
+    /**
377
+     * @param string $filename
378
+     * @param string $link
379
+     * @param string $initiator
380
+     * @param string $shareWith
381
+     * @param \DateTime|null $expiration
382
+     * @throws \Exception If mail couldn't be sent
383
+     */
384
+    protected function sendMailNotification($filename,
385
+                                            $link,
386
+                                            $initiator,
387
+                                            $shareWith,
388
+                                            \DateTime $expiration = null) {
389
+        $initiatorUser = $this->userManager->get($initiator);
390
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
391
+        $message = $this->mailer->createMessage();
392
+
393
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
394
+            'filename' => $filename,
395
+            'link' => $link,
396
+            'initiator' => $initiatorDisplayName,
397
+            'expiration' => $expiration,
398
+            'shareWith' => $shareWith,
399
+        ]);
400
+
401
+        $emailTemplate->setSubject($this->l->t('%s shared »%s« with you', array($initiatorDisplayName, $filename)));
402
+        $emailTemplate->addHeader();
403
+        $emailTemplate->addHeading($this->l->t('%s shared »%s« with you', [$initiatorDisplayName, $filename]), false);
404
+        $text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
405
+
406
+        $emailTemplate->addBodyText(
407
+            $text . ' ' . $this->l->t('Click the button below to open it.'),
408
+            $text
409
+        );
410
+        $emailTemplate->addBodyButton(
411
+            $this->l->t('Open »%s«', [$filename]),
412
+            $link
413
+        );
414
+
415
+        $message->setTo([$shareWith]);
416
+
417
+        // The "From" contains the sharers name
418
+        $instanceName = $this->defaults->getName();
419
+        $senderName = $this->l->t(
420
+            '%s via %s',
421
+            [
422
+                $initiatorDisplayName,
423
+                $instanceName
424
+            ]
425
+        );
426
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
427
+
428
+        // The "Reply-To" is set to the sharer if an mail address is configured
429
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
430
+        $initiatorEmail = $initiatorUser->getEMailAddress();
431
+        if($initiatorEmail !== null) {
432
+            $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
433
+            $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
434
+        } else {
435
+            $emailTemplate->addFooter();
436
+        }
437
+
438
+        $message->useTemplate($emailTemplate);
439
+        $this->mailer->send($message);
440
+    }
441
+
442
+    /**
443
+     * send password to recipient of a mail share
444
+     *
445
+     * @param IShare $share
446
+     * @param string $password
447
+     * @return bool
448
+     */
449
+    protected function sendPassword(IShare $share, $password) {
450
+
451
+        $filename = $share->getNode()->getName();
452
+        $initiator = $share->getSharedBy();
453
+        $shareWith = $share->getSharedWith();
454
+
455
+        if ($password === '' || $this->settingsManager->sendPasswordByMail() === false) {
456
+            return false;
457
+        }
458
+
459
+        $initiatorUser = $this->userManager->get($initiator);
460
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
461
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
462
+
463
+        $plainBodyPart = $this->l->t("%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
464
+        $htmlBodyPart = $this->l->t('%s shared »%s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
465
+
466
+        $message = $this->mailer->createMessage();
467
+
468
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
469
+            'filename' => $filename,
470
+            'password' => $password,
471
+            'initiator' => $initiatorDisplayName,
472
+            'initiatorEmail' => $initiatorEmailAddress,
473
+            'shareWith' => $shareWith,
474
+        ]);
475
+
476
+        $emailTemplate->setSubject($this->l->t('Password to access »%s« shared to you by %s', [$filename, $initiatorDisplayName]));
477
+        $emailTemplate->addHeader();
478
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
479
+        $emailTemplate->addBodyText($htmlBodyPart, $plainBodyPart);
480
+        $emailTemplate->addBodyText($this->l->t('It is protected with the following password: %s', [$password]));
481
+
482
+        // The "From" contains the sharers name
483
+        $instanceName = $this->defaults->getName();
484
+        $senderName = $this->l->t(
485
+            '%s via %s',
486
+            [
487
+                $initiatorDisplayName,
488
+                $instanceName
489
+            ]
490
+        );
491
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
492
+        if ($initiatorEmailAddress !== null) {
493
+            $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
494
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
495
+        } else {
496
+            $emailTemplate->addFooter();
497
+        }
498
+
499
+        $message->setTo([$shareWith]);
500
+        $message->useTemplate($emailTemplate);
501
+        $this->mailer->send($message);
502
+
503
+        $this->createPasswordSendActivity($share, $shareWith, false);
504
+
505
+        return true;
506
+    }
507
+
508
+    /**
509
+     * send auto generated password to the owner. This happens if the admin enforces
510
+     * a password for mail shares and forbid to send the password by mail to the recipient
511
+     *
512
+     * @param IShare $share
513
+     * @param string $password
514
+     * @return bool
515
+     * @throws \Exception
516
+     */
517
+    protected function sendPasswordToOwner(IShare $share, $password) {
518
+
519
+        $filename = $share->getNode()->getName();
520
+        $initiator = $this->userManager->get($share->getSharedBy());
521
+        $initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
522
+        $initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
523
+        $shareWith = $share->getSharedWith();
524
+
525
+        if ($initiatorEMailAddress === null) {
526
+            throw new \Exception(
527
+                $this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
528
+            );
529
+        }
530
+
531
+        $bodyPart = $this->l->t("You just shared »%s« with %s. The share was already send to the recipient. Due to the security policies defined by the administrator of %s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.", [$filename, $shareWith, $this->defaults->getName()]);
532
+
533
+        $message = $this->mailer->createMessage();
534
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
535
+            'filename' => $filename,
536
+            'password' => $password,
537
+            'initiator' => $initiatorDisplayName,
538
+            'initiatorEmail' => $initiatorEMailAddress,
539
+            'shareWith' => $shareWith,
540
+        ]);
541
+
542
+        $emailTemplate->setSubject($this->l->t('Password to access »%s« shared with %s', [$filename, $shareWith]));
543
+        $emailTemplate->addHeader();
544
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
545
+        $emailTemplate->addBodyText($bodyPart);
546
+        $emailTemplate->addBodyText($this->l->t('This is the password: %s', [$password]));
547
+        $emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
548
+        $emailTemplate->addFooter();
549
+
550
+        if ($initiatorEMailAddress) {
551
+            $message->setFrom([$initiatorEMailAddress => $initiatorDisplayName]);
552
+        }
553
+        $message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
554
+        $message->useTemplate($emailTemplate);
555
+        $this->mailer->send($message);
556
+
557
+        $this->createPasswordSendActivity($share, $shareWith, true);
558
+
559
+        return true;
560
+    }
561
+
562
+    /**
563
+     * generate share token
564
+     *
565
+     * @return string
566
+     */
567
+    protected function generateToken($size = 15) {
568
+        $token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
569
+        return $token;
570
+    }
571
+
572
+    /**
573
+     * Get all children of this share
574
+     *
575
+     * @param IShare $parent
576
+     * @return IShare[]
577
+     */
578
+    public function getChildren(IShare $parent) {
579
+        $children = [];
580
+
581
+        $qb = $this->dbConnection->getQueryBuilder();
582
+        $qb->select('*')
583
+            ->from('share')
584
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
585
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
586
+            ->orderBy('id');
587
+
588
+        $cursor = $qb->execute();
589
+        while($data = $cursor->fetch()) {
590
+            $children[] = $this->createShareObject($data);
591
+        }
592
+        $cursor->closeCursor();
593
+
594
+        return $children;
595
+    }
596
+
597
+    /**
598
+     * add share to the database and return the ID
599
+     *
600
+     * @param int $itemSource
601
+     * @param string $itemType
602
+     * @param string $shareWith
603
+     * @param string $sharedBy
604
+     * @param string $uidOwner
605
+     * @param int $permissions
606
+     * @param string $token
607
+     * @return int
608
+     */
609
+    protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password) {
610
+        $qb = $this->dbConnection->getQueryBuilder();
611
+        $qb->insert('share')
612
+            ->setValue('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
613
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
614
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
615
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
616
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
617
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
618
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
619
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
620
+            ->setValue('token', $qb->createNamedParameter($token))
621
+            ->setValue('password', $qb->createNamedParameter($password))
622
+            ->setValue('stime', $qb->createNamedParameter(time()));
623
+
624
+        /*
625 625
 		 * Added to fix https://github.com/owncloud/core/issues/22215
626 626
 		 * Can be removed once we get rid of ajax/share.php
627 627
 		 */
628
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
628
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
629 629
 
630
-		$qb->execute();
631
-		$id = $qb->getLastInsertId();
630
+        $qb->execute();
631
+        $id = $qb->getLastInsertId();
632 632
 
633
-		return (int)$id;
634
-	}
633
+        return (int)$id;
634
+    }
635 635
 
636
-	/**
637
-	 * Update a share
638
-	 *
639
-	 * @param IShare $share
640
-	 * @param string|null $plainTextPassword
641
-	 * @return IShare The share object
642
-	 */
643
-	public function update(IShare $share, $plainTextPassword = null) {
636
+    /**
637
+     * Update a share
638
+     *
639
+     * @param IShare $share
640
+     * @param string|null $plainTextPassword
641
+     * @return IShare The share object
642
+     */
643
+    public function update(IShare $share, $plainTextPassword = null) {
644 644
 
645
-		$originalShare = $this->getShareById($share->getId());
645
+        $originalShare = $this->getShareById($share->getId());
646 646
 
647
-		// a real password was given
648
-		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
647
+        // a real password was given
648
+        $validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
649 649
 
650
-		if($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
651
-			$this->sendPassword($share, $plainTextPassword);
652
-		}
653
-		/*
650
+        if($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
651
+            $this->sendPassword($share, $plainTextPassword);
652
+        }
653
+        /*
654 654
 		 * We allow updating the permissions and password of mail shares
655 655
 		 */
656
-		$qb = $this->dbConnection->getQueryBuilder();
657
-		$qb->update('share')
658
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
659
-			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
660
-			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
661
-			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
662
-			->set('password', $qb->createNamedParameter($share->getPassword()))
663
-			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
664
-			->execute();
665
-
666
-		return $share;
667
-	}
668
-
669
-	/**
670
-	 * @inheritdoc
671
-	 */
672
-	public function move(IShare $share, $recipient) {
673
-		/**
674
-		 * nothing to do here, mail shares are only outgoing shares
675
-		 */
676
-		return $share;
677
-	}
678
-
679
-	/**
680
-	 * Delete a share (owner unShares the file)
681
-	 *
682
-	 * @param IShare $share
683
-	 */
684
-	public function delete(IShare $share) {
685
-		$this->removeShareFromTable($share->getId());
686
-	}
687
-
688
-	/**
689
-	 * @inheritdoc
690
-	 */
691
-	public function deleteFromSelf(IShare $share, $recipient) {
692
-		// nothing to do here, mail shares are only outgoing shares
693
-		return;
694
-	}
695
-
696
-	/**
697
-	 * @inheritdoc
698
-	 */
699
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
700
-		$qb = $this->dbConnection->getQueryBuilder();
701
-		$qb->select('*')
702
-			->from('share');
703
-
704
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
705
-
706
-		/**
707
-		 * Reshares for this user are shares where they are the owner.
708
-		 */
709
-		if ($reshares === false) {
710
-			//Special case for old shares created via the web UI
711
-			$or1 = $qb->expr()->andX(
712
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
713
-				$qb->expr()->isNull('uid_initiator')
714
-			);
715
-
716
-			$qb->andWhere(
717
-				$qb->expr()->orX(
718
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
719
-					$or1
720
-				)
721
-			);
722
-		} else {
723
-			$qb->andWhere(
724
-				$qb->expr()->orX(
725
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
726
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
727
-				)
728
-			);
729
-		}
730
-
731
-		if ($node !== null) {
732
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
733
-		}
734
-
735
-		if ($limit !== -1) {
736
-			$qb->setMaxResults($limit);
737
-		}
738
-
739
-		$qb->setFirstResult($offset);
740
-		$qb->orderBy('id');
741
-
742
-		$cursor = $qb->execute();
743
-		$shares = [];
744
-		while($data = $cursor->fetch()) {
745
-			$shares[] = $this->createShareObject($data);
746
-		}
747
-		$cursor->closeCursor();
748
-
749
-		return $shares;
750
-	}
751
-
752
-	/**
753
-	 * @inheritdoc
754
-	 */
755
-	public function getShareById($id, $recipientId = null) {
756
-		$qb = $this->dbConnection->getQueryBuilder();
757
-
758
-		$qb->select('*')
759
-			->from('share')
760
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
761
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
762
-
763
-		$cursor = $qb->execute();
764
-		$data = $cursor->fetch();
765
-		$cursor->closeCursor();
766
-
767
-		if ($data === false) {
768
-			throw new ShareNotFound();
769
-		}
770
-
771
-		try {
772
-			$share = $this->createShareObject($data);
773
-		} catch (InvalidShare $e) {
774
-			throw new ShareNotFound();
775
-		}
776
-
777
-		return $share;
778
-	}
779
-
780
-	/**
781
-	 * Get shares for a given path
782
-	 *
783
-	 * @param \OCP\Files\Node $path
784
-	 * @return IShare[]
785
-	 */
786
-	public function getSharesByPath(Node $path) {
787
-		$qb = $this->dbConnection->getQueryBuilder();
788
-
789
-		$cursor = $qb->select('*')
790
-			->from('share')
791
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
792
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
793
-			->execute();
794
-
795
-		$shares = [];
796
-		while($data = $cursor->fetch()) {
797
-			$shares[] = $this->createShareObject($data);
798
-		}
799
-		$cursor->closeCursor();
800
-
801
-		return $shares;
802
-	}
803
-
804
-	/**
805
-	 * @inheritdoc
806
-	 */
807
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
808
-		/** @var IShare[] $shares */
809
-		$shares = [];
810
-
811
-		//Get shares directly with this user
812
-		$qb = $this->dbConnection->getQueryBuilder();
813
-		$qb->select('*')
814
-			->from('share');
815
-
816
-		// Order by id
817
-		$qb->orderBy('id');
818
-
819
-		// Set limit and offset
820
-		if ($limit !== -1) {
821
-			$qb->setMaxResults($limit);
822
-		}
823
-		$qb->setFirstResult($offset);
824
-
825
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
826
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
827
-
828
-		// Filter by node if provided
829
-		if ($node !== null) {
830
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
831
-		}
832
-
833
-		$cursor = $qb->execute();
834
-
835
-		while($data = $cursor->fetch()) {
836
-			$shares[] = $this->createShareObject($data);
837
-		}
838
-		$cursor->closeCursor();
839
-
840
-
841
-		return $shares;
842
-	}
843
-
844
-	/**
845
-	 * Get a share by token
846
-	 *
847
-	 * @param string $token
848
-	 * @return IShare
849
-	 * @throws ShareNotFound
850
-	 */
851
-	public function getShareByToken($token) {
852
-		$qb = $this->dbConnection->getQueryBuilder();
853
-
854
-		$cursor = $qb->select('*')
855
-			->from('share')
856
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
857
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
858
-			->execute();
859
-
860
-		$data = $cursor->fetch();
861
-
862
-		if ($data === false) {
863
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
864
-		}
865
-
866
-		try {
867
-			$share = $this->createShareObject($data);
868
-		} catch (InvalidShare $e) {
869
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
870
-		}
871
-
872
-		return $share;
873
-	}
874
-
875
-	/**
876
-	 * remove share from table
877
-	 *
878
-	 * @param string $shareId
879
-	 */
880
-	protected function removeShareFromTable($shareId) {
881
-		$qb = $this->dbConnection->getQueryBuilder();
882
-		$qb->delete('share')
883
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
884
-		$qb->execute();
885
-	}
886
-
887
-	/**
888
-	 * Create a share object from an database row
889
-	 *
890
-	 * @param array $data
891
-	 * @return IShare
892
-	 * @throws InvalidShare
893
-	 * @throws ShareNotFound
894
-	 */
895
-	protected function createShareObject($data) {
896
-
897
-		$share = new Share($this->rootFolder, $this->userManager);
898
-		$share->setId((int)$data['id'])
899
-			->setShareType((int)$data['share_type'])
900
-			->setPermissions((int)$data['permissions'])
901
-			->setTarget($data['file_target'])
902
-			->setMailSend((bool)$data['mail_send'])
903
-			->setToken($data['token']);
904
-
905
-		$shareTime = new \DateTime();
906
-		$shareTime->setTimestamp((int)$data['stime']);
907
-		$share->setShareTime($shareTime);
908
-		$share->setSharedWith($data['share_with']);
909
-		$share->setPassword($data['password']);
910
-
911
-		if ($data['uid_initiator'] !== null) {
912
-			$share->setShareOwner($data['uid_owner']);
913
-			$share->setSharedBy($data['uid_initiator']);
914
-		} else {
915
-			//OLD SHARE
916
-			$share->setSharedBy($data['uid_owner']);
917
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
918
-
919
-			$owner = $path->getOwner();
920
-			$share->setShareOwner($owner->getUID());
921
-		}
922
-
923
-		if ($data['expiration'] !== null) {
924
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
925
-			if ($expiration !== false) {
926
-				$share->setExpirationDate($expiration);
927
-			}
928
-		}
929
-
930
-		$share->setNodeId((int)$data['file_source']);
931
-		$share->setNodeType($data['item_type']);
932
-
933
-		$share->setProviderId($this->identifier());
934
-
935
-		return $share;
936
-	}
937
-
938
-	/**
939
-	 * Get the node with file $id for $user
940
-	 *
941
-	 * @param string $userId
942
-	 * @param int $id
943
-	 * @return \OCP\Files\File|\OCP\Files\Folder
944
-	 * @throws InvalidShare
945
-	 */
946
-	private function getNode($userId, $id) {
947
-		try {
948
-			$userFolder = $this->rootFolder->getUserFolder($userId);
949
-		} catch (NoUserException $e) {
950
-			throw new InvalidShare();
951
-		}
952
-
953
-		$nodes = $userFolder->getById($id);
954
-
955
-		if (empty($nodes)) {
956
-			throw new InvalidShare();
957
-		}
958
-
959
-		return $nodes[0];
960
-	}
961
-
962
-	/**
963
-	 * A user is deleted from the system
964
-	 * So clean up the relevant shares.
965
-	 *
966
-	 * @param string $uid
967
-	 * @param int $shareType
968
-	 */
969
-	public function userDeleted($uid, $shareType) {
970
-		$qb = $this->dbConnection->getQueryBuilder();
971
-
972
-		$qb->delete('share')
973
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
974
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
975
-			->execute();
976
-	}
977
-
978
-	/**
979
-	 * This provider does not support group shares
980
-	 *
981
-	 * @param string $gid
982
-	 */
983
-	public function groupDeleted($gid) {
984
-		return;
985
-	}
986
-
987
-	/**
988
-	 * This provider does not support group shares
989
-	 *
990
-	 * @param string $uid
991
-	 * @param string $gid
992
-	 */
993
-	public function userDeletedFromGroup($uid, $gid) {
994
-		return;
995
-	}
996
-
997
-	/**
998
-	 * get database row of a give share
999
-	 *
1000
-	 * @param $id
1001
-	 * @return array
1002
-	 * @throws ShareNotFound
1003
-	 */
1004
-	protected function getRawShare($id) {
1005
-
1006
-		// Now fetch the inserted share and create a complete share object
1007
-		$qb = $this->dbConnection->getQueryBuilder();
1008
-		$qb->select('*')
1009
-			->from('share')
1010
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1011
-
1012
-		$cursor = $qb->execute();
1013
-		$data = $cursor->fetch();
1014
-		$cursor->closeCursor();
1015
-
1016
-		if ($data === false) {
1017
-			throw new ShareNotFound;
1018
-		}
1019
-
1020
-		return $data;
1021
-	}
1022
-
1023
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
1024
-		$qb = $this->dbConnection->getQueryBuilder();
1025
-		$qb->select('*')
1026
-			->from('share', 's')
1027
-			->andWhere($qb->expr()->orX(
1028
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1029
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1030
-			))
1031
-			->andWhere(
1032
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
1033
-			);
1034
-
1035
-		/**
1036
-		 * Reshares for this user are shares where they are the owner.
1037
-		 */
1038
-		if ($reshares === false) {
1039
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1040
-		} else {
1041
-			$qb->andWhere(
1042
-				$qb->expr()->orX(
1043
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1044
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1045
-				)
1046
-			);
1047
-		}
1048
-
1049
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1050
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1051
-
1052
-		$qb->orderBy('id');
1053
-
1054
-		$cursor = $qb->execute();
1055
-		$shares = [];
1056
-		while ($data = $cursor->fetch()) {
1057
-			$shares[$data['fileid']][] = $this->createShareObject($data);
1058
-		}
1059
-		$cursor->closeCursor();
1060
-
1061
-		return $shares;
1062
-	}
1063
-
1064
-	/**
1065
-	 * @inheritdoc
1066
-	 */
1067
-	public function getAccessList($nodes, $currentAccess) {
1068
-		$ids = [];
1069
-		foreach ($nodes as $node) {
1070
-			$ids[] = $node->getId();
1071
-		}
1072
-
1073
-		$qb = $this->dbConnection->getQueryBuilder();
1074
-		$qb->select('share_with')
1075
-			->from('share')
1076
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1077
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1078
-			->andWhere($qb->expr()->orX(
1079
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1080
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1081
-			))
1082
-			->setMaxResults(1);
1083
-		$cursor = $qb->execute();
1084
-
1085
-		$mail = $cursor->fetch() !== false;
1086
-		$cursor->closeCursor();
1087
-
1088
-		return ['public' => $mail];
1089
-	}
656
+        $qb = $this->dbConnection->getQueryBuilder();
657
+        $qb->update('share')
658
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
659
+            ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
660
+            ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
661
+            ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
662
+            ->set('password', $qb->createNamedParameter($share->getPassword()))
663
+            ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
664
+            ->execute();
665
+
666
+        return $share;
667
+    }
668
+
669
+    /**
670
+     * @inheritdoc
671
+     */
672
+    public function move(IShare $share, $recipient) {
673
+        /**
674
+         * nothing to do here, mail shares are only outgoing shares
675
+         */
676
+        return $share;
677
+    }
678
+
679
+    /**
680
+     * Delete a share (owner unShares the file)
681
+     *
682
+     * @param IShare $share
683
+     */
684
+    public function delete(IShare $share) {
685
+        $this->removeShareFromTable($share->getId());
686
+    }
687
+
688
+    /**
689
+     * @inheritdoc
690
+     */
691
+    public function deleteFromSelf(IShare $share, $recipient) {
692
+        // nothing to do here, mail shares are only outgoing shares
693
+        return;
694
+    }
695
+
696
+    /**
697
+     * @inheritdoc
698
+     */
699
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
700
+        $qb = $this->dbConnection->getQueryBuilder();
701
+        $qb->select('*')
702
+            ->from('share');
703
+
704
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
705
+
706
+        /**
707
+         * Reshares for this user are shares where they are the owner.
708
+         */
709
+        if ($reshares === false) {
710
+            //Special case for old shares created via the web UI
711
+            $or1 = $qb->expr()->andX(
712
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
713
+                $qb->expr()->isNull('uid_initiator')
714
+            );
715
+
716
+            $qb->andWhere(
717
+                $qb->expr()->orX(
718
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
719
+                    $or1
720
+                )
721
+            );
722
+        } else {
723
+            $qb->andWhere(
724
+                $qb->expr()->orX(
725
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
726
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
727
+                )
728
+            );
729
+        }
730
+
731
+        if ($node !== null) {
732
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
733
+        }
734
+
735
+        if ($limit !== -1) {
736
+            $qb->setMaxResults($limit);
737
+        }
738
+
739
+        $qb->setFirstResult($offset);
740
+        $qb->orderBy('id');
741
+
742
+        $cursor = $qb->execute();
743
+        $shares = [];
744
+        while($data = $cursor->fetch()) {
745
+            $shares[] = $this->createShareObject($data);
746
+        }
747
+        $cursor->closeCursor();
748
+
749
+        return $shares;
750
+    }
751
+
752
+    /**
753
+     * @inheritdoc
754
+     */
755
+    public function getShareById($id, $recipientId = null) {
756
+        $qb = $this->dbConnection->getQueryBuilder();
757
+
758
+        $qb->select('*')
759
+            ->from('share')
760
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
761
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
762
+
763
+        $cursor = $qb->execute();
764
+        $data = $cursor->fetch();
765
+        $cursor->closeCursor();
766
+
767
+        if ($data === false) {
768
+            throw new ShareNotFound();
769
+        }
770
+
771
+        try {
772
+            $share = $this->createShareObject($data);
773
+        } catch (InvalidShare $e) {
774
+            throw new ShareNotFound();
775
+        }
776
+
777
+        return $share;
778
+    }
779
+
780
+    /**
781
+     * Get shares for a given path
782
+     *
783
+     * @param \OCP\Files\Node $path
784
+     * @return IShare[]
785
+     */
786
+    public function getSharesByPath(Node $path) {
787
+        $qb = $this->dbConnection->getQueryBuilder();
788
+
789
+        $cursor = $qb->select('*')
790
+            ->from('share')
791
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
792
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
793
+            ->execute();
794
+
795
+        $shares = [];
796
+        while($data = $cursor->fetch()) {
797
+            $shares[] = $this->createShareObject($data);
798
+        }
799
+        $cursor->closeCursor();
800
+
801
+        return $shares;
802
+    }
803
+
804
+    /**
805
+     * @inheritdoc
806
+     */
807
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
808
+        /** @var IShare[] $shares */
809
+        $shares = [];
810
+
811
+        //Get shares directly with this user
812
+        $qb = $this->dbConnection->getQueryBuilder();
813
+        $qb->select('*')
814
+            ->from('share');
815
+
816
+        // Order by id
817
+        $qb->orderBy('id');
818
+
819
+        // Set limit and offset
820
+        if ($limit !== -1) {
821
+            $qb->setMaxResults($limit);
822
+        }
823
+        $qb->setFirstResult($offset);
824
+
825
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
826
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
827
+
828
+        // Filter by node if provided
829
+        if ($node !== null) {
830
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
831
+        }
832
+
833
+        $cursor = $qb->execute();
834
+
835
+        while($data = $cursor->fetch()) {
836
+            $shares[] = $this->createShareObject($data);
837
+        }
838
+        $cursor->closeCursor();
839
+
840
+
841
+        return $shares;
842
+    }
843
+
844
+    /**
845
+     * Get a share by token
846
+     *
847
+     * @param string $token
848
+     * @return IShare
849
+     * @throws ShareNotFound
850
+     */
851
+    public function getShareByToken($token) {
852
+        $qb = $this->dbConnection->getQueryBuilder();
853
+
854
+        $cursor = $qb->select('*')
855
+            ->from('share')
856
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
857
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
858
+            ->execute();
859
+
860
+        $data = $cursor->fetch();
861
+
862
+        if ($data === false) {
863
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
864
+        }
865
+
866
+        try {
867
+            $share = $this->createShareObject($data);
868
+        } catch (InvalidShare $e) {
869
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
870
+        }
871
+
872
+        return $share;
873
+    }
874
+
875
+    /**
876
+     * remove share from table
877
+     *
878
+     * @param string $shareId
879
+     */
880
+    protected function removeShareFromTable($shareId) {
881
+        $qb = $this->dbConnection->getQueryBuilder();
882
+        $qb->delete('share')
883
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
884
+        $qb->execute();
885
+    }
886
+
887
+    /**
888
+     * Create a share object from an database row
889
+     *
890
+     * @param array $data
891
+     * @return IShare
892
+     * @throws InvalidShare
893
+     * @throws ShareNotFound
894
+     */
895
+    protected function createShareObject($data) {
896
+
897
+        $share = new Share($this->rootFolder, $this->userManager);
898
+        $share->setId((int)$data['id'])
899
+            ->setShareType((int)$data['share_type'])
900
+            ->setPermissions((int)$data['permissions'])
901
+            ->setTarget($data['file_target'])
902
+            ->setMailSend((bool)$data['mail_send'])
903
+            ->setToken($data['token']);
904
+
905
+        $shareTime = new \DateTime();
906
+        $shareTime->setTimestamp((int)$data['stime']);
907
+        $share->setShareTime($shareTime);
908
+        $share->setSharedWith($data['share_with']);
909
+        $share->setPassword($data['password']);
910
+
911
+        if ($data['uid_initiator'] !== null) {
912
+            $share->setShareOwner($data['uid_owner']);
913
+            $share->setSharedBy($data['uid_initiator']);
914
+        } else {
915
+            //OLD SHARE
916
+            $share->setSharedBy($data['uid_owner']);
917
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
918
+
919
+            $owner = $path->getOwner();
920
+            $share->setShareOwner($owner->getUID());
921
+        }
922
+
923
+        if ($data['expiration'] !== null) {
924
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
925
+            if ($expiration !== false) {
926
+                $share->setExpirationDate($expiration);
927
+            }
928
+        }
929
+
930
+        $share->setNodeId((int)$data['file_source']);
931
+        $share->setNodeType($data['item_type']);
932
+
933
+        $share->setProviderId($this->identifier());
934
+
935
+        return $share;
936
+    }
937
+
938
+    /**
939
+     * Get the node with file $id for $user
940
+     *
941
+     * @param string $userId
942
+     * @param int $id
943
+     * @return \OCP\Files\File|\OCP\Files\Folder
944
+     * @throws InvalidShare
945
+     */
946
+    private function getNode($userId, $id) {
947
+        try {
948
+            $userFolder = $this->rootFolder->getUserFolder($userId);
949
+        } catch (NoUserException $e) {
950
+            throw new InvalidShare();
951
+        }
952
+
953
+        $nodes = $userFolder->getById($id);
954
+
955
+        if (empty($nodes)) {
956
+            throw new InvalidShare();
957
+        }
958
+
959
+        return $nodes[0];
960
+    }
961
+
962
+    /**
963
+     * A user is deleted from the system
964
+     * So clean up the relevant shares.
965
+     *
966
+     * @param string $uid
967
+     * @param int $shareType
968
+     */
969
+    public function userDeleted($uid, $shareType) {
970
+        $qb = $this->dbConnection->getQueryBuilder();
971
+
972
+        $qb->delete('share')
973
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
974
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
975
+            ->execute();
976
+    }
977
+
978
+    /**
979
+     * This provider does not support group shares
980
+     *
981
+     * @param string $gid
982
+     */
983
+    public function groupDeleted($gid) {
984
+        return;
985
+    }
986
+
987
+    /**
988
+     * This provider does not support group shares
989
+     *
990
+     * @param string $uid
991
+     * @param string $gid
992
+     */
993
+    public function userDeletedFromGroup($uid, $gid) {
994
+        return;
995
+    }
996
+
997
+    /**
998
+     * get database row of a give share
999
+     *
1000
+     * @param $id
1001
+     * @return array
1002
+     * @throws ShareNotFound
1003
+     */
1004
+    protected function getRawShare($id) {
1005
+
1006
+        // Now fetch the inserted share and create a complete share object
1007
+        $qb = $this->dbConnection->getQueryBuilder();
1008
+        $qb->select('*')
1009
+            ->from('share')
1010
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1011
+
1012
+        $cursor = $qb->execute();
1013
+        $data = $cursor->fetch();
1014
+        $cursor->closeCursor();
1015
+
1016
+        if ($data === false) {
1017
+            throw new ShareNotFound;
1018
+        }
1019
+
1020
+        return $data;
1021
+    }
1022
+
1023
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
1024
+        $qb = $this->dbConnection->getQueryBuilder();
1025
+        $qb->select('*')
1026
+            ->from('share', 's')
1027
+            ->andWhere($qb->expr()->orX(
1028
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1029
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1030
+            ))
1031
+            ->andWhere(
1032
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
1033
+            );
1034
+
1035
+        /**
1036
+         * Reshares for this user are shares where they are the owner.
1037
+         */
1038
+        if ($reshares === false) {
1039
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1040
+        } else {
1041
+            $qb->andWhere(
1042
+                $qb->expr()->orX(
1043
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1044
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1045
+                )
1046
+            );
1047
+        }
1048
+
1049
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1050
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1051
+
1052
+        $qb->orderBy('id');
1053
+
1054
+        $cursor = $qb->execute();
1055
+        $shares = [];
1056
+        while ($data = $cursor->fetch()) {
1057
+            $shares[$data['fileid']][] = $this->createShareObject($data);
1058
+        }
1059
+        $cursor->closeCursor();
1060
+
1061
+        return $shares;
1062
+    }
1063
+
1064
+    /**
1065
+     * @inheritdoc
1066
+     */
1067
+    public function getAccessList($nodes, $currentAccess) {
1068
+        $ids = [];
1069
+        foreach ($nodes as $node) {
1070
+            $ids[] = $node->getId();
1071
+        }
1072
+
1073
+        $qb = $this->dbConnection->getQueryBuilder();
1074
+        $qb->select('share_with')
1075
+            ->from('share')
1076
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1077
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1078
+            ->andWhere($qb->expr()->orX(
1079
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1080
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1081
+            ))
1082
+            ->setMaxResults(1);
1083
+        $cursor = $qb->execute();
1084
+
1085
+        $mail = $cursor->fetch() !== false;
1086
+        $cursor->closeCursor();
1087
+
1088
+        return ['public' => $mail];
1089
+    }
1090 1090
 
1091 1091
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -210,10 +210,10 @@  discard block
 block discarded – undo
210 210
 		}
211 211
 
212 212
 		$passwordPolicy = $this->getPasswordPolicy();
213
-		$passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
213
+		$passwordCharset = ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_UPPER.ISecureRandom::CHAR_DIGITS;
214 214
 		$passwordLength = 8;
215 215
 		if (!empty($passwordPolicy)) {
216
-			$passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
216
+			$passwordLength = (int) $passwordPolicy['minLength'] > 0 ? (int) $passwordPolicy['minLength'] : $passwordLength;
217 217
 			$passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
218 218
 		}
219 219
 
@@ -404,7 +404,7 @@  discard block
 block discarded – undo
404 404
 		$text = $this->l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
405 405
 
406 406
 		$emailTemplate->addBodyText(
407
-			$text . ' ' . $this->l->t('Click the button below to open it.'),
407
+			$text.' '.$this->l->t('Click the button below to open it.'),
408 408
 			$text
409 409
 		);
410 410
 		$emailTemplate->addBodyButton(
@@ -428,9 +428,9 @@  discard block
 block discarded – undo
428 428
 		// The "Reply-To" is set to the sharer if an mail address is configured
429 429
 		// also the default footer contains a "Do not reply" which needs to be adjusted.
430 430
 		$initiatorEmail = $initiatorUser->getEMailAddress();
431
-		if($initiatorEmail !== null) {
431
+		if ($initiatorEmail !== null) {
432 432
 			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
433
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
433
+			$emailTemplate->addFooter($instanceName.($this->defaults->getSlogan() !== '' ? ' - '.$this->defaults->getSlogan() : ''));
434 434
 		} else {
435 435
 			$emailTemplate->addFooter();
436 436
 		}
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
 		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
492 492
 		if ($initiatorEmailAddress !== null) {
493 493
 			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
494
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
494
+			$emailTemplate->addFooter($instanceName.' - '.$this->defaults->getSlogan());
495 495
 		} else {
496 496
 			$emailTemplate->addFooter();
497 497
 		}
@@ -586,7 +586,7 @@  discard block
 block discarded – undo
586 586
 			->orderBy('id');
587 587
 
588 588
 		$cursor = $qb->execute();
589
-		while($data = $cursor->fetch()) {
589
+		while ($data = $cursor->fetch()) {
590 590
 			$children[] = $this->createShareObject($data);
591 591
 		}
592 592
 		$cursor->closeCursor();
@@ -630,7 +630,7 @@  discard block
 block discarded – undo
630 630
 		$qb->execute();
631 631
 		$id = $qb->getLastInsertId();
632 632
 
633
-		return (int)$id;
633
+		return (int) $id;
634 634
 	}
635 635
 
636 636
 	/**
@@ -647,7 +647,7 @@  discard block
 block discarded – undo
647 647
 		// a real password was given
648 648
 		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
649 649
 
650
-		if($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
650
+		if ($validPassword && $originalShare->getPassword() !== $share->getPassword()) {
651 651
 			$this->sendPassword($share, $plainTextPassword);
652 652
 		}
653 653
 		/*
@@ -741,7 +741,7 @@  discard block
 block discarded – undo
741 741
 
742 742
 		$cursor = $qb->execute();
743 743
 		$shares = [];
744
-		while($data = $cursor->fetch()) {
744
+		while ($data = $cursor->fetch()) {
745 745
 			$shares[] = $this->createShareObject($data);
746 746
 		}
747 747
 		$cursor->closeCursor();
@@ -793,7 +793,7 @@  discard block
 block discarded – undo
793 793
 			->execute();
794 794
 
795 795
 		$shares = [];
796
-		while($data = $cursor->fetch()) {
796
+		while ($data = $cursor->fetch()) {
797 797
 			$shares[] = $this->createShareObject($data);
798 798
 		}
799 799
 		$cursor->closeCursor();
@@ -832,7 +832,7 @@  discard block
 block discarded – undo
832 832
 
833 833
 		$cursor = $qb->execute();
834 834
 
835
-		while($data = $cursor->fetch()) {
835
+		while ($data = $cursor->fetch()) {
836 836
 			$shares[] = $this->createShareObject($data);
837 837
 		}
838 838
 		$cursor->closeCursor();
@@ -895,15 +895,15 @@  discard block
 block discarded – undo
895 895
 	protected function createShareObject($data) {
896 896
 
897 897
 		$share = new Share($this->rootFolder, $this->userManager);
898
-		$share->setId((int)$data['id'])
899
-			->setShareType((int)$data['share_type'])
900
-			->setPermissions((int)$data['permissions'])
898
+		$share->setId((int) $data['id'])
899
+			->setShareType((int) $data['share_type'])
900
+			->setPermissions((int) $data['permissions'])
901 901
 			->setTarget($data['file_target'])
902
-			->setMailSend((bool)$data['mail_send'])
902
+			->setMailSend((bool) $data['mail_send'])
903 903
 			->setToken($data['token']);
904 904
 
905 905
 		$shareTime = new \DateTime();
906
-		$shareTime->setTimestamp((int)$data['stime']);
906
+		$shareTime->setTimestamp((int) $data['stime']);
907 907
 		$share->setShareTime($shareTime);
908 908
 		$share->setSharedWith($data['share_with']);
909 909
 		$share->setPassword($data['password']);
@@ -914,7 +914,7 @@  discard block
 block discarded – undo
914 914
 		} else {
915 915
 			//OLD SHARE
916 916
 			$share->setSharedBy($data['uid_owner']);
917
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
917
+			$path = $this->getNode($share->getSharedBy(), (int) $data['file_source']);
918 918
 
919 919
 			$owner = $path->getOwner();
920 920
 			$share->setShareOwner($owner->getUID());
@@ -927,7 +927,7 @@  discard block
 block discarded – undo
927 927
 			}
928 928
 		}
929 929
 
930
-		$share->setNodeId((int)$data['file_source']);
930
+		$share->setNodeId((int) $data['file_source']);
931 931
 		$share->setNodeType($data['item_type']);
932 932
 
933 933
 		$share->setProviderId($this->identifier());
@@ -1046,7 +1046,7 @@  discard block
 block discarded – undo
1046 1046
 			);
1047 1047
 		}
1048 1048
 
1049
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1049
+		$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1050 1050
 		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1051 1051
 
1052 1052
 		$qb->orderBy('id');
Please login to merge, or discard this patch.
apps/federation/lib/SyncJob.php 1 patch
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -29,32 +29,32 @@
 block discarded – undo
29 29
 
30 30
 class SyncJob extends TimedJob {
31 31
 
32
-	/** @var SyncFederationAddressBooks */
33
-	protected $syncService;
32
+    /** @var SyncFederationAddressBooks */
33
+    protected $syncService;
34 34
 
35
-	/** @var ILogger */
36
-	protected $logger;
35
+    /** @var ILogger */
36
+    protected $logger;
37 37
 
38
-	/**
39
-	 * @param SyncFederationAddressBooks $syncService
40
-	 * @param ILogger $logger
41
-	 */
42
-	public function __construct(SyncFederationAddressBooks $syncService, ILogger $logger) {
43
-		// Run once a day
44
-		$this->setInterval(24 * 60 * 60);
45
-		$this->syncService = $syncService;
46
-		$this->logger = $logger;
47
-	}
38
+    /**
39
+     * @param SyncFederationAddressBooks $syncService
40
+     * @param ILogger $logger
41
+     */
42
+    public function __construct(SyncFederationAddressBooks $syncService, ILogger $logger) {
43
+        // Run once a day
44
+        $this->setInterval(24 * 60 * 60);
45
+        $this->syncService = $syncService;
46
+        $this->logger = $logger;
47
+    }
48 48
 
49
-	protected function run($argument) {
50
-		$this->syncService->syncThemAll(function($url, $ex) {
51
-			if ($ex instanceof \Exception) {
52
-				$this->logger->logException($ex, [
53
-					'message' => "Error while syncing $url.",
54
-					'level' => \OCP\Util::ERROR,
55
-					'app' => 'fed-sync',
56
-				]);
57
-			}
58
-		});
59
-	}
49
+    protected function run($argument) {
50
+        $this->syncService->syncThemAll(function($url, $ex) {
51
+            if ($ex instanceof \Exception) {
52
+                $this->logger->logException($ex, [
53
+                    'message' => "Error while syncing $url.",
54
+                    'level' => \OCP\Util::ERROR,
55
+                    'app' => 'fed-sync',
56
+                ]);
57
+            }
58
+        });
59
+    }
60 60
 }
Please login to merge, or discard this patch.
apps/federation/lib/BackgroundJob/GetSharedSecret.php 2 patches
Indentation   +209 added lines, -209 removed lines patch added patch discarded remove patch
@@ -57,213 +57,213 @@
 block discarded – undo
57 57
  */
58 58
 class GetSharedSecret extends Job {
59 59
 
60
-	/** @var IClient */
61
-	private $httpClient;
62
-
63
-	/** @var IJobList */
64
-	private $jobList;
65
-
66
-	/** @var IURLGenerator */
67
-	private $urlGenerator;
68
-
69
-	/** @var TrustedServers  */
70
-	private $trustedServers;
71
-
72
-	/** @var DbHandler */
73
-	private $dbHandler;
74
-
75
-	/** @var IDiscoveryService  */
76
-	private $ocsDiscoveryService;
77
-
78
-	/** @var ILogger */
79
-	private $logger;
80
-
81
-	/** @var ITimeFactory */
82
-	private $timeFactory;
83
-
84
-	/** @var bool */
85
-	protected $retainJob = false;
86
-
87
-	private $format = '?format=json';
88
-
89
-	private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret';
90
-
91
-	/** @var  int  30 day = 2592000sec */
92
-	private $maxLifespan = 2592000;
93
-
94
-	/**
95
-	 * RequestSharedSecret constructor.
96
-	 *
97
-	 * @param IClientService $httpClientService
98
-	 * @param IURLGenerator $urlGenerator
99
-	 * @param IJobList $jobList
100
-	 * @param TrustedServers $trustedServers
101
-	 * @param ILogger $logger
102
-	 * @param DbHandler $dbHandler
103
-	 * @param IDiscoveryService $ocsDiscoveryService
104
-	 * @param ITimeFactory $timeFactory
105
-	 */
106
-	public function __construct(
107
-		IClientService $httpClientService,
108
-		IURLGenerator $urlGenerator,
109
-		IJobList $jobList,
110
-		TrustedServers $trustedServers,
111
-		ILogger $logger,
112
-		DbHandler $dbHandler,
113
-		IDiscoveryService $ocsDiscoveryService,
114
-		ITimeFactory $timeFactory
115
-	) {
116
-		$this->logger = $logger;
117
-		$this->httpClient = $httpClientService->newClient();
118
-		$this->jobList = $jobList;
119
-		$this->urlGenerator = $urlGenerator;
120
-		$this->dbHandler = $dbHandler;
121
-		$this->ocsDiscoveryService = $ocsDiscoveryService;
122
-		$this->trustedServers = $trustedServers;
123
-		$this->timeFactory = $timeFactory;
124
-	}
125
-
126
-	/**
127
-	 * run the job, then remove it from the joblist
128
-	 *
129
-	 * @param JobList $jobList
130
-	 * @param ILogger|null $logger
131
-	 */
132
-	public function execute($jobList, ILogger $logger = null) {
133
-		$target = $this->argument['url'];
134
-		// only execute if target is still in the list of trusted domains
135
-		if ($this->trustedServers->isTrustedServer($target)) {
136
-			$this->parentExecute($jobList, $logger);
137
-		}
138
-
139
-		$jobList->remove($this, $this->argument);
140
-
141
-		if ($this->retainJob) {
142
-			$this->reAddJob($this->argument);
143
-		}
144
-	}
145
-
146
-	/**
147
-	 * call execute() method of parent
148
-	 *
149
-	 * @param JobList $jobList
150
-	 * @param ILogger $logger
151
-	 */
152
-	protected function parentExecute($jobList, $logger = null) {
153
-		parent::execute($jobList, $logger);
154
-	}
155
-
156
-	protected function run($argument) {
157
-		$target = $argument['url'];
158
-		$created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
159
-		$currentTime = $this->timeFactory->getTime();
160
-		$source = $this->urlGenerator->getAbsoluteURL('/');
161
-		$source = rtrim($source, '/');
162
-		$token = $argument['token'];
163
-
164
-		// kill job after 30 days of trying
165
-		$deadline = $currentTime - $this->maxLifespan;
166
-		if ($created < $deadline) {
167
-			$this->retainJob = false;
168
-			$this->trustedServers->setServerStatus($target,TrustedServers::STATUS_FAILURE);
169
-			return;
170
-		}
171
-
172
-		$endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING');
173
-		$endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
174
-
175
-		// make sure that we have a well formatted url
176
-		$url = rtrim($target, '/') . '/' . trim($endPoint, '/') . $this->format;
177
-
178
-		$result = null;
179
-		try {
180
-			$result = $this->httpClient->get(
181
-				$url,
182
-				[
183
-					'query' =>
184
-						[
185
-							'url' => $source,
186
-							'token' => $token
187
-						],
188
-					'timeout' => 3,
189
-					'connect_timeout' => 3,
190
-				]
191
-			);
192
-
193
-			$status = $result->getStatusCode();
194
-
195
-		} catch (ClientException $e) {
196
-			$status = $e->getCode();
197
-			if ($status === Http::STATUS_FORBIDDEN) {
198
-				$this->logger->info($target . ' refused to exchange a shared secret with you.', ['app' => 'federation']);
199
-			} else {
200
-				$this->logger->info($target . ' responded with a ' . $status . ' containing: ' . $e->getMessage(), ['app' => 'federation']);
201
-			}
202
-		} catch (RequestException $e) {
203
-			$status = -1; // There is no status code if we could not connect
204
-			$this->logger->logException($e, [
205
-				'message' => 'Could not connect to ' . $target,
206
-				'level' => \OCP\Util::INFO,
207
-				'app' => 'federation',
208
-			]);
209
-		} catch (RingException $e) {
210
-			$status = -1; // There is no status code if we could not connect
211
-			$this->logger->logException($e, [
212
-				'message' => 'Could not connect to ' . $target,
213
-				'level' => \OCP\Util::INFO,
214
-				'app' => 'federation',
215
-			]);
216
-		} catch (\Exception $e) {
217
-			$status = Http::STATUS_INTERNAL_SERVER_ERROR;
218
-			$this->logger->logException($e, ['app' => 'federation']);
219
-		}
220
-
221
-		// if we received a unexpected response we try again later
222
-		if (
223
-			$status !== Http::STATUS_OK
224
-			&& $status !== Http::STATUS_FORBIDDEN
225
-		) {
226
-			$this->retainJob = true;
227
-		}  else {
228
-			// reset token if we received a valid response
229
-			$this->dbHandler->addToken($target, '');
230
-		}
231
-
232
-		if ($status === Http::STATUS_OK && $result instanceof IResponse) {
233
-			$body = $result->getBody();
234
-			$result = json_decode($body, true);
235
-			if (isset($result['ocs']['data']['sharedSecret'])) {
236
-				$this->trustedServers->addSharedSecret(
237
-						$target,
238
-						$result['ocs']['data']['sharedSecret']
239
-				);
240
-			} else {
241
-				$this->logger->error(
242
-						'remote server "' . $target . '"" does not return a valid shared secret',
243
-						['app' => 'federation']
244
-				);
245
-				$this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
246
-			}
247
-		}
248
-
249
-	}
250
-
251
-	/**
252
-	 * re-add background job
253
-	 *
254
-	 * @param array $argument
255
-	 */
256
-	protected function reAddJob(array $argument) {
257
-		$url = $argument['url'];
258
-		$created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
259
-		$token = $argument['token'];
260
-		$this->jobList->add(
261
-			GetSharedSecret::class,
262
-			[
263
-				'url' => $url,
264
-				'token' => $token,
265
-				'created' => $created
266
-			]
267
-		);
268
-	}
60
+    /** @var IClient */
61
+    private $httpClient;
62
+
63
+    /** @var IJobList */
64
+    private $jobList;
65
+
66
+    /** @var IURLGenerator */
67
+    private $urlGenerator;
68
+
69
+    /** @var TrustedServers  */
70
+    private $trustedServers;
71
+
72
+    /** @var DbHandler */
73
+    private $dbHandler;
74
+
75
+    /** @var IDiscoveryService  */
76
+    private $ocsDiscoveryService;
77
+
78
+    /** @var ILogger */
79
+    private $logger;
80
+
81
+    /** @var ITimeFactory */
82
+    private $timeFactory;
83
+
84
+    /** @var bool */
85
+    protected $retainJob = false;
86
+
87
+    private $format = '?format=json';
88
+
89
+    private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret';
90
+
91
+    /** @var  int  30 day = 2592000sec */
92
+    private $maxLifespan = 2592000;
93
+
94
+    /**
95
+     * RequestSharedSecret constructor.
96
+     *
97
+     * @param IClientService $httpClientService
98
+     * @param IURLGenerator $urlGenerator
99
+     * @param IJobList $jobList
100
+     * @param TrustedServers $trustedServers
101
+     * @param ILogger $logger
102
+     * @param DbHandler $dbHandler
103
+     * @param IDiscoveryService $ocsDiscoveryService
104
+     * @param ITimeFactory $timeFactory
105
+     */
106
+    public function __construct(
107
+        IClientService $httpClientService,
108
+        IURLGenerator $urlGenerator,
109
+        IJobList $jobList,
110
+        TrustedServers $trustedServers,
111
+        ILogger $logger,
112
+        DbHandler $dbHandler,
113
+        IDiscoveryService $ocsDiscoveryService,
114
+        ITimeFactory $timeFactory
115
+    ) {
116
+        $this->logger = $logger;
117
+        $this->httpClient = $httpClientService->newClient();
118
+        $this->jobList = $jobList;
119
+        $this->urlGenerator = $urlGenerator;
120
+        $this->dbHandler = $dbHandler;
121
+        $this->ocsDiscoveryService = $ocsDiscoveryService;
122
+        $this->trustedServers = $trustedServers;
123
+        $this->timeFactory = $timeFactory;
124
+    }
125
+
126
+    /**
127
+     * run the job, then remove it from the joblist
128
+     *
129
+     * @param JobList $jobList
130
+     * @param ILogger|null $logger
131
+     */
132
+    public function execute($jobList, ILogger $logger = null) {
133
+        $target = $this->argument['url'];
134
+        // only execute if target is still in the list of trusted domains
135
+        if ($this->trustedServers->isTrustedServer($target)) {
136
+            $this->parentExecute($jobList, $logger);
137
+        }
138
+
139
+        $jobList->remove($this, $this->argument);
140
+
141
+        if ($this->retainJob) {
142
+            $this->reAddJob($this->argument);
143
+        }
144
+    }
145
+
146
+    /**
147
+     * call execute() method of parent
148
+     *
149
+     * @param JobList $jobList
150
+     * @param ILogger $logger
151
+     */
152
+    protected function parentExecute($jobList, $logger = null) {
153
+        parent::execute($jobList, $logger);
154
+    }
155
+
156
+    protected function run($argument) {
157
+        $target = $argument['url'];
158
+        $created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
159
+        $currentTime = $this->timeFactory->getTime();
160
+        $source = $this->urlGenerator->getAbsoluteURL('/');
161
+        $source = rtrim($source, '/');
162
+        $token = $argument['token'];
163
+
164
+        // kill job after 30 days of trying
165
+        $deadline = $currentTime - $this->maxLifespan;
166
+        if ($created < $deadline) {
167
+            $this->retainJob = false;
168
+            $this->trustedServers->setServerStatus($target,TrustedServers::STATUS_FAILURE);
169
+            return;
170
+        }
171
+
172
+        $endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING');
173
+        $endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
174
+
175
+        // make sure that we have a well formatted url
176
+        $url = rtrim($target, '/') . '/' . trim($endPoint, '/') . $this->format;
177
+
178
+        $result = null;
179
+        try {
180
+            $result = $this->httpClient->get(
181
+                $url,
182
+                [
183
+                    'query' =>
184
+                        [
185
+                            'url' => $source,
186
+                            'token' => $token
187
+                        ],
188
+                    'timeout' => 3,
189
+                    'connect_timeout' => 3,
190
+                ]
191
+            );
192
+
193
+            $status = $result->getStatusCode();
194
+
195
+        } catch (ClientException $e) {
196
+            $status = $e->getCode();
197
+            if ($status === Http::STATUS_FORBIDDEN) {
198
+                $this->logger->info($target . ' refused to exchange a shared secret with you.', ['app' => 'federation']);
199
+            } else {
200
+                $this->logger->info($target . ' responded with a ' . $status . ' containing: ' . $e->getMessage(), ['app' => 'federation']);
201
+            }
202
+        } catch (RequestException $e) {
203
+            $status = -1; // There is no status code if we could not connect
204
+            $this->logger->logException($e, [
205
+                'message' => 'Could not connect to ' . $target,
206
+                'level' => \OCP\Util::INFO,
207
+                'app' => 'federation',
208
+            ]);
209
+        } catch (RingException $e) {
210
+            $status = -1; // There is no status code if we could not connect
211
+            $this->logger->logException($e, [
212
+                'message' => 'Could not connect to ' . $target,
213
+                'level' => \OCP\Util::INFO,
214
+                'app' => 'federation',
215
+            ]);
216
+        } catch (\Exception $e) {
217
+            $status = Http::STATUS_INTERNAL_SERVER_ERROR;
218
+            $this->logger->logException($e, ['app' => 'federation']);
219
+        }
220
+
221
+        // if we received a unexpected response we try again later
222
+        if (
223
+            $status !== Http::STATUS_OK
224
+            && $status !== Http::STATUS_FORBIDDEN
225
+        ) {
226
+            $this->retainJob = true;
227
+        }  else {
228
+            // reset token if we received a valid response
229
+            $this->dbHandler->addToken($target, '');
230
+        }
231
+
232
+        if ($status === Http::STATUS_OK && $result instanceof IResponse) {
233
+            $body = $result->getBody();
234
+            $result = json_decode($body, true);
235
+            if (isset($result['ocs']['data']['sharedSecret'])) {
236
+                $this->trustedServers->addSharedSecret(
237
+                        $target,
238
+                        $result['ocs']['data']['sharedSecret']
239
+                );
240
+            } else {
241
+                $this->logger->error(
242
+                        'remote server "' . $target . '"" does not return a valid shared secret',
243
+                        ['app' => 'federation']
244
+                );
245
+                $this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
246
+            }
247
+        }
248
+
249
+    }
250
+
251
+    /**
252
+     * re-add background job
253
+     *
254
+     * @param array $argument
255
+     */
256
+    protected function reAddJob(array $argument) {
257
+        $url = $argument['url'];
258
+        $created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
259
+        $token = $argument['token'];
260
+        $this->jobList->add(
261
+            GetSharedSecret::class,
262
+            [
263
+                'url' => $url,
264
+                'token' => $token,
265
+                'created' => $created
266
+            ]
267
+        );
268
+    }
269 269
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
 
156 156
 	protected function run($argument) {
157 157
 		$target = $argument['url'];
158
-		$created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
158
+		$created = isset($argument['created']) ? (int) $argument['created'] : $this->timeFactory->getTime();
159 159
 		$currentTime = $this->timeFactory->getTime();
160 160
 		$source = $this->urlGenerator->getAbsoluteURL('/');
161 161
 		$source = rtrim($source, '/');
@@ -165,7 +165,7 @@  discard block
 block discarded – undo
165 165
 		$deadline = $currentTime - $this->maxLifespan;
166 166
 		if ($created < $deadline) {
167 167
 			$this->retainJob = false;
168
-			$this->trustedServers->setServerStatus($target,TrustedServers::STATUS_FAILURE);
168
+			$this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
169 169
 			return;
170 170
 		}
171 171
 
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
 		$endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
174 174
 
175 175
 		// make sure that we have a well formatted url
176
-		$url = rtrim($target, '/') . '/' . trim($endPoint, '/') . $this->format;
176
+		$url = rtrim($target, '/').'/'.trim($endPoint, '/').$this->format;
177 177
 
178 178
 		$result = null;
179 179
 		try {
@@ -195,21 +195,21 @@  discard block
 block discarded – undo
195 195
 		} catch (ClientException $e) {
196 196
 			$status = $e->getCode();
197 197
 			if ($status === Http::STATUS_FORBIDDEN) {
198
-				$this->logger->info($target . ' refused to exchange a shared secret with you.', ['app' => 'federation']);
198
+				$this->logger->info($target.' refused to exchange a shared secret with you.', ['app' => 'federation']);
199 199
 			} else {
200
-				$this->logger->info($target . ' responded with a ' . $status . ' containing: ' . $e->getMessage(), ['app' => 'federation']);
200
+				$this->logger->info($target.' responded with a '.$status.' containing: '.$e->getMessage(), ['app' => 'federation']);
201 201
 			}
202 202
 		} catch (RequestException $e) {
203 203
 			$status = -1; // There is no status code if we could not connect
204 204
 			$this->logger->logException($e, [
205
-				'message' => 'Could not connect to ' . $target,
205
+				'message' => 'Could not connect to '.$target,
206 206
 				'level' => \OCP\Util::INFO,
207 207
 				'app' => 'federation',
208 208
 			]);
209 209
 		} catch (RingException $e) {
210 210
 			$status = -1; // There is no status code if we could not connect
211 211
 			$this->logger->logException($e, [
212
-				'message' => 'Could not connect to ' . $target,
212
+				'message' => 'Could not connect to '.$target,
213 213
 				'level' => \OCP\Util::INFO,
214 214
 				'app' => 'federation',
215 215
 			]);
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 			&& $status !== Http::STATUS_FORBIDDEN
225 225
 		) {
226 226
 			$this->retainJob = true;
227
-		}  else {
227
+		} else {
228 228
 			// reset token if we received a valid response
229 229
 			$this->dbHandler->addToken($target, '');
230 230
 		}
@@ -239,7 +239,7 @@  discard block
 block discarded – undo
239 239
 				);
240 240
 			} else {
241 241
 				$this->logger->error(
242
-						'remote server "' . $target . '"" does not return a valid shared secret',
242
+						'remote server "'.$target.'"" does not return a valid shared secret',
243 243
 						['app' => 'federation']
244 244
 				);
245 245
 				$this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
@@ -255,7 +255,7 @@  discard block
 block discarded – undo
255 255
 	 */
256 256
 	protected function reAddJob(array $argument) {
257 257
 		$url = $argument['url'];
258
-		$created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime();
258
+		$created = isset($argument['created']) ? (int) $argument['created'] : $this->timeFactory->getTime();
259 259
 		$token = $argument['token'];
260 260
 		$this->jobList->add(
261 261
 			GetSharedSecret::class,
Please login to merge, or discard this patch.
apps/federation/lib/TrustedServers.php 2 patches
Indentation   +248 added lines, -248 removed lines patch added patch discarded remove patch
@@ -40,252 +40,252 @@
 block discarded – undo
40 40
 
41 41
 class TrustedServers {
42 42
 
43
-	/** after a user list was exchanged at least once successfully */
44
-	const STATUS_OK = 1;
45
-	/** waiting for shared secret or initial user list exchange */
46
-	const STATUS_PENDING = 2;
47
-	/** something went wrong, misconfigured server, software bug,... user interaction needed */
48
-	const STATUS_FAILURE = 3;
49
-	/** remote server revoked access */
50
-	const STATUS_ACCESS_REVOKED = 4;
51
-
52
-	/** @var  dbHandler */
53
-	private $dbHandler;
54
-
55
-	/** @var  IClientService */
56
-	private $httpClientService;
57
-
58
-	/** @var ILogger */
59
-	private $logger;
60
-
61
-	/** @var IJobList */
62
-	private $jobList;
63
-
64
-	/** @var ISecureRandom */
65
-	private $secureRandom;
66
-
67
-	/** @var IConfig */
68
-	private $config;
69
-
70
-	/** @var EventDispatcherInterface */
71
-	private $dispatcher;
72
-
73
-	/** @var ITimeFactory */
74
-	private $timeFactory;
75
-
76
-	/**
77
-	 * @param DbHandler $dbHandler
78
-	 * @param IClientService $httpClientService
79
-	 * @param ILogger $logger
80
-	 * @param IJobList $jobList
81
-	 * @param ISecureRandom $secureRandom
82
-	 * @param IConfig $config
83
-	 * @param EventDispatcherInterface $dispatcher
84
-	 * @param ITimeFactory $timeFactory
85
-	 */
86
-	public function __construct(
87
-		DbHandler $dbHandler,
88
-		IClientService $httpClientService,
89
-		ILogger $logger,
90
-		IJobList $jobList,
91
-		ISecureRandom $secureRandom,
92
-		IConfig $config,
93
-		EventDispatcherInterface $dispatcher,
94
-		ITimeFactory $timeFactory
95
-	) {
96
-		$this->dbHandler = $dbHandler;
97
-		$this->httpClientService = $httpClientService;
98
-		$this->logger = $logger;
99
-		$this->jobList = $jobList;
100
-		$this->secureRandom = $secureRandom;
101
-		$this->config = $config;
102
-		$this->dispatcher = $dispatcher;
103
-		$this->timeFactory = $timeFactory;
104
-	}
105
-
106
-	/**
107
-	 * add server to the list of trusted servers
108
-	 *
109
-	 * @param $url
110
-	 * @return int server id
111
-	 */
112
-	public function addServer($url) {
113
-		$url = $this->updateProtocol($url);
114
-		$result = $this->dbHandler->addServer($url);
115
-		if ($result) {
116
-			$token = $this->secureRandom->generate(16);
117
-			$this->dbHandler->addToken($url, $token);
118
-			$this->jobList->add(
119
-				'OCA\Federation\BackgroundJob\RequestSharedSecret',
120
-				[
121
-					'url' => $url,
122
-					'token' => $token,
123
-					'created' => $this->timeFactory->getTime()
124
-				]
125
-			);
126
-		}
127
-
128
-		return $result;
129
-	}
130
-
131
-	/**
132
-	 * enable/disable to automatically add servers to the list of trusted servers
133
-	 * once a federated share was created and accepted successfully
134
-	 *
135
-	 * @param bool $status
136
-	 */
137
-	public function setAutoAddServers($status) {
138
-		$value = $status ? '1' : '0';
139
-		$this->config->setAppValue('federation', 'autoAddServers', $value);
140
-	}
141
-
142
-	/**
143
-	 * return if we automatically add servers to the list of trusted servers
144
-	 * once a federated share was created and accepted successfully
145
-	 *
146
-	 * @return bool
147
-	 */
148
-	public function getAutoAddServers() {
149
-		$value = $this->config->getAppValue('federation', 'autoAddServers', '0');
150
-		return $value === '1';
151
-	}
152
-
153
-	/**
154
-	 * get shared secret for the given server
155
-	 *
156
-	 * @param string $url
157
-	 * @return string
158
-	 */
159
-	public function getSharedSecret($url) {
160
-		return $this->dbHandler->getSharedSecret($url);
161
-	}
162
-
163
-	/**
164
-	 * add shared secret for the given server
165
-	 *
166
-	 * @param string $url
167
-	 * @param $sharedSecret
168
-	 */
169
-	public function addSharedSecret($url, $sharedSecret) {
170
-		$this->dbHandler->addSharedSecret($url, $sharedSecret);
171
-	}
172
-
173
-	/**
174
-	 * remove server from the list of trusted servers
175
-	 *
176
-	 * @param int $id
177
-	 */
178
-	public function removeServer($id) {
179
-		$server = $this->dbHandler->getServerById($id);
180
-		$this->dbHandler->removeServer($id);
181
-		$event = new GenericEvent($server['url_hash']);
182
-		$this->dispatcher->dispatch('OCP\Federation\TrustedServerEvent::remove', $event);
183
-	}
184
-
185
-	/**
186
-	 * get all trusted servers
187
-	 *
188
-	 * @return array
189
-	 */
190
-	public function getServers() {
191
-		return $this->dbHandler->getAllServer();
192
-	}
193
-
194
-	/**
195
-	 * check if given server is a trusted Nextcloud server
196
-	 *
197
-	 * @param string $url
198
-	 * @return bool
199
-	 */
200
-	public function isTrustedServer($url) {
201
-		return $this->dbHandler->serverExists($url);
202
-	}
203
-
204
-	/**
205
-	 * set server status
206
-	 *
207
-	 * @param string $url
208
-	 * @param int $status
209
-	 */
210
-	public function setServerStatus($url, $status) {
211
-		$this->dbHandler->setServerStatus($url, $status);
212
-	}
213
-
214
-	/**
215
-	 * @param string $url
216
-	 * @return int
217
-	 */
218
-	public function getServerStatus($url) {
219
-		return $this->dbHandler->getServerStatus($url);
220
-	}
221
-
222
-	/**
223
-	 * check if URL point to a ownCloud/Nextcloud server
224
-	 *
225
-	 * @param string $url
226
-	 * @return bool
227
-	 */
228
-	public function isOwnCloudServer($url) {
229
-		$isValidOwnCloud = false;
230
-		$client = $this->httpClientService->newClient();
231
-		try {
232
-			$result = $client->get(
233
-				$url . '/status.php',
234
-				[
235
-					'timeout' => 3,
236
-					'connect_timeout' => 3,
237
-				]
238
-			);
239
-			if ($result->getStatusCode() === Http::STATUS_OK) {
240
-				$isValidOwnCloud = $this->checkOwnCloudVersion($result->getBody());
241
-
242
-			}
243
-		} catch (\Exception $e) {
244
-			\OC::$server->getLogger()->logException($e, [
245
-				'message' => 'No Nextcloud server.',
246
-				'level' => \OCP\Util::DEBUG,
247
-				'app' => 'federation',
248
-			]);
249
-			return false;
250
-		}
251
-
252
-		return $isValidOwnCloud;
253
-	}
254
-
255
-	/**
256
-	 * check if ownCloud version is >= 9.0
257
-	 *
258
-	 * @param $status
259
-	 * @return bool
260
-	 * @throws HintException
261
-	 */
262
-	protected function checkOwnCloudVersion($status) {
263
-		$decoded = json_decode($status, true);
264
-		if (!empty($decoded) && isset($decoded['version'])) {
265
-			if (!version_compare($decoded['version'], '9.0.0', '>=')) {
266
-				throw new HintException('Remote server version is too low. 9.0 is required.');
267
-			}
268
-			return true;
269
-		}
270
-		return false;
271
-	}
272
-
273
-	/**
274
-	 * check if the URL contain a protocol, if not add https
275
-	 *
276
-	 * @param string $url
277
-	 * @return string
278
-	 */
279
-	protected function updateProtocol($url) {
280
-		if (
281
-			strpos($url, 'https://') === 0
282
-			|| strpos($url, 'http://') === 0
283
-		) {
284
-
285
-			return $url;
286
-
287
-		}
288
-
289
-		return 'https://' . $url;
290
-	}
43
+    /** after a user list was exchanged at least once successfully */
44
+    const STATUS_OK = 1;
45
+    /** waiting for shared secret or initial user list exchange */
46
+    const STATUS_PENDING = 2;
47
+    /** something went wrong, misconfigured server, software bug,... user interaction needed */
48
+    const STATUS_FAILURE = 3;
49
+    /** remote server revoked access */
50
+    const STATUS_ACCESS_REVOKED = 4;
51
+
52
+    /** @var  dbHandler */
53
+    private $dbHandler;
54
+
55
+    /** @var  IClientService */
56
+    private $httpClientService;
57
+
58
+    /** @var ILogger */
59
+    private $logger;
60
+
61
+    /** @var IJobList */
62
+    private $jobList;
63
+
64
+    /** @var ISecureRandom */
65
+    private $secureRandom;
66
+
67
+    /** @var IConfig */
68
+    private $config;
69
+
70
+    /** @var EventDispatcherInterface */
71
+    private $dispatcher;
72
+
73
+    /** @var ITimeFactory */
74
+    private $timeFactory;
75
+
76
+    /**
77
+     * @param DbHandler $dbHandler
78
+     * @param IClientService $httpClientService
79
+     * @param ILogger $logger
80
+     * @param IJobList $jobList
81
+     * @param ISecureRandom $secureRandom
82
+     * @param IConfig $config
83
+     * @param EventDispatcherInterface $dispatcher
84
+     * @param ITimeFactory $timeFactory
85
+     */
86
+    public function __construct(
87
+        DbHandler $dbHandler,
88
+        IClientService $httpClientService,
89
+        ILogger $logger,
90
+        IJobList $jobList,
91
+        ISecureRandom $secureRandom,
92
+        IConfig $config,
93
+        EventDispatcherInterface $dispatcher,
94
+        ITimeFactory $timeFactory
95
+    ) {
96
+        $this->dbHandler = $dbHandler;
97
+        $this->httpClientService = $httpClientService;
98
+        $this->logger = $logger;
99
+        $this->jobList = $jobList;
100
+        $this->secureRandom = $secureRandom;
101
+        $this->config = $config;
102
+        $this->dispatcher = $dispatcher;
103
+        $this->timeFactory = $timeFactory;
104
+    }
105
+
106
+    /**
107
+     * add server to the list of trusted servers
108
+     *
109
+     * @param $url
110
+     * @return int server id
111
+     */
112
+    public function addServer($url) {
113
+        $url = $this->updateProtocol($url);
114
+        $result = $this->dbHandler->addServer($url);
115
+        if ($result) {
116
+            $token = $this->secureRandom->generate(16);
117
+            $this->dbHandler->addToken($url, $token);
118
+            $this->jobList->add(
119
+                'OCA\Federation\BackgroundJob\RequestSharedSecret',
120
+                [
121
+                    'url' => $url,
122
+                    'token' => $token,
123
+                    'created' => $this->timeFactory->getTime()
124
+                ]
125
+            );
126
+        }
127
+
128
+        return $result;
129
+    }
130
+
131
+    /**
132
+     * enable/disable to automatically add servers to the list of trusted servers
133
+     * once a federated share was created and accepted successfully
134
+     *
135
+     * @param bool $status
136
+     */
137
+    public function setAutoAddServers($status) {
138
+        $value = $status ? '1' : '0';
139
+        $this->config->setAppValue('federation', 'autoAddServers', $value);
140
+    }
141
+
142
+    /**
143
+     * return if we automatically add servers to the list of trusted servers
144
+     * once a federated share was created and accepted successfully
145
+     *
146
+     * @return bool
147
+     */
148
+    public function getAutoAddServers() {
149
+        $value = $this->config->getAppValue('federation', 'autoAddServers', '0');
150
+        return $value === '1';
151
+    }
152
+
153
+    /**
154
+     * get shared secret for the given server
155
+     *
156
+     * @param string $url
157
+     * @return string
158
+     */
159
+    public function getSharedSecret($url) {
160
+        return $this->dbHandler->getSharedSecret($url);
161
+    }
162
+
163
+    /**
164
+     * add shared secret for the given server
165
+     *
166
+     * @param string $url
167
+     * @param $sharedSecret
168
+     */
169
+    public function addSharedSecret($url, $sharedSecret) {
170
+        $this->dbHandler->addSharedSecret($url, $sharedSecret);
171
+    }
172
+
173
+    /**
174
+     * remove server from the list of trusted servers
175
+     *
176
+     * @param int $id
177
+     */
178
+    public function removeServer($id) {
179
+        $server = $this->dbHandler->getServerById($id);
180
+        $this->dbHandler->removeServer($id);
181
+        $event = new GenericEvent($server['url_hash']);
182
+        $this->dispatcher->dispatch('OCP\Federation\TrustedServerEvent::remove', $event);
183
+    }
184
+
185
+    /**
186
+     * get all trusted servers
187
+     *
188
+     * @return array
189
+     */
190
+    public function getServers() {
191
+        return $this->dbHandler->getAllServer();
192
+    }
193
+
194
+    /**
195
+     * check if given server is a trusted Nextcloud server
196
+     *
197
+     * @param string $url
198
+     * @return bool
199
+     */
200
+    public function isTrustedServer($url) {
201
+        return $this->dbHandler->serverExists($url);
202
+    }
203
+
204
+    /**
205
+     * set server status
206
+     *
207
+     * @param string $url
208
+     * @param int $status
209
+     */
210
+    public function setServerStatus($url, $status) {
211
+        $this->dbHandler->setServerStatus($url, $status);
212
+    }
213
+
214
+    /**
215
+     * @param string $url
216
+     * @return int
217
+     */
218
+    public function getServerStatus($url) {
219
+        return $this->dbHandler->getServerStatus($url);
220
+    }
221
+
222
+    /**
223
+     * check if URL point to a ownCloud/Nextcloud server
224
+     *
225
+     * @param string $url
226
+     * @return bool
227
+     */
228
+    public function isOwnCloudServer($url) {
229
+        $isValidOwnCloud = false;
230
+        $client = $this->httpClientService->newClient();
231
+        try {
232
+            $result = $client->get(
233
+                $url . '/status.php',
234
+                [
235
+                    'timeout' => 3,
236
+                    'connect_timeout' => 3,
237
+                ]
238
+            );
239
+            if ($result->getStatusCode() === Http::STATUS_OK) {
240
+                $isValidOwnCloud = $this->checkOwnCloudVersion($result->getBody());
241
+
242
+            }
243
+        } catch (\Exception $e) {
244
+            \OC::$server->getLogger()->logException($e, [
245
+                'message' => 'No Nextcloud server.',
246
+                'level' => \OCP\Util::DEBUG,
247
+                'app' => 'federation',
248
+            ]);
249
+            return false;
250
+        }
251
+
252
+        return $isValidOwnCloud;
253
+    }
254
+
255
+    /**
256
+     * check if ownCloud version is >= 9.0
257
+     *
258
+     * @param $status
259
+     * @return bool
260
+     * @throws HintException
261
+     */
262
+    protected function checkOwnCloudVersion($status) {
263
+        $decoded = json_decode($status, true);
264
+        if (!empty($decoded) && isset($decoded['version'])) {
265
+            if (!version_compare($decoded['version'], '9.0.0', '>=')) {
266
+                throw new HintException('Remote server version is too low. 9.0 is required.');
267
+            }
268
+            return true;
269
+        }
270
+        return false;
271
+    }
272
+
273
+    /**
274
+     * check if the URL contain a protocol, if not add https
275
+     *
276
+     * @param string $url
277
+     * @return string
278
+     */
279
+    protected function updateProtocol($url) {
280
+        if (
281
+            strpos($url, 'https://') === 0
282
+            || strpos($url, 'http://') === 0
283
+        ) {
284
+
285
+            return $url;
286
+
287
+        }
288
+
289
+        return 'https://' . $url;
290
+    }
291 291
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -230,7 +230,7 @@  discard block
 block discarded – undo
230 230
 		$client = $this->httpClientService->newClient();
231 231
 		try {
232 232
 			$result = $client->get(
233
-				$url . '/status.php',
233
+				$url.'/status.php',
234 234
 				[
235 235
 					'timeout' => 3,
236 236
 					'connect_timeout' => 3,
@@ -286,6 +286,6 @@  discard block
 block discarded – undo
286 286
 
287 287
 		}
288 288
 
289
-		return 'https://' . $url;
289
+		return 'https://'.$url;
290 290
 	}
291 291
 }
Please login to merge, or discard this patch.