Skip to content

Commit

Permalink
Merge pull request #2456 from nextcloud/backport/stable25/2442
Browse files Browse the repository at this point in the history
  • Loading branch information
juliusknorr authored Sep 23, 2022
2 parents 5458a45 + a968af3 commit a1273b7
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 9 deletions.
4 changes: 4 additions & 0 deletions img/launch.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/Listener/CSPListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public function handle(Event $event): void {

$policy = new EmptyContentSecurityPolicy();
$policy->addAllowedFrameDomain("'self'");
$policy->addAllowedFrameDomain("nc:");

foreach ($urls as $url) {
$policy->addAllowedFrameDomain($url);
Expand Down
79 changes: 77 additions & 2 deletions src/document.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { emit } from '@nextcloud/event-bus'
import { getRootUrl } from '@nextcloud/router'
import { getRootUrl, imagePath } from '@nextcloud/router'
import { getRequestToken } from '@nextcloud/auth'
import Config from './services/config.tsx'
import { setGuestName, shouldAskForGuestName } from './helpers/guestName'
Expand All @@ -11,9 +11,10 @@ import {
isDirectEditing,
isMobileInterfaceAvailable,
} from './helpers/mobile'
import { getWopiUrl, getSearchParam } from './helpers/url'
import { getWopiUrl, getSearchParam, getNextcloudUrl } from './helpers/url'

import '../css/document.scss'
import axios from '@nextcloud/axios'

const PostMessages = new PostMessageService({
parent: window.parent,
Expand Down Expand Up @@ -307,6 +308,15 @@ const documentsMain = {

if (Config.get('userId') === null) {
PostMessages.sendWOPIPostMessage('loolframe', 'Hide_Menu_Item', { id: 'insertgraphicremote' })
} else {
PostMessages.sendWOPIPostMessage('loolframe', 'Insert_Button', {
id: 'Open_Local_Editor',
imgurl: window.location.protocol + '//' + getNextcloudUrl() + imagePath('richdocuments', 'launch.svg'),
mobile: false,
label: t('richdocuments', 'Open in local editor'),
hint: t('richdocuments', 'Open in local editor'),
insertBefore: 'undo',
})
}

emit('richdocuments:wopi-load:succeeded', {
Expand Down Expand Up @@ -442,6 +452,23 @@ const documentsMain = {
case 'File_Rename':
documentsMain.fileName = args.NewName
break
case 'Clicked_Button':
if (parsed.args.Id === 'Open_Local_Editor') {
documentsMain.UI.initiateOpenLocally()
} else {
console.debug('[document] Unhandled `Clicked_Button` post message', parsed)
}
break
case 'Get_Views_Resp':
if (documentsMain.openingLocally) {
documentsMain.UI.removeViews(parsed.args)
documentsMain.unlockFile()
.catch(_ => {}) // Unlocking failed, possibly because file was not locked, we want to proceed regardless.
.then(() => {
documentsMain.openLocally()
})
}
break
default:
console.debug('[document] Unhandled post message', parsed)
}
Expand Down Expand Up @@ -500,6 +527,53 @@ const documentsMain = {
$(document.body).removeClass('claro')
})
},

initiateOpenLocally() {
OC.dialogs.confirmDestructive(
t('richdocuments', 'When opening a file locally, the document will close for all users currently viewing the document.'),
t('richdocuments', 'Open file locally'),
{
type: OC.dialogs.YES_NO_BUTTONS,
confirm: t('richdocuments', 'Open locally'),
confirmClasses: 'error',
cancel: t('richdocuments', 'Continue editing online'),
},
(decision) => {
if (!decision) {
return
}
documentsMain.openingLocally = true
PostMessages.sendWOPIPostMessage('loolframe', 'Get_Views')
}
)
},

removeViews(views) {
PostMessages.sendWOPIPostMessage('loolframe', 'Action_Save', {
DontTerminateEdit: false,
DontSaveIfUnmodified: false,
Notify: false,
})

views.forEach((view) => {
PostMessages.sendWOPIPostMessage('loolframe', 'Action_RemoveView', { ViewId: Number(view.ViewId) })
})
},
},

unlockFile() {
const unlockUrl = getRootUrl() + '/index.php/apps/richdocuments/wopi/files/' + documentsMain.fileId
const unlockConfig = {
headers: { 'X-WOPI-Override': 'UNLOCK' }
}
return axios.post(unlockUrl, { access_token: documentsMain.token }, unlockConfig)
},

openLocally() {
if (documentsMain.openingLocally) {
documentsMain.openingLocally = false
window.location.href = 'nc://open/' + Config.get('userId') + '@' + getNextcloudUrl() + OC.encodePath(documentsMain.fullPath)
}
},

onStartup() {
Expand Down Expand Up @@ -560,6 +634,7 @@ const documentsMain = {

$('footer,nav').show()
documentsMain.UI.hideEditor()
documentsMain.openLocally()

PostMessages.sendPostMessage('parent', 'close', '*')
},
Expand Down
5 changes: 5 additions & 0 deletions src/helpers/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,16 @@ const getDocumentUrlForFile = (fileDir, fileId) => {
})
}

const getNextcloudUrl = () => {
return window.location.host + (window.location.port ? `:${window.location.port}` : '')
}

export {
getSearchParam,
getWopiUrl,

getDocumentUrlFromTemplate,
getDocumentUrlForPublicFile,
getDocumentUrlForFile,
getNextcloudUrl,
}
14 changes: 7 additions & 7 deletions tests/lib/Listener/CSPListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public function testHandle() {

$policy = $this->getMergedPolicy();

self::assertEquals(["'self'", "http://public"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "nc:" , "http://public"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "http://public"], $policy->getAllowedFormActionDomains());
}

Expand All @@ -123,7 +123,7 @@ public function testNotSetup() {

$policy = $this->getMergedPolicy();

self::assertEquals(["'self'"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "nc:"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'"], $policy->getAllowedFormActionDomains());
}

Expand All @@ -135,7 +135,7 @@ public function testWopiUrlPublic() {

$policy = $this->getMergedPolicy();

self::assertEquals(["'self'", "http://public"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "nc:", "http://public"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "http://public"], $policy->getAllowedFormActionDomains());
}

Expand All @@ -147,7 +147,7 @@ public function testWopiUrl() {

$policy = $this->getMergedPolicy();

self::assertEquals(["'self'", "https://public"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "nc:", "https://public"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "https://public"], $policy->getAllowedFormActionDomains());
}

Expand All @@ -165,7 +165,7 @@ public function testGS() {

$policy = $this->getMergedPolicy();

self::assertEquals(["'self'", "https://public", "*.example.com"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "nc:", "https://public", "*.example.com"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "https://public", "*.example.com"], $policy->getAllowedFormActionDomains());
}

Expand All @@ -180,7 +180,7 @@ public function testNoGS() {

$policy = $this->getMergedPolicy();

self::assertEquals(["'self'", "http://internal"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "nc:", "http://internal"], $policy->getAllowedFrameDomains());
self::assertEquals(["'self'", "http://internal"], $policy->getAllowedFormActionDomains());
}

Expand All @@ -205,7 +205,7 @@ public function testHandleMerged() {

$policy = $manager->getDefaultPolicy();

self::assertArrayUnordered(["'self'", "external.example.com", "http://public"], $policy->getAllowedFrameDomains(), "Domains are equal", 0.0, 10, true);
self::assertArrayUnordered(["'self'", "external.example.com", "http://public", "nc:"], $policy->getAllowedFrameDomains(), "Domains are equal", 0.0, 10, true);
self::assertArrayUnordered(["'self'", "external.example.com", "http://public"], $policy->getAllowedFormActionDomains());
}

Expand Down

0 comments on commit a1273b7

Please sign in to comment.