Completed
Pull Request — master (#8058)
by Morris
77:14 queued 61:45
created
lib/private/Files/Cache/FailedCache.php 1 patch
Indentation   +108 added lines, -108 removed lines patch added patch discarded remove patch
@@ -30,112 +30,112 @@
 block discarded – undo
30 30
  * Storage placeholder to represent a missing precondition, storage unavailable
31 31
  */
32 32
 class FailedCache implements ICache {
33
-	/** @var bool whether to show the failed storage in the ui */
34
-	private $visible;
35
-
36
-	/**
37
-	 * FailedCache constructor.
38
-	 *
39
-	 * @param bool $visible
40
-	 */
41
-	public function __construct($visible = true) {
42
-		$this->visible = $visible;
43
-	}
44
-
45
-
46
-	public function getNumericStorageId() {
47
-		return -1;
48
-	}
49
-
50
-	public function get($file) {
51
-		if ($file === '') {
52
-			return new CacheEntry([
53
-				'fileid' => -1,
54
-				'size' => 0,
55
-				'mimetype' => 'httpd/unix-directory',
56
-				'mimepart' => 'httpd',
57
-				'permissions' => $this->visible ? Constants::PERMISSION_READ : 0,
58
-				'mtime' => time()
59
-			]);
60
-		} else {
61
-			return false;
62
-		}
63
-	}
64
-
65
-	public function getFolderContents($folder) {
66
-		return [];
67
-	}
68
-
69
-	public function getFolderContentsById($fileId) {
70
-		return [];
71
-	}
72
-
73
-	public function put($file, array $data) {
74
-	}
75
-
76
-	public function insert($file, array $data) {
77
-	}
78
-
79
-	public function update($id, array $data) {
80
-	}
81
-
82
-	public function getId($file) {
83
-		return -1;
84
-	}
85
-
86
-	public function getParentId($file) {
87
-		return -1;
88
-	}
89
-
90
-	public function inCache($file) {
91
-		return false;
92
-	}
93
-
94
-	public function remove($file) {
95
-	}
96
-
97
-	public function move($source, $target) {
98
-	}
99
-
100
-	public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
101
-	}
102
-
103
-	public function clear() {
104
-	}
105
-
106
-	public function getStatus($file) {
107
-		return ICache::NOT_FOUND;
108
-	}
109
-
110
-	public function search($pattern) {
111
-		return [];
112
-	}
113
-
114
-	public function searchByMime($mimetype) {
115
-		return [];
116
-	}
117
-
118
-	public function searchByTag($tag, $userId) {
119
-		return [];
120
-	}
121
-
122
-	public function searchQuery(ISearchQuery $query) {
123
-		return [];
124
-	}
125
-
126
-	public function getAll() {
127
-		return [];
128
-	}
129
-
130
-	public function getIncomplete() {
131
-		return [];
132
-	}
133
-
134
-	public function getPathById($id) {
135
-		return null;
136
-	}
137
-
138
-	public function normalize($path) {
139
-		return $path;
140
-	}
33
+    /** @var bool whether to show the failed storage in the ui */
34
+    private $visible;
35
+
36
+    /**
37
+     * FailedCache constructor.
38
+     *
39
+     * @param bool $visible
40
+     */
41
+    public function __construct($visible = true) {
42
+        $this->visible = $visible;
43
+    }
44
+
45
+
46
+    public function getNumericStorageId() {
47
+        return -1;
48
+    }
49
+
50
+    public function get($file) {
51
+        if ($file === '') {
52
+            return new CacheEntry([
53
+                'fileid' => -1,
54
+                'size' => 0,
55
+                'mimetype' => 'httpd/unix-directory',
56
+                'mimepart' => 'httpd',
57
+                'permissions' => $this->visible ? Constants::PERMISSION_READ : 0,
58
+                'mtime' => time()
59
+            ]);
60
+        } else {
61
+            return false;
62
+        }
63
+    }
64
+
65
+    public function getFolderContents($folder) {
66
+        return [];
67
+    }
68
+
69
+    public function getFolderContentsById($fileId) {
70
+        return [];
71
+    }
72
+
73
+    public function put($file, array $data) {
74
+    }
75
+
76
+    public function insert($file, array $data) {
77
+    }
78
+
79
+    public function update($id, array $data) {
80
+    }
81
+
82
+    public function getId($file) {
83
+        return -1;
84
+    }
85
+
86
+    public function getParentId($file) {
87
+        return -1;
88
+    }
89
+
90
+    public function inCache($file) {
91
+        return false;
92
+    }
93
+
94
+    public function remove($file) {
95
+    }
96
+
97
+    public function move($source, $target) {
98
+    }
99
+
100
+    public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
101
+    }
102
+
103
+    public function clear() {
104
+    }
105
+
106
+    public function getStatus($file) {
107
+        return ICache::NOT_FOUND;
108
+    }
109
+
110
+    public function search($pattern) {
111
+        return [];
112
+    }
113
+
114
+    public function searchByMime($mimetype) {
115
+        return [];
116
+    }
117
+
118
+    public function searchByTag($tag, $userId) {
119
+        return [];
120
+    }
121
+
122
+    public function searchQuery(ISearchQuery $query) {
123
+        return [];
124
+    }
125
+
126
+    public function getAll() {
127
+        return [];
128
+    }
129
+
130
+    public function getIncomplete() {
131
+        return [];
132
+    }
133
+
134
+    public function getPathById($id) {
135
+        return null;
136
+    }
137
+
138
+    public function normalize($path) {
139
+        return $path;
140
+    }
141 141
 }
Please login to merge, or discard this patch.
lib/private/Files/Node/Node.php 1 patch
Indentation   +387 added lines, -387 removed lines patch added patch discarded remove patch
@@ -35,392 +35,392 @@
 block discarded – undo
35 35
 
36 36
 // FIXME: this class really should be abstract
