summaryrefslogtreecommitdiffabout
path: root/src
authorMichael Krelin <hacker@klever.net>2005-07-04 22:54:09 (UTC)
committer Michael Krelin <hacker@klever.net>2005-07-04 22:54:09 (UTC)
commitc5d7daf77e265b53951e1e2b09c51e2fba5e93dc (patch) (unidiff)
tree2337ff96d85d8de6d25fbaed75eb9c0d71a1625d /src
parentc8bcbfb951eec5fe14dac0b14f4faaf4a9f9f229 (diff)
downloadkingate-c5d7daf77e265b53951e1e2b09c51e2fba5e93dc.zip
kingate-c5d7daf77e265b53951e1e2b09c51e2fba5e93dc.tar.gz
kingate-c5d7daf77e265b53951e1e2b09c51e2fba5e93dc.tar.bz2
1. awkward yet working support for POST file upload (requires mimetic)
2. support for NOT handling/parsing POSTed data (including application/x-www-form-urlencoded)
Diffstat (limited to 'src') (more/less context) (show whitespace changes)
-rw-r--r--src/cgi_gateway.cc118
1 files changed, 112 insertions, 6 deletions
diff --git a/src/cgi_gateway.cc b/src/cgi_gateway.cc
index ab48f78..1706679 100644
--- a/src/cgi_gateway.cc
+++ b/src/cgi_gateway.cc
@@ -1,113 +1,219 @@
1#include <errno.h> 1#include <errno.h>
2#include <ctype.h> 2#include <ctype.h>
3#include <sstream>
3#include "kingate/cgi_gateway.h" 4#include "kingate/cgi_gateway.h"
4#include "kingate/util.h" 5#include "kingate/util.h"
5#include "kingate/exception.h" 6#include "kingate/exception.h"
7#include "config.h"
8#ifdef HAVE_MIMETIC
9# include <mimetic/mimeentity.h>
10# include <mimetic/parser/itparser.h>
11#endif /* HAVE_MIMETIC */
6 12
7namespace kingate { 13namespace kingate {
14 using mimetic::MimeEntity;
15
16#ifdef HAVE_MIMETIC
17 struct TornMimeEntity : public MimeEntity {
18 typedef istreambuf_iterator<char> it_type;
19 typedef it_type::iterator_category it_cat;
20 struct IParser : public mimetic::IteratorParser<it_type,it_cat> {
21 typedef mimetic::IteratorParser<it_type,it_cat> BT;
22 IParser(MimeEntity& me)
23 : BT::IteratorParser<it_type,it_cat>(me) { }
24 void loadHeader(it_type bit,it_type eit) {
25 m_bit = bit; m_eit = eit;
26 BT::loadHeader();
27 }
28 void loadBody(it_type bit,it_type eit) {
29 m_bit = bit; m_eit = eit;
30 BT::loadBody();
31 }
32 };
33 void load(istream& hs,istream& bs,int mask=0) {
34 IParser prs(*this);
35 prs.iMask(mask);
36 prs.loadHeader(it_type(hs),it_type());
37 prs.loadBody(it_type(bs),it_type());
38 }
39 };
40#endif /* HAVE_MIMETIC */
8 41
9 static string empty_string; 42 static string empty_string;
10 43
11 cgi_gateway::cgi_gateway(cgi_interface& ci) 44 cgi_gateway::basic_file_t::~basic_file_t() { }
45
46 class string_file_t : public cgi_gateway::basic_file_t {
47 public:
48 string _file_name;
49 string _content_type;
50 stringstream _content;
51
52 string_file_t(const string& fn,const string& ct,const string& s)
53 : _file_name(fn), _content_type(ct), _content(s,ios::in) { }
54 const string& filename() const { return _file_name; }
55 const string& content_type() const { return _content_type; }
56 istream& content() { return _content; }
57 };
58
59 cgi_gateway::cgi_gateway(cgi_interface& ci,bool parsebody)
12 : iface(ci), b_parsed_content(false) { 60 : iface(ci), b_parsed_content(false) {
13 // Fetch GET content 61 // Fetch GET content
14 try { 62 try {
15 string qs = get_meta("QUERY_STRING"); 63 string qs = get_meta("QUERY_STRING");
16 parse_query(qs,get); 64 parse_query(qs,get);
17 }catch(exception_notfound& enf) { } 65 }catch(exception_notfound& enf) { }
66 if(parsebody)
67 parse_request_body();
68 // Parse cookies
69 try {
70 cookies.parse_cookies(get_meta("HTTP_COOKIE"));
71 }catch(exception_notfound& enf) { }
72 }
73
74 cgi_gateway::~cgi_gateway() throw() {
75 for(files_t::iterator i=files.begin();i!=files.end();++i)
76 delete i->second;
77 files.clear();
78 }
79
80 void cgi_gateway::parse_request_body() {
81 if(b_parsed_content)
82 throw konforka::exception(CODEPOINT,"request body is already parsed");
18 // Fetch POST content 83 // Fetch POST content
19 if(!strcasecmp(content_type().c_str(),"application/x-www-form-urlencoded")) { 84 if(!strncasecmp(
85 content_type().c_str(),
86 "application/x-www-form-urlencoded",
87 sizeof("application/x-www-form-urlencoded")-1) ) {
20 unsigned long cl = content_length(); 88 unsigned long cl = content_length();
21 if(cl) { 89 if(cl) {
22 char * tmp = new char[cl]; 90 char * tmp = new char[cl];
23 iface.in().read(tmp,cl); 91 iface.in().read(tmp,cl);
24 string qs(tmp,cl); 92 string qs(tmp,cl);
25 delete tmp; 93 delete tmp;
26 parse_query(qs,post); 94 parse_query(qs,post);
27 } 95 }
28 b_parsed_content = true; 96 b_parsed_content = true;
29 } 97 }
30 // Parse cookies 98#ifdef HAVE_MIMETIC
31 try { 99 else if(!strncasecmp(
32 cookies.parse_cookies(get_meta("HTTP_COOKIE")); 100 content_type().c_str(),
33 }catch(exception_notfound& enf) { } 101 "multipart/form-data",
102 sizeof("multipart/form-data")-1) ) {
103 stringstream h;
104 h
105 << "Content-Type: " << content_type() << "\r\n"
106 << "Content-Length: " << content_length() << "\r\n\n";
107 TornMimeEntity me;
108 me.load(h,iface.in(),0);
109 mimetic::MimeEntityList& parts = me.body().parts();
110 for(mimetic::MimeEntityList::iterator i=parts.begin();i!=parts.end();++i) {
111 MimeEntity *p = *i;
112 const mimetic::ContentDisposition& cd = p->header().contentDisposition();
113 string n = cd.param("name");
114 string fn = cd.param("filename");
115 if(fn.empty()) {
116 post.insert(params_t::value_type(n,p->body()));
117 }else{
118 const mimetic::ContentType& ct = p->header().contentType();
119 files.insert(files_t::value_type(n,new string_file_t(fn,ct.str(),p->body())));
120 }
121 }
122 b_parsed_content = true;
123 }
124#endif /* HAVE_MIMETIC */
34 } 125 }
35 126
36 bool cgi_gateway::has_GET(const string& n) const { 127 bool cgi_gateway::has_GET(const string& n) const {
37 return get.find(n) != get.end(); 128 return get.find(n) != get.end();
38 } 129 }
39 const string& cgi_gateway::get_GET(const string& n) const { 130 const string& cgi_gateway::get_GET(const string& n) const {
40 params_t::const_iterator i = get.find(n); 131 params_t::const_iterator i = get.find(n);
41 if(i==get.end()) 132 if(i==get.end())
42 throw exception_notfound(CODEPOINT,"no such parameter"); 133 throw exception_notfound(CODEPOINT,"no such parameter");
43 return i->second; 134 return i->second;
44 } 135 }
45 bool cgi_gateway::has_POST(const string& n) const { 136 bool cgi_gateway::has_POST(const string& n) const {
46 return post.find(n) != post.end(); 137 return post.find(n) != post.end();
47 } 138 }
48 const string& cgi_gateway::get_POST(const string& n) const { 139 const string& cgi_gateway::get_POST(const string& n) const {
49 params_t::const_iterator i = post.find(n); 140 params_t::const_iterator i = post.find(n);
50 if(i==post.end()) 141 if(i==post.end())
51 throw exception_notfound(CODEPOINT,"no such parameter"); 142 throw exception_notfound(CODEPOINT,"no such parameter");
52 return i->second; 143 return i->second;
53 } 144 }
54 bool cgi_gateway::has_param(const string& n) const { 145 bool cgi_gateway::has_param(const string& n) const {
55 return has_GET(n) || has_POST(n); 146 return has_GET(n) || has_POST(n);
56 } 147 }
57 const string& cgi_gateway::get_param(const string& n) const { 148 const string& cgi_gateway::get_param(const string& n) const {
58 params_t::const_iterator i = get.find(n); 149 params_t::const_iterator i = get.find(n);
59 if(i!=get.end()) 150 if(i!=get.end())
60 return i->second; 151 return i->second;
61 i = post.find(n); 152 i = post.find(n);
62 if(i!=post.end()) 153 if(i!=post.end())
63 return i->second; 154 return i->second;
64 throw exception_notfound(CODEPOINT,"no such parameter"); 155 throw exception_notfound(CODEPOINT,"no such parameter");
65 } 156 }
157 bool cgi_gateway::has_file(const string& n) const {
158 return files.find(n) != files.end();
159 }
160 const cgi_gateway::file_t cgi_gateway::get_file(const string& n) const {
161 files_t::const_iterator i = files.find(n);
162 if(i==files.end())
163 throw exception_notfound(CODEPOINT,"no such parameter");
164 return i->second;
165 }
166 cgi_gateway::file_t cgi_gateway::get_file(const string& n) {
167 files_t::const_iterator i = files.find(n);
168 if(i==files.end())
169 throw exception_notfound(CODEPOINT,"no such parameter");
170 return i->second;
171 }
66 172
67 /* 173 /*
68 * deprecated stuff. 174 * deprecated stuff.
69 */ 175 */
70 const string& cgi_gateway::get_content_type() const { 176 const string& cgi_gateway::get_content_type() const {
71 if(!has_meta("CONTENT_TYPE")) 177 if(!has_meta("CONTENT_TYPE"))
72 return empty_string; 178 return empty_string;
73 return get_meta("CONTENT_TYPE"); 179 return get_meta("CONTENT_TYPE");
74 } 180 }
75 unsigned long cgi_gateway::get_content_length() const { 181 unsigned long cgi_gateway::get_content_length() const {
76 if(!has_meta("CONTENT_LENGTH")) 182 if(!has_meta("CONTENT_LENGTH"))
77 return 0; 183 return 0;
78 string cl = get_meta("CONTENT_LENGTH"); 184 string cl = get_meta("CONTENT_LENGTH");
79 return strtol(cl.c_str(),NULL,10); 185 return strtol(cl.c_str(),NULL,10);
80 } 186 }
81 /* 187 /*
82 * 188 *
83 */ 189 */
84 190
85 const string& cgi_gateway::http_request_header(const string& hn) const { 191 const string& cgi_gateway::http_request_header(const string& hn) const {
86 string mvn = "HTTP_"; 192 string mvn = "HTTP_";
87 for(const char* p=hn.c_str();*p;p++) { 193 for(const char* p=hn.c_str();*p;p++) {
88 if(*p=='-') 194 if(*p=='-')
89 mvn += '_'; 195 mvn += '_';
90 else 196 else
91 mvn += toupper(*p); 197 mvn += toupper(*p);
92 } 198 }
93 return get_meta(mvn); 199 return get_meta(mvn);
94 } 200 }
95 201
96 const string& cgi_gateway::auth_type() const { 202 const string& cgi_gateway::auth_type() const {
97 try { 203 try {
98 return get_meta("AUTH_TYPE"); 204 return get_meta("AUTH_TYPE");
99 }catch(exception_notfound& enf) { 205 }catch(exception_notfound& enf) {
100 return empty_string; 206 return empty_string;
101 } 207 }
102 } 208 }
103 unsigned long cgi_gateway::content_length() const { 209 unsigned long cgi_gateway::content_length() const {
104 try { 210 try {
105 const string& cl = get_meta("CONTENT_LENGTH"); 211 const string& cl = get_meta("CONTENT_LENGTH");
106 errno = 0; 212 errno = 0;
107 const char *clp = cl.c_str(); 213 const char *clp = cl.c_str();
108 unsigned long rv = strtol(clp,(char**)&clp,10); 214 unsigned long rv = strtol(clp,(char**)&clp,10);
109 if(errno || *clp) 215 if(errno || *clp)
110 throw server_error(CODEPOINT,"Invalid CONTENT_LENGTH value passed from server"); 216 throw server_error(CODEPOINT,"Invalid CONTENT_LENGTH value passed from server");
111 return rv; 217 return rv;
112 }catch(exception_notfound& enf) { 218 }catch(exception_notfound& enf) {
113 return 0; 219 return 0;