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( |
|
|
|
|
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']); |
|
|
|
|
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(); |
|
|
|
|
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']); |
|
|
|
|
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) { |
|
|
|
|
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); |
|
|
|
|
263
|
|
|
$response->setContentSecurityPolicy($policy); |
264
|
|
|
return $response; |
265
|
|
|
} catch (\Exception $e) { |
266
|
|
|
$this->logger->logException($e, ['app'=>'richdocuments']); |
|
|
|
|
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'); |
|
|
|
|
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); |
|
|
|
|
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) { |
|
|
|
|
340
|
|
|
try { |
341
|
|
|
$share = $this->shareManager->getShareByToken($shareToken); |
342
|
|
|
// not authenticated ? |
343
|
|
View Code Duplication |
if($share->getPassword()){ |
|
|
|
|
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); |
|
|
|
|
374
|
|
|
$response->setContentSecurityPolicy($policy); |
375
|
|
|
return $response; |
376
|
|
|
} |
377
|
|
|
} catch (\Exception $e) { |
378
|
|
|
$this->logger->logException($e, ['app'=>'richdocuments']); |
|
|
|
|
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()){ |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
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']); |
|
|
|
|
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)) { |
|
|
|
|
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)) { |
|
|
|
|
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()) |
|
|
|
|
549
|
|
|
]); |
550
|
|
|
} |
551
|
|
|
|
552
|
|
|
|
553
|
|
|
return new JSONResponse([ |
554
|
|
|
'status' => 'error', |
555
|
|
|
'message' => $this->l10n->t('Can\'t create document') |
556
|
|
|
]); |
557
|
|
|
} |
558
|
|
|
} |
559
|
|
|
|
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.