Completed
Push — master ( 8f3ef0...c4f5b8 )
by Andras
12s
created

DocumentController::domainOnly()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 7
cp 0
rs 10
c 0
b 0
f 0
cc 4
nc 8
nop 1
crap 20
1
<?php
2
/**
3
 * ownCloud - Richdocuments App
4
 *
5
 * @author Victor Dubiniuk
6
 * @copyright 2014 Victor Dubiniuk [email protected]
7
 *
8
 * This file is licensed under the Affero General Public License version 3 or
9
 * later.
10
 */
11
12
namespace OCA\Richdocuments\Controller;
13
14
use OCA\Richdocuments\TokenManager;
15
use OCA\Richdocuments\WOPI\Parser;
16
use \OCP\AppFramework\Controller;
17
use OCP\AppFramework\Http;
18
use OCP\AppFramework\Http\JSONResponse;
19
use OCP\Files\Folder;
20
use OCP\Files\IRootFolder;
21
use OCP\Files\Node;
22
use OCP\Files\NotFoundException;
23
use OCP\Files\NotPermittedException;
24
use \OCP\IRequest;
25
use \OCP\IConfig;
26
use \OCP\IL10N;
27
use \OCP\ILogger;
28
use \OCP\AppFramework\Http\ContentSecurityPolicy;
29
use \OCP\AppFramework\Http\TemplateResponse;
30
use \OCA\Richdocuments\AppConfig;
31
use \OCA\Richdocuments\Helper;
32
use OCP\ISession;
33
use OCP\Share\IManager;
34
use OC\Files\Type\TemplateManager;
35
36
class DocumentController extends Controller {
37
	/** @var string */
38
	private $uid;
39
	/** @var IL10N */
40
	private $l10n;
41
	/** @var IConfig */
42
	private $settings;
43
	/** @var AppConfig */
44
	private $appConfig;
45
	/** @var ILogger */
46
	private $logger;
47
	/** @var IManager */
48
	private $shareManager;
49
	/** @var TokenManager */
50
	private $tokenManager;
51
	/** @var ISession */
52
	private $session;
53
	/** @var IRootFolder */
54
	private $rootFolder;
55
56
	const ODT_TEMPLATE_PATH = '/assets/odttemplate.odt';
57
58
	/**
59
	 * @param string $appName
60
	 * @param IRequest $request
61
	 * @param IConfig $settings
62
	 * @param AppConfig $appConfig
63
	 * @param IL10N $l10n
64
	 * @param IManager $shareManager
65
	 * @param TokenManager $tokenManager
66
	 * @param IRootFolder $rootFolder
67
	 * @param ISession $session
68
	 * @param string $UserId
69
	 * @param ILogger $logger
70
	 */
71
	public function __construct($appName,
72
								IRequest $request,
73
								IConfig $settings,
74
								AppConfig $appConfig,
75
								IL10N $l10n,
76
								IManager $shareManager,
77
								TokenManager $tokenManager,
78
								IRootFolder $rootFolder,
79
								ISession $session,
80
								$UserId,
81
								ILogger $logger) {
82
		parent::__construct($appName, $request);
83
		$this->uid = $UserId;
84
		$this->l10n = $l10n;
85
		$this->settings = $settings;
86
		$this->appConfig = $appConfig;
87
		$this->shareManager = $shareManager;
88
		$this->tokenManager = $tokenManager;
89
		$this->rootFolder = $rootFolder;
90
		$this->session = $session;
91
		$this->logger = $logger;
92
	}
93
94
	/**
95
	 * @PublicPage
96
	 * @NoCSRFRequired
97
	 *
98
	 * Returns the access_token and urlsrc for WOPI access for given $fileId
99
	 * Requests is accepted only when a secret_token is provided set by admin in
100
	 * settings page
101
	 *
102
	 * @param string $fileId
103
	 * @return access_token, urlsrc
0 ignored issues
show
Documentation introduced by
The doc-type access_token, could not be parsed: Expected "|" or "end of type", but got "," at position 12. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
104
	 */
105
	public function extAppGetData($fileId) {
106
		$secretToken = $this->request->getParam('secret_token');
107
		$apps = array_filter(explode(',', $this->appConfig->getAppValue('external_apps')));
108
		foreach($apps as $app) {
109
			if ($app !== '' && $secretToken === $app) {
110
				$appName = explode(':', $app);
111
				$this->logger->debug('External app "{extApp}" authenticated; issuing access token for fileId {fileId}', [
112
					'app' => $this->appName,
113
					'extApp' => $appName[0],
114
					'fileId' => $fileId
115
				]);
116
				try {
117
					$folder = $this->rootFolder->getUserFolder($this->uid);
118
					$item = $folder->getById($fileId)[0];
119
					if(!($item instanceof Node)) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\Node does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
120
						throw new \Exception();
121
					}
122
					list($urlSrc, $token) = $this->tokenManager->getToken($item->getId());
123
					return [
124
						'status' => 'success',
125
						'urlsrc' => $urlSrc,
126
						'token' => $token
127
					];
128
				} catch (\Exception $e) {
129
					$this->logger->logException($e, ['app'=>'richdocuments']);
130
					$params = [
131
						'remoteAddr' => $this->request->getRemoteAddress(),
132
						'requestID' => $this->request->getId(),
133
						'debugMode' => $this->settings->getSystemValue('debug'),
134
						'errorClass' => get_class($e),
135
						'errorCode' => $e->getCode(),
136
						'errorMsg' => $e->getMessage(),
137
						'file' => $e->getFile(),
138
						'line' => $e->getLine(),
139
						'trace' => $e->getTraceAsString()
140
					];
141
					return new TemplateResponse('core', 'exception', $params, 'guest');
142
				}
143
			}
144
145
			return [
146
				'status' => 'error',
147
				'message' => 'Permission denied'
148
			];
149
		}
150
	}
