Completed
Push — master ( 125f9f...2c140b )
by Julius
02:26 queued 10s
created

DocumentController   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 517
Duplicated Lines 11.41 %

Coupling/Cohesion

Components 1
Dependencies 23

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 54
lcom 1
cbo 23
dl 59
loc 517
ccs 0
cts 356
cp 0
rs 6.4799
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 28 28 1
B extAppGetData() 0 37 6
A domainOnly() 0 7 4
A open() 0 32 5
B index() 5 56 5
A template() 0 40 4
B publicPage() 7 48 7
B remote() 7 59 8
C create() 12 90 14

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DocumentController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DocumentController, and based on these observations, apply Extract Interface, too.

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\Db\WopiMapper;
15
use OCA\Richdocuments\Service\FederationService;
16
use OCA\Richdocuments\TokenManager;
17
use OCA\Richdocuments\WOPI\Parser;
18
use \OCP\AppFramework\Controller;
19
use OCP\AppFramework\Http;
20
use OCP\AppFramework\Http\JSONResponse;
21
use OCP\AppFramework\Http\RedirectResponse;
22
use OCP\Constants;
23
use OCP\Files\File;
24
use OCP\Files\Folder;
25
use OCP\Files\GenericFileException;
26
use OCP\Files\IRootFolder;
27
use OCP\Files\Node;
28
use OCP\Files\NotFoundException;
29
use OCP\Files\NotPermittedException;
30
use \OCP\IRequest;
31
use \OCP\IConfig;
32
use \OCP\IL10N;
33
use \OCP\ILogger;
34
use \OCP\AppFramework\Http\ContentSecurityPolicy;
35
use \OCP\AppFramework\Http\TemplateResponse;
36
use \OCA\Richdocuments\AppConfig;
37
use \OCA\Richdocuments\Helper;
38
use OCP\ISession;
39
use OCP\Share\IManager;
40
use OC\Files\Type\TemplateManager;
41
42
class DocumentController extends Controller {
43
	/** @var string */
44
	private $uid;
45
	/** @var IL10N */
46
	private $l10n;
47
	/** @var IConfig */
48
	private $settings;
49
	/** @var AppConfig */
50
	private $appConfig;
51
	/** @var ILogger */
52
	private $logger;
53
	/** @var IManager */
54
	private $shareManager;
55
	/** @var TokenManager */
56
	private $tokenManager;
57
	/** @var ISession */
58
	private $session;
59
	/** @var IRootFolder */
60
	private $rootFolder;
61
	/** @var \OCA\Richdocuments\TemplateManager */
62
	private $templateManager;
63
	/** @var FederationService */
64
	private $federationService;
65
66
	const ODT_TEMPLATE_PATH = '/assets/odttemplate.odt';
67
68
	/**
69
	 * @param string $appName
70
	 * @param IRequest $request
71
	 * @param IConfig $settings
72
	 * @param AppConfig $appConfig
73
	 * @param IL10N $l10n
74
	 * @param IManager $shareManager
75
	 * @param TokenManager $tokenManager
76
	 * @param IRootFolder $rootFolder
77
	 * @param ISession $session
78
	 * @param string $UserId
79
	 * @param ILogger $logger
80
	 */
81 View Code Duplication
	public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
82
		$appName,
83
		IRequest $request,
84
		IConfig $settings,
85
		AppConfig $appConfig,
86
		IL10N $l10n,
87
		IManager $shareManager,
88
		TokenManager $tokenManager,
89
		IRootFolder $rootFolder,
90
		ISession $session,
91
		$UserId,
92
		ILogger $logger,
93
		\OCA\Richdocuments\TemplateManager $templateManager,
94
		FederationService $federationService
95
	) {
96
		parent::__construct($appName, $request);
97
		$this->uid = $UserId;
98
		$this->l10n = $l10n;
99
		$this->settings = $settings;
100
		$this->appConfig = $appConfig;
101
		$this->shareManager = $shareManager;
102
		$this->tokenManager = $tokenManager;
103
		$this->rootFolder = $rootFolder;
104
		$this->session = $session;
105
		$this->logger = $logger;
106
		$this->templateManager = $templateManager;
107
		$this->federationService = $federationService;
108
	}
