summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2020-12-04 14:16:26 +0000
committerSadie Powell <sadie@witchery.services>2020-12-04 14:18:01 +0000
commit151a902ced88b0c1f1791d975332bbe293259acb (patch)
tree7c66b8a35444206766c83546605310b616912dc7
parent08572a9376e6f41109e233cb45d7e491ad1ebf07 (diff)
Normalise paths in the httpd module.
-rw-r--r--src/modules/m_httpd.cpp27
-rw-r--r--src/modules/m_httpd_config.cpp2
-rw-r--r--src/modules/m_httpd_stats.cpp13
3 files changed, 31 insertions, 11 deletions
diff --git a/src/modules/m_httpd.cpp b/src/modules/m_httpd.cpp
index efed34799..a155dd278 100644
--- a/src/modules/m_httpd.cpp
+++ b/src/modules/m_httpd.cpp
@@ -351,7 +351,32 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
return false;
if (url.field_set & (1 << UF_PATH))
- out.path = uri.substr(url.field_data[UF_PATH].off, url.field_data[UF_PATH].len);
+ {
+ // Normalise the path.
+ std::vector<std::string> pathsegments;
+ irc::sepstream pathstream(uri.substr(url.field_data[UF_PATH].off, url.field_data[UF_PATH].len), '/');
+ for (std::string pathsegment; pathstream.GetToken(pathsegment); )
+ {
+ if (pathsegment == ".")
+ {
+ // Stay at the current level.
+ continue;
+ }
+
+ if (pathsegment == "..")
+ {
+ // Traverse up to the previous level.
+ if (!pathsegments.empty())
+ pathsegment.pop_back();
+ continue;
+ }
+
+ pathsegments.push_back(pathsegment);
+ }
+
+ out.path.reserve(url.field_data[UF_PATH].len);
+ out.path.append("/").append(stdalgo::string::join(pathsegments, '/'));
+ }
if (url.field_set & (1 << UF_FRAGMENT))
out.fragment = uri.substr(url.field_data[UF_FRAGMENT].off, url.field_data[UF_FRAGMENT].len);
diff --git a/src/modules/m_httpd_config.cpp b/src/modules/m_httpd_config.cpp
index bc669dae3..b8b1fd7a7 100644
--- a/src/modules/m_httpd_config.cpp
+++ b/src/modules/m_httpd_config.cpp
@@ -39,7 +39,7 @@ class ModuleHttpConfig : public Module, public HTTPRequestEventListener
ModResult OnHTTPRequest(HTTPRequest& request) CXX11_OVERRIDE
{
- if ((request.GetPath() != "/config") && (request.GetPath() != "/config/"))
+ if (request.GetPath() != "/config")
return MOD_RES_PASSTHRU;
ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Handling HTTP request for %s", request.GetPath().c_str());
diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp
index 0b674cf64..f24fd9aec 100644
--- a/src/modules/m_httpd_stats.cpp
+++ b/src/modules/m_httpd_stats.cpp
@@ -423,32 +423,27 @@ class ModuleHttpStats : public Module, public HTTPRequestEventListener
ModResult HandleRequest(HTTPRequest* http)
{
- std::string path = http->GetPath();
-
- if (path != "/stats" && path.substr(0, 7) != "/stats/")
+ if (http->GetPath() != "/stats")
return MOD_RES_PASSTHRU;
- if (path[path.size() - 1] == '/')
- path.erase(path.size() - 1, 1);
-
ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Handling HTTP request for %s", http->GetPath().c_str());
bool found = true;
std::stringstream data;
data << "<inspircdstats>";
- if (path == "/stats")
+ if (http->GetPath() == "/stats")
{
data << Stats::ServerInfo << Stats::General
<< Stats::XLines << Stats::Modules
<< Stats::Channels << Stats::Users
<< Stats::Servers << Stats::Commands;
}
- else if (path == "/stats/general")
+ else if (http->GetPath() == "/stats/general")
{
data << Stats::General;
}
- else if (path == "/stats/users")
+ else if (http->GetPath() == "/stats/users")
{
if (enableparams)
Stats::ListUsers(data, http->GetParsedURI().query_params);