Welcome to mirror list, hosted at ThFree Co, Russian Federation.

environment.php « environment - github.com/nextcloud/gallery.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: a5e3a8ff2faeb12fe9f5f9180951aba5027dc88f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
<?php
/**
 * ownCloud - galleryplus
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author Olivier Paroz <owncloud@interfasys.ch>
 * @author Authors of \OCA\Files_Sharing\Helper
 *
 * @copyright Olivier Paroz 2015
 * @copyright Authors of \OCA\Files_Sharing\Helper 2014-2015
 */

namespace OCA\GalleryPlus\Environment;

use OCP\IServerContainer;
use OCP\IUserManager;
use OCP\Share;
use OCP\ILogger;
use OCP\Files\Folder;
use OCP\Files\Node;
use OCP\Files\File;
use OCP\Files\NotFoundException;

/**
 * Builds the environment so that the services have access to the files and folders' owner
 *
 * @todo remove the serverContainer once OCP\IUserManager has a getUserFolder() method
 *
 * @package OCA\GalleryPlus\Environment
 */
class Environment {

	/**
	 * @var string
	 */
	private $appName;
	/**
	 * The userId of the logged-in user or the person sharing a folder publicly
	 *
	 * @var string
	 */
	private $userId;
	/**
	 * The userFolder of the logged-in user or the ORIGINAL owner of the files which are shared
	 * publicly
	 *
	 * A share needs to be tracked back to its original owner in order to be able to access the
	 * resource
	 *
	 * @var Folder|null
	 */
	private $userFolder;
	/**
	 * @var IUserManager
	 */
	private $userManager;
	/**
	 * @var IServerContainer
	 */
	private $serverContainer;
	/**
	 * @var ILogger
	 */
	private $logger;
	/**
	 * The path to the userFolder for users with accounts: /userId/files
	 *
	 * For public folders, it's the path from the shared folder to the root folder in the original
	 * owner's filesystem: /userId/files/parent_folder/shared_folder
	 *
	 * @var string
	 */
	private $fromRootToFolder;
	/**
	 * The name of the shared folder
	 *
	 * @var string
	 */
	private $folderName;

	/***
	 * Constructor
	 *
	 * @param string $appName
	 * @param string|null $userId
	 * @param Folder|null $userFolder
	 * @param IUserManager $userManager
	 * @param IServerContainer $serverContainer
	 * @param ILogger $logger
	 */
	public function __construct(
		$appName,
		$userId,
		$userFolder,
		IUserManager $userManager,
		IServerContainer $serverContainer,
		ILogger $logger
	) {
		$this->appName = $appName;
		$this->userId = $userId;
		$this->userFolder = $userFolder;
		$this->userManager = $userManager;
		$this->serverContainer = $serverContainer;
		$this->logger = $logger;
	}

	/**
	 * Creates the environment based on the linkItem the token links to
	 *
	 * @param array $linkItem
	 */
	public function setTokenBasedEnv($linkItem) {
		// Resolves reshares down to the last real share
		$rootLinkItem = Share::resolveReShare($linkItem);
		$origShareOwner = $rootLinkItem['uid_owner'];
		$this->userFolder = $this->setupFilesystem($origShareOwner);

		// This is actually the node ID
		$fileSource = $linkItem['file_source'];
		$this->fromRootToFolder = $this->buildFromRootToFolder($fileSource);

		$this->folderName = $linkItem['file_target'];
		$this->userId = $rootLinkItem['uid_owner'];
	}

	/**
	 * Creates the environment for a logged-in user
	 *
	 * userId and userFolder are already known, we define fromRootToFolder
	 * so that the services can use one method to have access to resources
	 * without having to know whether they're private or public
	 */
	public function setStandardEnv() {
		$this->fromRootToFolder = $this->userFolder->getPath() . '/';
	}

	/**
	 * Returns the resource located at the given path
	 *
	 * The path starts from the user's files folder because we'll query that folder to get the
	 * information we need. The resource is either a File or a Folder
	 *
	 * @param string $subPath
	 *
	 * @return File|Folder
	 */
	public function getResourceFromPath($subPath) {
		$relativePath = $this->getRelativePath($this->fromRootToFolder);
		$path = $relativePath . '/' . $subPath;
		$node = $this->getNode($path);

		return $this->getResourceFromId($node->getId());
	}

	/**
	 * Returns the Node based on the current user's files folder and a given
	 * path
	 *
	 * @param string $path
	 *
	 * @return File|Folder
	 *
	 * @throws EnvironmentException
	 */
	public function getNode($path) {
		$node = false;
		$folder = $this->userFolder;
		if ($folder === null) {
			$this->logAndThrowNotFound("Could not access the user's folder");
		} else {
			try {
				$node = $folder->get($path);
			} catch (NotFoundException $exception) {
				$message = 'Could not find anything at: ' . $exception->getMessage();
				$this->logAndThrowNotFound($message);
			}
		}

		return $node;
	}

	/**
	 * Returns the resource identified by the given ID
	 *
	 * @param int $resourceId
	 *
	 * @return Node
	 *
	 * @throws EnvironmentException
	 */
	public function getResourceFromId($resourceId) {
		$resourcesArray = $this->userFolder->getById($resourceId);
		if ($resourcesArray[0] === null) {
			$this->logAndThrowNotFound('Could not locate file linked to ID: ' . $resourceId);
		}

		return $resourcesArray[0];
	}

	/**
	 * Returns the userId of the currently logged-in user or the sharer
	 *
	 * @return string
	 */
	public function getUserId() {
		return $this->userId;
	}

	/**
	 * Returns the name of the user sharing files publicly
	 *
	 * @return string
	 */
	public function getDisplayName() {
		$user = null;
		$userId = $this->userId;

		if (isset($userId)) {
			$user = $this->userManager->get($userId);
		}
		if ($user === null) {
			$this->logAndThrowNotFound('Could not find user');
		}

		return $user->getDisplayName();
	}

	/**
	 * Returns the name of shared folder
	 *
	 * @return string
	 */
	public function getSharedFolderName() {
		return trim($this->folderName, '//');
	}

	/**
	 * Returns the path which goes from the file, up to the user folder, based on a node:
	 * parent_folder/current_folder/my_file
	 *
	 * This is used for the preview system, which needs a full path
	 *
	 * getPath() on the file produces a path like:
	 * '/userId/files/my_folder/my_sub_folder/my_file'
	 *
	 * So we substract the path to the folder, giving us a relative path
	 * 'my_folder/my_sub_folder/my_file'
	 *
	 * @param Node $file
	 *
	 * @return string
	 */
	public function getPathFromUserFolder($file) {
		$path = $file->getPath();

		return $this->getRelativePath($path);
	}

	/**
	 * Returns the path which goes from the file, up to the root folder of the Gallery:
	 * current_folder/my_file
	 *
	 * That root folder changes when folders are shared publicly
	 *
	 * @param File|Folder $node
	 *
	 * @return string
	 */
	public function getPathFromVirtualRoot($node) {
		$path = $node->getPath();

		if ($node->getType() === 'dir') {
			// Needed because fromRootToFolder always ends with a slash
			$path .= '/';
		}

		$path = str_replace($this->fromRootToFolder, '', $path);
		$path = rtrim($path, '/');

		return $path;
	}

	/**
	 * Sets up the filesystem for the original share owner so that we can
	 * retrieve the files and returns the userFolder for that user
	 *
	 * We can't use 'UserFolder' from Application as the user is not known
	 * at instantiation time
	 *
	 * @param $origShareOwner
	 *
	 * @return Folder
	 */
	private function setupFilesystem($origShareOwner) {
		\OC_Util::tearDownFS(); // FIXME: Private API
		\OC_Util::setupFS($origShareOwner); // FIXME: Private API

		$folder = $this->serverContainer->getUserFolder($origShareOwner);

		/*// Alternative which does not exist yet
		$user = $this->userManager->get($origShareOwner);
		$folder = $user->getUserFolder();*/

		return $folder;
	}

	/**
	 * Returns the path from the shared folder to the root folder in the original
	 * owner's filesystem: /userId/files/parent_folder/shared_folder
	 *
	 * This cannot be calculated with paths and IDs, the linkitem's file source is required
	 *
	 * @param string $fileSource
	 *
	 * @return string
	 */
	private function buildFromRootToFolder($fileSource) {
		$resource = $this->getResourceFromId($fileSource);
		$fromRootToFolder = $resource->getPath() . '/';

		return $fromRootToFolder;
	}

	/**
	 * Returns the path which goes from the file, up to the user folder, based on a path:
	 * parent_folder/current_folder/my_file
	 *
	 * getPath() on the file produces a path like:
	 * '/userId/files/my_folder/my_sub_folder/my_file'
	 *
	 * So we substract the path to the user folder, giving us a relative path
	 * 'my_folder/my_sub_folder'
	 *
	 * @param string $fullPath
	 *
	 * @return string
	 */
	private function getRelativePath($fullPath) {
		$folderPath = $this->userFolder->getPath() . '/';
		$origShareRelPath = str_replace($folderPath, '', $fullPath);

		return $origShareRelPath;
	}

	/**
	 * Logs the error and raises an exception
	 *
	 * @param string $message
	 *
	 * @throws NotFoundEnvException
	 */
	private function logAndThrowNotFound($message) {
		$this->logger->error($message . ' (404)');
		throw new NotFoundEnvException($message);
	}

}