summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAshod Nakashian <ashod.nakashian@collabora.co.uk>2024-05-04 08:45:10 -0400
committerTimur <timur@libreoffice.org>2024-05-04 20:13:26 +0100
commitafafe35a41529e0fe86385638fb6ddd5c8a6a0b0 (patch)
tree7e5e3c842a9b9a06ebbaa0ca453d1699c3eaf770
parentRevert "killpoco: use http::Response for Admin metrics" (diff)
downloadonline-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.cpp27
-rw-r--r--net/HttpHelper.hpp10
-rw-r--r--net/HttpRequest.hpp6
-rw-r--r--test/UnitHTTP.cpp24
-rw-r--r--test/UnitWOPIFileUrl.cpp24
-rw-r--r--test/UnitWOPITemplate.cpp4
-rw-r--r--wsd/COOLWSD.cpp21
-rw-r--r--wsd/ClientSession.cpp32
-rw-r--r--wsd/FileServer.cpp57
-rw-r--r--wsd/FileServer.hpp1
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,