summaryrefslogtreecommitdiffabout
path: root/src
Unidiff
Diffstat (limited to 'src') (more/less context) (ignore whitespace changes)
-rw-r--r--src/.gitignore7
-rw-r--r--src/Makefile.am15
-rw-r--r--src/cgi_gateway.cc88
-rw-r--r--src/cgi_interface.cc16
-rw-r--r--src/fastcgi.cc67
-rw-r--r--src/util.cc53
6 files changed, 246 insertions, 0 deletions
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..af4f4dd
--- a/dev/null
+++ b/src/.gitignore
@@ -0,0 +1,7 @@
1Makefile.in
2.deps
3Makefile
4.libs
5*.o
6*.lo
7*.la
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..8a5447b
--- a/dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,15 @@
1lib_LTLIBRARIES = libkingate.la libkingate-fcgi.la
2
3INCLUDES = -I${top_srcdir}/include
4AM_CXXFLAGS = ${KONFORKA_CFLAGS}
5LDADD = ${KONFORKA_LIBS}
6
7libkingate_la_SOURCES = \
8 cgi_gateway.cc \
9 cgi_interface.cc \
10 util.cc
11libkingate_la_LDFLAGS = -version-info 1:0:0
12
13libkingate_fcgi_la_SOURCES = \
14 fastcgi.cc
15libkingate_fcgi_la_LDFLAGS = -version-info 1:0:0
diff --git a/src/cgi_gateway.cc b/src/cgi_gateway.cc
new file mode 100644
index 0000000..eae7a03
--- a/dev/null
+++ b/src/cgi_gateway.cc
@@ -0,0 +1,88 @@
1#include "kingate/cgi_gateway.h"
2#include "kingate/util.h"
3#include "kingate/exception.h"
4
5namespace kingate {
6
7 cgi_gateway::cgi_gateway(cgi_interface& ci)
8 : iface(ci), b_parsed_content(false) {
9 // Fetch GET content
10 if(iface.has_meta("QUERY_STRING")) {
11 string qs = iface.get_meta("QUERY_STRING");
12 parse_query(qs,get);
13 }
14 // Fetch POST content
15 if(!strcasecmp(get_content_type().c_str(),"application/x-www-form-urlencoded")) {
16 unsigned long cl = get_content_length();
17 if(cl) {
18 char * tmp = new char[cl];
19 iface.in().read(tmp,cl);
20 string qs(tmp,cl);
21 delete tmp;
22 parse_query(qs,post);
23 }
24 b_parsed_content = true;
25 }
26 }
27
28 bool cgi_gateway::has_GET(const string& n) const {
29 return get.find(n) != get.end();
30 }
31 string cgi_gateway::get_GET(const string& n) const {
32 params_t::const_iterator i = get.find(n);
33 if(i==get.end())
34 throw exception_notfound(CODEPOINT,"no such parameter");
35 return i->second;
36 }
37 bool cgi_gateway::has_POST(const string& n) const {
38 return post.find(n) != post.end();
39 }
40 string cgi_gateway::get_POST(const string& n) const {
41 params_t::const_iterator i = post.find(n);
42 if(i==post.end())
43 throw exception_notfound(CODEPOINT,"no such parameter");
44 return i->second;
45 }
46 bool cgi_gateway::has_param(const string& n) const {
47 return has_GET(n) || has_POST(n);
48 }
49 string cgi_gateway::get_param(const string& n) const {
50 params_t::const_iterator i = get.find(n);
51 if(i!=get.end())
52 return i->second;
53 i = post.find(n);
54 if(i!=post.end())
55 return i->second;
56 throw exception_notfound(CODEPOINT,"no such parameter");
57 }
58
59 const string& cgi_gateway::get_content_type() const {
60 if(!has_meta("CONTENT_TYPE"))
61 return ""; // XXX:
62 return get_meta("CONTENT_TYPE");
63 }
64 unsigned long cgi_gateway::get_content_length() const {
65 if(!has_meta("CONTENT_LENGTH"))
66 return 0;
67 string cl = get_meta("CONTENT_LENGTH");
68 return strtol(cl.c_str(),NULL,10);
69 }
70
71 void cgi_gateway::parse_query(string& q,params_t& p) {
72 while(!q.empty()) {
73 string::size_type amp = q.find('&');
74 string pp = (amp==string::npos)?q:q.substr(0,amp);
75 if(amp==string::npos)
76 q.clear();
77 else
78 q.erase(0,amp+1);
79 string::size_type eq = pp.find('=');
80 if(eq == string::npos) {
81 p.insert(params_t::value_type("",url_unescape(pp)));
82 }else{
83 p.insert(params_t::value_type(url_unescape(pp.substr(0,eq)),url_unescape(pp.substr(eq+1))));
84 }
85 }
86 }
87
88}
diff --git a/src/cgi_interface.cc b/src/cgi_interface.cc
new file mode 100644
index 0000000..ffbd2bf
--- a/dev/null
+++ b/src/cgi_interface.cc
@@ -0,0 +1,16 @@
1#include "kingate/cgi_interface.h"
2#include "kingate/exception.h"
3
4namespace kingate {
5
6 bool cgi_interface::has_meta(const string& n) const {
7 return metavars.find(n) != metavars.end();
8 }
9 const string& cgi_interface::get_meta(const string& n) const {
10 metavars_t::const_iterator rv = metavars.find(n);
11 if(rv == metavars.end())
12 throw exception_notfound(CODEPOINT,"no such meta-variable");
13 return rv->second;
14 }
15
16}
diff --git a/src/fastcgi.cc b/src/fastcgi.cc
new file mode 100644
index 0000000..7484449
--- a/dev/null
+++ b/src/fastcgi.cc
@@ -0,0 +1,67 @@
1#include <unistd.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include "kingate/fastcgi.h"
5#include "kingate/exception.h"
6
7namespace kingate {
8
9 bool fcgi_socket::_initialized = false;
10
11 fcgi_socket::fcgi_socket(const char *s,int bl)
12 : sock(-1) {
13 if(!_initialized) {
14 if( FCGX_Init() )
15 throw exception(CODEPOINT,"failed to FCGX_Init()");
16 _initialized = true;
17 }
18 sock = FCGX_OpenSocket(s,bl);
19 if(sock<0)
20 throw exception(CODEPOINT,"failed to FCGX_OpenSocket(");
21 // TODO: check if there is a ':', not if it starts with ':'
22 if(*s != ':')
23 if(chmod(s,0777)) // XXX: configurable.
24 throw exception(CODEPOINT,"failed to chmod()");
25 }
26 fcgi_socket::fcgi_socket(int s)
27 : sock(0) {
28 if(!_initialized) {
29 if( FCGX_Init() )
30 throw exception(CODEPOINT,"failed to FCGX_Init()");
31 _initialized = true;
32 }
33 }
34 fcgi_socket::~fcgi_socket() {
35 if(sock>=0)
36 close(sock);
37 }
38
39 fcgi_interface::fcgi_interface(fcgi_socket& s,int f)
40 : sin(&sbin), sout(&sbout), serr(&sberr) {
41 if( FCGX_InitRequest(&request,s.sock,f) )
42 throw exception(CODEPOINT,"failed to FCGX_InitRequest()");
43 if( FCGX_Accept_r(&request) )
44 throw exception(CODEPOINT,"failed to FCGX_Accept_r()");
45 sbin.attach(request.in);
46 sbout.attach(request.out);
47 sberr.attach(request.err);
48 metavars.clear(); // XXX: redundant.
49 for(char **p = request.envp; *p; p++) {
50 const char *e = strchr(*p,'=');
51 if(!e){
52 // XXX: check if we have it already?
53 metavars[*p] = string(0);
54 }else{
55 int l = e-*p; e++;
56 // XXX: check if we have it already?
57 metavars[string(*p,l)]=e;
58 }
59 }
60 }
61 fcgi_interface::~fcgi_interface() {
62 sout.flush();
63 serr.flush();
64 FCGX_Finish_r(&request);
65 }
66
67}
diff --git a/src/util.cc b/src/util.cc
new file mode 100644
index 0000000..2e2d305
--- a/dev/null
+++ b/src/util.cc
@@ -0,0 +1,53 @@
1#include "kingate/util.h"
2#include "kingate/exception.h"
3
4namespace kingate {
5
6 static const char *safeChars =
7 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
8 "abcdefghijklmnopqrstuvwxyz"
9 "0123456789"
10 "_-" ;
11
12 string url_escape(const string& str) {
13 string rv = str;
14 string::size_type screwed = 0;
15 for(;;) {
16 screwed = rv.find_first_not_of(safeChars,screwed);
17 if(screwed == string::npos)
18 break;
19 while(screwed<rv.length() && !strchr(safeChars,rv.at(screwed))) {
20 char danger = rv.at(screwed);
21 if(danger==' ') {
22 rv.replace(screwed++,1,1,'+');
23 }else{
24 static char tmp[4] = {'%',0,0,0};
25 snprintf(&tmp[1],3,"%02X",0xFF&(int)danger);
26 rv.replace(screwed,1,tmp,3);
27 screwed+=3;
28 }
29 }
30 }
31 return rv;
32 }
33 string url_unescape(const string& str) {
34 string rv = str;
35 string::size_type unscrewed = 0;
36 for(;;) {
37 unscrewed = rv.find_first_of("%+",unscrewed);
38 if(unscrewed == string::npos)
39 break;
40 if(rv.at(unscrewed)=='+') {
41 rv.replace(unscrewed++,1,1,' ');
42 }else{
43 if((rv.length()-unscrewed)<3)
44 throw exception(CODEPOINT,"incorrectly escaped string");
45 // XXX: ensure it's hex?
46 int danger = strtol(rv.substr(unscrewed+1,2).c_str(),NULL,16);
47 rv.replace(unscrewed,3,1,danger);
48 unscrewed++;
49 }
50 }
51 return rv;
52 }
53}