author | Michael Krelin <hacker@klever.net> | 2020-10-07 22:52:19 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2020-10-07 22:52:19 (UTC) |
commit | c561689bf162fb22997bd88f4392f222f151c950 (patch) (unidiff) | |
tree | ce4656e92c379f7089f4bb72a4b10d781b61211e /src | |
parent | 3a4530372bc95d728dbddbac788f2c1f2d03a030 (diff) | |
download | kingate-master.zip kingate-master.tar.gz kingate-master.tar.bz2 |
-rw-r--r-- | src/cgi_gateway.cc | 1 | ||||
-rw-r--r-- | src/fastcgi.cc | 1 | ||||
-rw-r--r-- | src/plaincgi.cc | 1 | ||||
-rw-r--r-- | src/util.cc | 1 |
4 files changed, 4 insertions, 0 deletions
diff --git a/src/cgi_gateway.cc b/src/cgi_gateway.cc index a2681aa..3763654 100644 --- a/src/cgi_gateway.cc +++ b/src/cgi_gateway.cc | |||
@@ -1,352 +1,353 @@ | |||
1 | #include <errno.h> | 1 | #include <errno.h> |
2 | #include <ctype.h> | 2 | #include <ctype.h> |
3 | #include <sstream> | 3 | #include <sstream> |
4 | #include <cstring> | ||
4 | #include "kingate/cgi_gateway.h" | 5 | #include "kingate/cgi_gateway.h" |
5 | #include "kingate/util.h" | 6 | #include "kingate/util.h" |
6 | #include "kingate/exception.h" | 7 | #include "kingate/exception.h" |
7 | #include "config.h" | 8 | #include "config.h" |
8 | #ifdef HAVE_MIMETIC | 9 | #ifdef HAVE_MIMETIC |
9 | # include <mimetic/mimeentity.h> | 10 | # include <mimetic/mimeentity.h> |
10 | # include <mimetic/parser/itparser.h> | 11 | # include <mimetic/parser/itparser.h> |
11 | #endif /* HAVE_MIMETIC */ | 12 | #endif /* HAVE_MIMETIC */ |
12 | 13 | ||
13 | namespace kingate { | 14 | namespace kingate { |
14 | 15 | ||
15 | #ifdef HAVE_MIMETIC | 16 | #ifdef HAVE_MIMETIC |
16 | using mimetic::MimeEntity; | 17 | using mimetic::MimeEntity; |
17 | 18 | ||
18 | struct TornMimeEntity : public MimeEntity { | 19 | struct TornMimeEntity : public MimeEntity { |
19 | typedef istreambuf_iterator<char> it_type; | 20 | typedef istreambuf_iterator<char> it_type; |
20 | typedef it_type::iterator_category it_cat; | 21 | typedef it_type::iterator_category it_cat; |
21 | struct IParser : public mimetic::IteratorParser<it_type,it_cat> { | 22 | struct IParser : public mimetic::IteratorParser<it_type,it_cat> { |
22 | typedef mimetic::IteratorParser<it_type,it_cat> BT; | 23 | typedef mimetic::IteratorParser<it_type,it_cat> BT; |
23 | IParser(MimeEntity& me) | 24 | IParser(MimeEntity& me) |
24 | : BT::IteratorParser<it_type,it_cat>(me) { } | 25 | : BT::IteratorParser<it_type,it_cat>(me) { } |
25 | void loadHeader(it_type bit,it_type eit) { | 26 | void loadHeader(it_type bit,it_type eit) { |
26 | m_bit = bit; m_eit = eit; | 27 | m_bit = bit; m_eit = eit; |
27 | BT::loadHeader(); | 28 | BT::loadHeader(); |
28 | } | 29 | } |
29 | void loadBody(it_type bit,it_type eit) { | 30 | void loadBody(it_type bit,it_type eit) { |
30 | m_bit = bit; m_eit = eit; | 31 | m_bit = bit; m_eit = eit; |
31 | BT::loadBody(); | 32 | BT::loadBody(); |
32 | } | 33 | } |
33 | }; | 34 | }; |
34 | void load(istream& hs,istream& bs,int mask=0) { | 35 | void load(istream& hs,istream& bs,int mask=0) { |
35 | IParser prs(*this); | 36 | IParser prs(*this); |
36 | prs.iMask(mask); | 37 | prs.iMask(mask); |
37 | prs.loadHeader(it_type(hs),it_type()); | 38 | prs.loadHeader(it_type(hs),it_type()); |
38 | prs.loadBody(it_type(bs),it_type()); | 39 | prs.loadBody(it_type(bs),it_type()); |
39 | } | 40 | } |
40 | }; | 41 | }; |
41 | #endif /* HAVE_MIMETIC */ | 42 | #endif /* HAVE_MIMETIC */ |
42 | 43 | ||
43 | static string empty_string; | 44 | static string empty_string; |
44 | 45 | ||
45 | cgi_gateway::basic_file_t::~basic_file_t() { } | 46 | cgi_gateway::basic_file_t::~basic_file_t() { } |
46 | 47 | ||
47 | class string_file_t : public cgi_gateway::basic_file_t { | 48 | class string_file_t : public cgi_gateway::basic_file_t { |
48 | public: | 49 | public: |
49 | string _file_name; | 50 | string _file_name; |
50 | string _content_type; | 51 | string _content_type; |
51 | stringstream _content; | 52 | stringstream _content; |
52 | 53 | ||
53 | string_file_t(const string& fn,const string& ct,const string& s) | 54 | string_file_t(const string& fn,const string& ct,const string& s) |
54 | : _file_name(fn), _content_type(ct), _content(s,ios::in) { } | 55 | : _file_name(fn), _content_type(ct), _content(s,ios::in) { } |
55 | const string& filename() const { return _file_name; } | 56 | const string& filename() const { return _file_name; } |
56 | const string& content_type() const { return _content_type; } | 57 | const string& content_type() const { return _content_type; } |
57 | istream& content() { return _content; } | 58 | istream& content() { return _content; } |
58 | }; | 59 | }; |
59 | 60 | ||
60 | cgi_gateway::cgi_gateway(cgi_interface& ci,bool parsebody) | 61 | cgi_gateway::cgi_gateway(cgi_interface& ci,bool parsebody) |
61 | : iface(ci), b_parsed_content(false) { | 62 | : iface(ci), b_parsed_content(false) { |
62 | // Fetch GET content | 63 | // Fetch GET content |
63 | try { | 64 | try { |
64 | string qs = get_meta("QUERY_STRING"); | 65 | string qs = get_meta("QUERY_STRING"); |
65 | parse_query(qs,get); | 66 | parse_query(qs,get); |
66 | }catch(exception_notfound& enf) { } | 67 | }catch(exception_notfound& enf) { } |
67 | if(parsebody) | 68 | if(parsebody) |
68 | parse_request_body(); | 69 | parse_request_body(); |
69 | // Parse cookies | 70 | // Parse cookies |
70 | try { | 71 | try { |
71 | cookies.parse_cookies(get_meta("HTTP_COOKIE")); | 72 | cookies.parse_cookies(get_meta("HTTP_COOKIE")); |
72 | }catch(exception_notfound& enf) { } | 73 | }catch(exception_notfound& enf) { } |
73 | } | 74 | } |
74 | 75 | ||
75 | cgi_gateway::~cgi_gateway() throw() { | 76 | cgi_gateway::~cgi_gateway() throw() { |
76 | for(files_t::iterator i=files.begin();i!=files.end();++i) | 77 | for(files_t::iterator i=files.begin();i!=files.end();++i) |
77 | delete i->second; | 78 | delete i->second; |
78 | files.clear(); | 79 | files.clear(); |
79 | } | 80 | } |
80 | 81 | ||
81 | void cgi_gateway::parse_request_body() { | 82 | void cgi_gateway::parse_request_body() { |
82 | if(b_parsed_content) | 83 | if(b_parsed_content) |
83 | throw konforka::exception(CODEPOINT,"request body is already parsed"); | 84 | throw konforka::exception(CODEPOINT,"request body is already parsed"); |
84 | // Fetch POST content | 85 | // Fetch POST content |
85 | if(!strncasecmp( | 86 | if(!strncasecmp( |
86 | content_type().c_str(), | 87 | content_type().c_str(), |
87 | "application/x-www-form-urlencoded", | 88 | "application/x-www-form-urlencoded", |
88 | sizeof("application/x-www-form-urlencoded")-1) ) { | 89 | sizeof("application/x-www-form-urlencoded")-1) ) { |
89 | unsigned long cl = content_length(); | 90 | unsigned long cl = content_length(); |
90 | if(cl) { | 91 | if(cl) { |
91 | char * tmp = new char[cl]; | 92 | char * tmp = new char[cl]; |
92 | iface.in().read(tmp,cl); | 93 | iface.in().read(tmp,cl); |
93 | string qs(tmp,cl); | 94 | string qs(tmp,cl); |
94 | delete tmp; | 95 | delete tmp; |
95 | parse_query(qs,post); | 96 | parse_query(qs,post); |
96 | } | 97 | } |
97 | b_parsed_content = true; | 98 | b_parsed_content = true; |
98 | } | 99 | } |
99 | #ifdef HAVE_MIMETIC | 100 | #ifdef HAVE_MIMETIC |
100 | else if(!strncasecmp( | 101 | else if(!strncasecmp( |
101 | content_type().c_str(), | 102 | content_type().c_str(), |
102 | "multipart/form-data", | 103 | "multipart/form-data", |
103 | sizeof("multipart/form-data")-1) ) { | 104 | sizeof("multipart/form-data")-1) ) { |
104 | stringstream h; | 105 | stringstream h; |
105 | h | 106 | h |
106 | << "Content-Type: " << content_type() << "\r\n" | 107 | << "Content-Type: " << content_type() << "\r\n" |
107 | << "Content-Length: " << content_length() << "\r\n\n"; | 108 | << "Content-Length: " << content_length() << "\r\n\n"; |
108 | TornMimeEntity me; | 109 | TornMimeEntity me; |
109 | me.load(h,iface.in(),0); | 110 | me.load(h,iface.in(),0); |
110 | mimetic::MimeEntityList& parts = me.body().parts(); | 111 | mimetic::MimeEntityList& parts = me.body().parts(); |
111 | for(mimetic::MimeEntityList::iterator i=parts.begin();i!=parts.end();++i) { | 112 | for(mimetic::MimeEntityList::iterator i=parts.begin();i!=parts.end();++i) { |
112 | MimeEntity *p = *i; | 113 | MimeEntity *p = *i; |
113 | const mimetic::ContentDisposition& cd = p->header().contentDisposition(); | 114 | const mimetic::ContentDisposition& cd = p->header().contentDisposition(); |
114 | string n = cd.param("name"); | 115 | string n = cd.param("name"); |
115 | string fn = cd.param("filename"); | 116 | string fn = cd.param("filename"); |
116 | if(fn.empty()) { | 117 | if(fn.empty()) { |
117 | post.insert(params_t::value_type(n,p->body())); | 118 | post.insert(params_t::value_type(n,p->body())); |
118 | }else{ | 119 | }else{ |
119 | const mimetic::ContentType& ct = p->header().contentType(); | 120 | const mimetic::ContentType& ct = p->header().contentType(); |
120 | files.insert(files_t::value_type(n,new string_file_t(fn,ct.str(),p->body()))); | 121 | files.insert(files_t::value_type(n,new string_file_t(fn,ct.str(),p->body()))); |
121 | } | 122 | } |
122 | } | 123 | } |
123 | b_parsed_content = true; | 124 | b_parsed_content = true; |
124 | } | 125 | } |
125 | #endif /* HAVE_MIMETIC */ | 126 | #endif /* HAVE_MIMETIC */ |
126 | } | 127 | } |
127 | 128 | ||
128 | bool cgi_gateway::has_GET(const string& n) const { | 129 | bool cgi_gateway::has_GET(const string& n) const { |
129 | return get.find(n) != get.end(); | 130 | return get.find(n) != get.end(); |
130 | } | 131 | } |
131 | const string& cgi_gateway::get_GET(const string& n) const { | 132 | const string& cgi_gateway::get_GET(const string& n) const { |
132 | params_t::const_iterator i = get.find(n); | 133 | params_t::const_iterator i = get.find(n); |
133 | if(i==get.end()) | 134 | if(i==get.end()) |
134 | throw exception_notfound(CODEPOINT,"no such parameter"); | 135 | throw exception_notfound(CODEPOINT,"no such parameter"); |
135 | return i->second; | 136 | return i->second; |
136 | } | 137 | } |
137 | bool cgi_gateway::has_POST(const string& n) const { | 138 | bool cgi_gateway::has_POST(const string& n) const { |
138 | return post.find(n) != post.end(); | 139 | return post.find(n) != post.end(); |
139 | } | 140 | } |
140 | const string& cgi_gateway::get_POST(const string& n) const { | 141 | const string& cgi_gateway::get_POST(const string& n) const { |
141 | params_t::const_iterator i = post.find(n); | 142 | params_t::const_iterator i = post.find(n); |
142 | if(i==post.end()) | 143 | if(i==post.end()) |
143 | throw exception_notfound(CODEPOINT,"no such parameter"); | 144 | throw exception_notfound(CODEPOINT,"no such parameter"); |
144 | return i->second; | 145 | return i->second; |
145 | } | 146 | } |
146 | bool cgi_gateway::has_param(const string& n) const { | 147 | bool cgi_gateway::has_param(const string& n) const { |
147 | return has_GET(n) || has_POST(n); | 148 | return has_GET(n) || has_POST(n); |
148 | } | 149 | } |
149 | const string& cgi_gateway::get_param(const string& n) const { | 150 | const string& cgi_gateway::get_param(const string& n) const { |
150 | params_t::const_iterator i = get.find(n); | 151 | params_t::const_iterator i = get.find(n); |
151 | if(i!=get.end()) | 152 | if(i!=get.end()) |
152 | return i->second; | 153 | return i->second; |
153 | i = post.find(n); | 154 | i = post.find(n); |
154 | if(i!=post.end()) | 155 | if(i!=post.end()) |
155 | return i->second; | 156 | return i->second; |
156 | throw exception_notfound(CODEPOINT,"no such parameter"); | 157 | throw exception_notfound(CODEPOINT,"no such parameter"); |
157 | } | 158 | } |
158 | bool cgi_gateway::has_file(const string& n) const { | 159 | bool cgi_gateway::has_file(const string& n) const { |
159 | return files.find(n) != files.end(); | 160 | return files.find(n) != files.end(); |
160 | } | 161 | } |
161 | const cgi_gateway::file_t cgi_gateway::get_file(const string& n) const { | 162 | const cgi_gateway::file_t cgi_gateway::get_file(const string& n) const { |
162 | files_t::const_iterator i = files.find(n); | 163 | files_t::const_iterator i = files.find(n); |
163 | if(i==files.end()) | 164 | if(i==files.end()) |
164 | throw exception_notfound(CODEPOINT,"no such parameter"); | 165 | throw exception_notfound(CODEPOINT,"no such parameter"); |
165 | return i->second; | 166 | return i->second; |
166 | } | 167 | } |
167 | cgi_gateway::file_t cgi_gateway::get_file(const string& n) { | 168 | cgi_gateway::file_t cgi_gateway::get_file(const string& n) { |
168 | files_t::const_iterator i = files.find(n); | 169 | files_t::const_iterator i = files.find(n); |
169 | if(i==files.end()) | 170 | if(i==files.end()) |
170 | throw exception_notfound(CODEPOINT,"no such parameter"); | 171 | throw exception_notfound(CODEPOINT,"no such parameter"); |
171 | return i->second; | 172 | return i->second; |
172 | } | 173 | } |
173 | 174 | ||
174 | /* | 175 | /* |
175 | * deprecated stuff. | 176 | * deprecated stuff. |
176 | */ | 177 | */ |
177 | const string& cgi_gateway::get_content_type() const { | 178 | const string& cgi_gateway::get_content_type() const { |
178 | if(!has_meta("CONTENT_TYPE")) | 179 | if(!has_meta("CONTENT_TYPE")) |
179 | return empty_string; | 180 | return empty_string; |
180 | return get_meta("CONTENT_TYPE"); | 181 | return get_meta("CONTENT_TYPE"); |
181 | } | 182 | } |
182 | unsigned long cgi_gateway::get_content_length() const { | 183 | unsigned long cgi_gateway::get_content_length() const { |
183 | if(!has_meta("CONTENT_LENGTH")) | 184 | if(!has_meta("CONTENT_LENGTH")) |
184 | return 0; | 185 | return 0; |
185 | string cl = get_meta("CONTENT_LENGTH"); | 186 | string cl = get_meta("CONTENT_LENGTH"); |
186 | return strtol(cl.c_str(),NULL,10); | 187 | return strtol(cl.c_str(),NULL,10); |
187 | } | 188 | } |
188 | /* | 189 | /* |
189 | * | 190 | * |
190 | */ | 191 | */ |
191 | 192 | ||
192 | const string& cgi_gateway::http_request_header(const string& hn) const { | 193 | const string& cgi_gateway::http_request_header(const string& hn) const { |
193 | string mvn = "HTTP_"; | 194 | string mvn = "HTTP_"; |
194 | for(const char* p=hn.c_str();*p;p++) { | 195 | for(const char* p=hn.c_str();*p;p++) { |
195 | if(*p=='-') | 196 | if(*p=='-') |
196 | mvn += '_'; | 197 | mvn += '_'; |
197 | else | 198 | else |
198 | mvn += toupper(*p); | 199 | mvn += toupper(*p); |
199 | } | 200 | } |
200 | return get_meta(mvn); | 201 | return get_meta(mvn); |
201 | } | 202 | } |
202 | 203 | ||
203 | const string& cgi_gateway::auth_type() const { | 204 | const string& cgi_gateway::auth_type() const { |
204 | try { | 205 | try { |
205 | return get_meta("AUTH_TYPE"); | 206 | return get_meta("AUTH_TYPE"); |
206 | }catch(exception_notfound& enf) { | 207 | }catch(exception_notfound& enf) { |
207 | return empty_string; | 208 | return empty_string; |
208 | } | 209 | } |
209 | } | 210 | } |
210 | unsigned long cgi_gateway::content_length() const { | 211 | unsigned long cgi_gateway::content_length() const { |
211 | try { | 212 | try { |
212 | const string& cl = get_meta("CONTENT_LENGTH"); | 213 | const string& cl = get_meta("CONTENT_LENGTH"); |
213 | errno = 0; | 214 | errno = 0; |
214 | const char *clp = cl.c_str(); | 215 | const char *clp = cl.c_str(); |
215 | unsigned long rv = strtol(clp,(char**)&clp,10); | 216 | unsigned long rv = strtol(clp,(char**)&clp,10); |
216 | if(errno || *clp) | 217 | if(errno || *clp) |
217 | throw server_error(CODEPOINT,"Invalid CONTENT_LENGTH value passed from server"); | 218 | throw server_error(CODEPOINT,"Invalid CONTENT_LENGTH value passed from server"); |
218 | return rv; | 219 | return rv; |
219 | }catch(exception_notfound& enf) { | 220 | }catch(exception_notfound& enf) { |
220 | return 0; | 221 | return 0; |
221 | } | 222 | } |
222 | } | 223 | } |
223 | const string& cgi_gateway::content_type() const { | 224 | const string& cgi_gateway::content_type() const { |
224 | try { | 225 | try { |
225 | return get_meta("CONTENT_TYPE"); | 226 | return get_meta("CONTENT_TYPE"); |
226 | }catch(exception_notfound& enf) { | 227 | }catch(exception_notfound& enf) { |
227 | return empty_string; | 228 | return empty_string; |
228 | } | 229 | } |
229 | } | 230 | } |
230 | const string& cgi_gateway::gateway_interface() const { | 231 | const string& cgi_gateway::gateway_interface() const { |
231 | try { | 232 | try { |
232 | return get_meta("GATEWAY_INTERFACE"); | 233 | return get_meta("GATEWAY_INTERFACE"); |
233 | }catch(exception_notfound& enf) { | 234 | }catch(exception_notfound& enf) { |
234 | return empty_string; | 235 | return empty_string; |
235 | } | 236 | } |
236 | } | 237 | } |
237 | const string& cgi_gateway::path_info() const { | 238 | const string& cgi_gateway::path_info() const { |
238 | try { | 239 | try { |
239 | return get_meta("PATH_INFO"); | 240 | return get_meta("PATH_INFO"); |
240 | }catch(exception_notfound& enf) { | 241 | }catch(exception_notfound& enf) { |
241 | return empty_string; | 242 | return empty_string; |
242 | } | 243 | } |
243 | } | 244 | } |
244 | const string& cgi_gateway::path_translated() const { | 245 | const string& cgi_gateway::path_translated() const { |
245 | try { | 246 | try { |
246 | return get_meta("PATH_TRANSLATED"); | 247 | return get_meta("PATH_TRANSLATED"); |
247 | }catch(exception_notfound& enf) { | 248 | }catch(exception_notfound& enf) { |
248 | return empty_string; | 249 | return empty_string; |
249 | } | 250 | } |
250 | } | 251 | } |
251 | const string& cgi_gateway::query_string() const { | 252 | const string& cgi_gateway::query_string() const { |
252 | try { | 253 | try { |
253 | return get_meta("QUERY_STRING"); | 254 | return get_meta("QUERY_STRING"); |
254 | }catch(exception_notfound& enf) { | 255 | }catch(exception_notfound& enf) { |
255 | return empty_string; | 256 | return empty_string; |
256 | } | 257 | } |
257 | } | 258 | } |
258 | const string& cgi_gateway::remote_addr() const { | 259 | const string& cgi_gateway::remote_addr() const { |
259 | try { | 260 | try { |
260 | return get_meta("REMOTE_ADDR"); | 261 | return get_meta("REMOTE_ADDR"); |
261 | }catch(exception_notfound& enf) { | 262 | }catch(exception_notfound& enf) { |
262 | return empty_string; | 263 | return empty_string; |
263 | } | 264 | } |
264 | } | 265 | } |
265 | const string& cgi_gateway::remote_host() const { | 266 | const string& cgi_gateway::remote_host() const { |
266 | try { | 267 | try { |
267 | return get_meta("REMOTE_HOST"); | 268 | return get_meta("REMOTE_HOST"); |
268 | }catch(exception_notfound& enf) { | 269 | }catch(exception_notfound& enf) { |
269 | return remote_addr(); | 270 | return remote_addr(); |
270 | } | 271 | } |
271 | } | 272 | } |
272 | const string& cgi_gateway::remote_ident() const { | 273 | const string& cgi_gateway::remote_ident() const { |
273 | try { | 274 | try { |
274 | return get_meta("REMOTE_IDENT"); | 275 | return get_meta("REMOTE_IDENT"); |
275 | }catch(exception_notfound& enf) { | 276 | }catch(exception_notfound& enf) { |
276 | return empty_string; | 277 | return empty_string; |
277 | } | 278 | } |
278 | } | 279 | } |
279 | const string& cgi_gateway::remote_user() const { | 280 | const string& cgi_gateway::remote_user() const { |
280 | try { | 281 | try { |
281 | return get_meta("REMOTE_USER"); | 282 | return get_meta("REMOTE_USER"); |
282 | }catch(exception_notfound& enf) { | 283 | }catch(exception_notfound& enf) { |
283 | return empty_string; | 284 | return empty_string; |
284 | } | 285 | } |
285 | } | 286 | } |
286 | const string& cgi_gateway::request_method() const { | 287 | const string& cgi_gateway::request_method() const { |
287 | try { | 288 | try { |
288 | return get_meta("REQUEST_METHOD"); | 289 | return get_meta("REQUEST_METHOD"); |
289 | }catch(exception_notfound& enf) { | 290 | }catch(exception_notfound& enf) { |
290 | throw server_error(CODEPOINT,"No REQUEST_METHOD passed from server"); | 291 | throw server_error(CODEPOINT,"No REQUEST_METHOD passed from server"); |
291 | } | 292 | } |
292 | } | 293 | } |
293 | const string& cgi_gateway::script_name() const { | 294 | const string& cgi_gateway::script_name() const { |
294 | try { | 295 | try { |
295 | return get_meta("SCRIPT_NAME"); | 296 | return get_meta("SCRIPT_NAME"); |
296 | }catch(exception_notfound& enf) { | 297 | }catch(exception_notfound& enf) { |
297 | throw server_error(CODEPOINT,"No SCRIPT_NAME passed from server"); | 298 | throw server_error(CODEPOINT,"No SCRIPT_NAME passed from server"); |
298 | } | 299 | } |
299 | } | 300 | } |
300 | const string& cgi_gateway::server_name() const { | 301 | const string& cgi_gateway::server_name() const { |
301 | try { | 302 | try { |
302 | return get_meta("SERVER_NAME"); | 303 | return get_meta("SERVER_NAME"); |
303 | }catch(exception_notfound& enf) { | 304 | }catch(exception_notfound& enf) { |
304 | throw server_error(CODEPOINT,"No SERVER_NAME passed from server"); | 305 | throw server_error(CODEPOINT,"No SERVER_NAME passed from server"); |
305 | } | 306 | } |
306 | } | 307 | } |
307 | unsigned int cgi_gateway::server_port() const { | 308 | unsigned int cgi_gateway::server_port() const { |
308 | try { | 309 | try { |
309 | const string& sp = get_meta("SERVER_PORT"); | 310 | const string& sp = get_meta("SERVER_PORT"); |
310 | errno = 0; | 311 | errno = 0; |
311 | const char *spp = sp.c_str(); | 312 | const char *spp = sp.c_str(); |
312 | unsigned int rv = strtol(spp,(char**)&spp,10); | 313 | unsigned int rv = strtol(spp,(char**)&spp,10); |
313 | if(errno || *spp) | 314 | if(errno || *spp) |
314 | throw server_error(CODEPOINT,"Invalid SERVER_PORT value passed from server"); | 315 | throw server_error(CODEPOINT,"Invalid SERVER_PORT value passed from server"); |
315 | return rv; | 316 | return rv; |
316 | }catch(exception_notfound& enf) { | 317 | }catch(exception_notfound& enf) { |
317 | throw server_error(CODEPOINT,"No SERVER_PORT passed from server"); | 318 | throw server_error(CODEPOINT,"No SERVER_PORT passed from server"); |
318 | } | 319 | } |
319 | } | 320 | } |
320 | const string& cgi_gateway::server_protocol() const { | 321 | const string& cgi_gateway::server_protocol() const { |
321 | try { | 322 | try { |
322 | return get_meta("SERVER_PROTOCOL"); | 323 | return get_meta("SERVER_PROTOCOL"); |
323 | }catch(exception_notfound& enf) { | 324 | }catch(exception_notfound& enf) { |
324 | throw server_error(CODEPOINT,"No SERVER_PROTOCOL passed from server"); | 325 | throw server_error(CODEPOINT,"No SERVER_PROTOCOL passed from server"); |
325 | } | 326 | } |
326 | } | 327 | } |
327 | const string& cgi_gateway::server_software() const { | 328 | const string& cgi_gateway::server_software() const { |
328 | try { | 329 | try { |
329 | return get_meta("SERVER_SOFTWARE"); | 330 | return get_meta("SERVER_SOFTWARE"); |
330 | }catch(exception_notfound& enf) { | 331 | }catch(exception_notfound& enf) { |
331 | throw server_error(CODEPOINT,"No SERVER_SOFTWARE passed from server"); | 332 | throw server_error(CODEPOINT,"No SERVER_SOFTWARE passed from server"); |
332 | } | 333 | } |
333 | } | 334 | } |
334 | 335 | ||
335 | void cgi_gateway::parse_query(string& q,params_t& p) { | 336 | void cgi_gateway::parse_query(string& q,params_t& p) { |
336 | while(!q.empty()) { | 337 | while(!q.empty()) { |
337 | string::size_type amp = q.find('&'); | 338 | string::size_type amp = q.find('&'); |
338 | string pp = (amp==string::npos)?q:q.substr(0,amp); | 339 | string pp = (amp==string::npos)?q:q.substr(0,amp); |
339 | if(amp==string::npos) | 340 | if(amp==string::npos) |
340 | q.clear(); | 341 | q.clear(); |
341 | else | 342 | else |
342 | q.erase(0,amp+1); | 343 | q.erase(0,amp+1); |
343 | string::size_type eq = pp.find('='); | 344 | string::size_type eq = pp.find('='); |
344 | if(eq == string::npos) { | 345 | if(eq == string::npos) { |
345 | p.insert(params_t::value_type("",url_decode(pp))); | 346 | p.insert(params_t::value_type("",url_decode(pp))); |
346 | }else{ | 347 | }else{ |
347 | p.insert(params_t::value_type(url_decode(pp.substr(0,eq)),url_decode(pp.substr(eq+1)))); | 348 | p.insert(params_t::value_type(url_decode(pp.substr(0,eq)),url_decode(pp.substr(eq+1)))); |
348 | } | 349 | } |
349 | } | 350 | } |
350 | } | 351 | } |
351 | 352 | ||
352 | } | 353 | } |
diff --git a/src/fastcgi.cc b/src/fastcgi.cc index 8b7668c..5a6c081 100644 --- a/src/fastcgi.cc +++ b/src/fastcgi.cc | |||
@@ -1,69 +1,70 @@ | |||
1 | #include <unistd.h> | 1 | #include <unistd.h> |
2 | #include <sys/types.h> | 2 | #include <sys/types.h> |
3 | #include <sys/stat.h> | 3 | #include <sys/stat.h> |
4 | #include <cstring> | ||
4 | #include "kingate/fastcgi.h" | 5 | #include "kingate/fastcgi.h" |
5 | #include "kingate/exception.h" | 6 | #include "kingate/exception.h" |
6 | 7 | ||
7 | namespace kingate { | 8 | namespace kingate { |
8 | 9 | ||
9 | bool fcgi_socket::_initialized = false; | 10 | bool fcgi_socket::_initialized = false; |
10 | 11 | ||
11 | fcgi_socket::fcgi_socket(const char *s,int bl) | 12 | fcgi_socket::fcgi_socket(const char *s,int bl) |
12 | : sock(-1) { | 13 | : sock(-1) { |
13 | if(!_initialized) { | 14 | if(!_initialized) { |
14 | if( FCGX_Init() ) | 15 | if( FCGX_Init() ) |
15 | throw exception(CODEPOINT,"failed to FCGX_Init()"); | 16 | throw exception(CODEPOINT,"failed to FCGX_Init()"); |
16 | _initialized = true; | 17 | _initialized = true; |
17 | } | 18 | } |
18 | sock = FCGX_OpenSocket(s,bl); | 19 | sock = FCGX_OpenSocket(s,bl); |
19 | if(sock<0) | 20 | if(sock<0) |
20 | throw exception(CODEPOINT,"failed to FCGX_OpenSocket("); | 21 | throw exception(CODEPOINT,"failed to FCGX_OpenSocket("); |
21 | // TODO: check if there is a ':', not if it starts with ':' | 22 | // TODO: check if there is a ':', not if it starts with ':' |
22 | if(*s != ':') | 23 | if(*s != ':') |
23 | if(chmod(s,0777)) // XXX: configurable. | 24 | if(chmod(s,0777)) // XXX: configurable. |
24 | throw exception(CODEPOINT,"failed to chmod()"); | 25 | throw exception(CODEPOINT,"failed to chmod()"); |
25 | } | 26 | } |
26 | fcgi_socket::fcgi_socket(int s) | 27 | fcgi_socket::fcgi_socket(int s) |
27 | : sock(0) { | 28 | : sock(0) { |
28 | if(!_initialized) { | 29 | if(!_initialized) { |
29 | if( FCGX_Init() ) | 30 | if( FCGX_Init() ) |
30 | throw exception(CODEPOINT,"failed to FCGX_Init()"); | 31 | throw exception(CODEPOINT,"failed to FCGX_Init()"); |
31 | _initialized = true; | 32 | _initialized = true; |
32 | } | 33 | } |
33 | } | 34 | } |
34 | fcgi_socket::~fcgi_socket() { | 35 | fcgi_socket::~fcgi_socket() { |
35 | if(sock>=0) | 36 | if(sock>=0) |
36 | close(sock); | 37 | close(sock); |
37 | } | 38 | } |
38 | 39 | ||
39 | fcgi_interface::fcgi_interface(fcgi_socket& s,int f) | 40 | fcgi_interface::fcgi_interface(fcgi_socket& s,int f) |
40 | : sbin(buf_sbin,sizeof(buf_sbin)), | 41 | : sbin(buf_sbin,sizeof(buf_sbin)), |
41 | sbout(buf_sbout,sizeof(buf_sbout)), | 42 | sbout(buf_sbout,sizeof(buf_sbout)), |
42 | sberr(buf_sberr,sizeof(buf_sberr)), | 43 | sberr(buf_sberr,sizeof(buf_sberr)), |
43 | sin(&sbin), sout(&sbout), serr(&sberr) { | 44 | sin(&sbin), sout(&sbout), serr(&sberr) { |
44 | if( FCGX_InitRequest(&request,s.sock,f) ) | 45 | if( FCGX_InitRequest(&request,s.sock,f) ) |
45 | throw exception(CODEPOINT,"failed to FCGX_InitRequest()"); | 46 | throw exception(CODEPOINT,"failed to FCGX_InitRequest()"); |
46 | if( FCGX_Accept_r(&request) ) | 47 | if( FCGX_Accept_r(&request) ) |
47 | throw exception(CODEPOINT,"failed to FCGX_Accept_r()"); | 48 | throw exception(CODEPOINT,"failed to FCGX_Accept_r()"); |
48 | sbin.attach(request.in); | 49 | sbin.attach(request.in); |
49 | sbout.attach(request.out); | 50 | sbout.attach(request.out); |
50 | sberr.attach(request.err); | 51 | sberr.attach(request.err); |
51 | for(char **p = request.envp; *p; p++) { | 52 | for(char **p = request.envp; *p; p++) { |
52 | const char *e = strchr(*p,'='); | 53 | const char *e = strchr(*p,'='); |
53 | if(!e){ | 54 | if(!e){ |
54 | // XXX: check if we have it already? | 55 | // XXX: check if we have it already? |
55 | metavars[*p] = string(0); | 56 | metavars[*p] = string(0); |
56 | }else{ | 57 | }else{ |
57 | int l = e-*p; e++; | 58 | int l = e-*p; e++; |
58 | // XXX: check if we have it already? | 59 | // XXX: check if we have it already? |
59 | metavars[string(*p,l)]=e; | 60 | metavars[string(*p,l)]=e; |
60 | } | 61 | } |
61 | } | 62 | } |
62 | } | 63 | } |
63 | fcgi_interface::~fcgi_interface() { | 64 | fcgi_interface::~fcgi_interface() { |
64 | sout.flush(); | 65 | sout.flush(); |
65 | serr.flush(); | 66 | serr.flush(); |
66 | FCGX_Finish_r(&request); | 67 | FCGX_Finish_r(&request); |
67 | } | 68 | } |
68 | 69 | ||
69 | } | 70 | } |
diff --git a/src/plaincgi.cc b/src/plaincgi.cc index 1cb7dc6..3a82d33 100644 --- a/src/plaincgi.cc +++ b/src/plaincgi.cc | |||
@@ -1,32 +1,33 @@ | |||
1 | #include <unistd.h> | 1 | #include <unistd.h> |
2 | #include <sys/types.h> | 2 | #include <sys/types.h> |
3 | #include <sys/stat.h> | 3 | #include <sys/stat.h> |
4 | #include <cstring> | ||
4 | #include "kingate/plaincgi.h" | 5 | #include "kingate/plaincgi.h" |
5 | #include "kingate/exception.h" | 6 | #include "kingate/exception.h" |
6 | #include "config.h" | 7 | #include "config.h" |
7 | 8 | ||
8 | #if !HAVE_DECL_ENVIRON | 9 | #if !HAVE_DECL_ENVIRON |
9 | extern char **environ; | 10 | extern char **environ; |
10 | #endif /* HAVE_DECL_ENVIRON */ | 11 | #endif /* HAVE_DECL_ENVIRON */ |
11 | 12 | ||
12 | namespace kingate { | 13 | namespace kingate { |
13 | 14 | ||
14 | plaincgi_interface::plaincgi_interface() { | 15 | plaincgi_interface::plaincgi_interface() { |
15 | for(char **p = environ; *p; p++) { | 16 | for(char **p = environ; *p; p++) { |
16 | const char *e = strchr(*p,'='); | 17 | const char *e = strchr(*p,'='); |
17 | if(!e){ | 18 | if(!e){ |
18 | // XXX: check if we have it already? | 19 | // XXX: check if we have it already? |
19 | metavars[*p] = string(0); | 20 | metavars[*p] = string(0); |
20 | }else{ | 21 | }else{ |
21 | int l = e-*p; e++; | 22 | int l = e-*p; e++; |
22 | // XXX: check if we have it already? | 23 | // XXX: check if we have it already? |
23 | metavars[string(*p,l)]=e; | 24 | metavars[string(*p,l)]=e; |
24 | } | 25 | } |
25 | } | 26 | } |
26 | } | 27 | } |
27 | plaincgi_interface::~plaincgi_interface() { | 28 | plaincgi_interface::~plaincgi_interface() { |
28 | cout.flush(); | 29 | cout.flush(); |
29 | cerr.flush(); | 30 | cerr.flush(); |
30 | } | 31 | } |
31 | 32 | ||
32 | } | 33 | } |
diff --git a/src/util.cc b/src/util.cc index 48e486a..76e684f 100644 --- a/src/util.cc +++ b/src/util.cc | |||
@@ -1,106 +1,107 @@ | |||
1 | #include <cstring> | ||
1 | #include "kingate/util.h" | 2 | #include "kingate/util.h" |
2 | #include "kingate/exception.h" | 3 | #include "kingate/exception.h" |
3 | 4 | ||
4 | namespace kingate { | 5 | namespace kingate { |
5 | 6 | ||
6 | static const char *safeChars = | 7 | static const char *safeChars = |
7 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | 8 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
8 | "abcdefghijklmnopqrstuvwxyz" | 9 | "abcdefghijklmnopqrstuvwxyz" |
9 | "0123456789" | 10 | "0123456789" |
10 | "_-" ; | 11 | "_-" ; |
11 | 12 | ||
12 | string url_encode(const string& str) { | 13 | string url_encode(const string& str) { |
13 | string rv = str; | 14 | string rv = str; |
14 | string::size_type screwed = 0; | 15 | string::size_type screwed = 0; |
15 | for(;;) { | 16 | for(;;) { |
16 | screwed = rv.find_first_not_of(safeChars,screwed); | 17 | screwed = rv.find_first_not_of(safeChars,screwed); |
17 | if(screwed == string::npos) | 18 | if(screwed == string::npos) |
18 | break; | 19 | break; |
19 | while(screwed<rv.length() && !strchr(safeChars,rv.at(screwed))) { | 20 | while(screwed<rv.length() && !strchr(safeChars,rv.at(screwed))) { |
20 | char danger = rv.at(screwed); | 21 | char danger = rv.at(screwed); |
21 | if(danger==' ') { | 22 | if(danger==' ') { |
22 | rv.replace(screwed++,1,1,'+'); | 23 | rv.replace(screwed++,1,1,'+'); |
23 | }else{ | 24 | }else{ |
24 | static char tmp[4] = {'%',0,0,0}; | 25 | static char tmp[4] = {'%',0,0,0}; |
25 | snprintf(&tmp[1],3,"%02X",0xFF&(int)danger); | 26 | snprintf(&tmp[1],3,"%02X",0xFF&(int)danger); |
26 | rv.replace(screwed,1,tmp,3); | 27 | rv.replace(screwed,1,tmp,3); |
27 | screwed+=3; | 28 | screwed+=3; |
28 | } | 29 | } |
29 | } | 30 | } |
30 | } | 31 | } |
31 | return rv; | 32 | return rv; |
32 | } | 33 | } |
33 | string url_decode(const string& str) { | 34 | string url_decode(const string& str) { |
34 | string rv = str; | 35 | string rv = str; |
35 | string::size_type unscrewed = 0; | 36 | string::size_type unscrewed = 0; |
36 | for(;;) { | 37 | for(;;) { |
37 | unscrewed = rv.find_first_of("%+",unscrewed); | 38 | unscrewed = rv.find_first_of("%+",unscrewed); |
38 | if(unscrewed == string::npos) | 39 | if(unscrewed == string::npos) |
39 | break; | 40 | break; |
40 | if(rv.at(unscrewed)=='+') { | 41 | if(rv.at(unscrewed)=='+') { |
41 | rv.replace(unscrewed++,1,1,' '); | 42 | rv.replace(unscrewed++,1,1,' '); |
42 | }else{ | 43 | }else{ |
43 | if((rv.length()-unscrewed)<3) | 44 | if((rv.length()-unscrewed)<3) |
44 | throw exception(CODEPOINT,"incorrectly escaped string"); | 45 | throw exception(CODEPOINT,"incorrectly escaped string"); |
45 | // XXX: ensure it's hex? | 46 | // XXX: ensure it's hex? |
46 | int danger = strtol(rv.substr(unscrewed+1,2).c_str(),NULL,16); | 47 | int danger = strtol(rv.substr(unscrewed+1,2).c_str(),NULL,16); |
47 | rv.replace(unscrewed,3,1,danger); | 48 | rv.replace(unscrewed,3,1,danger); |
48 | unscrewed++; | 49 | unscrewed++; |
49 | } | 50 | } |
50 | } | 51 | } |
51 | return rv; | 52 | return rv; |
52 | } | 53 | } |
53 | 54 | ||
54 | /* | 55 | /* |
55 | * RFC 2616: | 56 | * RFC 2616: |
56 | * | 57 | * |
57 | * separators = "(" | ")" | "<" | ">" | "@" | 58 | * separators = "(" | ")" | "<" | ">" | "@" |
58 | * | "," | ";" | ":" | "\" | <"> | 59 | * | "," | ";" | ":" | "\" | <"> |
59 | * | "/" | "[" | "]" | "?" | "=" | 60 | * | "/" | "[" | "]" | "?" | "=" |
60 | * | "{" | "}" | SP | HT | 61 | * | "{" | "}" | SP | HT |
61 | */ | 62 | */ |
62 | 63 | ||
63 | /* | 64 | /* |
64 | * RFC 2616: | 65 | * RFC 2616: |
65 | * | 66 | * |
66 | * token = 1*<any CHAR except CTLs or separators> | 67 | * token = 1*<any CHAR except CTLs or separators> |
67 | */ | 68 | */ |
68 | 69 | ||
69 | static const char *quotible_chars = | 70 | static const char *quotible_chars = |
70 | "\001\002\003\004\005\006\007\010" | 71 | "\001\002\003\004\005\006\007\010" |
71 | "\011\012\013\014\015\016\017\020" | 72 | "\011\012\013\014\015\016\017\020" |
72 | "\021\022\023\024\025\026\027\030" | 73 | "\021\022\023\024\025\026\027\030" |
73 | "\031\032\033\034\035\036\037\040" | 74 | "\031\032\033\034\035\036\037\040" |
74 | "()<>@,;:\\\"/[]?={}" /* separator chars (except for SP and HT mentioned elsewhere */ | 75 | "()<>@,;:\\\"/[]?={}" /* separator chars (except for SP and HT mentioned elsewhere */ |
75 | "\177" | 76 | "\177" |
76 | ; | 77 | ; |
77 | 78 | ||
78 | /* | 79 | /* |
79 | * RFC 2616: | 80 | * RFC 2616: |
80 | * | 81 | * |
81 | * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) | 82 | * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) |
82 | * qdtext = <any TEXT except <">> | 83 | * qdtext = <any TEXT except <">> |
83 | * | 84 | * |
84 | * The backslash character ("\") MAY be used as a single-character | 85 | * The backslash character ("\") MAY be used as a single-character |
85 | * quoting mechanism only within quoted-string and comment constructs. | 86 | * quoting mechanism only within quoted-string and comment constructs. |
86 | * | 87 | * |
87 | * quoted-pair = "\" CHAR | 88 | * quoted-pair = "\" CHAR |
88 | */ | 89 | */ |
89 | 90 | ||
90 | string http_quoted_string(const string& str) { | 91 | string http_quoted_string(const string& str) { |
91 | string rv = str; | 92 | string rv = str; |
92 | string::size_type sp=0; | 93 | string::size_type sp=0; |
93 | for(string::size_type q=rv.find('"');(q=rv.find('"',q))!=string::npos;q+=2) | 94 | for(string::size_type q=rv.find('"');(q=rv.find('"',q))!=string::npos;q+=2) |
94 | rv.insert(q,1,'\\'); | 95 | rv.insert(q,1,'\\'); |
95 | rv.insert(0,1,'"'); | 96 | rv.insert(0,1,'"'); |
96 | rv += '"'; | 97 | rv += '"'; |
97 | return rv; | 98 | return rv; |
98 | } | 99 | } |
99 | 100 | ||
100 | string http_quote(const string& str) { | 101 | string http_quote(const string& str) { |
101 | if(str.find_first_of(quotible_chars)==string::npos) | 102 | if(str.find_first_of(quotible_chars)==string::npos) |
102 | return str; | 103 | return str; |
103 | return http_quoted_string(str); | 104 | return http_quoted_string(str); |
104 | } | 105 | } |
105 | 106 | ||
106 | } | 107 | } |