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@gmail.com> Tested-by: Ashod Nakashian <ashnakash@gmail.com>
This commit is contained in:
parent
cf3811a7fb
commit
ef95d51b67
3 changed files with 99 additions and 7 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue