X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fhttp%2Fipagehandler.cpp;h=1ec7947dbba72488785cdd4085377b8082dd56a1;hb=59a5414ec47a2932a7802fcd1d98c4d80166564f;hp=6edd8ac38e2a0b92537e30dfb972e271d93dfc78;hpb=14fff12d9df0ee30e2df4bf9d22c2e83065816df;p=fms.git diff --git a/src/http/ipagehandler.cpp b/src/http/ipagehandler.cpp index 6edd8ac..1ec7947 100644 --- a/src/http/ipagehandler.cpp +++ b/src/http/ipagehandler.cpp @@ -1,6 +1,13 @@ #include "../../include/http/ipagehandler.h" -#include "../../include/http/httpdefs.h" #include "../../include/stringfunctions.h" +#include "../../include/http/multipartparser.h" + +#include +#include +#include +#include +#include +#include #include @@ -33,6 +40,28 @@ void IPageHandler::CreateArgArray(const std::map &vars, } } +const std::string IPageHandler::CreateFormPassword() +{ + Poco::DateTime date; + Poco::UUIDGenerator uuidgen; + Poco::UUID uuid; + try + { + uuid=uuidgen.createRandom(); + } + catch(...) + { + } + + SQLite3DB::Statement st=m_db->Prepare("INSERT INTO tmpFormPassword(Date,Password) VALUES(?,?);"); + st.Bind(0,Poco::DateTimeFormatter::format(date,"%Y-%m-%d %H:%M:%S")); + st.Bind(1,uuid.toString()); + st.Step(); + + return ""; + +} + const std::string IPageHandler::CreateTrueFalseDropDown(const std::string &name, const std::string &selected) { std::string rval=""; @@ -55,241 +84,137 @@ const std::string IPageHandler::CreateTrueFalseDropDown(const std::string &name, return rval; } -const bool IPageHandler::Handle(shttpd_arg *arg) +void IPageHandler::CreateQueryVarMap(Poco::Net::HTTPServerRequest &request, std::map &vars) { - const char *uri=shttpd_get_env(arg,"REQUEST_URI"); - const char *method=shttpd_get_env(arg,"REQUEST_METHOD"); - std::string methodstr=""; - if(method) + for(Poco::Net::HTTPServerRequest::ConstIterator i=request.begin(); i!=request.end(); i++) { - methodstr=method; + vars[(*i).first]=(*i).second; } - if(uri && WillHandleURI(std::string(uri))) + // handle HTMLForm and multiparts + MultiPartParser mpp; + Poco::Net::HTMLForm form(request,request.stream(),mpp); + for(Poco::Net::HTMLForm::ConstIterator i=form.begin(); i!=form.end(); i++) { - httpstate *mystate=(httpstate *)arg->state; + vars[(*i).first]=(*i).second; + } - // first check if there was a connection error - if so delete the input/output and state buffers and return immediately - if((arg->flags & SHTTPD_CONNECTION_ERROR)==SHTTPD_CONNECTION_ERROR) + // for a POST method, the HTMLForm won't grab vars off the query string so we + // temporarily set the method to GET and parse with the HTMLForm again + if(request.getMethod()=="POST") + { + request.setMethod("GET"); + Poco::Net::HTMLForm form1(request,request.stream(),mpp); + for(Poco::Net::HTMLForm::ConstIterator i=form1.begin(); i!=form1.end(); i++) { - if(mystate && mystate->m_indata) - { - delete mystate->m_indata; - mystate->m_indata=NULL; - } - if(mystate && mystate->m_outdata) - { - delete mystate->m_outdata; - mystate->m_outdata=NULL; - } - if(mystate) - { - delete mystate; - mystate=NULL; - } - return true; + vars[(*i).first]=(*i).second; } + request.setMethod("POST"); + } - // this is a new request - create a new arg object - if(arg->state==NULL) - { - arg->state=new httpstate; - memset(arg->state,0,sizeof(httpstate)); - mystate=(httpstate *)arg->state; + // get any multiparts + std::map mpvars=mpp.GetVars(); + for(std::map::iterator i=mpvars.begin(); i!=mpvars.end(); i++) + { + vars[(*i).first]=(*i).second; + } - // if post then create input buffer - if(methodstr=="POST") - { - const char *lenstr=shttpd_get_header(arg,"Content-Length"); - if(lenstr) - { - long len; - StringFunctions::Convert(std::string(lenstr),len); - mystate->m_indata=new char[len+1]; - mystate->m_indata[len]='\0'; - mystate->m_indatalen=len; - mystate->m_indatapos=0; - } - } - } +} - // we have more POST data to get - if(arg->in.len>0) - { - int pos=0; - while(posin.len) - { - mystate->m_indata[mystate->m_indatapos++]=arg->in.buf[pos++]; - } - arg->in.num_bytes=arg->in.len; - } +void IPageHandler::handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response) +{ + m_log->trace("IPageHandler::handleRequest from "+request.clientAddress().toString()); - // we have all POST data (or it was 0 to begin with) - generate the page - if(mystate->m_indatalen==mystate->m_indatapos && mystate->m_outdata==NULL) - { - //parse POST data and any QUERY_STRING before generating page - std::map args; - std::vector argparts; - std::string contenttype=""; - - if(shttpd_get_header(arg,"Content-Type")) - { - contenttype=shttpd_get_header(arg,"Content-Type"); - } - - if(contenttype.find("multipart/form-data")!=std::string::npos) - { - HandleMultiPartData(contenttype,mystate->m_indata,mystate->m_indatalen,args); - } - else - { - // split apart non-multipart POST - if(mystate->m_indata) - { - StringFunctions::Split(mystate->m_indata,"&",argparts); - } - // split apart query string - if(shttpd_get_env(arg,"QUERY_STRING")) - { - StringFunctions::Split(shttpd_get_env(arg,"QUERY_STRING"),"&",argparts); - } + std::map vars; - for(std::vector::iterator argi=argparts.begin(); argi!=argparts.end(); argi++) - { - std::vector parts; - StringFunctions::Split((*argi),"=",parts); - if(parts.size()>0) - { - // replace + with space before UriDecoding - parts[0]=StringFunctions::Replace(parts[0],"+"," "); - args[StringFunctions::UriDecode(parts[0])]; - if(parts.size()>1) - { - // replace + with space before UriDecoding - parts[1]=StringFunctions::Replace(parts[1],"+"," "); - args[StringFunctions::UriDecode(parts[0])]=StringFunctions::UriDecode(parts[1]); - } - } - } - } + CreateQueryVarMap(request,vars); - std::string page=GeneratePage(methodstr,args); - mystate->m_outdata=new char[page.size()]; - memcpy(mystate->m_outdata,page.c_str(),page.size()); - mystate->m_outdatalen=page.size(); - mystate->m_outdatapos=0; - } + if(request.getVersion()==Poco::Net::HTTPRequest::HTTP_1_1) + { + response.setChunkedTransferEncoding(true); + } + response.setContentType("text/html"); - // if we have output data, push next block of data onto out buffer - if(mystate->m_outdata && mystate->m_outdataposm_outdatalen) - { - int pos=0; - while(mystate->m_outdataposm_outdatalen && posout.len) - { - arg->out.buf[pos++]=mystate->m_outdata[mystate->m_outdatapos++]; - } - arg->out.num_bytes=pos; - } + std::ostream &ostr = response.send(); + ostr << GeneratePage(request.getMethod(),vars); - // if we have no more output data to send - delete the data pointers and set end of output flag - if(mystate->m_outdata && mystate->m_outdatapos==mystate->m_outdatalen) - { - if(mystate->m_indata) - { - delete [] mystate->m_indata; - } - if(mystate->m_outdata) - { - delete [] mystate->m_outdata; - } - delete mystate; - arg->state=NULL; - - arg->flags|=SHTTPD_END_OF_OUTPUT; - } +} - return true; - } - else - { - return false; - } +const std::string IPageHandler::SanitizeOutput(const std::string &input) +{ + // must do & first because all other elements have & in them! + std::string output=StringFunctions::Replace(input,"&","&"); + output=StringFunctions::Replace(output,"<","<"); + output=StringFunctions::Replace(output,">",">"); + output=StringFunctions::Replace(output,"\"","""); + output=StringFunctions::Replace(output," "," "); + return output; } -void IPageHandler::HandleMultiPartData(const std::string &contenttypeheader, char *data, const long datalen, std::map &args) +const std::string IPageHandler::SanitizeTextAreaOutput(const std::string &input) { - if(data) - { - std::string datastr(data,data+datalen); - std::vector parts; - std::string boundary=""; - std::string::size_type pos=contenttypeheader.find("boundary="); + // must do & first because all other elements have & in them! + std::string output=StringFunctions::Replace(input,"&","&"); + output=StringFunctions::Replace(output,"<","<"); + output=StringFunctions::Replace(output,">",">"); + output=StringFunctions::Replace(output,"\"","""); + return output; +} - // find boundary - if(pos!=std::string::npos) - { - boundary=contenttypeheader.substr(pos+9); - // strip off any " and ; - boundary=StringFunctions::Replace(boundary,"\"",""); - boundary=StringFunctions::Replace(boundary,";",""); - } +const bool IPageHandler::ValidateFormPassword(const std::map &vars) +{ + Poco::DateTime date; + date-=Poco::Timespan(0,1,0,0,0); - // split into parts separated by boundary - StringFunctions::Split(datastr,"--"+boundary+"\r\n",parts); + SQLite3DB::Statement st=m_db->Prepare("DELETE FROM tmpFormPassword WHERE Date::iterator i=parts.begin(); i!=parts.end(); i++) + std::map::const_iterator i=vars.find("formpassword"); + if(i!=vars.end()) + { + st=m_db->Prepare("SELECT COUNT(*) FROM tmpFormPassword WHERE Password=?;"); + st.Bind(0,(*i).second); + st.Step(); + if(st.RowReturned()) { - std::string data=""; - std::string name=""; - - // find name - pos=(*i).find("name="); - if(pos!=std::string::npos) + if(st.ResultNull(0)==false) { - std::string::size_type pos2=(*i).find(";",pos); - if(pos2!=std::string::npos) + int rval=0; + st.ResultInt(0,rval); + if(rval>0) { - name=(*i).substr(pos+5,pos2-(pos+5)); + return true; } else { - pos2=(*i).find("\r\n",pos); - if(pos2!=std::string::npos) - { - name=(*i).substr(pos+5,pos2-(pos+5)); - } - } - - name=StringFunctions::Replace(name,"\"",""); - } - - // find header boundary - pos=(*i).find("\r\n\r\n"); - if(pos!=std::string::npos) - { - data=(*i).substr(pos+4); - // strip off final \r\n from data - if(data.size()>2 && data.rfind("\r\n")==data.size()-2) - { - data.erase(data.size()-2); + return false; } } - if(name!="" && data!="") + else { - args[name]=data; + return false; } } + else + { + return false; + } + } + else + { + return false; } } -const std::string IPageHandler::SanitizeOutput(const std::string &input) +const bool IPageHandler::WillHandleURI(const std::string &uri) { - // must do & first because all other elements have & in them! - std::string output=StringFunctions::Replace(input,"&","&"); - output=StringFunctions::Replace(output,"<","<"); - output=StringFunctions::Replace(output,">",">"); - output=StringFunctions::Replace(output,"\"","""); - output=StringFunctions::Replace(output," "," "); - return output; + if(uri.find(m_pagename)!=std::string::npos) + { + return true; + } + else + { + return false; + } }