151
152
	/**
153
	 * Strips the path and query parameters from the URL.
154
	 *
155
	 * @param string $url
156
	 * @return string
157
	 */
158
	private function domainOnly($url) {
159
		$parsed_url = parse_url($url);
160
		$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
161
		$host   = isset($parsed_url['host']) ? $parsed_url['host'] : '';
162
		$port   = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
163
		return "$scheme$host$port";
164
	}
165
166
	/**
167
	 * @NoAdminRequired
168
	 *
169
	 * @param string $fileId
170
	 * @return TemplateResponse
171
	 */
172
	public function index($fileId) {
173
		try {
174
			$folder = $this->rootFolder->getUserFolder($this->uid);
175
			$item = $folder->getById($fileId)[0];
176
			if(!($item instanceof Node)) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\Node does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
177
				throw new \Exception();
178
			}
179
			list($urlSrc, $token) = $this->tokenManager->getToken($item->getId());
180
			$params = [
181
				'permissions' => $item->getPermissions(),
182
				'title' => $item->getName(),
183
				'fileId' => $item->getId() . '_' . $this->settings->getSystemValue('instanceid'),
184
				'token' => $token,
185
				'urlsrc' => $urlSrc,
186
				'path' => $folder->getRelativePath($item->getPath()),
187
				'instanceId' => $this->settings->getSystemValue('instanceid'),
188
				'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
189
			];
190
191
			$encryptionManager = \OC::$server->getEncryptionManager();
192
			if ($encryptionManager->isEnabled())
193
			{
194
				// Update the current file to be accessible with system public shared key
195
				$owner = $item->getOwner()->getUID();
196
				$absPath = '/' . $owner . '/' .  $item->getInternalPath();
197
				$accessList = \OC::$server->getEncryptionFilesHelper()->getAccessList($absPath);
198
				$accessList['public'] = true;
199
				$encryptionManager->getEncryptionModule()->update($absPath, $owner, $accessList);
200
			}
201
202
			$response = new TemplateResponse('richdocuments', 'documents', $params, 'empty');
203
			$policy = new ContentSecurityPolicy();
204
			$policy->addAllowedFrameDomain($this->domainOnly($this->appConfig->getAppValue('wopi_url')));
205
			$policy->allowInlineScript(true);
206
			$response->setContentSecurityPolicy($policy);
207
			return $response;
208
		} catch (\Exception $e) {
209
			$this->logger->logException($e, ['app'=>'richdocuments']);
210
			$params = [
211
				'remoteAddr' => $this->request->getRemoteAddress(),
212
				'requestID' => $this->request->getId(),
213
				'debugMode' => $this->settings->getSystemValue('debug'),
214
				'errorClass' => get_class($e),
215
				'errorCode' => $e->getCode(),
216
				'errorMsg' => $e->getMessage(),
217
				'file' => $e->getFile(),
218
				'line' => $e->getLine(),
219
				'trace' => $e->getTraceAsString()
220
			];
221
			return new TemplateResponse('core', 'exception', $params, 'guest');
222
		}
223
224
		return new TemplateResponse('core', '403', [], 'guest');
0 ignored issues
show
Unused Code introduced by
return new \OCP\AppFrame...03', array(), 'guest'); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
225
	}
226
227
	/**
228
	 * @PublicPage
229
	 *
230
	 * @param string $shareToken
231
	 * @param string $fileName
232
	 * @return TemplateResponse
233
	 * @throws \Exception
234
	 */
