diff options
author | Ashod Nakashian <ashod.nakashian@collabora.co.uk> | 2024-05-04 08:45:10 -0400 |
---|---|---|
committer | Timur <timur@libreoffice.org> | 2024-05-04 20:13:26 +0100 |
commit | afafe35a41529e0fe86385638fb6ddd5c8a6a0b0 (patch) | |
tree | 7e5e3c842a9b9a06ebbaa0ca453d1699c3eaf770 | |
parent | Revert "killpoco: use http::Response for Admin metrics" (diff) | |
download | online-distro/collabora/co-22-05.tar.gz online-distro/collabora/co-22-05.zip |
Revert "killpoco: replace HTTPResponse in sendFileAndShutdown"
distro/collabora/co-22-05
This reverts commit 9346a5c7f1c69b3989e181b9f42936f0e413afc9.
Change-Id: Id4dd0c68f47c889fa3c6c2f8a98fa58a1ef8c595
Signed-off-by: Ashod Nakashian <ashod.nakashian@collabora.co.uk>
-rw-r--r-- | net/HttpHelper.cpp | 27 | ||||
-rw-r--r-- | net/HttpHelper.hpp | 10 | ||||
-rw-r--r-- | net/HttpRequest.hpp | 6 | ||||
-rw-r--r-- | test/UnitHTTP.cpp | 24 | ||||
-rw-r--r-- | test/UnitWOPIFileUrl.cpp | 24 | ||||
-rw-r--r-- | test/UnitWOPITemplate.cpp | 4 | ||||
-rw-r--r-- | wsd/COOLWSD.cpp | 21 | ||||
-rw-r--r-- | wsd/ClientSession.cpp | 32 | ||||
-rw-r--r-- | wsd/FileServer.cpp | 57 | ||||
-rw-r--r-- | wsd/FileServer.hpp | 1 |
10 files changed, 97 insertions, 109 deletions
diff --git a/net/HttpHelper.cpp b/net/HttpHelper.cpp index 658e6c87fa..deb4cd38f1 100644 --- a/net/HttpHelper.cpp +++ b/net/HttpHelper.cpp @@ -85,9 +85,14 @@ void sendDeflatedFileContent(const std::shared_ptr<StreamSocket>& socket, const } void sendFileAndShutdown(const std::shared_ptr<StreamSocket>& socket, const std::string& path, - const std::string& mediaType, http::Response& response, + const std::string& mediaType, Poco::Net::HTTPResponse* optResponse, const bool noCache, const bool deflate, const bool headerOnly) { + Poco::Net::HTTPResponse* response = optResponse; + Poco::Net::HTTPResponse localResponse; + if (!response) + response = &localResponse; + FileUtil::Stat st(path); if (st.bad()) { @@ -99,19 +104,19 @@ void sendFileAndShutdown(const std::shared_ptr<StreamSocket>& socket, const std: if (!noCache) { // 60 * 60 * 24 * 128 (days) = 11059200 - response.set("Cache-Control", "max-age=11059200"); - response.set("ETag", "\"" COOLWSD_VERSION_HASH "\""); + response->set("Cache-Control", "max-age=11059200"); + response->set("ETag", "\"" COOLWSD_VERSION_HASH "\""); } else { - response.set("Cache-Control", "no-cache"); + response->set("Cache-Control", "no-cache"); } - response.setContentType(mediaType); - response.add("X-Content-Type-Options", "nosniff"); + response->setContentType(mediaType); + response->add("X-Content-Type-Options", "nosniff"); //Should we add the header anyway ? if (headerOnly) - response.add("Connection", "close"); + response->add("Connection", "close"); int bufferSize = std::min<std::size_t>(st.size(), Socket::MaximumSendBufferSize); if (static_cast<long>(st.size()) >= socket->getSendBufferSize()) @@ -125,20 +130,20 @@ void sendFileAndShutdown(const std::shared_ptr<StreamSocket>& socket, const std: // IE/Edge before enabling the deflate again if (!deflate || true) { - response.setContentLength(st.size()); + response->setContentLength(st.size()); LOG_TRC('#' << socket->getFD() << ": Sending " << (headerOnly ? "header for " : "") << " file [" << path << "]."); - socket->send(response); + socket->send(*response); if (!headerOnly) sendUncompressedFileContent(socket, path, bufferSize); } else { - response.set("Content-Encoding", "deflate"); + response->set("Content-Encoding", "deflate"); LOG_TRC('#' << socket->getFD() << ": Sending " << (headerOnly ? "header for " : "") << " file [" << path << "]."); - socket->send(response); + socket->send(*response); if (!headerOnly) sendDeflatedFileContent(socket, path, st.size()); diff --git a/net/HttpHelper.hpp b/net/HttpHelper.hpp index 987e0571d6..a8bee82a1a 100644 --- a/net/HttpHelper.hpp +++ b/net/HttpHelper.hpp @@ -10,7 +10,13 @@ #include <memory> #include <string> -#include <HttpRequest.hpp> +namespace Poco +{ + namespace Net + { + class HTTPResponse; + } +} class StreamSocket; @@ -29,7 +35,7 @@ void sendErrorAndShutdown(int errorCode, const std::shared_ptr<StreamSocket>& so /// Sends file as HTTP response and shutdown the socket. void sendFileAndShutdown(const std::shared_ptr<StreamSocket>& socket, const std::string& path, const std::string& mediaType, - http::Response& response, bool noCache = false, + Poco::Net::HTTPResponse* optResponse = nullptr, bool noCache = false, bool deflate = false, const bool headerOnly = false); } // namespace HttpHelper diff --git a/net/HttpRequest.hpp b/net/HttpRequest.hpp index 1879d2fcb5..55d922ea41 100644 --- a/net/HttpRequest.hpp +++ b/net/HttpRequest.hpp @@ -832,12 +832,6 @@ public: /// Set an HTTP header field, replacing an earlier value, if exists. void set(const std::string& key, std::string value) { _header.set(key, std::move(value)); } - /// Set the Content-Type header. - void setContentType(std::string type) { _header.setContentType(std::move(type)); } - - /// Set the Content-Length header. - void setContentLength(int64_t length) { _header.setContentLength(length); } - /// Get a header entry value by key, if found, defaulting to @def, if missing. std::string get(const std::string& key, const std::string& def = std::string()) const { diff --git a/test/UnitHTTP.cpp b/test/UnitHTTP.cpp index b33435332f..368924e0b7 100644 --- a/test/UnitHTTP.cpp +++ b/test/UnitHTTP.cpp @@ -176,20 +176,18 @@ public: LOG_TST("Receiving..."); char buffer[4096] = { 0, }; int got = socket->receiveBytes(buffer, 4096); + static const std::string start = + "HTTP/1.0 200 OK\r\n" + "Content-Disposition: attachment; filename=\"test.txt\"\r\n"; - http::Response httpResponse; - LOK_ASSERT_MESSAGE("Expected to receive valid data", - httpResponse.readData(buffer, got) > 0); - LOK_ASSERT(!httpResponse.statusLine().httpVersion().empty()); - LOK_ASSERT(!httpResponse.statusLine().reasonPhrase().empty()); - LOK_ASSERT_EQUAL(static_cast<int>(http::StatusCode::OK), - static_cast<int>(httpResponse.statusLine().statusCode())); - LOK_ASSERT(httpResponse.statusLine().statusCategory() == - http::StatusLine::StatusCodeClass::Successful); - LOK_ASSERT_EQUAL(std::string("HTTP/1.1"), httpResponse.statusLine().httpVersion()); - LOK_ASSERT_EQUAL(std::string("OK"), httpResponse.statusLine().reasonPhrase()); - LOK_ASSERT_EQUAL(std::string("attachment; filename=\"test.txt\""), - httpResponse.header().get("Content-Disposition")); + if (strncmp(buffer, start.c_str(), start.size())) + { + LOG_TST("missing pre-amble " << got << " [" << buffer << "] vs. expected [" << start + << ']'); + LOK_ASSERT(Util::startsWith(std::string(buffer), start)); + exitTest(TestResult::Failed); + return; + } // TODO: check content-length etc. diff --git a/test/UnitWOPIFileUrl.cpp b/test/UnitWOPIFileUrl.cpp index 67f414976d..cb497948e7 100644 --- a/test/UnitWOPIFileUrl.cpp +++ b/test/UnitWOPIFileUrl.cpp @@ -124,10 +124,7 @@ public: { const std::string filename = std::string(TDOC) + FileUrlFilename; LOG_TST("FakeWOPIHost: Request, WOPI::GetFile sending FileUrl: " << filename); - - http::Response response(http::StatusCode::OK); - HttpHelper::sendFileAndShutdown(socket, filename, /*mediaType=*/std::string(), - response); + HttpHelper::sendFileAndShutdown(socket, filename, ""); return true; } @@ -156,10 +153,7 @@ public: const std::string filename = std::string(TDOC) + '/' + DefaultUrlFilename; LOG_TST("FakeWOPIHost: Request, WOPI::GetFile sending Default: " << filename); - - http::Response response(http::StatusCode::OK); - HttpHelper::sendFileAndShutdown(socket, filename, /*mediaType=*/std::string(), - response); + HttpHelper::sendFileAndShutdown(socket, filename, ""); return true; } } @@ -176,11 +170,15 @@ public: std::streamsize size = request.getContentLength(); LOK_ASSERT(size > 0); - http::Response httpResponse(http::StatusCode::OK); - httpResponse.setBody("{\"LastModifiedTime\": \"" + - Util::getHttpTime(getFileLastModifiedTime()) + "\" }", - "application/json; charset=utf-8"); - socket->sendAndShutdown(httpResponse); + std::ostringstream oss; + oss << "HTTP/1.1 200 OK\r\n" + << "User-Agent: " << WOPI_AGENT_STRING << "\r\n" + << "\r\n" + << "{\"LastModifiedTime\": \"" << Util::getHttpTime(getFileLastModifiedTime()) + << "\" }"; + + socket->send(oss.str()); + socket->shutdown(); LOG_TST("Closing document after PutFile"); WSD_CMD("closedocument"); diff --git a/test/UnitWOPITemplate.cpp b/test/UnitWOPITemplate.cpp index 559ad14142..6c863abd7d 100644 --- a/test/UnitWOPITemplate.cpp +++ b/test/UnitWOPITemplate.cpp @@ -93,9 +93,7 @@ public: { LOG_TST("FakeWOPIHost: Handling template GetFile: " << uriReq.getPath()); - http::Response response(http::StatusCode::OK); - HttpHelper::sendFileAndShutdown(socket, TDOC "/test.ott", /*mediaType=*/std::string(), - response); + HttpHelper::sendFileAndShutdown(socket, TDOC "/test.ott", ""); return true; } diff --git a/wsd/COOLWSD.cpp b/wsd/COOLWSD.cpp index 4b10aae9fa..71c2eb6ccd 100644 --- a/wsd/COOLWSD.cpp +++ b/wsd/COOLWSD.cpp @@ -1328,7 +1328,6 @@ public: { Poco::JSON::Object::Ptr aliasGroups; Poco::JSON::Array::Ptr groups; - try { aliasGroups = remoteJson->getObject("storage")->getObject("wopi")->getObject("alias_groups"); @@ -2459,7 +2458,7 @@ void COOLWSD::innerInitialize(Application& self) LOG_DBG("FileServerRoot after config: " << FileServerRoot); //creating quarantine directory - if (getConfigValue<bool>(conf, "quarantine_files[@enable]", false)) + if(getConfigValue<bool>(conf, "quarantine_files[@enable]", false)) { QuarantinePath = getPathFromConfig("quarantine_files.path"); if (QuarantinePath[QuarantinePath.size() - 1] != '/') @@ -3307,7 +3306,6 @@ static std::shared_ptr<DocumentBroker> proto->sendTextMessage(msg.data(), msg.size()); proto->shutdown(true, msg); } - return nullptr; } } @@ -3335,6 +3333,7 @@ static std::shared_ptr<DocumentBroker> if (!docBroker) { Util::assertIsLocked(DocBrokersMutex); + if (DocBrokers.size() + 1 > COOLWSD::MaxDocuments) { LOG_INF("Maximum number of open documents of " << COOLWSD::MaxDocuments << " reached."); @@ -3680,7 +3679,7 @@ public: std::string hostToCheck = request.getHost(); bool allow = allowPostFrom(addressToCheck) || HostUtil::allowedWopiHost(hostToCheck); - if (!allow) + if(!allow) { LOG_WRN_S("convert-to: Requesting address is denied: " << addressToCheck); return false; @@ -3691,7 +3690,7 @@ public: } // Handle forwarded header and make sure all participating IPs are allowed - if (request.has("X-Forwarded-For")) + if(request.has("X-Forwarded-For")) { const std::string fowardedData = request.get("X-Forwarded-For"); StringVector tokens = StringVector::tokenize(fowardedData, ','); @@ -3714,7 +3713,7 @@ public: // We can't find out the hostname, and it already failed the IP check allow = false; } - if (!allow) + if(!allow) { LOG_WRN_S("convert-to: Requesting address is denied: " << addressToCheck); return false; @@ -4051,13 +4050,12 @@ private: assert(socket && "Must have a valid socket"); LOG_TRC_S("Favicon request: " << requestDetails.getURI()); - http::Response response(http::StatusCode::OK); - response.setContentType("image/vnd.microsoft.icon"); + const std::string mimeType = "image/vnd.microsoft.icon"; std::string faviconPath = Path(Application::instance().commandPath()).parent().toString() + "favicon.ico"; if (!File(faviconPath).exists()) faviconPath = COOLWSD::FileServerRoot + "/favicon.ico"; - HttpHelper::sendFileAndShutdown(socket, faviconPath, /*mediaType=*/std::string(), response); + HttpHelper::sendFileAndShutdown(socket, faviconPath, mimeType); } void handleWopiDiscoveryRequest(const RequestDetails &requestDetails, @@ -4184,7 +4182,6 @@ private: if (!data || data->length() == 0) LOG_ERR_S("Invalid zero size set clipboard content"); } - // Do things in the right thread. LOG_TRC_S("Move clipboard request " << tag << " to docbroker thread with data: " << (data ? data->length() : 0) << " bytes"); @@ -4679,7 +4676,7 @@ private: if (attachmentIt != postRequestQueryParams.end()) serveAsAttachment = attachmentIt->second != "0"; - http::Response response(http::StatusCode::OK); + Poco::Net::HTTPResponse response; // Instruct browsers to download the file, not display it // with the exception of SVG where we need the browser to @@ -4690,7 +4687,7 @@ private: try { - HttpHelper::sendFileAndShutdown(socket, filePath.toString(), contentType, response); + HttpHelper::sendFileAndShutdown(socket, filePath.toString(), contentType, &response); } catch (const Exception& exc) { diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index a7c7675331..3656f2a8be 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -774,7 +774,7 @@ bool ClientSession::_handleInput(const char *buffer, int length) } else if (tokens.equals(0, "moveselectedclientparts")) { - if (!_isTextDocument) + if(!_isTextDocument) { int nPosition; if (tokens.size() != 2 || @@ -1729,11 +1729,11 @@ bool ClientSession::handleKitToClientMessage(const std::shared_ptr<Message>& pay LOG_TRC("Sending file: " << resultURL.getPath()); const std::string fileName = Poco::Path(resultURL.getPath()).getFileName(); - http::Response response(http::StatusCode::OK); + Poco::Net::HTTPResponse response; if (!fileName.empty()) response.set("Content-Disposition", "attachment; filename=\"" + fileName + '"'); - HttpHelper::sendFileAndShutdown(_saveAsSocket, resultURL.getPath(), mimeType, response); + HttpHelper::sendFileAndShutdown(_saveAsSocket, resultURL.getPath(), mimeType, &response); } // Conversion is done, cleanup this fake session. @@ -2138,20 +2138,20 @@ bool ClientSession::handleKitToClientMessage(const std::shared_ptr<Message>& pay LOG_TRC("Sending get-thumbnail response."); bool error = false; - if (firstLine.find("error") != std::string::npos) - error = true; + if (firstLine.find("error") != std::string::npos) + error = true; - if (!error) - { - int firstLineSize = firstLine.size() + 1; - std::string thumbnail(payload->data().data() + firstLineSize, payload->data().size() - firstLineSize); - - http::Response httpResponse(http::StatusCode::OK); - httpResponse.set("Last-Modified", Util::getHttpTimeNow()); - httpResponse.set("X-Content-Type-Options", "nosniff"); - httpResponse.setBody(thumbnail, "image/png"); - _saveAsSocket->sendAndShutdown(httpResponse); - } + if (!error) + { + int firstLineSize = firstLine.size() + 1; + std::string thumbnail(payload->data().data() + firstLineSize, payload->data().size() - firstLineSize); + + http::Response httpResponse(http::StatusCode::OK); + httpResponse.set("Last-Modified", Util::getHttpTimeNow()); + httpResponse.set("X-Content-Type-Options", "nosniff"); + httpResponse.setBody(thumbnail, "image/png"); + _saveAsSocket->sendAndShutdown(httpResponse); + } if (error) { diff --git a/wsd/FileServer.cpp b/wsd/FileServer.cpp index 3e3ed0f16f..583926e881 100644 --- a/wsd/FileServer.cpp +++ b/wsd/FileServer.cpp @@ -1,5 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* + * Copyright the Collabora Online contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * * 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/. @@ -71,7 +75,8 @@ using Poco::Util::Application; std::map<std::string, std::pair<std::string, std::string>> FileServerRequestHandler::FileHash; -namespace { +namespace +{ int functionConversation(int /*num_msg*/, const struct pam_message** /*msg*/, struct pam_response **reply, void *appdata_ptr) @@ -292,24 +297,6 @@ bool FileServerRequestHandler::isAdminLoggedIn(const HTTPRequest& request, authenticateAdmin(Poco::Net::HTTPBasicCredentials(request), response, jwtToken); } -bool FileServerRequestHandler::isAdminLoggedIn(const HTTPRequest& request, http::Response& response) -{ - // For now, we reuse the exiting implementation, which uses Poco HTTPCookie. - Poco::Net::HTTPResponse pocoResponse; - if (isAdminLoggedIn(request, pocoResponse)) - { - // Copy the headers, including the cookies. - for (const auto& pair : pocoResponse) - { - response.set(pair.first, pair.second); - } - - return true; - } - - return false; -} - #if ENABLE_DEBUG // Represents basic file's attributes. // Used for localFile @@ -532,7 +519,7 @@ void FileServerRequestHandler::handleRequest(const HTTPRequest& request, #if ENABLE_DEBUG noCache = true; #endif - http::Response response(http::StatusCode::OK); + Poco::Net::HTTPResponse response; const auto& config = Application::instance().config(); @@ -542,9 +529,10 @@ void FileServerRequestHandler::handleRequest(const HTTPRequest& request, { if (config.getBool("ssl.sts.enabled", false)) { - const auto maxAge = config.getInt("ssl.sts.max_age", 31536000); // Default 1 year. + const auto maxAge = + config.getInt("ssl.sts.max_age", 31536000); // Default 1 year. response.add("Strict-Transport-Security", - "max-age=" + std::to_string(maxAge) + "; includeSubDomains"); + "max-age=" + std::to_string(maxAge) + "; includeSubDomains"); } } #endif @@ -584,7 +572,10 @@ void FileServerRequestHandler::handleRequest(const HTTPRequest& request, if (coolLogging != "false") { LOG_ERR(message.rdbuf()); - socket->send(response); + + std::ostringstream oss; + response.write(oss); + socket->send(oss.str()); return; } } @@ -681,19 +672,18 @@ void FileServerRequestHandler::handleRequest(const HTTPRequest& request, response.set("Server", HTTP_SERVER_STRING); response.set("Date", Util::getHttpTimeNow()); + bool gzip = request.hasToken("Accept-Encoding", "gzip"); + const std::string *content; #if ENABLE_DEBUG if (std::getenv("COOL_SERVE_FROM_FS")) { // Useful to not serve from memory sometimes especially during cool development // Avoids having to restart cool everytime you make a change in cool const std::string filePath = Poco::Path(COOLWSD::FileServerRoot, relPath).absolute().toString(); - HttpHelper::sendFileAndShutdown(socket, filePath, mimeType, response, noCache); + HttpHelper::sendFileAndShutdown(socket, filePath, mimeType, &response, noCache); return; } #endif - - const bool gzip = request.hasToken("Accept-Encoding", "gzip"); - const std::string* content; if (gzip) { response.set("Content-Encoding", "gzip"); @@ -708,13 +698,15 @@ void FileServerRequestHandler::handleRequest(const HTTPRequest& request, response.set("Cache-Control", "max-age=11059200"); response.set("ETag", etagString); } + response.setContentType(mimeType); response.add("X-Content-Type-Options", "nosniff"); - LOG_TRC('#' << socket->getFD() << ": Sending " << (!gzip ? "un" : "") - << "compressed : file [" << relPath - << "]: " << response.header().toString()); - - socket->send(response); + std::ostringstream oss; + response.write(oss); + const std::string header = oss.str(); + LOG_TRC('#' << socket->getFD() << ": Sending " << + (!gzip ? "un":"") << "compressed : file [" << relPath << "]: " << header); + socket->send(header); socket->send(*content); // shutdown by caller } @@ -876,6 +868,7 @@ std::string FileServerRequestHandler::getRequestPathname(const HTTPRequest& requ requestUri.normalize(); std::string path(requestUri.getPath()); + Poco::RegularExpression gitHashRe("/([0-9a-f]+)/"); std::string gitHash; if (gitHashRe.extract(path, gitHash)) diff --git a/wsd/FileServer.hpp b/wsd/FileServer.hpp index 93b638a50e..b937ee47c5 100644 --- a/wsd/FileServer.hpp +++ b/wsd/FileServer.hpp @@ -65,7 +65,6 @@ public: /// Evaluate if the cookie exists, and if not, ask for the credentials. static bool isAdminLoggedIn(const Poco::Net::HTTPRequest& request, Poco::Net::HTTPResponse& response); - static bool isAdminLoggedIn(const Poco::Net::HTTPRequest& request, http::Response& response); /// Authenticate the admin. static bool authenticateAdmin(const Poco::Net::HTTPBasicCredentials& credentials, |