37 37
 class Node implements \OCP\Files\Node {
38
-	/**
39
-	 * @var \OC\Files\View $view
40
-	 */
41
-	protected $view;
42
-
43
-	/**
44
-	 * @var \OC\Files\Node\Root $root
45
-	 */
46
-	protected $root;
47
-
48
-	/**
49
-	 * @var string $path
50
-	 */
51
-	protected $path;
52
-
53
-	/**
54
-	 * @var \OCP\Files\FileInfo
55
-	 */
56
-	protected $fileInfo;
57
-
58
-	/**
59
-	 * @param \OC\Files\View $view
60
-	 * @param \OCP\Files\IRootFolder $root
61
-	 * @param string $path
62
-	 * @param FileInfo $fileInfo
63
-	 */
64
-	public function __construct($root, $view, $path, $fileInfo = null) {
65
-		$this->view = $view;
66
-		$this->root = $root;
67
-		$this->path = $path;
68
-		$this->fileInfo = $fileInfo;
69
-	}
70
-
71
-	/**
72
-	 * Creates a Node of the same type that represents a non-existing path
73
-	 *
74
-	 * @param string $path path
75
-	 * @return string non-existing node class
76
-	 */
77
-	protected function createNonExistingNode($path) {
78
-		throw new \Exception('Must be implemented by subclasses');
79
-	}
80
-
81
-	/**
82
-	 * Returns the matching file info
83
-	 *
84
-	 * @return FileInfo
85
-	 * @throws InvalidPathException
86
-	 * @throws NotFoundException
87
-	 */
88
-	public function getFileInfo() {
89
-		if (!Filesystem::isValidPath($this->path)) {
90
-			throw new InvalidPathException();
91
-		}
92
-		if (!$this->fileInfo) {
93
-			$fileInfo = $this->view->getFileInfo($this->path);
94
-			if ($fileInfo instanceof FileInfo) {
95
-				$this->fileInfo = $fileInfo;
96
-			} else {
97
-				throw new NotFoundException();
98
-			}
99
-		}
100
-		return $this->fileInfo;
101
-	}
102
-
103
-	/**
104
-	 * @param string[] $hooks
105
-	 */
106
-	protected function sendHooks($hooks) {
107
-		foreach ($hooks as $hook) {
108
-			$this->root->emit('\OC\Files', $hook, array($this));
109
-		}
110
-	}
111
-
112
-	/**
113
-	 * @param int $permissions
114
-	 * @return bool
115
-	 */
116
-	protected function checkPermissions($permissions) {
117
-		return ($this->getPermissions() & $permissions) === $permissions;
118
-	}
119
-
120
-	public function delete() {
121
-	}
122
-
123
-	/**
124
-	 * @param int $mtime
125
-	 * @throws \OCP\Files\NotPermittedException
126
-	 */
127
-	public function touch($mtime = null) {
128
-		if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) {
129
-			$this->sendHooks(array('preTouch'));
130
-			$this->view->touch($this->path, $mtime);
131
-			$this->sendHooks(array('postTouch'));
132
-			if ($this->fileInfo) {
133
-				if (is_null($mtime)) {
134
-					$mtime = time();
135
-				}
136
-				$this->fileInfo['mtime'] = $mtime;
137
-			}
138
-		} else {
139
-			throw new NotPermittedException();
140
-		}
141
-	}
142
-
143
-	/**
144
-	 * @return \OC\Files\Storage\Storage
145
-	 * @throws \OCP\Files\NotFoundException
146
-	 */
147
-	public function getStorage() {
148
-		list($storage,) = $this->view->resolvePath($this->path);
149
-		return $storage;
150
-	}
151
-
152
-	/**
153
-	 * @return string
154
-	 */
155
-	public function getPath() {
156
-		return $this->path;
157
-	}
158
-
159
-	/**
160
-	 * @return string
161
-	 */
162
-	public function getInternalPath() {
163
-		list(, $internalPath) = $this->view->resolvePath($this->path);
164
-		return $internalPath;
165
-	}
166
-
167
-	/**
168
-	 * @return int
169
-	 * @throws InvalidPathException
170
-	 * @throws NotFoundException
171
-	 */
172
-	public function getId() {
173
-		return $this->getFileInfo()->getId();
174
-	}
175
-
176
-	/**
177
-	 * @return array
178
-	 */
179
-	public function stat() {
180
-		return $this->view->stat($this->path);
181
-	}
182
-
183
-	/**
184
-	 * @return int
185
-	 * @throws InvalidPathException
186
-	 * @throws NotFoundException
187
-	 */
188
-	public function getMTime() {
189
-		return $this->getFileInfo()->getMTime();
190
-	}
191
-
192
-	/**
193
-	 * @return int
194
-	 * @throws InvalidPathException
195
-	 * @throws NotFoundException
196
-	 */
197
-	public function getSize() {
198
-		return $this->getFileInfo()->getSize();
199
-	}
200
-
201
-	/**
202
-	 * @return string
203
-	 * @throws InvalidPathException
204
-	 * @throws NotFoundException
205
-	 */
206
-	public function getEtag() {
207
-		return $this->getFileInfo()->getEtag();
208
-	}
209
-
210
-	/**
211
-	 * @return int
212
-	 * @throws InvalidPathException
213
-	 * @throws NotFoundException
214
-	 */
215
-	public function getPermissions() {
216
-		return $this->getFileInfo()->getPermissions();
217
-	}
218
-
219
-	/**
220
-	 * @return bool
221
-	 * @throws InvalidPathException
222
-	 * @throws NotFoundException
223
-	 */
224
-	public function isReadable() {
225
-		return $this->getFileInfo()->isReadable();
226
-	}
227
-
228
-	/**
229
-	 * @return bool
230
-	 * @throws InvalidPathException
231
-	 * @throws NotFoundException
232
-	 */
233
-	public function isUpdateable() {
234
-		return $this->getFileInfo()->isUpdateable();
235
-	}
236
-
237
-	/**
238
-	 * @return bool
239
-	 * @throws InvalidPathException
240
-	 * @throws NotFoundException
241
-	 */
242
-	public function isDeletable() {
243
-		return $this->getFileInfo()->isDeletable();
244
-	}
245
-
246
-	/**
247
-	 * @return bool
248
-	 * @throws InvalidPathException
249
-	 * @throws NotFoundException
250
-	 */
251
-	public function isShareable() {
252
-		return $this->getFileInfo()->isShareable();
253
-	}
254
-
255
-	/**
256
-	 * @return bool
257
-	 * @throws InvalidPathException
258
-	 * @throws NotFoundException
259
-	 */
260
-	public function isCreatable() {
261
-		return $this->getFileInfo()->isCreatable();
262
-	}
263
-
264
-	/**
265
-	 * @return Node
266
-	 */
267
-	public function getParent() {
268
-		return $this->root->get(dirname($this->path));
269
-	}
270
-
271
-	/**
272
-	 * @return string
273
-	 */
274
-	public function getName() {
275
-		return basename($this->path);
276
-	}
277
-
278
-	/**
279
-	 * @param string $path
280
-	 * @return string
281
-	 */
282
-	protected function normalizePath($path) {
283
-		if ($path === '' or $path === '/') {
284
-			return '/';
285
-		}
286
-		//no windows style slashes
287
-		$path = str_replace('\\', '/', $path);
288
-		//add leading slash
289
-		if ($path[0] !== '/') {
290
-			$path = '/' . $path;
291
-		}
292
-		//remove duplicate slashes
293
-		while (strpos($path, '//') !== false) {
294
-			$path = str_replace('//', '/', $path);
295
-		}
296
-		//remove trailing slash
297
-		$path = rtrim($path, '/');
298
-
299
-		return $path;
300
-	}
301
-
302
-	/**
303
-	 * check if the requested path is valid
304
-	 *
305
-	 * @param string $path
306
-	 * @return bool
307
-	 */
308
-	public function isValidPath($path) {
309
-		if (!$path || $path[0] !== '/') {
310
-			$path = '/' . $path;
311
-		}
312
-		if (strstr($path, '/../') || strrchr($path, '/') === '/..') {
313
-			return false;
314
-		}
315
-		return true;
316
-	}
317
-
318
-	public function isMounted() {
319
-		return $this->getFileInfo()->isMounted();
320
-	}
321
-
322
-	public function isShared() {
323
-		return $this->getFileInfo()->isShared();
324
-	}
325
-
326
-	public function getMimeType() {
327
-		return $this->getFileInfo()->getMimetype();
328
-	}
329
-
330
-	public function getMimePart() {
331
-		return $this->getFileInfo()->getMimePart();
332
-	}
333
-
334
-	public function getType() {
335
-		return $this->getFileInfo()->getType();
336
-	}
337
-
338
-	public function isEncrypted() {
339
-		return $this->getFileInfo()->isEncrypted();
340
-	}
341
-
342
-	public function getMountPoint() {
343
-		return $this->getFileInfo()->getMountPoint();
344
-	}
345
-
346
-	public function getOwner() {
347
-		return $this->getFileInfo()->getOwner();
348
-	}
349
-
350
-	public function getChecksum() {
351
-	}
352
-
353
-	/**
354
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
355
-	 * @throws \OCP\Lock\LockedException
356
-	 */
357
-	public function lock($type) {
358
-		$this->view->lockFile($this->path, $type);
359
-	}
360
-
361
-	/**
362
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
363
-	 * @throws \OCP\Lock\LockedException
364
-	 */
365
-	public function changeLock($type) {
366
-		$this->view->changeLock($this->path, $type);
367
-	}
368
-
369
-	/**
370
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
371
-	 * @throws \OCP\Lock\LockedException
372
-	 */
373
-	public function unlock($type) {
374
-		$this->view->unlockFile($this->path, $type);
375
-	}
376
-
377
-	/**
378
-	 * @param string $targetPath
379
-	 * @throws \OCP\Files\NotPermittedException if copy not allowed or failed
380
-	 * @return \OC\Files\Node\Node
381
-	 */
382
-	public function copy($targetPath) {
383
-		$targetPath = $this->normalizePath($targetPath);
384
-		$parent = $this->root->get(dirname($targetPath));
385
-		if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
386
-			$nonExisting = $this->createNonExistingNode($targetPath);
387
-			$this->root->emit('\OC\Files', 'preCopy', [$this, $nonExisting]);
388
-			$this->root->emit('\OC\Files', 'preWrite', [$nonExisting]);
389
-			if (!$this->view->copy($this->path, $targetPath)) {
390
-				throw new NotPermittedException('Could not copy ' . $this->path . ' to ' . $targetPath);
391
-			}
392
-			$targetNode = $this->root->get($targetPath);
393
-			$this->root->emit('\OC\Files', 'postCopy', [$this, $targetNode]);
394
-			$this->root->emit('\OC\Files', 'postWrite', [$targetNode]);
395
-			return $targetNode;
396
-		} else {
397
-			throw new NotPermittedException('No permission to copy to path ' . $targetPath);
398
-		}
399
-	}
400
-
401
-	/**
402
-	 * @param string $targetPath
403
-	 * @throws \OCP\Files\NotPermittedException if move not allowed or failed
404
-	 * @return \OC\Files\Node\Node
405
-	 */
406
-	public function move($targetPath) {
407
-		$targetPath = $this->normalizePath($targetPath);
408
-		$parent = $this->root->get(dirname($targetPath));
409
-		if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
410
-			$nonExisting = $this->createNonExistingNode($targetPath);
411
-			$this->root->emit('\OC\Files', 'preRename', [$this, $nonExisting]);
412
-			$this->root->emit('\OC\Files', 'preWrite', [$nonExisting]);
413
-			if (!$this->view->rename($this->path, $targetPath)) {
414
-				throw new NotPermittedException('Could not move ' . $this->path . ' to ' . $targetPath);
415
-			}
416
-			$targetNode = $this->root->get($targetPath);
417
-			$this->root->emit('\OC\Files', 'postRename', [$this, $targetNode]);
418
-			$this->root->emit('\OC\Files', 'postWrite', [$targetNode]);
419
-			$this->path = $targetPath;
420
-			return $targetNode;
421
-		} else {
422
-			throw new NotPermittedException('No permission to move to path ' . $targetPath);
423
-		}
424
-	}
38
+    /**
39
+     * @var \OC\Files\View $view
40
+     */
41
+    protected $view;
42
+
43
+    /**
44
+     * @var \OC\Files\Node\Root $root
45
+     */
46
+    protected $root;
47
+
48
+    /**
49
+     * @var string $path
50
+     */
51
+    protected $path;
52
+
53
+    /**
54
+     * @var \OCP\Files\FileInfo
55
+     */
56
+    protected $fileInfo;
57
+
58
+    /**
59
+     * @param \OC\Files\View $view
60
+     * @param \OCP\Files\IRootFolder $root
61
+     * @param string $path
62
+     * @param FileInfo $fileInfo
63
+     */
64
+    public function __construct($root, $view, $path, $fileInfo = null) {
65
+        $this->view = $view;
66
+        $this->root = $root;
67
+        $this->path = $path;
68
+        $this->fileInfo = $fileInfo;
69
+    }
70
+
71
+    /**
72
+     * Creates a Node of the same type that represents a non-existing path
73
+     *
74
+     * @param string $path path
75
+     * @return string non-existing node class
76
+     */
77
+    protected function createNonExistingNode($path) {
78
+        throw new \Exception('Must be implemented by subclasses');
79
+    }
80
+
81
+    /**
82
+     * Returns the matching file info
83
+     *
84
+     * @return FileInfo
85
+     * @throws InvalidPathException
86
+     * @throws NotFoundException
87
+     */
88
+    public function getFileInfo() {
89
+        if (!Filesystem::isValidPath($this->path)) {
90
+            throw new InvalidPathException();
91
+        }
92
+        if (!$this->fileInfo) {
93
+            $fileInfo = $this->view->getFileInfo($this->path);
94
+            if ($fileInfo instanceof FileInfo) {
95
+                $this->fileInfo = $fileInfo;
96
+            } else {
97
+                throw new NotFoundException();
98
+            }
99
+        }
100
+        return $this->fileInfo;
101
+    }
102
+
103
+    /**
104
+     * @param string[] $hooks
105
+     */
106
+    protected function sendHooks($hooks) {
107
+        foreach ($hooks as $hook) {
108
+            $this->root->emit('\OC\Files', $hook, array($this));
109
+        }
110
+    }
111
+
112
+    /**
113
+     * @param int $permissions
114
+     * @return bool
115
+     */
116
+    protected function checkPermissions($permissions) {
117
+        return ($this->getPermissions() & $permissions) === $permissions;
118
+    }
119
+
120
+    public function delete() {
121
+    }
122
+
123
+    /**
124
+     * @param int $mtime
125
+     * @throws \OCP\Files\NotPermittedException
126
+     */
127
+    public function touch($mtime = null) {
128
+        if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) {
129
+            $this->sendHooks(array('preTouch'));
130
+            $this->view->touch($this->path, $mtime);
131
+            $this->sendHooks(array('postTouch'));
132
+            if ($this->fileInfo) {
133
+                if (is_null($mtime)) {
134
+                    $mtime = time();
135
+                }
136
+                $this->fileInfo['mtime'] = $mtime;
137
+            }
138
+        } else {
139
+            throw new NotPermittedException();
140
+        }
141
+    }
142
+
143
+    /**
144
+     * @return \OC\Files\Storage\Storage
145
+     * @throws \OCP\Files\NotFoundException
146
+     */
147
+    public function getStorage() {
148
+        list($storage,) = $this->view->resolvePath($this->path);
149
+        return $storage;
150
+    }
151
+
152
+    /**
153
+     * @return string
154
+     */
155
+    public function getPath() {
156
+        return $this->path;
157
+    }
158
+
159
+    /**
160
+     * @return string
161
+     */
162
+    public function getInternalPath() {
163
+        list(, $internalPath) = $this->view->resolvePath($this->path);
164
+        return $internalPath;
165
+    }
166
+
167
+    /**
168
+     * @return int
169
+     * @throws InvalidPathException
170
+     * @throws NotFoundException
171
+     */
172
+    public function getId() {
173
+        return $this->getFileInfo()->getId();
174
+    }
175
+
176
+    /**
177
+     * @return array
178
+     */
179
+    public function stat() {
180
+        return $this->view->stat($this->path);
181
+    }
182
+
183
+    /**
184
+     * @return int
185
+     * @throws InvalidPathException
186
+     * @throws NotFoundException
187
+     */
188
+    public function getMTime() {
189
+        return $this->getFileInfo()->getMTime();
190
+    }
191
+
192
+    /**
193
+     * @return int
194
+     * @throws InvalidPathException
195
+     * @throws NotFoundException
196
+     */
197
+    public function getSize() {
198
+        return $this->getFileInfo()->getSize();
199
+    }
200
+
201
+    /**
202
+     * @return string
203
+     * @throws InvalidPathException
204
+     * @throws NotFoundException
205
+     */
206
+    public function getEtag() {
207
+        return $this->getFileInfo()->getEtag();
208
+    }
209
+
210
+    /**
211
+     * @return int
212
+     * @throws InvalidPathException
213
+     * @throws NotFoundException
214
+     */
215
+    public function getPermissions() {
216
+        return $this->getFileInfo()->getPermissions();
217
+    }
218
+
219
+    /**
220
+     * @return bool
221
+     * @throws InvalidPathException
222
+     * @throws NotFoundException
223
+     */
224
+    public function isReadable() {
225
+        return $this->getFileInfo()->isReadable();
226
+    }
227
+
228
+    /**
229
+     * @return bool
230
+     * @throws InvalidPathException
231
+     * @throws NotFoundException
232
+     */
233
+    public function isUpdateable() {
234
+        return $this->getFileInfo()->isUpdateable();
235
+    }
236
+
237
+    /**
238
+     * @return bool
239
+     * @throws InvalidPathException
240
+     * @throws NotFoundException
241
+     */
242
+    public function isDeletable() {
243
+        return $this->getFileInfo()->isDeletable();
244
+    }
245
+
246
+    /**
247
+     * @return bool
248
+     * @throws InvalidPathException
249
+     * @throws NotFoundException
250
+     */
251
+    public function isShareable() {
252
+        return $this->getFileInfo()->isShareable();
253
+    }
254
+
255
+    /**
256
+     * @return bool
257
+     * @throws InvalidPathException
258
+     * @throws NotFoundException
259
+     */
260
+    public function isCreatable() {
261
+        return $this->getFileInfo()->isCreatable();
262
+    }
263
+
264
+    /**
265
+     * @return Node
266
+     */
267
+    public function getParent() {
268
+        return $this->root->get(dirname($this->path));
269
+    }
270
+
271
+    /**
272
+     * @return string
273
+     */
274
+    public function getName() {
275
+        return basename($this->path);
276
+    }
277
+
278
+    /**
279
+     * @param string $path
280
+     * @return string
281
+     */
282
+    protected function normalizePath($path) {
283
+        if ($path === '' or $path === '/') {
284
+            return '/';
285
+        }
286
+        //no windows style slashes
287
+        $path = str_replace('\\', '/', $path);
288
+        //add leading slash
289
+        if ($path[0] !== '/') {
290
+            $path = '/' . $path;
291
+        }
292
+        //remove duplicate slashes
293
+        while (strpos($path, '//') !== false) {
294
+            $path = str_replace('//', '/', $path);
295
+        }
296
+        //remove trailing slash
297
+        $path = rtrim($path, '/');
298
+
299
+        return $path;
300
+    }
301
+
302
+    /**
303
+     * check if the requested path is valid
304
+     *
305
+     * @param string $path
306
+     * @return bool
307
+     */
308
+    public function isValidPath($path) {
309
+        if (!$path || $path[0] !== '/') {
310
+            $path = '/' . $path;
311
+        }
312
+        if (strstr($path, '/../') || strrchr($path, '/') === '/..') {
313
+            return false;
314
+        }
315
+        return true;
316
+    }
317
+
318
+    public function isMounted() {
319
+        return $this->getFileInfo()->isMounted();
320
+    }
321
+
322
+    public function isShared() {
323
+        return $this->getFileInfo()->isShared();
324
+    }
325
+
326
+    public function getMimeType() {
327
+        return $this->getFileInfo()->getMimetype();
328
+    }
329
+
330
+    public function getMimePart() {
331
+        return $this->getFileInfo()->getMimePart();
332
+    }
333
+
334
+    public function getType() {
335
+        return $this->getFileInfo()->getType();
336
+    }
337
+
338
+    public function isEncrypted() {
339
+        return $this->getFileInfo()->isEncrypted();
340
+    }
341
+
342
+    public function getMountPoint() {
343
+        return $this->getFileInfo()->getMountPoint();
344
+    }
345
+
346
+    public function getOwner() {
347
+        return $this->getFileInfo()->getOwner();
348
+    }
349
+
350
+    public function getChecksum() {
351
+    }
352
+
353
+    /**
354
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
355
+     * @throws \OCP\Lock\LockedException
356
+     */
357
+    public function lock($type) {
358
+        $this->view->lockFile($this->path, $type);
359
+    }
360
+
361
+    /**
362
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
363
+     * @throws \OCP\Lock\LockedException
364
+     */
365
+    public function changeLock($type) {
366
+        $this->view->changeLock($this->path, $type);
367
+    }
368
+
369
+    /**
370
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
371
+     * @throws \OCP\Lock\LockedException
372
+     */
373
+    public function unlock($type) {
374
+        $this->view->unlockFile($this->path, $type);
375
+    }
376
+
377
+    /**
378
+     * @param string $targetPath
379
+     * @throws \OCP\Files\NotPermittedException if copy not allowed or failed
380
+     * @return \OC\Files\Node\Node
381
+     */
382
+    public function copy($targetPath) {
383
+        $targetPath = $this->normalizePath($targetPath);
384
+        $parent = $this->root->get(dirname($targetPath));
385
+        if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
386
+            $nonExisting = $this->createNonExistingNode($targetPath);
387
+            $this->root->emit('\OC\Files', 'preCopy', [$this, $nonExisting]);
388
+            $this->root->emit('\OC\Files', 'preWrite', [$nonExisting]);
389
+            if (!$this->view->copy($this->path, $targetPath)) {
390
+                throw new NotPermittedException('Could not copy ' . $this->path . ' to ' . $targetPath);
391
+            }
392
+            $targetNode = $this->root->get($targetPath);
393
+            $this->root->emit('\OC\Files', 'postCopy', [$this, $targetNode]);
394
+            $this->root->emit('\OC\Files', 'postWrite', [$targetNode]);
395
+            return $targetNode;
396
+        } else {
397
+            throw new NotPermittedException('No permission to copy to path ' . $targetPath);
398
+        }
399
+    }
400
+
401
+    /**
402
+     * @param string $targetPath
403
+     * @throws \OCP\Files\NotPermittedException if move not allowed or failed
404
+     * @return \OC\Files\Node\Node
405
+     */
406
+    public function move($targetPath) {
407
+        $targetPath = $this->normalizePath($targetPath);
408
+        $parent = $this->root->get(dirname($targetPath));
409
+        if ($parent instanceof Folder and $this->isValidPath($targetPath) and $parent->isCreatable()) {
410
+            $nonExisting = $this->createNonExistingNode($targetPath);
411
+            $this->root->emit('\OC\Files', 'preRename', [$this, $nonExisting]);
412
+            $this->root->emit('\OC\Files', 'preWrite', [$nonExisting]);
413
+            if (!$this->view->rename($this->path, $targetPath)) {
414
+                throw new NotPermittedException('Could not move ' . $this->path . ' to ' . $targetPath);
415
+            }
416
+            $targetNode = $this->root->get($targetPath);
417
+            $this->root->emit('\OC\Files', 'postRename', [$this, $targetNode]);
418
+            $this->root->emit('\OC\Files', 'postWrite', [$targetNode]);
419
+            $this->path = $targetPath;
420
+            return $targetNode;
421
+        } else {
422
+            throw new NotPermittedException('No permission to move to path ' . $targetPath);
423
+        }
424
+    }
425 425
 
