summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--configure.ac16
-rw-r--r--include/kingate/cgi_gateway.h57
-rw-r--r--kingate.pc.in4
-rw-r--r--src/cgi_gateway.cc132
4 files changed, 190 insertions, 19 deletions
diff --git a/configure.ac b/configure.ac
index b3141f1..b51d64d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,70 +1,84 @@
1AC_INIT([kingate], [0.0.1], [kingate-bugs@klever.net]) 1AC_INIT([kingate], [0.0.1], [kingate-bugs@klever.net])
2AC_CONFIG_SRCDIR([include/kingate/cgi_gateway.h]) 2AC_CONFIG_SRCDIR([include/kingate/cgi_gateway.h])
3AC_CONFIG_HEADER([config.h]) 3AC_CONFIG_HEADERS([config.h])
4AM_INIT_AUTOMAKE([dist-bzip2]) 4AM_INIT_AUTOMAKE([dist-bzip2])
5 5
6AC_PROG_INSTALL 6AC_PROG_INSTALL
7AC_PROG_AWK 7AC_PROG_AWK
8AC_PROG_CXX 8AC_PROG_CXX
9AC_PROG_CC 9AC_PROG_CC
10AC_PROG_LIBTOOL 10AC_PROG_LIBTOOL
11 11
12AC_HEADER_STDC 12AC_HEADER_STDC
13AC_CHECK_HEADERS([sys/types.h sys/stat.h]) 13AC_CHECK_HEADERS([sys/types.h sys/stat.h])
14AC_CHECK_DECLS([environ],,,[ 14AC_CHECK_DECLS([environ],,,[
15 #include <unistd.h> 15 #include <unistd.h>
16]) 16])
17 17
18HAVE_FCGI=false 18HAVE_FCGI=false
19AC_LANG_PUSH(C++) 19AC_LANG_PUSH(C++)
20AC_CHECK_HEADERS([fcgio.h],[ 20AC_CHECK_HEADERS([fcgio.h],[
21 AC_CHECK_LIB(fcgi,FCGX_Init,[ 21 AC_CHECK_LIB(fcgi,FCGX_Init,[
22 LIBS="-lfcgi ${LIBS}" 22 LIBS="-lfcgi ${LIBS}"
23 AC_CHECK_LIB([fcgi++],[main],[ 23 AC_CHECK_LIB([fcgi++],[main],[
24 LIBS="-lfcgi++ ${LIBS}" 24 LIBS="-lfcgi++ ${LIBS}"
25 HAVE_FCGI=true 25 HAVE_FCGI=true
26 ]) 26 ])
27 ]) 27 ])
28]) 28])
29AC_LANG_POP(C++) 29AC_LANG_POP(C++)
30if ! ${HAVE_FCGI} ; then 30if ! ${HAVE_FCGI} ; then
31 AC_MSG_NOTICE([no FastCGI development kit found. It is highly recommnded that you get one. Meanwhile we will proceed without FastCGI support]) 31 AC_MSG_NOTICE([no FastCGI development kit found. It is highly recommnded that you get one. Meanwhile we will proceed without FastCGI support])
32fi 32fi
33AM_CONDITIONAL([HAVE_FCGI],[${HAVE_FCGI}]) 33AM_CONDITIONAL([HAVE_FCGI],[${HAVE_FCGI}])
34 34
35AC_C_CONST 35AC_C_CONST
36 36
37AC_FUNC_MALLOC 37AC_FUNC_MALLOC
38AC_FUNC_REALLOC 38AC_FUNC_REALLOC
39 39
40AC_PATH_PROG([XSLTPROC],[xsltproc],[true]) 40AC_PATH_PROG([XSLTPROC],[xsltproc],[true])
41 41
42AC_WITH_PKGCONFIG 42AC_WITH_PKGCONFIG
43 43
44PKG_CHECK_MODULES([KONFORKA],[konforka],,[ 44PKG_CHECK_MODULES([KONFORKA],[konforka],,[
45 AC_MSG_ERROR([no konforka library found. get one from http://kin.klever.net/konforka/]) 45 AC_MSG_ERROR([no konforka library found. get one from http://kin.klever.net/konforka/])
46]) 46])
47 47
48WANT_DOXYGEN="yes" 48WANT_DOXYGEN="yes"
49AC_ARG_ENABLE([doxygen], 49AC_ARG_ENABLE([doxygen],
50 AC_HELP_STRING([--disable-doxygen],[do not generate documentation]), 50 AC_HELP_STRING([--disable-doxygen],[do not generate documentation]),
51 [ 51 [
52 test "${enableval}" = "no" && WANT_DOXYGEN="no" 52 test "${enableval}" = "no" && WANT_DOXYGEN="no"
53 ] 53 ]
54) 54)
55if test "${WANT_DOXYGEN}" = "yes" ; then 55if test "${WANT_DOXYGEN}" = "yes" ; then
56 AC_WITH_DOXYGEN 56 AC_WITH_DOXYGEN
57 AC_WITH_DOT 57 AC_WITH_DOT
58else 58else
59 AM_CONDITIONAL([HAVE_DOXYGEN],[false]) 59 AM_CONDITIONAL([HAVE_DOXYGEN],[false])
60 AM_CONDITIONAL([HAVE_DOT],[false]) 60 AM_CONDITIONAL([HAVE_DOT],[false])
61fi 61fi
62 62
63HAVE_MIMETIC=false
64AC_LANG_PUSH(C++)
65 AC_CHECK_LIB([mimetic],[main],[
66 MIMETIC_LIBS=-lmimetic
67 HAVE_MIMETIC=true
68 ]
69 )
70AC_LANG_POP(C++)
71AC_SUBST([MIMETIC_LIBS])
72AC_SUBST([MIMETIC_CFLAGS])
73if ${HAVE_MIMETIC} ; then
74 AC_DEFINE([HAVE_MIMETIC],,[defined in presence of mimetic])
75fi
76
63AC_CONFIG_FILES([ 77AC_CONFIG_FILES([
64 Makefile 78 Makefile
65 kingate.pc kingate-fcgi.pc kingate-plaincgi.pc 79 kingate.pc kingate-fcgi.pc kingate-plaincgi.pc
66 Doxyfile 80 Doxyfile
67 include/Makefile 81 include/Makefile
68 src/Makefile 82 src/Makefile
69]) 83])
70AC_OUTPUT 84AC_OUTPUT
diff --git a/include/kingate/cgi_gateway.h b/include/kingate/cgi_gateway.h
index f20d72b..a26b0ae 100644
--- a/include/kingate/cgi_gateway.h
+++ b/include/kingate/cgi_gateway.h
@@ -1,244 +1,295 @@
1#ifndef __KINGATE_CGI_GATEWAY_H 1#ifndef __KINGATE_CGI_GATEWAY_H
2#define __KINGATE_CGI_GATEWAY_H 2#define __KINGATE_CGI_GATEWAY_H
3 3
4#include <map> 4#include <map>
5#include "kingate/cgi_interface.h" 5#include "kingate/cgi_interface.h"
6#include "kingate/cookies.h" 6#include "kingate/cookies.h"
7 7
8#ifndef __deprecated 8#ifndef __deprecated
9#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3 9#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3
10#define __deprecated __attribute__((deprecated)) 10#define __deprecated __attribute__((deprecated))
11#else 11#else
12#define __deprecated 12#define __deprecated
13#endif 13#endif
14#endif 14#endif
15 15
16/** 16/**
17 * @file 17 * @file
18 * @brief the cgi_gateway -- main interface to CGI. 18 * @brief the cgi_gateway -- main interface to CGI.
19 */ 19 */
20 20
21namespace kingate { 21namespace kingate {
22 using namespace std; 22 using namespace std;
23 23
24 /** 24 /**
25 * The main class interfacing with the CGI environment. 25 * The main class interfacing with the CGI environment.
26 */ 26 */
27 class cgi_gateway { 27 class cgi_gateway {
28 public: 28 public:
29 /** 29 /**
30 * The interface to CGI environment (e.g. fastcgi). 30 * The interface to CGI environment (e.g. fastcgi).
31 */ 31 */
32 cgi_interface& iface; 32 cgi_interface& iface;
33 /** 33 /**
34 * The type describing map holding parameters parsed from query string or input. 34 * The type describing map holding parameters parsed from query string or input.
35 */ 35 */
36 typedef multimap<string,string> params_t; 36 typedef multimap<string,string> params_t;
37 /** 37 /**
38 * The GET-passed parameters. 38 * The GET-passed parameters.
39 */ 39 */
40 params_t get; 40 params_t get;
41 /** 41 /**
42 * The POST-passed parameters. 42 * The POST-passed parameters.
43 */ 43 */
44 params_t post; 44 params_t post;
45 /** 45 /**
46 * Abstract base class for retrieving posted files.
47 */
48 class basic_file_t {
49 public:
50 /**
51 * Retrieve file name.
52 * @return filename
53 */
54 virtual const string& filename() const = 0;
55 /**
56 * Retrieve file content type.
57 * @return content type
58 */
59 virtual const string& content_type() const = 0;
60 /**
61 * Retrieve file contents.
62 * @return reference to the stream for accessing file content.
63 */
64 virtual istream& content() = 0;
65 virtual ~basic_file_t();
66 };
67 typedef basic_file_t *file_t;
68 /**
69 * The map holding information pertaining to files uploaded via post.
70 */
71 typedef multimap<string,file_t> files_t;
72 /**
73 * Files uploaded via post
74 */
75 files_t files;
76 /**
46 * Cookies passed. 77 * Cookies passed.
47 */ 78 */
48 cookies_t cookies; 79 cookies_t cookies;
49 /** 80 /**
50 * Was the stdin content parsed? 81 * Was the stdin content parsed?
51 */ 82 */
52 bool b_parsed_content; 83 bool b_parsed_content;
53 84
54 /** 85 /**
55 * @param ci the interface to use. 86 * @param ci the interface to use.
56 */ 87 */
57 cgi_gateway(cgi_interface& ci); 88 cgi_gateway(cgi_interface& ci,bool parsebody = true);
89 virtual ~cgi_gateway() throw();
90
91 /**
92 * Parse request body.
93 */
94 void parse_request_body();
58 95
59 /** 96 /**
60 * Check whether there is an 'environment' meta-variable with specific name 97 * Check whether there is an 'environment' meta-variable with specific name
61 * passed to CGI. 98 * passed to CGI.
62 * @param n variable name. 99 * @param n variable name.
63 * @return true if yes. 100 * @return true if yes.
64 * @see cgi_interface::has_meta() 101 * @see cgi_interface::has_meta()
65 * @see get_meta() 102 * @see get_meta()
66 */ 103 */
67 bool has_meta(const string& n) const { return iface.has_meta(n); } 104 bool has_meta(const string& n) const { return iface.has_meta(n); }
68 /** 105 /**
69 * Retrieve the 'environment' meta-variable value. 106 * Retrieve the 'environment' meta-variable value.
70 * @param n variable name. 107 * @param n variable name.
71 * @return variable contents. 108 * @return variable contents.
72 * @see exception_notfound 109 * @see exception_notfound
73 * @see cgi_interface::get_meta() 110 * @see cgi_interface::get_meta()
74 */ 111 */
75 const string& get_meta(const string& n) const { return iface.get_meta(n); } 112 const string& get_meta(const string& n) const { return iface.get_meta(n); }
76 113
77 /** 114 /**
78 * fetch reference to the 'stdin' stream. 115 * fetch reference to the 'stdin' stream.
79 * @return the reference to the corresponding istream object. 116 * @return the reference to the corresponding istream object.
80 * @see cgi_interface::in() 117 * @see cgi_interface::in()
81 */ 118 */
82 istream& in() { return iface.in(); } 119 istream& in() { return iface.in(); }
83 /** 120 /**
84 * fetch reference to the 'stdout' stream. 121 * fetch reference to the 'stdout' stream.
85 * @return the reference to the corresponding ostream object. 122 * @return the reference to the corresponding ostream object.
86 * @see cgi_interface::out() 123 * @see cgi_interface::out()
87 */ 124 */
88 ostream& out() { return iface.out(); } 125 ostream& out() { return iface.out(); }
89 /** 126 /**
90 * fetch reference to the 'stderr' stream. 127 * fetch reference to the 'stderr' stream.
91 * @return the reference to the corresponding ostream object. 128 * @return the reference to the corresponding ostream object.
92 * @see cgi_interface::err() 129 * @see cgi_interface::err()
93 */ 130 */
94 ostream& err() { return iface.err(); } 131 ostream& err() { return iface.err(); }
95 /** 132 /**
96 * cast to the ostream -- fetches the reference to the 'stdout' 133 * cast to the ostream -- fetches the reference to the 'stdout'
97 * stream. 134 * stream.
98 * @see out() 135 * @see out()
99 */ 136 */
100 operator ostream& (void) { return out(); } 137 operator ostream& (void) { return out(); }
101 138
102 /** 139 /**
103 * Check to see whether the parameter was passed via GET. 140 * Check to see whether the parameter was passed via GET.
104 * @param n the parameter name. 141 * @param n the parameter name.
105 * @return true if yes. 142 * @return true if yes.
106 */ 143 */
107 bool has_GET(const string& n) const; 144 bool has_GET(const string& n) const;
108 /** 145 /**
109 * Retrieve the parameter passed via GET. 146 * Retrieve the parameter passed via GET.
110 * @param n the parameter name. 147 * @param n the parameter name.
111 * @return the parameter contents. 148 * @return the parameter contents.
112 * @see exception_notfound 149 * @see exception_notfound
113 */ 150 */
114 const string& get_GET(const string& n) const; 151 const string& get_GET(const string& n) const;
115 /** 152 /**
116 * Check to see whether the parameter was passed via POST. 153 * Check to see whether the parameter was passed via POST.
117 * @param n the parameter name. 154 * @param n the parameter name.
118 * @return true if yes. 155 * @return true if yes.
119 */ 156 */
120 bool has_POST(const string& n) const; 157 bool has_POST(const string& n) const;
121 /** 158 /**
122 * Retrieve the POST-parameter. 159 * Retrieve the POST-parameter.
123 * @param n the parameter name. 160 * @param n the parameter name.
124 * @return the parameter contents. 161 * @return the parameter contents.
125 * @see exception_notfound 162 * @see exception_notfound
126 */ 163 */
127 const string& get_POST(const string& n) const; 164 const string& get_POST(const string& n) const;
128 /** 165 /**
129 * Check to see whether the parameter was passed either via POST or 166 * Check to see whether the parameter was passed either via POST or
130 * GET. 167 * GET.
131 * @param n the parameter name. 168 * @param n the parameter name.
132 * @return true if yes. 169 * @return true if yes.
133 */ 170 */
134 bool has_param(const string& n) const; 171 bool has_param(const string& n) const;
135 /** 172 /**
136 * Retrieve the parameter passed either via POST or GET 173 * Retrieve the parameter passed either via POST or GET
137 * (GET-parameter takes precedence). 174 * (GET-parameter takes precedence).
138 * @param n the parameter name. 175 * @param n the parameter name.
139 * @return true if yes. 176 * @return the parameter contents.
140 * @see exception_notfound. 177 * @see exception_notfound.
141 */ 178 */
142 const string& get_param(const string& n) const; 179 const string& get_param(const string& n) const;
180 /**
181 * Check to see whether the file was uploaded in the request body.
182 * @param n the parameter name.
183 * @return true if yes.
184 */
185 bool has_file(const string& n) const;
186 /**
187 * Retrieve the file uploaded in the request body.
188 * @param n the parameter name.
189 * @return the file.
190 * @see exception_notfound.
191 */
192 const file_t get_file(const string& n) const;
193 file_t get_file(const string& n);
143 194
144 /** 195 /**
145 * Retrieve the POST content-type (as passed via CONTENT_TYPE 196 * Retrieve the POST content-type (as passed via CONTENT_TYPE
146 * environment variable). 197 * environment variable).
147 * @return the content type. 198 * @return the content type.
148 */ 199 */
149 const string& __deprecated get_content_type() const; 200 const string& __deprecated get_content_type() const;
150 /** 201 /**
151 * Retrieve the POST content length (as passed via the 202 * Retrieve the POST content length (as passed via the
152 * CONTENT_LENGTH environment variable). 203 * CONTENT_LENGTH environment variable).
153 * @return the content length. 204 * @return the content length.
154 */ 205 */
155 unsigned long __deprecated get_content_length() const; 206 unsigned long __deprecated get_content_length() const;
156 207
157 /** 208 /**
158 * Check to see whether the content from stdin stream was parsed. 209 * Check to see whether the content from stdin stream was parsed.
159 * @return true if yes. 210 * @return true if yes.
160 */ 211 */
161 bool is_content_parsed() const { return b_parsed_content; } 212 bool is_content_parsed() const { return b_parsed_content; }
162 213
163 /** 214 /**
164 * Retrieve the HTTP header value from the HTTP_ meta-variable. 215 * Retrieve the HTTP header value from the HTTP_ meta-variable.
165 * (see RFC3875) 216 * (see RFC3875)
166 * @param hn header field name. 217 * @param hn header field name.
167 * @return the HTTP header value. 218 * @return the HTTP header value.
168 */ 219 */
169 const string& http_request_header(const string& hn) const; 220 const string& http_request_header(const string& hn) const;
170 221
171 /** 222 /**
172 * Retrieve the AUTH_TYPE meta-variable (see RFC3875) 223 * Retrieve the AUTH_TYPE meta-variable (see RFC3875)
173 * @return authentication type. 224 * @return authentication type.
174 */ 225 */
175 const string& auth_type() const; 226 const string& auth_type() const;
176 /** 227 /**
177 * Retrieve the CONTENT_LENGTH meta-variable (see RFC3875) 228 * Retrieve the CONTENT_LENGTH meta-variable (see RFC3875)
178 * @return size of the request message body. 229 * @return size of the request message body.
179 */ 230 */
180 unsigned long cgi_gateway::content_length() const; 231 unsigned long content_length() const;
181 /** 232 /**
182 * Retrieve the CONTENT_TYPE meta-variable (see RFC3875) 233 * Retrieve the CONTENT_TYPE meta-variable (see RFC3875)
183 * @return media type of the request message body. 234 * @return media type of the request message body.
184 */ 235 */
185 const string& content_type() const; 236 const string& content_type() const;
186 /** 237 /**
187 * Retrieve the GATEWAY_INTERFACE meta-variable (see RFC3875) 238 * Retrieve the GATEWAY_INTERFACE meta-variable (see RFC3875)
188 * @return the gateway interface dialect. 239 * @return the gateway interface dialect.
189 */ 240 */
190 const string& gateway_interface() const; 241 const string& gateway_interface() const;
191 /** 242 /**
192 * Retrieve the PATH_INFO meta-variable (see RFC3875) 243 * Retrieve the PATH_INFO meta-variable (see RFC3875)
193 * @return path to be interpreted by the script. 244 * @return path to be interpreted by the script.
194 */ 245 */
195 const string& path_info() const; 246 const string& path_info() const;
196 /** 247 /**
197 * Retrieve the PATH_TRANSLATED meta-variable (see RFC3875) 248 * Retrieve the PATH_TRANSLATED meta-variable (see RFC3875)
198 * @return the translated path to the document. 249 * @return the translated path to the document.
199 */ 250 */
200 const string& path_translated() const; 251 const string& path_translated() const;
201 /** 252 /**
202 * Retrieve the QUERY_STRING meta-variable (see RFC3875) 253 * Retrieve the QUERY_STRING meta-variable (see RFC3875)
203 * @return the query string. 254 * @return the query string.
204 */ 255 */
205 const string& query_string() const; 256 const string& query_string() const;
206 /** 257 /**
207 * Retrieve the REMOTE_ADDR meta-variable (see RFC3875) 258 * Retrieve the REMOTE_ADDR meta-variable (see RFC3875)
208 * @return the network address of the remote host. 259 * @return the network address of the remote host.
209 */ 260 */
210 const string& remote_addr() const; 261 const string& remote_addr() const;
211 /** 262 /**
212 * Retrieve the REMOTE_HOST meta-variable (see RFC3875) 263 * Retrieve the REMOTE_HOST meta-variable (see RFC3875)
213 * @return the fully qualified domain name of the client if 264 * @return the fully qualified domain name of the client if
214 * available. REMOTE_ADDR otherwise. 265 * available. REMOTE_ADDR otherwise.
215 * @see remote_addr() 266 * @see remote_addr()
216 */ 267 */
217 const string& remote_host() const; 268 const string& remote_host() const;
218 /** 269 /**
219 * Retrieve the REMOTE_IDENT meta-variable (see RFC3875) 270 * Retrieve the REMOTE_IDENT meta-variable (see RFC3875)
220 * @return remote user identity (see RFC1413). 271 * @return remote user identity (see RFC1413).
221 */ 272 */
222 const string& remote_ident() const; 273 const string& remote_ident() const;
223 /** 274 /**
224 * Retrieve the REMOTE_USER meta-variable (see RFC3875) 275 * Retrieve the REMOTE_USER meta-variable (see RFC3875)
225 * @return the authenticated user name. 276 * @return the authenticated user name.
226 */ 277 */
227 const string& remote_user() const; 278 const string& remote_user() const;
228 /** 279 /**
229 * Retrieve the REQUEST_METHOD meta-variable (see RFC3875) 280 * Retrieve the REQUEST_METHOD meta-variable (see RFC3875)
230 * @return the http request method. 281 * @return the http request method.
231 */ 282 */
232 const string& request_method() const; 283 const string& request_method() const;
233 /** 284 /**
234 * Retrieve the SCRIPT_NAME meta-variable (see RFC3875) 285 * Retrieve the SCRIPT_NAME meta-variable (see RFC3875)
235 * @return the uri path identifying the script. 286 * @return the uri path identifying the script.
236 */ 287 */
237 const string& script_name() const; 288 const string& script_name() const;
238 /** 289 /**
239 * Retrieve the SERVER_NAME meta-variable (see RFC3875) 290 * Retrieve the SERVER_NAME meta-variable (see RFC3875)
240 * @return the server name of the script. 291 * @return the server name of the script.
241 */ 292 */
242 const string& server_name() const; 293 const string& server_name() const;
243 /** 294 /**
244 * Retrieve the SERVER_PORT meta-variable (see RFC3875) 295 * Retrieve the SERVER_PORT meta-variable (see RFC3875)
diff --git a/kingate.pc.in b/kingate.pc.in
index 671faac..05cfe1d 100644
--- a/kingate.pc.in
+++ b/kingate.pc.in
@@ -1,11 +1,11 @@
1prefix=@prefix@ 1prefix=@prefix@
2exec_prefix=@exec_prefix@ 2exec_prefix=@exec_prefix@
3libdir=@libdir@ 3libdir=@libdir@
4includedir=@includedir@ 4includedir=@includedir@
5 5
6Name: kingate 6Name: kingate
7Description: C++ CGI support library 7Description: C++ CGI support library
8Version: @VERSION@ 8Version: @VERSION@
9Requires: konforka 9Requires: konforka
10Libs: -L${libdir} -lkingate 10Libs: -L${libdir} -lkingate @MIMETIC_LIBS@
11Cflags: -I${includedir} 11Cflags: -I${includedir} @MIMETIC_CFLAGS@
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,129 +1,235 @@
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) { }
18 // Fetch POST content 66 if(parsebody)
19 if(!strcasecmp(content_type().c_str(),"application/x-www-form-urlencoded")) { 67 parse_request_body();
20 unsigned long cl = content_length();
21 if(cl) {
22 char * tmp = new char[cl];
23 iface.in().read(tmp,cl);
24 string qs(tmp,cl);
25 delete tmp;
26 parse_query(qs,post);
27 }
28 b_parsed_content = true;
29 }
30 // Parse cookies 68 // Parse cookies
31 try { 69 try {
32 cookies.parse_cookies(get_meta("HTTP_COOKIE")); 70 cookies.parse_cookies(get_meta("HTTP_COOKIE"));
33 }catch(exception_notfound& enf) { } 71 }catch(exception_notfound& enf) { }
34 } 72 }
35 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");
83 // Fetch POST content
84 if(!strncasecmp(
85 content_type().c_str(),
86 "application/x-www-form-urlencoded",
87 sizeof("application/x-www-form-urlencoded")-1) ) {
88 unsigned long cl = content_length();
89 if(cl) {
90 char * tmp = new char[cl];
91 iface.in().read(tmp,cl);
92 string qs(tmp,cl);
93 delete tmp;
94 parse_query(qs,post);
95 }
96 b_parsed_content = true;
97 }
98#ifdef HAVE_MIMETIC
99 else if(!strncasecmp(
100 content_type().c_str(),
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 */
125 }
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;
114 } 220 }
115 } 221 }
116 const string& cgi_gateway::content_type() const { 222 const string& cgi_gateway::content_type() const {
117 try { 223 try {
118 return get_meta("CONTENT_TYPE"); 224 return get_meta("CONTENT_TYPE");
119 }catch(exception_notfound& enf) { 225 }catch(exception_notfound& enf) {
120 return empty_string; 226 return empty_string;
121 } 227 }
122 } 228 }
123 const string& cgi_gateway::gateway_interface() const { 229 const string& cgi_gateway::gateway_interface() const {
124 try { 230 try {
125 return get_meta("GATEWAY_INTERFACE"); 231 return get_meta("GATEWAY_INTERFACE");
126 }catch(exception_notfound& enf) { 232 }catch(exception_notfound& enf) {
127 return empty_string; 233 return empty_string;
128 } 234 }
129 } 235 }