diff options
-rw-r--r-- | wsd/ClientSession.cpp | 14 | ||||
-rw-r--r-- | wsd/ClientSession.hpp | 5 | ||||
-rw-r--r-- | wsd/DocumentBroker.cpp | 17 | ||||
-rw-r--r-- | wsd/Storage.cpp | 53 | ||||
-rw-r--r-- | wsd/Storage.hpp | 59 |
5 files changed, 108 insertions, 40 deletions
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index beed136e51..60ed55c6fd 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -60,7 +60,19 @@ ClientSession::ClientSession(const std::string& id, _isTextDocument(false) { const size_t curConnections = ++LOOLWSD::NumConnections; - LOG_INF("ClientSession ctor [" << getName() << "], current number of connections: " << curConnections); + LOG_INF("ClientSession ctor [" << getName() << "] for URI: [" << _uriPublic.toString() + << "], current number of connections: " << curConnections); + + for (const auto& param : _uriPublic.getQueryParameters()) + { + if (param.first == "reuse_cookies") + { + // Cache the cookies to avoid re-parsing the URI again. + _cookies = param.second; + LOG_INF("ClientSession [" << getName() << "] has cookies: " << _cookies); + break; + } + } // populate with random values. for (auto it : _clipboardKeys) diff --git a/wsd/ClientSession.hpp b/wsd/ClientSession.hpp index 8ee1846874..d714179ceb 100644 --- a/wsd/ClientSession.hpp +++ b/wsd/ClientSession.hpp @@ -123,6 +123,8 @@ public: /// The access token of this session. Authorization getAuthorization() const; + const std::string& getCookies() const { return _cookies; } + /// Set WOPI fileinfo object void setWopiFileInfo(std::unique_ptr<WopiStorage::WOPIFileInfo>& wopiFileInfo) { _wopiFileInfo = std::move(wopiFileInfo); } @@ -220,6 +222,9 @@ private: /// URI with which client made request to us const Poco::URI _uriPublic; + /// The cookies we should pass on to the storage on saving. + std::string _cookies; + /// Whether this session is the owner of currently opened document bool _isDocumentOwner; diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp index 876436abed..1eed16ea04 100644 --- a/wsd/DocumentBroker.cpp +++ b/wsd/DocumentBroker.cpp @@ -596,8 +596,8 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s WopiStorage* wopiStorage = dynamic_cast<WopiStorage*>(_storage.get()); if (wopiStorage != nullptr) { - std::unique_ptr<WopiStorage::WOPIFileInfo> wopifileinfo = - wopiStorage->getWOPIFileInfo(session->getAuthorization(), *_lockCtx); + std::unique_ptr<WopiStorage::WOPIFileInfo> wopifileinfo = wopiStorage->getWOPIFileInfo( + session->getAuthorization(), session->getCookies(), *_lockCtx); userId = wopifileinfo->getUserId(); username = wopifileinfo->getUsername(); userExtraInfo = wopifileinfo->getUserExtraInfo(); @@ -754,9 +754,9 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s if (!_storage->isLoaded()) { std::string localPath = _storage->loadStorageFileToLocal( - session->getAuthorization(), *_lockCtx, templateSource); + session->getAuthorization(), session->getCookies(), *_lockCtx, templateSource); - if (!_storage->updateLockState(session->getAuthorization(), *_lockCtx, true)) + if (!_storage->updateLockState(session->getAuthorization(), session->getCookies(), *_lockCtx, true)) LOG_ERR("Failed to lock!"); #if !MOBILEAPP @@ -990,8 +990,8 @@ bool DocumentBroker::saveToStorageInternal(const std::string& sessionId, bool su LOG_DBG("Persisting [" << _docKey << "] after saving to URI [" << uriAnonym << "]."); assert(_storage && _tileCache); - StorageBase::SaveResult storageSaveResult = _storage->saveLocalFileToStorage( - auth, *_lockCtx, saveAsPath, saveAsFilename, isRename); + const StorageBase::SaveResult storageSaveResult = _storage->saveLocalFileToStorage( + auth, it->second->getCookies(), *_lockCtx, saveAsPath, saveAsFilename, isRename); if (storageSaveResult.getResult() == StorageBase::SaveResult::OK) { #if !MOBILEAPP @@ -1146,7 +1146,7 @@ void DocumentBroker::refreshLock() else { std::shared_ptr<ClientSession> session = it->second; - if (!session || !_storage->updateLockState(session->getAuthorization(), *_lockCtx, true)) + if (!session || !_storage->updateLockState(session->getAuthorization(), session->getCookies(), *_lockCtx, true)) LOG_ERR("Failed to refresh lock"); } } @@ -1418,7 +1418,7 @@ void DocumentBroker::disconnectSessionInternal(const std::string& id) if (_markToDestroy && // last session to remove; FIXME: Editable? _lockCtx->_isLocked && _storage) { - if (!_storage->updateLockState(it->second->getAuthorization(), *_lockCtx, false)) + if (!_storage->updateLockState(it->second->getAuthorization(), it->second->getCookies(), *_lockCtx, false)) LOG_ERR("Failed to unlock!"); } @@ -1782,7 +1782,6 @@ void DocumentBroker::sendRequestedTiles(const std::shared_ptr<ClientSession>& se float tilesOnFlyUpperLimit = 0; if (normalizedVisArea.hasSurface() && session->getTileWidthInTwips() != 0 && session->getTileHeightInTwips() != 0) { - const int tilesFitOnWidth = std::ceil(normalizedVisArea.getRight() / session->getTileWidthInTwips()) - std::ceil(normalizedVisArea.getLeft() / session->getTileWidthInTwips()) + 1; const int tilesFitOnHeight = std::ceil(normalizedVisArea.getBottom() / session->getTileHeightInTwips()) - diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp index ab2ad71c61..f465e0a011 100644 --- a/wsd/Storage.cpp +++ b/wsd/Storage.cpp @@ -300,7 +300,10 @@ std::unique_ptr<LocalStorage::LocalFileInfo> LocalStorage::getLocalFileInfo() return std::unique_ptr<LocalStorage::LocalFileInfo>(new LocalFileInfo({"localhost" + std::to_string(LastLocalStorageId), "LocalHost#" + std::to_string(LastLocalStorageId++)})); } -std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/, LockContext & /*lockCtx*/, const std::string& /*templateUri*/) +std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/, + const std::string& /*cookies*/, + LockContext& /*lockCtx*/, + const std::string& /*templateUri*/) { #if !MOBILEAPP // /chroot/jailId/user/doc/childId/file.ext @@ -363,7 +366,10 @@ std::string LocalStorage::loadStorageFileToLocal(const Authorization& /*auth*/, } -StorageBase::SaveResult LocalStorage::saveLocalFileToStorage(const Authorization& /*auth*/, LockContext &/*lockCtx*/, const std::string& /*saveAsPath*/, const std::string& /*saveAsFilename*/, bool /*isRename*/) +StorageBase::SaveResult +LocalStorage::saveLocalFileToStorage(const Authorization& /*auth*/, const std::string& /*cookies*/, + LockContext& /*lockCtx*/, const std::string& /*saveAsPath*/, + const std::string& /*saveAsFilename*/, bool /*isRename*/) { try { @@ -428,6 +434,8 @@ static void addStorageReuseCookie(Poco::Net::HTTPRequest& request, const std::st if (!reuseStorageCookies.empty()) { Poco::Net::NameValueCollection nvcCookies; + request.getCookies(nvcCookies); // Preserve existing cookies. + std::vector<std::string> cookies = LOOLProtocol::tokenize(reuseStorageCookies, ':'); for (auto cookie : cookies) { @@ -435,9 +443,10 @@ static void addStorageReuseCookie(Poco::Net::HTTPRequest& request, const std::st if (cookieTokens.size() == 2) { nvcCookies.add(cookieTokens[0], cookieTokens[1]); - LOG_DBG("Added storage reuse cookie [" << cookieTokens[0] << "=" << cookieTokens[1] << "]."); + LOG_DBG("Added storage reuse cookie [" << cookieTokens[0] << '=' << cookieTokens[1] << "]."); } } + request.setCookies(nvcCookies); } } @@ -494,7 +503,9 @@ void LockContext::dumpState(std::ostream& os) const #if !MOBILEAPP -std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Authorization& auth, LockContext &lockCtx) +std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Authorization& auth, + const std::string& cookies, + LockContext& lockCtx) { // update the access_token to the one matching to the session Poco::URI uriObject(getUri()); @@ -513,7 +524,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au auth.authorizeRequest(request); addStorageDebugCookie(request); if (_reuseCookies) - addStorageReuseCookie(request, params["reuse_cookies"]); + addStorageReuseCookie(request, cookies); addWopiProof(request, params["access_token"]); const auto startTime = std::chrono::steady_clock::now(); @@ -712,7 +723,8 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au userCanRename, callDuration})); } -bool WopiStorage::updateLockState(const Authorization &auth, LockContext &lockCtx, bool lock) +bool WopiStorage::updateLockState(const Authorization& auth, const std::string& cookies, + LockContext& lockCtx, bool lock) { if (!lockCtx._supportsLocks) return true; @@ -743,7 +755,7 @@ bool WopiStorage::updateLockState(const Authorization &auth, LockContext &lockCt request.set("X-LOOL-WOPI-ExtendedData", getExtendedData()); addStorageDebugCookie(request); if (_reuseCookies) - addStorageReuseCookie(request, params["reuse_cookies"]); + addStorageReuseCookie(request, cookies); addWopiProof(request, params["access_token"]); psession->sendRequest(request); @@ -782,7 +794,10 @@ bool WopiStorage::updateLockState(const Authorization &auth, LockContext &lockCt } /// uri format: http://server/<...>/wopi*/files/<id>/content -std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, LockContext &/* lockCtx */, const std::string& templateUri) +std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, + const std::string& cookies, + LockContext& /*lockCtx*/, + const std::string& templateUri) { // WOPI URI to download files ends in '/contents'. // Add it here to get the payload instead of file info. @@ -819,7 +834,7 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, LockC auth.authorizeRequest(request); addStorageDebugCookie(request); if (_reuseCookies) - addStorageReuseCookie(request, params["reuse_cookies"]); + addStorageReuseCookie(request, cookies); addWopiProof(request, params["access_token"]); psession->sendRequest(request); @@ -876,7 +891,10 @@ std::string WopiStorage::loadStorageFileToLocal(const Authorization& auth, LockC return ""; } -StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) +StorageBase::SaveResult +WopiStorage::saveLocalFileToStorage(const Authorization& auth, const std::string& cookies, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, const bool isRename) { // TODO: Check if this URI has write permission (canWrite = true) @@ -975,7 +993,7 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization& request.setContentLength(size); addStorageDebugCookie(request); if (_reuseCookies) - addStorageReuseCookie(request, params["reuse_cookies"]); + addStorageReuseCookie(request, cookies); addWopiProof(request, params["access_token"]); std::ostream& os = psession->sendRequest(request); @@ -1106,17 +1124,20 @@ StorageBase::SaveResult WopiStorage::saveLocalFileToStorage(const Authorization& return saveResult; } -std::string WebDAVStorage::loadStorageFileToLocal( - const Authorization& /*auth*/, LockContext &/*lockCtx*/, const std::string& /*templateUri*/) +std::string WebDAVStorage::loadStorageFileToLocal(const Authorization& /*auth*/, + const std::string& /*cookies*/, + LockContext& /*lockCtx*/, + const std::string& /*templateUri*/) { // TODO: implement webdav GET. setLoaded(true); return getUri().toString(); } -StorageBase::SaveResult WebDAVStorage::saveLocalFileToStorage( - const Authorization& /*auth*/, LockContext &/*lockCtx*/, const std::string& /*saveAsPath*/, - const std::string& /*saveAsFilename*/, bool /*isRename*/) +StorageBase::SaveResult +WebDAVStorage::saveLocalFileToStorage(const Authorization& /*auth*/, const std::string& /*cookies*/, + LockContext& /*lockCtx*/, const std::string& /*saveAsPath*/, + const std::string& /*saveAsFilename*/, bool /*isRename*/) { // TODO: implement webdav PUT. return StorageBase::SaveResult(StorageBase::SaveResult::OK); diff --git a/wsd/Storage.hpp b/wsd/Storage.hpp index 7060cd7a4e..bb678ac8aa 100644 --- a/wsd/Storage.hpp +++ b/wsd/Storage.hpp @@ -53,7 +53,6 @@ struct LockContext class StorageBase { public: - /// Represents basic file's attributes. /// Used for local and network files. class FileInfo @@ -217,15 +216,25 @@ public: std::string getFileExtension() const { return Poco::Path(_fileInfo.getFilename()).getExtension(); } /// Update the locking state (check-in/out) of the associated file - virtual bool updateLockState(const Authorization &auth, LockContext &lockCtx, bool lock) = 0; + virtual bool updateLockState(const Authorization& auth, const std::string& cookies, + LockContext& lockCtx, bool lock) + = 0; /// Returns a local file path for the given URI. /// If necessary copies the file locally first. - virtual std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) = 0; + virtual std::string loadStorageFileToLocal(const Authorization& auth, + const std::string& /*cookies*/, LockContext& lockCtx, + const std::string& templateUri) + = 0; /// Writes the contents of the file back to the source. + /// @param cookies A string representing key=value pairs that are set as cookies. /// @param savedFile When the operation was saveAs, this is the path to the file that was saved. - virtual SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) = 0; + virtual SaveResult + saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, const bool isRename) + = 0; static size_t getFileSize(const std::string& filename); @@ -312,11 +321,19 @@ public: /// obtained using getFileInfo method std::unique_ptr<LocalFileInfo> getLocalFileInfo(); - bool updateLockState(const Authorization &, LockContext &, bool) override { return true; } + bool updateLockState(const Authorization&, const std::string&, LockContext&, bool) override + { + return true; + } - std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) override; + std::string loadStorageFileToLocal(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, + const std::string& templateUri) override; - SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override; + SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, + const bool isRename) override; private: /// True if the jailed file is not linked but copied. @@ -545,15 +562,21 @@ public: /// which can then be obtained using getFileInfo() /// Also sets up the locking context for future operations. std::unique_ptr<WOPIFileInfo> getWOPIFileInfo(const Authorization& auth, - LockContext &lockCtx); + const std::string& cookies, LockContext& lockCtx); /// Update the locking state (check-in/out) of the associated file - bool updateLockState(const Authorization &auth, LockContext &lockCtx, bool lock) override; + bool updateLockState(const Authorization& auth, const std::string& cookies, + LockContext& lockCtx, bool lock) override; /// uri format: http://server/<...>/wopi*/files/<id>/content - std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) override; + std::string loadStorageFileToLocal(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, + const std::string& templateUri) override; - SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override; + SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, + const bool isRename) override; /// Total time taken for making WOPI calls during load std::chrono::duration<double> getWopiLoadDuration() const { return _wopiLoadDuration; } @@ -585,11 +608,19 @@ public: // Implement me // WebDAVFileInfo getWebDAVFileInfo(const Poco::URI& uriPublic); - bool updateLockState(const Authorization &, LockContext &, bool) override { return true; } + bool updateLockState(const Authorization&, const std::string&, LockContext&, bool) override + { + return true; + } - std::string loadStorageFileToLocal(const Authorization& auth, LockContext &lockCtx, const std::string& templateUri) override; + std::string loadStorageFileToLocal(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, + const std::string& templateUri) override; - SaveResult saveLocalFileToStorage(const Authorization& auth, LockContext &lockCtx, const std::string& saveAsPath, const std::string& saveAsFilename, const bool isRename) override; + SaveResult saveLocalFileToStorage(const Authorization& auth, const std::string& /*cookies*/, + LockContext& lockCtx, const std::string& saveAsPath, + const std::string& saveAsFilename, + const bool isRename) override; private: std::unique_ptr<AuthBase> _authAgent; |