From ff4b919683537625f693eedf53006364d0f8444d Mon Sep 17 00:00:00 2001 From: Michael Krelin Date: Sat, 29 Jan 2005 20:14:37 +0000 Subject: initial commit into repository --- (limited to 'src') 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 @@ +Makefile.in +.deps +Makefile +.libs +*.o +*.lo +*.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 @@ +lib_LTLIBRARIES = libkingate.la libkingate-fcgi.la + +INCLUDES = -I${top_srcdir}/include +AM_CXXFLAGS = ${KONFORKA_CFLAGS} +LDADD = ${KONFORKA_LIBS} + +libkingate_la_SOURCES = \ + cgi_gateway.cc \ + cgi_interface.cc \ + util.cc +libkingate_la_LDFLAGS = -version-info 1:0:0 + +libkingate_fcgi_la_SOURCES = \ + fastcgi.cc +libkingate_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 @@ +#include "kingate/cgi_gateway.h" +#include "kingate/util.h" +#include "kingate/exception.h" + +namespace kingate { + + cgi_gateway::cgi_gateway(cgi_interface& ci) + : iface(ci), b_parsed_content(false) { + // Fetch GET content + if(iface.has_meta("QUERY_STRING")) { + string qs = iface.get_meta("QUERY_STRING"); + parse_query(qs,get); + } + // Fetch POST content + if(!strcasecmp(get_content_type().c_str(),"application/x-www-form-urlencoded")) { + unsigned long cl = get_content_length(); + if(cl) { + char * tmp = new char[cl]; + iface.in().read(tmp,cl); + string qs(tmp,cl); + delete tmp; + parse_query(qs,post); + } + b_parsed_content = true; + } + } + + bool cgi_gateway::has_GET(const string& n) const { + return get.find(n) != get.end(); + } + string cgi_gateway::get_GET(const string& n) const { + params_t::const_iterator i = get.find(n); + if(i==get.end()) + throw exception_notfound(CODEPOINT,"no such parameter"); + return i->second; + } + bool cgi_gateway::has_POST(const string& n) const { + return post.find(n) != post.end(); + } + string cgi_gateway::get_POST(const string& n) const { + params_t::const_iterator i = post.find(n); + if(i==post.end()) + throw exception_notfound(CODEPOINT,"no such parameter"); + return i->second; + } + bool cgi_gateway::has_param(const string& n) const { + return has_GET(n) || has_POST(n); + } + string cgi_gateway::get_param(const string& n) const { + params_t::const_iterator i = get.find(n); + if(i!=get.end()) + return i->second; + i = post.find(n); + if(i!=post.end()) + return i->second; + throw exception_notfound(CODEPOINT,"no such parameter"); + } + + const string& cgi_gateway::get_content_type() const { + if(!has_meta("CONTENT_TYPE")) + return ""; // XXX: + return get_meta("CONTENT_TYPE"); + } + unsigned long cgi_gateway::get_content_length() const { + if(!has_meta("CONTENT_LENGTH")) + return 0; + string cl = get_meta("CONTENT_LENGTH"); + return strtol(cl.c_str(),NULL,10); + } + + void cgi_gateway::parse_query(string& q,params_t& p) { + while(!q.empty()) { + string::size_type amp = q.find('&'); + string pp = (amp==string::npos)?q:q.substr(0,amp); + if(amp==string::npos) + q.clear(); + else + q.erase(0,amp+1); + string::size_type eq = pp.find('='); + if(eq == string::npos) { + p.insert(params_t::value_type("",url_unescape(pp))); + }else{ + p.insert(params_t::value_type(url_unescape(pp.substr(0,eq)),url_unescape(pp.substr(eq+1)))); + } + } + } + +} 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 @@ +#include "kingate/cgi_interface.h" +#include "kingate/exception.h" + +namespace kingate { + + bool cgi_interface::has_meta(const string& n) const { + return metavars.find(n) != metavars.end(); + } + const string& cgi_interface::get_meta(const string& n) const { + metavars_t::const_iterator rv = metavars.find(n); + if(rv == metavars.end()) + throw exception_notfound(CODEPOINT,"no such meta-variable"); + return rv->second; + } + +} 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 @@ +#include +#include +#include +#include "kingate/fastcgi.h" +#include "kingate/exception.h" + +namespace kingate { + + bool fcgi_socket::_initialized = false; + + fcgi_socket::fcgi_socket(const char *s,int bl) + : sock(-1) { + if(!_initialized) { + if( FCGX_Init() ) + throw exception(CODEPOINT,"failed to FCGX_Init()"); + _initialized = true; + } + sock = FCGX_OpenSocket(s,bl); + if(sock<0) + throw exception(CODEPOINT,"failed to FCGX_OpenSocket("); + // TODO: check if there is a ':', not if it starts with ':' + if(*s != ':') + if(chmod(s,0777)) // XXX: configurable. + throw exception(CODEPOINT,"failed to chmod()"); + } + fcgi_socket::fcgi_socket(int s) + : sock(0) { + if(!_initialized) { + if( FCGX_Init() ) + throw exception(CODEPOINT,"failed to FCGX_Init()"); + _initialized = true; + } + } + fcgi_socket::~fcgi_socket() { + if(sock>=0) + close(sock); + } + + fcgi_interface::fcgi_interface(fcgi_socket& s,int f) + : sin(&sbin), sout(&sbout), serr(&sberr) { + if( FCGX_InitRequest(&request,s.sock,f) ) + throw exception(CODEPOINT,"failed to FCGX_InitRequest()"); + if( FCGX_Accept_r(&request) ) + throw exception(CODEPOINT,"failed to FCGX_Accept_r()"); + sbin.attach(request.in); + sbout.attach(request.out); + sberr.attach(request.err); + metavars.clear(); // XXX: redundant. + for(char **p = request.envp; *p; p++) { + const char *e = strchr(*p,'='); + if(!e){ + // XXX: check if we have it already? + metavars[*p] = string(0); + }else{ + int l = e-*p; e++; + // XXX: check if we have it already? + metavars[string(*p,l)]=e; + } + } + } + fcgi_interface::~fcgi_interface() { + sout.flush(); + serr.flush(); + FCGX_Finish_r(&request); + } + +} 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 @@ +#include "kingate/util.h" +#include "kingate/exception.h" + +namespace kingate { + + static const char *safeChars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "_-" ; + + string url_escape(const string& str) { + string rv = str; + string::size_type screwed = 0; + for(;;) { + screwed = rv.find_first_not_of(safeChars,screwed); + if(screwed == string::npos) + break; + while(screwed