bool cHTTPFormParser::HasFormData(const cHTTPRequest & a_Request) { const AString & ContentType = a_Request.GetContentType(); return ( (ContentType == "application/x-www-form-urlencoded") || (strncmp(ContentType.c_str(), "multipart/form-data", 19) == 0) || ( (a_Request.GetMethod() == "GET") && (a_Request.GetURL().find('?') != AString::npos) ) ); }
virtual void OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override { UNUSED(a_Connection); if (cHTTPFormParser::HasFormData(a_Request)) { a_Request.SetUserData(new cHTTPFormParser(a_Request, *this)); } }
void cWebAdmin::OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, int a_Size) { cRequestData * Data = (cRequestData *)(a_Request.GetUserData()); if (Data == NULL) { return; } Data->OnBody(a_Data, a_Size); }
void cWebAdmin::OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) { const AString & URL = a_Request.GetURL(); if ( (strncmp(URL.c_str(), "/webadmin", 9) == 0) || (strncmp(URL.c_str(), "/~webadmin", 10) == 0) ) { a_Request.SetUserData(new cWebadminRequestData(a_Request)); return; } if (URL == "/") { // The root needs no body handler and is fully handled in the OnRequestFinished() call return; } // TODO: Handle other requests }
virtual void OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) override { UNUSED(a_Connection); cHTTPFormParser * FormParser = (cHTTPFormParser *)(a_Request.GetUserData()); if (FormParser != NULL) { FormParser->Parse(a_Data, a_Size); } }
virtual void OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) override { UNUSED(a_Connection); cHTTPFormParser * FormParser = reinterpret_cast<cHTTPFormParser *>(a_Request.GetUserData()); if (FormParser != nullptr) { FormParser->Parse(a_Data, a_Size); } }
virtual void OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override { cHTTPFormParser * FormParser = (cHTTPFormParser *)(a_Request.GetUserData()); if (FormParser != NULL) { if (FormParser->Finish()) { cHTTPResponse Resp; Resp.SetContentType("text/html"); a_Connection.Send(Resp); a_Connection.Send("<html><body><table border=1 cellspacing=0><tr><th>Name</th><th>Value</th></tr>\r\n"); for (cHTTPFormParser::iterator itr = FormParser->begin(), end = FormParser->end(); itr != end; ++itr) { a_Connection.Send(Printf("<tr><td valign=\"top\"><pre>%s</pre></td><td valign=\"top\"><pre>%s</pre></td></tr>\r\n", itr->first.c_str(), itr->second.c_str())); } // for itr - FormParser[] a_Connection.Send("</table></body></html>"); return; } // Parsing failed: cHTTPResponse Resp; Resp.SetContentType("text/plain"); a_Connection.Send(Resp); a_Connection.Send("Form parsing failed"); return; } // Test the auth failure and success: if (a_Request.GetURL() == "/auth") { if (!a_Request.HasAuth() || (a_Request.GetAuthUsername() != "a") || (a_Request.GetAuthPassword() != "b")) { a_Connection.SendNeedAuth("MCServer WebAdmin"); return; } } cHTTPResponse Resp; Resp.SetContentType("text/plain"); a_Connection.Send(Resp); a_Connection.Send("Hello, world"); }
cHTTPFormParser::cHTTPFormParser(cHTTPRequest & a_Request, cCallbacks & a_Callbacks) : m_Callbacks(a_Callbacks), m_IsValid(true) { if (a_Request.GetMethod() == "GET") { m_Kind = fpkURL; // Directly parse the URL in the request: const AString & URL = a_Request.GetURL(); size_t idxQM = URL.find('?'); if (idxQM != AString::npos) { Parse(URL.c_str() + idxQM + 1, URL.size() - idxQM - 1); } return; } if ((a_Request.GetMethod() == "POST") || (a_Request.GetMethod() == "PUT")) { if (strncmp(a_Request.GetContentType().c_str(), "application/x-www-form-urlencoded", 33) == 0) { m_Kind = fpkFormUrlEncoded; return; } if (strncmp(a_Request.GetContentType().c_str(), "multipart/form-data", 19) == 0) { m_Kind = fpkMultipart; BeginMultipart(a_Request); return; } } // Invalid method / content type combination, this is not a HTTP form m_IsValid = false; }
void cWebAdmin::OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) { const AString & URL = a_Request.GetURL(); if ( (strncmp(URL.c_str(), "/webadmin", 9) == 0) || (strncmp(URL.c_str(), "/~webadmin", 10) == 0) ) { HandleWebadminRequest(a_Connection, a_Request); } else if (URL == "/") { // The root needs no body handler and is fully handled in the OnRequestFinished() call HandleRootRequest(a_Connection, a_Request); } else { // TODO: Handle other requests } // Delete any request data assigned to the request: cRequestData * Data = (cRequestData *)(a_Request.GetUserData()); delete Data; }
void cHTTPFormParser::BeginMultipart(const cHTTPRequest & a_Request) { ASSERT(m_MultipartParser.get() == nullptr); m_MultipartParser.reset(new cMultipartParser(a_Request.GetContentType(), *this)); }
void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) { if (!a_Request.HasAuth()) { a_Connection.SendNeedAuth("MCServer WebAdmin"); return; } // Check auth: AString UserPassword = m_IniFile.GetValue("User:"******"Password", ""); if ((UserPassword == "") || (a_Request.GetAuthPassword() != UserPassword)) { a_Connection.SendNeedAuth("MCServer WebAdmin - bad username or password"); return; } // Check if the contents should be wrapped in the template: AString URL = a_Request.GetBareURL(); ASSERT(URL.length() > 0); bool ShouldWrapInTemplate = ((URL.length() > 1) && (URL[1] != '~')); // Retrieve the request data: cWebadminRequestData * Data = (cWebadminRequestData *)(a_Request.GetUserData()); if (Data == NULL) { a_Connection.SendStatusAndReason(500, "Bad UserData"); return; } // Wrap it all up for the Lua call: AString Template; HTTPTemplateRequest TemplateRequest; TemplateRequest.Request.Username = a_Request.GetAuthUsername(); TemplateRequest.Request.Method = a_Request.GetMethod(); TemplateRequest.Request.Path = URL.substr(1); if (Data->m_Form.Finish()) { for (cHTTPFormParser::const_iterator itr = Data->m_Form.begin(), end = Data->m_Form.end(); itr != end; ++itr) { HTTPFormData HTTPfd; HTTPfd.Value = itr->second; HTTPfd.Type = ""; HTTPfd.Name = itr->first; TemplateRequest.Request.FormData[itr->first] = HTTPfd; TemplateRequest.Request.PostParams[itr->first] = itr->second; } // for itr - Data->m_Form[] // Parse the URL into individual params: size_t idxQM = a_Request.GetURL().find('?'); if (idxQM != AString::npos) { cHTTPFormParser URLParams(cHTTPFormParser::fpkURL, a_Request.GetURL().c_str() + idxQM + 1, a_Request.GetURL().length() - idxQM - 1, *Data); URLParams.Finish(); for (cHTTPFormParser::const_iterator itr = URLParams.begin(), end = URLParams.end(); itr != end; ++itr) { TemplateRequest.Request.Params[itr->first] = itr->second; } // for itr - URLParams[] } } // Try to get the template from the Lua template script if (ShouldWrapInTemplate) { if (m_TemplateScript.Call("ShowPage", this, &TemplateRequest, cLuaState::Return, Template)) { cHTTPResponse Resp; Resp.SetContentType("text/html"); a_Connection.Send(Resp); a_Connection.Send(Template.c_str(), Template.length()); return; } a_Connection.SendStatusAndReason(500, "m_TemplateScript failed"); return; } AString BaseURL = GetBaseURL(URL); AString Menu; Template = "{CONTENT}"; AString FoundPlugin; for (PluginList::iterator itr = m_Plugins.begin(); itr != m_Plugins.end(); ++itr) { cWebPlugin * WebPlugin = *itr; std::list< std::pair<AString, AString> > NameList = WebPlugin->GetTabNames(); for (std::list< std::pair<AString, AString> >::iterator Names = NameList.begin(); Names != NameList.end(); ++Names) { Menu += "<li><a href='" + BaseURL + WebPlugin->GetWebTitle().c_str() + "/" + (*Names).second + "'>" + (*Names).first + "</a></li>"; } } sWebAdminPage Page = GetPage(TemplateRequest.Request); AString Content = Page.Content; FoundPlugin = Page.PluginName; if (!Page.TabName.empty()) { FoundPlugin += " - " + Page.TabName; } if (FoundPlugin.empty()) // Default page { Content = GetDefaultPage(); } if (ShouldWrapInTemplate && (URL.size() > 1)) { Content += "\n<p><a href='" + BaseURL + "'>Go back</a></p>"; } int MemUsageKiB = cRoot::GetPhysicalRAMUsage(); if (MemUsageKiB > 0) { ReplaceString(Template, "{MEM}", Printf("%.02f", (double)MemUsageKiB / 1024)); ReplaceString(Template, "{MEMKIB}", Printf("%d", MemUsageKiB)); } else { ReplaceString(Template, "{MEM}", "unknown"); ReplaceString(Template, "{MEMKIB}", "unknown"); } ReplaceString(Template, "{USERNAME}", a_Request.GetAuthUsername()); ReplaceString(Template, "{MENU}", Menu); ReplaceString(Template, "{PLUGIN_NAME}", FoundPlugin); ReplaceString(Template, "{CONTENT}", Content); ReplaceString(Template, "{TITLE}", "MCServer"); AString NumChunks; Printf(NumChunks, "%d", cRoot::Get()->GetTotalChunkCount()); ReplaceString(Template, "{NUMCHUNKS}", NumChunks); cHTTPResponse Resp; Resp.SetContentType("text/html"); a_Connection.Send(Resp); a_Connection.Send(Template.c_str(), Template.length()); }