[Libreoffice-commits] online.git: Branch 'distro/collabora/collabora-online-2-1' - 2 commits - kit/ChildSession.cpp loleaflet/src test/UnitWOPISaveAs.cpp test/WopiTestServer.hpp wsd/ClientSession.cpp wsd/DocumentBroker.cpp wsd/protocol.txt wsd/Storage.cpp wsd/Storage.hpp
Jan Holesovsky
kendy at collabora.com
Thu Oct 26 07:16:41 UTC 2017
kit/ChildSession.cpp | 9 +---
loleaflet/src/control/Toolbar.js | 5 --
loleaflet/src/core/Socket.js | 10 ++--
loleaflet/src/map/handler/Map.WOPI.js | 9 +---
test/UnitWOPISaveAs.cpp | 7 +--
test/WopiTestServer.hpp | 13 ++----
wsd/ClientSession.cpp | 8 +--
wsd/DocumentBroker.cpp | 23 +++++++----
wsd/Storage.cpp | 69 +++++++++++++++++++++++++++-------
wsd/Storage.hpp | 53 ++++++++++++++++++++++----
wsd/protocol.txt | 11 ++++-
11 files changed, 154 insertions(+), 63 deletions(-)
New commits:
commit fb8f9079cd4b72c06878ebb83ba1494294ec75b0
Author: Jan Holesovsky <kendy at collabora.com>
Date: Wed Oct 25 14:09:27 2017 +0200
tdf#99744 SaveAs: Report back to loleaflet that the saveas succeeded.
Change-Id: I670c8b4503c1a4c0a88001a1343f6dec2974e044
Reviewed-on: https://gerrit.libreoffice.org/43842
Reviewed-by: pranavk <pranavk at collabora.co.uk>
Tested-by: pranavk <pranavk at collabora.co.uk>
diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index ad43c8f0..d7db56b4 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -945,11 +945,10 @@ bool ChildSession::saveAs(const char* /*buffer*/, int /*length*/, const std::vec
Poco::URI::encode(url, "", encodedURL);
Poco::URI::encode(wopiFilename, "", encodedWopiFilename);
- sendTextFrame("saveas: url=" + encodedURL + " wopifilename=" + encodedWopiFilename);
- std::string successStr = success ? "true" : "false";
- sendTextFrame("unocommandresult: {"
- "\"commandName\":\"saveas\","
- "\"success\":\"" + successStr + "\"}");
+ if (success)
+ sendTextFrame("saveas: url=" + encodedURL + " filename=" + encodedWopiFilename);
+ else
+ sendTextFrame("error: cmd=storage kind=savefailed");
return true;
}
diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js
index 832abdb0..c47e523d 100644
--- a/loleaflet/src/control/Toolbar.js
+++ b/loleaflet/src/control/Toolbar.js
@@ -93,13 +93,10 @@ L.Map.include({
}
this.showBusy(_('Saving...'), false);
- // TakeOwnership: we are performing a 'real' save-as, the document
- // is just getting a new place, ie. it will get the
- // '.uno:ModifiedStatus' upon completion.
this._socket.sendMessage('saveas ' +
'url=' + url + ' ' +
'format=' + format + ' ' +
- 'options=TakeOwnership,' + options);
+ 'options=' + options);
},
applyStyle: function (style, familyName) {
diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js
index e3c549b8..e5028b69 100644
--- a/loleaflet/src/core/Socket.js
+++ b/loleaflet/src/core/Socket.js
@@ -559,10 +559,9 @@ L.Socket = L.Class.extend({
this._map._docLayer._debugRenderCount = command.rendercount;
}
else if (textMsg.startsWith('saveas:')) {
- textMsg = (textMsg.substring(7)).trim();
- // var url = textMsg.substring(0, textMsg.indexOf(' '));
- // var fileName = textMsg.substring(textMsg.indexOf(' '));
- /// redirect or not?
+ 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"
}
else if (textMsg.startsWith('statusindicator:')) {
//FIXME: We should get statusindicator when saving too, no?
@@ -784,6 +783,9 @@ L.Socket = L.Class.extend({
else if (tokens[i].substring(0, 5) === 'char=') {
command.char = tokens[i].substring(5);
}
+ else if (tokens[i].substring(0, 4) === 'url=') {
+ command.url = tokens[i].substring(4);
+ }
else if (tokens[i].substring(0, 7) === 'viewid=') {
command.viewid = tokens[i].substring(7);
}
diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index 560be0c8..e2a3840d 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -211,15 +211,12 @@ L.Map.WOPI = L.Handler.extend({
this._postMessage({msgId: 'Get_Export_Formats_Resp', args: exportFormatsResp});
}
else if (msg.MessageId === 'Action_SaveAs') {
- /* TODO
if (msg.Values) {
- if (msg.Values.Filename === null || msg.Values.Filename === undefined) {
- msg.Values.Filename = '';
+ if (msg.Values.Filename !== null && msg.Values.Filename !== undefined) {
+ this._map.showBusy(_('Creating copy...'), false);
+ map.saveAs('wopi:' + msg.Values.Filename);
}
- this.showBusy(_('Creating copy...'), false);
- map.saveAs(msg.Values.Filename);
}
- */
}
},
diff --git a/test/UnitWOPISaveAs.cpp b/test/UnitWOPISaveAs.cpp
index 82e89de0..cb9ff9c3 100644
--- a/test/UnitWOPISaveAs.cpp
+++ b/test/UnitWOPISaveAs.cpp
@@ -31,7 +31,7 @@ public:
{
}
- void assertPutFileRelativeRequest(const Poco::Net::HTTPRequest& request) override
+ 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"));
diff --git a/test/WopiTestServer.hpp b/test/WopiTestServer.hpp
index 6324114d..4f0e14c6 100644
--- a/test/WopiTestServer.hpp
+++ b/test/WopiTestServer.hpp
@@ -64,7 +64,7 @@ public:
{
}
- virtual void assertPutFileRelativeRequest(const Poco::Net::HTTPRequest& /*request*/)
+ virtual void assertPutRelativeFileRequest(const Poco::Net::HTTPRequest& /*request*/)
{
}
@@ -140,17 +140,14 @@ protected:
}
else if (request.getMethod() == "POST" && (uriReq.getPath() == "/wopi/files/0" || uriReq.getPath() == "/wopi/files/1"))
{
- LOG_INF("Fake wopi host request, handling PutFileRelative: " << uriReq.getPath());
+ LOG_INF("Fake wopi host request, handling PutRelativeFile: " << uriReq.getPath());
CPPUNIT_ASSERT_EQUAL(std::string("PUT_RELATIVE"), request.get("X-WOPI-Override"));
- assertPutFileRelativeRequest(request);
+ assertPutRelativeFileRequest(request);
- Poco::URI wopiURL(helpers::getTestServerURI() + "/wopi/files/1");
- std::string url;
- Poco::URI::encode(wopiURL.toString(), ":/?", url);
-
- std::string content = "{ \"Name\":\"hello world.txt\", \"Url\":\"" + url + "\" }";
+ std::string wopiURL = helpers::getTestServerURI() + "/something wopi/files/1?access_token=anything";
+ std::string content = "{ \"Name\":\"hello world.txt\", \"Url\":\"" + wopiURL + "\" }";
std::ostringstream oss;
oss << "HTTP/1.1 200 OK\r\n"
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index 5bd105ad..e4e41cae 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -626,7 +626,7 @@ bool ClientSession::handleKitToClientMessage(const char* buffer, const int lengt
}
std::string encodedWopiFilename;
- if (!getTokenString(tokens[2], "wopifilename", encodedWopiFilename))
+ if (!getTokenString(tokens[2], "filename", encodedWopiFilename))
{
LOG_ERR("Bad syntax for: " << firstLine);
return false;
@@ -665,11 +665,11 @@ bool ClientSession::handleKitToClientMessage(const char* buffer, const int lengt
// Normal SaveAs - save to Storage and log result.
if (resultURL.getScheme() == "file" && !resultURL.getPath().empty())
{
+ // this also sends the saveas: result
docBroker->saveAsToStorage(getId(), resultURL.getPath(), wopiFilename);
}
-
- if (!isCloseFrame())
- forwardToClient(payload);
+ else
+ sendTextFrame("error: cmd=storage kind=savefailed");
}
else
{
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 308aecd6..966c3184 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -652,7 +652,7 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId,
assert(_storage && _tileCache);
StorageBase::SaveResult storageSaveResult = _storage->saveLocalFileToStorage(auth, saveAsPath, saveAsFilename);
- if (storageSaveResult == StorageBase::SaveResult::OK)
+ if (storageSaveResult.getResult() == StorageBase::SaveResult::OK)
{
if (!isSaveAs)
{
@@ -674,12 +674,21 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId,
}
else
{
- Log::debug() << "Saved As docKey [" << _docKey << "] to URI [" << uri
- << "] successfully.";
+ // normalize the url (mainly to " " -> "%20")
+ std::string url = Poco::URI(storageSaveResult.getSaveAsUrl()).toString();
+
+ // encode the name
+ std::string encodedName;
+ Poco::URI::encode(storageSaveResult.getSaveAsName(), "", encodedName);
+
+ it->second->sendTextFrame("saveas: url=" + url + " filename=" + encodedName);
+
+ Log::debug() << "Saved As docKey [" << _docKey << "] to URI [" << url
+ << " with name '" << encodedName << "'] successfully.";
}
return true;
}
- else if (storageSaveResult == StorageBase::SaveResult::DISKFULL)
+ else if (storageSaveResult.getResult() == StorageBase::SaveResult::DISKFULL)
{
LOG_WRN("Disk full while saving docKey [" << _docKey << "] to URI [" << uri <<
"]. Making all sessions on doc read-only and notifying clients.");
@@ -691,18 +700,18 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId,
sessionIt.second->sendTextFrame("error: cmd=storage kind=savediskfull");
}
}
- else if (storageSaveResult == StorageBase::SaveResult::UNAUTHORIZED)
+ else if (storageSaveResult.getResult() == StorageBase::SaveResult::UNAUTHORIZED)
{
LOG_ERR("Cannot save docKey [" << _docKey << "] to storage URI [" << uri << "]. Invalid or expired access token. Notifying client.");
it->second->sendTextFrame("error: cmd=storage kind=saveunauthorized");
}
- else if (storageSaveResult == StorageBase::SaveResult::FAILED)
+ else if (storageSaveResult.getResult() == StorageBase::SaveResult::FAILED)
{
//TODO: Should we notify all clients?
LOG_ERR("Failed to save docKey [" << _docKey << "] to URI [" << uri << "]. Notifying client.");
it->second->sendTextFrame("error: cmd=storage kind=savefailed");
}
- else if (storageSaveResult == StorageBase::SaveResult::DOC_CHANGED)
+ else if (storageSaveResult.getResult() == StorageBase::SaveResult::DOC_CHANGED)
{
LOG_ERR("PutFile says that Document changed in storage");
_documentChangedInStorage = true;
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index 36247a68..05f3b945 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -324,7 +324,7 @@ StorageBase::SaveResult LocalStorage::saveLocalFileToStorage(const Authorization
throw;
}
- return StorageBase::SaveResult::OK;
+ return StorageBase::SaveResult(StorageBase::SaveResult::OK);
}
namespace {
@@ -674,7 +674,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
LOG_INF("Uploading URI via WOPI [" << uriObject.toString() << "] from [" << _jailedFilePath + "].");
std::ostringstream oss;
- StorageBase::SaveResult saveResult = StorageBase::SaveResult::FAILED;
+ StorageBase::SaveResult saveResult(StorageBase::SaveResult::FAILED);
try
{
std::unique_ptr<Poco::Net::HTTPClientSession> psession(getHTTPClientSession(uriObject));
@@ -748,7 +748,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
std::istream& rs = psession->receiveResponse(response);
Poco::StreamCopier::copyStream(rs, oss);
- std::string wopiLog(isSaveAs? "WOPI::PutFileRelative": "WOPI::PutFile");
+ std::string wopiLog(isSaveAs? "WOPI::PutRelativeFile": "WOPI::PutFile");
LOG_INF(wopiLog << " response: " << oss.str());
LOG_INF(wopiLog << " uploaded " << size << " bytes from [" << filePath <<
"] -> [" << uriObject.toString() << "]: " <<
@@ -756,7 +756,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK)
{
- saveResult = StorageBase::SaveResult::OK;
+ saveResult.setResult(StorageBase::SaveResult::OK);
Poco::JSON::Object::Ptr object;
if (parseJSON(oss.str(), object))
{
@@ -764,38 +764,49 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
LOG_TRC(wopiLog << " returns LastModifiedTime [" << lastModifiedTime << "].");
_fileInfo._modifiedTime = iso8601ToTimestamp(lastModifiedTime);
+ if (isSaveAs)
+ {
+ const std::string name = getJSONValue<std::string>(object, "Name");
+ LOG_TRC(wopiLog << " returns Name [" << name << "].");
+
+ const std::string url = getJSONValue<std::string>(object, "Url");
+ LOG_TRC(wopiLog << " returns Url [" << url << "].");
+
+ saveResult.setSaveAsResult(name, url);
+ }
+
// Reset the force save flag now, if any, since we are done saving
// Next saves shouldn't be saved forcefully unless commanded
_forceSave = false;
}
else
{
- LOG_WRN("Invalid/Missing JSON found in " << wopiLog << " response");
+ LOG_WRN("Invalid or missing JSON in " << wopiLog << " HTTP_OK response");
}
}
else if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_REQUESTENTITYTOOLARGE)
{
- saveResult = StorageBase::SaveResult::DISKFULL;
+ saveResult.setResult(StorageBase::SaveResult::DISKFULL);
}
else if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED)
{
- saveResult = StorageBase::SaveResult::UNAUTHORIZED;
+ saveResult.setResult(StorageBase::SaveResult::UNAUTHORIZED);
}
else if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_CONFLICT)
{
- saveResult = StorageBase::SaveResult::CONFLICT;
+ saveResult.setResult(StorageBase::SaveResult::CONFLICT);
Poco::JSON::Object::Ptr object;
if (parseJSON(oss.str(), object))
{
const unsigned loolStatusCode = getJSONValue<unsigned>(object, "LOOLStatusCode");
if (loolStatusCode == static_cast<unsigned>(LOOLStatusCode::DOC_CHANGED))
{
- saveResult = StorageBase::SaveResult::DOC_CHANGED;
+ saveResult.setResult(StorageBase::SaveResult::DOC_CHANGED);
}
}
else
{
- LOG_WRN("Invalid/missing JSON in " << wopiLog << " response");
+ LOG_WRN("Invalid or missing JSON in " << wopiLog << " HTTP_CONFLICT response");
}
}
}
@@ -803,7 +814,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
{
LOG_ERR("Cannot save file to WOPI storage uri [" + uriObject.toString() + "]. Error: " << pexc.displayText() <<
(pexc.nested() ? " (" + pexc.nested()->displayText() + ")" : ""));
- saveResult = StorageBase::SaveResult::FAILED;
+ saveResult.setResult(StorageBase::SaveResult::FAILED);
}
return saveResult;
@@ -819,7 +830,7 @@ std::string WebDAVStorage::loadStorageFileToLocal(const Authorization& /*auth*/)
StorageBase::SaveResult WebDAVStorage::saveLocalFileToStorage(const Authorization& /*auth*/, const std::string& /*saveAsPath*/, const std::string& /*saveAsFilename*/)
{
// TODO: implement webdav PUT.
- return StorageBase::SaveResult::OK;
+ return StorageBase::SaveResult(StorageBase::SaveResult::OK);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/wsd/Storage.hpp b/wsd/Storage.hpp
index d698ba45..90dad874 100644
--- a/wsd/Storage.hpp
+++ b/wsd/Storage.hpp
@@ -53,14 +53,53 @@ public:
size_t _size;
};
- enum class SaveResult
+ class SaveResult
{
- OK,
- DISKFULL,
- UNAUTHORIZED,
- DOC_CHANGED, /* Document changed in storage */
- CONFLICT,
- FAILED
+ public:
+ enum Result
+ {
+ OK,
+ DISKFULL,
+ UNAUTHORIZED,
+ DOC_CHANGED, /**< Document changed in storage */
+ CONFLICT,
+ FAILED
+ };
+
+ SaveResult(Result result) : _result(result)
+ {
+ }
+
+ void setResult(Result result)
+ {
+ _result = result;
+ }
+
+ Result getResult() const
+ {
+ return _result;
+ }
+
+ void setSaveAsResult(const std::string& name, const std::string& url)
+ {
+ _saveAsName = name;
+ _saveAsUrl = url;
+ }
+
+ const std::string& getSaveAsName() const
+ {
+ return _saveAsName;
+ }
+
+ const std::string& getSaveAsUrl() const
+ {
+ return _saveAsUrl;
+ }
+
+ private:
+ Result _result;
+ std::string _saveAsName;
+ std::string _saveAsUrl;
};
enum class LOOLStatusCode
diff --git a/wsd/protocol.txt b/wsd/protocol.txt
index 7ac54b68..9af08e88 100644
--- a/wsd/protocol.txt
+++ b/wsd/protocol.txt
@@ -112,6 +112,8 @@ saveas url=<url> format=<format> options=<options>
<url> is a URL, encoded. <format> is also URL-encoded, i.e. spaces as %20 and it can be empty
options are the whole rest of the line, not URL-encoded, and can be empty
+ If <url> uses 'wopi:' as the protocol, the path is treated as the path on
+ the wopi host.
selecttext type=<type> x=<x> y=<y>
@@ -307,6 +309,12 @@ pong rendercount=<num>
sent in reply to a 'ping' message, where <num> is the total number
of rendered tiles of the document.
+saveas: url=<url> name=<name>
+
+ <url> is a wopi URL of the newly created file, including the access token.
+ <name> is the resulting name (without path) that was created on the wopi
+ host. It can differ from what was requested in case the file already existed.
+
status: type=<typeName> parts=<numberOfParts> current=<currentPartNumber> width=<width> height=<height> viewid=<viewId> [partNames]
<typeName> is 'text, 'spreadsheet', 'presentation', 'drawing' or 'other. Others are numbers.
@@ -449,10 +457,11 @@ nextmessage: size=<upperlimit>
one doesn't need to use a pre-allocated buffer when receiving
WebSocket messages, this will go away.
-saveas: url=<url>
+saveas: url=<url> filename=<filename>
<url> is a URL of the destination, encoded. Sent from the child to the
parent after a saveAs() completed.
+ <filename> is the resulting jailed filename of the newly created file.
client-<sessionId> <Payload Message>
commit 48d566599e7151bc2069f459e6ec1ec599e15f10
Author: Jan Holesovsky <kendy at collabora.com>
Date: Tue Oct 24 11:31:39 2017 +0200
tdf#99744 SaveAs: Use X-WOPI-SuggestedTarget instead of X-WOPI-RelativeTarget.
And the correct encoding - UTF-7 (huh).
Change-Id: I6634fedb598c620128cc25a3e8fdc46e4096a756
Reviewed-on: https://gerrit.libreoffice.org/43841
Reviewed-by: pranavk <pranavk at collabora.co.uk>
Tested-by: pranavk <pranavk at collabora.co.uk>
diff --git a/test/UnitWOPISaveAs.cpp b/test/UnitWOPISaveAs.cpp
index 4bd3e9e0..82e89de0 100644
--- a/test/UnitWOPISaveAs.cpp
+++ b/test/UnitWOPISaveAs.cpp
@@ -33,7 +33,8 @@ public:
void assertPutFileRelativeRequest(const Poco::Net::HTTPRequest& request) override
{
- CPPUNIT_ASSERT_EQUAL(std::string("/path/to/hello world.txt"), request.get("X-WOPI-RelativeTarget"));
+ // spec says UTF-7...
+ CPPUNIT_ASSERT_EQUAL(std::string("/jan/hole+AWE-ovsk+AP0-/hello world.txt"), request.get("X-WOPI-SuggestedTarget"));
exitTest(TestResult::Ok);
}
@@ -49,7 +50,7 @@ public:
initWebsocket("/wopi/files/0?access_token=anything");
helpers::sendTextFrame(*_ws->getLOOLWebSocket(), "load url=" + _wopiSrc, testName);
- helpers::sendTextFrame(*_ws->getLOOLWebSocket(), "saveas url=wopi:///path/to/hello%20world.txt", testName);
+ helpers::sendTextFrame(*_ws->getLOOLWebSocket(), "saveas url=wopi:///jan/hole%C5%A1ovsk%C3%BD/hello%20world.txt", testName);
SocketPoll::wakeupWorld();
_phase = Phase::Polling;
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index c36c07ca..36247a68 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -14,6 +14,7 @@
#include <algorithm>
#include <cassert>
#include <fstream>
+#include <iconv.h>
#include <string>
#include <Poco/DateTime.h>
@@ -664,7 +665,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
// TODO: Check if this URI has write permission (canWrite = true)
const auto size = getFileSize(_jailedFilePath);
- const bool isSaveAs = !saveAsPath.empty();
+ const bool isSaveAs = !saveAsPath.empty() && !saveAsFilename.empty();
Poco::URI uriObject(_uri);
uriObject.setPath(isSaveAs? uriObject.getPath(): uriObject.getPath() + "/contents");
@@ -701,7 +702,36 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
{
// save as
request.set("X-WOPI-Override", "PUT_RELATIVE");
- request.set("X-WOPI-RelativeTarget", saveAsFilename);
+
+ // the suggested target has to be in UTF-7; default to extension
+ // only when the conversion fails
+ std::string suggestedTarget = "." + Poco::Path(saveAsFilename).getExtension();
+
+ iconv_t cd = iconv_open("UTF-7", "UTF-8");
+ if (cd == (iconv_t) -1)
+ LOG_ERR("Failed to initialize iconv for UTF-7 conversion, using '" << suggestedTarget << "'.");
+ else
+ {
+ std::vector<char> input(saveAsFilename.begin(), saveAsFilename.end());
+ std::vector<char> buffer(8 * saveAsFilename.size());
+
+ char* in = &input[0];
+ size_t in_left = input.size();
+ char* out = &buffer[0];
+ size_t out_left = buffer.size();
+
+ if (iconv(cd, &in, &in_left, &out, &out_left) == (size_t) -1)
+ LOG_ERR("Failed to convert '" << saveAsFilename << "' to UTF-7, using '" << suggestedTarget << "'.");
+ else
+ {
+ // conversion succeeded
+ suggestedTarget = std::string(&buffer[0], buffer.size() - out_left);
+ LOG_TRC("Converted '" << saveAsFilename << "' to UTF-7 as '" << suggestedTarget << "'.");
+ }
+ }
+
+ request.set("X-WOPI-SuggestedTarget", suggestedTarget);
+
request.set("X-WOPI-Size", std::to_string(size));
}
More information about the Libreoffice-commits
mailing list