summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules/http
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/modules/http')
-rw-r--r--sca-cpp/trunk/modules/http/Makefile.am14
-rw-r--r--sca-cpp/trunk/modules/http/curl-connect.cpp10
-rw-r--r--sca-cpp/trunk/modules/http/curl-get.cpp4
-rw-r--r--sca-cpp/trunk/modules/http/curl-test.cpp19
-rw-r--r--sca-cpp/trunk/modules/http/http.hpp358
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-callgrind25
-rw-r--r--sca-cpp/trunk/modules/http/httpd.hpp181
-rw-r--r--sca-cpp/trunk/modules/http/mod-openauth.cpp269
-rw-r--r--sca-cpp/trunk/modules/http/mod-ssltunnel.cpp72
-rw-r--r--sca-cpp/trunk/modules/http/openauth.hpp39
10 files changed, 570 insertions, 421 deletions
diff --git a/sca-cpp/trunk/modules/http/Makefile.am b/sca-cpp/trunk/modules/http/Makefile.am
index a504adcda5..42504d57ec 100644
--- a/sca-cpp/trunk/modules/http/Makefile.am
+++ b/sca-cpp/trunk/modules/http/Makefile.am
@@ -20,28 +20,28 @@ INCLUDES = -I${HTTPD_INCLUDE}
incl_HEADERS = *.hpp
incldir = $(prefix)/include/modules/http
-dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf basic-auth-conf cert-auth-conf form-auth-conf open-auth-conf passwd-auth-conf group-auth-conf cache-conf cache-ssl-conf cache-manifest proxy-conf proxy-base-conf proxy-ssl-conf proxy-balancer-conf proxy-member-conf proxy-ssl-member-conf proxy-ssl-nossl-member-conf alt-host-conf mass-host-conf mass-host-ssl-conf httpd-tunnel-ssl-conf tunnel-ssl-conf httpd-worker-conf httpd-event-conf httpd-loglevel-conf minify-html minify-js minify-css
+dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf base64-encode basic-auth-conf cert-auth-conf form-auth-conf open-auth-conf passwd-auth-conf group-auth-conf cache-conf cache-ssl-conf cache-manifest proxy-conf proxy-base-conf proxy-ssl-conf proxy-balancer-conf proxy-member-conf proxy-ssl-member-conf proxy-ssl-nossl-member-conf alt-host-conf mass-host-conf mass-host-ssl-conf httpd-tunnel-ssl-conf tunnel-ssl-conf httpd-worker-conf httpd-event-conf httpd-loglevel-conf minify-html minify-js minify-css
moddir = $(prefix)/modules/http
curl_test_SOURCES = curl-test.cpp
-curl_test_LDFLAGS = -lxml2 -lcurl -lmozjs
+curl_test_LDFLAGS = -lxml2 -lcurl -ljansson
curl_get_SOURCES = curl-get.cpp
-curl_get_LDFLAGS = -lxml2 -lcurl -lmozjs
+curl_get_LDFLAGS = -lxml2 -lcurl -ljansson
curl_connect_SOURCES = curl-connect.cpp
-curl_connect_LDFLAGS = -lxml2 -lcurl -lmozjs
+curl_connect_LDFLAGS = -lxml2 -lcurl -ljansson
mod_LTLIBRARIES = libmod_tuscany_ssltunnel.la libmod_tuscany_openauth.la
noinst_DATA = libmod_tuscany_ssltunnel${libsuffix} libmod_tuscany_openauth${libsuffix}
libmod_tuscany_ssltunnel_la_SOURCES = mod-ssltunnel.cpp
-libmod_tuscany_ssltunnel_la_LDFLAGS = -lxml2 -lcurl -lmozjs
+libmod_tuscany_ssltunnel_la_LDFLAGS = -lxml2 -lcurl -ljansson
libmod_tuscany_ssltunnel${libsuffix}:
ln -s .libs/libmod_tuscany_ssltunnel${libsuffix}
libmod_tuscany_openauth_la_SOURCES = mod-openauth.cpp
-libmod_tuscany_openauth_la_LDFLAGS = -lxml2 -lcurl -lmozjs
+libmod_tuscany_openauth_la_LDFLAGS = -lxml2 -lcurl -ljansson
libmod_tuscany_openauth${libsuffix}:
ln -s .libs/libmod_tuscany_openauth${libsuffix}
@@ -82,7 +82,7 @@ modsecuritydir = $(prefix)/modules/http
endif
-dist_noinst_SCRIPTS = httpd-test http-test proxy-test
+dist_noinst_SCRIPTS = httpd-test http-test proxy-test httpd-memgrind httpd-callgrind
noinst_PROGRAMS = curl-test curl-get curl-connect
TESTS = httpd-test http-test proxy-test
diff --git a/sca-cpp/trunk/modules/http/curl-connect.cpp b/sca-cpp/trunk/modules/http/curl-connect.cpp
index 9f5ee17368..6e16da7163 100644
--- a/sca-cpp/trunk/modules/http/curl-connect.cpp
+++ b/sca-cpp/trunk/modules/http/curl-connect.cpp
@@ -34,14 +34,14 @@ namespace tuscany {
namespace http {
const bool testConnect(const string& url, const string& ca = "", const string& cert = "", const string& key = "") {
- gc_scoped_pool p;
+ const gc_scoped_pool p;
- CURLSession cs(ca, cert, key, "", 0);
+ const CURLSession cs(ca, cert, key, "", 0);
const failable<bool> crc = connect(url, cs);
assert(hasContent(crc));
apr_pollset_t* pollset;
- apr_status_t cprc = apr_pollset_create(&pollset, 2, pool(p), 0);
+ const apr_status_t cprc = apr_pollset_create(&pollset, 2, pool(p), 0);
assert(cprc == APR_SUCCESS);
apr_socket_t* csock = sock(0, p);
const apr_pollfd_t* cpollfd = pollfd(csock, APR_POLLIN | APR_POLLERR | APR_POLLNVAL | APR_POLLHUP, p);
@@ -53,7 +53,7 @@ const bool testConnect(const string& url, const string& ca = "", const string& c
const apr_pollfd_t* pollfds;
apr_int32_t pollcount;
for(;;) {
- apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds);
+ const apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds);
assert(pollrc == APR_SUCCESS);
for (; pollcount > 0; pollcount--, pollfds++) {
@@ -88,7 +88,7 @@ const bool testConnect(const string& url, const string& ca = "", const string& c
}
}
-int main(unused const int argc, const char** argv) {
+int main(unused const int argc, const char** const argv) {
if (argc > 2)
tuscany::http::testConnect(tuscany::string(argv[1]), tuscany::string(argv[2]), tuscany::string(argv[3]), tuscany::string(argv[4]));
else
diff --git a/sca-cpp/trunk/modules/http/curl-get.cpp b/sca-cpp/trunk/modules/http/curl-get.cpp
index a16daeeae3..983dd20fc5 100644
--- a/sca-cpp/trunk/modules/http/curl-get.cpp
+++ b/sca-cpp/trunk/modules/http/curl-get.cpp
@@ -33,7 +33,7 @@ namespace tuscany {
namespace http {
const bool testGet(const string& url, const string& ca = "", const string& cert = "", const string& key = "") {
- CURLSession ch(ca, cert, key, "", 0);
+ const CURLSession ch(ca, cert, key, "", 0);
const failable<value> val = get(url, ch);
assert(hasContent(val));
cout << content(val) << endl;
@@ -43,7 +43,7 @@ const bool testGet(const string& url, const string& ca = "", const string& cert
}
}
-int main(unused const int argc, const char** argv) {
+int main(unused const int argc, const char** const argv) {
if (argc > 2)
tuscany::http::testGet(tuscany::string(argv[1]), tuscany::string(argv[2]), tuscany::string(argv[3]), tuscany::string(argv[4]));
else
diff --git a/sca-cpp/trunk/modules/http/curl-test.cpp b/sca-cpp/trunk/modules/http/curl-test.cpp
index f0806ea577..6a1174a404 100644
--- a/sca-cpp/trunk/modules/http/curl-test.cpp
+++ b/sca-cpp/trunk/modules/http/curl-test.cpp
@@ -40,7 +40,7 @@ ostream* curlWriter(const string& s, ostream* os) {
}
const bool testGet() {
- CURLSession ch("", "", "", "", 0);
+ const CURLSession ch("", "", "", "", 0);
{
ostringstream os;
const failable<list<ostream*> > r = get<ostream*>(curlWriter, &os, testURI, ch);
@@ -56,21 +56,14 @@ const bool testGet() {
return true;
}
-struct getLoop {
- CURLSession& ch;
- getLoop(CURLSession& ch) : ch(ch) {
- }
- const bool operator()() const {
+const bool testGetPerf() {
+ const CURLSession ch("", "", "", "", 0);
+ blambda gl = [ch]() -> const bool {
const failable<value> r = getcontent(testURI, ch);
assert(hasContent(r));
assert(contains(car(reverse(list<value>(content(r)))), "It works"));
return true;
- }
-};
-
-const bool testGetPerf() {
- CURLSession ch("", "", "", "", 0);
- lambda<bool()> gl = getLoop(ch);
+ };
cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl;
return true;
}
@@ -79,7 +72,7 @@ const bool testGetPerf() {
}
int main() {
- tuscany::gc_scoped_pool p;
+ const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
//tuscany::http::testURI = tuscany::string("http://") + tuscany::http::hostName() + ":8090";
diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp
index 408b9fdee5..1153f61840 100644
--- a/sca-cpp/trunk/modules/http/http.hpp
+++ b/sca-cpp/trunk/modules/http/http.hpp
@@ -71,86 +71,91 @@ public:
*/
class CURLSession {
public:
- CURLSession() : h(NULL), p(), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(false), ca(""), cert(""), key(""), cookie(""), timeout(0) {
+ CURLSession() : p(), h(*(new (gc_new<handles>()) handles())), owner(false), ca(emptyString), cert(emptyString), key(emptyString), cookie(emptyString), timeout(0) {
}
- CURLSession(const string& ca, const string& cert, const string& key, const string& cookie, const int timeout) : h(NULL), p(), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(true), ca(ca), cert(cert), key(key), cookie(cookie), timeout(timeout) {
+ CURLSession(const string& ca, const string& cert, const string& key, const string& cookie, const int timeout) : p(), h(*(new (gc_new<handles>()) handles())), owner(true), ca(ca), cert(cert), key(key), cookie(cookie), timeout(timeout) {
}
- CURLSession(const CURLSession& c) : h(c.h), p(c.p), sock(c.sock), wpollset(c.wpollset), wpollfd(c.wpollfd), rpollset(c.rpollset), rpollfd(c.rpollfd), owner(false), ca(c.ca), cert(c.cert), key(c.key), cookie(c.cookie), timeout(c.timeout) {
+ CURLSession(const CURLSession& c) : p(c.p), h(c.h), owner(false), ca(c.ca), cert(c.cert), key(c.key), cookie(c.cookie), timeout(c.timeout) {
}
- const CURLSession& operator=(const CURLSession& c) {
- if(this == &c)
- return *this;
- h = c.h;
- p = c.p;
- sock = c.sock;
- wpollset = c.wpollset;
- wpollfd = c.wpollfd;
- rpollset = c.rpollset;
- rpollfd = c.rpollfd;
- owner = false;
- ca = c.ca;
- cert = c.cert;
- key = c.key;
- cookie = c.cookie;
- timeout = c.timeout;
- return *this;
- }
+ CURLSession& operator=(const CURLSession& c) = delete;
~CURLSession() {
if (!owner)
return;
- if (h == NULL)
+ if (h.h == NULL)
return;
- curl_easy_cleanup(h);
+ debug(h.h, "http::~CURLSession::cleanup::h");
+ curl_easy_cleanup(h.h);
}
private:
- CURL* h;
- gc_child_pool p;
- apr_socket_t* sock;
- apr_pollset_t* wpollset;
- apr_pollfd_t* wpollfd;
- apr_pollset_t* rpollset;
- apr_pollfd_t* rpollfd;
- bool owner;
-
- friend CURL* handle(const CURLSession& cs);
- friend apr_socket_t* sock(const CURLSession& cs);
- friend const failable<CURL*> setup(const string& url, CURLSession& cs);
- friend const failable<bool> cleanup(CURLSession& cs);
- friend const failable<bool> connect(const string& url, CURLSession& cs);
- friend const failable<bool> send(const char* c, const size_t l, CURLSession& cs);
- friend const failable<size_t> recv(char* c, const size_t l, CURLSession& cs);
+ class handles {
+ public:
+ handles() : h(NULL), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL) {
+ }
+
+ handles(const handles& c) : h(c.h), sock(c.sock), wpollset(c.wpollset), wpollfd(c.wpollfd), rpollset(c.rpollset), rpollfd(c.rpollfd) {
+ }
+
+ private:
+ CURL* h;
+ apr_socket_t* sock;
+ apr_pollset_t* wpollset;
+ apr_pollfd_t* wpollfd;
+ apr_pollset_t* rpollset;
+ apr_pollfd_t* rpollfd;
+
+ friend class CURLSession;
+ friend CURL* const handle(const CURLSession& cs);
+ friend apr_socket_t* const sock(const CURLSession& cs);
+ friend const failable<CURL*> setup(const string& url, const CURLSession& cs);
+ friend const failable<bool> cleanup(const CURLSession& cs);
+ friend const failable<bool> connect(const string& url, const CURLSession& cs);
+ friend const failable<bool> send(const char* const c, const size_t l, const CURLSession& cs);
+ friend const failable<size_t> recv(char* const c, const size_t l, const CURLSession& cs);
+ };
+
+ const gc_child_pool p;
+ handles& h;
+ const bool owner;
+
+ friend CURL* const handle(const CURLSession& cs);
+ friend apr_socket_t* const sock(const CURLSession& cs);
+ friend const failable<CURL*> setup(const string& url, const CURLSession& cs);
+ friend const failable<bool> cleanup(const CURLSession& cs);
+ friend const failable<bool> connect(const string& url, const CURLSession& cs);
+ friend const failable<bool> send(const char* const c, const size_t l, const CURLSession& cs);
+ friend const failable<size_t> recv(char* const c, const size_t l, const CURLSession& cs);
public:
- string ca;
- string cert;
- string key;
- string cookie;
- int timeout;
+ const string ca;
+ const string cert;
+ const string key;
+ const string cookie;
+ const int timeout;
};
/**
* Returns the CURL handle used by a CURL session.
*/
-CURL* handle(const CURLSession& cs) {
- return cs.h;
+CURL* const handle(const CURLSession& cs) {
+ return cs.h.h;
}
/**
* Return an apr_socket_t for the socket used by a CURL session.
*/
-apr_socket_t* sock(const CURLSession& cs) {
- return cs.sock;
+apr_socket_t* const sock(const CURLSession& cs) {
+ return cs.h.sock;
}
/**
* Convert a socket fd to an apr_socket_t.
*/
-apr_socket_t* sock(const int sd, const gc_pool& p) {
+apr_socket_t* const sock(const int sd, const gc_pool& p) {
int fd = sd;
apr_socket_t* s = NULL;
apr_os_sock_put(&s, &fd, pool(p));
@@ -160,14 +165,14 @@ apr_socket_t* sock(const int sd, const gc_pool& p) {
/**
* Convert a CURL return code to an error string.
*/
-const string curlreason(CURLcode rc) {
+const string curlreason(const CURLcode rc) {
return curl_easy_strerror(rc);
}
/**
* Convert an APR status to an error string.
*/
-const string apreason(apr_status_t rc) {
+const string apreason(const apr_status_t rc) {
char buf[256];
return apr_strerror(rc, buf, sizeof(buf));
}
@@ -178,7 +183,7 @@ const string apreason(apr_status_t rc) {
const char escape_c2x[] = "0123456789ABCDEF";
const string escape(const string& unesc, const char* reserv) {
- char* copy = (char*)apr_palloc(gc_current_pool(), 3 * length(unesc) + 3);
+ char* const copy = (char*)apr_palloc(gc_current_pool(), 3 * length(unesc) + 3);
const unsigned char* s = (const unsigned char *)c_str(unesc);
unsigned char* d = (unsigned char*)copy;
unsigned c;
@@ -225,9 +230,9 @@ const string hostName(const string& uri, const gc_pool& p) {
apr_uri_t u;
const apr_status_t rc = apr_uri_parse(pool(p), c_str(uri), &u);
if (rc != APR_SUCCESS)
- return "";
+ return emptyString;
if (u.hostname == NULL)
- return "";
+ return emptyString;
return u.hostname;
}
@@ -238,9 +243,9 @@ const string scheme(const string& uri, const gc_pool& p) {
apr_uri_t u;
const apr_status_t rc = apr_uri_parse(pool(p), c_str(uri), &u);
if (rc != APR_SUCCESS)
- return "";
+ return emptyString;
if (u.scheme == NULL)
- return "";
+ return emptyString;
return u.scheme;
}
@@ -262,13 +267,14 @@ const string topDomain(const string& host) {
/**
* Setup a CURL session
*/
-const failable<CURL*> setup(const string& url, CURLSession& cs) {
+const failable<CURL*> setup(const string& url, const CURLSession& cs) {
// Init CURL session
- if (cs.h != NULL)
+ if (cs.h.h != NULL)
cleanup(cs);
- cs.h = curl_easy_init();
- CURL* ch = cs.h;
+ cs.h.h = curl_easy_init();
+ debug(cs.h.h, "http::setup::init::h");
+ CURL* const ch = cs.h.h;
curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0");
#ifdef WANT_MAINTAINER_CURL_VERBOSE
curl_easy_setopt(ch, CURLOPT_VERBOSE, true);
@@ -279,34 +285,35 @@ const failable<CURL*> setup(const string& url, CURLSession& cs) {
curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, true);
curl_easy_setopt(ch, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(ch, CURLOPT_DNS_USE_GLOBAL_CACHE, 0);
curl_easy_setopt(ch, CURLOPT_TIMEOUT, cs.timeout);
// Setup SSL options
- if (cs.ca != "") {
+ if (cs.ca != emptyString) {
debug(cs.ca, "http::setup::ca");
curl_easy_setopt(ch, CURLOPT_CAINFO, c_str(cs.ca));
curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, true);
curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, 2);
} else
curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, false);
- if (cs.cert != "") {
+ if (cs.cert != emptyString) {
debug(cs.cert, "http::setup::cert");
curl_easy_setopt(ch, CURLOPT_SSLCERT, c_str(cs.cert));
curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
}
- if (cs.key != "") {
+ if (cs.key != emptyString) {
debug(cs.key, "http::setup::key");
curl_easy_setopt(ch, CURLOPT_SSLKEY, c_str(cs.key));
curl_easy_setopt(ch, CURLOPT_SSLKEYTYPE, "PEM");
}
- if (cs.cookie != "") {
+ if (cs.cookie != emptyString) {
debug(cs.cookie, "http::setup::cookie");
curl_easy_setopt(ch, CURLOPT_COOKIE, c_str(cs.cookie));
}
// Set up HTTP basic auth if requested
apr_uri_t u;
- apr_pool_t* p = gc_current_pool();
+ apr_pool_t* const p = gc_current_pool();
const apr_status_t prc = apr_uri_parse(p, c_str(url), &u);
if (prc == APR_SUCCESS) {
if (u.user != NULL) {
@@ -336,11 +343,12 @@ const failable<CURL*> setup(const string& url, CURLSession& cs) {
/**
* Cleanup a CURL session
*/
-const failable<bool> cleanup(CURLSession& cs) {
- if (cs.h == NULL)
+const failable<bool> cleanup(const CURLSession& cs) {
+ if (cs.h.h == NULL)
return true;
- curl_easy_cleanup(cs.h);
- cs.h = NULL;
+ debug(cs.h.h, "http::cleanup::cleanup::h");
+ curl_easy_cleanup(cs.h.h);
+ cs.h.h = NULL;
return true;
}
@@ -351,15 +359,16 @@ class CURLReadContext {
public:
CURLReadContext(const list<string>& ilist) : ilist(ilist) {
}
- list<string> ilist;
+
+ gc_mutable_ref<list<string> > ilist;
};
/**
* Called by CURL to read data to send.
*/
size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) {
- CURLReadContext& rcx = *static_cast<CURLReadContext*>(data);
- if (isNil(rcx.ilist))
+ CURLReadContext& rcx = *(CURLReadContext*)data;
+ if (isNil((const list<string>)rcx.ilist))
return 0;
const list<string> f(fragment(rcx.ilist, size * nmemb));
const string s = car(f);
@@ -373,17 +382,18 @@ size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) {
*/
template<typename R> class CURLWriteContext {
public:
- CURLWriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
+ CURLWriteContext(const lambda<const R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
}
- const lambda<R(const string&, const R)> reduce;
- R accum;
+
+ const lambda<const R(const string&, const R)> reduce;
+ gc_mutable_ref<R> accum;
};
/**
* Called by CURL to write received data.
*/
template<typename R> size_t writeCallback(void *ptr, size_t size, size_t nmemb, void *data) {
- CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data));
+ CURLWriteContext<R>& wcx = *(CURLWriteContext<R>*)data;
const size_t realsize = size * nmemb;
wcx.accum = wcx.reduce(string((const char*)ptr, realsize), wcx.accum);
return realsize;
@@ -393,13 +403,13 @@ template<typename R> size_t writeCallback(void *ptr, size_t size, size_t nmemb,
* Apply an HTTP verb to a list containing a list of headers and a list of content, and
* a reduce function used to process the response.
*/
-curl_slist* headers(curl_slist* cl, const list<string>& h) {
+curl_slist* headers(curl_slist* const cl, const list<string>& h) {
if (isNil(h))
return cl;
return headers(curl_slist_append(cl, c_str(string(car(h)))), cdr(h));
}
-template<typename R> const failable<list<R> > apply(const list<list<string> >& hdr, const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, const string& verb, CURLSession& cs) {
+template<typename R> const failable<list<R> > apply(const list<list<string> >& hdr, const lambda<const R(const string&, const R)>& reduce, const R& initial, const string& url, const string& verb, const CURLSession& cs) {
debug(url, "http::apply::url");
debug(verb, "http::apply::verb");
@@ -409,12 +419,12 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h
cleanup(cs);
return mkfailure<list<R>>(fch);
}
- CURL* ch = content(fch);
+ CURL* const ch = content(fch);
// Set the request headers
curl_slist* hl = headers(NULL, car(hdr));
- if (hl != NULL)
- curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl);
+ hl = curl_slist_append(hl, "X-Accept: text/x-scheme; charset=utf-8");
+ curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl);
// Convert request body to a string
// TODO use HTTP chunking instead
@@ -462,9 +472,7 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h
curl_easy_getinfo (ch, CURLINFO_RESPONSE_CODE, &httprc);
if (httprc != 200 && httprc != 201) {
cleanup(cs);
- ostringstream es;
- es << "HTTP code " << httprc;
- return mkfailure<list<R> >(str(es));
+ return mkfailure<list<R> >(string("HTTP code not 200"), (int)httprc, (httprc != 301 && httprc != 302 && httprc != 404));
}
cleanup(cs);
@@ -474,13 +482,12 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h
/**
* Evaluate an expression remotely, at the given URL.
*/
-const failable<value> evalExpr(const value& expr, const string& url, CURLSession& cs) {
+const failable<value> evalExpr(const value& expr, const string& url, const CURLSession& cs) {
debug(url, "http::evalExpr::url");
debug(expr, "http::evalExpr::input");
// Convert expression to a JSON-RPC request
- js::JSContext cx;
- const failable<list<string> > jsreq = json::jsonRequest(1, car<value>(expr), cdr<value>(expr), cx);
+ const failable<list<string> > jsreq = json::jsonRequest(1, car<value>(expr), cdr<value>(expr));
if (!hasContent(jsreq))
return mkfailure<value>(jsreq);
@@ -491,7 +498,7 @@ const failable<value> evalExpr(const value& expr, const string& url, CURLSession
return mkfailure<value>(res);
// Parse and return JSON-RPC result
- const failable<value> rval = json::jsonResultValue(cadr<list<string> >(content(res)), cx);
+ const failable<value> rval = json::jsonResultValue(cadr<list<string> >(content(res)));
debug(rval, "http::evalExpr::result");
if (!hasContent(rval))
return mkfailure<value>(rval);
@@ -501,7 +508,7 @@ const failable<value> evalExpr(const value& expr, const string& url, CURLSession
/**
* Find and return a header.
*/
-const maybe<string> header(const char* prefix, const list<string>& h) {
+const maybe<string> header(const char* const prefix, const list<string>& h) {
if (isNil(h))
return maybe<string>();
const string s = car(h);
@@ -516,7 +523,7 @@ const maybe<string> header(const char* prefix, const list<string>& h) {
*/
const string location(const list<string>& h) {
const maybe<string> l = header("Location: ", h);
- return hasContent(l)? content(l) : "";
+ return hasContent(l)? content(l) : emptyString;
}
/**
@@ -524,7 +531,7 @@ const string location(const list<string>& h) {
*/
const value entryId(const failable<string> l) {
if (!hasContent(l))
- return list<value>();
+ return nilListValue;
const string ls(content(l));
return value(mklist<value>(string(substr(ls, find_last(ls, '/') + 1))));
}
@@ -534,13 +541,13 @@ const value entryId(const failable<string> l) {
*/
const string contentType(const list<string>& h) {
const maybe<string> ct = header("Content-Type: ", h);
- return hasContent(ct)? content(ct) : "";
+ return hasContent(ct)? content(ct) : emptyString;
}
/**
* HTTP GET, return the resource at the given URL.
*/
-template<typename R> const failable<list<R> > get(const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, CURLSession& cs) {
+template<typename R> const failable<list<R> > get(const lambda<const R(const string&, const R)>& reduce, const R& initial, const string& url, const CURLSession& cs) {
debug(url, "http::get::url");
const list<list<string> > req = mklist(list<string>(), list<string>());
return apply(req, reduce, initial, url, "GET", cs);
@@ -549,7 +556,7 @@ template<typename R> const failable<list<R> > get(const lambda<R(const string&,
/**
* HTTP GET, return a list of values representing the resource at the given URL.
*/
-const failable<value> getcontent(const string& url, CURLSession& cs) {
+const failable<value> getcontent(const string& url, const CURLSession& cs) {
debug(url, "http::get::url");
// Get the contents of the resource at the given URL
@@ -576,6 +583,15 @@ const failable<value> responseValue(const list<list<string> > res) {
const list<string> ls(reverse(cadr(res)));
debug(ls, "http::responseValue::content");
+ if (contains(ct, "text/x-scheme")) {
+ // Read a Scheme value
+ ostringstream os;
+ write(ls, os);
+ istringstream is(str(os));
+ const value val(content(scheme::readValue(is)));
+ debug(val, "http::responseValue::result");
+ return val;
+ }
if (atom::isATOMEntry(ls)) {
// Read an ATOM entry
const value val(elementsToValues(content(atom::readATOMEntry(ls))));
@@ -596,8 +612,7 @@ const failable<value> responseValue(const list<list<string> > res) {
}
if (contains(ct, "text/javascript") || contains(ct, "application/json") || json::isJSON(ls)) {
// Read a JSON document
- js::JSContext cx;
- const value val(json::jsonValues(content(json::readJSON(ls, cx))));
+ const value val(content(json::readValue(ls)));
debug(val, "http::responseValue::result");
return val;
}
@@ -612,14 +627,13 @@ const failable<value> responseValue(const list<list<string> > res) {
const list<string> jls = mklist<string>(substr(s, fp + 1, lp - (fp + 1)));
debug(jls, "http::responseValue::javascript::content");
- js::JSContext cx;
- const value val(json::jsonValues(content(json::readJSON(jls, cx))));
+ const value val(content(json::readValue(jls)));
debug(val, "http::responseValue::result");
return val;
}
- if (contains(ct, "text/xml") || contains(ct, "application/xml") || isXML(ls)) {
+ if (contains(ct, "text/xml") || contains(ct, "application/xml") || xml::isXML(ls)) {
// Read an XML document
- const value val(elementsToValues(readXML(ls)));
+ const value val(elementsToValues(content(xml::readElements(ls))));
debug(val, "http::responseValue::result");
return val;
}
@@ -633,7 +647,7 @@ const failable<value> responseValue(const list<list<string> > res) {
/**
* HTTP GET, return a list of values representing the resource at the given URL.
*/
-const failable<value> get(const string& url, CURLSession& cs) {
+const failable<value> get(const string& url, const CURLSession& cs) {
debug(url, "http::get::url");
// Get the contents of the resource at the given URL
@@ -661,58 +675,41 @@ const failable<list<list<string> > > writeRequest(const failable<list<string> >&
*/
const failable<list<list<string> > > contentRequest(const value& c, unused const string& url) {
- // Check if the client requested a specific format
- //TODO derive that from given URL
- const list<value> fmt = assoc<value>("format", list<value>());
-
- // Write as a scheme value if requested by the client
- if (!isNil(fmt) && cadr(fmt) == "scheme")
- return writeRequest(mklist<string>(scheme::writeValue(c)), "text/plain; charset=utf-8");
+ // Write in the format requested by the client, if any
+ const list<value> fmt = assoc<value>("format", nilListValue);
+ if (!isNil(fmt)) {
+ if (cadr(fmt) == "scheme")
+ return writeRequest(scheme::writeValue(c), "text/x-scheme; charset=utf-8");
+ if (cadr(fmt) == "json")
+ return writeRequest(json::writeValue(c), "application/json; charset=utf-8");
+ if (cadr(fmt) == "xml")
+ return writeRequest(xml::writeElements(valuesToElements(c)), "text/xml; charset=utf-8");
+ }
// Write a simple value as a JSON value
if (!isList(c)) {
- js::JSContext cx;
- if (isSymbol(c)) {
- const list<value> lc = mklist<value>(mklist<value>("name", value(string(c))));
- debug(lc, "http::contentRequest::symbol");
- return writeRequest(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8");
- }
- const list<value> lc = mklist<value>(mklist<value>("value", c));
- debug(lc, "http::contentRequest::value");
- return writeRequest(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8");
+ debug(c, "http::contentRequest::value");
+ return writeRequest(json::writeValue(c), "application/json; charset=utf-8");
}
- // Write an empty list as a JSON empty value
+ // Write an empty list as a JSON value
if (isNil((list<value>)c)) {
- js::JSContext cx;
- debug(list<value>(), "http::contentRequest::empty");
- return writeRequest(json::writeJSON(list<value>(), cx), "application/json; charset=utf-8");
+ debug(nilListValue, "http::contentRequest::empty");
+ return writeRequest(json::writeValue(c), "application/json; charset=utf-8");
}
// Write content-type / content-list pair
if (isString(car<value>(c)) && !isNil(cdr<value>(c)) && isList(cadr<value>(c)))
return writeRequest(convertValues<string>(cadr<value>(c)), car<value>(c));
- // Write an assoc value as JSON
+ // Write an assoc value as a JSON value
if (isSymbol(car<value>(c)) && !isNil(cdr<value>(c))) {
- js::JSContext cx;
- const list<value> lc = mklist<value>(c);
- debug(lc, "http::contentRequest::assoc");
- debug(valuesToElements(lc), "http::contentRequest::assoc::element");
- return writeRequest(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8");
- }
-
- // Write value as JSON if requested by the client
- if (!isNil(fmt) && cadr(fmt) == "json") {
- js::JSContext cx;
- return writeRequest(json::writeJSON(valuesToElements(c), cx), "application/json; charset=utf-8");
+ debug(c, "http::contentRequest::assoc");
+ return writeRequest(json::writeValue(c), "application/json; charset=utf-8");
}
- // Convert list of values to element values
- const list<value> e = valuesToElements(c);
- debug(e, "http::contentRequest::elements");
-
// Write an ATOM feed or entry
+ const list<value> e = valuesToElements(c);
if (isList(car<value>(e)) && !isNil(car<value>(e))) {
const list<value> el = car<value>(e);
if (isSymbol(car<value>(el)) && car<value>(el) == element && !isNil(cdr<value>(el)) && isSymbol(cadr<value>(el)) && elementHasChildren(el) && !elementHasValue(el)) {
@@ -724,14 +721,13 @@ const failable<list<list<string> > > contentRequest(const value& c, unused const
}
// Write any other compound value as a JSON value
- js::JSContext cx;
- return writeRequest(json::writeJSON(e, cx), "application/json; charset=utf-8");
+ return writeRequest(json::writeValue(c), "application/json; charset=utf-8");
}
/**
* HTTP POST.
*/
-const failable<value> post(const value& val, const string& url, CURLSession& cs) {
+const failable<value> post(const value& val, const string& url, const CURLSession& cs) {
debug(url, "http::post::url");
// Convert value to a content request
@@ -760,7 +756,7 @@ const failable<value> post(const value& val, const string& url, CURLSession& cs)
/**
* HTTP PUT.
*/
-const failable<value> put(const value& val, const string& url, CURLSession& cs) {
+const failable<value> put(const value& val, const string& url, const CURLSession& cs) {
debug(url, "http::put::url");
// Convert value to a content request
@@ -775,13 +771,13 @@ const failable<value> put(const value& val, const string& url, CURLSession& cs)
return mkfailure<value>(res);
debug(true, "http::put::result");
- return value(true);
+ return trueValue;
}
/**
* HTTP PATCH.
*/
-const failable<value> patch(const value& val, const string& url, CURLSession& cs) {
+const failable<value> patch(const value& val, const string& url, const CURLSession& cs) {
debug(url, "http::put::patch");
// Convert value to a content request
@@ -796,13 +792,13 @@ const failable<value> patch(const value& val, const string& url, CURLSession& cs
return mkfailure<value>(res);
debug(true, "http::patch::result");
- return value(true);
+ return trueValue;
}
/**
* HTTP DELETE.
*/
-const failable<value, string> del(const string& url, CURLSession& cs) {
+const failable<value, string> del(const string& url, const CURLSession& cs) {
debug(url, "http::delete::url");
const list<list<string> > req = mklist(list<string>(), list<string>());
@@ -811,7 +807,7 @@ const failable<value, string> del(const string& url, CURLSession& cs) {
return mkfailure<value>(res);
debug(true, "http::delete::result");
- return value(true);
+ return trueValue;
}
/**
@@ -827,7 +823,7 @@ const string hostName() {
/**
* Create an APR pollfd for a socket.
*/
-apr_pollfd_t* pollfd(apr_socket_t* s, const int e, const gc_pool& p) {
+apr_pollfd_t* const pollfd(apr_socket_t* const s, const int e, const gc_pool& p) {
apr_pollfd_t* pfd = gc_new<apr_pollfd_t>(p);
pfd->p = pool(p);
pfd->desc_type = APR_POLL_SOCKET;
@@ -841,7 +837,7 @@ apr_pollfd_t* pollfd(apr_socket_t* s, const int e, const gc_pool& p) {
/**
* Connect to a URL.
*/
-const failable<bool> connect(const string& url, CURLSession& cs) {
+const failable<bool> connect(const string& url, const CURLSession& cs) {
debug(url, "http::connect::url");
// Setup the CURL session
@@ -850,7 +846,7 @@ const failable<bool> connect(const string& url, CURLSession& cs) {
cleanup(cs);
return mkfailure<bool>(fch);
}
- CURL* ch = content(fch);
+ CURL* const ch = content(fch);
// Connect
curl_easy_setopt(ch, CURLOPT_CONNECT_ONLY, true);
@@ -867,23 +863,23 @@ const failable<bool> connect(const string& url, CURLSession& cs) {
cleanup(cs);
return mkfailure<bool>(string(curl_easy_strerror(grc)));
}
- cs.sock = sock(sd, cs.p);
+ cs.h.sock = sock(sd, cs.p);
// Create pollsets and pollfds which can be used to poll the socket
- apr_status_t rpcrc = apr_pollset_create(&cs.rpollset, 1, pool(cs.p), 0);
+ const apr_status_t rpcrc = apr_pollset_create(&cs.h.rpollset, 1, pool(cs.p), 0);
if (rpcrc != APR_SUCCESS) {
cleanup(cs);
return mkfailure<bool>(apreason(rpcrc));
}
- cs.rpollfd = pollfd(cs.sock, APR_POLLIN, cs.p);
- apr_pollset_add(cs.rpollset, cs.rpollfd);
- apr_status_t wpcrc = apr_pollset_create(&cs.wpollset, 1, pool(cs.p), 0);
+ cs.h.rpollfd = pollfd(cs.h.sock, APR_POLLIN, cs.p);
+ apr_pollset_add(cs.h.rpollset, cs.h.rpollfd);
+ const apr_status_t wpcrc = apr_pollset_create(&cs.h.wpollset, 1, pool(cs.p), 0);
if (wpcrc != APR_SUCCESS) {
cleanup(cs);
return mkfailure<bool>(apreason(wpcrc));
}
- cs.wpollfd = pollfd(cs.sock, APR_POLLOUT, cs.p);
- apr_pollset_add(cs.wpollset, cs.wpollfd);
+ cs.h.wpollfd = pollfd(cs.h.sock, APR_POLLOUT, cs.p);
+ apr_pollset_add(cs.h.wpollset, cs.h.wpollfd);
return true;
}
@@ -891,11 +887,11 @@ const failable<bool> connect(const string& url, CURLSession& cs) {
/**
* Send an array of chars.
*/
-const failable<bool> send(const char* c, const size_t l, CURLSession& cs) {
+const failable<bool> send(const char* const c, const size_t l, const CURLSession& cs) {
// Send the data
size_t wl = 0;
- const CURLcode rc = curl_easy_send(cs.h, c, (size_t)l, &wl);
+ const CURLcode rc = curl_easy_send(cs.h.h, c, (size_t)l, &wl);
if (rc == CURLE_OK && wl == (size_t)l)
return true;
if (rc != CURLE_AGAIN) {
@@ -906,7 +902,7 @@ const failable<bool> send(const char* c, const size_t l, CURLSession& cs) {
// If the socket was not ready, wait for it to become ready
const apr_pollfd_t* pollfds;
apr_int32_t pollcount;
- apr_status_t pollrc = apr_pollset_poll(cs.wpollset, -1, &pollcount, &pollfds);
+ const apr_status_t pollrc = apr_pollset_poll(cs.h.wpollset, -1, &pollcount, &pollfds);
if (pollrc != APR_SUCCESS)
return mkfailure<bool>(apreason(pollrc));
@@ -917,11 +913,11 @@ const failable<bool> send(const char* c, const size_t l, CURLSession& cs) {
/**
* Receive an array of chars.
*/
-const failable<size_t> recv(char* c, const size_t l, CURLSession& cs) {
+const failable<size_t> recv(char* const c, const size_t l, const CURLSession& cs) {
// Receive data
size_t rl;
- const CURLcode rc = curl_easy_recv(cs.h, c, (size_t)l, &rl);
+ const CURLcode rc = curl_easy_recv(cs.h.h, c, (size_t)l, &rl);
if (rc == CURLE_OK)
return (size_t)rl;
if (rc == 1)
@@ -934,7 +930,7 @@ const failable<size_t> recv(char* c, const size_t l, CURLSession& cs) {
// If the socket was not ready, wait for it to become ready
const apr_pollfd_t* pollfds;
apr_int32_t pollcount;
- apr_status_t pollrc = apr_pollset_poll(cs.rpollset, -1, &pollcount, &pollfds);
+ const apr_status_t pollrc = apr_pollset_poll(cs.h.rpollset, -1, &pollcount, &pollfds);
if (pollrc != APR_SUCCESS) {
cleanup(cs);
return mkfailure<size_t>(apreason(pollrc));
@@ -990,8 +986,9 @@ const value escapeQuery(const value& arg) {
/**
* HTTP client proxy function.
*/
-struct proxy {
- proxy(const string& uri, const string& ca, const string& cert, const string& key, const string& cookie, const int timeout, const gc_pool& p) : p(p), uri(uri), ca(ca), cert(cert), key(key), cookie(cookie), cs(*(new (gc_new<CURLSession>(p)) CURLSession(ca, cert, key, cookie, timeout))) {
+class proxy {
+public:
+ proxy(const string& uri, const string& ca, const string& cert, const string& key, const string& cookie, const int timeout) : uri(uri), cs(mksession(ca, cert, key, cookie, timeout)) {
}
const value operator()(const list<value>& args) const {
@@ -1001,39 +998,44 @@ struct proxy {
const list<value> lp = filter<value>(filterPath, cadr(args));
debug(lp, "http::proxy::path");
const list<value> lq = map<value, value>(escapeQuery, filter<value>(filterQuery, cadr(args)));
- debug(lp, "http::proxy::query");
- const value p = path(lp);
+ debug(lq, "http::proxy::query");
const value q = queryString(lq);
- const failable<value> val = get(uri + p + (q != ""? string("?") + q : string("")), cs);
+ const failable<value> val = get(uri + (string)path(lp) + (q != emptyString? string("?") + (string)q : emptyString), *cs);
return content(val);
}
if (fun == "post") {
- const failable<value> val = post(caddr(args), uri + path(cadr(args)), cs);
+ const failable<value> val = post(caddr(args), uri + (string)path(cadr(args)), *cs);
return content(val);
}
if (fun == "put") {
- const failable<value> val = put(caddr(args), uri + path(cadr(args)), cs);
+ const failable<value> val = put(caddr(args), uri + (string)path(cadr(args)), *cs);
return content(val);
}
if (fun == "patch") {
- const failable<value> val = patch(caddr(args), uri + path(cadr(args)), cs);
+ const failable<value> val = patch(caddr(args), uri + (string)path(cadr(args)), *cs);
return content(val);
}
if (fun == "delete") {
- const failable<value> val = del(uri + path(cadr(args)), cs);
+ const failable<value> val = del(uri + (string)path(cadr(args)), *cs);
return content(val);
}
- const failable<value> val = evalExpr(args, uri, cs);
+ const failable<value> val = evalExpr(args, uri, *cs);
return content(val);
}
- const gc_pool p;
+private:
const string uri;
- const string ca;
- const string cert;
- const string key;
- const string cookie;
- CURLSession& cs;
+ const perthread_ptr<http::CURLSession> cs;
+
+
+ const perthread_ptr<http::CURLSession> mksession(const string& ca, const string& cert, const string& key, const string& cookie, const int timeout) {
+ const gc_pool cp = gc_current_pool();
+ const lambda<const gc_ptr<http::CURLSession>()> newsession = [ca, cert, key, cookie, timeout, cp]() -> const gc_ptr<http::CURLSession> {
+ const gc_scoped_pool sp(pool(cp));
+ return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, cookie, timeout);
+ };
+ return *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<CURLSession>(newsession));
+ }
};
}
diff --git a/sca-cpp/trunk/modules/http/httpd-callgrind b/sca-cpp/trunk/modules/http/httpd-callgrind
new file mode 100755
index 0000000000..964b046638
--- /dev/null
+++ b/sca-cpp/trunk/modules/http/httpd-callgrind
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Start httpd server
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+httpd=`cat $here/httpd.prefix`
+$here/../../etc/callgrind $httpd/bin/httpd -X -E $root/logs/error_log -d $root -f $root/conf/httpd.conf
diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp
index 6470d6c587..e090c2fc35 100644
--- a/sca-cpp/trunk/modules/http/httpd.hpp
+++ b/sca-cpp/trunk/modules/http/httpd.hpp
@@ -46,14 +46,14 @@ extern "C" {
#include <http_request.h>
// Ignore conversion warnings in HTTPD 2.3.15 header
#ifdef WANT_MAINTAINER_WARNINGS
-#ifndef IS_DARWIN
+#ifndef __clang__
#pragma GCC diagnostic ignored "-Wconversion"
#endif
#endif
#include <http_protocol.h>
// Re-enable conversion warnings
#ifdef WANT_MAINTAINER_WARNINGS
-#ifndef IS_DARWIN
+#ifndef __clang__
#pragma GCC diagnostic warning "-Wconversion"
#endif
#endif
@@ -94,15 +94,15 @@ template<typename C> void* makeServerConf(apr_pool_t* p, server_rec* s) {
return new (gc_new<C>(p)) C(p, s);
}
-template<typename C> const C& serverConf(const request_rec* r, const module* mod) {
+template<typename C> const C& serverConf(const request_rec* const r, const module* const mod) {
return *(C*)ap_get_module_config(r->server->module_config, mod);
}
-template<typename C> C& serverConf(const server_rec* s, const module* mod) {
+template<typename C> C& serverConf(const server_rec* const s, const module* const mod) {
return *(C*)ap_get_module_config(s->module_config, mod);
}
-template<typename C> C& serverConf(const cmd_parms* cmd, const module* mod) {
+template<typename C> C& serverConf(const cmd_parms* const cmd, const module* const mod) {
return *(C*)ap_get_module_config(cmd->server->module_config, mod);
}
@@ -113,25 +113,25 @@ template<typename C> void* makeDirConf(apr_pool_t *p, char* d) {
return new (gc_new<C>(p)) C(p, d);
}
-template<typename C> const C& dirConf(const request_rec* r, const module* mod) {
+template<typename C> const C& dirConf(const request_rec* const r, const module* const mod) {
return *(C*)ap_get_module_config(r->per_dir_config, mod);
}
-template<typename C> C& dirConf(const void* c) {
+template<typename C> C& dirConf(const void* const c) {
return *(C*)c;
}
/**
* Returns a request-scoped module configuration.
*/
-template<typename C> C& makeRequestConf(const request_rec* r, const module* mod) {
- C* c = new (gc_new<C>(r->pool)) C(r->pool, r);
+template<typename C> C& makeRequestConf(const request_rec* const r, const module* const mod) {
+ C* const c = new (gc_new<C>(r->pool)) C(r->pool, r);
ap_set_module_config(r->request_config, mod, c);
return *c;
}
-template<typename C> C& requestConf(const request_rec* r, const module* mod) {
- C* c = (C*)ap_get_module_config(r->request_config, mod);
+template<typename C> C& requestConf(const request_rec* const r, const module* const mod) {
+ C* const c = (C*)ap_get_module_config(r->request_config, mod);
if (c == NULL)
return makeRequestConf<C>(r, mod);
return *c;
@@ -140,18 +140,18 @@ template<typename C> C& requestConf(const request_rec* r, const module* mod) {
/**
* Return the host name for a server.
*/
-const string hostName(const server_rec* s, const string& def = "localhost") {
+const string hostName(const server_rec* const s, const string& def = "localhost") {
return s->server_hostname != NULL? s->server_hostname : def;
}
/**
* Return the host name from an HTTP request.
*/
-const string hostName(request_rec* r, const string& def = "localhost") {
- const char* fh = apr_table_get(r->headers_in, "X-Forwarded-Server");
+const string hostName(request_rec* const r, const string& def = "localhost") {
+ const char* const fh = apr_table_get(r->headers_in, "X-Forwarded-Server");
if (fh != NULL)
return fh;
- const char* h = ap_get_server_name(r);
+ const char* const h = ap_get_server_name(r);
return h != NULL? h : (r->server->server_hostname != NULL? r->server->server_hostname : def);
}
@@ -166,15 +166,15 @@ const string realm(const string& host) {
/**
* Return the protocol scheme for a server.
*/
-const string scheme(const server_rec* s, const string& def = "http") {
+const string scheme(const server_rec* const s, const string& def = "http") {
return s->server_scheme != NULL? s->server_scheme : def;
}
/**
* Return the protocol scheme from an HTTP request.
*/
-const string scheme(request_rec* r, const string& def = "http") {
- const char* fs = apr_table_get(r->headers_in, "X-Forwarded-HTTPS");
+const string scheme(const request_rec* const r, const string& def = "http") {
+ const char* const fs = apr_table_get(r->headers_in, "X-Forwarded-HTTPS");
if (fs != NULL)
return !strcmp(fs, "on")? "https" : "http";
return r->server->server_scheme != NULL? r->server->server_scheme : def;
@@ -183,15 +183,15 @@ const string scheme(request_rec* r, const string& def = "http") {
/**
* Return the port number for a server.
*/
-const int port(const server_rec* s, const int def = 80) {
+const int port(const server_rec* const s, const int def = 80) {
return s->port != 0? s->port : def;
}
/**
* Return the port number from an HTTP request.
*/
-const int port(request_rec* r, const int def = 80) {
- const char* fp = apr_table_get(r->headers_in, "X-Forwarded-Port");
+const int port(const request_rec* const r, const int def = 80) {
+ const char* const fp = apr_table_get(r->headers_in, "X-Forwarded-Port");
if (fp != NULL)
return atoi(fp);
const int p = ap_get_server_port(r);
@@ -201,7 +201,7 @@ const int port(request_rec* r, const int def = 80) {
/**
* Return the name of a server.
*/
-const string serverName(const server_rec* s, const string& def = "localhost") {
+const string serverName(server_rec* const s, const string& def = "localhost") {
ostringstream n;
const string sc = scheme(s);
const string h = hostName(s, def);
@@ -209,14 +209,14 @@ const string serverName(const server_rec* s, const string& def = "localhost") {
n << sc << "://" << h;
if (!((sc == "http" && p == 80) || (sc == "https" && p == 443)))
n << ":" << p;
- n << (s->path != NULL? string(s->path, s->pathlen) : "");
+ n << (s->path != NULL? string(s->path, s->pathlen) : emptyString);
return str(n);
}
/**
* Determine the name of a server from an HTTP request.
*/
-const string serverName(request_rec* r, const string& def = "localhost") {
+const string serverName(request_rec* const r, const string& def = "localhost") {
ostringstream n;
const string s = scheme(r);
const string h = hostName(r, def);
@@ -224,14 +224,14 @@ const string serverName(request_rec* r, const string& def = "localhost") {
n << s << "://" << h;
if (!((s == "http" && p == 80) || (s == "https" && p == 443)))
n << ":" << p;
- n << (r->server->path != NULL? string(r->server->path, r->server->pathlen) : "");
+ n << (r->server->path != NULL? string(r->server->path, r->server->pathlen) : emptyString);
return str(n);
}
/**
* Return true if a request is targeting a virtual host.
*/
-const bool isVhostRequest(const server_rec* s, const string& d, request_rec* r) {
+const bool isVhostRequest(const server_rec* const s, const string& d, request_rec* const r) {
const string rh = hostName(r);
return rh != hostName(s) && http::topDomain(rh) == d;
}
@@ -239,20 +239,20 @@ const bool isVhostRequest(const server_rec* s, const string& d, request_rec* r)
/**
* Return the content type of a request.
*/
-const string contentType(const request_rec* r) {
+const string contentType(const request_rec* const r) {
const char* ct = apr_table_get(r->headers_in, "Content-Type");
if (ct == NULL)
- return "";
+ return emptyString;
return ct;
}
/**
* Return the cookie header of a request.
*/
-const string cookie(const request_rec* r) {
+const string cookie(const request_rec* const r) {
const char* c = apr_table_get(r->headers_in, "Cookie");
if (c == NULL)
- return "";
+ return emptyString;
return c;
}
@@ -268,7 +268,7 @@ const list<value> pathInfo(const list<value>& uri, const list<value>& path) {
/**
* Convert a URI to an absolute URL.
*/
-const string url(const string& uri, request_rec* r) {
+const string url(const string& uri, request_rec* const r) {
if (contains(uri, "://"))
return uri;
ostringstream n;
@@ -285,8 +285,8 @@ const string url(const string& uri, request_rec* r) {
/**
* Convert a URI and a path to an absolute URL.
*/
-const string url(const string& uri, const list<value>& p, request_rec* r) {
- return url(uri + path(p), r);
+const string url(const string& uri, const list<value>& p, request_rec* const r) {
+ return url(uri + (string)path(p), r);
}
/**
@@ -295,7 +295,7 @@ const string url(const string& uri, const list<value>& p, request_rec* r) {
const char escape_c2x[] = "0123456789ABCDEF";
const string escape(const string& uri) {
debug(uri, "httpd::escape::uri");
- char* copy = (char*)apr_palloc(gc_current_pool(), 3 * length(uri) + 3);
+ char* const copy = (char*)apr_palloc(gc_current_pool(), 3 * length(uri) + 3);
const unsigned char* s = (const unsigned char *)c_str(uri);
unsigned char* d = (unsigned char*)copy;
unsigned c;
@@ -321,7 +321,7 @@ const string escape(const string& uri) {
*/
const string unescape(const string& uri) {
debug(uri, "httpd::unescape::uri");
- char* b = const_cast<char*>(c_str(string(c_str(uri))));
+ char* const b = const_cast<char*>(c_str(string(c_str(uri))));
ap_unescape_url(b);
debug(b, "httpd::unescape::result");
return b;
@@ -348,7 +348,7 @@ const list<value> queryArg(const string& s) {
debug(s, "httpd::queryArg::string");
const list<string> t = tokenize("=", s);
if (isNil(cdr(t)))
- return mklist<value>(c_str(car(t)), "");
+ return mklist<value>(c_str(car(t)), emptyString);
return mklist<value>(c_str(car(t)), cadr(t));
}
@@ -366,7 +366,7 @@ const list<list<value> > queryArgs(const string& a) {
/**
* Returns a list of key value pairs from the args in an HTTP request.
*/
-const list<list<value> > queryArgs(const request_rec* r) {
+const list<list<value> > queryArgs(const request_rec* const r) {
if (r->args == NULL)
return list<list<value> >();
return queryArgs(r->args);
@@ -385,7 +385,7 @@ const list<list<value> > postArgs(const list<value>& a) {
/**
* Setup the HTTP read policy.
*/
-const int setupReadPolicy(request_rec* r) {
+const int setupReadPolicy(request_rec* const r) {
const int rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
if(rc != OK)
return rc;
@@ -399,7 +399,7 @@ const int setupReadPolicy(request_rec* r) {
/**
* Read the content of a POST or PUT.
*/
-const list<string> read(request_rec* r) {
+const list<string> read(request_rec* const r) {
char b[1024];
const size_t n = ap_get_client_block(r, b, sizeof(b));
if (n <= 0)
@@ -410,7 +410,7 @@ const list<string> read(request_rec* r) {
/**
* Write an HTTP result.
*/
-const failable<int> writeResult(const failable<list<string> >& ls, const string& ct, request_rec* r) {
+const failable<int> writeResult(const failable<list<string> >& ls, const string& ct, request_rec* const r) {
if (!hasContent(ls))
return mkfailure<int>(ls);
ostringstream os;
@@ -456,16 +456,16 @@ const int reportStatus(const failable<int>& rc) {
}
/**
- * Convert a value to an HTTPD request struc
+ * Convert a value to an HTTPD request struct.
*/
request_rec* request(const value& v) {
return (request_rec*)(long)(double)v;
}
/**
- * Convert an HTTPD request struct to a value
+ * Convert an HTTPD request struct to a value.
*/
-const value requestValue(request_rec* r) {
+const value requestValue(const request_rec* const r) {
return value((double)(long)r);
}
@@ -473,19 +473,37 @@ const value requestValue(request_rec* r) {
* Update request filters in an HTTPD redirect request.
* Similar to httpd/modules/http/http_request.c::update_r_in_filters.
*/
-const bool redirectFilters(ap_filter_t* f, request_rec* from, request_rec* to) {
- if (f == NULL)
- return true;
- if (f->r == from)
- f->r = to;
- return redirectFilters(f->next, from, to);
+const bool internalUpdateFilters(ap_filter_t *f, const request_rec* const from, request_rec* const to) {
+ while(f) {
+ if(f->r == from)
+ f->r = to;
+ f = f->next;
+ }
+ return true;
+}
+
+/**
+ * Rename original env in an HTTPD redirect request.
+ * Similar to httpd/modules/http/http_request.c::rename_original_env.
+ */
+apr_table_t* const internalRenameOriginalEnv(apr_pool_t* const p, apr_table_t* const t) {
+ const apr_array_header_t *env_arr = apr_table_elts(t);
+ const apr_table_entry_t *elts = (const apr_table_entry_t *) (void*)env_arr->elts;
+ apr_table_t *nt = apr_table_make(p, env_arr->nalloc);
+ int i;
+ for(i = 0; i < env_arr->nelts; ++i) {
+ if (!elts[i].key)
+ continue;
+ apr_table_setn(nt, apr_pstrcat(p, "REDIRECT_", elts[i].key, NULL), elts[i].val);
+ }
+ return nt;
}
/**
* Create an HTTPD internal redirect request.
* Similar to httpd/modules/http/http_request.c::internal_internal_redirect.
*/
-const failable<request_rec*> internalRedirectRequest(const string& nr_uri, request_rec* r) {
+const failable<request_rec*> internalRedirectRequest(const string& nr_uri, request_rec* const r) {
if (ap_is_recursion_limit_exceeded(r))
return mkfailure<request_rec*>("Redirect recursion limit exceeded", HTTP_INTERNAL_SERVER_ERROR);
@@ -498,11 +516,15 @@ const failable<request_rec*> internalRedirectRequest(const string& nr_uri, reque
nr->method_number = r->method_number;
nr->allowed_methods = ap_make_method_list(nr->pool, 2);
ap_parse_uri(nr, apr_pstrdup(nr->pool, c_str(nr_uri)));
+ nr->parsed_uri.port_str = r->parsed_uri.port_str;
+ nr->parsed_uri.port = r->parsed_uri.port;
nr->filename = apr_pstrdup(nr->pool, c_str(string("/redirected:") + nr_uri));
nr->request_config = ap_create_request_config(r->pool);
nr->per_dir_config = r->server->lookup_defaults;
nr->prev = r;
r->next = nr;
+ nr->useragent_addr = r->useragent_addr;
+ nr->useragent_ip = r->useragent_ip;
// Run create request hook
ap_run_create_request(nr);
@@ -520,10 +542,15 @@ const failable<request_rec*> internalRedirectRequest(const string& nr_uri, reque
nr->main = r->main;
nr->headers_in = r->headers_in;
nr->headers_out = apr_table_make(r->pool, 12);
+ if (ap_is_HTTP_REDIRECT(nr->status)) {
+ const char *location = apr_table_get(r->headers_out, "Location");
+ if (location)
+ apr_table_setn(nr->headers_out, "Location", location);
+ }
nr->err_headers_out = r->err_headers_out;
nr->subprocess_env = r->subprocess_env;
+ nr->subprocess_env = internalRenameOriginalEnv(r->pool, r->subprocess_env);
nr->notes = apr_table_make(r->pool, 5);
- nr->allowed_methods = ap_make_method_list(nr->pool, 2);
nr->htaccess = r->htaccess;
nr->no_cache = r->no_cache;
nr->expecting_100 = r->expecting_100;
@@ -537,10 +564,28 @@ const failable<request_rec*> internalRedirectRequest(const string& nr_uri, reque
nr->proto_input_filters = r->proto_input_filters;
nr->output_filters = nr->proto_output_filters;
nr->input_filters = nr->proto_input_filters;
- if (nr->main)
- ap_add_output_filter_handle(ap_subreq_core_filter_handle, NULL, nr, nr->connection);
- redirectFilters(nr->input_filters, r, nr);
- redirectFilters(nr->output_filters, r, nr);
+ if (nr->main) {
+ ap_filter_t *f, *nextf;
+ nr->output_filters = r->output_filters;
+ f = nr->output_filters;
+ do {
+ nextf = f->next;
+ if (f->r == r && f->frec != ap_subreq_core_filter_handle) {
+ f->r = nr;
+ ap_remove_output_filter(f);
+ }
+ f = nextf;
+ } while(f && f != nr->proto_output_filters);
+ }
+ else {
+ nr->output_filters = nr->proto_output_filters;
+ }
+ internalUpdateFilters(nr->input_filters, r, nr);
+ internalUpdateFilters(nr->output_filters, r, nr);
+
+ apr_table_setn(nr->subprocess_env, "REDIRECT_STATUS", apr_itoa(r->pool, r->status));
+ nr->used_path_info = AP_REQ_DEFAULT_PATH_INFO;
+
const int rrc = ap_run_post_read_request(nr);
if (rrc != OK && rrc != DECLINED)
return mkfailure<request_rec*>("Error handling internal redirect", rrc);
@@ -552,7 +597,7 @@ const failable<request_rec*> internalRedirectRequest(const string& nr_uri, reque
* Process an HTTPD internal redirect request.
* Similar to httpd/modules/http/http_request.c::ap_internal_redirect.
*/
-const int internalRedirect(request_rec* nr) {
+const int internalRedirect(request_rec* const nr) {
int status = ap_run_quick_handler(nr, 0);
if (status == DECLINED) {
status = ap_process_request_internal(nr);
@@ -570,8 +615,10 @@ const int internalRedirect(request_rec* nr) {
/**
* Create and process an HTTPD internal redirect request.
*/
-const int internalRedirect(const string& uri, request_rec* r) {
+const int internalRedirect(const string& uri, request_rec* const r) {
debug(uri, "httpd::internalRedirect");
+ //ap_internal_redirect(c_str(uri), r);
+ //return OK;
const failable<request_rec*> nr = httpd::internalRedirectRequest(uri, r);
if (!hasContent(nr))
return rcode(nr);
@@ -582,7 +629,7 @@ const int internalRedirect(const string& uri, request_rec* r) {
* Create an HTTPD sub request.
* Similar to httpd/server/request.c::make_sub_request
*/
-const failable<request_rec*> internalSubRequest(const string& nr_uri, request_rec* r) {
+const failable<request_rec*> internalSubRequest(const string& nr_uri, request_rec* const r) {
if (ap_is_recursion_limit_exceeded(r))
return mkfailure<request_rec*>("Redirect recursion limit exceeded", HTTP_INTERNAL_SERVER_ERROR);
@@ -647,7 +694,7 @@ const failable<request_rec*> internalSubRequest(const string& nr_uri, request_re
/**
* Return an HTTP external redirect request.
*/
-const int externalRedirect(const string& uri, request_rec* r) {
+const int externalRedirect(const string& uri, request_rec* const r) {
debug(uri, "httpd::externalRedirect");
r->status = HTTP_MOVED_TEMPORARILY;
apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(uri)));
@@ -660,7 +707,7 @@ const int externalRedirect(const string& uri, request_rec* r) {
/**
* Put a value in the process user data.
*/
-const bool putUserData(const string& k, const void* v, const server_rec* s) {
+const bool putUserData(const string& k, const void* const v, const server_rec* const s) {
apr_pool_userdata_set((const void *)v, c_str(k), apr_pool_cleanup_null, s->process->pool);
return true;
}
@@ -668,7 +715,7 @@ const bool putUserData(const string& k, const void* v, const server_rec* s) {
/**
* Return a user data value.
*/
-const void* userData(const string& k, const server_rec* s) {
+const void* const userData(const string& k, const server_rec* const s) {
void* v = NULL;
apr_pool_userdata_get(&v, c_str(k), s->process->pool);
return v;
@@ -683,7 +730,7 @@ const void* userData(const string& k, const server_rec* s) {
/**
* Log an optional value.
*/
-const char* debugOptional(const char* s) {
+const char* const debugOptional(const char* const s) {
if (s == NULL)
return "";
return s;
@@ -692,7 +739,7 @@ const char* debugOptional(const char* s) {
/**
* Log a header
*/
-int debugHeader(unused void* r, const char* key, const char* value) {
+int debugHeader(unused void* r, const char* const key, const char* const value) {
cdebug << " header key: " << key << ", value: " << value << endl;
return 1;
}
@@ -700,7 +747,7 @@ int debugHeader(unused void* r, const char* key, const char* value) {
/**
* Log an environment variable
*/
-int debugEnv(unused void* r, const char* key, const char* value) {
+int debugEnv(unused void* r, const char* const key, const char* const value) {
cdebug << " var key: " << key << ", value: " << value << endl;
return 1;
}
@@ -708,7 +755,7 @@ int debugEnv(unused void* r, const char* key, const char* value) {
/**
* Log a note.
*/
-int debugNote(unused void* r, const char* key, const char* value) {
+int debugNote(unused void* r, const char* const key, const char* const value) {
cdebug << " note key: " << key << ", value: " << value << endl;
return 1;
}
@@ -716,8 +763,8 @@ int debugNote(unused void* r, const char* key, const char* value) {
/**
* Log a request.
*/
-const bool debugRequest(request_rec* r, const string& msg) {
- gc_scoped_pool pool;
+const bool debugRequest(request_rec* const r, const string& msg) {
+ const gc_scoped_pool pool;
cdebug << msg << ":" << endl;
cdebug << " unparsed uri: " << debugOptional(r->unparsed_uri) << endl;
cdebug << " uri: " << debugOptional(r->uri) << endl;
diff --git a/sca-cpp/trunk/modules/http/mod-openauth.cpp b/sca-cpp/trunk/modules/http/mod-openauth.cpp
index 2e308ecedb..797e8c10b5 100644
--- a/sca-cpp/trunk/modules/http/mod-openauth.cpp
+++ b/sca-cpp/trunk/modules/http/mod-openauth.cpp
@@ -57,11 +57,11 @@ namespace openauth {
*/
class ServerConf {
public:
- ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) {
+ ServerConf(apr_pool_t* const p, server_rec* const s) : p(p), server(s) {
}
const gc_pool p;
- server_rec* server;
+ server_rec* const server;
};
/**
@@ -71,11 +71,11 @@ class AuthnProviderConf {
public:
AuthnProviderConf() : name(), provider(NULL) {
}
- AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) {
+ AuthnProviderConf(const string name, const authn_provider* const provider) : name(name), provider(provider) {
}
- string name;
- const authn_provider* provider;
+ const string name;
+ const authn_provider* const provider;
};
/**
@@ -83,14 +83,14 @@ public:
*/
class DirConf {
public:
- DirConf(apr_pool_t* p, char* d) : p(p), dir(d), enabled(false), login("") {
+ DirConf(apr_pool_t* const p, const char* d) : p(p), dir(d), enabled(false), login(emptyString) {
}
const gc_pool p;
- const char* dir;
+ const char* const dir;
bool enabled;
- string login;
- list<AuthnProviderConf> apcs;
+ gc_mutable_ref<string> login;
+ gc_mutable_ref<list<AuthnProviderConf> > apcs;
};
#ifdef WANT_MAINTAINER_LOG
@@ -98,17 +98,17 @@ public:
/**
* Log session entries.
*/
-int debugSessionEntry(unused void* r, const char* key, const char* value) {
+int debugSessionEntry(unused void* r, const char* const key, const char* const value) {
cdebug << " session key: " << key << ", value: " << value << endl;
return 1;
}
-const bool debugSession(request_rec* r, session_rec* z) {
+const bool debugSession(request_rec* const r, const session_rec* const z) {
apr_table_do(debugSessionEntry, r, z->entries, NULL);
return true;
}
-#define debug_authSession(r, z) if (debug_islogging()) openauth::debugSession(r, z)
+#define debug_authSession(r, z) if(debug_islogging()) openauth::debugSession(r, z)
#else
@@ -117,28 +117,35 @@ const bool debugSession(request_rec* r, session_rec* z) {
#endif
/**
+ * Session hook functions.
+ */
+static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL;
+static apr_status_t (*ap_session_get_fn) (request_rec * r, session_rec * z, const char *key, const char **value) = NULL;
+static apr_status_t (*ap_session_set_fn)(request_rec * r, session_rec * z, const char *key, const char *value) = NULL;
+
+/**
* Run the authnz hooks to authenticate a request.
*/
-const failable<int> checkAuthnzProviders(const string& user, const string& pw, request_rec* r, const list<AuthnProviderConf>& apcs) {
- if (isNil(apcs))
- return mkfailure<int>("Authentication failure for: " + user);
+const failable<int> checkAuthnzProviders(const string& user, const string& pw, request_rec* const r, const list<AuthnProviderConf>& apcs) {
+ if(isNil(apcs))
+ return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED);
const AuthnProviderConf apc = car<AuthnProviderConf>(apcs);
- if (apc.provider == NULL || !apc.provider->check_password)
+ if(apc.provider == NULL || !apc.provider->check_password)
return checkAuthnzProviders(user, pw, r, cdr(apcs));
apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, c_str(apc.name));
const authn_status auth_result = apc.provider->check_password(r, c_str(user), c_str(pw));
apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
- if (auth_result != AUTH_GRANTED)
+ if(auth_result != AUTH_GRANTED)
return checkAuthnzProviders(user, pw, r, cdr(apcs));
return OK;
}
-const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* r, const DirConf& dc) {
- if (substr(user, 0, 1) == "/" && pw == "password")
+const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* const r, const DirConf& dc) {
+ if(substr(user, 0, 1) == "/" && pw == "password")
return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED);
- if (isNil(dc.apcs)) {
+ if(isNil((const list<AuthnProviderConf>)dc.apcs)) {
const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION);
return checkAuthnzProviders(user, pw, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider)));
}
@@ -148,54 +155,47 @@ const failable<int> checkAuthnz(const string& user, const string& pw, request_re
/**
* Return the user info from a form auth encrypted session cookie.
*/
-static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL;
-static int (*ap_session_get_fn) (request_rec * r, session_rec * z, const char *key, const char **value) = NULL;
-
-const failable<value> userInfoFromSession(const string& realm, request_rec* r) {
+const failable<value> userInfoFromSession(const string& realm, request_rec* const r) {
debug("modopenauth::userInfoFromSession");
- if (ap_session_load_fn == NULL)
- ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load);
session_rec *z = NULL;
ap_session_load_fn(r, &z);
- if (z == NULL)
- return mkfailure<value>("Couldn't retrieve user session");
+ if(z == NULL)
+ return mkfailure<value>("Couldn't retrieve user session", HTTP_UNAUTHORIZED);
debug_authSession(r, z);
- if (ap_session_get_fn == NULL)
- ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get);
const char* user = NULL;
ap_session_get_fn(r, z, c_str(realm + "-user"), &user);
- if (user == NULL)
- return mkfailure<value>("Couldn't retrieve user id");
+ if(user == NULL)
+ return mkfailure<value>("Couldn't retrieve user id", HTTP_UNAUTHORIZED);
const char* pw = NULL;
ap_session_get_fn(r, z, c_str(realm + "-pw"), &pw);
- if (pw == NULL)
- return mkfailure<value>("Couldn't retrieve password");
+ if(pw == NULL)
+ return mkfailure<value>("Couldn't retrieve password", HTTP_UNAUTHORIZED);
return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", string(user)), mklist<value>("password", string(pw))));
}
/**
* Return the user info from a form auth session cookie.
*/
-const failable<value> userInfoFromCookie(const value& sid, const string& realm, request_rec* r) {
+const failable<value> userInfoFromCookie(const value& sid, const string& realm, request_rec* const r) {
const list<list<value>> info = httpd::queryArgs(sid);
debug(info, "modopenauth::userInfoFromCookie::info");
const list<value> user = assoc<value>(realm + "-user", info);
- if (isNil(user))
+ if(isNil(user))
return userInfoFromSession(realm, r);
const list<value> pw = assoc<value>(realm + "-pw", info);
- if (isNil(pw))
- return mkfailure<value>("Couldn't retrieve password");
+ if(isNil(pw))
+ return mkfailure<value>("Couldn't retrieve password", HTTP_UNAUTHORIZED);
return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", cadr(user)), mklist<value>("password", cadr(pw))));
}
/**
* Return the user info from a basic auth header.
*/
-const failable<value> userInfoFromHeader(const char* header, const string& realm, request_rec* r) {
+const failable<value> userInfoFromHeader(const char* header, const string& realm, request_rec* const r) {
debug(header, "modopenauth::userInfoFromHeader::header");
- if (strcasecmp(ap_getword(r->pool, &header, ' '), "Basic"))
- return mkfailure<value>("Wrong authentication scheme");
+ if(strcasecmp(ap_getword(r->pool, &header, ' '), "Basic"))
+ return mkfailure<value>("Wrong authentication scheme", HTTP_UNAUTHORIZED);
while (apr_isspace(*header))
header++;
@@ -212,18 +212,18 @@ const failable<value> userInfoFromHeader(const char* header, const string& realm
/**
* Handle an authenticated request.
*/
-const failable<int> authenticated(const list<list<value> >& info, request_rec* r) {
+const failable<int> authenticated(const list<list<value> >& info, request_rec* const r) {
debug(info, "modopenauth::authenticated::info");
// Store user info in the request
const list<value> realm = assoc<value>("realm", info);
- if (isNil(realm) || isNil(cdr(realm)))
- return mkfailure<int>("Couldn't retrieve realm");
+ if(isNil(realm) || isNil(cdr(realm)))
+ return mkfailure<int>("Couldn't retrieve realm", HTTP_UNAUTHORIZED);
apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "REALM"), apr_pstrdup(r->pool, c_str(cadr(realm))));
const list<value> id = assoc<value>("id", info);
- if (isNil(id) || isNil(cdr(id)))
- return mkfailure<int>("Couldn't retrieve user id");
+ if(isNil(id) || isNil(cdr(id)))
+ return mkfailure<int>("Couldn't retrieve user id", HTTP_UNAUTHORIZED);
r->user = apr_pstrdup(r->pool, c_str(cadr(id)));
apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "NICKNAME"), apr_pstrdup(r->pool, c_str(cadr(id))));
@@ -233,127 +233,113 @@ const failable<int> authenticated(const list<list<value> >& info, request_rec* r
/**
* Check user authentication.
*/
-static int checkAuthn(request_rec *r) {
- gc_scoped_pool pool(r->pool);
+static int checkAuthn(request_rec* const r) {
+ const gc_scoped_pool sp(r->pool);
// Decline if we're not enabled or AuthType is not set to Open
const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
- if (!dc.enabled)
+ if(!dc.enabled)
return DECLINED;
const char* atype = ap_auth_type(r);
- if (atype == NULL || strcasecmp(atype, "Open"))
- return DECLINED;
debug_httpdRequest(r, "modopenauth::checkAuthn::input");
debug(atype, "modopenauth::checkAuthn::auth_type");
+ if(atype == NULL || strcasecmp(atype, "Open"))
+ return DECLINED;
+ debug(atype, "modopenauth::checkAuthn::auth_type");
// Get the request args
const list<list<value> > args = httpd::queryArgs(r);
// Get session id from the request
const maybe<string> sid = sessionID(r, "TuscanyOpenAuth");
- if (hasContent(sid)) {
+ if(hasContent(sid)) {
// Decline if the session id was not created by this module
const string stype = substr(content(sid), 0, 7);
- if (stype == "OAuth2_" || stype == "OAuth1_" || stype == "OpenID_")
+ if(stype == "OAuth2_" || stype == "OAuth1_" || stype == "OpenID_")
return DECLINED;
// Retrieve the auth realm
const char* aname = ap_auth_name(r);
- if (aname == NULL)
- return httpd::reportStatus(mkfailure<int>("Missing AuthName"));
+ if(aname == NULL)
+ return reportStatus(mkfailure<int>("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r);
// Extract user info from the session id
const failable<value> userinfo = userInfoFromCookie(content(sid), aname, r);
- if (hasContent(userinfo)) {
+ if(hasContent(userinfo)) {
// Try to authenticate the request
const value uinfo = content(userinfo);
const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc);
- if (!hasContent(authz)) {
+ if(!hasContent(authz)) {
// Authentication failed, redirect to login page
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(login(dc.login, value(), 1, r));
+ return reportStatus(authz, dc.login, 1, r);
}
// Successfully authenticated, store the user info in the request
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authenticated(uinfo, r));
+ return reportStatus(authenticated(uinfo, r), dc.login, nilValue, r);
}
}
// Get basic auth header from the request
- const char* header = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" : "Authorization");
- if (header != NULL) {
+ const char* const header = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" : "Authorization");
+ if(header != NULL) {
// Retrieve the auth realm
- const char* aname = ap_auth_name(r);
- if (aname == NULL)
- return httpd::reportStatus(mkfailure<int>("Missing AuthName"));
+ const char* const aname = ap_auth_name(r);
+ if(aname == NULL)
+ return reportStatus(mkfailure<int>("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r);
// Extract user info from the session id
const failable<value> info = userInfoFromHeader(header, aname, r);
- if (hasContent(info)) {
+ if(hasContent(info)) {
// Try to authenticate the request
const value uinfo = content(info);
const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc);
- if (!hasContent(authz)) {
+ if(!hasContent(authz)) {
// Authentication failed, redirect to login page
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(login(dc.login, value(), 1, r));
+ return reportStatus(authz, dc.login, 1, r);
}
// Successfully authenticated, store the user info in the request
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(authenticated(uinfo, r));
+ return reportStatus(authenticated(uinfo, r), dc.login, nilValue, r);
}
}
// Decline if the request is for another authentication provider
- if (!isNil(assoc<value>("openid_identifier", args)))
+ if(!isNil(assoc<value>("openid_identifier", args)))
return DECLINED;
// Redirect to the login page, unless we have a session id from another module
- if (hasContent(sessionID(r, "TuscanyOpenIDAuth")) ||
+ if(hasContent(sessionID(r, "TuscanyOpenIDAuth")) ||
hasContent(sessionID(r, "TuscanyOAuth1")) ||
hasContent(sessionID(r, "TuscanyOAuth2")))
return DECLINED;
r->ap_auth_type = const_cast<char*>(atype);
- return httpd::reportStatus(login(dc.login, value(), value(), r));
+ return httpd::reportStatus(login(dc.login, nilValue, nilValue, r));
}
/**
- * Save the auth session cookie in the response.
- */
-static int sessionCookieSave(request_rec* r, session_rec* z) {
- gc_scoped_pool pool(r->pool);
-
- const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
- if (!dc.enabled)
- return DECLINED;
-
- debug(c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))), "modopenauth::setcookie");
- apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))));
- return OK;
-}
-
-/**
- * Load the auth session cookie from the request. Similar
+ * Load the auth session cookie from the request.
*/
-static int sessionCookieLoad(request_rec* r, session_rec** z) {
- gc_scoped_pool pool(r->pool);
+static int sessionCookieLoad(request_rec* const r, session_rec** const z) {
+ const gc_scoped_pool sp(r->pool);
const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
- if (!dc.enabled)
+ if(!dc.enabled)
return DECLINED;
// First look in the notes
- const char* note = apr_pstrcat(r->pool, "mod_openauth", "TuscanyOpenAuth", NULL);
+ const char* const note = apr_pstrcat(r->pool, "mod_openauth", "TuscanyOpenAuth", NULL);
session_rec* zz = (session_rec*)(void*)apr_table_get(r->notes, note);
- if (zz != NULL) {
+ if(zz != NULL) {
*z = zz;
return OK;
}
@@ -376,22 +362,86 @@ static int sessionCookieLoad(request_rec* r, session_rec** z) {
}
/**
+ * Save the auth session cookie in the response.
+ */
+static int sessionCookieSave(request_rec* const r, session_rec* const z) {
+ const gc_scoped_pool sp(r->pool);
+
+ const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
+ if(!dc.enabled)
+ return DECLINED;
+ if(z->encoded == NULL || *(z->encoded) == '\0') {
+ const maybe<string> sid = sessionID(r, "TuscanyOpenAuth");
+ if(!hasContent(sid))
+ return OK;
+ }
+
+ debug(c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))), "modopenauth::sessioncookiesave::setcookie");
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))));
+ return OK;
+}
+
+/**
+ * Logout request handler.
+ */
+int logoutHandler(request_rec* const r) {
+ if(r->handler == NULL || strcmp(r->handler, "mod_tuscany_openauth_logout"))
+ return DECLINED;
+
+ const gc_scoped_pool sp(r->pool);
+ debug_httpdRequest(r, "modopenauth::handler::input");
+ const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
+ if(!dc.enabled)
+ return DECLINED;
+
+ // Clear the current session
+ if(hasContent(sessionID(r, "TuscanyOpenAuth"))) {
+ const char* const authname = ap_auth_name(r);
+ session_rec* z = NULL;
+ ap_session_load_fn(r, &z);
+ if(z != NULL && authname != NULL) {
+ ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-user", NULL), NULL);
+ ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-pw", NULL), NULL);
+ ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-site", NULL), NULL);
+ } else
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", emptyString, httpd::hostName(r))));
+ }
+ if(hasContent(sessionID(r, "TuscanyOpenIDAuth")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenIDAuth", emptyString, httpd::hostName(r))));
+ if(hasContent(sessionID(r, "TuscanyOAuth1")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth1", emptyString, httpd::hostName(r))));
+ if(hasContent(sessionID(r, "TuscanyOAuth2")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth2", emptyString, httpd::hostName(r))));
+
+ // Redirect to the login page
+ return httpd::reportStatus(login(dc.login, "/", nilValue, r));
+}
+
+/**
* Process the module configuration.
*/
-int postConfigMerge(ServerConf& mainsc, server_rec* s) {
- if (s == NULL)
+int postConfigMerge(const ServerConf& mainsc, server_rec* const s) {
+ if(s == NULL)
return OK;
debug(httpd::serverName(s), "modopenauth::postConfigMerge::serverName");
return postConfigMerge(mainsc, s->next);
}
-int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) {
- gc_scoped_pool pool(p);
+int postConfig(apr_pool_t* const p, unused apr_pool_t* const plog, unused apr_pool_t* const ptemp, server_rec* const s) {
+ const gc_scoped_pool sp(p);
- ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_openauth);
+ const ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_openauth);
debug(httpd::serverName(s), "modopenauth::postConfig::serverName");
+ // Retrieve session hook functions
+ if(ap_session_load_fn == NULL)
+ ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load);
+ if(ap_session_get_fn == NULL)
+ ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get);
+ if(ap_session_set_fn == NULL)
+ ap_session_set_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_set);
+
// Merge server configurations
return postConfigMerge(sc, s);
}
@@ -399,15 +449,15 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp,
/**
* Child process initialization.
*/
-void childInit(apr_pool_t* p, server_rec* s) {
- gc_scoped_pool pool(p);
+void childInit(apr_pool_t* const p, server_rec* const s) {
+ const gc_scoped_pool sp(p);
- ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_openauth);
+ const ServerConf* const psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_openauth);
if(psc == NULL) {
cfailure << "[Tuscany] Due to one or more errors mod_tuscany_openauth loading failed. Causing apache to stop loading." << endl;
exit(APEXIT_CHILDFATAL);
}
- ServerConf& sc = *psc;
+ const ServerConf& sc = *psc;
// Merge the updated configuration into the virtual hosts
postConfigMerge(sc, s->next);
@@ -416,27 +466,27 @@ void childInit(apr_pool_t* p, server_rec* s) {
/**
* Configuration commands.
*/
-const char* confEnabled(cmd_parms *cmd, void *c, const int arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confEnabled(cmd_parms* cmd, void *c, const int arg) {
+ const gc_scoped_pool sp(cmd->pool);
DirConf& dc = httpd::dirConf<DirConf>(c);
dc.enabled = (bool)arg;
return NULL;
}
-const char* confLogin(cmd_parms *cmd, void *c, const char* arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confLogin(cmd_parms *cmd, void *c, const char* arg) {
+ const gc_scoped_pool sp(cmd->pool);
DirConf& dc = httpd::dirConf<DirConf>(c);
dc.login = arg;
return NULL;
}
-const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
+ const gc_scoped_pool sp(cmd->pool);
DirConf& dc = httpd::dirConf<DirConf>(c);
// Lookup and cache the Authn provider
const authn_provider* provider = (authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, arg, AUTHN_PROVIDER_VERSION);
- if (provider == NULL)
+ if(provider == NULL)
return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg);
- if (!provider->check_password)
+ if(!provider->check_password)
return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support password authentication", arg);
dc.apcs = append<AuthnProviderConf>(dc.apcs, mklist<AuthnProviderConf>(AuthnProviderConf(arg, provider)));
return NULL;
@@ -458,6 +508,7 @@ void registerHooks(unused apr_pool_t *p) {
ap_hook_check_authn(checkAuthn, NULL, NULL, APR_HOOK_MIDDLE, AP_AUTH_INTERNAL_PER_CONF);
ap_hook_session_load(sessionCookieLoad, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_session_save(sessionCookieSave, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_handler(logoutHandler, NULL, NULL, APR_HOOK_MIDDLE);
}
}
diff --git a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp
index b66cd29959..0a9ebc1a80 100644
--- a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp
+++ b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp
@@ -53,17 +53,17 @@ namespace modssltunnel {
*/
class ServerConf {
public:
- ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) {
+ ServerConf(apr_pool_t* const p, server_rec* const s) : p(p), server(s) {
}
const gc_pool p;
- server_rec* server;
- string pass;
- string host;
- string path;
- string ca;
- string cert;
- string key;
+ server_rec* const server;
+ gc_mutable_ref<string> pass;
+ gc_mutable_ref<string> host;
+ gc_mutable_ref<string> path;
+ gc_mutable_ref<string> ca;
+ gc_mutable_ref<string> cert;
+ gc_mutable_ref<string> key;
};
extern "C" {
@@ -74,7 +74,7 @@ extern module AP_DECLARE_DATA core_module;
* Process the module configuration.
*/
int M_SSLTUNNEL;
-int postConfigMerge(ServerConf& mainsc, apr_pool_t* p, server_rec* s) {
+int postConfigMerge(const ServerConf& mainsc, apr_pool_t* const p, server_rec* const s) {
if (s == NULL)
return OK;
ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel);
@@ -102,10 +102,10 @@ int postConfigMerge(ServerConf& mainsc, apr_pool_t* p, server_rec* s) {
return postConfigMerge(mainsc, p, s->next);
}
-int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) {
- gc_scoped_pool pool(p);
+int postConfig(apr_pool_t* const p, unused apr_pool_t* const plog, unused apr_pool_t* const ptemp, server_rec* const s) {
+ const gc_scoped_pool sp(p);
- ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel);
+ const ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel);
debug(httpd::serverName(s), "modssltunnel::postConfig::serverName");
// Register the SSLTUNNEL method
@@ -118,7 +118,7 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp,
/**
* Close a connection.
*/
-const int close(conn_rec* conn, apr_socket_t* csock) {
+const int close(conn_rec* const conn, apr_socket_t* const csock) {
debug("modssltunnel::close");
apr_socket_close(csock);
conn->aborted = 1;
@@ -128,7 +128,7 @@ const int close(conn_rec* conn, apr_socket_t* csock) {
/**
* Abort a connection.
*/
-const int abort(conn_rec* conn, apr_socket_t* csock, const string& reason) {
+const int abort(conn_rec* const conn, apr_socket_t* const csock, const string& reason) {
debug("modssltunnel::abort");
apr_socket_close(csock);
conn->aborted = 1;
@@ -138,21 +138,21 @@ const int abort(conn_rec* conn, apr_socket_t* csock, const string& reason) {
/**
* Tunnel traffic from a client connection to a target URL.
*/
-int tunnel(conn_rec* conn, const string& ca, const string& cert, const string& key, const string& url, const string& preamble, const gc_pool& p, unused ap_filter_t* ifilter, ap_filter_t* ofilter) {
+int tunnel(conn_rec* const conn, const string& ca, const string& cert, const string& key, const string& url, const string& preamble, const gc_pool& p, unused ap_filter_t* const ifilter, ap_filter_t* const ofilter) {
// Create input/output bucket brigades
- apr_bucket_brigade* ib = apr_brigade_create(pool(p), conn->bucket_alloc);
- apr_bucket_brigade* ob = apr_brigade_create(pool(p), conn->bucket_alloc);
+ apr_bucket_brigade* const ib = apr_brigade_create(pool(p), conn->bucket_alloc);
+ apr_bucket_brigade* const ob = apr_brigade_create(pool(p), conn->bucket_alloc);
// Get client connection socket
- apr_socket_t* csock = (apr_socket_t*)ap_get_module_config(conn->conn_config, &core_module);
+ apr_socket_t* const csock = (apr_socket_t*)ap_get_module_config(conn->conn_config, &core_module);
// Open connection to target
- http::CURLSession cs(ca, cert, key, "", 0);
+ const http::CURLSession cs(ca, cert, key, emptyString, 0);
const failable<bool> crc = http::connect(url, cs);
if (!hasContent(crc))
return abort(conn, csock, reason(crc));
- apr_socket_t* tsock = http::sock(cs);
+ apr_socket_t* const tsock = http::sock(cs);
// Send preamble
if (length(preamble) != 0) {
@@ -164,7 +164,7 @@ int tunnel(conn_rec* conn, const string& ca, const string& cert, const string& k
// Create a pollset for the client and target sockets
apr_pollset_t* pollset;
- apr_status_t cprc = apr_pollset_create(&pollset, 2, pool(p), 0);
+ const apr_status_t cprc = apr_pollset_create(&pollset, 2, pool(p), 0);
if (cprc != APR_SUCCESS)
return abort(conn, csock, http::apreason(cprc));
const apr_pollfd_t* cpollfd = http::pollfd(csock, APR_POLLIN, p);
@@ -241,7 +241,7 @@ int tunnel(conn_rec* conn, const string& ca, const string& cert, const string& k
// Poll the client and target sockets
debug("modssltunnel::tunnel::poll");
- apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds);
+ const apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds);
if (pollrc != APR_SUCCESS)
return abort(conn, csock, "Couldn't poll sockets");
debug(pollcount, "modssltunnel::tunnel::pollfds");
@@ -254,7 +254,7 @@ int tunnel(conn_rec* conn, const string& ca, const string& cert, const string& k
/**
* Return the first connection filter in a list of filters.
*/
-ap_filter_t* connectionFilter(ap_filter_t* f) {
+ap_filter_t* const connectionFilter(ap_filter_t* const f) {
if (f == NULL)
return f;
if (f->frec->ftype < AP_FTYPE_CONNECTION)
@@ -265,14 +265,14 @@ ap_filter_t* connectionFilter(ap_filter_t* f) {
/**
* Process a client connection and relay it to a tunnel.
*/
-int processConnection(conn_rec *conn) {
+int processConnection(conn_rec* conn) {
// Only allow configured virtual hosts
if (!conn->base_server->is_virtual)
return DECLINED;
if (ap_get_module_config(conn->base_server->module_config, &mod_tuscany_ssltunnel) == NULL)
return DECLINED;
- gc_scoped_pool pool(conn->pool);
+ const gc_scoped_pool sp(conn->pool);
// Get the server configuration
const ServerConf& sc = httpd::serverConf<ServerConf>(conn->base_server, &mod_tuscany_ssltunnel);
@@ -297,41 +297,41 @@ int handler(request_rec* r) {
if (strcmp(r->server->server_scheme, "https"))
return DECLINED;
- gc_scoped_pool pool(r->pool);
+ const gc_scoped_pool sp(r->pool);
// Build the target URL
debug(r->uri, "modssltunnel::handler::uri");
const list<value> path(pathValues(r->uri));
- const string url = string(cadr(path)) + ":" + caddr(path);
+ const string url = string(cadr(path)) + ":" + (string)caddr(path);
debug(url, "modssltunnel::handler::target");
// Run the tunnel
- return tunnel(r->connection, "", "", "", url, "", gc_pool(r->pool), connectionFilter(r->proto_input_filters), connectionFilter(r->proto_output_filters));
+ return tunnel(r->connection, emptyString, emptyString, emptyString, url, emptyString, gc_pool(r->pool), connectionFilter(r->proto_input_filters), connectionFilter(r->proto_output_filters));
}
/**
* Configuration commands.
*/
-const char* confTunnelPass(cmd_parms *cmd, unused void *c, const char *arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confTunnelPass(cmd_parms *cmd, unused void *c, const char *arg) {
+ const gc_scoped_pool sp(cmd->pool);
ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_ssltunnel);
sc.pass = arg;
return NULL;
}
-const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) {
+ const gc_scoped_pool sp(cmd->pool);
ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_ssltunnel);
sc.ca = arg;
return NULL;
}
-const char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) {
+ const gc_scoped_pool sp(cmd->pool);
ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_ssltunnel);
sc.cert = arg;
return NULL;
}
-const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) {
- gc_scoped_pool pool(cmd->pool);
+char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) {
+ const gc_scoped_pool sp(cmd->pool);
ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_ssltunnel);
sc.key = arg;
return NULL;
diff --git a/sca-cpp/trunk/modules/http/openauth.hpp b/sca-cpp/trunk/modules/http/openauth.hpp
index 3ffa88d362..dcf405d487 100644
--- a/sca-cpp/trunk/modules/http/openauth.hpp
+++ b/sca-cpp/trunk/modules/http/openauth.hpp
@@ -42,11 +42,12 @@ namespace openauth {
/**
* Return the session id from a request.
*/
-const char* cookieName(const char* cs) {
+const char* const cookieName(const char* const cs) {
if (*cs != ' ')
return cs;
return cookieName(cs + 1);
}
+
const maybe<string> sessionID(const list<string>& c, const string& key) {
if (isNil(c))
return maybe<string>();
@@ -62,7 +63,7 @@ const maybe<string> sessionID(const list<string>& c, const string& key) {
return sessionID(cdr(c), key);
}
-const maybe<string> sessionID(const request_rec* r, const string& key) {
+const maybe<string> sessionID(const request_rec* const r, const string& key) {
const string c = httpd::cookie(r);
debug(c, "openauth::sessionid::cookies");
if (length(c) == 0)
@@ -74,10 +75,15 @@ const maybe<string> sessionID(const request_rec* r, const string& key) {
* Convert a session id to a cookie string.
*/
const string cookie(const string& key, const string& sid, const string& domain) {
+ if (length(sid) == 0) {
+ const string c = key + string("=") + "; max-age=0; domain=." + httpd::realm(domain) + "; path=/; secure; httponly";
+ debug(c, "openauth::cookie");
+ return c;
+ }
const time_t t = time(NULL) + 86400;
char exp[32];
strftime(exp, 32, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime(&t));
- const string c = key + string("=") + sid + "; expires=" + string(exp) + "; domain=." + httpd::realm(domain) + "; path=/";
+ const string c = key + string("=") + sid + "; expires=" + string(exp) + "; domain=." + httpd::realm(domain) + "; path=/; secure; httponly";
debug(c, "openauth::cookie");
return c;
}
@@ -85,7 +91,7 @@ const string cookie(const string& key, const string& sid, const string& domain)
/**
* Redirect to the configured login page.
*/
-const failable<int> login(const string& page, const value& ref, const value& attempt, request_rec* r) {
+const failable<int> login(const string& page, const value& ref, const value& attempt, request_rec* const r) {
const list<list<value> > rarg = ref == string("/")? list<list<value> >() : mklist<list<value> >(mklist<value>("openauth_referrer", httpd::escape(httpd::url(isNil(ref)? r->uri : ref, r))));
const list<list<value> > aarg = isNil(attempt)? list<list<value> >() : mklist<list<value> >(mklist<value>("openauth_attempt", attempt));
const list<list<value> > largs = append<list<value> >(rarg, aarg);
@@ -94,6 +100,31 @@ const failable<int> login(const string& page, const value& ref, const value& att
return httpd::externalRedirect(loc, r);
}
+/**
+ * Report a request auth status.
+ */
+const int reportStatus(const failable<int>& authrc, const string& page, const value& attempt, request_rec* const r) {
+ debug(authrc, "openauth::reportStatus::authrc");
+
+ // Redirect to the login page if not authorized
+ if (!hasContent(authrc) && rcode(authrc) == HTTP_UNAUTHORIZED) {
+
+ // Clear any auth cookies
+ if(hasContent(sessionID(r, "TuscanyOpenAuth")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", emptyString, httpd::hostName(r))));
+ if(hasContent(sessionID(r, "TuscanyOpenIDAuth")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenIDAuth", emptyString, httpd::hostName(r))));
+ if(hasContent(sessionID(r, "TuscanyOAuth1")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth1", emptyString, httpd::hostName(r))));
+ if(hasContent(sessionID(r, "TuscanyOAuth2")))
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth2", emptyString, httpd::hostName(r))));
+
+ return httpd::reportStatus(login(page, string("/"), attempt, r));
+ }
+
+ return httpd::reportStatus(authrc);
+}
+
}
}