426 426
 }
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/Plugin.php 2 patches
Indentation   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -27,15 +27,15 @@
 block discarded – undo
27 27
 
28 28
 class Plugin extends \Sabre\CalDAV\Plugin {
29 29
 
30
-	/**
31
-	 * @inheritdoc
32
-	 */
33
-	function getCalendarHomeForPrincipal($principalUrl) {
30
+    /**
31
+     * @inheritdoc
32
+     */
33
+    function getCalendarHomeForPrincipal($principalUrl) {
34 34
 
35
-		if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) {
36
-			list(, $principalId) = \Sabre\Uri\split($principalUrl);
37
-			return self::CALENDAR_ROOT .'/' . $principalId;
38
-		}
39
-	}
35
+        if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) {
36
+            list(, $principalId) = \Sabre\Uri\split($principalUrl);
37
+            return self::CALENDAR_ROOT .'/' . $principalId;
38
+        }
39
+    }
40 40
 
41 41
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -34,7 +34,7 @@
 block discarded – undo
34 34
 
35 35
 		if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) {
36 36
 			list(, $principalId) = \Sabre\Uri\split($principalUrl);
37
-			return self::CALENDAR_ROOT .'/' . $principalId;
37
+			return self::CALENDAR_ROOT.'/'.$principalId;
38 38
 		}