109
110
	/**
111
	 * @PublicPage
112
	 * @NoCSRFRequired
113
	 *
114
	 * Returns the access_token and urlsrc for WOPI access for given $fileId
115
	 * Requests is accepted only when a secret_token is provided set by admin in
116
	 * settings page
117
	 *
118
	 * @param string $fileId
119
	 * @return array access_token, urlsrc
120
	 */
121
	public function extAppGetData($fileId) {
122
		$secretToken = $this->request->getParam('secret_token');
123
		$apps = array_filter(explode(',', $this->appConfig->getAppValue('external_apps')));
124
		foreach($apps as $app) {
125
			if ($app !== '' && $secretToken === $app) {
126
				$appName = explode(':', $app);
127
				$this->logger->debug('External app "{extApp}" authenticated; issuing access token for fileId {fileId}', [
128
					'app' => $this->appName,
129
					'extApp' => $appName[0],
130
					'fileId' => $fileId
131
				]);
132
				try {
133
					$folder = $this->rootFolder->getUserFolder($this->uid);
134
					$item = $folder->getById($fileId)[0];
135
					if(!($item instanceof Node)) {
136
						throw new \Exception();
137
					}
138
					list($urlSrc, $token) = $this->tokenManager->getToken($item->getId());
139
					return [
140
						'status' => 'success',
141
						'urlsrc' => $urlSrc,
142
						'token' => $token
143
					];
144
				} catch (\Exception $e) {
145
					$this->logger->logException($e, ['app'=>'richdocuments']);
0 ignored issues
show
Documentation introduced by
$e is of type object<Exception>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
146
					$params = [
147
						'errors' => [['error' => $e->getMessage()]]
148
					];
149
					return new TemplateResponse('core', 'error', $params, 'guest');
150
				}
151
			}
152
		}
153
		return [
154
			'status' => 'error',
155
			'message' => 'Permission denied'
156
		];
157
	}
158
159
	/**
160
	 * Strips the path and query parameters from the URL.
161
	 *
162
	 * @param string $url
163
	 * @return string
164
	 */
165
	private function domainOnly($url) {
166
		$parsed_url = parse_url($url);
167
		$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
168
		$host   = isset($parsed_url['host']) ? $parsed_url['host'] : '';
169
		$port   = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
170
		return "$scheme$host$port";
171
	}
172
173
	/**
174
	 * Redirect to the files app with proper CSP headers set for federated editing
175
	 * This is a workaround since we cannot set a nonce for allowing dynamic URLs in the richdocument iframe
176
	 *
177
	 * @NoAdminRequired
178
	 * @NoCSRFRequired
179
	 */
180
	public function open($fileId) {
181
		try {
182
			$folder = $this->rootFolder->getUserFolder($this->uid);
183
			$item = $folder->getById($fileId)[0];
184
			if (!($item instanceof File)) {
185
				throw new \Exception('Node is not a file');
186
			}
187
188
			if ($item->getStorage()->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class)) {
189
				$remote = $item->getStorage()->getRemote();
0 ignored issues
show
Bug introduced by
The method getRemote() does not seem to exist on object<OCP\Files\Storage>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
190
				$remoteCollabora = $this->federationService->getRemoteCollaboraURL($remote);
191
				if ($remoteCollabora !== '') {
192
					$absolute = $item->getParent()->getPath();
193
					$relative = $folder->getRelativePath($absolute);
194
					$url = '/index.php/apps/files?dir=' . $relative .
195
						'&richdocuments_open=' . $item->getName() .
196
						'&richdocuments_fileId=' . $fileId .
197
						'&richdocuments_remote_access=' . $remote;
198
					return new RedirectResponse($url);
199
				}
200
				$this->logger->warning('Failed to connect to remote collabora instance for ' . $fileId);
201
			}
202
		} catch (\Exception $e) {
203
			$this->logger->logException($e, ['app'=>'richdocuments']);
0 ignored issues
show
Documentation introduced by
$e is of type object<Exception>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
204
			$params = [
205
				'errors' => [['error' => $e->getMessage()]]
206
			];
207
			return new TemplateResponse('core', 'error', $params, 'guest');
208
		}
209
210
		return new TemplateResponse('core', '403', [], 'guest');
211
	}
212
213
	/**
214
	 * @NoAdminRequired
215
	 *
216
	 * @param string $fileId
217
	 * @return RedirectResponse|TemplateResponse
218
	 */
219
	public function index($fileId) {
220
		try {
221
			$folder = $this->rootFolder->getUserFolder($this->uid);
222
			$item = $folder->getById($fileId)[0];
223
			if(!($item instanceof File)) {
224
				throw new \Exception();
225
			}
226
227
			/** Open file from remote collabora */
228
			$federatedUrl = $this->federationService->getRemoteRedirectURL($item);
229 View Code Duplication
			if ($federatedUrl !== null) {
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...
230
				$response = new RedirectResponse($federatedUrl);
231
				$response->addHeader('X-Frame-Options', 'ALLOW');
232
				return $response;
233
			}
234
235
			list($urlSrc, $token) = $this->tokenManager->getToken($item->getId());
236
			$params = [
237
				'permissions' => $item->getPermissions(),
238
				'title' => $item->getName(),
239
				'fileId' => $item->getId() . '_' . $this->settings->getSystemValue('instanceid'),
240
				'token' => $token,
241
				'urlsrc' => $urlSrc,
242
				'path' => $folder->getRelativePath($item->getPath()),
243
				'instanceId' => $this->settings->getSystemValue('instanceid'),
244
				'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
245
				'userId' => $this->uid
246
			];
247
248
			$encryptionManager = \OC::$server->getEncryptionManager();
249
			if ($encryptionManager->isEnabled())
250
			{
251
				// Update the current file to be accessible with system public shared key
252
				$owner = $item->getOwner()->getUID();
253
				$absPath = '/' . $owner . '/' .  $item->getInternalPath();
254
				$accessList = \OC::$server->getEncryptionFilesHelper()->getAccessList($absPath);
255
				$accessList['public'] = true;
256
				$encryptionManager->getEncryptionModule()->update($absPath, $owner, $accessList);
257
			}
258
259
			$response = new TemplateResponse('richdocuments', 'documents', $params, 'empty');
260
			$policy = new ContentSecurityPolicy();
261
			$policy->addAllowedFrameDomain($this->domainOnly($this->appConfig->getAppValue('public_wopi_url')));
262
			$policy->allowInlineScript(true);
0 ignored issues
show
Deprecated Code introduced by
The method OCP\AppFramework\Http\Em...cy::allowInlineScript() has been deprecated with message: 10.0 CSP tokens are now used

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
263
			$response->setContentSecurityPolicy($policy);
264
			return $response;
265
		} catch (\Exception $e) {
266
			$this->logger->logException($e, ['app'=>'richdocuments']);
0 ignored issues
show
Documentation introduced by
$e is of type object<Exception>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
267
			$params = [
268
				'errors' => [['error' => $e->getMessage()]]
269
			];
270
			return new TemplateResponse('core', 'error', $params, 'guest');
271
		}
272
273
		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...
274
	}
275
276
	/**
277
	 * @NoAdminRequired
278
	 *
279
	 * Create a new file from a template
280
	 *
281
	 * @param int $templateId
282
	 * @param string $fileName
283
	 * @param string $dir
284
	 * @return TemplateResponse
285
	 * @throws NotFoundException
286
	 * @throws NotPermittedException
287
	 * @throws \OCP\Files\InvalidPathException
288
	 */
