X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fhttp%2Fipagehandler.cpp;h=3565aabb20707637d88160a6e6f604b764996f25;hb=ee580d19b7920904587e18d72a3465d52eab6204;hp=d90a927529fc564a8cdb02279e1d4ab1becbcc1a;hpb=37a8d59548287dcad78ef00e7b18058721eb9935;p=fms.git diff --git a/src/http/ipagehandler.cpp b/src/http/ipagehandler.cpp index d90a927..3565aab 100644 --- a/src/http/ipagehandler.cpp +++ b/src/http/ipagehandler.cpp @@ -12,7 +12,7 @@ void IPageHandler::CreateArgArray(const std::map &vars, { if((*i).first.find(basename)==0 && (*i).first.find("[")!=std::string::npos && (*i).first.find("]")!=std::string::npos) { - int index; + int index=0; std::string indexstr; std::string::size_type startpos; std::string::size_type endpos; @@ -44,6 +44,28 @@ const bool IPageHandler::Handle(shttpd_arg *arg) if(uri && WillHandleURI(std::string(uri))) { httpstate *mystate=(httpstate *)arg->state; + + // 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) + { + 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; + } + // this is a new request - create a new arg object if(arg->state==NULL) { @@ -60,7 +82,7 @@ const bool IPageHandler::Handle(shttpd_arg *arg) long len; StringFunctions::Convert(std::string(lenstr),len); mystate->m_indata=new char[len+1]; - mystate->m_indata[len]=NULL; + mystate->m_indata[len]='\0'; mystate->m_indatalen=len; mystate->m_indatapos=0; } @@ -81,32 +103,48 @@ const bool IPageHandler::Handle(shttpd_arg *arg) // 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) { - //TODO parse POST data and any QUERY_STRING before generating page + //parse POST data and any QUERY_STRING before generating page std::map args; std::vector argparts; + std::string contenttype=""; - if(mystate->m_indata) + if(shttpd_get_header(arg,"Content-Type")) { - StringFunctions::Split(mystate->m_indata,"&",argparts); + contenttype=shttpd_get_header(arg,"Content-Type"); } - if(shttpd_get_env(arg,"QUERY_STRING")) + + if(contenttype.find("multipart/form-data")!=std::string::npos) { - StringFunctions::Split(shttpd_get_env(arg,"QUERY_STRING"),"&",argparts); + HandleMultiPartData(contenttype,mystate->m_indata,mystate->m_indatalen,args); } - for(std::vector::iterator argi=argparts.begin(); argi!=argparts.end(); argi++) + else { - std::vector parts; - StringFunctions::Split((*argi),"=",parts); - if(parts.size()>0) + // split apart non-multipart POST + if(mystate->m_indata) { - // replace + with space before UriDecoding - parts[0]=StringFunctions::Replace(parts[0],"+"," "); - args[StringFunctions::UriDecode(parts[0])]; - if(parts.size()>1) + 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); + } + + 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[1]=StringFunctions::Replace(parts[1],"+"," "); - args[StringFunctions::UriDecode(parts[0])]=StringFunctions::UriDecode(parts[1]); + 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]); + } } } } @@ -153,3 +191,81 @@ const bool IPageHandler::Handle(shttpd_arg *arg) return false; } } + +void IPageHandler::HandleMultiPartData(const std::string &contenttypeheader, char *data, const long datalen, std::map &args) +{ + if(data) + { + std::string datastr(data,data+datalen); + std::vector parts; + std::string boundary=""; + std::string::size_type pos=contenttypeheader.find("boundary="); + + // find boundary + if(pos!=std::string::npos) + { + boundary=contenttypeheader.substr(pos+9); + // strip off any " and ; + boundary=StringFunctions::Replace(boundary,"\"",""); + boundary=StringFunctions::Replace(boundary,";",""); + } + + // split into parts separated by boundary + StringFunctions::Split(datastr,"--"+boundary+"\r\n",parts); + + // go through each part and get name=value + for(std::vector::iterator i=parts.begin(); i!=parts.end(); i++) + { + std::string data=""; + std::string name=""; + + // find name + pos=(*i).find("name="); + if(pos!=std::string::npos) + { + std::string::size_type pos2=(*i).find(";",pos); + if(pos2!=std::string::npos) + { + name=(*i).substr(pos+5,pos2-(pos+5)); + } + 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); + } + } + if(name!="" && data!="") + { + args[name]=data; + } + } + } +} + +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; +}