Compare commits

...

46 Commits
master ... nc11

Author SHA1 Message Date
Andras Timar 93f8b0da47 Bump version to 1.11.34 7 years ago
Pranav Kant 3eba8b7644 Use fileId instead of dir
(cherry picked from commit e9f9711421)
7 years ago
Andreas Böhler 909053b299 Fix editing publicly shared documents
(cherry picked from commit c4b794360a)
7 years ago
Andras Timar 29d587293d Delete creator/last modifier name from document templates
(cherry picked from commit 3af4174ce0)
7 years ago
Andras Timar 9d2563d545 Bump version to 1.11.33 7 years ago
Andras Timar 3a8a629d10 Restore 'Enable edit for specific groups' feature, fixes #66
(cherry picked from commit aa4df2e800)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Patrik Kernstock d76740bc75 only edit textfiles when texteditorapp is disabled
Signed-off-by: Patrik Kernstock <info@pkern.at>
(cherry picked from commit 4db76d6f01)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Patrik Kernstock 5855b7de9e Do not open text files using Collabora app
Signed-off-by: Patrik Kernstock <info@pkern.at>(cherry picked from commit dee4991091)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant 9d4cff8f97 Include support for X-LOOL-WOPI-Timestamp
See for more detailed message:
https://github.com/owncloud/richdocuments/pull/178

(cherry picked from commit 65769bd861)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Andras Timar ba25db2b4d Merge pull request #95 from pranavk/nc11-undefined
Undefined owneruid
7 years ago
Pranav Kant fc24ac3319 Undefined owneruid 7 years ago
Andras Timar bbefee2e4f Update CHAMGELOG.md. for 1.11.32 7 years ago
Pranav Kant 49a73108e9 Shorter db index name
Fixes #54

(cherry picked from commit 2058ec84e5)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant 32755343ed Use the file owner from the share object, if available
Fixes #85

When a link is shared on external storage and user is not logged in, the
owner returned by the $file object is null. Use owner information from
the $share object whenever available.

(cherry picked from commit ee09fb0748)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant 2c1dd44651 Don't throw exception when user not found
It might be a public link share.

(cherry picked from commit 3f4aa7b23e)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Andras Timar 57f6a5ba32 Merge pull request #81 from pranavk/nc11-usernames
Show Display Name of user, not its uid in userlist
7 years ago
Pranav Kant 654c8e988d Show Display Name of user, not its uid in userlist
(cherry picked from commit 3940ec64c7)
7 years ago
Andras Timar 257e9f2020 Bump version to 1.11.31 7 years ago
Pranav Kant 9afe6fb69c Guard encryption support
(cherry picked from commit c14ff8fee8)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Andras Timar c99ec2d615 Bump version to 1.11.30 7 years ago
Pranav Kant 0a4c5816ee Register the change under user's name when saving the document
(cherry picked from commit 0f086cfe87)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant 6b112402f9 Support opening encrypted files
(cherry picked from commit eef417f05b)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Andras Timar b44c4da9a5 Merge pull request #61 from pranavk/nc11
Revert "Remove unrequired route"; respect OOXML settings again
7 years ago
Andras Timar f74a7b7f4a Bump version to 1.11.29 7 years ago
Andras Timar cc5fb99cb4 Fix issue#68: undefined variable instanceId
(cherry picked from commit 4ffef00aca)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Andras Timar d4e0ac2387 Bump version to 1.11.28
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Marius Blüm 586c925bb1 Update Collabora screenshots
Signed-off-by: Marius Blüm <marius@lineone.io>(cherry picked from commit b320276ee1)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant 5e42ea1dab allowfullscreen
(cherry picked from commit 75a12f07e4)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant d6c90226b9 Revert "Remove unrequired route"; respect OOXML settings again
This reverts commit aa89c908a7.

(cherry picked from commit 0c14789cc3)
7 years ago
Andras Timar 6925e4f2f6 Bump version to 1.11.27 7 years ago
Andras Timar bd68097a92 Update CHANGELOG.md
(cherry picked from commit f6b7e441d9)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant 2385b70915 Fix file revisions
(cherry picked from commit 9bb400714c)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant b1e51782fc Bin superfluous returnToDir logic
This was initially introduced in OC so that we know which directory to
go after we close the editor but this seems unnecessary here in NC as
richdocuments is just an iframe which is removed from DOM when we close
the document.