289
	public function template($templateId, $fileName, $dir) {
290
		if (!$this->templateManager->isTemplate($templateId)) {
291
			return new TemplateResponse('core', '403', [], 'guest');
292
		}
293
294
		$userFolder = $this->rootFolder->getUserFolder($this->uid);
295
		try {
296
			$folder = $userFolder->get($dir);
297
		} catch (NotFoundException $e) {
298
			return new TemplateResponse('core', '403', [], 'guest');
299
		}
300
301
		if (!$folder instanceof Folder) {
302
			return new TemplateResponse('core', '403', [], 'guest');
303
		}
304
305
		$file = $folder->newFile($fileName);
306
307
		$template = $this->templateManager->get($templateId);
308
		list($urlSrc, $token) = $this->tokenManager->getTokenForTemplate($template, $this->uid, $file->getId());
309
310
		$params = [
311
			'permissions' => $template->getPermissions(),
312
			'title' => $fileName,
313
			'fileId' => $template->getId() . '_' . $this->settings->getSystemValue('instanceid'),
314
			'token' => $token,
315
			'urlsrc' => $urlSrc,
316
			'path' => $userFolder->getRelativePath($file->getPath()),
317
			'instanceId' => $this->settings->getSystemValue('instanceid'),
318
			'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
319
			'userId' => $this->uid
320
		];
321
322
		$response = new TemplateResponse('richdocuments', 'documents', $params, 'empty');
323
		$policy = new ContentSecurityPolicy();
324
		$policy->addAllowedFrameDomain($this->domainOnly($this->appConfig->getAppValue('public_wopi_url')));
325
		$policy->allowInlineScript(true);
0 ignored issues
show
Deprecated Code introduced by
The method OCP\AppFramework\Http\Em...cy::allowInlineScript() has been deprecated with message: 10.0 CSP tokens are now used

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
326
		$response->setContentSecurityPolicy($policy);
327
		return $response;
328
	}
329
330
	/**
331
	 * @PublicPage
332
	 * @NoCSRFRequired
333
	 *
334
	 * @param string $shareToken
335
	 * @param string $fileName
336
	 * @return TemplateResponse
337
	 * @throws \Exception
338
	 */
339
	public function publicPage($shareToken, $fileName, $fileId) {
0 ignored issues
show
Unused Code introduced by
The parameter $fileName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
340
		try {
341
			$share = $this->shareManager->getShareByToken($shareToken);
342
			// not authenticated ?
343 View Code Duplication
			if($share->getPassword()){
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...
344
				if (!$this->session->exists('public_link_authenticated')
345
					|| $this->session->get('public_link_authenticated') !== (string)$share->getId()
346
				) {
347
					throw new \Exception('Invalid password');
348
				}
349
			}
350
351
			$node = $share->getNode();
352
			if($node instanceof Folder) {
353
				$item = $node->getById($fileId)[0];
354
			} else {
355
				$item = $node;
356
			}
357
			if ($item instanceof Node) {
358
				list($urlSrc, $token) = $this->tokenManager->getToken($item->getId(), $shareToken, $this->uid);
359
				$params = [
360
					'permissions' => $share->getPermissions(),
361
					'title' => $item->getName(),
362
					'fileId' => $item->getId() . '_' . $this->settings->getSystemValue('instanceid'),
363
					'token' => $token,
364
					'urlsrc' => $urlSrc,
365
					'path' => '/',
366
					'instanceId' => $this->settings->getSystemValue('instanceid'),
367
					'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
368
				];
369
370
				$response = new TemplateResponse('richdocuments', 'documents', $params, 'empty');
371
				$policy = new ContentSecurityPolicy();
372
				$policy->addAllowedFrameDomain($this->domainOnly($this->appConfig->getAppValue('public_wopi_url')));
373
				$policy->allowInlineScript(true);
0 ignored issues
show
Deprecated Code introduced by
The method OCP\AppFramework\Http\Em...cy::allowInlineScript() has been deprecated with message: 10.0 CSP tokens are now used

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
374
				$response->setContentSecurityPolicy($policy);
375
				return $response;
376
			}
377
		} catch (\Exception $e) {
378
			$this->logger->logException($e, ['app'=>'richdocuments']);
0 ignored issues
show
Documentation introduced by
$e is of type object<Exception>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
379
			$params = [
380
				'errors' => [['error' => $e->getMessage()]]
381
			];
382
			return new TemplateResponse('core', 'error', $params, 'guest');
383
		}
384
385
		return new TemplateResponse('core', '403', [], 'guest');
386
	}
