summaryrefslogtreecommitdiffabout
path: root/src/cgi_gateway.cc
Unidiff
Diffstat (limited to 'src/cgi_gateway.cc') (more/less context) (show whitespace changes)
-rw-r--r--src/cgi_gateway.cc1
1 files changed, 1 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
13namespace kingate { 14namespace 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}