235
	public function publicPage($shareToken, $fileName, $fileId) {
236
		try {
237
			$share = $this->shareManager->getShareByToken($shareToken);
238
			// not authenticated ?
239
			if($share->getPassword()){
240
				if (!$this->session->exists('public_link_authenticated')
241
					|| $this->session->get('public_link_authenticated') !== (string)$share->getId()
242
				) {
243
					throw new \Exception('Invalid password');
244
				}
245
			}
246
247
			$node = $share->getNode();
248
			if($node instanceof Folder) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\Folder does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
249
				$item = $node->getById($fileId)[0];
250
			} else {
251
				$item = $node;
252
			}
253
			if ($item instanceof Node) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\Node does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
254
				list($urlSrc, $token) = $this->tokenManager->getToken($item->getId(), $shareToken);
255
				$params = [
256
					'permissions' => $share->getPermissions(),
257
					'title' => $item->getName(),
258
					'fileId' => $item->getId() . '_' . $this->settings->getSystemValue('instanceid'),
259
					'token' => $token,
260
					'urlsrc' => $urlSrc,
261
					'path' => '/',
262
					'instanceId' => $this->settings->getSystemValue('instanceid'),
263
					'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
264
				];
265
266
				$response = new TemplateResponse('richdocuments', 'documents', $params, 'empty');
267
				$policy = new ContentSecurityPolicy();
268
				$policy->addAllowedFrameDomain($this->domainOnly($this->appConfig->getAppValue('wopi_url')));
269
				$policy->allowInlineScript(true);
270
				$response->setContentSecurityPolicy($policy);
271
				return $response;
272
			}
273
		} catch (\Exception $e) {
274
			$this->logger->logException($e, ['app'=>'richdocuments']);
275
			$params = [
276
				'remoteAddr' => $this->request->getRemoteAddress(),
277
				'requestID' => $this->request->getId(),
278
				'debugMode' => $this->settings->getSystemValue('debug'),
279
				'errorClass' => get_class($e),
280
				'errorCode' => $e->getCode(),
281
				'errorMsg' => $e->getMessage(),
282
				'file' => $e->getFile(),
283
				'line' => $e->getLine(),
284
				'trace' => $e->getTraceAsString()
285
			];
286
			return new TemplateResponse('core', 'exception', $params, 'guest');
287
		}
288
289
		return new TemplateResponse('core', '403', [], 'guest');
290
	}
291
292
	/**
293
	 * @NoAdminRequired
294
	 *
295
	 * @param string $mimetype
296
	 * @param string $filename
297
	 * @param string $dir
298
	 * @return JSONResponse
299
	 */
300
	public function create($mimetype,
301
						   $filename,
302
						   $dir = '/'){
303
304
		$root = $this->rootFolder->getUserFolder($this->uid);
305
		try {
306
			/** @var Folder $folder */
307
			$folder = $root->get($dir);
308
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
309
			return new JSONResponse([
310
					'status' => 'error',
311
					'message' => $this->l10n->t('Can\'t create document')
312
			], Http::STATUS_BAD_REQUEST);
313
		}
314
315 View Code Duplication
		if (!($folder instanceof Folder)) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\Folder does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
316
			return new JSONResponse([
317
				'status' => 'error',
318
				'message' => $this->l10n->t('Can\'t create document')
319
			], Http::STATUS_BAD_REQUEST);
320
		}
321
322
		$basename = $this->l10n->t('New Document.odt');
323
		switch ($mimetype) {
324
			case 'application/vnd.oasis.opendocument.spreadsheet':
325
				$basename = $this->l10n->t('New Spreadsheet.ods');
326
				break;
327
			case 'application/vnd.oasis.opendocument.presentation':
328
				$basename = $this->l10n->t('New Presentation.odp');
329
				break;
330
			case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
331
				$basename = $this->l10n->t('New Document.docx');
332
				break;
333
			case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
334
				$basename = $this->l10n->t('New Spreadsheet.xlsx');
335
				break;
336
			case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
337
				$basename = $this->l10n->t('New Presentation.pptx');
338
				break;
339
			default:
340
				// to be safe
341
				$mimetype = 'application/vnd.oasis.opendocument.text';
342
				break;
343
		}
344
345
		if (!$filename){
346
			$filename = Helper::getNewFileName($folder, $basename);
347
		}
348
349 View Code Duplication
		if ($folder->nodeExists($filename)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
350
			return new JSONResponse([
351
				'status' => 'error',
352
				'message' => $this->l10n->t('Document already exists')
353
			], Http::STATUS_BAD_REQUEST);
354
		}
355
356
		try {
357
			$file = $folder->newFile($filename);
358
		} catch (NotPermittedException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\NotPermittedException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
359
			return new JSONResponse([
360
				'status' => 'error',
361
				'message' => $this->l10n->t('Not allowed to create document')
362
			], Http::STATUS_BAD_REQUEST);
363
		}
364
365
		$content = '';
366
		if (class_exists(TemplateManager::class)){
367
			$manager = \OC_Helper::getFileTemplateManager();
368
			$content = $manager->getTemplate($mimetype);
369
		}
370
371
		if (!$content){
372
			$content = file_get_contents(dirname(dirname(__DIR__)) . self::ODT_TEMPLATE_PATH);
373
		}
374
375
		if ($content) {
376
			$file->putContent($content);
377
378
			return new JSONResponse([
379
				'status' => 'success',
380
				'data' => \OCA\Files\Helper::formatFileInfo($file->getFileInfo())
381
			]);
382
		}
383
384
385
		return new JSONResponse([
386
			'status' => 'error',
387
			'message' => $this->l10n->t('Can\'t create document')
388
		]);
389
	}
390
}
391