loolwsd/DocumentBroker.hpp | 8 +++ loolwsd/LOOLWSD.cpp | 3 + loolwsd/Storage.hpp | 95 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 99 insertions(+), 7 deletions(-)
New commits: commit ef95d51b672b336772d832aad4c0c899955d1786 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Mon Mar 21 19:12:00 2016 -0400 loolwsd: FileInfo used to authenticate and store with original name Change-Id: I94105441134ded2146736affba7b763eb3d54791 Reviewed-on: https://gerrit.libreoffice.org/23452 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/loolwsd/DocumentBroker.hpp b/loolwsd/DocumentBroker.hpp index 3f7c75e..471df0c 100644 --- a/loolwsd/DocumentBroker.hpp +++ b/loolwsd/DocumentBroker.hpp @@ -77,6 +77,13 @@ public: Log::info("~DocumentBroker [" + _uriPublic.toString() + "] destroyed."); } + void validate(const Poco::URI& uri) + { + Log::info("validating: " + uri.toString()); + auto storage = createStorage("", "", uri); + storage->getFileInfo(uri.toString()); + } + /// Loads a document from the public URI into the jail. bool load(const std::string& jailId) { @@ -136,6 +143,7 @@ private: const std::string _childRoot; Poco::URI _uriJailed; std::string _jailId; + std::string _filename; std::unique_ptr<StorageBase> _storage; std::mutex _mutex; std::atomic<unsigned> _sessionsCount; diff --git a/loolwsd/LOOLWSD.cpp b/loolwsd/LOOLWSD.cpp index 2d3dd66..8c518fc 100644 --- a/loolwsd/LOOLWSD.cpp +++ b/loolwsd/LOOLWSD.cpp @@ -577,6 +577,9 @@ private: docBrokers.emplace(docKey, docBroker); } + // Validate the URI and Storage before moving on. + docBroker->validate(uriPublic); + auto ws = std::make_shared<WebSocket>(request, response); auto session = std::make_shared<MasterProcessSession>(id, LOOLSession::Kind::ToClient, ws, docBroker); docBroker->incSessions(); diff --git a/loolwsd/Storage.hpp b/loolwsd/Storage.hpp index edc8569..574c844 100644 --- a/loolwsd/Storage.hpp +++ b/loolwsd/Storage.hpp @@ -16,6 +16,8 @@ #include <Poco/Net/HTTPResponse.h> #include <Poco/StreamCopier.h> +#include <Poco/JSON/Object.h> +#include <Poco/JSON/Parser.h> #include "Common.hpp" #include "Auth.hpp" @@ -26,6 +28,13 @@ class StorageBase { public: + class FileInfo + { + public: + std::string Filename; + size_t Size; + }; + /// localStorePath the absolute root path of the chroot. /// jailPath the path within the jail that the child uses. StorageBase(const std::string& localStorePath, @@ -56,11 +65,17 @@ public: const std::string& getUri() const { return _uri; } - /// Returns a local file path given a URI or ID. + /// Returns information about the file. + virtual FileInfo getFileInfo(const std::string& uri) = 0; + + /// Returns a local file path for the given URI. /// If necessary copies the file locally first. virtual std::string loadStorageFileToLocal() = 0; /// Writes the contents of the file back to the source. + /// TODO: Should we save to the specific client's URI? + /// The advantage is that subseqent views (to the first) + /// will not depend on the token of the first. virtual bool saveLocalFileToStorage() = 0; static @@ -74,7 +89,7 @@ protected: const std::string _jailPath; const std::string _uri; std::string _jailedFilePath; - std::string _filename; + FileInfo _fileInfo; }; /// Trivial implementation of local storage that does not need do anything. @@ -89,6 +104,13 @@ public: { } + FileInfo getFileInfo(const std::string& uri) + { + const auto filename = Poco::Path(uri).getFileName(); + const auto size = Poco::File(uri).getSize(); + return FileInfo({filename, size}); + } + std::string loadStorageFileToLocal() override { const auto rootPath = getLocalRootPath(); @@ -163,14 +185,68 @@ public: { } + FileInfo getFileInfo(const std::string& uri) + { + Log::info("FileInfo for URI [" + uri + "]."); + + Poco::URI uriObject(uri); + Poco::Net::HTTPClientSession session(uriObject.getHost(), uriObject.getPort()); + Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, uriObject.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1); + request.set("User-Agent", "LOOLWSD WOPI Agent"); + session.sendRequest(request); + + Poco::Net::HTTPResponse response; + std::istream& rs = session.receiveResponse(response); + + auto logger = Log::trace(); + logger << "WOPI::CheckFileInfo header for URI [" << uri << "]:\n"; + for (auto& pair : response) + { + logger << '\t' + pair.first + ": " + pair.second << " / "; + } + + logger << Log::end; + + // Parse the response. + std::string filename; + size_t size = 0; + std::string resMsg; + Poco::StreamCopier::copyToString(rs, resMsg); + Log::debug("WOPI::CheckFileInfo returned: " + resMsg); + const auto index = resMsg.find_first_of("{"); + if (index != std::string::npos) + { + const std::string stringJSON = resMsg.substr(index); + Poco::JSON::Parser parser; + const auto result = parser.parse(stringJSON); + const auto object = result.extract<Poco::JSON::Object::Ptr>(); + filename = object->get("BaseFileName").toString(); + size = std::stoul (object->get("Size").toString(), nullptr, 0); + } + + return FileInfo({filename, size}); + } + /// uri format: http://server/<...>/wopi*/files/<id>/content std::string loadStorageFileToLocal() override { Log::info("Downloading URI [" + _uri + "]."); + _fileInfo = getFileInfo(_uri); + if (_fileInfo.Size == 0 && _fileInfo.Filename.empty()) + { + //TODO: Should throw a more appropriate exception. + throw std::runtime_error("Failed to load file from storage."); + } + + // WOPI URI to download files ends in '/contents'. + // Add it here to get the payload instead of file info. Poco::URI uriObject(_uri); + const auto url = uriObject.getPath() + "/contents?" + uriObject.getQuery(); + Log::info("Requesting: " + url); + Poco::Net::HTTPClientSession session(uriObject.getHost(), uriObject.getPort()); - Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, uriObject.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1); + Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, url, Poco::Net::HTTPMessage::HTTP_1_1); request.set("User-Agent", "LOOLWSD WOPI Agent"); session.sendRequest(request); @@ -186,9 +262,7 @@ public: logger << Log::end; - //TODO: Get proper filename. - _filename = "filename"; - _jailedFilePath = Poco::Path(getLocalRootPath(), _filename).toString(); + _jailedFilePath = Poco::Path(getLocalRootPath(), _fileInfo.Filename).toString(); std::ofstream ofs(_jailedFilePath); std::copy(std::istreambuf_iterator<char>(rs), std::istreambuf_iterator<char>(), @@ -200,7 +274,7 @@ public: << response.getStatus() << " " << response.getReason() << Log::end; // Now return the jailed path. - return Poco::Path(_jailPath, _filename).toString(); + return Poco::Path(_jailPath, _fileInfo.Filename).toString(); } bool saveLocalFileToStorage() override @@ -246,6 +320,13 @@ public: { } + FileInfo getFileInfo(const std::string& uri) + { + (void)uri; + assert(!"Not Implemented!"); + return FileInfo({"bazinga", 0}); + } + std::string loadStorageFileToLocal() override { // TODO: implement webdav GET. _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits