[Libreoffice-commits] online.git: loolwsd/LOOLWSD.cpp loolwsd/LOOLWSD.hpp loolwsd/MasterProcessSession.cpp
Ashod Nakashian
ashod.nakashian at collabora.co.uk
Wed Jan 6 21:57:43 PST 2016
loolwsd/LOOLWSD.cpp | 4 +
loolwsd/LOOLWSD.hpp | 118 +++++++++++++++++++++++++++++++++++++++
loolwsd/MasterProcessSession.cpp | 69 ++++------------------
3 files changed, 136 insertions(+), 55 deletions(-)
New commits:
commit a7556a7c1e298e40de55e915017a9fad4e0d519c
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date: Thu Jan 7 00:16:47 2016 -0500
loolwsd: new Document class to manage the lifetime of a document
Change-Id: I8596d0f2514106e384bc6519ce05028753026678
Reviewed-on: https://gerrit.libreoffice.org/21184
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp
index 7117cb3..5afeb6d 100644
--- a/loolwsd/LOOLWSD.cpp
+++ b/loolwsd/LOOLWSD.cpp
@@ -151,6 +151,10 @@ using Poco::NamedMutex;
using Poco::ProcessHandle;
using Poco::URI;
+// Document management mutex.
+std::mutex Document::DocumentsMutex;
+std::map<std::string, std::shared_ptr<Document>> Document::UriToDocumentMap;
+
/// Handles the filename part of the convert-to POST request payload.
class ConvertToPartHandler : public Poco::Net::PartHandler
{
diff --git a/loolwsd/LOOLWSD.hpp b/loolwsd/LOOLWSD.hpp
index f8e8f63..44ad381 100644
--- a/loolwsd/LOOLWSD.hpp
+++ b/loolwsd/LOOLWSD.hpp
@@ -23,8 +23,126 @@
#include <Poco/SharedMemory.h>
#include <Poco/NamedMutex.h>
+#include "Common.hpp"
#include "Util.hpp"
+// A Document as mananged by us.
+// Contains URI, physical path, etc.
+class Document
+{
+public:
+
+ static
+ std::shared_ptr<Document> create(const std::string& url,
+ const std::string& jailRoot,
+ const std::string& childId)
+ {
+ // TODO: Sanitize the url and limit access!
+ auto uriPublic = Poco::URI(url);
+ uriPublic.normalize();
+
+ const auto publicFilePath = uriPublic.getPath();
+
+ if (publicFilePath.empty())
+ throw std::runtime_error("Invalid URL.");
+
+ // This lock could become a bottleneck.
+ // In that case, we can use a pool and index by publicPath.
+ std::unique_lock<std::mutex> lock(DocumentsMutex);
+
+ // Find the document if already open.
+ auto it = UriToDocumentMap.lower_bound(publicFilePath);
+ if (it != UriToDocumentMap.end())
+ {
+ Log::info("Document [" + it->first + "] found.");
+ return it->second;
+ }
+
+ // The URL is the publicly visible one, not visible in the chroot jail.
+ // We need to map it to a jailed path and copy the file there.
+ auto uriJailed = uriPublic;
+ if (uriPublic.isRelative() || uriPublic.getScheme() == "file")
+ {
+ // chroot/jailId/user/doc
+ const auto jailedDocRoot = Poco::Path(jailRoot, JailedDocumentRoot);
+
+ // chroot/jailId/user/doc/childId
+ const auto docPath = Poco::Path(jailedDocRoot, childId);
+ Poco::File(docPath).createDirectories();
+
+ const auto filename = Poco::Path(uriPublic.getPath()).getFileName();
+
+ // chroot/jailId/user/doc/childId/file.ext
+ const auto jailedFilePath = Poco::Path(docPath, filename).toString();
+
+ uriJailed = Poco::URI(Poco::URI("file://"), jailedFilePath);
+
+ Log::info("Public URI [" + uriPublic.toString() +
+ "] jailed to [" + uriJailed.toString() + "].");
+
+#ifdef __linux
+ Log::info("Linking " + publicFilePath + " to " + jailedFilePath);
+ if (!Poco::File(jailedFilePath).exists() && link(publicFilePath.c_str(), jailedFilePath.c_str()) == -1)
+ {
+ // Failed
+ Log::error("link(\"" + publicFilePath + "\", \"" + jailedFilePath + "\") failed.");
+ }
+#endif
+
+ try
+ {
+ // Fallback to copying.
+ if (!Poco::File(jailedFilePath).exists())
+ {
+ Log::info("Copying " + publicFilePath + " to " + jailedFilePath);
+ Poco::File(publicFilePath).copyTo(jailedFilePath);
+ }
+ }
+ catch (const Poco::Exception& exc)
+ {
+ Log::error("copyTo(\"" + publicFilePath + "\", \"" + jailedFilePath + "\") failed: " + exc.displayText());
+ throw;
+ }
+ }
+ else
+ {
+ Log::info("Public URI [" + uriPublic.toString() +
+ "] is not a file.");
+ }
+
+ auto document = std::shared_ptr<Document>(new Document(uriPublic, uriJailed, childId));
+
+ Log::info("Document [" + publicFilePath + "] created.");
+ it = UriToDocumentMap.emplace_hint(it, publicFilePath, document);
+ return it->second;
+ }
+
+ Poco::URI getPublicUri() const { return _uriPublic; }
+ Poco::URI getJailedUri() const { return _uriJailed; }
+ std::string getChildId() const { return _childId; }
+
+private:
+ Document(const Poco::URI& uriPublic,
+ const Poco::URI& uriJailed,
+ const std::string& childId) :
+ _uriPublic(uriPublic),
+ _uriJailed(uriJailed),
+ _childId(childId)
+ {
+ }
+
+private:
+
+ // Document management mutex.
+ static std::mutex DocumentsMutex;
+ static std::map<std::string, std::shared_ptr<Document>> UriToDocumentMap;
+
+private:
+ const Poco::URI _uriPublic;
+ const Poco::URI _uriJailed;
+ const std::string _childId;
+};
+
class LOOLWSD: public Poco::Util::ServerApplication
{
public:
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index 99db723..902b56f 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -617,67 +617,26 @@ void MasterProcessSession::dispatchChild()
return;
}
- // Assume a valid URI
- URI aUri(_docURL);
+ const auto jailRoot = Poco::Path(LOOLWSD::childRoot, LOOLWSD::jailId);
+ const auto childId = std::to_string(childSession->_pidChild);
- if (aUri.isRelative())
- aUri = URI( URI("file://"), aUri.toString() );
+ auto document = Document::create(_docURL, jailRoot.toString(), childId);
- // Copy document into jail using the fixed name
- if (!aUri.empty() && aUri.getScheme() == "file")
- {
- const std::string aJailDoc = JailedDocumentRoot.substr(1) + Path::separator() + std::to_string(childSession->_pidChild);
- const Path aSrcFile(aUri.getPath());
- const Path aDstPath(getJailPath(childSession->_childId), aJailDoc);
- const Path aDstFile(aDstPath, aSrcFile.getFileName());
- const Path aJailFile(aJailDoc, aSrcFile.getFileName());
-
- Log::debug("JailDoc: " + aJailDoc);
- Log::debug("SrcFile: " + aSrcFile.toString());
- Log::debug("DstFile: " + aDstFile.toString());
- Log::debug("JailFile: " + aJailFile.toString());
-
- try
- {
- File(aDstPath).createDirectories();
- }
- catch (const Exception& exc)
- {
- Log::error(getName() + ": createDirectories(\"" + aDstPath.toString() + "\") failed: " + exc.displayText() );
- }
+ _peer = childSession;
+ childSession->_peer = shared_from_this();
- // cleanup potential leftovers from the last time
- Util::removeFile(aDstFile);
+ std::ostringstream oss;
+ oss << "load";
+ oss << " url=" << document->getPublicUri().toString();
+ oss << " jail=" << document->getJailedUri().toString();
-#ifdef __linux
- Log::info("Linking " + aSrcFile.toString() + " to " + aDstFile.toString());
- if (!File(aDstFile).exists() && link(aSrcFile.toString().c_str(), aDstFile.toString().c_str()) == -1)
- {
- // Failed
- Log::error(getName() + ": link(\"" + aSrcFile.toString() + "\",\"" + aDstFile.toString() + "\") failed.");
- }
-#endif
+ if (_loadPart >= 0)
+ oss << " part=" + _loadPart;
- try
- {
- //fallback
- if (!File(aDstFile).exists())
- {
- Log::info("Copying " + aSrcFile.toString() + " to " + aDstFile.toString());
- File(aSrcFile).copyTo(aDstFile.toString());
- }
- }
- catch (const Exception& exc)
- {
- Log::error(getName() + ": copyTo(\"" + aSrcFile.toString() + "\",\"" + aDstFile.toString() + "\") failed: " + exc.displayText());
- }
- }
-
- _peer = childSession;
- childSession->_peer = shared_from_this();
+ if (!_docOptions.empty())
+ oss << " options=" << _docOptions;
- const std::string loadRequest = "load" + (_loadPart >= 0 ? " part=" + std::to_string(_loadPart) : "")
- + " url=" + _docURL + (!_docOptions.empty() ? " options=" + _docOptions : "");
+ const auto loadRequest = oss.str();
forwardToPeer(loadRequest.c_str(), loadRequest.size());
}
More information about the Libreoffice-commits
mailing list