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

github.com/nextcloud/richdocuments.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2019-05-23 17:02:31 +0300
committerJulius Härtl <jus@bitgrid.net>2019-12-18 11:54:06 +0300
commitedb200299d513184b6bf6bd84936b951c288cb89 (patch)
tree7e1057f8b2ab9ec1fb30a3f19fd60c5b16604aac /lib
parent6ecc8499f9d0ebc20c15125f4bde959d2d658e12 (diff)
Start with new template creation mechanism
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/Capabilities.php3
-rw-r--r--lib/Controller/DirectViewController.php9
-rw-r--r--lib/Controller/DocumentController.php9
-rw-r--r--lib/Controller/WopiController.php66
-rw-r--r--lib/Db/Direct.php6
-rw-r--r--lib/Db/Wopi.php10
-rw-r--r--lib/Db/WopiMapper.php5
-rw-r--r--lib/Preview/Office.php2
-rw-r--r--lib/Service/CapabilitiesService.php31
-rw-r--r--lib/TokenManager.php46
10 files changed, 156 insertions, 31 deletions
diff --git a/lib/Capabilities.php b/lib/Capabilities.php
index 90094269..43eb427b 100644
--- a/lib/Capabilities.php
+++ b/lib/Capabilities.php
@@ -105,13 +105,14 @@ class Capabilities implements ICapability {
'mimetypesNoDefaultOpen' => self::MIMETYPES_OPTIONAL,
'collabora' => $collaboraCapabilities,
'direct_editing' => isset($collaboraCapabilities['hasMobileSupport']) ? : false,
- 'templates' => isset($collaboraCapabilities['hasTemplateSaveAs']) ? : false,
+ 'templates' => isset($collaboraCapabilities['hasTemplateSaveAs']) || isset($collaboraCapabilities['hasTemplateSource']) ? : false,
'productName' => isset($collaboraCapabilities['productName']) ? $collaboraCapabilities['productName'] : $this->l10n->t('Collabora Online'),
],
];
}
/**
+ * TODO: use CapabilitiesService
* @return array
* @throws \OCP\Files\NotPermittedException
*/
diff --git a/lib/Controller/DirectViewController.php b/lib/Controller/DirectViewController.php
index b392fa8e..62dec909 100644
--- a/lib/Controller/DirectViewController.php
+++ b/lib/Controller/DirectViewController.php
@@ -114,7 +114,8 @@ class DirectViewController extends Controller {
}
try {
- list($urlSrc, $token) = $this->tokenManager->getTokenForTemplate($item, $direct->getUid(), $direct->getTemplateDestination(), true);
+
+ list($urlSrc, $wopi) = $this->tokenManager->getTokenForTemplate($item, $direct->getUid(), $direct->getTemplateDestination(), true);
} catch (\Exception $e) {
return new JSONResponse([], Http::STATUS_BAD_REQUEST);
}
@@ -136,7 +137,7 @@ class DirectViewController extends Controller {
return $response;
}
- list($urlSrc, $token) = $this->tokenManager->getToken($item->getId(), null, $direct->getUid(), true);
+ list($urlSrc, $token, $wopi) = $this->tokenManager->getToken($item->getId(), null, $direct->getUid(), true);
} catch (\Exception $e) {
$params = [
'errors' => [['error' => $e->getMessage()]]
@@ -151,8 +152,8 @@ class DirectViewController extends Controller {
$params = [
'permissions' => $item->getPermissions(),
'title' => $item->getName(),
- 'fileId' => $item->getId() . '_' . $this->config->getSystemValue('instanceid'),
- 'token' => $token,
+ 'fileId' => $wopi->getFileid() . '_' . $this->config->getSystemValue('instanceid'),
+ 'token' => $wopi->getToken(),
'urlsrc' => $urlSrc,
'path' => $relativePath,
'instanceId' => $this->config->getSystemValue('instanceid'),
diff --git a/lib/Controller/DocumentController.php b/lib/Controller/DocumentController.php
index dd6db804..ca6eb0fd 100644
--- a/lib/Controller/DocumentController.php
+++ b/lib/Controller/DocumentController.php
@@ -306,13 +306,16 @@ class DocumentController extends Controller {
$file = $folder->newFile($fileName);
$template = $this->templateManager->get($templateId);
- list($urlSrc, $token) = $this->tokenManager->getTokenForTemplate($template, $this->uid, $file->getId());
+ list($urlSrc, $wopi) = $this->tokenManager->getTokenForTemplate($template, $this->uid, $file->getId());
+
+ $wopiFileId = $template->getId() . '-' . $file->getId() . '_' . $this->settings->getSystemValue('instanceid');
+ $wopiFileId = $wopi->getFileid() . '_' . $this->settings->getSystemValue('instanceid');
$params = [
'permissions' => $template->getPermissions(),
'title' => $fileName,
- 'fileId' => $template->getId() . '-' . $file->getId() . '_' . $this->settings->getSystemValue('instanceid'),
- 'token' => $token,
+ 'fileId' => $wopiFileId,
+ 'token' => $wopi->getToken(),
'urlsrc' => $urlSrc,
'path' => $userFolder->getRelativePath($file->getPath()),
'instanceId' => $this->settings->getSystemValue('instanceid'),
diff --git a/lib/Controller/WopiController.php b/lib/Controller/WopiController.php
index e32eea51..d0ffc771 100644
--- a/lib/Controller/WopiController.php
+++ b/lib/Controller/WopiController.php
@@ -202,12 +202,21 @@ class WopiController extends Controller {
];
$watermarkTemplate = $this->appConfig->getAppValue('watermark_text');
- $response['WatermarkText'] = preg_replace_callback('/{(.+?)}/', function($matches) use ($replacements)
- {
+ $response['WatermarkText'] = preg_replace_callback('/{(.+?)}/', function ($matches) use ($replacements) {
return $replacements[$matches[1]];
}, $watermarkTemplate);
}
+ /**
+ * New approach for generating files from templates by creating an empty file
+ * and providing an URL which returns the actual templyte
+ */
+ if ($wopi->hasTemplateId()) {
+ $templateUrl = 'index.php/apps/richdocuments/wopi/template/' . $wopi->getTemplateId() . '?access_token=' . $wopi->getToken();
+ $templateUrl = $this->urlGenerator->getAbsoluteURL($templateUrl);
+ $response['TemplateSource'] = $templateUrl;
+ }
+
$user = $this->userManager->get($wopi->getEditorUid());
if($user !== null && $user->getAvatarImage(32) !== null) {
$response['UserExtraInfo']['avatar'] = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $wopi->getEditorUid(), 'size' => 32]);
@@ -387,8 +396,11 @@ class WopiController extends Controller {
if ($isPutRelative) {
// the new file needs to be installed in the current user dir
$userFolder = $this->rootFolder->getUserFolder($wopi->getEditorUid());
- $file = $userFolder->getById($fileId)[0];
-
+ $file = $userFolder->getById($fileId);
+ if (count($file) === 0) {
+ return new JSONResponse([], Http::STATUS_NOT_FOUND);
+ }
+ $file = $file[0];
$suggested = $this->request->getHeader('X-WOPI-SuggestedTarget');
$suggested = iconv('utf-7', 'utf-8', $suggested);
@@ -421,10 +433,11 @@ class WopiController extends Controller {
} else {
$file = $this->getFileForWopiToken($wopi);
$wopiHeaderTime = $this->request->getHeader('X-LOOL-WOPI-Timestamp');
- if ($wopiHeaderTime !== null && $wopiHeaderTime !== Helper::toISO8601($file->getMTime())) {
+
+ if ($wopiHeaderTime !== null && $wopiHeaderTime !== Helper::toISO8601($file->getMTime() ?? 0)) {
$this->logger->debug('Document timestamp mismatch ! WOPI client says mtime {headerTime} but storage says {storageTime}', [
'headerTime' => $wopiHeaderTime,
- 'storageTime' => Helper::toISO8601($file->getMTime())
+ 'storageTime' => Helper::toISO8601($file->getMTime() ?? 0)
]);
// Tell WOPI client about this conflict.
return new JSONResponse(['LOOLStatusCode' => self::LOOL_STATUS_DOC_CHANGED], Http::STATUS_CONFLICT);
@@ -538,7 +551,11 @@ class WopiController extends Controller {
$path = $this->rootFolder->getNonExistingName($path);
$file = $file->move($path);
} else {
- $file = $userFolder->getById($fileId)[0];
+ $file = $userFolder->getById($fileId);
+ if (count($file) === 0) {
+ return new JSONResponse([], Http::STATUS_NOT_FOUND);
+ }
+ $file = $file[0];
$suggested = $this->request->getHeader('X-WOPI-SuggestedTarget');
$suggested = iconv('utf-7', 'utf-8', $suggested);
@@ -658,4 +675,39 @@ class WopiController extends Controller {
}
return $file;
}
+
+ /**
+ * Endpoint to return the template file that is requested by collabora to create a new document
+ *
+ * @PublicPage
+ * @NoCSRFRequired
+ *
+ * @param $fileId
+ * @param $access_token
+ * @return JSONResponse|StreamResponse
+ */
+ public function getTemplate($fileId, $access_token) {
+ try {
+ $wopi = $this->wopiMapper->getPathForToken($access_token);
+ } catch (DoesNotExistException $e) {
+ return new JSONResponse([], Http::STATUS_FORBIDDEN);
+ }
+
+ if ((int)$fileId !== $wopi->getTemplateId()) {
+ return new JSONResponse([], Http::STATUS_FORBIDDEN);
+ }
+
+ try {
+ $this->templateManager->setUserId($wopi->getOwnerUid());
+ $file = $this->templateManager->get($wopi->getTemplateId());
+ $response = new StreamResponse($file->fopen('rb'));
+ $response->addHeader('Content-Disposition', 'attachment');
+ $response->addHeader('Content-Type', 'application/octet-stream');
+ return $response;
+ } catch (\Exception $e) {
+ $this->logger->logException($e, ['level' => ILogger::ERROR, 'app' => 'richdocuments', 'message' => 'getTemplate failed']);
+ return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
}
diff --git a/lib/Db/Direct.php b/lib/Db/Direct.php
index 437df370..92dcbe05 100644
--- a/lib/Db/Direct.php
+++ b/lib/Db/Direct.php
@@ -36,6 +36,8 @@ use OCP\AppFramework\Db\Entity;
* @method int getTimestamp()
* @method void setTemplateDestination(int $fileId)
* @method int getTemplateDestination()
+ * @method void setTemplateId(int $fileId)
+ * @method int getTemplateId()
*/
class Direct extends Entity {
/** @var string */
@@ -53,11 +55,15 @@ class Direct extends Entity {
/** @var int */
protected $templateDestination;
+ /** @var int */
+ protected $templateId;
+
public function __construct() {
$this->addType('token', 'string');
$this->addType('uid', 'string');
$this->addType('fileid', 'int');
$this->addType('timestamp', 'int');
$this->addType('template_destination', 'int');
+ $this->addType('template_id', 'int');
}
}
diff --git a/lib/Db/Wopi.php b/lib/Db/Wopi.php
index f8d8143b..fab36964 100644
--- a/lib/Db/Wopi.php
+++ b/lib/Db/Wopi.php
@@ -49,6 +49,8 @@ use OCP\AppFramework\Db\Entity;
* @method string getGuestDisplayname()
* @method void setTemplateDestination(int $fileId)
* @method int getTemplateDestination()
+ * @method void setTemplateId(int $fileId)
+ * @method int getTemplateId()
*/
class Wopi extends Entity {
/** @var string */
@@ -81,6 +83,9 @@ class Wopi extends Entity {
/** @var int */
protected $templateDestination;
+ /** @var int */
+ protected $templateId;
+
/** @var bool */
protected $hideDownload;
@@ -107,6 +112,7 @@ class Wopi extends Entity {
$this->addType('expiry', 'int');
$this->addType('guest_displayname', 'string');
$this->addType('templateDestination', 'int');
+ $this->addType('templateId', 'int');
$this->addType('hide_download', 'bool');
$this->addType('direct', 'bool');
@@ -116,4 +122,8 @@ class Wopi extends Entity {
return $this->getTemplateDestination() !== 0 && $this->getTemplateDestination() !== null;
}
+ public function hasTemplateId() {
+ return $this->getTemplateId() !== 0 && $this->getTemplateId() !== null;
+ }
+
}
diff --git a/lib/Db/WopiMapper.php b/lib/Db/WopiMapper.php
index e9056730..e5cf8665 100644
--- a/lib/Db/WopiMapper.php
+++ b/lib/Db/WopiMapper.php
@@ -64,7 +64,7 @@ class WopiMapper extends Mapper {
* @param int $templateDestination
* @return Wopi
*/
- public function generateFileToken($fileId, $owner, $editor, $version, $updatable, $serverHost, $guestDisplayname, $templateDestination = 0, $hideDownload = false, $direct = false, $isRemoteToken = false) {
+ public function generateFileToken($fileId, $owner, $editor, $version, $updatable, $serverHost, $guestDisplayname, $templateDestination = 0, $hideDownload = false, $direct = false, $isRemoteToken = false, $templateId = 0) {
$token = $this->random->generate(32, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
$wopi = Wopi::fromParams([
@@ -80,7 +80,8 @@ class WopiMapper extends Mapper {
'templateDestination' => $templateDestination,
'hideDownload' => $hideDownload,
'direct' => $direct,
- 'isRemoteToken' => $isRemoteToken
+ 'isRemoteToken' => $isRemoteToken,
+ 'templateId' => $templateId,
]);
/** @var Wopi $wopi */
diff --git a/lib/Preview/Office.php b/lib/Preview/Office.php
index 6b43c045..f3f8af01 100644
--- a/lib/Preview/Office.php
+++ b/lib/Preview/Office.php
@@ -21,6 +21,8 @@
*/
namespace OCA\Richdocuments\Preview;
+use GuzzleHttp\Psr7\LimitStream;
+use function GuzzleHttp\Psr7\stream_for;
use OC\Preview\Provider;
use OCA\Richdocuments\Capabilities;
use OCP\Http\Client\IClientService;
diff --git a/lib/Service/CapabilitiesService.php b/lib/Service/CapabilitiesService.php
index 82202ce4..fb8856c4 100644
--- a/lib/Service/CapabilitiesService.php
+++ b/lib/Service/CapabilitiesService.php
@@ -38,6 +38,8 @@ class CapabilitiesService {
private $clientService;
/** @var ISimpleFolder */
private $appData;
+ /** @var array */
+ private $capabilities;
public function __construct(IConfig $config, IClientService $clientService, IAppData $appData) {
$this->config = $config;
@@ -49,6 +51,34 @@ class CapabilitiesService {
}
}
+
+ public function getCapabilities() {
+ if ($this->capabilities) {
+ return $this->capabilities;
+ }
+ try {
+ $file = $this->appData->getFile('capabilities.json');
+ $decodedFile = \json_decode($file->getContent(), true);
+ } catch (NotFoundException $e) {
+ return [];
+ }
+
+ if (!is_array($decodedFile)) {
+ return [];
+ }
+ $this->capabilities = $decodedFile;
+
+ return $this->capabilities;
+ }
+
+ public function hasTemplateSaveAs() {
+ return $this->getCapabilities()['hasTemplateSaveAs'] ?? false;
+ }
+
+ public function hasTemplateSource() {
+ return $this->getCapabilities()['hasTemplateSource'] ?? false;
+ }
+
private function getFile() {
try {
$file = $this->appData->getFile('capabilities.json');
@@ -103,4 +133,5 @@ class CapabilitiesService {
return $ret;
}
+
}
diff --git a/lib/TokenManager.php b/lib/TokenManager.php
index 33233ddb..bb0b4f6a 100644
--- a/lib/TokenManager.php
+++ b/lib/TokenManager.php
@@ -25,6 +25,7 @@ use OC\Share\Constants;
use OCA\Richdocuments\Db\WopiMapper;
use OCA\Richdocuments\Helper;
use OCA\Richdocuments\Db\Wopi;
+use OCA\Richdocuments\Service\CapabilitiesService;
use OCA\Richdocuments\WOPI\Parser;
use OCP\Files\File;
use OCP\Files\IRootFolder;
@@ -58,6 +59,8 @@ class TokenManager {
private $userManager;
/** @var IGroupManager */
private $groupManager;
+ /** @var CapabilitiesService */
+ private $capabilitiesService;
/**
* @param IRootFolder $rootFolder
@@ -73,6 +76,7 @@ class TokenManager {
IManager $shareManager,
IURLGenerator $urlGenerator,
Parser $wopiParser,
+ CapabilitiesService $capabilitiesService,
AppConfig $appConfig,
$UserId,
WopiMapper $wopiMapper,
@@ -83,6 +87,7 @@ class TokenManager {
$this->shareManager = $shareManager;
$this->urlGenerator = $urlGenerator;
$this->wopiParser = $wopiParser;
+ $this->capabilitiesService = $capabilitiesService;
$this->appConfig = $appConfig;
$this->trans = $trans;
$this->userId = $UserId;
@@ -99,11 +104,11 @@ class TokenManager {
* @throws \Exception
*/
public function getToken($fileId, $shareToken = null, $editoruid = null, $direct = false, $isRemoteToken = false) {
- list($fileId,, $version) = Helper::parseFileId($fileId);
+ list($fileId, , $version) = Helper::parseFileId($fileId);
$owneruid = null;
$hideDownload = false;
// if the user is not logged-in do use the sharers storage
- if($shareToken !== null) {
+ if ($shareToken !== null) {
/** @var File $file */
$rootFolder = $this->rootFolder;
$share = $this->shareManager->getShareByToken($shareToken);
@@ -132,12 +137,12 @@ class TokenManager {
$editorUser = $this->userManager->get($editoruid);
if ($updatable && count($editGroups) > 0 && $editorUser) {
$updatable = false;
- foreach($editGroups as $editGroup) {
- $editorGroup = $this->groupManager->get($editGroup);
- if ($editorGroup !== null && $editorGroup->inGroup($editorUser)) {
+ foreach ($editGroups as $editGroup) {
+ $editorGroup = $this->groupManager->get($editGroup);
+ if ($editorGroup !== null && $editorGroup->inGroup($editorUser)) {
$updatable = true;
break;
- }
+ }
}
}
} catch (\Exception $e) {
@@ -174,7 +179,7 @@ class TokenManager {
$serverHost = $this->urlGenerator->getAbsoluteURL('/');//$this->request->getServerProtocol() . '://' . $this->request->getServerHost();
- $guest_name = NULL;
+ $guest_name = null;
if ($this->userId === null) {
if (isset($_COOKIE['guestUser']) && $_COOKIE['guestUser'] !== '') {
$guest_name = $this->trans->t('%s (Guest)', Util::sanitizeHTML($_COOKIE['guestUser']));
@@ -188,11 +193,11 @@ class TokenManager {
try {
return [
- $this->wopiParser->getUrlSrc($file->getMimeType())['urlsrc'],
+ $this->wopiParser->getUrlSrc($file->getMimeType())['urlsrc'], // url src might not be found ehre
$wopi->getToken(),
$wopi
];
- } catch (\Exception $e){
+ } catch (\Exception $e) {
throw $e;
}
}
@@ -208,10 +213,18 @@ class TokenManager {
return $wopi;
}
- public function getTokenForTemplate(File $file, $userId, $templateDestination, $direct = false) {
+ public function getTokenForTemplate(File $templateFile, $userId, $targetFileId, $direct = false) {
$owneruid = $userId;
$editoruid = $userId;
- $updatable = $file->isUpdateable();
+ $rootFolder = $this->rootFolder->getUserFolder($editoruid);
+ /** @var File $targetFile */
+ $targetFile = $rootFolder->getById($targetFileId);
+ $targetFile = $targetFile[0] ?? null;
+ if (!$targetFile) {
+ // TODO: Exception
+ return null;
+ }
+ $updatable = $targetFile->isUpdateable();
// Check if the editor (user who is accessing) is in editable group
// UserCanWrite only if
// 1. No edit groups are set or
@@ -231,11 +244,16 @@ class TokenManager {
$serverHost = $this->urlGenerator->getAbsoluteURL('/');
- $wopi = $this->wopiMapper->generateFileToken($file->getId(), $owneruid, $editoruid, 0, (int)$updatable, $serverHost, null, $templateDestination, $direct);
+ if ($this->capabilitiesService->hasTemplateSource()) {
+ $wopi = $this->wopiMapper->generateFileToken($targetFile->getId(), $owneruid, $editoruid, 0, (int)$updatable, $serverHost, null, 0, false, false, false, $templateFile->getId());
+ } else {
+ // Legacy way of creating new documents from a template
+ $wopi = $this->wopiMapper->generateFileToken($templateFile->getId(), $owneruid, $editoruid, 0, (int)$updatable, $serverHost, null, $targetFile->getId(), $direct);
+ }
return [
- $this->wopiParser->getUrlSrc($file->getMimeType())['urlsrc'],
- $wopi->getToken(),
+ $this->wopiParser->getUrlSrc($templateFile->getMimeType())['urlsrc'],
+ $wopi
];
}