kit/ChildSession.cpp | 29 +++++++++++++++++++++++ loleaflet/dist/loleaflet.html | 2 + loleaflet/dist/toolbar.css | 25 ++++++++++++++++++++ loleaflet/dist/toolbar/toolbar.js | 42 ++++++++++++++++++++++++++++++++++ loleaflet/src/control/Toolbar.js | 5 +++- loleaflet/src/core/Socket.js | 36 +++++++++++++++++++++++++---- loleaflet/src/map/handler/Map.WOPI.js | 4 ++- test/UnitWOPISaveAs.cpp | 10 +++++--- test/WopiTestServer.hpp | 2 - wsd/ClientSession.cpp | 1 wsd/DocumentBroker.cpp | 9 +++++++ wsd/Storage.cpp | 7 +++-- 12 files changed, 159 insertions(+), 13 deletions(-)
New commits: commit 2153c8af9b84666cf43347a85be1e6f888b24753 Author: Jan Holesovsky <ke...@collabora.com> Date: Wed Nov 8 19:36:15 2017 +0100 Save As: Don't save the document several times. Also don't perform the save as when the document name hasn't changed. Change-Id: I4fb7e0abd73996e90107b301a09b8703b66e80f9 Reviewed-on: https://gerrit.libreoffice.org/44504 Reviewed-by: Andras Timar <andras.ti...@collabora.com> Tested-by: Andras Timar <andras.ti...@collabora.com> diff --git a/loleaflet/dist/toolbar/toolbar.js b/loleaflet/dist/toolbar/toolbar.js index f030ce0d..05091a9f 100644 --- a/loleaflet/dist/toolbar/toolbar.js +++ b/loleaflet/dist/toolbar/toolbar.js @@ -814,7 +814,7 @@ function onSearchKeyPress(e) { function documentNameConfirm() { var value = $('#document-name-input').val(); - if (value !== null && value != '') { + if (value !== null && value != '' && value != map['wopi'].BaseFileName) { map.saveAs(value); } map._onGotFocus(); @@ -833,6 +833,11 @@ function onDocumentNameKeyPress(e) { } } +function onDocumentNameFocus() { + // hide the caret in the main document + map._onLostFocus(); +} + function sortFontSizes() { var oldVal = $('.fontsizes-select').val(); var selectList = $('.fontsizes-select option'); @@ -1029,9 +1034,9 @@ map.on('wopiprops', function(e) { // Save As allowed $('#document-name-input').prop('disabled', false); $('#document-name-input').addClass('editable'); - $('#document-name-input').on('keypress', onDocumentNameKeyPress); - $('#document-name-input').on('focus', function() { map._onLostFocus(); /* hide the caret in the main document */ }); - $('#document-name-input').on('blur', documentNameCancel); + $('#document-name-input').off('keypress', onDocumentNameKeyPress).on('keypress', onDocumentNameKeyPress); + $('#document-name-input').off('focus', onDocumentNameFocus).on('focus', onDocumentNameFocus); + $('#document-name-input').off('blur', documentNameCancel).on('blur', documentNameCancel); } else { $('#document-name-input').prop('disabled', true); $('#document-name-input').removeClass('editable'); commit 676b6ca6105988ef60e12bb30d221dda5abbf0dc Author: Jan Holesovsky <ke...@collabora.com> Date: Tue Nov 7 14:30:52 2017 +0100 Save As: If the LOK's saveAs failed, try under a different name. This helps when the caller omitted the extension... Change-Id: Ib7602ce8fa88bc867198dbba36b2582145bd0994 Reviewed-on: https://gerrit.libreoffice.org/44405 Reviewed-by: pranavk <pran...@collabora.co.uk> Tested-by: pranavk <pran...@collabora.co.uk> diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp index f3af2d5c..71feb376 100644 --- a/kit/ChildSession.cpp +++ b/kit/ChildSession.cpp @@ -994,6 +994,27 @@ bool ChildSession::saveAs(const char* /*buffer*/, int /*length*/, const std::vec success = getLOKitDocument()->saveAs(url.c_str(), format.size() == 0 ? nullptr :format.c_str(), filterOptions.size() == 0 ? nullptr : filterOptions.c_str()); + + if (!success) + { + // a desperate try - add an extension hoping that it'll help + bool retry = true; + switch (getLOKitDocument()->getDocumentType()) + { + case LOK_DOCTYPE_TEXT: url += ".odt"; wopiFilename += ".odt"; break; + case LOK_DOCTYPE_SPREADSHEET: url += ".ods"; wopiFilename += ".ods"; break; + case LOK_DOCTYPE_PRESENTATION: url += ".odp"; wopiFilename += ".odp"; break; + case LOK_DOCTYPE_DRAWING: url += ".odg"; wopiFilename += ".odg"; break; + default: retry = false; break; + } + + if (retry) + { + success = getLOKitDocument()->saveAs(url.c_str(), + format.size() == 0 ? nullptr :format.c_str(), + filterOptions.size() == 0 ? nullptr : filterOptions.c_str()); + } + } } std::string encodedURL, encodedWopiFilename; commit d9a6c2bc4ae62aa6c7eb98dab163c4e52d538575 Author: Jan Holesovsky <ke...@collabora.com> Date: Tue Nov 7 13:38:22 2017 +0100 Each error should hide the busy indicator in the statusbar. Change-Id: I4676b2b6fe44351102feedf4728ff0911c15417b Reviewed-on: https://gerrit.libreoffice.org/44404 Reviewed-by: pranavk <pran...@collabora.co.uk> Tested-by: pranavk <pran...@collabora.co.uk> diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js index d363920e..5adf34b8 100644 --- a/loleaflet/src/core/Socket.js +++ b/loleaflet/src/core/Socket.js @@ -390,6 +390,7 @@ L.Socket = L.Class.extend({ return; } else if (textMsg.startsWith('error:') && command.errorCmd === 'storage') { + this._map.hideBusy(); var storageError; if (command.errorKind === 'savediskfull') { storageError = errorMessages.storage.savediskfull; @@ -405,7 +406,6 @@ L.Socket = L.Class.extend({ // Since this is a document load failure, wsd will disconnect the socket anyway, // better we do it first so that another error message doesn't override this one // upon socket close. - this._map.hideBusy(); this.close(); } else if (command.errorKind === 'documentconflict') @@ -451,12 +451,12 @@ L.Socket = L.Class.extend({ return; } else if (textMsg.startsWith('error:') && command.errorCmd === 'internal') { + this._map.hideBusy(); this._map._fatal = true; if (command.errorKind === 'diskfull') { this._map.fire('error', {msg: errorMessages.diskfull}); } else if (command.errorKind === 'unauthorized') { - this._map.hideBusy(); this._map.fire('error', {msg: errorMessages.unauthorized}); } @@ -471,6 +471,7 @@ L.Socket = L.Class.extend({ this._map.hideBusy(); } else if (textMsg.startsWith('error:') && command.errorCmd === 'load') { + this._map.hideBusy(); this.close(); var errorKind = command.errorKind; commit 61ce9c38e6d38d531aa3ddd749047d121d67a3a6 Author: Jan Holesovsky <ke...@collabora.com> Date: Tue Nov 7 13:12:23 2017 +0100 Save: Inform the user when saving has failed in LOK. Change-Id: Ie3bcdf9f6ca898b2763c31e6eb05c3a20be5859f Reviewed-on: https://gerrit.libreoffice.org/44399 Reviewed-by: pranavk <pran...@collabora.co.uk> Tested-by: pranavk <pran...@collabora.co.uk> diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp index 184f1200..45396631 100644 --- a/wsd/DocumentBroker.cpp +++ b/wsd/DocumentBroker.cpp @@ -656,6 +656,14 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId, return false; } + // Check that we are actually about to upload a successfully saved document. + if (!success) + { + LOG_ERR("Cannot save docKey [" << _docKey << "], the .uno:Save has failed in LOK."); + it->second->sendTextFrame("error: cmd=storage kind=savefailed"); + return false; + } + const Authorization auth = it->second->getAuthorization(); const auto uri = isSaveAs? saveAsPath: it->second->getPublicUri().toString(); commit b20faa8bdc36ba1bdf9a846b86c129a45abd4832 Author: Jan Holesovsky <ke...@collabora.com> Date: Mon Nov 6 12:44:37 2017 +0100 Save As: Advertise the correct size when uploading the new file. Change-Id: I9b20c4bdb7ddc848437edceae1a77ddb49d55133 Reviewed-on: https://gerrit.libreoffice.org/44357 Reviewed-by: Andras Timar <andras.ti...@collabora.com> Tested-by: Andras Timar <andras.ti...@collabora.com> diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp index b9549c06..f3af2d5c 100644 --- a/kit/ChildSession.cpp +++ b/kit/ChildSession.cpp @@ -620,6 +620,10 @@ bool ChildSession::downloadAs(const char* /*buffer*/, int /*length*/, const std: { std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex()); + LOG_DBG("Calling LOK's downloadAs with: '" << url.c_str() << "', '" << + (format.size() == 0 ? "(nullptr)" : format.c_str()) << "', '" << + (filterOptions.size() == 0 ? "(nullptr)" : filterOptions.c_str()) << "'."); + getLOKitDocument()->saveAs(url.c_str(), format.size() == 0 ? nullptr :format.c_str(), filterOptions.size() == 0 ? nullptr : filterOptions.c_str()); @@ -983,6 +987,10 @@ bool ChildSession::saveAs(const char* /*buffer*/, int /*length*/, const std::vec getLOKitDocument()->setView(_viewId); + LOG_DBG("Calling LOK's saveAs with: '" << url.c_str() << "', '" << + (format.size() == 0 ? "(nullptr)" : format.c_str()) << "', '" << + (filterOptions.size() == 0 ? "(nullptr)" : filterOptions.c_str()) << "'."); + success = getLOKitDocument()->saveAs(url.c_str(), format.size() == 0 ? nullptr :format.c_str(), filterOptions.size() == 0 ? nullptr : filterOptions.c_str()); diff --git a/test/UnitWOPISaveAs.cpp b/test/UnitWOPISaveAs.cpp index d981c551..578ec37f 100644 --- a/test/UnitWOPISaveAs.cpp +++ b/test/UnitWOPISaveAs.cpp @@ -34,13 +34,17 @@ public: void assertPutRelativeFileRequest(const Poco::Net::HTTPRequest& request) override { // spec says UTF-7... - CPPUNIT_ASSERT_EQUAL(std::string("/jan/hole+AWE-ovsk+AP0-/hello world.txt"), request.get("X-WOPI-SuggestedTarget")); + CPPUNIT_ASSERT_EQUAL(std::string("/jan/hole+AWE-ovsk+AP0-/hello world.pdf"), request.get("X-WOPI-SuggestedTarget")); + + // make sure it is a pdf - or at least that it is larger than what it + // used to be + CPPUNIT_ASSERT(std::stoul(request.get("X-WOPI-Size")) > _fileContent.size()); } bool filterSendMessage(const char* data, const size_t len, const WSOpCode /* code */, const bool /* flush */, int& /*unitReturn*/) override { std::string message(data, len); - if (message == "saveas: url=" + helpers::getTestServerURI() + "/something%20wopi/files/1?access_token=anything filename=hello%20world.txt") + if (message == "saveas: url=" + helpers::getTestServerURI() + "/something%20wopi/files/1?access_token=anything filename=hello%20world.pdf") { // successfully exit the test if we also got the outgoing message // notifying about saving the file @@ -61,7 +65,7 @@ public: initWebsocket("/wopi/files/0?access_token=anything"); helpers::sendTextFrame(*_ws->getLOOLWebSocket(), "load url=" + _wopiSrc, testName); - helpers::sendTextFrame(*_ws->getLOOLWebSocket(), "saveas url=wopi:///jan/hole%C5%A1ovsk%C3%BD/hello%20world.txt", testName); + helpers::sendTextFrame(*_ws->getLOOLWebSocket(), "saveas url=wopi:///jan/hole%C5%A1ovsk%C3%BD/hello%20world.pdf", testName); SocketPoll::wakeupWorld(); _phase = Phase::Polling; diff --git a/test/WopiTestServer.hpp b/test/WopiTestServer.hpp index 4f0e14c6..b20aa032 100644 --- a/test/WopiTestServer.hpp +++ b/test/WopiTestServer.hpp @@ -147,7 +147,7 @@ protected: assertPutRelativeFileRequest(request); std::string wopiURL = helpers::getTestServerURI() + "/something wopi/files/1?access_token=anything"; - std::string content = "{ \"Name\":\"hello world.txt\", \"Url\":\"" + wopiURL + "\" }"; + std::string content = "{ \"Name\":\"hello world.pdf\", \"Url\":\"" + wopiURL + "\" }"; std::ostringstream oss; oss << "HTTP/1.1 200 OK\r\n" diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index c6b25f8f..586f1ea9 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -689,6 +689,7 @@ bool ClientSession::handleKitToClientMessage(const char* buffer, const int lengt if (resultURL.getScheme() == "file" && !resultURL.getPath().empty()) { // this also sends the saveas: result + LOG_TRC("Save-as path: " << resultURL.getPath()); docBroker->saveAsToStorage(getId(), resultURL.getPath(), wopiFilename); } else diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp index ebb1994d..1ebd28e0 100644 --- a/wsd/Storage.cpp +++ b/wsd/Storage.cpp @@ -659,15 +659,17 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth) StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization& auth, const std::string& saveAsPath, const std::string& saveAsFilename) { // TODO: Check if this URI has write permission (canWrite = true) - const auto size = getFileSize(_jailedFilePath); const bool isSaveAs = !saveAsPath.empty() && !saveAsFilename.empty(); + const std::string filePath(isSaveAs? saveAsPath: _jailedFilePath); + + const auto size = getFileSize(filePath); Poco::URI uriObject(_uri); uriObject.setPath(isSaveAs? uriObject.getPath(): uriObject.getPath() + "/contents"); auth.authorizeURI(uriObject); - LOG_INF("Uploading URI via WOPI [" << uriObject.toString() << "] from [" << _jailedFilePath + "]."); + LOG_INF("Uploading URI via WOPI [" << uriObject.toString() << "] from [" << filePath + "]."); std::ostringstream oss; StorageBase::SaveResult saveResult(StorageBase::SaveResult::FAILED); @@ -736,7 +738,6 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization& addStorageDebugCookie(request); std::ostream& os = psession->sendRequest(request); - const std::string filePath(isSaveAs? saveAsPath: _jailedFilePath); std::ifstream ifs(filePath); Poco::StreamCopier::copyStream(ifs, os); commit 2355f2792fe9f7446bc275f8a435ca030d3e6759 Author: Jan Holesovsky <ke...@collabora.com> Date: Fri Nov 3 19:00:58 2017 +0100 Save As: Reload the newly created document after the Save As. Change-Id: Ibf979cce4fea13a31ece089394dab296158a159b Reviewed-on: https://gerrit.libreoffice.org/44283 Reviewed-by: Andras Timar <andras.ti...@collabora.com> Tested-by: Andras Timar <andras.ti...@collabora.com> diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js index 46ebabea..66514d7b 100644 --- a/loleaflet/src/control/Toolbar.js +++ b/loleaflet/src/control/Toolbar.js @@ -85,6 +85,9 @@ L.Map.include({ }, saveAs: function (url, format, options) { + if (url === undefined || url == null) { + return; + } if (format === undefined || format === null) { format = ''; } @@ -94,7 +97,7 @@ L.Map.include({ this.showBusy(_('Saving...'), false); this._socket.sendMessage('saveas ' + - 'url=' + url + ' ' + + 'url=wopi:' + encodeURIComponent(url) + ' ' + 'format=' + format + ' ' + 'options=' + options); }, diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js index 367e2f18..d363920e 100644 --- a/loleaflet/src/core/Socket.js +++ b/loleaflet/src/core/Socket.js @@ -122,6 +122,12 @@ L.Socket = L.Class.extend({ this.socket.send(msg); }, + _getParameterByName: function(url, name) { + name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); + var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'), results = regex.exec(url); + return results === null ? '' : results[1].replace(/\+/g, ' '); + }, + _onSocketOpen: function () { console.debug('_onSocketOpen:'); this._map._serverRecycling = false; @@ -563,8 +569,29 @@ L.Socket = L.Class.extend({ } else if (textMsg.startsWith('saveas:')) { this._map.hideBusy(); - // var url = command.url; // WOPI url - if needed at some stage - // var name = command.name; TODO dialog that the file was saved as "name" + if (command !== undefined && command.url !== undefined && command.url !== '') { + this.close(); + var url = command.url; + var accessToken = this._getParameterByName(url, 'access_token'); + var accessTokenTtl = this._getParameterByName(url, 'access_token_ttl'); + + if (accessToken !== undefined) { + if (accessTokenTtl === undefined) { + accessTokenTtl = 0; + } + this._map.options.docParams = { 'access_token': accessToken, 'access_token_ttl': accessTokenTtl }; + } + else { + this._map.options.docParams = {}; + } + + // setup for loading the new document, and trigger the load + var docUrl = url.split('?')[0]; + this._map.options.doc = docUrl; + this._map.options.wopiSrc = encodeURIComponent(docUrl); + this._map.loadDocument(); + } + // var name = command.name; - ignored, we get the new name via the wopi's BaseFileName } else if (textMsg.startsWith('statusindicator:')) { //FIXME: We should get statusindicator when saving too, no? diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js index 256f947a..2a00b05d 100644 --- a/loleaflet/src/map/handler/Map.WOPI.js +++ b/loleaflet/src/map/handler/Map.WOPI.js @@ -226,7 +226,7 @@ L.Map.WOPI = L.Handler.extend({ if (msg.Values) { if (msg.Values.Filename !== null && msg.Values.Filename !== undefined) { this._map.showBusy(_('Creating copy...'), false); - map.saveAs('wopi:' + msg.Values.Filename); + map.saveAs(msg.Values.Filename); } } } commit 513ffe36c114534895862bd652f3969bc94659cd Author: Jan Holesovsky <ke...@collabora.com> Date: Tue Oct 31 17:58:58 2017 +0100 Save As: UI for changing the document name. Change-Id: I23aba95ff0f8d867b021ba3cf0a6bc5eb4754f9d Reviewed-on: https://gerrit.libreoffice.org/44282 Reviewed-by: Andras Timar <andras.ti...@collabora.com> Tested-by: Andras Timar <andras.ti...@collabora.com> diff --git a/loleaflet/dist/loleaflet.html b/loleaflet/dist/loleaflet.html index 1bc8072c..f24f58e4 100644 --- a/loleaflet/dist/loleaflet.html +++ b/loleaflet/dist/loleaflet.html @@ -53,6 +53,8 @@ <input id="insertgraphic" type="file" style="position: fixed; top: -100em"> </div> + <input id="document-name-input" type="text" disabled="true"/> + <div id="closebuttonwrapper"> <div class="closebuttonimage" id="closebutton"></div> </div> diff --git a/loleaflet/dist/toolbar.css b/loleaflet/dist/toolbar.css index a4070770..31d3d209 100644 --- a/loleaflet/dist/toolbar.css +++ b/loleaflet/dist/toolbar.css @@ -72,6 +72,31 @@ width: 700px; } +#document-name-input { + position: fixed; + z-index: 1050; + right: 35px; + top: 2px; + width: 200px; + font-size: 16px; + //font-weight: bold; + border: 1px solid transparent; + background-color: transparent; +} + +#document-name-input.editable:focus { + border: 1px solid #bbbbbb; + background-color: white; +} + +#document-name-input.editable:hover { + border: 1px solid #bbbbbb; + background-color: white; + background-image: url('../images/lc_editdoc.svg'); + background-position: right; + background-repeat: no-repeat; +} + #closebuttonwrapper { position: fixed; z-index: 1050; diff --git a/loleaflet/dist/toolbar/toolbar.js b/loleaflet/dist/toolbar/toolbar.js index 9bd33b91..f030ce0d 100644 --- a/loleaflet/dist/toolbar/toolbar.js +++ b/loleaflet/dist/toolbar/toolbar.js @@ -812,6 +812,27 @@ function onSearchKeyPress(e) { } } +function documentNameConfirm() { + var value = $('#document-name-input').val(); + if (value !== null && value != '') { + map.saveAs(value); + } + map._onGotFocus(); +} + +function documentNameCancel() { + $('#document-name-input').val(map['wopi'].BaseFileName); + map._onGotFocus(); +} + +function onDocumentNameKeyPress(e) { + if (e.keyCode === 13) { // Enter key + documentNameConfirm(); + } else if (e.keyCode === 27) { // Escape key + documentNameCancel(); + } +} + function sortFontSizes() { var oldVal = $('.fontsizes-select').val(); var selectList = $('.fontsizes-select option'); @@ -1000,6 +1021,22 @@ map.on('wopiprops', function(e) { evt.preventDefault(); }); } + if (e.BaseFileName !== null) { + // set the document name into the name field + $('#document-name-input').val(e.BaseFileName); + } + if (e.UserCanNotWriteRelative === false) { + // Save As allowed + $('#document-name-input').prop('disabled', false); + $('#document-name-input').addClass('editable'); + $('#document-name-input').on('keypress', onDocumentNameKeyPress); + $('#document-name-input').on('focus', function() { map._onLostFocus(); /* hide the caret in the main document */ }); + $('#document-name-input').on('blur', documentNameCancel); + } else { + $('#document-name-input').prop('disabled', true); + $('#document-name-input').removeClass('editable'); + $('#document-name-input').off('keypress', onDocumentNameKeyPress); + } }); map.on('doclayerinit', function () { diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js index dc08693e..256f947a 100644 --- a/loleaflet/src/map/handler/Map.WOPI.js +++ b/loleaflet/src/map/handler/Map.WOPI.js @@ -8,6 +8,7 @@ L.Map.WOPI = L.Handler.extend({ // So use '*' because we still needs to send 'close' message to the parent frame which // wouldn't be possible otherwise. PostMessageOrigin: '*', + BaseFileName: '', DocumentLoadedTime: false, HidePrintOption: false, HideSaveOption: false, @@ -61,6 +62,7 @@ L.Map.WOPI = L.Handler.extend({ this.PostMessageOrigin = wopiInfo['PostMessageOrigin']; } + this.BaseFileName = wopiInfo['BaseFileName']; this.HidePrintOption = !!wopiInfo['HidePrintOption']; this.HideSaveOption = !!wopiInfo['HideSaveOption']; this.HideExportOption = !!wopiInfo['HideExportOption']; diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp index 06a40c99..184f1200 100644 --- a/wsd/DocumentBroker.cpp +++ b/wsd/DocumentBroker.cpp @@ -463,6 +463,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s if (wopifileinfo->_disableExport) wopifileinfo->_hideExportOption = true; + wopiInfo->set("BaseFileName", wopiStorage->getFileInfo()._filename); wopiInfo->set("HidePrintOption", wopifileinfo->_hidePrintOption); wopiInfo->set("HideSaveOption", wopifileinfo->_hideSaveOption); wopiInfo->set("HideExportOption", wopifileinfo->_hideExportOption); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits