]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_httpd.cpp
Sync helpop chmodes s and p with docs
[user/henk/code/inspircd.git] / src / modules / m_httpd.cpp
index 978a60ab76e8a959fca18f52a76f4190deb719ea..f3ec3298bd8823b154b4c9fb5017159ba7bea800 100644 (file)
@@ -3,9 +3,9 @@
  *
  *   Copyright (C) 2019 linuxdaemon <linuxdaemon.irc@gmail.com>
  *   Copyright (C) 2018 edef <edef@edef.eu>
- *   Copyright (C) 2013-2014, 2017-2019 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2013-2014, 2017-2020 Sadie Powell <sadie@witchery.services>
  *   Copyright (C) 2012-2016 Attila Molnar <attilamolnar@hush.com>
- *   Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
+ *   Copyright (C) 2012 Robby <robby@chatbelgie.be>
  *   Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
  *   Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
@@ -95,6 +95,7 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
        {
                if (!messagecomplete)
                {
+                       ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "HTTP socket %d timed out", GetFd());
                        Close();
                        return false;
                }
@@ -229,6 +230,8 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
                        // IOHook may have errored
                        if (!getError().empty())
                        {
+                               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "HTTP socket %d encountered a hook error: %s",
+                                       GetFd(), getError().c_str());
                                Close();
                                return;
                        }
@@ -254,19 +257,25 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
                ServerInstance->GlobalCulls.AddItem(this);
        }
 
-       void OnError(BufferedSocketError) CXX11_OVERRIDE
+       void OnError(BufferedSocketError err) CXX11_OVERRIDE
        {
+               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "HTTP socket %d encountered an error: %d - %s",
+                       GetFd(), err, getError().c_str());
                Close();
        }
 
-       void SendHTTPError(unsigned int response)
+       void SendHTTPError(unsigned int response, const char* errstr = NULL)
        {
+               if (!errstr)
+                       errstr = http_status_str((http_status)response);
+
+               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Sending HTTP error %u: %s", response, errstr);
                static HTTPHeaders empty;
                std::string data = InspIRCd::Format(
                        "<html><head></head><body style='font-family: sans-serif; text-align: center'>"
                        "<h1 style='font-size: 48pt'>Error %u</h1><h2 style='font-size: 24pt'>%s</h2><hr>"
                        "<small>Powered by <a href='https://www.inspircd.org'>InspIRCd</a></small></body></html>",
-                       response, http_status_str((http_status)response));
+                       response, errstr);
 
                Page(data, response, &empty);
        }
@@ -284,7 +293,7 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
                else
                        rheaders.RemoveHeader("Content-Type");
 
-               /* Supporting Connection: keep-alive causes a whole world of hurt syncronizing timeouts,
+               /* Supporting Connection: keep-alive causes a whole world of hurt synchronizing timeouts,
                 * so remove it, its not essential for what we need.
                 */
                rheaders.SetHeader("Connection", "Close");
@@ -298,8 +307,10 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
                if (parser.upgrade || HTTP_PARSER_ERRNO(&parser))
                        return;
                http_parser_execute(&parser, &parser_settings, recvq.data(), recvq.size());
-               if (parser.upgrade || HTTP_PARSER_ERRNO(&parser))
+               if (parser.upgrade)
                        SendHTTPError(status_code ? status_code : 400);
+               else if (HTTP_PARSER_ERRNO(&parser))
+                       SendHTTPError(status_code ? status_code : 400, http_errno_description((http_errno)parser.http_errno));
        }
 
        void ServeData()
@@ -340,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())
+                                               pathsegments.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);
@@ -446,7 +482,7 @@ class ModuleHttpServer : public Module
 
        Version GetVersion() CXX11_OVERRIDE
        {
-               return Version("Provides HTTP serving facilities to modules", VF_VENDOR);
+               return Version("Allows the server administrator to serve various useful resources over HTTP.", VF_VENDOR);
        }
 };