39 39
 	}
40 40
 
Please login to merge, or discard this patch.
apps/sharebymail/lib/ShareByMailProvider.php 1 patch
Indentation   +1018 added lines, -1018 removed lines patch added patch discarded remove patch
@@ -53,1036 +53,1036 @@
 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
-	}
694
-
695
-	/**
696
-	 * @inheritdoc
697
-	 */
698
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
699
-		$qb = $this->dbConnection->getQueryBuilder();
700
-		$qb->select('*')
701
-			->from('share');
702
-
703
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
704
-
705
-		/**
706
-		 * Reshares for this user are shares where they are the owner.
707
-		 */
708
-		if ($reshares === false) {
709
-			//Special case for old shares created via the web UI
710
-			$or1 = $qb->expr()->andX(
711
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
712
-				$qb->expr()->isNull('uid_initiator')
713
-			);
714
-
715
-			$qb->andWhere(
716
-				$qb->expr()->orX(
717
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
718
-					$or1
719
-				)
720
-			);
721
-		} else {
722
-			$qb->andWhere(
723
-				$qb->expr()->orX(
724
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
725
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
726
-				)
727
-			);
728
-		}
729
-
730
-		if ($node !== null) {
731
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
732
-		}
733
-
734
-		if ($limit !== -1) {
735
-			$qb->setMaxResults($limit);
736
-		}
737
-
738
-		$qb->setFirstResult($offset);
739
-		$qb->orderBy('id');
740
-
741
-		$cursor = $qb->execute();
742
-		$shares = [];
743
-		while($data = $cursor->fetch()) {
744
-			$shares[] = $this->createShareObject($data);
745
-		}
746
-		$cursor->closeCursor();
747
-
748
-		return $shares;
749
-	}
750
-
751
-	/**
752
-	 * @inheritdoc
753
-	 */
754
-	public function getShareById($id, $recipientId = null) {
755
-		$qb = $this->dbConnection->getQueryBuilder();
756
-
757
-		$qb->select('*')
758
-			->from('share')
759
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
760
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
761
-
762
-		$cursor = $qb->execute();
763
-		$data = $cursor->fetch();
764
-		$cursor->closeCursor();
765
-
766
-		if ($data === false) {
767
-			throw new ShareNotFound();
768
-		}
769
-
770
-		try {
771
-			$share = $this->createShareObject($data);
772
-		} catch (InvalidShare $e) {
773
-			throw new ShareNotFound();
774
-		}
775
-
776
-		return $share;
777
-	}
778
-
779
-	/**
780
-	 * Get shares for a given path
781
-	 *
782
-	 * @param \OCP\Files\Node $path
783
-	 * @return IShare[]
784
-	 */
785
-	public function getSharesByPath(Node $path) {
786
-		$qb = $this->dbConnection->getQueryBuilder();
787
-
788
-		$cursor = $qb->select('*')
789
-			->from('share')
790
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
791
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
792
-			->execute();
793
-
794
-		$shares = [];
795
-		while($data = $cursor->fetch()) {
796
-			$shares[] = $this->createShareObject($data);
797
-		}
798
-		$cursor->closeCursor();
799
-
800
-		return $shares;
801
-	}
802
-
803
-	/**
804
-	 * @inheritdoc
805
-	 */
806
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
807
-		/** @var IShare[] $shares */
808
-		$shares = [];
809
-
810
-		//Get shares directly with this user
811
-		$qb = $this->dbConnection->getQueryBuilder();
812
-		$qb->select('*')
813
-			->from('share');
814
-
815
-		// Order by id
816
-		$qb->orderBy('id');
817
-
818
-		// Set limit and offset
819
-		if ($limit !== -1) {
820
-			$qb->setMaxResults($limit);
821
-		}
822
-		$qb->setFirstResult($offset);
823
-
824
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
825
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
826
-
827
-		// Filter by node if provided
828
-		if ($node !== null) {
829
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
830
-		}
831
-
832
-		$cursor = $qb->execute();
833
-
834
-		while($data = $cursor->fetch()) {
835
-			$shares[] = $this->createShareObject($data);
836
-		}
837
-		$cursor->closeCursor();
838
-
839
-
840
-		return $shares;
841
-	}
842
-
843
-	/**
844
-	 * Get a share by token
845
-	 *
846
-	 * @param string $token
847
-	 * @return IShare
848
-	 * @throws ShareNotFound
849
-	 */
850
-	public function getShareByToken($token) {
851
-		$qb = $this->dbConnection->getQueryBuilder();
852
-
853
-		$cursor = $qb->select('*')
854
-			->from('share')
855
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
856
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
857
-			->execute();
858
-
859
-		$data = $cursor->fetch();
860
-
861
-		if ($data === false) {
862
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
863
-		}
864
-
865
-		try {
866
-			$share = $this->createShareObject($data);
867
-		} catch (InvalidShare $e) {
868
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
869
-		}
870
-
871
-		return $share;
872
-	}
873
-
874
-	/**
875
-	 * remove share from table
876
-	 *
877
-	 * @param string $shareId
878
-	 */
879
-	protected function removeShareFromTable($shareId) {
880
-		$qb = $this->dbConnection->getQueryBuilder();
881
-		$qb->delete('share')
882
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
883
-		$qb->execute();
884
-	}
885
-
886
-	/**
887
-	 * Create a share object from an database row
888
-	 *
889
-	 * @param array $data
890
-	 * @return IShare
891
-	 * @throws InvalidShare
892
-	 * @throws ShareNotFound
893
-	 */
894
-	protected function createShareObject($data) {
895
-
896
-		$share = new Share($this->rootFolder, $this->userManager);
897
-		$share->setId((int)$data['id'])
898
-			->setShareType((int)$data['share_type'])
899
-			->setPermissions((int)$data['permissions'])
900
-			->setTarget($data['file_target'])
901
-			->setMailSend((bool)$data['mail_send'])
902
-			->setToken($data['token']);
903
-
904
-		$shareTime = new \DateTime();
905
-		$shareTime->setTimestamp((int)$data['stime']);
906
-		$share->setShareTime($shareTime);
907
-		$share->setSharedWith($data['share_with']);
908
-		$share->setPassword($data['password']);
909
-
910
-		if ($data['uid_initiator'] !== null) {
911
-			$share->setShareOwner($data['uid_owner']);
912
-			$share->setSharedBy($data['uid_initiator']);
913
-		} else {
914
-			//OLD SHARE
915
-			$share->setSharedBy($data['uid_owner']);
916
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
917
-
918
-			$owner = $path->getOwner();
919
-			$share->setShareOwner($owner->getUID());
920
-		}
921
-
922
-		if ($data['expiration'] !== null) {
923
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
924
-			if ($expiration !== false) {
925
-				$share->setExpirationDate($expiration);
926
-			}
927
-		}
928
-
929
-		$share->setNodeId((int)$data['file_source']);
930
-		$share->setNodeType($data['item_type']);
931
-
932
-		$share->setProviderId($this->identifier());
933
-
934
-		return $share;
935
-	}
936
-
937
-	/**
938
-	 * Get the node with file $id for $user
939
-	 *
940
-	 * @param string $userId
941
-	 * @param int $id
942
-	 * @return \OCP\Files\File|\OCP\Files\Folder
943
-	 * @throws InvalidShare
944
-	 */
945
-	private function getNode($userId, $id) {
946
-		try {
947
-			$userFolder = $this->rootFolder->getUserFolder($userId);
948
-		} catch (NoUserException $e) {
949
-			throw new InvalidShare();
950
-		}
951
-
952
-		$nodes = $userFolder->getById($id);
953
-
954
-		if (empty($nodes)) {
955
-			throw new InvalidShare();
956
-		}
957
-
958
-		return $nodes[0];
959
-	}
960
-
961
-	/**
962
-	 * A user is deleted from the system
963
-	 * So clean up the relevant shares.
964
-	 *
965
-	 * @param string $uid
966
-	 * @param int $shareType
967
-	 */
968
-	public function userDeleted($uid, $shareType) {
969
-		$qb = $this->dbConnection->getQueryBuilder();
970
-
971
-		$qb->delete('share')
972
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
973
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
974
-			->execute();
975
-	}
976
-
977
-	/**
978
-	 * This provider does not support group shares
979
-	 *
980
-	 * @param string $gid
981
-	 */
982
-	public function groupDeleted($gid) {
983
-	}
984
-
985
-	/**
986
-	 * This provider does not support group shares
987
-	 *
988
-	 * @param string $uid
989
-	 * @param string $gid
990
-	 */
991
-	public function userDeletedFromGroup($uid, $gid) {
992
-	}
993
-
994
-	/**
995
-	 * get database row of a give share
996
-	 *
997
-	 * @param $id
998
-	 * @return array
999
-	 * @throws ShareNotFound
1000
-	 */
1001
-	protected function getRawShare($id) {
1002
-
1003
-		// Now fetch the inserted share and create a complete share object
1004
-		$qb = $this->dbConnection->getQueryBuilder();
1005
-		$qb->select('*')
1006
-			->from('share')
1007
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1008
-
1009
-		$cursor = $qb->execute();
1010
-		$data = $cursor->fetch();
1011
-		$cursor->closeCursor();
1012
-
1013
-		if ($data === false) {
1014
-			throw new ShareNotFound;
1015
-		}
1016
-
1017
-		return $data;
1018
-	}
1019
-
1020
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
1021
-		$qb = $this->dbConnection->getQueryBuilder();
1022
-		$qb->select('*')
1023
-			->from('share', 's')
1024
-			->andWhere($qb->expr()->orX(
1025
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1026
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1027
-			))
1028
-			->andWhere(
1029
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
1030
-			);
1031
-
1032
-		/**
1033
-		 * Reshares for this user are shares where they are the owner.
1034
-		 */
1035
-		if ($reshares === false) {
1036
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1037
-		} else {
1038
-			$qb->andWhere(
1039
-				$qb->expr()->orX(
1040
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1041
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1042
-				)
1043
-			);
1044
-		}
1045
-
1046
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1047
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1048
-
1049
-		$qb->orderBy('id');
1050
-
1051
-		$cursor = $qb->execute();
1052
-		$shares = [];
1053
-		while ($data = $cursor->fetch()) {
1054
-			$shares[$data['fileid']][] = $this->createShareObject($data);
1055
-		}
1056
-		$cursor->closeCursor();
1057
-
1058
-		return $shares;
1059
-	}
1060
-
1061
-	/**
1062
-	 * @inheritdoc
1063
-	 */
1064
-	public function getAccessList($nodes, $currentAccess) {
1065
-		$ids = [];
1066
-		foreach ($nodes as $node) {
1067
-			$ids[] = $node->getId();
1068
-		}
1069
-
1070
-		$qb = $this->dbConnection->getQueryBuilder();
1071
-		$qb->select('share_with')
1072
-			->from('share')
1073
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1074
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1075
-			->andWhere($qb->expr()->orX(
1076
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1077
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1078
-			))
1079
-			->setMaxResults(1);
1080
-		$cursor = $qb->execute();
1081
-
1082
-		$mail = $cursor->fetch() !== false;
1083
-		$cursor->closeCursor();
1084
-
1085
-		return ['public' => $mail];
1086
-	}
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
+    }
694
+
695
+    /**
696
+     * @inheritdoc
697
+     */
698
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
699
+        $qb = $this->dbConnection->getQueryBuilder();
700
+        $qb->select('*')
701
+            ->from('share');
702
+
703
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
704
+
705
+        /**
706
+         * Reshares for this user are shares where they are the owner.
707
+         */
708
+        if ($reshares === false) {
709
+            //Special case for old shares created via the web UI
710
+            $or1 = $qb->expr()->andX(
711
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
712
+                $qb->expr()->isNull('uid_initiator')
713
+            );
714
+
715
+            $qb->andWhere(
716
+                $qb->expr()->orX(
717
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
718
+                    $or1
719
+                )
720
+            );
721
+        } else {
722
+            $qb->andWhere(
723
+                $qb->expr()->orX(
724
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
725
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
726
+                )
727
+            );
728
+        }
729
+
730
+        if ($node !== null) {
731
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
732
+        }
733
+
734
+        if ($limit !== -1) {
735
+            $qb->setMaxResults($limit);
736
+        }
737
+
738
+        $qb->setFirstResult($offset);
739
+        $qb->orderBy('id');
740
+
741
+        $cursor = $qb->execute();
742
+        $shares = [];
743
+        while($data = $cursor->fetch()) {
744
+            $shares[] = $this->createShareObject($data);
745
+        }
746
+        $cursor->closeCursor();
747
+
748
+        return $shares;
749
+    }
750
+
751
+    /**
752
+     * @inheritdoc
753
+     */
754
+    public function getShareById($id, $recipientId = null) {
755
+        $qb = $this->dbConnection->getQueryBuilder();
756
+
757
+        $qb->select('*')
758
+            ->from('share')
759
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
760
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
761
+
762
+        $cursor = $qb->execute();
763
+        $data = $cursor->fetch();
764
+        $cursor->closeCursor();
765
+
766
+        if ($data === false) {
767
+            throw new ShareNotFound();
768
+        }
769
+
770
+        try {
771
+            $share = $this->createShareObject($data);
772
+        } catch (InvalidShare $e) {
773
+            throw new ShareNotFound();
774
+        }
775
+
776
+        return $share;
777
+    }
778
+
779
+    /**
780
+     * Get shares for a given path
781
+     *
782
+     * @param \OCP\Files\Node $path
783
+     * @return IShare[]
784
+     */
785
+    public function getSharesByPath(Node $path) {
786
+        $qb = $this->dbConnection->getQueryBuilder();
787
+
788
+        $cursor = $qb->select('*')
789
+            ->from('share')
790
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
791
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
792
+            ->execute();
793
+
794
+        $shares = [];
795
+        while($data = $cursor->fetch()) {
796
+            $shares[] = $this->createShareObject($data);
797
+        }
798
+        $cursor->closeCursor();
799
+
800
+        return $shares;
801
+    }
802
+
803
+    /**
804
+     * @inheritdoc
805
+     */
806
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
807
+        /** @var IShare[] $shares */
808
+        $shares = [];
809
+
810
+        //Get shares directly with this user
811
+        $qb = $this->dbConnection->getQueryBuilder();
812
+        $qb->select('*')
813
+            ->from('share');
814
+
815
+        // Order by id
816
+        $qb->orderBy('id');
817
+
818
+        // Set limit and offset
819
+        if ($limit !== -1) {
820
+            $qb->setMaxResults($limit);
821
+        }
822
+        $qb->setFirstResult($offset);
823
+
824
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)));
825
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
826
+
827
+        // Filter by node if provided
828
+        if ($node !== null) {
829
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
830
+        }
831
+
832
+        $cursor = $qb->execute();
833
+
834
+        while($data = $cursor->fetch()) {
835
+            $shares[] = $this->createShareObject($data);
836
+        }
837
+        $cursor->closeCursor();
838
+
839
+
840
+        return $shares;
841
+    }
842
+
843
+    /**
844
+     * Get a share by token
845
+     *
846
+     * @param string $token
847
+     * @return IShare
848
+     * @throws ShareNotFound
849
+     */
850
+    public function getShareByToken($token) {
851
+        $qb = $this->dbConnection->getQueryBuilder();
852
+
853
+        $cursor = $qb->select('*')
854
+            ->from('share')
855
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
856
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
857
+            ->execute();
858
+
859
+        $data = $cursor->fetch();
860
+
861
+        if ($data === false) {
862
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
863
+        }
864
+
865
+        try {
866
+            $share = $this->createShareObject($data);
867
+        } catch (InvalidShare $e) {
868
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
869
+        }
870
+
871
+        return $share;
872
+    }
873
+
874
+    /**
875
+     * remove share from table
876
+     *
877
+     * @param string $shareId
878
+     */
879
+    protected function removeShareFromTable($shareId) {
880
+        $qb = $this->dbConnection->getQueryBuilder();
881
+        $qb->delete('share')
882
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
883
+        $qb->execute();
884
+    }
885
+
886
+    /**
887
+     * Create a share object from an database row
888
+     *
889
+     * @param array $data
890
+     * @return IShare
891
+     * @throws InvalidShare
892
+     * @throws ShareNotFound
893
+     */
894
+    protected function createShareObject($data) {
895
+
896
+        $share = new Share($this->rootFolder, $this->userManager);
897
+        $share->setId((int)$data['id'])
898
+            ->setShareType((int)$data['share_type'])
899
+            ->setPermissions((int)$data['permissions'])
900
+            ->setTarget($data['file_target'])
901
+            ->setMailSend((bool)$data['mail_send'])
902
+            ->setToken($data['token']);
903
+
904
+        $shareTime = new \DateTime();
905
+        $shareTime->setTimestamp((int)$data['stime']);
906
+        $share->setShareTime($shareTime);
907
+        $share->setSharedWith($data['share_with']);
908
+        $share->setPassword($data['password']);
909
+
910
+        if ($data['uid_initiator'] !== null) {
911
+            $share->setShareOwner($data['uid_owner']);
912
+            $share->setSharedBy($data['uid_initiator']);
913
+        } else {
914
+            //OLD SHARE
915
+            $share->setSharedBy($data['uid_owner']);
916
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
917
+
918
+            $owner = $path->getOwner();
919
+            $share->setShareOwner($owner->getUID());
920
+        }
921
+
922
+        if ($data['expiration'] !== null) {
923
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
924
+            if ($expiration !== false) {
925
+                $share->setExpirationDate($expiration);
926
+            }
927
+        }
928
+
929
+        $share->setNodeId((int)$data['file_source']);
930
+        $share->setNodeType($data['item_type']);
931
+
932
+        $share->setProviderId($this->identifier());
933
+
934
+        return $share;
935
+    }
936
+
937
+    /**
938
+     * Get the node with file $id for $user
939
+     *
940
+     * @param string $userId
941
+     * @param int $id
942
+     * @return \OCP\Files\File|\OCP\Files\Folder
943
+     * @throws InvalidShare
944
+     */
945
+    private function getNode($userId, $id) {
946
+        try {
947
+            $userFolder = $this->rootFolder->getUserFolder($userId);
948
+        } catch (NoUserException $e) {
949
+            throw new InvalidShare();
950
+        }
951
+
952
+        $nodes = $userFolder->getById($id);
953
+
954
+        if (empty($nodes)) {
955
+            throw new InvalidShare();
956
+        }
957
+
958
+        return $nodes[0];
959
+    }
960
+
961
+    /**
962
+     * A user is deleted from the system
963
+     * So clean up the relevant shares.
964
+     *
965
+     * @param string $uid
966
+     * @param int $shareType
967
+     */
968
+    public function userDeleted($uid, $shareType) {
969
+        $qb = $this->dbConnection->getQueryBuilder();
970
+
971
+        $qb->delete('share')
972
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
973
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
974
+            ->execute();
975
+    }
976
+
977
+    /**
978
+     * This provider does not support group shares
979
+     *
980
+     * @param string $gid
981
+     */
982
+    public function groupDeleted($gid) {
983
+    }
984
+
985
+    /**
986
+     * This provider does not support group shares
987
+     *
988
+     * @param string $uid
989
+     * @param string $gid
990
+     */
991
+    public function userDeletedFromGroup($uid, $gid) {
992
+    }
993
+
994
+    /**
995
+     * get database row of a give share
996
+     *
997
+     * @param $id
998
+     * @return array
999
+     * @throws ShareNotFound
1000
+     */
1001
+    protected function getRawShare($id) {
1002
+
1003
+        // Now fetch the inserted share and create a complete share object
1004
+        $qb = $this->dbConnection->getQueryBuilder();
1005
+        $qb->select('*')
1006
+            ->from('share')
1007
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1008
+
1009
+        $cursor = $qb->execute();
1010
+        $data = $cursor->fetch();
1011
+        $cursor->closeCursor();
1012
+
1013
+        if ($data === false) {
1014
+            throw new ShareNotFound;
1015
+        }
1016
+
1017
+        return $data;
1018
+    }
1019
+
1020
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
1021
+        $qb = $this->dbConnection->getQueryBuilder();
1022
+        $qb->select('*')
1023
+            ->from('share', 's')
1024
+            ->andWhere($qb->expr()->orX(
1025
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1026
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1027
+            ))
1028
+            ->andWhere(
1029
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL))
1030
+            );
1031
+
1032
+        /**
1033
+         * Reshares for this user are shares where they are the owner.
1034
+         */
1035
+        if ($reshares === false) {
1036
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1037
+        } else {
1038
+            $qb->andWhere(
1039
+                $qb->expr()->orX(
1040
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1041
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1042
+                )
1043
+            );
1044
+        }
1045
+
1046
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1047
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1048
+
1049
+        $qb->orderBy('id');
1050
+
1051
+        $cursor = $qb->execute();
1052
+        $shares = [];
1053
+        while ($data = $cursor->fetch()) {
1054
+            $shares[$data['fileid']][] = $this->createShareObject($data);
1055
+        }
1056
+        $cursor->closeCursor();
1057
+
1058
+        return $shares;
1059
+    }
1060
+
1061
+    /**
1062
+     * @inheritdoc
1063
+     */
1064
+    public function getAccessList($nodes, $currentAccess) {
1065
+        $ids = [];
1066
+        foreach ($nodes as $node) {
1067
+            $ids[] = $node->getId();
1068
+        }
1069
+
1070
+        $qb = $this->dbConnection->getQueryBuilder();
1071
+        $qb->select('share_with')
1072
+            ->from('share')
1073
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_EMAIL)))
1074
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1075
+            ->andWhere($qb->expr()->orX(
1076
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1077
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1078
+            ))
1079
+            ->setMaxResults(1);
1080
+        $cursor = $qb->execute();
1081
+
1082
+        $mail = $cursor->fetch() !== false;
1083
+        $cursor->closeCursor();
1084
+
1085
+        return ['public' => $mail];
1086
+    }
1087 1087
 
1088 1088
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/FederatedShareProvider.php 1 patch
Indentation   +975 added lines, -975 removed lines patch added patch discarded remove patch
@@ -53,989 +53,989 @@
 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
-	}
596
-
597
-
598
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
599
-		$qb = $this->dbConnection->getQueryBuilder();
600
-		$qb->select('*')
601
-			->from('share', 's')
602
-			->andWhere($qb->expr()->orX(
603
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
604
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
605
-			))
606
-			->andWhere(
607
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
608
-			);
609
-
610
-		/**
611
-		 * Reshares for this user are shares where they are the owner.
612
-		 */
613
-		if ($reshares === false) {
614
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
615
-		} else {
616
-			$qb->andWhere(
617
-				$qb->expr()->orX(
618
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
619
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
620
-				)
621
-			);
622
-		}
623
-
624
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
625
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
626
-
627
-		$qb->orderBy('id');
628
-
629
-		$cursor = $qb->execute();
630
-		$shares = [];
631
-		while ($data = $cursor->fetch()) {
632
-			$shares[$data['fileid']][] = $this->createShareObject($data);
633
-		}
634
-		$cursor->closeCursor();
635
-
636
-		return $shares;
637
-	}
638
-
639
-	/**
640
-	 * @inheritdoc
641
-	 */
642
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
643
-		$qb = $this->dbConnection->getQueryBuilder();
644
-		$qb->select('*')
645
-			->from('share');
646
-
647
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
648
-
649
-		/**
650
-		 * Reshares for this user are shares where they are the owner.
651
-		 */
652
-		if ($reshares === false) {
653
-			//Special case for old shares created via the web UI
654
-			$or1 = $qb->expr()->andX(
655
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
656
-				$qb->expr()->isNull('uid_initiator')
657
-			);
658
-
659
-			$qb->andWhere(
660
-				$qb->expr()->orX(
661
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
662
-					$or1
663
-				)
664
-			);
665
-		} else {
666
-			$qb->andWhere(
667
-				$qb->expr()->orX(
668
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
669
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
670
-				)
671
-			);
672
-		}
673
-
674
-		if ($node !== null) {
675
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
676
-		}
677
-
678
-		if ($limit !== -1) {
679
-			$qb->setMaxResults($limit);
680
-		}
681
-
682
-		$qb->setFirstResult($offset);
683
-		$qb->orderBy('id');
684
-
685
-		$cursor = $qb->execute();
686
-		$shares = [];
687
-		while($data = $cursor->fetch()) {
688
-			$shares[] = $this->createShareObject($data);
689
-		}
690
-		$cursor->closeCursor();
691
-
692
-		return $shares;
693
-	}
694
-
695
-	/**
696
-	 * @inheritdoc
697
-	 */
698
-	public function getShareById($id, $recipientId = null) {
699
-		$qb = $this->dbConnection->getQueryBuilder();
700
-
701
-		$qb->select('*')
702
-			->from('share')
703
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
704
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
705
-
706
-		$cursor = $qb->execute();
707
-		$data = $cursor->fetch();
708
-		$cursor->closeCursor();
709
-
710
-		if ($data === false) {
711
-			throw new ShareNotFound();
712
-		}
713
-
714
-		try {
715
-			$share = $this->createShareObject($data);
716
-		} catch (InvalidShare $e) {
717
-			throw new ShareNotFound();
718
-		}
719
-
720
-		return $share;
721
-	}
722
-
723
-	/**
724
-	 * Get shares for a given path
725
-	 *
726
-	 * @param \OCP\Files\Node $path
727
-	 * @return IShare[]
728
-	 */
729
-	public function getSharesByPath(Node $path) {
730
-		$qb = $this->dbConnection->getQueryBuilder();
731
-
732
-		$cursor = $qb->select('*')
733
-			->from('share')
734
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
735
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
736
-			->execute();
737
-
738
-		$shares = [];
739
-		while($data = $cursor->fetch()) {
740
-			$shares[] = $this->createShareObject($data);
741
-		}
742
-		$cursor->closeCursor();
743
-
744
-		return $shares;
745
-	}
746
-
747
-	/**
748
-	 * @inheritdoc
749
-	 */
750
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
751
-		/** @var IShare[] $shares */
752
-		$shares = [];
753
-
754
-		//Get shares directly with this user
755
-		$qb = $this->dbConnection->getQueryBuilder();
756
-		$qb->select('*')
757
-			->from('share');
758
-
759
-		// Order by id
760
-		$qb->orderBy('id');
761
-
762
-		// Set limit and offset
763
-		if ($limit !== -1) {
764
-			$qb->setMaxResults($limit);
765
-		}
766
-		$qb->setFirstResult($offset);
767
-
768
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
769
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
770
-
771
-		// Filter by node if provided
772
-		if ($node !== null) {
773
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
774
-		}
775
-
776
-		$cursor = $qb->execute();
777
-
778
-		while($data = $cursor->fetch()) {
779
-			$shares[] = $this->createShareObject($data);
780
-		}
781
-		$cursor->closeCursor();
782
-
783
-
784
-		return $shares;
785
-	}
786
-
787
-	/**
788
-	 * Get a share by token
789
-	 *
790
-	 * @param string $token
791
-	 * @return IShare
792
-	 * @throws ShareNotFound
793
-	 */
794
-	public function getShareByToken($token) {
795
-		$qb = $this->dbConnection->getQueryBuilder();
796
-
797
-		$cursor = $qb->select('*')
798
-			->from('share')
799
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
800
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
801
-			->execute();
802
-
803
-		$data = $cursor->fetch();
804
-
805
-		if ($data === false) {
806
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
807
-		}
808
-
809
-		try {
810
-			$share = $this->createShareObject($data);
811
-		} catch (InvalidShare $e) {
812
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
813
-		}
814
-
815
-		return $share;
816
-	}
817
-
818
-	/**
819
-	 * get database row of a give share
820
-	 *
821
-	 * @param $id
822
-	 * @return array
823
-	 * @throws ShareNotFound
824
-	 */
825
-	private function getRawShare($id) {
826
-
827
-		// Now fetch the inserted share and create a complete share object
828
-		$qb = $this->dbConnection->getQueryBuilder();
829
-		$qb->select('*')
830
-			->from('share')
831
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
832
-
833
-		$cursor = $qb->execute();
834
-		$data = $cursor->fetch();
835
-		$cursor->closeCursor();
836
-
837
-		if ($data === false) {
838
-			throw new ShareNotFound;
839
-		}
840
-
841
-		return $data;
842
-	}
843
-
844
-	/**
845
-	 * Create a share object from an database row
846
-	 *
847
-	 * @param array $data
848
-	 * @return IShare
849
-	 * @throws InvalidShare
850
-	 * @throws ShareNotFound
851
-	 */
852
-	private function createShareObject($data) {
853
-
854
-		$share = new Share($this->rootFolder, $this->userManager);
855
-		$share->setId((int)$data['id'])
856
-			->setShareType((int)$data['share_type'])
857
-			->setPermissions((int)$data['permissions'])
858
-			->setTarget($data['file_target'])
859
-			->setMailSend((bool)$data['mail_send'])
860
-			->setToken($data['token']);
861
-
862
-		$shareTime = new \DateTime();
863
-		$shareTime->setTimestamp((int)$data['stime']);
864
-		$share->setShareTime($shareTime);
865
-		$share->setSharedWith($data['share_with']);
866
-
867
-		if ($data['uid_initiator'] !== null) {
868
-			$share->setShareOwner($data['uid_owner']);
869
-			$share->setSharedBy($data['uid_initiator']);
870
-		} else {
871
-			//OLD SHARE
872
-			$share->setSharedBy($data['uid_owner']);
873
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
874
-
875
-			$owner = $path->getOwner();
876
-			$share->setShareOwner($owner->getUID());
877
-		}
878
-
879
-		$share->setNodeId((int)$data['file_source']);
880
-		$share->setNodeType($data['item_type']);
881
-
882
-		$share->setProviderId($this->identifier());
883
-
884
-		return $share;
885
-	}
886
-
887
-	/**
888
-	 * Get the node with file $id for $user
889
-	 *
890
-	 * @param string $userId
891
-	 * @param int $id
892
-	 * @return \OCP\Files\File|\OCP\Files\Folder
893
-	 * @throws InvalidShare
894
-	 */
895
-	private function getNode($userId, $id) {
896
-		try {
897
-			$userFolder = $this->rootFolder->getUserFolder($userId);
898
-		} catch (NotFoundException $e) {
899
-			throw new InvalidShare();
900
-		}
901
-
902
-		$nodes = $userFolder->getById($id);
903
-
904
-		if (empty($nodes)) {
905
-			throw new InvalidShare();
906
-		}
907
-
908
-		return $nodes[0];
909
-	}
910
-
911
-	/**
912
-	 * A user is deleted from the system
913
-	 * So clean up the relevant shares.
914
-	 *
915
-	 * @param string $uid
916
-	 * @param int $shareType
917
-	 */
918
-	public function userDeleted($uid, $shareType) {
919
-		//TODO: probabaly a good idea to send unshare info to remote servers
920
-
921
-		$qb = $this->dbConnection->getQueryBuilder();
922
-
923
-		$qb->delete('share')
924
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
925
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
926
-			->execute();
927
-	}
928
-
929
-	/**
930
-	 * This provider does not handle groups
931
-	 *
932
-	 * @param string $gid
933
-	 */
934
-	public function groupDeleted($gid) {
935
-		// We don't handle groups here
936
-	}
937
-
938
-	/**
939
-	 * This provider does not handle groups
940
-	 *
941
-	 * @param string $uid
942
-	 * @param string $gid
943
-	 */
944
-	public function userDeletedFromGroup($uid, $gid) {
945
-		// We don't handle groups here
946
-	}
947
-
948
-	/**
949
-	 * check if users from other Nextcloud instances are allowed to mount public links share by this instance
950
-	 *
951
-	 * @return bool
952
-	 */
953
-	public function isOutgoingServer2serverShareEnabled() {
954
-		if ($this->gsConfig->onlyInternalFederation()) {
955
-			return false;
956
-		}
957
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
958
-		return ($result === 'yes');
959
-	}
960
-
961
-	/**
962
-	 * check if users are allowed to mount public links from other Nextclouds
963
-	 *
964
-	 * @return bool
965
-	 */
966
-	public function isIncomingServer2serverShareEnabled() {
967
-		if ($this->gsConfig->onlyInternalFederation()) {
968
-			return false;
969
-		}
970
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
971
-		return ($result === 'yes');
972
-	}
973
-
974
-	/**
975
-	 * Check if querying sharees on the lookup server is enabled
976
-	 *
977
-	 * @return bool
978
-	 */
979
-	public function isLookupServerQueriesEnabled() {
980
-		// in a global scale setup we should always query the lookup server
981
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
982
-			return true;
983
-		}
984
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
985
-		return ($result === 'yes');
986
-	}
987
-
988
-
989
-	/**
990
-	 * Check if it is allowed to publish user specific data to the lookup server
991
-	 *
992
-	 * @return bool
993
-	 */
994
-	public function isLookupServerUploadEnabled() {
995
-		// in a global scale setup the admin is responsible to keep the lookup server up-to-date
996
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
997
-			return false;
998
-		}
999
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1000
-		return ($result === 'yes');
1001
-	}
1002
-
1003
-	/**
1004
-	 * @inheritdoc
1005
-	 */
1006
-	public function getAccessList($nodes, $currentAccess) {
1007
-		$ids = [];
1008
-		foreach ($nodes as $node) {
1009
-			$ids[] = $node->getId();
1010
-		}
1011
-
1012
-		$qb = $this->dbConnection->getQueryBuilder();
1013
-		$qb->select('share_with', 'token', 'file_source')
1014
-			->from('share')
1015
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1016
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1017
-			->andWhere($qb->expr()->orX(
1018
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1019
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1020
-			));
1021
-		$cursor = $qb->execute();
1022
-
1023
-		if ($currentAccess === false) {
1024
-			$remote = $cursor->fetch() !== false;
1025
-			$cursor->closeCursor();
1026
-
1027
-			return ['remote' => $remote];
1028
-		}
1029
-
1030
-		$remote = [];
1031
-		while ($row = $cursor->fetch()) {
1032
-			$remote[$row['share_with']] = [
1033
-				'node_id' => $row['file_source'],
1034
-				'token' => $row['token'],
1035
-			];
1036
-		}
1037
-		$cursor->closeCursor();
1038
-
1039
-		return ['remote' => $remote];
1040
-	}
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
+    }
596
+
597
+
598
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
599
+        $qb = $this->dbConnection->getQueryBuilder();
600
+        $qb->select('*')
601
+            ->from('share', 's')
602
+            ->andWhere($qb->expr()->orX(
603
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
604
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
605
+            ))
606
+            ->andWhere(
607
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE))
608
+            );
609
+
610
+        /**
611
+         * Reshares for this user are shares where they are the owner.
612
+         */
613
+        if ($reshares === false) {
614
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
615
+        } else {
616
+            $qb->andWhere(
617
+                $qb->expr()->orX(
618
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
619
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
620
+                )
621
+            );
622
+        }
623
+
624
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
625
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
626
+
627
+        $qb->orderBy('id');
628
+
629
+        $cursor = $qb->execute();
630
+        $shares = [];
631
+        while ($data = $cursor->fetch()) {
632
+            $shares[$data['fileid']][] = $this->createShareObject($data);
633
+        }
634
+        $cursor->closeCursor();
635
+
636
+        return $shares;
637
+    }
638
+
639
+    /**
640
+     * @inheritdoc
641
+     */
642
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
643
+        $qb = $this->dbConnection->getQueryBuilder();
644
+        $qb->select('*')
645
+            ->from('share');
646
+
647
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
648
+
649
+        /**
650
+         * Reshares for this user are shares where they are the owner.
651
+         */
652
+        if ($reshares === false) {
653
+            //Special case for old shares created via the web UI
654
+            $or1 = $qb->expr()->andX(
655
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
656
+                $qb->expr()->isNull('uid_initiator')
657
+            );
658
+
659
+            $qb->andWhere(
660
+                $qb->expr()->orX(
661
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
662
+                    $or1
663
+                )
664
+            );
665
+        } else {
666
+            $qb->andWhere(
667
+                $qb->expr()->orX(
668
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
669
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
670
+                )
671
+            );
672
+        }
673
+
674
+        if ($node !== null) {
675
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
676
+        }
677
+
678
+        if ($limit !== -1) {
679
+            $qb->setMaxResults($limit);
680
+        }
681
+
682
+        $qb->setFirstResult($offset);
683
+        $qb->orderBy('id');
684
+
685
+        $cursor = $qb->execute();
686
+        $shares = [];
687
+        while($data = $cursor->fetch()) {
688
+            $shares[] = $this->createShareObject($data);
689
+        }
690
+        $cursor->closeCursor();
691
+
692
+        return $shares;
693
+    }
694
+
695
+    /**
696
+     * @inheritdoc
697
+     */
698
+    public function getShareById($id, $recipientId = null) {
699
+        $qb = $this->dbConnection->getQueryBuilder();
700
+
701
+        $qb->select('*')
702
+            ->from('share')
703
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
704
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
705
+
706
+        $cursor = $qb->execute();
707
+        $data = $cursor->fetch();
708
+        $cursor->closeCursor();
709
+
710
+        if ($data === false) {
711
+            throw new ShareNotFound();
712
+        }
713
+
714
+        try {
715
+            $share = $this->createShareObject($data);
716
+        } catch (InvalidShare $e) {
717
+            throw new ShareNotFound();
718
+        }
719
+
720
+        return $share;
721
+    }
722
+
723
+    /**
724
+     * Get shares for a given path
725
+     *
726
+     * @param \OCP\Files\Node $path
727
+     * @return IShare[]
728
+     */
729
+    public function getSharesByPath(Node $path) {
730
+        $qb = $this->dbConnection->getQueryBuilder();
731
+
732
+        $cursor = $qb->select('*')
733
+            ->from('share')
734
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
735
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
736
+            ->execute();
737
+
738
+        $shares = [];
739
+        while($data = $cursor->fetch()) {
740
+            $shares[] = $this->createShareObject($data);
741
+        }
742
+        $cursor->closeCursor();
743
+
744
+        return $shares;
745
+    }
746
+
747
+    /**
748
+     * @inheritdoc
749
+     */
750
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
751
+        /** @var IShare[] $shares */
752
+        $shares = [];
753
+
754
+        //Get shares directly with this user
755
+        $qb = $this->dbConnection->getQueryBuilder();
756
+        $qb->select('*')
757
+            ->from('share');
758
+
759
+        // Order by id
760
+        $qb->orderBy('id');
761
+
762
+        // Set limit and offset
763
+        if ($limit !== -1) {
764
+            $qb->setMaxResults($limit);
765
+        }
766
+        $qb->setFirstResult($offset);
767
+
768
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)));
769
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
770
+
771
+        // Filter by node if provided
772
+        if ($node !== null) {
773
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
774
+        }
775
+
776
+        $cursor = $qb->execute();
777
+
778
+        while($data = $cursor->fetch()) {
779
+            $shares[] = $this->createShareObject($data);
780
+        }
781
+        $cursor->closeCursor();
782
+
783
+
784
+        return $shares;
785
+    }
786
+
787
+    /**
788
+     * Get a share by token
789
+     *
790
+     * @param string $token
791
+     * @return IShare
792
+     * @throws ShareNotFound
793
+     */
794
+    public function getShareByToken($token) {
795
+        $qb = $this->dbConnection->getQueryBuilder();
796
+
797
+        $cursor = $qb->select('*')
798
+            ->from('share')
799
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_REMOTE)))
800
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
801
+            ->execute();
802
+
803
+        $data = $cursor->fetch();
804
+
805
+        if ($data === false) {
806
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
807
+        }
808
+
809
+        try {
810
+            $share = $this->createShareObject($data);
811
+        } catch (InvalidShare $e) {
812
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
813
+        }
814
+
815
+        return $share;
816
+    }
817
+
818
+    /**
819
+     * get database row of a give share
820
+     *
821
+     * @param $id
822
+     * @return array
823
+     * @throws ShareNotFound
824
+     */
825
+    private function getRawShare($id) {
826
+
827
+        // Now fetch the inserted share and create a complete share object
828
+        $qb = $this->dbConnection->getQueryBuilder();
829
+        $qb->select('*')
830
+            ->from('share')
831
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
832
+
833
+        $cursor = $qb->execute();
834
+        $data = $cursor->fetch();
835
+        $cursor->closeCursor();
836
+
837
+        if ($data === false) {
838
+            throw new ShareNotFound;
839
+        }
840
+
841
+        return $data;
842
+    }
843
+
844
+    /**
845
+     * Create a share object from an database row
846
+     *
847
+     * @param array $data
848
+     * @return IShare
849
+     * @throws InvalidShare
850
+     * @throws ShareNotFound
851
+     */
852
+    private function createShareObject($data) {
853
+
854
+        $share = new Share($this->rootFolder, $this->userManager);
855
+        $share->setId((int)$data['id'])
856
+            ->setShareType((int)$data['share_type'])
857
+            ->setPermissions((int)$data['permissions'])
858
+            ->setTarget($data['file_target'])
859
+            ->setMailSend((bool)$data['mail_send'])
860
+            ->setToken($data['token']);
861
+
862
+        $shareTime = new \DateTime();
863
+        $shareTime->setTimestamp((int)$data['stime']);
864
+        $share->setShareTime($shareTime);
865
+        $share->setSharedWith($data['share_with']);
866
+
867
+        if ($data['uid_initiator'] !== null) {
868
+            $share->setShareOwner($data['uid_owner']);
869
+            $share->setSharedBy($data['uid_initiator']);
870
+        } else {
871
+            //OLD SHARE
872
+            $share->setSharedBy($data['uid_owner']);
873
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
874
+
875
+            $owner = $path->getOwner();
876
+            $share->setShareOwner($owner->getUID());
877
+        }
878
+
879
+        $share->setNodeId((int)$data['file_source']);
880
+        $share->setNodeType($data['item_type']);
881
+
882
+        $share->setProviderId($this->identifier());
883
+
884
+        return $share;
885
+    }
886
+
887
+    /**
888
+     * Get the node with file $id for $user
889
+     *
890
+     * @param string $userId
891
+     * @param int $id
892
+     * @return \OCP\Files\File|\OCP\Files\Folder
893
+     * @throws InvalidShare
894
+     */
895
+    private function getNode($userId, $id) {
896
+        try {
897
+            $userFolder = $this->rootFolder->getUserFolder($userId);
898
+        } catch (NotFoundException $e) {
899
+            throw new InvalidShare();
900
+        }
901
+
902
+        $nodes = $userFolder->getById($id);
903
+
904
+        if (empty($nodes)) {
905
+            throw new InvalidShare();
906
+        }
907
+
908
+        return $nodes[0];
909
+    }
910
+
911
+    /**
912
+     * A user is deleted from the system
913
+     * So clean up the relevant shares.
914
+     *
915
+     * @param string $uid
916
+     * @param int $shareType
917
+     */
918
+    public function userDeleted($uid, $shareType) {
919
+        //TODO: probabaly a good idea to send unshare info to remote servers
920
+
921
+        $qb = $this->dbConnection->getQueryBuilder();
922
+
923
+        $qb->delete('share')
924
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
925
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
926
+            ->execute();
927
+    }
928
+
929
+    /**
930
+     * This provider does not handle groups
931
+     *
932
+     * @param string $gid
933
+     */
934
+    public function groupDeleted($gid) {
935
+        // We don't handle groups here
936
+    }
937
+
938
+    /**
939
+     * This provider does not handle groups
940
+     *
941
+     * @param string $uid
942
+     * @param string $gid
943
+     */
944
+    public function userDeletedFromGroup($uid, $gid) {
945
+        // We don't handle groups here
946
+    }
947
+
948
+    /**
949
+     * check if users from other Nextcloud instances are allowed to mount public links share by this instance
950
+     *
951
+     * @return bool
952
+     */
953
+    public function isOutgoingServer2serverShareEnabled() {
954
+        if ($this->gsConfig->onlyInternalFederation()) {
955
+            return false;
956
+        }
957
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
958
+        return ($result === 'yes');
959
+    }
960
+
961
+    /**
962
+     * check if users are allowed to mount public links from other Nextclouds
963
+     *
964
+     * @return bool
965
+     */
966
+    public function isIncomingServer2serverShareEnabled() {
967
+        if ($this->gsConfig->onlyInternalFederation()) {
968
+            return false;
969
+        }
970
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
971
+        return ($result === 'yes');
972
+    }
973
+
974
+    /**
975
+     * Check if querying sharees on the lookup server is enabled
976
+     *
977
+     * @return bool
978
+     */
979
+    public function isLookupServerQueriesEnabled() {
980
+        // in a global scale setup we should always query the lookup server
981
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
982
+            return true;
983
+        }
984
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no');
985
+        return ($result === 'yes');
986
+    }
987
+
988
+
989
+    /**
990
+     * Check if it is allowed to publish user specific data to the lookup server
991
+     *
992
+     * @return bool
993
+     */
994
+    public function isLookupServerUploadEnabled() {
995
+        // in a global scale setup the admin is responsible to keep the lookup server up-to-date
996
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
997
+            return false;
998
+        }
999
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1000
+        return ($result === 'yes');
1001
+    }
1002
+
1003
+    /**
1004
+     * @inheritdoc
1005
+     */
1006
+    public function getAccessList($nodes, $currentAccess) {
1007
+        $ids = [];
1008
+        foreach ($nodes as $node) {
1009
+            $ids[] = $node->getId();
1010
+        }
1011
+
1012
+        $qb = $this->dbConnection->getQueryBuilder();
1013
+        $qb->select('share_with', 'token', 'file_source')
1014
+            ->from('share')
1015
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share::SHARE_TYPE_REMOTE)))
1016
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1017
+            ->andWhere($qb->expr()->orX(
1018
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1019
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1020
+            ));
1021
+        $cursor = $qb->execute();
1022
+
1023
+        if ($currentAccess === false) {
1024
+            $remote = $cursor->fetch() !== false;
1025
+            $cursor->closeCursor();
1026
+
1027
+            return ['remote' => $remote];
1028
+        }
1029
+
1030
+        $remote = [];
1031
+        while ($row = $cursor->fetch()) {
1032
+            $remote[$row['share_with']] = [
1033
+                'node_id' => $row['file_source'],
1034
+                'token' => $row['token'],
1035
+            ];
1036
+        }
1037
+        $cursor->closeCursor();
1038
+
1039
+        return ['remote' => $remote];
1040
+    }
1041 1041
 }
Please login to merge, or discard this patch.