(cherry picked from commit a5f6569591)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Andras Timar ff1ee24c46 modify version to 1.1.26-nc11 7 years ago
Andras Timar ff7aa2d5e8 Bump version to 1.1.25.1 for Nextcloud 11 7 years ago
Andras Timar 472a22ef21 Updated CHANGELOG.md 7 years ago
Pranav Kant c21c029fa4 Send file path to the client also, fix revision history
(cherry picked from commit 66935d4bed)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Lukas Reschke 7e4c59e360 Append instance id to rev history
Signed-off-by: Lukas Reschke <lukas@statuscode.ch>
(cherry picked from commit 9cd9258dbb)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Lukas Reschke ad61db1158 Add instance id to file id
For multitenancy

Signed-off-by: Lukas Reschke <lukas@statuscode.ch>
(cherry picked from commit 1441bdc594)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
michag86 6b629b2c67 Make files_versions work again
Added some lines which were lost after rewrite with version 1.1.22.
(cherry picked from commit c72f22e180)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant f790f640b1 Fix incorrect language tags feeding to loleaflet
loleaflet expect a BCP47 language tag syntax while OC.getLocale returns
a lanugage tag where subtags are separated by '_' instead of '-'
(BCP47).

It seems safe to just replace '_' with '-' before feeding it to
loleaflet

(cherry picked from commit 5596ae17ce)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Pranav Kant 674a6cb384 Try opening readonly documents too
Also simplify the logic during file action registration. Basically, we
should try to open all known mimetypes; file permissions are taken care
of later in the WOPI protocol.

Without this commit, it is not possible to open a document in a
directory for which user has no write access.

(cherry picked from commit f36c5106d6)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Andras Timar df0c7cce94 replace trailing slash of wopi url
(cherry picked from commit 6d49e2d003)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Andras Timar 1cc5e43106 set the correct language tag expected by JS
(cherry picked from commit b565415e1c)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Andras Timar f74b0b3018 add rtf and txt as supported file formats
(cherry picked from commit 829b2b77b9)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago
Lukas Reschke bf72f5b01d Uses proper top height
Fixes https://github.com/nextcloud/richdocuments/issues/5

Signed-off-by: Lukas Reschke <lukas@statuscode.ch>
(cherry picked from commit 43ffbf2e97)
Signed-off-by: Andras Timar <andras.timar@collabora.com>
7 years ago

@ -1,3 +1,46 @@
**1.11.34**
- Bug: Fix editing publicly shared documents
- Bug: Delete creator/last modifier name from document templates
**1.11.33**
- Feature: Restore 'Enable edit for specific groups' feature, fixes #66
- Feature: Only edit textfiles with Collabora Online, when texteditorapp is disabled
- Feature: Include support for X-LOOL-WOPI-Timestamp
- Bug: Undefined variable 'owneruid'
**1.11.32**
- Bug: Show Display Name of user, not its uid in userlist
- Bug: Do not throw exception when user not found. It might be a public link share.
- Bug: Use the file owner from the share object, if available. Fixes #85.
- Bug: Shorter db index name. Fixes #54.
**1.11.31**
- Bug: Guard encryption support
**1.11.30**
- Feature: Support opening encrypted files
- Bug: Respect OOXML settings again
- Bug: Register the change under users name when saving the document
**1.11.29**
- Bug: Fix undefined instanceId
**1.11.28**
- Bug: Allow full screen
- Updated screenshots
**1.11.27**
- Bug: Fix revision history
**1.1.25.1**
- Bug: Fix height for revision history viewer
- Bug: Set the correct language tag expected by JS
- Bug: Replace trailing slash of WOPI URL
- Bug: Try opening readonly documents too
- Bug: Fix revision history
- Feature: Add rtf and txt as supported file formats
- Feature: Support for multitenancy installations of LibreOffice Online
**1.1.24**
- Bug: Fix undefined PHP notices
- Security: Properly check for password on password protected shares
- Security: Properly check for password on password protected shares

@ -121,7 +121,7 @@
</field>
<index>
<name>richdocuments_wopi_token_idx</name>
<name>rd_wopi_token_idx</name>
<unique>true</unique>
<field>
<name>token</name>

@ -5,7 +5,7 @@
<description>Collabora Online allows you to to work with all kinds of office documents directly in your browser. This application requires Collabora Cloudsuite to be installed on one of your servers, please read the documentation to learn more about that.</description>
<summary>Edit office documents directly in your browser.</summary>
<licence>AGPL</licence>
<version>1.1.24</version>
<version>1.11.34</version>
<author>Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk</author>
<bugs>https://github.com/nextcloud/richdocuments/issues</bugs>
<repository type="git">https://github.com/nextcloud/richdocuments.git</repository>
@ -22,7 +22,6 @@
<prevent_group_restriction/>
</types>
<screenshot>https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-document.png</screenshot>
<screenshot>https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-app.png</screenshot>
<screenshot>https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-presentation.png</screenshot>
<screenshot>https://nextcloud.com/wp-content/themes/next/assets/img/features/collabora-spreadsheet.png</screenshot>
<settings>

