]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_httpd.cpp
Fix the ctctags module being marked as a draft.
[user/henk/code/inspircd.git] / src / modules / m_httpd.cpp
index f67f4cb81464a18779745cb3e47bef523e213101..f9e5bc0fdca282acb328208c51deef4780847e02 100644 (file)
 #if defined __clang__
 # pragma clang diagnostic ignored "-Wc++11-extensions"
 #elif defined __GNUC__
-# pragma GCC diagnostic ignored "-pedantic"
+# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))
+#  pragma GCC diagnostic ignored "-Wpedantic"
+# else
+#  pragma GCC diagnostic ignored "-pedantic"
+# endif
 #endif
 
 // Fix warnings about shadowing in http_parser.
-#pragma GCC diagnostic ignored "-Wshadow"
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wshadow"
+#endif
 
 #include <http_parser.c>
 
@@ -55,6 +61,7 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
        friend ModuleHttpServer;
 
        http_parser parser;
+       http_parser_url url;
        std::string ip;
        std::string uri;
        HTTPHeaders headers;
@@ -217,24 +224,12 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
                AddToCull();
        }
 
-       const char* Response(unsigned int response)
-       {
-               switch (response)
-               {
-#define HTTP_STATUS_CASE(n, m, s) case n: return #s;
-                       HTTP_STATUS_MAP(HTTP_STATUS_CASE)
-                       default:
-                               return "WTF";
-                       break;
-               }
-       }
-
        void SendHTTPError(unsigned int response)
        {
                HTTPHeaders empty;
                std::string data = InspIRCd::Format(
                        "<html><head></head><body>Server error %u: %s<br>"
-                       "<small>Powered by <a href='http://www.inspircd.org'>InspIRCd</a></small></body></html>", response, Response(response));
+                       "<small>Powered by <a href='https://www.inspircd.org'>InspIRCd</a></small></body></html>", response, http_status_str((http_status)response));
 
                SendHeaders(data.length(), response, empty);
                WriteData(data);
@@ -243,7 +238,7 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
 
        void SendHeaders(unsigned long size, unsigned int response, HTTPHeaders &rheaders)
        {
-               WriteData(InspIRCd::Format("HTTP/%u.%u %u %s\r\n", parser.http_major ? parser.http_major : 1, parser.http_major ? parser.http_minor : 1, response, Response(response)));
+               WriteData(InspIRCd::Format("HTTP/%u.%u %u %s\r\n", parser.http_major ? parser.http_major : 1, parser.http_major ? parser.http_minor : 1, response, http_status_str((http_status)response)));
 
                rheaders.CreateHeader("Date", InspIRCd::TimeString(ServerInstance->Time(), "%a, %d %b %Y %H:%M:%S GMT", true));
                rheaders.CreateHeader("Server", INSPIRCD_BRANCH);
@@ -276,11 +271,13 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
        {
                ModResult MOD_RESULT;
                std::string method = http_method_str(static_cast<http_method>(parser.method));
-               HTTPRequest acl(method, uri, &headers, this, ip, body);
+               HTTPRequestURI parsed;
+               ParseURI(uri, parsed);
+               HTTPRequest acl(method, parsed, &headers, this, ip, body);
                FIRST_MOD_RESULT_CUSTOM(*aclevprov, HTTPACLEventListener, OnHTTPACLCheck, MOD_RESULT, (acl));
                if (MOD_RESULT != MOD_RES_DENY)
                {
-                       HTTPRequest url(method, uri, &headers, this, ip, body);
+                       HTTPRequest url(method, parsed, &headers, this, ip, body);
                        FIRST_MOD_RESULT_CUSTOM(*reqevprov, HTTPRequestEventListener, OnHTTPRequest, MOD_RESULT, (url));
                        if (MOD_RESULT == MOD_RES_PASSTHRU)
                        {
@@ -305,6 +302,40 @@ class HttpServerSocket : public BufferedSocket, public Timer, public insp::intru
                Close();
                ServerInstance->GlobalCulls.AddItem(this);
        }
+
+       bool ParseURI(const std::string& uri, HTTPRequestURI& out)
+       {
+               http_parser_url_init(&url);
+               if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &url) != 0)
+                       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);
+
+               if (url.field_set & (1 << UF_FRAGMENT))
+                       out.fragment = uri.substr(url.field_data[UF_FRAGMENT].off, url.field_data[UF_FRAGMENT].len);
+
+               std::string param_str;
+               if (url.field_set & (1 << UF_QUERY))
+                       param_str = uri.substr(url.field_data[UF_QUERY].off, url.field_data[UF_QUERY].len);
+
+               irc::sepstream param_stream(param_str, '&');
+               std::string token;
+               std::string::size_type eq_pos;
+               while (param_stream.GetToken(token))
+               {
+                       eq_pos = token.find('=');
+                       if (eq_pos == std::string::npos)
+                       {
+                               out.query_params.insert(std::make_pair(token, ""));
+                       }
+                       else
+                       {
+                               out.query_params.insert(std::make_pair(token.substr(0, eq_pos), token.substr(eq_pos + 1)));
+                       }
+               }
+               return true;
+       }
 };
 
 class HTTPdAPIImpl : public HTTPdAPIBase