/* -*- 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/. */ // Storage abstraction. #ifndef INCLUDED_STORAGE_HPP #define INCLUDED_STORAGE_HPP #include #include #include #include #include "Auth.hpp" #include "Log.hpp" #include "Util.hpp" /// Base class of all Storage abstractions. class StorageBase { public: /// Represents basic file's attributes. /// Used for local and network files. class FileInfo { public: FileInfo(const std::string& filename, const std::string& ownerId, const Poco::Timestamp& modifiedTime, size_t size) : _filename(filename), _ownerId(ownerId), _modifiedTime(modifiedTime), _size(size) { } bool isValid() const { // 0-byte files are valid; LO will open them as new docs. return !_filename.empty(); } std::string _filename; std::string _ownerId; Poco::Timestamp _modifiedTime; size_t _size; }; enum class SaveResult { OK, DISKFULL, UNAUTHORIZED, DOC_CHANGED, /* Document changed in storage */ CONFLICT, FAILED }; enum class LOOLStatusCode { DOC_CHANGED = 1010 // Document changed externally in storage }; /// localStorePath the absolute root path of the chroot. /// jailPath the path within the jail that the child uses. StorageBase(const Poco::URI& uri, const std::string& localStorePath, const std::string& jailPath) : _uri(uri), _localStorePath(localStorePath), _jailPath(jailPath), _fileInfo("", "lool", Poco::Timestamp::fromEpochTime(0), 0), _isLoaded(false), _forceSave(false) { LOG_DBG("Storage ctor: " << uri.toString()); } virtual ~StorageBase() {} const std::string getUri() const { return _uri.toString(); } /// Returns the root path to the jailed file. const std::string& getRootFilePath() const { return _jailedFilePath; }; bool isLoaded() const { return _isLoaded; } /// Asks the storage object to force overwrite to storage upon next save /// even if document turned out to be changed in storage void forceSave() { _forceSave = true; } /// Returns the basic information about the file. const FileInfo& getFileInfo() const { return _fileInfo; } std::string getFileExtension() const { return Poco::Path(_fileInfo._filename).getExtension(); } /// Returns a local file path for the given URI. /// If necessary copies the file locally first. virtual std::string loadStorageFileToLocal(const Authorization& auth) = 0; /// Writes the contents of the file back to the source. virtual SaveResult saveLocalFileToStorage(const Authorization& auth) = 0; static size_t getFileSize(const std::string& filename); /// Must be called at startup to configure. static void initialize(); /// Storage object creation factory. static std::unique_ptr create(const Poco::URI& uri, const std::string& jailRoot, const std::string& jailPath); protected: /// Returns the root path of the jail directory of docs. std::string getLocalRootPath() const; protected: const Poco::URI _uri; std::string _localStorePath; std::string _jailPath; std::string _jailedFilePath; FileInfo _fileInfo; bool _isLoaded; bool _forceSave; static bool FilesystemEnabled; static bool WopiEnabled; /// Allowed/denied WOPI hosts, if any and if WOPI is enabled. static Util::RegexListMatcher WopiHosts; }; /// Trivial implementation of local storage that does not need do anything. class LocalStorage : public StorageBase { public: LocalStorage(const Poco::URI& uri, const std::string& localStorePath, const std::string& jailPath) : StorageBase(uri, localStorePath, jailPath), _isCopy(false) { LOG_INF("LocalStorage ctor with localStorePath: [" << localStorePath << "], jailPath: [" << jailPath << "], uri: [" << uri.toString() << "]."); } class LocalFileInfo { public: LocalFileInfo(const std::string& userid, const std::string& username) : _userid(userid), _username(username) { } std::string _userid; std::string _username; }; /// Returns the URI specific file data /// Also stores the basic file information which can then be /// obtained using getFileInfo method std::unique_ptr getLocalFileInfo(); std::string loadStorageFileToLocal(const Authorization& auth) override; SaveResult saveLocalFileToStorage(const Authorization& auth) override; private: /// True if the jailed file is not linked but copied. bool _isCopy; static std::atomic LastLocalStorageId; }; /// WOPI protocol backed storage. class WopiStorage : public StorageBase { public: WopiStorage(const Poco::URI& uri, const std::string& localStorePath, const std::string& jailPath) : StorageBase(uri, localStorePath, jailPath), _wopiLoadDuration(0) { LOG_INF("WopiStorage ctor with localStorePath: [" << localStorePath << "], jailPath: [" << jailPath << "], uri: [" << uri.toString() << "]."); } class WOPIFileInfo { public: WOPIFileInfo(const std::string& userid, const std::string& username, const std::string& userExtraInfo, const std::string& watermarkText, const bool userCanWrite, const std::string& postMessageOrigin, const bool hidePrintOption, const bool hideSaveOption, const bool hideExportOption, const bool enableOwnerTermination, const bool disablePrint, const bool disableExport, const bool disableCopy, const bool disableInactiveMessages, const std::chrono::duration callDuration) : _userid(userid), _username(username), _watermarkText(watermarkText), _userCanWrite(userCanWrite), _postMessageOrigin(postMessageOrigin), _hidePrintOption(hidePrintOption), _hideSaveOption(hideSaveOption), _hideExportOption(hideExportOption), _enableOwnerTermination(enableOwnerTermination), _disablePrint(disablePrint), _disableExport(disableExport), _disableCopy(disableCopy), _disableInactiveMessages(disableInactiveMessages), _callDuration(callDuration) { _userExtraInfo = userExtraInfo; } /// User id of the user accessing the file std::string _userid; /// Display Name of user accessing the file std::string _username; /// Extra info per user, typically mail and other links, as json. std::string _userExtraInfo; /// In case a watermark has to be rendered on each tile. std::string _watermarkText; /// If user accessing the file has write permission bool _userCanWrite; /// WOPI Post message property std::string _postMessageOrigin; /// Hide print button from UI bool _hidePrintOption; /// Hide save button from UI bool _hideSaveOption; /// Hide 'Download as' button/menubar item from UI bool _hideExportOption; /// If WOPI host has enabled owner termination feature on bool _enableOwnerTermination; /// If WOPI host has allowed the user to print the document bool _disablePrint; /// If WOPI host has allowed the user to export the document bool _disableExport; /// If WOPI host has allowed the user to copy to/from the document bool _disableCopy; /// If WOPI host has allowed the loleaflet to show texts on the overlay informing about inactivity, or if the integration is handling that. bool _disableInactiveMessages; /// Time it took to call WOPI's CheckFileInfo std::chrono::duration _callDuration; }; /// Returns the response of CheckFileInfo WOPI call for URI that was /// provided during the initial creation of the WOPI storage. /// Also extracts the basic file information from the response /// which can then be obtained using getFileInfo() std::unique_ptr getWOPIFileInfo(const Authorization& auth); /// returns std::string createCopyFile(const Authorization& auth, const std::string& newFileName, const std::string& path); /// uri format: http://server/<...>/wopi*/files//content std::string loadStorageFileToLocal(const Authorization& auth) override; SaveResult saveLocalFileToStorage(const Authorization& auth) override; /// Total time taken for making WOPI calls during load std::chrono::duration getWopiLoadDuration() const { return _wopiLoadDuration; } private: // Time spend in loading the file from storage std::chrono::duration _wopiLoadDuration; }; /// WebDAV protocol backed storage. class WebDAVStorage : public StorageBase { public: WebDAVStorage(const Poco::URI& uri, const std::string& localStorePath, const std::string& jailPath, std::unique_ptr authAgent) : StorageBase(uri, localStorePath, jailPath), _authAgent(std::move(authAgent)) { LOG_INF("WebDAVStorage ctor with localStorePath: [" << localStorePath << "], jailPath: [" << jailPath << "], uri: [" << uri.toString() << "]."); } // Implement me // WebDAVFileInfo getWebDAVFileInfo(const Poco::URI& uriPublic); std::string loadStorageFileToLocal(const Authorization& auth) override; SaveResult saveLocalFileToStorage(const Authorization& auth) override; private: std::unique_ptr _authAgent; }; #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */