[Libreoffice-commits] online.git: loolwsd/DocumentBroker.hpp loolwsd/LOOLWSD.cpp loolwsd/Storage.hpp

Ashod Nakashian ashod.nakashian at collabora.co.uk
Wed Mar 23 00:05:16 UTC 2016


 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.nakashian at 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 <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at 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.


More information about the Libreoffice-commits mailing list