1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* ownCloud - galleryplus |
4
|
|
|
* |
5
|
|
|
* This file is licensed under the Affero General Public License version 3 or |
6
|
|
|
* later. See the COPYING file. |
7
|
|
|
* |
8
|
|
|
* @author Olivier Paroz <[email protected]> |
9
|
|
|
* @author Authors of \OCA\Files_Sharing\Helper |
10
|
|
|
* |
11
|
|
|
* @copyright Olivier Paroz 2016 |
12
|
|
|
* @copyright Authors of \OCA\Files_Sharing\Helper 2014-2016 |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace OCA\GalleryPlus\Environment; |
16
|
|
|
|
17
|
|
|
use OCP\IUserManager; |
18
|
|
|
use OCP\Share; |
19
|
|
|
use OCP\ILogger; |
20
|
|
|
use OCP\Files\IRootFolder; |
21
|
|
|
use OCP\Files\Folder; |
22
|
|
|
use OCP\Files\Node; |
23
|
|
|
use OCP\Files\File; |
24
|
|
|
use OCP\Files\NotFoundException; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Builds the environment so that the services have access to the files and folders' owner |
28
|
|
|
* |
29
|
|
|
* @package OCA\GalleryPlus\Environment |
30
|
|
|
*/ |
31
|
|
|
class Environment { |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @var string |
35
|
|
|
*/ |
36
|
|
|
private $appName; |
37
|
|
|
/** |
38
|
|
|
* The userId of the logged-in user or the person sharing a folder publicly |
39
|
|
|
* |
40
|
|
|
* @var string |
41
|
|
|
*/ |
42
|
|
|
private $userId; |
43
|
|
|
/** |
44
|
|
|
* The userFolder of the logged-in user or the ORIGINAL owner of the files which are shared |
45
|
|
|
* publicly |
46
|
|
|
* |
47
|
|
|
* A share needs to be tracked back to its original owner in order to be able to access the |
48
|
|
|
* resource |
49
|
|
|
* |
50
|
|
|
* @var Folder|null |
51
|
|
|
*/ |
52
|
|
|
private $userFolder; |
53
|
|
|
/** |
54
|
|
|
* @var IUserManager |
55
|
|
|
*/ |
56
|
|
|
private $userManager; |
57
|
|
|
/** |
58
|
|
|
* @var int |
59
|
|
|
*/ |
60
|
|
|
private $sharedNodeId; |
61
|
|
|
/** |
62
|
|
|
* @var File|Folder |
63
|
|
|
*/ |
64
|
|
|
private $sharedNode; |
65
|
|
|
/** |
66
|
|
|
* @var IRootFolder |
67
|
|
|
*/ |
68
|
|
|
private $rootFolder; |
69
|
|
|
/** |
70
|
|
|
* @var ILogger |
71
|
|
|
*/ |
72
|
|
|
private $logger; |
73
|
|
|
/** |
74
|
|
|
* The path to the userFolder for users with accounts: /userId/files |
75
|
|
|
* |
76
|
|
|
* For public folders, it's the path from the shared folder to the root folder in the original |
77
|
|
|
* owner's filesystem: /userId/files/parent_folder/shared_folder |
78
|
|
|
* |
79
|
|
|
* @var string |
80
|
|
|
*/ |
81
|
|
|
private $fromRootToFolder; |
82
|
|
|
/** |
83
|
|
|
* The name of the shared folder |
84
|
|
|
* |
85
|
|
|
* @var string |
86
|
|
|
*/ |
87
|
|
|
private $folderName; |
88
|
|
|
/** |
89
|
|
|
* @var string|null |
90
|
|
|
*/ |
91
|
|
|
private $sharePassword; |
92
|
|
|
|
93
|
|
|
/*** |
94
|
|
|
* Constructor |
95
|
|
|
* |
96
|
|
|
* @param string $appName |
97
|
|
|
* @param string|null $userId |
98
|
|
|
* @param Folder|null $userFolder |
99
|
|
|
* @param IUserManager $userManager |
100
|
|
|
* @param IRootFolder $rootFolder |
101
|
|
|
* @param ILogger $logger |
102
|
|
|
*/ |
103
|
59 |
|
public function __construct( |
104
|
|
|
$appName, |
105
|
|
|
$userId, |
106
|
|
|
$userFolder, |
107
|
|
|
IUserManager $userManager, |
108
|
|
|
IRootFolder $rootFolder, |
109
|
|
|
ILogger $logger |
110
|
|
|
) { |
111
|
59 |
|
$this->appName = $appName; |
112
|
59 |
|
$this->userId = $userId; |
113
|
59 |
|
$this->userFolder = $userFolder; |
114
|
59 |
|
$this->userManager = $userManager; |
115
|
59 |
|
$this->rootFolder = $rootFolder; |
116
|
59 |
|
$this->logger = $logger; |
117
|
59 |
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Creates the environment based on the linkItem the token links to |
121
|
|
|
* |
122
|
|
|
* @param array $linkItem |
123
|
|
|
*/ |
124
|
21 |
|
public function setTokenBasedEnv($linkItem) { |
125
|
|
|
// Resolves reshares down to the last real share |
126
|
21 |
|
$rootLinkItem = Share::resolveReShare($linkItem); |
127
|
21 |
|
$origShareOwner = $rootLinkItem['uid_owner']; |
128
|
21 |
|
$this->userFolder = $this->rootFolder->getUserFolder($origShareOwner); |
129
|
|
|
|
130
|
|
|
// This is actually the node ID |
131
|
21 |
|
$this->sharedNodeId = $linkItem['file_source']; |
132
|
21 |
|
$this->sharedNode = |
133
|
21 |
|
$this->getResourceFromFolderAndId($this->userFolder, $this->sharedNodeId); |
|
|
|
|
134
|
21 |
|
$this->fromRootToFolder = $this->buildFromRootToFolder($this->sharedNodeId); |
135
|
|
|
|
136
|
21 |
|
$this->folderName = $linkItem['file_target']; |
137
|
21 |
|
$this->userId = $rootLinkItem['uid_owner']; |
138
|
21 |
|
$this->sharePassword = $linkItem['share_with']; |
139
|
21 |
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Creates the environment for a logged-in user |
143
|
|
|
* |
144
|
|
|
* userId and userFolder are already known, we define fromRootToFolder |
145
|
|
|
* so that the services can use one method to have access to resources |
146
|
|
|
* without having to know whether they're private or public |
147
|
|
|
*/ |
148
|
29 |
|
public function setStandardEnv() { |
149
|
29 |
|
$this->fromRootToFolder = $this->userFolder->getPath() . '/'; |
150
|
29 |
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Returns true if the environment has been setup using a token |
154
|
|
|
* |
155
|
|
|
* @return bool |
156
|
|
|
*/ |
157
|
43 |
|
public function isTokenBasedEnv() { |
158
|
43 |
|
return !empty($this->sharedNodeId); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Returns the Node based on a path starting from the virtual root |
163
|
|
|
* |
164
|
|
|
* @param string $subPath |
165
|
|
|
* |
166
|
|
|
* @return File|Folder |
|
|
|
|
167
|
|
|
*/ |
168
|
8 |
|
public function getNodeFromVirtualRoot($subPath) { |
169
|
8 |
|
$relativePath = $this->getRelativePath($this->fromRootToFolder); |
170
|
8 |
|
$path = $relativePath . '/' . $subPath; |
171
|
8 |
|
$node = $this->getNodeFromUserFolder($path); |
172
|
|
|
|
173
|
8 |
|
return $this->getResourceFromId($node->getId()); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Returns the Node based on a path starting from the files' owner user folder |
178
|
|
|
* |
179
|
|
|
* When logged in, this is the current user's user folder |
180
|
|
|
* When visiting a link, this is the sharer's user folder |
181
|
|
|
* |
182
|
|
|
* @param string $path |
183
|
|
|
* |
184
|
|
|
* @return File|Folder |
185
|
|
|
* |
186
|
|
|
* @throws NotFoundEnvException |
187
|
|
|
*/ |
188
|
11 |
|
public function getNodeFromUserFolder($path) { |
189
|
11 |
|
$folder = $this->userFolder; |
190
|
11 |
|
if ($folder === null) { |
191
|
1 |
|
throw new NotFoundEnvException("Could not access the user's folder"); |
192
|
|
|
} else { |
193
|
|
|
try { |
194
|
10 |
|
$node = $folder->get($path); |
195
|
2 |
|
} catch (NotFoundException $exception) { |
196
|
2 |
|
$message = 'Could not find anything at: ' . $exception->getMessage(); |
197
|
2 |
|
throw new NotFoundEnvException($message); |
198
|
|
|
} |
199
|
|
|
} |
200
|
|
|
|
201
|
10 |
|
return $node; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Returns the resource identified by the given ID |
206
|
|
|
* |
207
|
|
|
* @param int $resourceId |
208
|
|
|
* |
209
|
|
|
* @return Node |
210
|
|
|
* |
211
|
|
|
* @throws NotFoundEnvException |
212
|
|
|
*/ |
213
|
37 |
|
public function getResourceFromId($resourceId) { |
214
|
37 |
|
if ($this->isTokenBasedEnv()) { |
215
|
21 |
|
if ($this->sharedNode->getType() === 'dir') { |
216
|
16 |
|
$resource = $this->getResourceFromFolderAndId($this->sharedNode, $resourceId); |
217
|
|
|
} else { |
218
|
21 |
|
$resource = $this->sharedNode; |
219
|
|
|
} |
220
|
|
|
} else { |
221
|
17 |
|
$resource = $this->getResourceFromFolderAndId($this->userFolder, $resourceId); |
|
|
|
|
222
|
|
|
} |
223
|
|
|
|
224
|
34 |
|
return $resource; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* Returns the shared node |
229
|
|
|
* |
230
|
|
|
* @return File|Folder |
|
|
|
|
231
|
|
|
*/ |
232
|
8 |
|
public function getSharedNode() { |
233
|
8 |
|
return $this->getResourceFromId($this->sharedNodeId); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* Returns the virtual root where the user lands after logging in or when following a link |
238
|
|
|
* |
239
|
|
|
* @return Folder |
240
|
|
|
* @throws NotFoundEnvException |
241
|
|
|
*/ |
242
|
14 |
|
public function getVirtualRootFolder() { |
243
|
14 |
|
$rootFolder = $this->userFolder; |
244
|
14 |
|
if ($this->isTokenBasedEnv()) { |
245
|
4 |
|
$node = $this->getSharedNode(); |
246
|
4 |
|
$nodeType = $node->getType(); |
247
|
4 |
|
if ($nodeType === 'dir') { |
248
|
3 |
|
$rootFolder = $node; |
249
|
|
|
} else { |
250
|
1 |
|
throw new NotFoundEnvException($node->getPath() . ' is not a folder'); |
251
|
|
|
} |
252
|
|
|
} |
253
|
|
|
|
254
|
13 |
|
return $rootFolder; |
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
/** |
258
|
|
|
* Returns the userId of the currently logged-in user or the sharer |
259
|
|
|
* |
260
|
|
|
* @return string |
261
|
|
|
*/ |
262
|
9 |
|
public function getUserId() { |
263
|
9 |
|
return $this->userId; |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
/** |
267
|
|
|
* Returns the name of the user sharing files publicly |
268
|
|
|
* |
269
|
|
|
* @return string |
270
|
|
|
* @throws NotFoundEnvException |
271
|
|
|
*/ |
272
|
2 |
|
public function getDisplayName() { |
273
|
2 |
|
$user = null; |
274
|
2 |
|
$userId = $this->userId; |
275
|
|
|
|
276
|
2 |
|
if (isset($userId)) { |
277
|
1 |
|
$user = $this->userManager->get($userId); |
278
|
|
|
} |
279
|
2 |
|
if ($user === null) { |
280
|
1 |
|
throw new NotFoundEnvException('Could not find user'); |
281
|
|
|
} |
282
|
|
|
|
283
|
1 |
|
return $user->getDisplayName(); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* Returns the name of shared folder |
288
|
|
|
* |
289
|
|
|
* @return string |
290
|
|
|
*/ |
291
|
1 |
|
public function getSharedFolderName() { |
292
|
1 |
|
return trim($this->folderName, '//'); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
/** |
296
|
|
|
* Returns the password for the share, if there is one |
297
|
|
|
* |
298
|
|
|
* @return string|null |
299
|
|
|
*/ |
300
|
1 |
|
public function getSharePassword() { |
301
|
1 |
|
return $this->sharePassword; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* Returns the path which goes from the file, up to the user folder, based on a node: |
306
|
|
|
* parent_folder/current_folder/my_file |
307
|
|
|
* |
308
|
|
|
* This is used for the preview system, which needs a full path |
309
|
|
|
* |
310
|
|
|
* getPath() on the file produces a path like: |
311
|
|
|
* '/userId/files/my_folder/my_sub_folder/my_file' |
312
|
|
|
* |
313
|
|
|
* So we substract the path to the folder, giving us a relative path |
314
|
|
|
* 'my_folder/my_sub_folder/my_file' |
315
|
|
|
* |
316
|
|
|
* @param Node $file |
317
|
|
|
* |
318
|
|
|
* @return string |
319
|
|
|
*/ |
320
|
9 |
|
public function getPathFromUserFolder($file) { |
321
|
9 |
|
$path = $file->getPath(); |
322
|
|
|
|
323
|
9 |
|
return $this->getRelativePath($path); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Returns the path which goes from the file, up to the root folder of the Gallery: |
328
|
|
|
* current_folder/my_file |
329
|
|
|
* |
330
|
|
|
* That root folder changes when folders are shared publicly |
331
|
|
|
* |
332
|
|
|
* @param File|Folder|N $node |
333
|
|
|
* |
334
|
|
|
* @return string |
335
|
|
|
*/ |
336
|
10 |
|
public function getPathFromVirtualRoot($node) { |
337
|
10 |
|
$path = $node->getPath(); |
338
|
10 |
|
$nodeType = $node->getType(); |
339
|
|
|
|
340
|
|
|
// Needed because fromRootToFolder always ends with a slash |
341
|
10 |
|
if ($nodeType === 'dir') { |
342
|
8 |
|
$path .= '/'; |
343
|
|
|
} |
344
|
|
|
|
345
|
10 |
|
$path = str_replace($this->fromRootToFolder, '', $path); |
346
|
10 |
|
$path = rtrim($path, '/'); |
347
|
|
|
|
348
|
10 |
|
return $path; |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
/** |
352
|
|
|
* Returns the resource found in a specific folder and identified by the given ID |
353
|
|
|
* |
354
|
|
|
* @param Folder $folder |
355
|
|
|
* @param int $resourceId |
356
|
|
|
* |
357
|
|
|
* @return Node |
358
|
|
|
* @throws NotFoundEnvException |
359
|
|
|
*/ |
360
|
37 |
|
private function getResourceFromFolderAndId($folder, $resourceId) { |
361
|
37 |
|
$resourcesArray = $folder->getById($resourceId); |
362
|
|
|
|
363
|
37 |
|
if ($resourcesArray[0] === null) { |
364
|
3 |
|
throw new NotFoundEnvException('Could not locate node linked to ID: ' . $resourceId); |
365
|
|
|
} |
366
|
|
|
|
367
|
34 |
|
return $resourcesArray[0]; |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Returns the path from the shared folder to the root folder in the original |
372
|
|
|
* owner's filesystem: /userId/files/parent_folder/shared_folder |
373
|
|
|
* |
374
|
|
|
* This cannot be calculated with paths and IDs, the linkitem's file source is required |
375
|
|
|
* |
376
|
|
|
* @param string $fileSource |
377
|
|
|
* |
378
|
|
|
* @return string |
379
|
|
|
*/ |
380
|
21 |
|
private function buildFromRootToFolder($fileSource) { |
381
|
21 |
|
$resource = $this->getResourceFromId($fileSource); |
382
|
21 |
|
$fromRootToFolder = $resource->getPath() . '/'; |
383
|
|
|
|
384
|
21 |
|
return $fromRootToFolder; |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
/** |
388
|
|
|
* Returns the path which goes from the file, up to the user folder, based on a path: |
389
|
|
|
* parent_folder/current_folder/my_file |
390
|
|
|
* |
391
|
|
|
* getPath() on the file produces a path like: |
392
|
|
|
* '/userId/files/my_folder/my_sub_folder/my_file' |
393
|
|
|
* |
394
|
|
|
* So we substract the path to the user folder, giving us a relative path |
395
|
|
|
* 'my_folder/my_sub_folder' |
396
|
|
|
* |
397
|
|
|
* @param string $fullPath |
398
|
|
|
* |
399
|
|
|
* @return string |
400
|
|
|
*/ |
401
|
17 |
|
private function getRelativePath($fullPath) { |
402
|
17 |
|
$folderPath = $this->userFolder->getPath() . '/'; |
403
|
17 |
|
$origShareRelPath = str_replace($folderPath, '', $fullPath); |
404
|
|
|
|
405
|
17 |
|
return $origShareRelPath; |
406
|
|
|
} |
407
|
|
|
|
408
|
|
|
} |
409
|
|
|
|
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..