[Libreoffice-commits] online.git: Branch 'distro/collabora/collabora-online-4-0' - common/Session.cpp common/Session.hpp kit/ChildSession.cpp kit/ChildSession.hpp kit/Kit.cpp test/data test/Makefile.am test/UnitWOPITemplate.cpp test/WhiteBoxTests.cpp wsd/ClientSession.cpp wsd/DocumentBroker.cpp wsd/LOOLWSD.cpp wsd/Storage.cpp wsd/Storage.hpp
Henry Castro (via logerrit)
logerrit at kemper.freedesktop.org
Fri Nov 15 10:07:30 UTC 2019
common/Session.cpp | 7 +
common/Session.hpp | 2
kit/ChildSession.cpp | 17 +++-
kit/ChildSession.hpp | 3
kit/Kit.cpp | 10 +-
test/Makefile.am | 10 +-
test/UnitWOPITemplate.cpp | 172 ++++++++++++++++++++++++++++++++++++++++++++++
test/WhiteBoxTests.cpp | 3
test/data/test.ott |binary
wsd/ClientSession.cpp | 16 +++-
wsd/DocumentBroker.cpp | 14 ++-
wsd/LOOLWSD.cpp | 3
wsd/Storage.cpp | 24 +++++-
wsd/Storage.hpp | 14 ++-
14 files changed, 264 insertions(+), 31 deletions(-)
New commits:
commit 40dd5c05881675b223ea79c412ba75e83ad13eb3
Author: Henry Castro <hcastro at collabora.com>
AuthorDate: Tue May 21 23:33:26 2019 -0400
Commit: Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Nov 15 11:07:10 2019 +0100
wsd: introduce "TemplateSource" WOPI property
Reviewed-on: https://gerrit.libreoffice.org/76190
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
Reviewed-by: Jan Holesovsky <kendy at collabora.com>
(cherry picked from commit 760864870fa8992fda58be03f3f55232b247506f)
Change-Id: I9df1d5d0d4be7fe10ee15c40c36195c86ccf857e
Reviewed-on: https://gerrit.libreoffice.org/82710
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
Reviewed-by: Jan Holesovsky <kendy at collabora.com>
diff --git a/common/Session.cpp b/common/Session.cpp
index 040bbc25e..414d35869 100644
--- a/common/Session.cpp
+++ b/common/Session.cpp
@@ -76,7 +76,7 @@ bool Session::sendBinaryFrame(const char *buffer, int length)
return sendMessage(buffer, length, WSOpCode::Binary) >= length;
}
-void Session::parseDocOptions(const std::vector<std::string>& tokens, int& part, std::string& timestamp)
+void Session::parseDocOptions(const std::vector<std::string>& tokens, int& part, std::string& timestamp, std::string& doctemplate)
{
// First token is the "load" command itself.
size_t offset = 1;
@@ -167,6 +167,11 @@ void Session::parseDocOptions(const std::vector<std::string>& tokens, int& part,
timestamp = value;
++offset;
}
+ else if (name == "template")
+ {
+ doctemplate = value;
+ ++offset;
+ }
}
Util::mapAnonymized(_userId, _userIdAnonym);
diff --git a/common/Session.hpp b/common/Session.hpp
index 1934c9465..d70d687c2 100644
--- a/common/Session.hpp
+++ b/common/Session.hpp
@@ -135,7 +135,7 @@ protected:
/// Parses the options of the "load" command,
/// shared between MasterProcessSession::loadDocument() and ChildProcessSession::loadDocument().
- void parseDocOptions(const std::vector<std::string>& tokens, int& part, std::string& timestamp);
+ void parseDocOptions(const std::vector<std::string>& tokens, int& part, std::string& timestamp, std::string& doctemplate);
void updateLastActivityTime()
{
diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index d75809532..da16d807f 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -545,8 +545,8 @@ bool ChildSession::loadDocument(const char * /*buffer*/, int /*length*/, const s
return false;
}
- std::string timestamp;
- parseDocOptions(tokens, part, timestamp);
+ std::string timestamp, doctemplate;
+ parseDocOptions(tokens, part, timestamp, doctemplate);
std::string renderOpts;
if (!getDocOptions().empty())
@@ -567,7 +567,7 @@ bool ChildSession::loadDocument(const char * /*buffer*/, int /*length*/, const s
const bool loaded = _docManager.onLoad(getId(), getJailedFilePath(), getJailedFilePathAnonym(),
getUserName(), getUserNameAnonym(),
getDocPassword(), renderOpts, getHaveDocPassword(),
- getLang(), getWatermarkText());
+ getLang(), getWatermarkText(), doctemplate);
if (!loaded || _viewId < 0)
{
LOG_ERR("Failed to get LoKitDocument instance for [" << getJailedFilePathAnonym() << "].");
@@ -579,6 +579,17 @@ bool ChildSession::loadDocument(const char * /*buffer*/, int /*length*/, const s
std::unique_lock<std::mutex> lockLokDoc(_docManager.getDocumentMutex());
+ if (!doctemplate.empty())
+ {
+ std::string url = getJailedFilePath();
+ bool success = getLOKitDocument()->saveAs(url.c_str(), nullptr, nullptr);
+ if (!success)
+ {
+ LOG_ERR("Failed to save template [" << getJailedFilePath() << "].");
+ return false;
+ }
+ }
+
getLOKitDocument()->setView(_viewId);
_docType = LOKitHelper::getDocumentTypeAsString(getLOKitDocument()->get());
diff --git a/kit/ChildSession.hpp b/kit/ChildSession.hpp
index bbcc2c773..e26b8b78f 100644
--- a/kit/ChildSession.hpp
+++ b/kit/ChildSession.hpp
@@ -47,7 +47,8 @@ public:
const std::string& renderOpts,
const bool haveDocPassword,
const std::string& lang,
- const std::string& watermarkText) = 0;
+ const std::string& watermarkText,
+ const std::string& docTemplate) = 0;
/// Unload a client session, which unloads the document
/// if it is the last and only.
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 66042d9d3..e449a9b95 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -1241,7 +1241,8 @@ private:
const std::string& renderOpts,
const bool haveDocPassword,
const std::string& lang,
- const std::string& watermarkText) override
+ const std::string& watermarkText,
+ const std::string& docTemplate) override
{
std::unique_lock<std::mutex> lock(_mutex);
@@ -1270,7 +1271,7 @@ private:
try
{
- if (!load(session, uri, uriAnonym, userName, userNameAnonym, docPassword, renderOpts, haveDocPassword, lang, watermarkText))
+ if (!load(session, uri, uriAnonym, userName, userNameAnonym, docPassword, renderOpts, haveDocPassword, lang, watermarkText, docTemplate))
{
return false;
}
@@ -1525,7 +1526,8 @@ private:
const std::string& renderOpts,
const bool haveDocPassword,
const std::string& lang,
- const std::string& watermarkText)
+ const std::string& watermarkText,
+ const std::string& docTemplate)
{
const std::string sessionId = session->getId();
@@ -1558,7 +1560,7 @@ private:
LOG_DBG("Calling lokit::documentLoad(" << uriAnonym << ", \"" << options << "\").");
Timestamp timestamp;
- _loKitDocument.reset(_loKit->documentLoad(uri.c_str(), options.c_str()));
+ _loKitDocument.reset(_loKit->documentLoad(docTemplate.empty() ? uri.c_str() : docTemplate.c_str(), options.c_str()));
LOG_DBG("Returned lokit::documentLoad(" << uriAnonym << ") in " << (timestamp.elapsed() / 1000.) << "ms.");
#ifdef IOS
// The iOS app (and the Android one) has max one document open at a time, so we can keep
diff --git a/test/Makefile.am b/test/Makefile.am
index 8b4bb0ed0..cc41aa6a4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -9,7 +9,7 @@ check_PROGRAMS = test fakesockettest
noinst_PROGRAMS = test fakesockettest unittest
-AM_CXXFLAGS = $(CPPUNIT_CFLAGS) -DTDOC=\"$(top_srcdir)/test/data\" \
+AM_CXXFLAGS = $(CPPUNIT_CFLAGS) -DTDOC=\"$(abs_top_srcdir)/test/data\" \
-I${top_srcdir}/common -I${top_srcdir}/net -I${top_srcdir}/wsd -I${top_srcdir}/kit
noinst_LTLIBRARIES = \
@@ -21,8 +21,7 @@ noinst_LTLIBRARIES = \
unit-wopi.la unit-wopi-saveas.la \
unit-wopi-ownertermination.la unit-wopi-versionrestore.la \
unit-wopi-documentconflict.la unit_wopi_renamefile.la \
- unit-wopi-loadencoded.la
-
+ unit-wopi-loadencoded.la unit-wopi-temp.la
MAGIC_TO_FORCE_SHLIB_CREATION = -rpath /dummy
AM_LDFLAGS = -pthread -module $(MAGIC_TO_FORCE_SHLIB_CREATION) $(ZLIB_LIBS)
@@ -112,6 +111,8 @@ unit_wopi_renamefile_la_SOURCES = UnitWOPIRenameFile.cpp
unit_wopi_renamefile_la_LIBADD = $(CPPUNIT_LIBS)
unit_wopi_loadencoded_la_SOURCES = UnitWOPILoadEncoded.cpp
unit_wopi_loadencoded_la_LIBADD = $(CPPUNIT_LIBS)
+unit_wopi_temp_la_SOURCES = UnitWOPITemplate.cpp
+unit_wopi_temp_la_LIBADD = $(CPPUNIT_LIBS)
if HAVE_LO_PATH
SYSTEM_STAMP = @SYSTEMPLATE_PATH@/system_stamp
@@ -129,7 +130,8 @@ check-local:
TESTS = unit-convert.la unit-prefork.la unit-tilecache.la unit-timeout.la \
unit-oauth.la unit-wopi.la unit-wopi-saveas.la \
unit-wopi-ownertermination.la unit-wopi-versionrestore.la \
- unit-wopi-documentconflict.la unit_wopi_renamefile.la
+ unit-wopi-documentconflict.la unit_wopi_renamefile.la \
+ unit-wopi-temp.la
# TESTS = unit-client.la
# TESTS += unit-admin.la
# TESTS += unit-storage.la
diff --git a/test/UnitWOPITemplate.cpp b/test/UnitWOPITemplate.cpp
new file mode 100644
index 000000000..1ab588799
--- /dev/null
+++ b/test/UnitWOPITemplate.cpp
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <config.h>
+
+#include <WopiTestServer.hpp>
+#include <Log.hpp>
+#include <Unit.hpp>
+#include <UnitHTTP.hpp>
+#include <helpers.hpp>
+#include <Poco/Net/HTTPRequest.h>
+#include <Poco/Util/LayeredConfiguration.h>
+
+class UnitWOPITemplate : public WopiTestServer
+{
+ enum class Phase
+ {
+ LoadTemplate,
+ SaveDoc,
+ CloseDoc,
+ Polling
+ } _phase;
+
+public:
+ UnitWOPITemplate() :
+ _phase(Phase::LoadTemplate)
+ {
+ }
+
+ virtual bool handleHttpRequest(const Poco::Net::HTTPRequest& request, Poco::MemoryInputStream& /*message*/, std::shared_ptr<StreamSocket>& socket) override
+ {
+ Poco::URI uriReq(request.getURI());
+ LOG_INF("Fake wopi host request: " << uriReq.toString() << " method " << request.getMethod());
+
+ // CheckFileInfo
+ if (request.getMethod() == "GET" && uriReq.getPath() == "/wopi/files/10")
+ {
+ LOG_INF("Fake wopi host request, handling CheckFileInfo: " << uriReq.getPath());
+
+ Poco::LocalDateTime now;
+ Poco::JSON::Object::Ptr fileInfo = new Poco::JSON::Object();
+ fileInfo->set("BaseFileName", "test.odt");
+ fileInfo->set("TemplateSource", std::string("http://127.0.0.1:") + std::to_string(helpers::getClientPort()) + "/test.ott"); // must be http, otherwise Neon in the core complains
+ fileInfo->set("Size", _fileContent.size());
+ fileInfo->set("Version", "1.0");
+ fileInfo->set("OwnerId", "test");
+ fileInfo->set("UserId", "test");
+ fileInfo->set("UserFriendlyName", "test");
+ fileInfo->set("UserCanWrite", "true");
+ fileInfo->set("PostMessageOrigin", "localhost");
+ fileInfo->set("LastModifiedTime", Poco::DateTimeFormatter::format(Poco::DateTime(_fileLastModifiedTime), Poco::DateTimeFormat::ISO8601_FRAC_FORMAT));
+ fileInfo->set("EnableOwnerTermination", "true");
+
+ std::ostringstream jsonStream;
+ fileInfo->stringify(jsonStream);
+ std::string responseString = jsonStream.str();
+
+ const std::string mimeType = "application/json; charset=utf-8";
+
+ std::ostringstream oss;
+ oss << "HTTP/1.1 200 OK\r\n"
+ << "Last-Modified: " << Poco::DateTimeFormatter::format(_fileLastModifiedTime, Poco::DateTimeFormat::HTTP_FORMAT) << "\r\n"
+ << "User-Agent: " << WOPI_AGENT_STRING << "\r\n"
+ << "Content-Length: " << responseString.size() << "\r\n"
+ << "Content-Type: " << mimeType << "\r\n"
+ << "\r\n"
+ << responseString;
+
+ socket->send(oss.str());
+ socket->shutdown();
+
+ return true;
+ }
+ else if ((request.getMethod() == "OPTIONS" || request.getMethod() == "HEAD" || request.getMethod() == "PROPFIND") && uriReq.getPath() == "/test.ott")
+ {
+ std::ostringstream oss;
+ oss << "HTTP/1.1 200 OK\r\n"
+ << "Allow: GET\r\n"
+ << "User-Agent: " << WOPI_AGENT_STRING << "\r\n"
+ << "\r\n";
+
+ socket->send(oss.str());
+ socket->shutdown();
+
+ return true;
+ }
+ // Get the template
+ else if (request.getMethod() == "GET" && uriReq.getPath() == "/test.ott")
+ {
+ LOG_INF("Fake wopi host request, handling template GetFile: " << uriReq.getPath());
+
+ Poco::Net::HTTPResponse response;
+ HttpHelper::sendFile(socket, TDOC "/test.ott", "", response);
+ socket->shutdown();
+
+ return true;
+ }
+ // Save template
+ else if (request.getMethod() == "POST" && uriReq.getPath() == "/wopi/files/10/contents")
+ {
+ LOG_INF("Fake wopi host request, handling PutFile: " << uriReq.getPath());
+
+ std::streamsize size = request.getContentLength();
+ CPPUNIT_ASSERT( size > 0 );
+
+ std::ostringstream oss;
+ oss << "HTTP/1.1 200 OK\r\n"
+ << "User-Agent: " << WOPI_AGENT_STRING << "\r\n"
+ << "\r\n"
+ << "{\"LastModifiedTime\": \"" << Poco::DateTimeFormatter::format(_fileLastModifiedTime, Poco::DateTimeFormat::ISO8601_FRAC_FORMAT) << "\" }";
+
+ socket->send(oss.str());
+ socket->shutdown();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<int>(Phase::SaveDoc), static_cast<int>(_phase));
+ _phase = Phase::CloseDoc;
+
+ return true;
+ }
+
+
+ return false;
+ }
+
+
+ void invokeTest() override
+ {
+ constexpr char testName[] = "UnitWOPITemplate";
+
+ switch (_phase)
+ {
+ case Phase::LoadTemplate:
+ {
+ initWebsocket("/wopi/files/10?access_token=anything");
+
+ helpers::sendTextFrame(*_ws->getLOOLWebSocket(), "load url=" + _wopiSrc, testName);
+ SocketPoll::wakeupWorld();
+
+ _phase = Phase::SaveDoc;
+ break;
+ }
+ case Phase::CloseDoc:
+ {
+ helpers::sendTextFrame(*_ws->getLOOLWebSocket(), "closedocument", testName);
+ _phase = Phase::Polling;
+ break;
+ }
+ case Phase::Polling:
+ {
+ exitTest(TestResult::Ok);
+ break;
+ }
+ case Phase::SaveDoc:
+ {
+ break;
+ }
+ }
+ }
+};
+
+UnitBase *unit_create_wsd(void)
+{
+ return new UnitWOPITemplate();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/test/WhiteBoxTests.cpp b/test/WhiteBoxTests.cpp
index dd210dd7a..6154a6cf7 100644
--- a/test/WhiteBoxTests.cpp
+++ b/test/WhiteBoxTests.cpp
@@ -503,7 +503,8 @@ public:
const std::string& /*renderOpts*/,
const bool /*haveDocPassword*/,
const std::string& /*lang*/,
- const std::string& /*watermarkText*/) override
+ const std::string& /*watermarkText*/,
+ const std::string& /*docTemplate*/) override
{
return false;
}
diff --git a/test/data/test.ott b/test/data/test.ott
new file mode 100644
index 000000000..d7f63419c
Binary files /dev/null and b/test/data/test.ott differ
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index 8517f0bb3..c898049d0 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -463,9 +463,9 @@ bool ClientSession::loadDocument(const char* /*buffer*/, int /*length*/,
LOG_INF("Requesting document load from child.");
try
{
- std::string timestamp;
+ std::string timestamp, doctemplate;
int loadPart = -1;
- parseDocOptions(tokens, loadPart, timestamp);
+ parseDocOptions(tokens, loadPart, timestamp, doctemplate);
std::ostringstream oss;
oss << "load";
@@ -523,6 +523,11 @@ bool ClientSession::loadDocument(const char* /*buffer*/, int /*length*/,
oss << " options=" << getDocOptions();
}
+ if (_wopiFileInfo && !_wopiFileInfo->getTemplateSource().empty())
+ {
+ oss << " template=" << _wopiFileInfo->getTemplateSource();
+ }
+
return forwardToChild(oss.str(), docBroker);
}
catch (const Poco::SyntaxException&)
@@ -989,6 +994,13 @@ bool ClientSession::handleKitToClientMessage(const char* buffer, const int lengt
{
setViewLoaded();
docBroker->setLoaded();
+ // Wopi post load actions
+ if (_wopiFileInfo && !_wopiFileInfo->getTemplateSource().empty())
+ {
+ std::string result;
+ LOG_DBG("Saving template [" << _wopiFileInfo->getTemplateSource() << "] to storage");
+ docBroker->saveToStorage(getId(), true, result);
+ }
for(auto &token : tokens)
{
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 32ae37ef4..0ddd086a1 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -290,7 +290,6 @@ void DocumentBroker::pollThread()
if (_childProcess)
_childProcess->terminate();
-
stop("Load timed out");
continue;
}
@@ -513,6 +512,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
std::string userId, username;
std::string userExtraInfo;
std::string watermarkText;
+ std::string templateSource;
#ifndef MOBILEAPP
std::chrono::duration<double> getInfoCallDuration(0);
@@ -524,6 +524,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
username = wopifileinfo->getUsername();
userExtraInfo = wopifileinfo->getUserExtraInfo();
watermarkText = wopifileinfo->getWatermarkText();
+ templateSource = wopifileinfo->getTemplateSource();
if (!wopifileinfo->getUserCanWrite() ||
LOOLWSD::IsViewFileExtension(wopiStorage->getFileExtension()))
@@ -558,6 +559,9 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
if (!wopifileinfo->getTemplateSaveAs().empty())
wopiInfo->set("TemplateSaveAs", wopifileinfo->getTemplateSaveAs());
+ if (!templateSource.empty())
+ wopiInfo->set("TemplateSource", templateSource);
+
wopiInfo->set("HidePrintOption", wopifileinfo->getHidePrintOption());
wopiInfo->set("HideSaveOption", wopifileinfo->getHideSaveOption());
wopiInfo->set("HideExportOption", wopifileinfo->getHideExportOption());
@@ -673,7 +677,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
// Let's load the document now, if not loaded.
if (!_storage->isLoaded())
{
- std::string localPath = _storage->loadStorageFileToLocal(session->getAuthorization());
+ std::string localPath = _storage->loadStorageFileToLocal(session->getAuthorization(), templateSource);
#ifndef MOBILEAPP
// Check if we have a prefilter "plugin" for this document format
@@ -746,7 +750,8 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
_filename = fileInfo.getFilename();
// Use the local temp file's timestamp.
- _lastFileModifiedTime = Poco::File(_storage->getRootFilePath()).getLastModified();
+ _lastFileModifiedTime = templateSource.empty() ? Poco::File(_storage->getRootFilePath()).getLastModified() :
+ Poco::Timestamp::fromEpochTime(0);
_tileCache.reset(new TileCache(_storage->getUriString(), _lastFileModifiedTime, _cacheRoot, LOOLWSD::TileCachePersistent));
_tileCache->setThreadOwner(std::this_thread::get_id());
}
@@ -1454,7 +1459,7 @@ void DocumentBroker::handleTileCombinedRequest(TileCombined& tileCombined,
LOG_TRC("TileCombined request for " << tileCombined.serialize());
- // Check which newly requested tiles needs rendering.
+ // Check which newly requested tiles need rendering.
std::vector<TileDesc> tilesNeedsRendering;
for (auto& tile : tileCombined.getTiles())
{
@@ -1537,7 +1542,6 @@ void DocumentBroker::sendRequestedTiles(const std::shared_ptr<ClientSession>& se
float tilesOnFlyUpperLimit = 0;
if (normalizedVisArea.hasSurface() && session->getTileWidthInTwips() != 0 && session->getTileHeightInTwips() != 0)
{
-
const int tilesFitOnWidth = std::ceil(normalizedVisArea.getRight() / session->getTileWidthInTwips()) -
std::ceil(normalizedVisArea.getLeft() / session->getTileWidthInTwips()) + 1;
const int tilesFitOnHeight = std::ceil(normalizedVisArea.getBottom() / session->getTileHeightInTwips()) -
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 35fc79c48..ad387d104 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -2822,6 +2822,9 @@ private:
// Supports the TemplateSaveAs in CheckFileInfo?
capabilities->set("hasTemplateSaveAs", true);
+ // Supports the TemplateSource in CheckFileInfo?
+ capabilities->set("hasTemplateSource", true);
+
// Hint to encourage use on mobile devices
capabilities->set("hasMobileSupport", true);
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index 94c05d5e7..30650814a 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -272,7 +272,7 @@ std::unique_ptr<LocalStorage::LocalFileInfo> LocalStorage::getLocalFileInfo()
return std::unique_ptr<LocalStorage::LocalFileInfo>(new LocalFileInfo({"localhost" + std::to_string(LastLocalStorageId), "LocalHost#" + std::to_string(LastLocalStorageId++)}));
}
-std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/)
+std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/, const std::string& /*templateUri*/)
{
#ifndef MOBILEAPP
// /chroot/jailId/user/doc/childId/file.ext
@@ -515,6 +515,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
std::string userExtraInfo;
std::string watermarkText;
std::string templateSaveAs;
+ std::string templateSource;
bool canWrite = false;
bool enableOwnerTermination = false;
std::string postMessageOrigin;
@@ -549,6 +550,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
JsonUtil::findJSONValue(object, "UserId", userId);
JsonUtil::findJSONValue(object, "UserFriendlyName", userName);
JsonUtil::findJSONValue(object, "TemplateSaveAs", templateSaveAs);
+ JsonUtil::findJSONValue(object, "TemplateSource", templateSource);
// Anonymize key values.
if (LOOLWSD::AnonymizeFilenames || LOOLWSD::AnonymizeUsernames)
@@ -587,6 +589,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
{
object->remove("BaseFileName");
object->remove("TemplateSaveAs");
+ object->remove("TemplateSource");
}
if (LOOLWSD::AnonymizeUsernames)
@@ -643,8 +646,8 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
setFileInfo(FileInfo({filename, ownerId, modifiedTime, size}));
return std::unique_ptr<WopiStorage::WOPIFileInfo>(new WOPIFileInfo(
- {userId, obfuscatedUserId, userName, userExtraInfo, watermarkText, templateSaveAs, canWrite,
- postMessageOrigin, hidePrintOption, hideSaveOption, hideExportOption,
+ {userId, obfuscatedUserId, userName, userExtraInfo, watermarkText, templateSaveAs, templateSource,
+ canWrite, postMessageOrigin, hidePrintOption, hideSaveOption, hideExportOption,
enableOwnerTermination, disablePrint, disableExport, disableCopy,
disableInactiveMessages, userCanNotWriteRelative, enableInsertRemoteImage, enableShare,
hideUserList, disableChangeTrackingShow, disableChangeTrackingRecord,
@@ -652,7 +655,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
}
/// uri format: http://server/<...>/wopi*/files/<id>/content
-std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth)
+std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, const std::string& templateUri)
{
// WOPI URI to download files ends in '/contents'.
// Add it here to get the payload instead of file info.
@@ -674,6 +677,17 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth)
uriObjectAnonym.setPath(LOOLWSD::anonymizeUrl(uriObjectAnonym.getPath()) + "/contents");
const std::string uriAnonym = uriObjectAnonym.toString();
+ if (!templateUri.empty())
+ {
+ // template are created in kit process, so just obtain a reference
+ setRootFilePath(Poco::Path(getLocalRootPath(), getFileInfo().getFilename()).toString());
+ setRootFilePathAnonym(LOOLWSD::anonymizeUrl(getRootFilePath()));
+ LOG_INF("Template reference " << getRootFilePathAnonym());
+
+ setLoaded(true);
+ return Poco::Path(getJailPath(), getFileInfo().getFilename()).toString();
+ }
+
LOG_DBG("Wopi requesting: " << uriAnonym);
const auto startTime = std::chrono::steady_clock::now();
@@ -955,7 +969,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization&
return saveResult;
}
-std::string WebDAVStorage::loadStorageFileToLocal(const Authorization& /*auth*/)
+std::string WebDAVStorage::loadStorageFileToLocal(const Authorization& /*auth*/, const std::string& /*templateUri*/)
{
// TODO: implement webdav GET.
setLoaded(true);
diff --git a/wsd/Storage.hpp b/wsd/Storage.hpp
index baa0317ad..a95e772b1 100644
--- a/wsd/Storage.hpp
+++ b/wsd/Storage.hpp
@@ -189,7 +189,7 @@ public:
/// Returns a local file path for the given URI.
/// If necessary copies the file locally first.
- virtual std::string loadStorageFileToLocal(const Authorization& auth) = 0;
+ virtual std::string loadStorageFileToLocal(const Authorization& auth, const std::string& templateUri) = 0;
/// Writes the contents of the file back to the source.
/// @param savedFile When the operation was saveAs, this is the path to the file that was saved.
@@ -272,7 +272,7 @@ public:
/// obtained using getFileInfo method
std::unique_ptr<LocalFileInfo> getLocalFileInfo();
- std::string loadStorageFileToLocal(const Authorization& auth) override;
+ std::string loadStorageFileToLocal(const Authorization& auth, const std::string& templateUri) override;
SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override;
@@ -317,6 +317,7 @@ public:
const std::string& userExtraInfo,
const std::string& watermarkText,
const std::string& templateSaveAs,
+ const std::string& templateSource,
const bool userCanWrite,
const std::string& postMessageOrigin,
const bool hidePrintOption,
@@ -342,6 +343,7 @@ public:
_username(username),
_watermarkText(watermarkText),
_templateSaveAs(templateSaveAs),
+ _templateSource(templateSource),
_userCanWrite(userCanWrite),
_postMessageOrigin(postMessageOrigin),
_hidePrintOption(hidePrintOption),
@@ -376,6 +378,8 @@ public:
const std::string& getTemplateSaveAs() const { return _templateSaveAs; }
+ const std::string& getTemplateSource() const { return _templateSource; }
+
bool getUserCanWrite() const { return _userCanWrite; }
std::string& getPostMessageOrigin() { return _postMessageOrigin; }
@@ -433,6 +437,8 @@ public:
std::string _watermarkText;
/// In case we want to use this file as a template, it should be first re-saved under this name (using PutRelativeFile).
std::string _templateSaveAs;
+ /// In case we want to use this file as a template.
+ std::string _templateSource;
/// If user accessing the file has write permission
bool _userCanWrite;
/// WOPI Post message property
@@ -485,7 +491,7 @@ public:
std::unique_ptr<WOPIFileInfo> getWOPIFileInfo(const Authorization& auth);
/// uri format: http://server/<...>/wopi*/files/<id>/content
- std::string loadStorageFileToLocal(const Authorization& auth) override;
+ std::string loadStorageFileToLocal(const Authorization& auth, const std::string& templateUri) override;
SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override;
@@ -517,7 +523,7 @@ public:
// Implement me
// WebDAVFileInfo getWebDAVFileInfo(const Poco::URI& uriPublic);
- std::string loadStorageFileToLocal(const Authorization& auth) override;
+ std::string loadStorageFileToLocal(const Authorization& auth, const std::string& templateUri) override;
SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override;
More information about the Libreoffice-commits
mailing list