@ -25,5 +25,6 @@ return [
//settings
['name' => 'settings#setSettings', 'url' => 'ajax/admin.php', 'verb' => 'POST'],
['name' => 'settings#getSettings', 'url' => 'ajax/settings.php', 'verb' => 'GET'],
]
];

Binary file not shown.

Binary file not shown.

@ -133,7 +133,7 @@
width: 100%;
z-index: 600;
background-color: #ddd !important;
top: 45px;
top: 0px;
bottom: 0;
}
@ -149,7 +149,7 @@
z-index: 600;
background-color: #efefef !important;
right: 0;
top: 45px;
top: 0px;
bottom: 0;
box-sizing: border-box;
overflow-x: hidden;

@ -4,7 +4,7 @@ var documentsSettings = {
save : function() {
$('#wopi_apply').attr('disabled', true);
var data = {
wopi_url : $('#wopi_url').val()
wopi_url : $('#wopi_url').val().replace(/\/$/, '')
};
OC.msg.startAction('#documents-admin-msg', t('richdocuments', 'Saving...'));
@ -15,6 +15,17 @@ var documentsSettings = {
);
},
saveGroups: function(groups) {
var data = {
'edit_groups': groups
};
$.post(
OC.filePath('richdocuments', 'ajax', 'admin.php'),
data
);
},
saveDocFormat: function(format) {
$.post(
OC.filePath('richdocuments', 'ajax', 'admin.php'),
@ -27,7 +38,19 @@ var documentsSettings = {
OC.msg.finishedAction('#documents-admin-msg', response);
},
initEditGroups: function() {
var groups = $('#edit_group_select').val();
if (groups !== '') {
OC.Settings.setupGroupsSelect($('#edit_group_select'));
$('.edit-groups-enable').attr('checked', 'checked');
} else {
$('.edit-groups-enable').attr('checked', null);
}
},
initialize: function() {
documentsSettings.initEditGroups();
$('#wopi_apply').on('click', documentsSettings.save);
$(document).on('change', '.doc-format-ooxml', function() {
@ -35,6 +58,27 @@ var documentsSettings = {
documentsSettings.saveDocFormat(ooxml ? 'ooxml' : 'odf');
});
$(document).on('change', '#edit_group_select', function() {
var element = $(this).parent().find('input.edit-groups-enable');
var groups = $(this).val();
documentsSettings.saveGroups(groups);
});
$(document).on('change', '.edit-groups-enable', function() {
var $select = $(this).parent().find('#edit_group_select');
$select.val('');
if (this.checked) {
OC.Settings.setupGroupsSelect($select, {
placeholder: t('core', 'All')
});
} else {
$select.select2('destroy');
}
$select.change();
});
}
};

@ -72,7 +72,6 @@ var documentsMain = {
loadErrorHint : '',
renderComplete: false, // false till page is rendered with all required data about the document(s)
toolbar : '<div id="ocToolbar"><div id="ocToolbarInside"></div><span id="toolbar" class="claro"></span></div>',
returnToDir : null, // directory where we started from in the 'Files' app
UI : {
/* Editor wrapper HTML */
@ -129,7 +128,7 @@ var documentsMain = {
var urlsrc = documentsMain.urlsrc +
"WOPISrc=" + wopisrc +
"&title=" + encodeURIComponent(title) +
"&lang=" + OC.getLocale() +
"&lang=" + OC.getLocale().replace('_', '-') + // loleaflet expects a BCP47 language tag syntax
"&permission=readonly";
// access_token - must be passed via a form post
@ -163,7 +162,6 @@ var documentsMain = {
if (version === 0) {
formattedTimestamp = t('richdocuments', 'Latest revision');
downloadUrl = OC.generateUrl('apps/files/download'+ documentPath);
fileId = fileId.replace(/_.*/, '');
} else {
downloadUrl = OC.generateUrl('apps/files_versions/download.php?file={file}&revision={revision}',
{file: documentPath, revision: version});
@ -268,12 +266,8 @@ var documentsMain = {
documentsMain.UI.notify(t('richdocuments', 'Failed to revert the document to older version'));
}
// generate file id with returnToDir information in it, if any
var fileid = e.currentTarget.parentElement.dataset.fileid.replace(/_.*/, '') +
(documentsMain.returnToDir ? '_' + documentsMain.returnToDir : '');
// load the file again, it should get reverted now
window.location = OC.generateUrl('apps/richdocuments/index#{fileid}', {fileid: fileid});
window.location = OC.generateUrl('apps/richdocuments/index#{fileid}', {fileid: e.currentTarget.parentElement.dataset.fileid});
window.location.reload();
documentsMain.overlay.documentOverlay('hide');
}
@ -320,7 +314,7 @@ var documentsMain = {
var urlsrc = documentsMain.urlsrc +
"WOPISrc=" + wopisrc +
"&title=" + encodeURIComponent(title) +
"&lang=" + OC.getLocale() +
"&lang=" + OC.getLocale().replace('_', '-') + // loleaflet expects a BCP47 language tag syntax
"&closebutton=1" +
"&revisionhistory=1";
if (!documentsMain.canEdit || action === "view") {
@ -426,11 +420,6 @@ var documentsMain = {
// Does anything indicate that we need to autostart a session?
fileId = getURLParameter('fileid').replace(/^\W*/, '');
if (fileId.indexOf('_') >= 0) {
documentsMain.returnToDir = unescape(fileId.replace(/^[^_]*_/, ''));
fileId = fileId.replace(/_.*/, '');
}
documentsMain.show(fileId);
if (fileId) {

@ -1,7 +1,7 @@
/* globals FileList, OCA.Files.fileActions, oc_debug */
var odfViewer = {
isDocuments : false,
supportedMimesReadWrite: [
supportedMimes: [
'application/vnd.oasis.opendocument.text',
'application/vnd.oasis.opendocument.spreadsheet',
'application/vnd.oasis.opendocument.graphics',
@ -12,6 +12,8 @@ var odfViewer = {
'application/vnd.wordperfect',
'application/msonenote',
'application/msword',
'application/rtf',
'text/rtf',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'application/vnd.ms-word.document.macroEnabled.12',
@ -35,34 +37,19 @@ var odfViewer = {
register : function() {
var i,
mimeReadOnly,
mimeReadWrite;
mime;
for (i = 0; i < odfViewer.supportedMimesReadWrite.length; ++i) {
mimeReadOnly = odfViewer.supportedMimesReadWrite[i];
OCA.Files.fileActions.register(mimeReadOnly, 'View', OC.PERMISSION_READ, '', odfViewer.onEdit);
OCA.Files.fileActions.setDefault(mimeReadOnly, 'View');
}
for (i = 0; i < odfViewer.supportedMimesReadWrite.length; ++i) {
mimeReadWrite = odfViewer.supportedMimesReadWrite[i];
for (i = 0; i < odfViewer.supportedMimes.length; ++i) {
mime = odfViewer.supportedMimes[i];
OCA.Files.fileActions.register(
mimeReadWrite,
mime,
'Edit',
OC.PERMISSION_UPDATE,
OC.PERMISSION_UPDATE | OC.PERMISSION_READ,
OC.imagePath('core', 'actions/rename'),
odfViewer.onEdit,
t('richdocuments', 'Edit')
);
OCA.Files.fileActions.register(
mimeReadWrite,
'View',
OC.PERMISSION_READ,
OC.imagePath('core', 'actions/rename'),
odfViewer.onEdit,
t('richdocuments', 'View')
);
OCA.Files.fileActions.setDefault(mimeReadWrite, 'View');
OCA.Files.fileActions.setDefault(mimeReadWrite, 'Edit');
OCA.Files.fileActions.setDefault(mime, 'Edit');
}
},
@ -79,17 +66,17 @@ var odfViewer = {
var viewer;
if($('#isPublic').val() === '1') {
viewer = OC.generateUrl(
'apps/richdocuments/public?shareToken={shareToken}&fileName={fileName}&requesttoken={requesttoken}',
'apps/richdocuments/public?shareToken={shareToken}&fileName={fileName}&requesttoken={requesttoken}&fileId={fileId}',
{
shareToken: $('#sharingToken').val(),
fileName: fileName,
dir: fileDir,
fileId: fileId,
requesttoken: OC.requestToken
}
);
} else {
viewer = OC.generateUrl(
'apps/richdocuments/index?fileId={fileId}_{dir}&requesttoken={requesttoken}',
'apps/richdocuments/index?fileId={fileId}&requesttoken={requesttoken}',
{
fileId: fileId,
dir: fileDir,
@ -102,7 +89,7 @@ var odfViewer = {
FileList.setViewerMode(true);
}
var $iframe = $('<iframe id="richdocumentsframe" style="width:100%;height:100%;display:block;position:absolute;top:0;" src="'+viewer+'" />');
var $iframe = $('<iframe id="richdocumentsframe" allowfullscreen style="width:100%;height:100%;display:block;position:absolute;top:0;z-index:5;" src="'+viewer+'" />');
if ($('#isPublic').val()) {
// force the preview to adjust its height
$('#preview').append($iframe).css({height: '100%'});
@ -122,7 +109,6 @@ var odfViewer = {
$('#app-content').append($iframe);
},
onClose: function() {
if(typeof FileList !== "undefined") {
FileList.setViewerMode(false);
@ -131,8 +117,8 @@ var odfViewer = {
$('#richdocumentsframe').remove();
},
registerFilesMenu: function() {
var ooxml = false;
registerFilesMenu: function(response) {
var ooxml = response.doc_format === 'ooxml';
var docExt, spreadsheetExt, presentationExt;
var docMime, spreadsheetMime, presentationMime;
@ -219,15 +205,28 @@ $(document).ready(function() {
&& typeof OCA.Files !== 'undefined'
&& typeof OCA.Files.fileActions !== 'undefined'
) {
// check if texteditor app is enabled and loaded...
if (_.isUndefined(OCA.Files_Texteditor)) {
// it is not, so we do open text files with this app too.
odfViewer.supportedMimes.push('text/plain');
}
// notice: when changing 'supportedMimes' interactively (e.g. dev console),
// register() needs to be re-run to re-register the fileActions.
odfViewer.register();
odfViewer.registerFilesMenu();
$.get(
OC.filePath('richdocuments', 'ajax', 'settings.php'),
{},
odfViewer.registerFilesMenu
);
}
});
// FIXME: Hack for single public file view since it is not attached to the fileslist
$(document).ready(function(){
// FIXME: FIlter compatible mime types
if ($('#isPublic').val() && odfViewer.supportedMimesReadWrite.indexOf($('#mimetype').val()) !== -1) {
// FIXME: Filter compatible mime types
if ($('#isPublic').val() && odfViewer.supportedMimes.indexOf($('#mimetype').val()) !== -1) {
odfViewer.onEdit($('#filename').val());
}
});
@ -244,4 +243,4 @@ $(document).ready(function() {
$('#content').removeClass('loading');
}
}, false);
});
});

@ -104,12 +104,24 @@ class DocumentController extends Controller {
$params = [
'permissions' => $item->getPermissions(),
'title' => $item->getName(),
'fileId' => $item->getId(),
'fileId' => $item->getId() . '_' . $this->settings->getSystemValue('instanceid'),
'token' => $token,
'urlsrc' => $urlSrc,
'path' => '/',
'path' => $folder->getRelativePath($item->getPath()),
'instanceId' => $this->settings->getSystemValue('instanceid'),
];
$encryptionManager = \OC::$server->getEncryptionManager();
if ($encryptionManager->isEnabled())
{
// Update the current file to be accessible with system public shared key
$owner = $item->getOwner()->getUID();
$absPath = '/' . $owner . '/' . $item->getInternalPath();
$accessList = \OC::$server->getEncryptionFilesHelper()->getAccessList($absPath);
$accessList['public'] = true;
$encryptionManager->getEncryptionModule()->update($absPath, $owner, $accessList);
}
$response = new TemplateResponse('richdocuments', 'documents', $params, 'empty');
$policy = new ContentSecurityPolicy();
$policy->addAllowedFrameDomain($this->appConfig->getAppValue('wopi_url'));
@ -130,7 +142,7 @@ class DocumentController extends Controller {
* @return TemplateResponse
* @throws \Exception
*/
public function publicPage($shareToken, $fileName) {
public function publicPage($shareToken, $fileName, $fileId) {
try {
$share = $this->shareManager->getShareByToken($shareToken);
// not authenticated ?
@ -144,7 +156,7 @@ class DocumentController extends Controller {
$node = $share->getNode();
if($node instanceof Folder) {
$item = $node->get($fileName);
$item = $node->getById($fileId)[0];
} else {
$item = $node;
}
@ -153,10 +165,11 @@ class DocumentController extends Controller {
$params = [
'permissions' => $share->getPermissions(),
'title' => $item->getName(),
'fileId' => $item->getId(),
'fileId' => $item->getId() . '_' . $this->settings->getSystemValue('instanceid'),
'token' => $token,
'urlsrc' => $urlSrc,
'path' => '/',
'instanceId' => $this->settings->getSystemValue('instanceid'),
];
$response = new TemplateResponse('richdocuments', 'documents', $params, 'empty');
@ -231,12 +244,13 @@ class DocumentController extends Controller {
if ($content && $view->file_put_contents($path, $content)) {
$info = $view->getFileInfo($path);
$ret = $this->wopiParser->getUrlSrc($mimetype);
$lolang = strtolower(str_replace('_', '-', $this->settings->getUserValue($this->uid, 'core', 'lang', 'en')));
$response = array(
'status' => 'success',
'fileid' => $info['fileid'],
'fileid' => $info['fileid'] . '_' . $this->settings->getSystemValue('instanceid'),
'urlsrc' => $ret['urlsrc'],
'action' => $ret['action'],
'lolang' => $this->settings->getUserValue($this->uid, 'core', 'lang', 'en'),
'lolang' => $lolang,
'data' => \OCA\Files\Helper::formatFileInfo($info)
);
} else {

@ -45,12 +45,27 @@ class SettingsController extends Controller{
$this->discoveryManager = $discoveryManager;
}
/**
* @NoAdminRequired
*
* @return JSONResponse
*/
public function getSettings() {
return new JSONResponse([
'wopi_url' => $this->appConfig->getAppValue('wopi_url'),
'edit_groups' => $this->appConfig->getAppValue('edit_groups'),
'doc_format' => $this->appConfig->getAppValue('doc_format'),
]);
}
/**
* @param string $wopi_url
* @param string $edit_groups
* @param string $doc_format
* @return JSONResponse
*/
public function setSettings($wopi_url,
$edit_groups,
$doc_format){
$message = $this->l10n->t('Saved');
@ -63,6 +78,10 @@ class SettingsController extends Controller{
}
}
if ($edit_groups !== null){
$this->appConfig->setAppValue('edit_groups', $edit_groups);
}
if ($doc_format !== null) {
$this->appConfig->setAppValue('doc_format', $doc_format);
}

@ -21,7 +21,9 @@
namespace OCA\Richdocuments\Controller;
use OC\Files\View;
use OCA\Richdocuments\Db\Wopi;
use OCA\Richdocuments\Helper;
use OCA\Richdocuments\WOPI\Parser;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
@ -35,32 +37,22 @@ use OCP\AppFramework\Http\StreamResponse;
class WopiController extends Controller {
/** @var IRootFolder */
private $rootFolder;
/** @var string */
private $userId;
/** @var IUserManager */
private $userManager;
/** @var Parser */
private $wopiParser;
// Signifies LOOL that document has been changed externally in this storage
const LOOL_STATUS_DOC_CHANGED = 1010;
/**
* @param string $appName
* @param IRequest $request
* @param IRootFolder $rootFolder
* @param string $UserId
* @param IUserManager $userManager
* @param Parser $wopiParser
*/
public function __construct($appName,
$UserId,
IRequest $request,
IRootFolder $rootFolder,
IUserManager $userManager,
Parser $wopiParser) {
IRootFolder $rootFolder) {
parent::__construct($appName, $request);
$this->rootFolder = $rootFolder;
$this->userId = $UserId;
$this->userManager = $userManager;
$this->wopiParser = $wopiParser;
}
/**
@ -76,16 +68,9 @@ class WopiController extends Controller {
public function checkFileInfo($fileId) {
$token = $this->request->getParam('access_token');
$arr = explode('_', $fileId, 2);
$version = '0';
if (count($arr) === 2) {
list($fileId, $version) = $arr;
}
$row = new Wopi();
$row->loadBy('token', $token);
$res = $row->getPathForToken($fileId, $version, $token);
list($fileId, , $version) = Helper::parseFileId($fileId);
$db = new Wopi();
$res = $db->getPathForToken($fileId, $token);
if ($res === false) {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}
@ -110,9 +95,10 @@ class WopiController extends Controller {
'Version' => $version,
'UserId' => $res['editor'] !== '' ? $res['editor'] : 'Guest user',
'OwnerId' => $res['owner'],
'UserFriendlyName' => $res['editor'] !== '' ? $res['editor'] : 'Guest user',
'UserFriendlyName' => $res['editor'] !== '' ? \OC_User::getDisplayName($res['editor']) : 'Guest user',
'UserCanWrite' => $res['canwrite'] ? true : false,
'PostMessageOrigin' => $res['server_host'],
'LastModifiedTime' => Helper::toISO8601($file->getMtime())
]
);
}
@ -130,22 +116,32 @@ class WopiController extends Controller {
*/
public function getFile($fileId,
$access_token) {
$arr = explode('_', $fileId, 2);
$version = '0';
if (count($arr) === 2) {
list($fileId, $version) = $arr;
}
list($fileId, , $version) = Helper::parseFileId($fileId);
$row = new Wopi();
$row->loadBy('token', $access_token);
$res = $row->getPathForToken($fileId, $version, $access_token);
$res = $row->getPathForToken($fileId, $access_token);
try {
/** @var File $file */
$userFolder = $this->rootFolder->getUserFolder($res['owner']);
$file = $userFolder->getById($fileId)[0];
$response = new StreamResponse($file->fopen('rb'));
\OC_User::setIncognitoMode(true);
if ($version !== '0')
{
$view = new View('/' . $res['owner'] . '/files');
$relPath = $view->getRelativePath($file->getPath());
$versionPath = '/files_versions/' . $relPath . '.v' . $version;
$view = new View('/' . $res['owner']);
if ($view->file_exists($versionPath)){
$response = new StreamResponse($view->fopen($versionPath, 'rb'));
}
else {
$response->setStatus(Http::STATUS_NOT_FOUND);
}
}
else
{
$response = new StreamResponse($file->fopen('rb'));
}
$response->addHeader('Content-Disposition', 'attachment');
$response->addHeader('Content-Type', 'application/octet-stream');
return $response;
@ -165,28 +161,48 @@ class WopiController extends Controller {
* @param string $access_token
* @return JSONResponse
*/
public function putFile($fileId, $access_token) {
$arr = explode('_', $fileId, 2);
$version = '0';
if (count($arr) === 2) {
list($fileId, $version) = $arr;
}
public function putFile($fileId,
$access_token) {
list($fileId, , $version) = Helper::parseFileId($fileId);
$row = new Wopi();
$row->loadBy('token', $access_token);
$res = $row->getPathForToken($fileId, $version, $access_token);
$res = $row->getPathForToken($fileId, $access_token);
if (!$res['canwrite']) {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}
try {
/** @var File $file */
$userFolder = $this->rootFolder->getUserFolder($res['owner']);
$file = $userFolder->getById($fileId)[0];
$wopiHeaderTime = $this->request->getHeader('X-LOOL-WOPI-Timestamp');
if (!is_null($wopiHeaderTime) && $wopiHeaderTime != Helper::toISO8601($file->getMTime())) {
\OC::$server->getLogger()->debug('Document timestamp mismatch ! WOPI client says mtime {headerTime} but storage says {storageTime}', [
'headerTime' => $wopiHeaderTime,
'storageTime' => Helper::toISO8601($file->getMtime())
]);
// Tell WOPI client about this conflict.
return new JSONResponse(['LOOLStatusCode' => self::LOOL_STATUS_DOC_CHANGED], Http::STATUS_CONFLICT);
}
$content = fopen('php://input', 'rb');
// Setup the FS which is needed to emit hooks (versioning).
\OC_Util::tearDownFS();
\OC_Util::setupFS($res['owner']);
// Set the user to register the change under his name
$editor = \OC::$server->getUserManager()->get($res['editor']);
if (!is_null($editor)) {
\OC::$server->getUserSession()->setUser($editor);
}
$file->putContent($content);
return new JSONResponse();
return new JSONResponse(['LastModifiedTime' => Helper::toISO8601($file->getMtime())]);
} catch (\Exception $e) {
return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
}

@ -49,8 +49,6 @@ class Admin implements ISettings {
'wopi_url' => $this->config->getAppValue('richdocuments', 'wopi_url'),
'edit_groups' => $this->config->getAppValue('richdocuments', 'edit_groups'),
'doc_format' => $this->config->getAppValue('richdocuments', 'doc_format'),
'test_wopi_url' => $this->config->getAppValue('richdocuments', 'test_wopi_url'),
'test_server_groups' => $this->config->getAppValue('richdocuments', 'test_server_groups')
],
'blank'
);

@ -22,6 +22,7 @@
namespace OCA\Richdocuments;
use OC\Share\Constants;
use OCA\Richdocuments\Helper;
use OCA\Richdocuments\Db\Wopi;
use OCA\Richdocuments\WOPI\Parser;
use OCP\Files\File;
@ -49,11 +50,13 @@ class TokenManager {
IManager $shareManager,
IURLGenerator $urlGenerator,
Parser $wopiParser,
AppConfig $appConfig,
$UserId) {
$this->rootFolder = $rootFolder;
$this->shareManager = $shareManager;
$this->urlGenerator = $urlGenerator;
$this->wopiParser = $wopiParser;
$this->appConfig = $appConfig;
$this->userId = $UserId;
}
@ -64,33 +67,49 @@ class TokenManager {
* @throws \Exception
*/
public function getToken($fileId, $shareToken = null) {
$arr = explode('_', $fileId, 2);
$version = '0';
if (count($arr) === 2) {
list($fileId, $version) = $arr;
}
list($fileId,, $version) = Helper::parseFileId($fileId);
$owneruid = null;
// if the user is not logged-in do use the sharers storage
if($shareToken !== null) {
/** @var File $file */
$rootFolder = $this->rootFolder;
$share = $this->shareManager->getShareByToken($shareToken);
$updatable = (bool)($share->getPermissions() & \OCP\Constants::PERMISSION_UPDATE);
$owneruid = $share->getShareOwner();
} else {
try {
/** @var File $file */
$rootFolder = $this->rootFolder->getUserFolder($this->userId);
$updatable = $rootFolder->isUpdateable();
// Check if the editor (user who is accessing) is in editable group
// UserCanWrite only if
// 1. No edit groups are set or
// 2. if they are set, it is in one of the edit groups
$editorUid = \OC::$server->getUserSession()->getUser()->getUID();
$editGroups = array_filter(explode('|', $this->appConfig->getAppValue('edit_groups')));
if ($updatable && count($editGroups) > 0) {
$updatable = false;
foreach($editGroups as $editGroup) {
$editorGroup = \OC::$server->getGroupManager()->get($editGroup);
if ($editorGroup !== null && sizeof($editorGroup->searchUsers($editorUid)) > 0) {
$updatable = true;
break;
}
}
}
} catch (\Exception $e) {
throw $e;
}
}
/** @var File $file */
$file = $rootFolder->getById($fileId)[0];
// If its a public share, use the owner from the share, otherwise check the file object
if (is_null($owneruid)) {
$owneruid = $file->getOwner()->getUID();
}
$row = new Wopi();
$serverHost = $this->urlGenerator->getAbsoluteURL('/');//$this->request->getServerProtocol() . '://' . $this->request->getServerHost();
$token = $row->generateFileToken($fileId, $file->getOwner()->getUID(), $this->userId, $version, (int)$updatable, $serverHost);
$token = $row->generateFileToken($fileId, $owneruid, $this->userId, $version, (int)$updatable, $serverHost);
try {
@ -102,4 +121,4 @@ class TokenManager {
throw $e;
}
}
}
}

@ -56,12 +56,12 @@ class Wopi extends \OCA\Richdocuments\Db{
* constructs and validates the path.
* Returns the path, if valid, else false.
*/
public function getPathForToken($fileId, $version, $token){
public function getPathForToken($fileId, $token){
$wopi = new Wopi();
$row = $wopi->loadBy('token', $token)->getData();
\OC::$server->getLogger()->debug('Loaded WOPI Token record: {row}.', [ 'row' => $row ]);
if (count($row) == 0)
if (count($row) === 0)
{
// Invalid token.
http_response_code(401);
@ -75,11 +75,6 @@ class Wopi extends \OCA\Richdocuments\Db{
//$wopi->deleteBy('id', $row['id']);
//return false;
}
if ($row['fileid'] != $fileId || $row['version'] != $version){
// File unknown / user unauthorized (for the requested file).
http_response_code(404);
return false;
}
return array(
'owner' => $row['owner_uid'],

@ -11,9 +11,53 @@
namespace OCA\Richdocuments;
use \DateTime;
use \DateTimeZone;
class Helper {
const APP_ID = 'richdocuments';
/**
* @param string $fileId
* @return array
* @throws \Exception
*/
public static function parseFileId($fileId) {
$arr = explode('_', $fileId);
if (count($arr) === 1) {
$fileId = $arr[0];
$instanceId = '';
$version = '0';
} else if (count($arr) === 2) {
list($fileId, $instanceId) = $arr;
$version = '0';
} else if (count($arr) === 3) {
list($fileId, $instanceId, $version) = $arr;
} else {
throw new \Exception('$fileId has not the expected format');
}
return [
$fileId,
$instanceId,
$version,
];
}
/**
* WOPI helper function to convert to ISO 8601 round-trip format.
* @param integer $time Must be seconds since unix epoch
*/
public static function toISO8601($time)
{
// TODO: Be more precise and don't ignore milli, micro seconds ?
$datetime = DateTime::createFromFormat('U', $time, new DateTimeZone('UTC'));
if ($datetime)
return $datetime->format('Y-m-d\TH:i:s.u\Z');
return false;
}
public static function getNewFileName($view, $path, $prepend = ' '){
$fileNum = 1;

@ -9,7 +9,10 @@ script('richdocuments', 'admin');
<br/><button type="button" id="wopi_apply"><?php p($l->t('Apply')) ?></button>
<span id="documents-admin-msg" class="msg"></span>
<br/>
<input type="checkbox" class="edit-groups-enable" id="edit_groups_enable-richdocuments" />
<label for="edit_groups_enable-richdocuments"><?php p($l->t('Enable edit for specific groups')) ?></label>
<input type="hidden" id="edit_group_select" value="<?php p($_['edit_groups'])?>" title="<?php p($l->t('All')); ?>" style="width: 200px">
<br/>
<input type="checkbox" class="doc-format-ooxml" id="doc_format_ooxml_enable-richdocuments" <?php p($_['doc_format'] === 'ooxml' ? 'checked' : '') ?> />
<label for="doc_format_ooxml_enable-richdocuments"><?php p($l->t('Use OOXML by default for new files')) ?></label>
</div>
</div>

@ -5,6 +5,7 @@
var richdocuments_token = '<?php p($_['token']) ?>';
var richdocuments_urlsrc = '<?php p($_['urlsrc']) ?>';
var richdocuments_path = '<?php p($_['path']) ?>';
var instanceId = '<?php p($_['instanceId']) ?>';
</script>
<?php

Loading…
Cancel
Save