1 #include "../../include/http/ipagehandler.h"
\r
2 #include "../../include/http/httpdefs.h"
\r
3 #include "../../include/stringfunctions.h"
\r
11 void IPageHandler::CreateArgArray(const std::map<std::string,std::string> &vars, const std::string &basename, std::vector<std::string> &args)
\r
13 for(std::map<std::string,std::string>::const_iterator i=vars.begin(); i!=vars.end(); i++)
\r
15 if((*i).first.find(basename)==0 && (*i).first.find("[")!=std::string::npos && (*i).first.find("]")!=std::string::npos)
\r
18 std::string indexstr;
\r
19 std::string::size_type startpos;
\r
20 std::string::size_type endpos;
\r
21 startpos=(*i).first.find("[");
\r
22 endpos=(*i).first.find("]");
\r
24 indexstr=(*i).first.substr(startpos+1,(endpos-startpos)-1);
\r
25 StringFunctions::Convert(indexstr,index);
\r
27 while(args.size()<index+1)
\r
31 args[index]=(*i).second;
\r
36 const std::string IPageHandler::CreateTrueFalseDropDown(const std::string &name, const std::string &selected)
\r
38 std::string rval="";
\r
40 rval+="<select name=\""+name+"\">";
\r
41 rval+="<option value=\"true\"";
\r
42 if(selected=="true")
\r
46 rval+=">true</option>";
\r
47 rval+="<option value=\"false\"";
\r
48 if(selected=="false")
\r
52 rval+=">false</option>";
\r
58 const bool IPageHandler::Handle(shttpd_arg *arg)
\r
60 const char *uri=shttpd_get_env(arg,"REQUEST_URI");
\r
61 const char *method=shttpd_get_env(arg,"REQUEST_METHOD");
\r
62 std::string methodstr="";
\r
68 if(uri && WillHandleURI(std::string(uri)))
\r
70 httpstate *mystate=(httpstate *)arg->state;
\r
72 // first check if there was a connection error - if so delete the input/output and state buffers and return immediately
\r
73 if((arg->flags & SHTTPD_CONNECTION_ERROR)==SHTTPD_CONNECTION_ERROR)
\r
75 if(mystate && mystate->m_indata)
\r
77 delete mystate->m_indata;
\r
78 mystate->m_indata=NULL;
\r
80 if(mystate && mystate->m_outdata)
\r
82 delete mystate->m_outdata;
\r
83 mystate->m_outdata=NULL;
\r
93 // this is a new request - create a new arg object
\r
94 if(arg->state==NULL)
\r
96 arg->state=new httpstate;
\r
97 memset(arg->state,0,sizeof(httpstate));
\r
98 mystate=(httpstate *)arg->state;
\r
100 // if post then create input buffer
\r
101 if(methodstr=="POST")
\r
103 const char *lenstr=shttpd_get_header(arg,"Content-Length");
\r
107 StringFunctions::Convert(std::string(lenstr),len);
\r
108 mystate->m_indata=new char[len+1];
\r
109 mystate->m_indata[len]='\0';
\r
110 mystate->m_indatalen=len;
\r
111 mystate->m_indatapos=0;
\r
116 // we have more POST data to get
\r
120 while(pos<arg->in.len)
\r
122 mystate->m_indata[mystate->m_indatapos++]=arg->in.buf[pos++];
\r
124 arg->in.num_bytes=arg->in.len;
\r
127 // we have all POST data (or it was 0 to begin with) - generate the page
\r
128 if(mystate->m_indatalen==mystate->m_indatapos && mystate->m_outdata==NULL)
\r
130 //parse POST data and any QUERY_STRING before generating page
\r
131 std::map<std::string,std::string> args;
\r
132 std::vector<std::string> argparts;
\r
133 std::string contenttype="";
\r
135 if(shttpd_get_header(arg,"Content-Type"))
\r
137 contenttype=shttpd_get_header(arg,"Content-Type");
\r
140 if(contenttype.find("multipart/form-data")!=std::string::npos)
\r
142 HandleMultiPartData(contenttype,mystate->m_indata,mystate->m_indatalen,args);
\r
146 // split apart non-multipart POST
\r
147 if(mystate->m_indata)
\r
149 StringFunctions::Split(mystate->m_indata,"&",argparts);
\r
151 // split apart query string
\r
152 if(shttpd_get_env(arg,"QUERY_STRING"))
\r
154 StringFunctions::Split(shttpd_get_env(arg,"QUERY_STRING"),"&",argparts);
\r
157 for(std::vector<std::string>::iterator argi=argparts.begin(); argi!=argparts.end(); argi++)
\r
159 std::vector<std::string> parts;
\r
160 StringFunctions::Split((*argi),"=",parts);
\r
163 // replace + with space before UriDecoding
\r
164 parts[0]=StringFunctions::Replace(parts[0],"+"," ");
\r
165 args[StringFunctions::UriDecode(parts[0])];
\r
168 // replace + with space before UriDecoding
\r
169 parts[1]=StringFunctions::Replace(parts[1],"+"," ");
\r
170 args[StringFunctions::UriDecode(parts[0])]=StringFunctions::UriDecode(parts[1]);
\r
176 std::string page=GeneratePage(methodstr,args);
\r
177 mystate->m_outdata=new char[page.size()];
\r
178 memcpy(mystate->m_outdata,page.c_str(),page.size());
\r
179 mystate->m_outdatalen=page.size();
\r
180 mystate->m_outdatapos=0;
\r
183 // if we have output data, push next block of data onto out buffer
\r
184 if(mystate->m_outdata && mystate->m_outdatapos<mystate->m_outdatalen)
\r
187 while(mystate->m_outdatapos<mystate->m_outdatalen && pos<arg->out.len)
\r
189 arg->out.buf[pos++]=mystate->m_outdata[mystate->m_outdatapos++];
\r
191 arg->out.num_bytes=pos;
\r
194 // if we have no more output data to send - delete the data pointers and set end of output flag
\r
195 if(mystate->m_outdata && mystate->m_outdatapos==mystate->m_outdatalen)
\r
197 if(mystate->m_indata)
\r
199 delete [] mystate->m_indata;
\r
201 if(mystate->m_outdata)
\r
203 delete [] mystate->m_outdata;
\r
208 arg->flags|=SHTTPD_END_OF_OUTPUT;
\r
219 void IPageHandler::HandleMultiPartData(const std::string &contenttypeheader, char *data, const long datalen, std::map<std::string,std::string> &args)
\r
223 std::string datastr(data,data+datalen);
\r
224 std::vector<std::string> parts;
\r
225 std::string boundary="";
\r
226 std::string::size_type pos=contenttypeheader.find("boundary=");
\r
229 if(pos!=std::string::npos)
\r
231 boundary=contenttypeheader.substr(pos+9);
\r
232 // strip off any " and ;
\r
233 boundary=StringFunctions::Replace(boundary,"\"","");
\r
234 boundary=StringFunctions::Replace(boundary,";","");
\r
237 // split into parts separated by boundary
\r
238 StringFunctions::Split(datastr,"--"+boundary+"\r\n",parts);
\r
240 // go through each part and get name=value
\r
241 for(std::vector<std::string>::iterator i=parts.begin(); i!=parts.end(); i++)
\r
243 std::string data="";
\r
244 std::string name="";
\r
247 pos=(*i).find("name=");
\r
248 if(pos!=std::string::npos)
\r
250 std::string::size_type pos2=(*i).find(";",pos);
\r
251 if(pos2!=std::string::npos)
\r
253 name=(*i).substr(pos+5,pos2-(pos+5));
\r
257 pos2=(*i).find("\r\n",pos);
\r
258 if(pos2!=std::string::npos)
\r
260 name=(*i).substr(pos+5,pos2-(pos+5));
\r
264 name=StringFunctions::Replace(name,"\"","");
\r
267 // find header boundary
\r
268 pos=(*i).find("\r\n\r\n");
\r
269 if(pos!=std::string::npos)
\r
271 data=(*i).substr(pos+4);
\r
272 // strip off final \r\n from data
\r
273 if(data.size()>2 && data.rfind("\r\n")==data.size()-2)
\r
275 data.erase(data.size()-2);
\r
278 if(name!="" && data!="")
\r
286 const std::string IPageHandler::SanitizeOutput(const std::string &input)
\r
288 // must do & first because all other elements have & in them!
\r
289 std::string output=StringFunctions::Replace(input,"&","&");
\r
290 output=StringFunctions::Replace(output,"<","<");
\r
291 output=StringFunctions::Replace(output,">",">");
\r
292 output=StringFunctions::Replace(output,"\"",""");
\r
293 output=StringFunctions::Replace(output," "," ");
\r