387
388
	/**
389
	 * @PublicPage
390
	 * @NoCSRFRequired
391
	 *
392
	 * @param string $shareToken
393
	 * @param $remoteServer
394
	 * @param $remoteServerToken
395
	 * @param null $filePath
396
	 * @return TemplateResponse
397
	 */
398
	public function remote($shareToken, $remoteServer, $remoteServerToken, $filePath = null) {
399
		try {
400
			$share = $this->shareManager->getShareByToken($shareToken);
401
			// not authenticated ?
402 View Code Duplication
			if($share->getPassword()){
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...
403
				if (!$this->session->exists('public_link_authenticated')
404
					|| $this->session->get('public_link_authenticated') !== (string)$share->getId()
405
				) {
406
					throw new \Exception('Invalid password');
407
				}
408
			}
409
410
			$node = $share->getNode();
411
			if ($filePath !== null) {
412
				$node = $node->get($filePath);
0 ignored issues
show
Bug introduced by
The method get does only exist in OCP\Files\Folder, but not in OCP\Files\File.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
413
			}
414
415
			if ($node instanceof Node) {
416
				list($urlSrc, $token, $wopi) = $this->tokenManager->getToken($node->getId(), $shareToken, $this->uid);
417
418
				$remoteWopi = $this->federationService->getRemoteFileDetails($remoteServer, $remoteServerToken);
419
				$this->tokenManager->updateToRemoteToken($wopi, $shareToken, $remoteServer, $remoteServerToken, $remoteWopi);
420
421
				$permissions = $share->getPermissions();
422
				if (!$remoteWopi['canwrite']) {
423
					$permissions = $permissions & ~ Constants::PERMISSION_UPDATE;
424
				}
425
426
				$params = [
427
					'permissions' => $permissions,
428
					'title' => $node->getName(),
429
					'fileId' => $node->getId() . '_' . $this->settings->getSystemValue('instanceid'),
430
					'token' => $token,
431
					'urlsrc' => $urlSrc,
432
					'path' => '/',
433
					'instanceId' => $this->settings->getSystemValue('instanceid'),
434
					'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
435
					'userId' => $remoteWopi['editorUid'] . '@' . $remoteServer
436
				];
437
438
				$response = new TemplateResponse('richdocuments', 'documents', $params, 'empty');
439
				$policy = new ContentSecurityPolicy();
440
				$policy->addAllowedFrameDomain($this->domainOnly($this->appConfig->getAppValue('wopi_url')));
441
				$policy->allowInlineScript(true);
0 ignored issues
show
Deprecated Code introduced by
The method OCP\AppFramework\Http\Em...cy::allowInlineScript() has been deprecated with message: 10.0 CSP tokens are now used

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
442
				$policy->addAllowedFrameAncestorDomain('https://*');
443
				$response->setContentSecurityPolicy($policy);
444
				$response->addHeader('X-Frame-Options', 'ALLOW');
445
				return $response;
446
			}
447
		} catch (\Exception $e) {
448
			$this->logger->logException($e, ['app'=>'richdocuments']);
0 ignored issues
show
Documentation introduced by
$e is of type object<Exception>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
449
			$params = [
450
				'errors' => [['error' => $e->getMessage()]]
451
			];
452
			return new TemplateResponse('core', 'error', $params, 'guest');
453
		}
454
455
		return new TemplateResponse('core', '403', [], 'guest');
456
	}
