version 0.1.8
[fms.git] / src / http / ipagehandler.cpp
1 #include "../../include/http/ipagehandler.h"\r
2 #include "../../include/http/httpdefs.h"\r
3 #include "../../include/stringfunctions.h"\r
4 \r
5 #ifdef XMEM\r
6         #include <xmem.h>\r
7 #endif\r
8 \r
9 void IPageHandler::CreateArgArray(const std::map<std::string,std::string> &vars, const std::string &basename, std::vector<std::string> &args)\r
10 {\r
11         for(std::map<std::string,std::string>::const_iterator i=vars.begin(); i!=vars.end(); i++)\r
12         {\r
13                 if((*i).first.find(basename)==0 && (*i).first.find("[")!=std::string::npos && (*i).first.find("]")!=std::string::npos)\r
14                 {\r
15                         int index;\r
16                         std::string indexstr;\r
17                         std::string::size_type startpos;\r
18                         std::string::size_type endpos;\r
19                         startpos=(*i).first.find("[");\r
20                         endpos=(*i).first.find("]");\r
21 \r
22                         indexstr=(*i).first.substr(startpos+1,(endpos-startpos)-1);\r
23                         StringFunctions::Convert(indexstr,index);\r
24 \r
25                         while(args.size()<index+1)\r
26                         {\r
27                                 args.push_back("");\r
28                         }\r
29                         args[index]=(*i).second;\r
30                 }\r
31         }\r
32 }\r
33 \r
34 const bool IPageHandler::Handle(shttpd_arg *arg)\r
35 {\r
36         const char *uri=shttpd_get_env(arg,"REQUEST_URI");\r
37         const char *method=shttpd_get_env(arg,"REQUEST_METHOD");\r
38         std::string methodstr="";\r
39         if(method)\r
40         {\r
41                 methodstr=method;\r
42         }\r
43 \r
44         if(uri && WillHandleURI(std::string(uri)))\r
45         {\r
46                 httpstate *mystate=(httpstate *)arg->state;\r
47                 // this is a new request - create a new arg object\r
48                 if(arg->state==NULL)\r
49                 {\r
50                         arg->state=new httpstate;\r
51                         memset(arg->state,0,sizeof(httpstate));\r
52                         mystate=(httpstate *)arg->state;\r
53 \r
54                         // if post then create input buffer\r
55                         if(methodstr=="POST")\r
56                         {\r
57                                 const char *lenstr=shttpd_get_header(arg,"Content-Length");\r
58                                 if(lenstr)\r
59                                 {\r
60                                         long len;\r
61                                         StringFunctions::Convert(std::string(lenstr),len);\r
62                                         mystate->m_indata=new char[len+1];\r
63                                         mystate->m_indata[len]=NULL;\r
64                                         mystate->m_indatalen=len;\r
65                                         mystate->m_indatapos=0;\r
66                                 }\r
67                         }\r
68                 }\r
69 \r
70                 // we have more POST data to get\r
71                 if(arg->in.len>0)\r
72                 {\r
73                         int pos=0;\r
74                         while(pos<arg->in.len)\r
75                         {\r
76                                 mystate->m_indata[mystate->m_indatapos++]=arg->in.buf[pos++];\r
77                         }\r
78                         arg->in.num_bytes=arg->in.len;\r
79                 }\r
80 \r
81                 // we have all POST data (or it was 0 to begin with) - generate the page\r
82                 if(mystate->m_indatalen==mystate->m_indatapos && mystate->m_outdata==NULL)\r
83                 {\r
84                         //TODO parse POST data and any QUERY_STRING before generating page\r
85                         std::map<std::string,std::string> args;\r
86                         std::vector<std::string> argparts;\r
87                         \r
88                         if(mystate->m_indata)\r
89                         {\r
90                                 StringFunctions::Split(mystate->m_indata,"&",argparts);\r
91                         }\r
92                         if(shttpd_get_env(arg,"QUERY_STRING"))\r
93                         {\r
94                                 StringFunctions::Split(shttpd_get_env(arg,"QUERY_STRING"),"&",argparts);\r
95                         }\r
96                         for(std::vector<std::string>::iterator argi=argparts.begin(); argi!=argparts.end(); argi++)\r
97                         {\r
98                                 std::vector<std::string> parts;\r
99                                 StringFunctions::Split((*argi),"=",parts);\r
100                                 if(parts.size()>0)\r
101                                 {\r
102                                         // replace + with space before UriDecoding\r
103                                         parts[0]=StringFunctions::Replace(parts[0],"+"," ");\r
104                                         args[StringFunctions::UriDecode(parts[0])];\r
105                                         if(parts.size()>1)\r
106                                         {\r
107                                                 // replace + with space before UriDecoding\r
108                                                 parts[1]=StringFunctions::Replace(parts[1],"+"," ");\r
109                                                 args[StringFunctions::UriDecode(parts[0])]=StringFunctions::UriDecode(parts[1]);\r
110                                         }\r
111                                 }\r
112                         }\r
113 \r
114                         std::string page=GeneratePage(methodstr,args);\r
115                         mystate->m_outdata=new char[page.size()];\r
116                         memcpy(mystate->m_outdata,page.c_str(),page.size());\r
117                         mystate->m_outdatalen=page.size();\r
118                         mystate->m_outdatapos=0;\r
119                 }\r
120 \r
121                 // if we have output data, push next block of data onto out buffer\r
122                 if(mystate->m_outdata && mystate->m_outdatapos<mystate->m_outdatalen)\r
123                 {\r
124                         int pos=0;\r
125                         while(mystate->m_outdatapos<mystate->m_outdatalen && pos<arg->out.len)\r
126                         {\r
127                                 arg->out.buf[pos++]=mystate->m_outdata[mystate->m_outdatapos++];\r
128                         }\r
129                         arg->out.num_bytes=pos;\r
130                 }\r
131 \r
132                 // if we have no more output data to send - delete the data pointers and set end of output flag\r
133                 if(mystate->m_outdata && mystate->m_outdatapos==mystate->m_outdatalen)\r
134                 {\r
135                         if(mystate->m_indata)\r
136                         {\r
137                                 delete [] mystate->m_indata;\r
138                         }\r
139                         if(mystate->m_outdata)\r
140                         {\r
141                                 delete [] mystate->m_outdata;\r
142                         }\r
143                         delete mystate;\r
144                         arg->state=NULL;\r
145 \r
146                         arg->flags|=SHTTPD_END_OF_OUTPUT;\r
147                 }\r
148 \r
149                 return true;\r
150         }\r
151         else\r
152         {\r
153                 return false;\r
154         }\r
155 }\r