457
458
	/**
459
	 * @NoAdminRequired
460
	 *
461
	 * @param string $mimetype
462
	 * @param string $filename
463
	 * @param string $dir
464
	 * @return JSONResponse
465
	 * @throws NotPermittedException
466
	 * @throws GenericFileException
467
	 */
468
	public function create($mimetype,
469
						   $filename,
470
						   $dir = '/'){
471
472
		$root = $this->rootFolder->getUserFolder($this->uid);
473
		try {
474
			/** @var Folder $folder */
475
			$folder = $root->get($dir);
476
		} catch (NotFoundException $e) {
477
			return new JSONResponse([
478
					'status' => 'error',
479
					'message' => $this->l10n->t('Can\'t create document')
480
			], Http::STATUS_BAD_REQUEST);
481
		}
482
483 View Code Duplication
		if (!($folder instanceof Folder)) {
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...
484
			return new JSONResponse([
485
				'status' => 'error',
486
				'message' => $this->l10n->t('Can\'t create document')
487
			], Http::STATUS_BAD_REQUEST);
488
		}
489
490
		$basename = $this->l10n->t('New Document.odt');
491
		switch ($mimetype) {
492
			case 'application/vnd.oasis.opendocument.spreadsheet':
493
				$basename = $this->l10n->t('New Spreadsheet.ods');
494
				break;
495
			case 'application/vnd.oasis.opendocument.presentation':
496
				$basename = $this->l10n->t('New Presentation.odp');
497
				break;
498
			case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
499
				$basename = $this->l10n->t('New Document.docx');
500
				break;
501
			case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
502
				$basename = $this->l10n->t('New Spreadsheet.xlsx');
503
				break;
504
			case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
505
				$basename = $this->l10n->t('New Presentation.pptx');
506
				break;
507
			default:
508
				// to be safe
509
				$mimetype = 'application/vnd.oasis.opendocument.text';
510
				break;
511
		}
512
513
		if (!$filename){
514
			$filename = Helper::getNewFileName($folder, $basename);
515
		}
516
517 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...
518
			return new JSONResponse([
519
				'status' => 'error',
520
				'message' => $this->l10n->t('Document already exists')
521
			], Http::STATUS_BAD_REQUEST);
522
		}
523
524
		try {
525
			$file = $folder->newFile($filename);
526
		} catch (NotPermittedException $e) {
527
			return new JSONResponse([
528
				'status' => 'error',
529
				'message' => $this->l10n->t('Not allowed to create document')
530
			], Http::STATUS_BAD_REQUEST);
531
		}
532
533
		$content = '';
534
		if (class_exists(TemplateManager::class)){
535
			$manager = \OC_Helper::getFileTemplateManager();
536
			$content = $manager->getTemplate($mimetype);
537
		}
538
539
		if (!$content){
540
			$content = file_get_contents(dirname(dirname(__DIR__)) . self::ODT_TEMPLATE_PATH);
541
		}
542
543
		if ($content) {
544
			$file->putContent($content);
545
546
			return new JSONResponse([
547
				'status' => 'success',
548
				'data' => \OCA\Files\Helper::formatFileInfo($file->getFileInfo())
0 ignored issues
show
Bug introduced by
The method getFileInfo() does not seem to exist on object<OCP\Files\File>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
549
			]);
550
		}
551
552
553
		return new JSONResponse([
554
			'status' => 'error',
555
			'message' => $this->l10n->t('Can\'t create document')
556
		]);
557
	}
558
}
559