summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-09-06 07:45:00 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2010-09-06 07:45:00 +0000
commit2d574d2281d05383e646f20147adbc3ca8934430 (patch)
tree194c6dcfdfb0bbbaf6dd439dcd95bb6235b9a3eb
parente6c50210013371ca5c1e45e4c86178a1fc212d49 (diff)
Strawman implementation of the OAuth 2.0 protocol. Minor improvements to the OpenID support and changes to enable it to co-exist with OAuth.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@992963 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--sca-cpp/trunk/INSTALL6
-rw-r--r--sca-cpp/trunk/components/cache/client-test.cpp4
-rw-r--r--sca-cpp/trunk/components/chat/client-test.cpp2
-rw-r--r--sca-cpp/trunk/components/log/client-test.cpp6
-rw-r--r--sca-cpp/trunk/components/nosqldb/client-test.cpp4
-rw-r--r--sca-cpp/trunk/components/queue/client-test.cpp2
-rw-r--r--sca-cpp/trunk/components/sqldb/client-test.cpp4
-rw-r--r--sca-cpp/trunk/components/webservice/client-test.cpp2
-rw-r--r--sca-cpp/trunk/configure.ac22
-rw-r--r--sca-cpp/trunk/kernel/value.hpp19
-rw-r--r--sca-cpp/trunk/modules/Makefile.am2
-rw-r--r--sca-cpp/trunk/modules/http/curl-test.cpp4
-rw-r--r--sca-cpp/trunk/modules/http/http.hpp26
-rw-r--r--sca-cpp/trunk/modules/http/httpd.hpp123
-rw-r--r--sca-cpp/trunk/modules/http/mod-ssltunnel.cpp12
-rw-r--r--sca-cpp/trunk/modules/json/json.hpp7
-rw-r--r--sca-cpp/trunk/modules/oauth/Makefile.am37
-rw-r--r--sca-cpp/trunk/modules/oauth/htdocs/index.html43
-rw-r--r--sca-cpp/trunk/modules/oauth/htdocs/login/index.html82
-rw-r--r--sca-cpp/trunk/modules/oauth/htdocs/logout/index.html33
-rw-r--r--sca-cpp/trunk/modules/oauth/htdocs/unprotected/index.html27
-rw-r--r--sca-cpp/trunk/modules/oauth/mod-oauth.cpp415
-rwxr-xr-xsca-cpp/trunk/modules/oauth/oauth-app-conf32
-rwxr-xr-xsca-cpp/trunk/modules/oauth/oauth-conf64
-rwxr-xr-xsca-cpp/trunk/modules/oauth/oauth-memcached-conf32
-rw-r--r--sca-cpp/trunk/modules/oauth/oauth.composite39
-rwxr-xr-xsca-cpp/trunk/modules/oauth/start-test42
-rwxr-xr-xsca-cpp/trunk/modules/oauth/stop-test24
-rw-r--r--sca-cpp/trunk/modules/oauth/user-info.scm26
-rw-r--r--sca-cpp/trunk/modules/openid/Makefile.am2
-rw-r--r--sca-cpp/trunk/modules/openid/htdocs/login/index.html5
-rw-r--r--sca-cpp/trunk/modules/openid/htdocs/logout/index.html2
-rwxr-xr-xsca-cpp/trunk/modules/openid/openid-conf10
-rw-r--r--sca-cpp/trunk/modules/server/client-test.hpp20
-rw-r--r--sca-cpp/trunk/modules/server/mod-eval.hpp26
-rw-r--r--sca-cpp/trunk/modules/server/mod-wiring.cpp8
-rw-r--r--sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/login/index.html5
-rw-r--r--sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/logout/index.html2
-rw-r--r--sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/login/index.html5
-rw-r--r--sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/logout/index.html2
-rw-r--r--sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html5
-rw-r--r--sca-cpp/trunk/samples/store-cluster/htdocs/logout/index.html2
-rwxr-xr-xsca-cpp/trunk/ubuntu/ubuntu-install-all2
43 files changed, 1160 insertions, 77 deletions
diff --git a/sca-cpp/trunk/INSTALL b/sca-cpp/trunk/INSTALL
index cd8b24d9c1..d2e642f23c 100644
--- a/sca-cpp/trunk/INSTALL
+++ b/sca-cpp/trunk/INSTALL
@@ -157,6 +157,12 @@ To build the SQL Database utility component (requires PostgreSQL):
To build the Web service utility component (requires Apache Axis2/C):
--enable-webservice
+To build the support for OAuth authentication:
+--enable-oauth
+
+To build the support for OpenID authentication:
+--enable-openid
+
To generate doxygen documentation, add:
--enable-doxygen
diff --git a/sca-cpp/trunk/components/cache/client-test.cpp b/sca-cpp/trunk/components/cache/client-test.cpp
index 4f655c3d98..4fb4cfe4e1 100644
--- a/sca-cpp/trunk/components/cache/client-test.cpp
+++ b/sca-cpp/trunk/components/cache/client-test.cpp
@@ -40,7 +40,7 @@ const string memcacheuri("http://localhost:8090/memcache");
const string frontcacheuri("http://localhost:8090/frontcache");
bool testCache(const string& uri) {
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
@@ -113,7 +113,7 @@ bool testGetPerf() {
+ (list<value>() + "price" + string("$4.55"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const failable<value> id = http::post(a, memcacheuri, cs);
assert(hasContent(id));
const string p = path(content(id));
diff --git a/sca-cpp/trunk/components/chat/client-test.cpp b/sca-cpp/trunk/components/chat/client-test.cpp
index 702d3ae041..2c91fda1f2 100644
--- a/sca-cpp/trunk/components/chat/client-test.cpp
+++ b/sca-cpp/trunk/components/chat/client-test.cpp
@@ -83,7 +83,7 @@ bool testListen() {
bool testPost() {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
const failable<value> id = http::post(entry, "http://localhost:8090/print-sender/sca2@localhost", ch);
assert(hasContent(id));
return true;
diff --git a/sca-cpp/trunk/components/log/client-test.cpp b/sca-cpp/trunk/components/log/client-test.cpp
index e972ed59bf..5f13f64ac1 100644
--- a/sca-cpp/trunk/components/log/client-test.cpp
+++ b/sca-cpp/trunk/components/log/client-test.cpp
@@ -39,7 +39,7 @@ namespace log {
const string uri("http://localhost:8090/log");
bool testLog() {
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
@@ -71,7 +71,7 @@ bool testLogPerf() {
+ (list<value>() + "price" + string("$2.99"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
@@ -82,7 +82,7 @@ bool testLogPerf() {
}
bool testLogger() {
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const failable<value> res = http::evalExpr(mklist<value>(string("sum"), 33, 22), string("http://localhost:8090/client"), cs);
assert(hasContent(res));
diff --git a/sca-cpp/trunk/components/nosqldb/client-test.cpp b/sca-cpp/trunk/components/nosqldb/client-test.cpp
index f28f084487..8eed7ce8cd 100644
--- a/sca-cpp/trunk/components/nosqldb/client-test.cpp
+++ b/sca-cpp/trunk/components/nosqldb/client-test.cpp
@@ -39,7 +39,7 @@ namespace nosqldb {
const string uri("http://localhost:8090/nosqldb");
bool testNoSqlDb() {
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
@@ -104,7 +104,7 @@ bool testGetPerf() {
+ (list<value>() + "price" + string("$4.55"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
diff --git a/sca-cpp/trunk/components/queue/client-test.cpp b/sca-cpp/trunk/components/queue/client-test.cpp
index c80b2d2a31..286faa2930 100644
--- a/sca-cpp/trunk/components/queue/client-test.cpp
+++ b/sca-cpp/trunk/components/queue/client-test.cpp
@@ -77,7 +77,7 @@ bool testListen() {
bool testPost() {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
const failable<value> id = http::post(entry, "http://localhost:8090/print-sender", ch);
assert(hasContent(id));
return true;
diff --git a/sca-cpp/trunk/components/sqldb/client-test.cpp b/sca-cpp/trunk/components/sqldb/client-test.cpp
index 303afe3c10..4e5c067633 100644
--- a/sca-cpp/trunk/components/sqldb/client-test.cpp
+++ b/sca-cpp/trunk/components/sqldb/client-test.cpp
@@ -39,7 +39,7 @@ namespace sqldb {
const string uri("http://localhost:8090/sqldb");
bool testSqlDb() {
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
@@ -104,7 +104,7 @@ bool testGetPerf() {
+ (list<value>() + "price" + string("$4.55"));
const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const failable<value> id = http::post(a, uri, cs);
assert(hasContent(id));
const string p = path(content(id));
diff --git a/sca-cpp/trunk/components/webservice/client-test.cpp b/sca-cpp/trunk/components/webservice/client-test.cpp
index e666895717..658c87e2fc 100644
--- a/sca-cpp/trunk/components/webservice/client-test.cpp
+++ b/sca-cpp/trunk/components/webservice/client-test.cpp
@@ -60,7 +60,7 @@ bool testModAxis2() {
}
bool testEval() {
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
const value func = "http://ws.apache.org/axis2/c/samples/echoString";
const list<value> arg = mklist<value>(
diff --git a/sca-cpp/trunk/configure.ac b/sca-cpp/trunk/configure.ac
index e5c66254e8..6f69a60e7b 100644
--- a/sca-cpp/trunk/configure.ac
+++ b/sca-cpp/trunk/configure.ac
@@ -508,6 +508,27 @@ else
AM_CONDITIONAL([WANT_OPENID], false)
fi
+# Enable support for OAuth.
+AC_MSG_CHECKING([whether to enable OAuth support])
+AC_ARG_ENABLE(oauth, [AS_HELP_STRING([--enable-oauth], [enable OAuth support [default=no]])],
+[ case "${enableval}" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ AC_MSG_RESULT(yes)
+ want_oauth=true
+ ;;
+ esac ],
+[ AC_MSG_RESULT(no)])
+if test "${want_oauth}" = "true"; then
+ AM_CONDITIONAL([WANT_OAUTH], true)
+ AC_DEFINE([WANT_OAUTH], 1, [enable OAuth support])
+
+else
+ AM_CONDITIONAL([WANT_OAUTH], false)
+fi
+
# Enable support for Google AppEngine.
AC_MSG_CHECKING([whether to enable Google AppEngine support])
AC_ARG_ENABLE(gae, [AS_HELP_STRING([--enable-gae], [enable Google AppEngine support [default=no]])],
@@ -842,6 +863,7 @@ AC_CONFIG_FILES([Makefile
modules/python/Makefile
modules/java/Makefile
modules/openid/Makefile
+ modules/oauth/Makefile
modules/wsgi/Makefile
components/Makefile
components/cache/Makefile
diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp
index 24688648d2..211873ef0c 100644
--- a/sca-cpp/trunk/kernel/value.hpp
+++ b/sca-cpp/trunk/kernel/value.hpp
@@ -28,6 +28,8 @@
#include <stdlib.h>
#include <apr_uuid.h>
+#include <apr_time.h>
+
#include "string.hpp"
#include "sstream.hpp"
#include "gc.hpp"
@@ -601,5 +603,22 @@ const value mkuuid() {
return value(string(buf, APR_UUID_FORMATTED_LENGTH));
}
+/**
+ * Make a random alphanumeric value.
+ */
+const int intrand() {
+ const apr_uint64_t now = apr_time_now();
+ srand((unsigned int)(((now >> 32) ^ now) & 0xffffffff));
+ return rand() & 0x0FFFF;
+}
+
+const value mkrand() {
+ char buf[32];
+ const char* an = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ for (int i =0; i < 32; i++)
+ buf[i] = an[intrand() % 62];
+ return value(string(buf, 32));
+}
+
}
#endif /* tuscany_value_hpp */
diff --git a/sca-cpp/trunk/modules/Makefile.am b/sca-cpp/trunk/modules/Makefile.am
index 0924fd04ca..fa07c599ca 100644
--- a/sca-cpp/trunk/modules/Makefile.am
+++ b/sca-cpp/trunk/modules/Makefile.am
@@ -15,5 +15,5 @@
# specific language governing permissions and limitations
# under the License.
-SUBDIRS = scheme atom rss json scdl http server python java openid wsgi
+SUBDIRS = scheme atom rss json scdl http server python java openid oauth wsgi
diff --git a/sca-cpp/trunk/modules/http/curl-test.cpp b/sca-cpp/trunk/modules/http/curl-test.cpp
index 1d1b07bff4..a7b8fd90b6 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;
+ CURLSession ch("", "", "");
{
ostringstream os;
const failable<list<ostream*> > r = get<ostream*>(curlWriter, &os, testURI, ch);
@@ -69,7 +69,7 @@ struct getLoop {
};
const bool testGetPerf() {
- CURLSession ch;
+ CURLSession ch("", "", "");
lambda<bool()> gl = getLoop(ch);
cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl;
return true;
diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp
index 6180518e23..1932ac3420 100644
--- a/sca-cpp/trunk/modules/http/http.hpp
+++ b/sca-cpp/trunk/modules/http/http.hpp
@@ -63,7 +63,10 @@ public:
*/
class CURLSession {
public:
- CURLSession(const string& ca = "", const string& cert = "", const string& key = "") : h(curl_easy_init()), p(gc_pool(mkpool())), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(true), ca(ca), cert(cert), key(key) {
+ CURLSession() : h(NULL), p(NULL), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(false), ca(""), cert(""), key("") {
+ }
+
+ CURLSession(const string& ca, const string& cert, const string& key) : h(curl_easy_init()), p(gc_pool(mkpool())), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(true), ca(ca), cert(cert), key(key) {
}
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) {
@@ -86,7 +89,7 @@ private:
apr_pollfd_t* wpollfd;
apr_pollset_t* rpollset;
apr_pollfd_t* rpollfd;
- const bool owner;
+ bool owner;
friend CURL* handle(const CURLSession& cs);
friend apr_socket_t* sock(const CURLSession& cs);
@@ -95,9 +98,9 @@ private:
friend const failable<int> recv(char* c, const int l, const CURLSession& cs);
public:
- const string ca;
- const string cert;
- const string key;
+ string ca;
+ string cert;
+ string key;
};
/**
@@ -397,24 +400,31 @@ const failable<value> get(const string& url, const CURLSession& cs) {
const list<string> ls(reverse(cadr(content(res))));
const string ct(content(contentType(car(content(res)))));
- if (ct == "application/atom+xml;type=entry") {
+ debug(ct, "http::get::contentType");
+ if (contains(ct, "application/atom+xml;type=entry")) {
// Read an ATOM entry
const value val(atom::entryValue(content(atom::readATOMEntry(ls))));
debug(val, "http::get::result");
return val;
}
- if (ct == "application/atom+xml;type=feed" || atom::isATOMFeed(ls)) {
+ if (contains(ct, "application/atom+xml;type=feed") || atom::isATOMFeed(ls)) {
// Read an ATOM feed
const value val(atom::feedValues(content(atom::readATOMFeed(ls))));
debug(val, "http::get::result");
return val;
}
- if (ct == "application/rss+xml" || rss::isRSSFeed(ls)) {
+ if (contains(ct, "application/rss+xml") || rss::isRSSFeed(ls)) {
// Read an RSS feed
const value val(rss::feedValues(content(rss::readRSSFeed(ls))));
debug(val, "http::get::result");
return val;
}
+ if (contains(ct, "text/javascript") || contains(ct, "application/json-rpc")) {
+ json::JSONContext cx;
+ const value val(json::jsonValues(content(json::readJSON(ls, cx))));
+ debug(val, "http::get::result");
+ return val;
+ }
// Return the content as a list of values
const value val(mkvalues(ls));
diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp
index f1b54d79ad..f407e1012e 100644
--- a/sca-cpp/trunk/modules/http/httpd.hpp
+++ b/sca-cpp/trunk/modules/http/httpd.hpp
@@ -49,6 +49,7 @@
#include "string.hpp"
#include "stream.hpp"
+#include "sstream.hpp"
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
@@ -60,7 +61,7 @@ namespace httpd {
/**
* Returns a server-scoped module configuration.
*/
-template<typename C> void* makeServerConf(apr_pool_t *p, server_rec *s) {
+template<typename C> void* makeServerConf(apr_pool_t* p, server_rec* s) {
return new (gc_new<C>(p)) C(p, s);
}
@@ -72,10 +73,24 @@ template<typename C> C& serverConf(const server_rec* s, const module* 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* cmd, const module* mod) {
return *(C*)ap_get_module_config(cmd->server->module_config, mod);
}
+/**
+ * Returns a directory-scoped module configuration.
+ */
+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) {
+ return *(C*)ap_get_module_config(r->per_dir_config, mod);
+}
+
+template<typename C> C& dirConf(const void* c) {
+ return *(C*)c;
+}
/**
* Return the name of a server.
@@ -172,18 +187,96 @@ const list<value> pathInfo(const list<value>& uri, const list<value>& path) {
}
/**
+ * Convert a URI and a path to an absolute URL.
+ */
+const string url(const string& uri, const list<value>& p, request_rec* r) {
+ const string u = uri + path(p);
+ return ap_construct_url(r->pool, c_str(u), r);
+}
+
+/**
+ * Convert a URI to an absolute URL.
+ */
+const string url(const string& uri, request_rec* r) {
+ return ap_construct_url(r->pool, c_str(uri), r);
+}
+
+/**
+ * Escape a URI.
+ */
+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);
+ const unsigned char* s = (const unsigned char *)c_str(uri);
+ unsigned char* d = (unsigned char*)copy;
+ unsigned c;
+ while ((c = *s)) {
+ if (apr_isalnum(c) || c == '_')
+ *d++ = (unsigned char)c;
+ else if (c == ' ')
+ *d++ = '+';
+ else {
+ *d++ = '%';
+ *d++ = escape_c2x[c >> 4];
+ *d++ = escape_c2x[c & 0xf];
+ }
+ ++s;
+ }
+ *d = '\0';
+ debug(copy, "httpd::escape::result");
+ return copy;
+}
+
+/**
+ * Unescape a URI.
+ */
+const string unescape(const string& uri) {
+ debug(uri, "httpd::unescape::uri");
+ char* b = const_cast<char*>(c_str(string(c_str(uri))));
+ ap_unescape_url(b);
+ debug(b, "httpd::unescape::result");
+ return b;
+}
+
+/**
* Returns a list of key value pairs from the args in a query string.
*/
const list<value> queryArg(const string& s) {
+ debug(s, "httpd::queryArg::string");
const list<string> t = tokenize("=", s);
return mklist<value>(c_str(car(t)), cadr(t));
}
+const list<list<value> > queryArgs(const string& a) {
+ return map<string, list<value>>(queryArg, tokenize("&", 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 char* a = r->args;
- if (a == NULL)
+ if (r->args == NULL)
return list<list<value> >();
- return map<string, list<value>>(queryArg, tokenize("&", a));
+ return queryArgs(r->args);
+}
+
+/**
+ * Converts a list of key value pairs to a query string.
+ */
+ostringstream& queryString(const list<list<value> > args, ostringstream& os) {
+ if (isNil(args))
+ return os;
+ debug(car(args), "httpd::queryString::arg");
+ os << car(car(args)) << "=" << c_str(cadr(car(args)));
+ if (!isNil(cdr(args)))
+ os << "&";
+ return queryString(cdr(args), os);
+}
+
+const string queryString(const list<list<value> > args) {
+ ostringstream os;
+ return str(queryString(args, os));
}
/**
@@ -222,14 +315,6 @@ const list<string> read(request_rec* r) {
}
/**
- * Convert a URI represented as a list to an absolute URL.
- */
-const char* url(const list<value>& v, request_rec* r) {
- const string u = string(r->uri) + path(v);
- return ap_construct_url(r->pool, c_str(u), r);
-}
-
-/**
* Write an HTTP result.
*/
const failable<int> writeResult(const failable<list<string> >& ls, const string& ct, request_rec* r) {
@@ -238,7 +323,7 @@ const failable<int> writeResult(const failable<list<string> >& ls, const string&
ostringstream os;
write(content(ls), os);
const string ob(str(os));
- debug(ob, "httpd::result");
+ debug(ob, "httpd::writeResult");
// Make sure browsers come back and check for updated dynamic content
apr_table_setn(r->headers_out, "Expires", "Tue, 01 Jan 1980 00:00:00 GMT");
@@ -478,6 +563,16 @@ const failable<request_rec*, int> internalSubRequest(const string& nr_uri, reque
}
/**
+ * Return an HTTP external redirect request.
+ */
+const int externalRedirect(const string& uri, request_rec* r) {
+ r->status = HTTP_MOVED_TEMPORARILY;
+ apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(uri)));
+ r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/") + uri));
+ return OK;
+}
+
+/**
* Put a value in the process user data.
*/
const bool putUserData(const string& k, const void* v, const server_rec* s) {
diff --git a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp
index 0d4fe3045f..c241cd982d 100644
--- a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp
+++ b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp
@@ -68,11 +68,11 @@ extern module AP_DECLARE_DATA core_module;
* Process the module configuration.
*/
int M_SSLTUNNEL;
-int postConfigParse(ServerConf& mainsc, apr_pool_t* p, server_rec* s) {
+int postConfigMerge(ServerConf& mainsc, apr_pool_t* p, server_rec* s) {
if (s == NULL)
return OK;
ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel);
- debug(httpd::serverName(s), "modwiring::postConfigParse::serverName");
+ debug(httpd::serverName(s), "modwiring::postConfigMerge::serverName");
// Merge configuration from main server
if (length(sc.ca) == 0 && length(mainsc.ca) !=0)
@@ -93,7 +93,7 @@ int postConfigParse(ServerConf& mainsc, apr_pool_t* p, server_rec* s) {
sc.host = uri.hostname;
sc.path = uri.path;
}
- return postConfigParse(mainsc, p, s->next);
+ 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) {
@@ -104,8 +104,8 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp,
// Register the SSLTUNNEL method
M_SSLTUNNEL = ap_method_register(p, "SSLTUNNEL");
- // Parse the configured TunnelPass URI
- return postConfigParse(sc, p, s);
+ // Merge and process server configurations
+ return postConfigMerge(sc, p, s);
}
/**
@@ -296,7 +296,7 @@ int handler(request_rec* r) {
debug(url, "modssltunnel::handler::target");
// Create the target connection
- http::CURLSession cs;
+ http::CURLSession cs("", "", "");
// Run the tunnel
return tunnel(r->connection, cs, url, "", gc_pool(r->pool), connectionFilter(r->proto_input_filters), connectionFilter(r->proto_output_filters));
diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp
index f904718f05..bade096b86 100644
--- a/sca-cpp/trunk/modules/json/json.hpp
+++ b/sca-cpp/trunk/modules/json/json.hpp
@@ -388,6 +388,13 @@ const failable<value> jsonResultValue(const list<string>& s, JSONContext& cx) {
}
/**
+ * Convert a JSON payload to a list of values.
+ */
+const list<value> jsonValues(const list<value>& e) {
+ return elementsToValues(e);
+}
+
+/**
* Return a portable function name from a JSON-RPC function name.
* Strip the "system." and "Service." prefixes added by some JSON-RPC clients.
*/
diff --git a/sca-cpp/trunk/modules/oauth/Makefile.am b/sca-cpp/trunk/modules/oauth/Makefile.am
new file mode 100644
index 0000000000..077b50bddf
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/Makefile.am
@@ -0,0 +1,37 @@
+# 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.
+
+if WANT_OAUTH
+
+INCLUDES = -I${HTTPD_INCLUDE}
+
+dist_mod_SCRIPTS = oauth-conf oauth-memcached-conf oauth-app-conf
+moddir=$(prefix)/modules/oauth
+
+mod_LTLIBRARIES = libmod_tuscany_oauth.la
+noinst_DATA = libmod_tuscany_oauth.so
+
+libmod_tuscany_oauth_la_SOURCES = mod-oauth.cpp
+libmod_tuscany_oauth_la_LDFLAGS = -lxml2 -lcurl -lmozjs
+libmod_tuscany_oauth.so:
+ ln -s .libs/libmod_tuscany_oauth.so
+
+EXTRA_DIST = oauth.composite user-info.scm htdocs/index.html htdocs/login/index.html htdocs/logout/index.html htdocs/unprotected/index.html
+
+dist_noinst_SCRIPTS = start-test stop-test
+
+endif
diff --git a/sca-cpp/trunk/modules/oauth/htdocs/index.html b/sca-cpp/trunk/modules/oauth/htdocs/index.html
new file mode 100644
index 0000000000..e6295a93b5
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/htdocs/index.html
@@ -0,0 +1,43 @@
+<!--
+ 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.
+-->
+
+<html>
+<head>
+<script type="text/javascript" src="/js/tuscany-ref.js"></script>
+<script type="text/javascript">
+var component = new tuscany.sca.Component("Protected");
+var userInfo = new tuscany.sca.Reference("userInfo");
+var user = userInfo.apply("getuser");
+var email = userInfo.apply("getemail");
+</script>
+</head>
+<body>
+<h1>Protected area - It works!</h1>
+<p>The following info is returned by a JSONRPC service:</p>
+<div id="user"></div>
+<div id="email"></div>
+<script type="text/javascript">
+document.getElementById('user').innerHTML="User: " + user;
+document.getElementById('email').innerHTML="Email: " + email;
+</script>
+<p><a href="info">User info</a></p>
+<p><a href="login">Sign in</a></p>
+<p><a href="logout">Sign out</a></p>
+<p><a href="unprotected">Unprotected area</a></p>
+</body></html>
diff --git a/sca-cpp/trunk/modules/oauth/htdocs/login/index.html b/sca-cpp/trunk/modules/oauth/htdocs/login/index.html
new file mode 100644
index 0000000000..fcf5a870c0
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/htdocs/login/index.html
@@ -0,0 +1,82 @@
+<!--
+ 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.
+-->
+
+<html><body><h1>Sign in with an OAuth 2.0 provider</h1>
+
+<script type="text/javascript">
+function queryParams() {
+ qp = new Array();
+ qs = window.location.search.substring(1).split('&');
+ for (i = 0; i < qs.length; i++) {
+ e = qs[i].indexOf('=');
+ if (e > 0)
+ qp[qs[i].substring(0, e)] = unescape(qs[i].substring(e + 1));
+ }
+ return qp;
+}
+
+function oauthReferrer() {
+ r = queryParams()['mod_oauth_referrer'];
+ if (typeof(r) == 'undefined')
+ return r;
+ q = r.indexOf('?');
+ if (q > 0)
+ return r.substring(0, q);
+ return r;
+}
+
+if (typeof(oauthReferrer()) == 'undefined') {
+ document.location = '/';
+}
+
+function submitSignin(w) {
+ parms = w();
+ document.signin.mod_oauth_authorize.value = parms[0];
+ document.signin.mod_oauth_access_token.value = parms[1];
+ document.signin.mod_oauth_client_id.value = parms[2];
+ document.signin.mod_oauth_info.value = parms[3];
+ document.signin.action = oauthReferrer();
+ document.signin.submit();
+}
+
+function withFacebook() {
+ var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'app1234', 'https://graph.facebook.com/me'];
+ return parms;
+}
+
+function withGithub() {
+ var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'app2345', 'https://github.com/api/v2/json/user/show'];
+ return parms;
+}
+</script>
+
+<form name="signin" action="/" method="GET">
+<input type="hidden" name="mod_oauth_authorize" value="https://graph.facebook.com/oauth/authorize"/>
+<input type="hidden" name="mod_oauth_access_token" value="https://graph.facebook.com/oauth/access_token"/>
+<input type="hidden" name="mod_oauth_client_id" value="app1234"/>
+<input type="hidden" name="mod_oauth_info" value="https://graph.facebook.com/me"/>
+<input type="hidden" name="mod_oauth_step" value="authorize"/>
+</form>
+
+<form name="fields">
+<p>Sign in with your Facebook account<br/><input type="button" onclick="submitSignin(withFacebook)" value="Sign in"/></p>
+<p>Sign in with your Github account<br/><input type="button" onclick="submitSignin(withGithub)" value="Sign in"/></p>
+</form>
+
+</body></html>
diff --git a/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html b/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html
new file mode 100644
index 0000000000..02a92d1b31
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/htdocs/logout/index.html
@@ -0,0 +1,33 @@
+<!--
+ 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.
+-->
+
+<html><body>
+<h1>Sign out</h1>
+
+<form name="signout" action="/login" method="GET">
+<script type="text/javascript">
+function submitSignout() {
+ document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE';
+ document.signout.submit();
+ return true;
+}
+</script>
+<input type="button" onclick="submitSignout()" value="Sign out"/>
+</form>
+</body></html>
diff --git a/sca-cpp/trunk/modules/oauth/htdocs/unprotected/index.html b/sca-cpp/trunk/modules/oauth/htdocs/unprotected/index.html
new file mode 100644
index 0000000000..af2cd7ca19
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/htdocs/unprotected/index.html
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+
+<html>
+<body>
+<h1>Unprotected area - It works!</h1>
+<p><a href="/info">User info</a></p>
+<p><a href="/login">Sign in</a></p>
+<p><a href="/logout">Sign out</a></p>
+<p><a href="/">Protected area</a></p>
+</body></html>
diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth.cpp
new file mode 100644
index 0000000000..9a0c9aa078
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/mod-oauth.cpp
@@ -0,0 +1,415 @@
+/*
+ * 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.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * HTTPD module for OAuth 2.0 authentication.
+ */
+
+#include <sys/stat.h>
+
+#include "string.hpp"
+#include "stream.hpp"
+#include "list.hpp"
+#include "tree.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "../http/httpd.hpp"
+#include "../http/http.hpp"
+#include "../../components/cache/memcache.hpp"
+
+extern "C" {
+extern module AP_MODULE_DECLARE_DATA mod_tuscany_oauth;
+}
+
+namespace tuscany {
+namespace oauth {
+
+/**
+ * Server configuration.
+ */
+class ServerConf {
+public:
+ ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) {
+ }
+
+ const gc_pool p;
+ server_rec* server;
+ string ca;
+ string cert;
+ string key;
+ list<list<value> > apps;
+ list<string> mcaddrs;
+ memcache::MemCached mc;
+ http::CURLSession cs;
+};
+
+/**
+ * Directory configuration.
+ */
+class DirConf {
+public:
+ DirConf(apr_pool_t* p, char* d) : p(p), dir(d), enabled(false), login("") {
+ }
+
+ const gc_pool p;
+ const char* dir;
+ bool enabled;
+ string login;
+};
+
+/**
+ * Check user authentication.
+ */
+static int checkUserID(request_rec *r) {
+ // Decline if we're not enabled or AuthType is not set to Open
+ const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth);
+ if (!dc.enabled)
+ return DECLINED;
+ const char* atype = ap_auth_type(r);
+ if (atype == NULL || strcasecmp(atype, "Open"))
+ return DECLINED;
+
+ gc_scoped_pool pool(r->pool);
+ httpdDebugRequest(r, "modoauth::checkUserID::input");
+ return OK;
+}
+
+/**
+ * Return the session id from a request.
+ */
+const maybe<string> sessionID(const list<string> c) {
+ if (isNil(c))
+ return maybe<string>();
+ const list<string> kv = tokenize("=", car(c));
+ if (!isNil(kv) && !isNil(cdr(kv))) {
+ if (car(kv) == "TuscanyOpenAuth")
+ return cadr(kv);
+ }
+ return sessionID(cdr(c));
+}
+
+const maybe<string> sessionID(const request_rec* r) {
+ const char* c = apr_table_get(r->headers_in, "Cookie");
+ debug(c, "modoauth::sessionid::cookies");
+ if (c == NULL)
+ return maybe<string>();
+ return sessionID(tokenize(";", c));
+}
+
+/**
+ * Return the user info for a session.
+ */
+const failable<value> userInfo(const value& sid, const ServerConf& sc) {
+ return memcache::get(mklist<value>("tuscanyOpenAuth", sid), sc.mc);
+}
+
+/**
+ * Handle an authenticated request.
+ */
+const failable<int> authenticated(const list<list<value> >& info, request_rec* r) {
+ debug(info, "modoauth::authenticated::info");
+
+ const list<value> id = assoc<value>("id", info);
+ r->user = apr_pstrdup(r->pool, c_str(cadr(id)));
+
+ const list<value> email = assoc<value>("email", info);
+ apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "EMAIL"), apr_pstrdup(r->pool, c_str(cadr(email))));
+
+ const list<value> fullname = assoc<value>("name", info);
+ apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "NICKNAME"), apr_pstrdup(r->pool, c_str(cadr(fullname))));
+ apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "FULLNAME"), apr_pstrdup(r->pool, c_str(cadr(fullname))));
+
+ const list<value> firstname = assoc<value>("first_name", info);
+ apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "FIRSTNAME"), apr_pstrdup(r->pool, c_str(cadr(firstname))));
+
+ const list<value> lastname = assoc<value>("last_name", info);
+ apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "LASTNAME"), apr_pstrdup(r->pool, c_str(cadr(lastname))));
+
+ if(r->ap_auth_type == NULL)
+ r->ap_auth_type = const_cast<char*>("OAuth");
+ return DECLINED;
+}
+
+/**
+ * Redirect to the configured login page.
+ */
+const failable<int> login(const string& page, request_rec* r) {
+ const list<list<value> > largs = mklist<list<value> >(mklist<value>("mod_oauth_referrer", httpd::escape(httpd::url(r->uri, r))));
+ const string loc = httpd::url(page, r) + string("?") + httpd::queryString(largs);
+ debug(loc, "modoauth::login::uri");
+ return httpd::externalRedirect(loc, r);
+}
+
+/**
+ * Handle an authorize request.
+ */
+const failable<int> authorize(const list<list<value> >& args, request_rec* r) {
+ // Extract authorize URI, access_token URI and client ID
+ const list<value> auth = assoc<value>("mod_oauth_authorize", args);
+ const list<value> tok = assoc<value>("mod_oauth_access_token", args);
+ const list<value> cid = assoc<value>("mod_oauth_client_id", args);
+ const list<value> info = assoc<value>("mod_oauth_info", args);
+
+ // Build the redirect URI
+ const list<list<value> > rargs = mklist<list<value> >(mklist<value>("mod_oauth_step", "access_token"), tok, cid, info);
+ const string redir = httpd::url(r->uri, r) + string("?") + httpd::queryString(rargs);
+ debug(redir, "modoauth::authorize::redir");
+
+ // Redirect to the authorize URI
+ const list<list<value> > aargs = mklist<list<value> >(mklist<value>("client_id", cadr(cid)), mklist<value>("scope", "email"), mklist<value>("redirect_uri", httpd::escape(redir)));
+ const string uri = httpd::unescape(cadr(auth)) + string("?") + httpd::queryString(aargs);
+ debug(uri, "modoauth::authorize::uri");
+ return httpd::externalRedirect(uri, r);
+}
+
+/**
+ * Convert a session id to a cookie string.
+ */
+const string cookie(const string& sid) {
+ 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 = string("TuscanyOpenAuth=") + sid + string(";path=/;expires=" + string(exp)) + ";secure=TRUE";
+ debug(c, "modoauth::cookie");
+ return c;
+}
+
+/**
+ * Handle an access_token request.
+ */
+const failable<int> access_token(const list<list<value> >& args, request_rec* r, const ServerConf& sc) {
+ // Extract access_token URI, client ID and authorization code
+ const list<value> tok = assoc<value>("mod_oauth_access_token", args);
+ const list<value> cid = assoc<value>("mod_oauth_client_id", args);
+ const list<value> info = assoc<value>("mod_oauth_info", args);
+ const list<value> code = assoc<value>("code", args);
+
+ // Lookup client app configuration
+ const list<value> app = assoc<value>(cadr(cid), sc.apps);
+
+ // Build the redirect URI
+ const list<list<value> > rargs = mklist<list<value> >(mklist<value>("mod_oauth_step", "access_token"), tok, cid, info);
+ const string redir = httpd::url(r->uri, r) + string("?") + httpd::queryString(rargs);
+ debug(redir, "modoauth::access_token::redir");
+
+ // Request access token
+ const list<list<value> > targs = mklist<list<value> >(mklist<value>("client_id", cadr(cid)), mklist<value>("redirect_uri", httpd::escape(redir)), mklist<value>("client_secret", cadr(app)), code);
+ const string turi = httpd::unescape(cadr(tok)) + string("?") + httpd::queryString(targs);
+ debug(turi, "modoauth::access_token::tokenuri");
+ const failable<value> tr = http::get(turi, sc.cs);
+ debug(tr, "modoauth::access_token::response");
+ const list<value> tv = assoc<value>("access_token", httpd::queryArgs(join("", convertValues<string>(content(tr)))));
+ debug(tv, "modoauth::access_token::token");
+
+ // Request user info
+ const list<list<value> > iargs = mklist<list<value> >(tv);
+ const string iuri = httpd::unescape(cadr(info)) + string("?") + httpd::queryString(iargs);
+ debug(iuri, "modoauth::access_token::infouri");
+ const failable<value> iv = http::get(iuri, sc.cs);
+ debug(iv, "modoauth::access_token::info");
+
+ // Store user info in memcached keyed by session ID
+ const value sid = mkrand();
+ memcache::put(mklist<value>("tuscanyOpenAuth", sid), content(iv), sc.mc);
+
+ // Send session ID to the client in a cookie
+ apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie(sid)));
+ return httpd::externalRedirect(httpd::url(r->uri, r), r);
+}
+
+/**
+ * Handle a request.
+ */
+int handler(request_rec* r) {
+ // Decline if we're not enabled or if the user is already
+ // authenticated by another module
+ const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth);
+ if(!dc.enabled)
+ return DECLINED;
+ if (r->user != NULL || apr_table_get(r->subprocess_env, "SSL_REMOTE_USER") != NULL)
+ return DECLINED;
+
+ gc_scoped_pool pool(r->pool);
+ httpdDebugRequest(r, "modoauth::handler::input");
+ const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth);
+
+ // Nothing to do if we're already authenticated
+ const maybe<string> sid = sessionID(r);
+ if (hasContent(sid)) {
+ const failable<value> info = userInfo(content(sid), sc);
+ if (hasContent(info))
+ return httpd::reportStatus(authenticated(content(info), r));
+ }
+
+ // Get the current protocol flow step from the query string
+ const list<list<value> > args = httpd::queryArgs(r);
+ const list<value> sl = assoc<value>("mod_oauth_step", args);
+ const value step = !isNil(sl) && !isNil(cdr(sl))? cadr(sl) : "";
+
+ // Handle an authorize request
+ if (step == "authorize")
+ return httpd::reportStatus(authorize(args, r));
+
+ // Handle an access_token request
+ if (step == "access_token")
+ return httpd::reportStatus(access_token(args, r, sc));
+
+ // Redirect to the login page
+ return httpd::reportStatus(login(dc.login, r));
+}
+
+/**
+ * Process the module configuration.
+ */
+int postConfigMerge(ServerConf& mainsc, server_rec* s) {
+ if (s == NULL)
+ return OK;
+ ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth);
+ debug(httpd::serverName(s), "modoauth::postConfigMerge::serverName");
+
+ // Merge configuration from main server
+ if (isNil(sc.apps))
+ sc.apps = mainsc.apps;
+ sc.mc = mainsc.mc;
+ sc.cs = mainsc.cs;
+
+ 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);
+ ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth);
+ debug(httpd::serverName(s), "modoauth::postConfig::serverName");
+
+ // Merge server configurations
+ return postConfigMerge(sc, s);
+}
+
+/**
+ * Child process initialization.
+ */
+void childInit(apr_pool_t* p, server_rec* s) {
+ gc_scoped_pool pool(p);
+ ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_oauth);
+ if(psc == NULL) {
+ cfailure << "[Tuscany] Due to one or more errors mod_tuscany_oauth loading failed. Causing apache to stop loading." << endl;
+ exit(APEXIT_CHILDFATAL);
+ }
+ ServerConf& sc = *psc;
+
+ // Connect to Memcached
+ if (isNil(sc.mcaddrs))
+ sc.mc = *(new (gc_new<memcache::MemCached>()) memcache::MemCached("localhost", 11211));
+ else
+ sc.mc = *(new (gc_new<memcache::MemCached>()) memcache::MemCached(sc.mcaddrs));
+
+ // Setup a CURL session
+ sc.cs = *(new (gc_new<http::CURLSession>()) http::CURLSession(sc.ca, sc.cert, sc.key));
+
+ // Merge the updated configuration into the virtual hosts
+ postConfigMerge(sc, s->next);
+}
+
+/**
+ * Configuration commands.
+ */
+const char* confApp(cmd_parms *cmd, unused void *c, const char *arg1, const char* arg2) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth);
+ sc.apps = cons<list<value> >(mklist<value>(arg1, arg2), sc.apps);
+ return NULL;
+}
+const char* confMemcached(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth);
+ sc.mcaddrs = cons<string>(arg, sc.mcaddrs);
+ return NULL;
+}
+const char* confEnabled(cmd_parms *cmd, void *c, const int arg) {
+ gc_scoped_pool pool(cmd->pool);
+ DirConf& dc = httpd::dirConf<DirConf>(c);
+ dc.enabled = (bool)arg;
+ debug(dc.dir, "modoauth::confEnabled::dir");
+ debug(dc.enabled, "modoauth::confEnabled::enabled");
+ return NULL;
+}
+const char* confLogin(cmd_parms *cmd, void *c, const char* arg) {
+ gc_scoped_pool pool(cmd->pool);
+ DirConf& dc = httpd::dirConf<DirConf>(c);
+ dc.login = arg;
+ return NULL;
+}
+const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth);
+ sc.ca = arg;
+ return NULL;
+}
+const char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth);
+ sc.cert = arg;
+ return NULL;
+}
+const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth);
+ sc.key = arg;
+ return NULL;
+}
+
+/**
+ * HTTP server module declaration.
+ */
+const command_rec commands[] = {
+ AP_INIT_ITERATE2("AddAuthOAuthApp", (const char*(*)())confApp, NULL, RSRC_CONF, "OAuth app-id app-secret"),
+ AP_INIT_ITERATE("AddAuthOAuthMemcached", (const char*(*)())confMemcached, NULL, RSRC_CONF, "Memcached server host:port"),
+ AP_INIT_FLAG("AuthOAuth", (const char*(*)())confEnabled, NULL, OR_AUTHCFG, "OAuth authentication On | Off"),
+ AP_INIT_TAKE1("AuthOAuthLoginPage", (const char*(*)())confLogin, NULL, OR_AUTHCFG, "OAuth login page"),
+ AP_INIT_TAKE1("AuthOAuthSSLCACertificateFile", (const char*(*)())confCAFile, NULL, RSRC_CONF, "OAUth SSL CA certificate file"),
+ AP_INIT_TAKE1("AuthOAuthSSLCertificateFile", (const char*(*)())confCertFile, NULL, RSRC_CONF, "OAuth SSL certificate file"),
+ AP_INIT_TAKE1("AuthOAuthSSLCertificateKeyFile", (const char*(*)())confCertKeyFile, NULL, RSRC_CONF, "OAuth SSL certificate key file"),
+ {NULL, NULL, NULL, 0, NO_ARGS, NULL}
+};
+
+void registerHooks(unused apr_pool_t *p) {
+ ap_hook_post_config(postConfig, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_child_init(childInit, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_check_user_id(checkUserID, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_handler(handler, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+}
+}
+
+extern "C" {
+
+module AP_MODULE_DECLARE_DATA mod_tuscany_oauth = {
+ STANDARD20_MODULE_STUFF,
+ // dir config and merger
+ tuscany::httpd::makeDirConf<tuscany::oauth::DirConf>, NULL,
+ // server config and merger
+ tuscany::httpd::makeServerConf<tuscany::oauth::ServerConf>, NULL,
+ // commands and hooks
+ tuscany::oauth::commands, tuscany::oauth::registerHooks
+};
+
+}
diff --git a/sca-cpp/trunk/modules/oauth/oauth-app-conf b/sca-cpp/trunk/modules/oauth/oauth-app-conf
new file mode 100755
index 0000000000..56beb0af95
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/oauth-app-conf
@@ -0,0 +1,32 @@
+#!/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.
+
+here=`readlink -f $0`; here=`dirname $here`
+mkdir -p $1
+root=`readlink -f $1`
+id=$2
+secret=$3
+
+# Configure an OAuth App
+cat >>$root/conf/httpd.conf <<EOF
+# Generated by: oauth-app-conf $*
+AddAuthOAuthApp $id $secret
+
+EOF
+
diff --git a/sca-cpp/trunk/modules/oauth/oauth-conf b/sca-cpp/trunk/modules/oauth/oauth-conf
new file mode 100755
index 0000000000..7123d8710e
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/oauth-conf
@@ -0,0 +1,64 @@
+#!/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.
+
+# Generate an OAuth server conf
+here=`readlink -f $0`; here=`dirname $here`
+mkdir -p $1
+root=`readlink -f $1`
+
+conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
+host=`echo $conf | awk '{ print $6 }'`
+
+# Configure HTTPD mod_tuscany_oauth module
+cat >>$root/conf/httpd.conf <<EOF
+# Generated by: oauth-conf $*
+# Load support for OAuth authentication
+LoadModule mod_tuscany_oauth $here/libmod_tuscany_oauth.so
+
+# Enable OAuth authentication
+<Location />
+AuthType Open
+AuthOAuth On
+AuthOAuthLoginPage /login
+</Location>
+
+# Enable unauthenticated access to unprotected areas
+<Location /login>
+AuthOAuth Off
+</Location>
+<Location /logout>
+AuthOAuth Off
+</Location>
+<Location /unprotected>
+AuthOAuth Off
+</Location>
+
+EOF
+
+cat >>$root/conf/vhost-ssl.conf <<EOF
+# Generated by: openid-conf $*
+# Require OAuth authentication
+<Location />
+AuthType Open
+AuthName "$host"
+Require valid-user
+</Location>
+
+EOF
+
diff --git a/sca-cpp/trunk/modules/oauth/oauth-memcached-conf b/sca-cpp/trunk/modules/oauth/oauth-memcached-conf
new file mode 100755
index 0000000000..8c133688d7
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/oauth-memcached-conf
@@ -0,0 +1,32 @@
+#!/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.
+
+here=`readlink -f $0`; here=`dirname $here`
+mkdir -p $1
+root=`readlink -f $1`
+host=$2
+port=$3
+
+# Configure HTTPD mod_tuscany_oauth module cache
+cat >>$root/conf/httpd.conf <<EOF
+# Generated by: oauth-cache-conf $*
+AddAuthOAuthMemcached $host:$port
+
+EOF
+
diff --git a/sca-cpp/trunk/modules/oauth/oauth.composite b/sca-cpp/trunk/modules/oauth/oauth.composite
new file mode 100644
index 0000000000..b1fc095ce5
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/oauth.composite
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
+ name="oauth">
+
+ <component name="Protected">
+ <t:implementation.widget location="protected/index.html"/>
+ <reference name="userInfo" target="UserInfo"/>
+ </component>
+
+ <component name="UserInfo">
+ <t:implementation.scheme script="user-info.scm"/>
+ <service name="info">
+ <t:binding.jsonrpc uri="info"/>
+ </service>
+ <property name="user">anonymous</property>
+ <property name="email">anonymous@example.com</property>
+ </component>
+
+</composite>
diff --git a/sca-cpp/trunk/modules/oauth/start-test b/sca-cpp/trunk/modules/oauth/start-test
new file mode 100755
index 0000000000..0946397f1a
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/start-test
@@ -0,0 +1,42 @@
+#!/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.
+
+# Setup
+../../components/cache/memcached-start 11212
+../../components/cache/memcached-start 11213
+
+../../modules/http/ssl-ca-conf tmp localhost
+../../modules/http/ssl-cert-conf tmp localhost
+../../modules/http/httpd-conf tmp localhost 8090 htdocs
+../../modules/http/httpd-ssl-conf tmp 8453
+
+./oauth-conf tmp
+./oauth-memcached-conf tmp localhost 11212
+./oauth-memcached-conf tmp localhost 11213
+./oauth-app-conf tmp app1234 secret6789
+
+../../modules/server/server-conf tmp
+../../modules/server/scheme-conf tmp
+cat >>tmp/conf/httpd.conf <<EOF
+SCAContribution `pwd`/
+SCAComposite oauth.composite
+EOF
+
+../../modules/http/httpd-start tmp
+
diff --git a/sca-cpp/trunk/modules/oauth/stop-test b/sca-cpp/trunk/modules/oauth/stop-test
new file mode 100755
index 0000000000..a0587f8cb7
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/stop-test
@@ -0,0 +1,24 @@
+#!/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.
+
+# Cleanup
+../../modules/http/httpd-stop tmp
+
+../../components/cache/memcached-stop 11212
+../../components/cache/memcached-stop 11213
diff --git a/sca-cpp/trunk/modules/oauth/user-info.scm b/sca-cpp/trunk/modules/oauth/user-info.scm
new file mode 100644
index 0000000000..0c4ebcfaf7
--- /dev/null
+++ b/sca-cpp/trunk/modules/oauth/user-info.scm
@@ -0,0 +1,26 @@
+; 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.
+
+; OAuth support test case
+
+(define (get id user email) (list "text/html" (list
+ "<html><body><p>The following info is generated on the server:</p><div>User: " (user) "</div><div>Email: " (email) "</div></body></html>")))
+
+(define (getuser user email) (user))
+
+(define (getemail user email) (email))
+
diff --git a/sca-cpp/trunk/modules/openid/Makefile.am b/sca-cpp/trunk/modules/openid/Makefile.am
index a613f2ef78..ba6e523ad2 100644
--- a/sca-cpp/trunk/modules/openid/Makefile.am
+++ b/sca-cpp/trunk/modules/openid/Makefile.am
@@ -25,7 +25,7 @@ mod_DATA = openid.prefix
openid.prefix: $(top_builddir)/config.status
echo ${MODAUTHOPENID_PREFIX} >openid.prefix
-EXTRA_DIST = openid.composite user-info.scm htdocs/index.html htdocs/login/index.html htdocs/logout/index.html htdocs/protected/index.html
+EXTRA_DIST = openid.composite user-info.scm htdocs/index.html htdocs/login/index.html htdocs/logout/index.html htdocs/unprotected/index.html
dist_noinst_SCRIPTS = start-test stop-test
diff --git a/sca-cpp/trunk/modules/openid/htdocs/login/index.html b/sca-cpp/trunk/modules/openid/htdocs/login/index.html
index 14f378e968..e6b8c6fce3 100644
--- a/sca-cpp/trunk/modules/openid/htdocs/login/index.html
+++ b/sca-cpp/trunk/modules/openid/htdocs/login/index.html
@@ -68,6 +68,10 @@ function withVerisign() {
return 'https://pip.verisignlabs.com/';
}
+function withMySpace() {
+ return 'https://api.myspace.com/openid';
+}
+
function withGoogleApps() {
return 'https://www.google.com/accounts/o8/site-xrds?ns=2&hd=' + document.fields.domain.value;
}
@@ -86,6 +90,7 @@ function withXRDSEndpoint() {
<p>Sign in with your Yahoo account<br/><input type="button" onclick="submitSignin(withYahoo)" value="Sign in"/></p>
<p>Sign in with your MyOpenID account<br/><input type="button" onclick="submitSignin(withMyOpenID)" value="Sign in"/></p>
<p>Sign in with your Verisign account<br/><input type="button" onclick="submitSignin(withVerisign)" value="Sign in"/></p>
+<p>Sign in with your MySpace account<br/><input type="button" onclick="submitSignin(withMySpace)" value="Sign in"/></p>
<p>Sign in with a Google apps domain<br/>
<input type="text" size="20" name="domain" value="example.com"/><br/>
<input type="button" onclick="submitSignin(withGoogleApps)" value="Sign in"/></p>
diff --git a/sca-cpp/trunk/modules/openid/htdocs/logout/index.html b/sca-cpp/trunk/modules/openid/htdocs/logout/index.html
index 5b58a1c38b..02a92d1b31 100644
--- a/sca-cpp/trunk/modules/openid/htdocs/logout/index.html
+++ b/sca-cpp/trunk/modules/openid/htdocs/logout/index.html
@@ -23,7 +23,7 @@
<form name="signout" action="/login" method="GET">
<script type="text/javascript">
function submitSignout() {
- document.cookie = 'TuscanyOpenIDAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE';
+ document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE';
document.signout.submit();
return true;
}
diff --git a/sca-cpp/trunk/modules/openid/openid-conf b/sca-cpp/trunk/modules/openid/openid-conf
index a8314261ac..95cdb1945c 100755
--- a/sca-cpp/trunk/modules/openid/openid-conf
+++ b/sca-cpp/trunk/modules/openid/openid-conf
@@ -34,13 +34,17 @@ LoadModule authopenid_module $openid_prefix/modules/mod_auth_openid.so
# Enable OpenID authentication
<Location />
-AuthType OpenID
+AuthType Open
AuthOpenIDEnabled On
AuthOpenIDCookiePath /
-AuthOpenIDCookieName TuscanyOpenIDAuth
+AuthOpenIDCookieName TuscanyOpenAuth
AuthOpenIDSecureCookie On
AuthOpenIDLoginPage /login
AuthOpenIDAXAdd EMAIL http://axschema.org/contact/email
+AuthOpenIDAXAdd FULLNAME http://axschema.org/namePerson
+AuthOpenIDAXAdd NICKNAME http://axschema.org/namePerson/friendly
+AuthOpenIDAXAdd FIRSTNAME http://axschema.org/namePerson/first
+AuthOpenIDAXAdd LASTNAME http://axschema.org/namePerson/last
</Location>
# Enable unauthenticated access to unprotected areas
@@ -60,7 +64,7 @@ cat >>$root/conf/vhost-ssl.conf <<EOF
# Generated by: openid-conf $*
# Require OpenID authentication
<Location />
-AuthType OpenID
+AuthType Open
AuthName "$host"
Require valid-user
</Location>
diff --git a/sca-cpp/trunk/modules/server/client-test.hpp b/sca-cpp/trunk/modules/server/client-test.hpp
index f2fdb60877..c17f012012 100644
--- a/sca-cpp/trunk/modules/server/client-test.hpp
+++ b/sca-cpp/trunk/modules/server/client-test.hpp
@@ -46,7 +46,7 @@ ostream* curlWriter(const string& s, ostream* os) {
const bool testGet() {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
{
ostringstream os;
const failable<list<ostream*> > r = http::get<ostream*>(curlWriter, &os, "http://localhost:8090/index.html", ch);
@@ -76,7 +76,7 @@ struct getLoop {
const bool testGetPerf() {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
const lambda<bool()> gl = getLoop(ch);
cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl;
return true;
@@ -84,7 +84,7 @@ const bool testGetPerf() {
const bool testEval() {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), testURI, ch));
assert(val == string("Hello"));
return true;
@@ -119,7 +119,7 @@ struct blobEvalLoop {
const bool testEvalPerf() {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
const lambda<bool()> el = evalLoop(testURI, ch);
cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl;
@@ -136,7 +136,7 @@ bool testPost() {
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
const failable<value> id = http::post(a, testURI, ch);
assert(hasContent(id));
return true;
@@ -171,7 +171,7 @@ struct postBlobLoop {
const bool testPostPerf() {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
{
const list<value> i = list<value>()
+ (list<value>() + "name" + string("Apple"))
@@ -197,7 +197,7 @@ const bool testPostPerf() {
const bool postThread(const string& uri, const int count, const value& val) {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
const lambda<bool()> pl = postLoop(uri, val, ch);
time(pl, 0, count);
return true;
@@ -251,7 +251,7 @@ const bool testPostThreadPerf() {
const bool postProc(const string& uri, const int count, const value& val) {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
const lambda<bool()> pl = postLoop(uri, val, ch);
time(pl, 0, count);
return true;
@@ -315,7 +315,7 @@ const bool testPut() {
+ (list<value>() + "name" + string("Apple"))
+ (list<value>() + "price" + string("$2.99"));
const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
value rc = content(http::put(a, testURI + "/111", ch));
assert(rc == value(true));
return true;
@@ -323,7 +323,7 @@ const bool testPut() {
const bool testDel() {
gc_scoped_pool pool;
- http::CURLSession ch;
+ http::CURLSession ch("", "", "");
value rc = content(http::del(testURI + "/111", ch));
assert(rc == value(true));
return true;
diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp
index 95c3d7cd09..40164530b7 100644
--- a/sca-cpp/trunk/modules/server/mod-eval.hpp
+++ b/sca-cpp/trunk/modules/server/mod-eval.hpp
@@ -194,7 +194,7 @@ const failable<int> post(request_rec* r, const lambda<value(const list<value>&)>
// Return the created resource location
debug(content(val), "modeval::post::location");
- apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, httpd::url(content(val), r)));
+ apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(httpd::url(r->uri, content(val), r))));
r->status = HTTP_CREATED;
return OK;
}
@@ -366,15 +366,16 @@ struct hostPropProxy {
}
};
-struct emailPropProxy {
+struct envPropProxy {
+ const string name;
const value v;
- emailPropProxy(const value& v) : v(v) {
+ envPropProxy(const string& name, const value& v) : name(name), v(v) {
}
const value operator()(unused const list<value>& params) const {
- const char* email = apr_table_get(currentRequest->subprocess_env, "EMAIL");
- if (email == NULL || *email == '\0')
+ const char* env = apr_table_get(currentRequest->subprocess_env, c_str(name));
+ if (env == NULL || *env == '\0')
return v;
- return string(email);
+ return string(env);
}
};
@@ -392,10 +393,18 @@ struct userPropProxy {
const value mkpropProxy(const value& prop) {
if (scdl::name(prop) == "host")
return lambda<value(const list<value>&)>(hostPropProxy(elementValue(prop)));
- if (scdl::name(prop) == "email")
- return lambda<value(const list<value>&)>(emailPropProxy(elementValue(prop)));
if (scdl::name(prop) == "user")
return lambda<value(const list<value>&)>(userPropProxy(elementValue(prop)));
+ if (scdl::name(prop) == "email")
+ return lambda<value(const list<value>&)>(envPropProxy("EMAIL", elementValue(prop)));
+ if (scdl::name(prop) == "nickname")
+ return lambda<value(const list<value>&)>(envPropProxy("NICKNAME", elementValue(prop)));
+ if (scdl::name(prop) == "fullname")
+ return lambda<value(const list<value>&)>(envPropProxy("FULLNAME", elementValue(prop)));
+ if (scdl::name(prop) == "firstname")
+ return lambda<value(const list<value>&)>(envPropProxy("FIRSTNAME", elementValue(prop)));
+ if (scdl::name(prop) == "lastname")
+ return lambda<value(const list<value>&)>(envPropProxy("LASTNAME", elementValue(prop)));
return lambda<value(const list<value>&)>(propProxy(elementValue(prop)));
}
@@ -828,7 +837,6 @@ const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) {
sc.key = arg;
return NULL;
}
-
const char* confEnv(unused cmd_parms *cmd, unused void *c, const char *name, const char *value) {
gc_scoped_pool pool(cmd->pool);
setenv(name, value != NULL? value : "", 1);
diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp
index 188aa620fb..1a7105013c 100644
--- a/sca-cpp/trunk/modules/server/mod-wiring.cpp
+++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp
@@ -112,12 +112,9 @@ int translateReference(const ServerConf& sc, request_rec *r) {
return OK;
}
- r->status = HTTP_MOVED_TEMPORARILY;
- apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(target)));
- r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/") + target));
debug(target, "modwiring::translateReference::location");
r->handler = "mod_tuscany_wiring";
- return OK;
+ return httpd::externalRedirect(target, r);
}
// Route to a relative target URI using a local internal redirect
@@ -397,8 +394,7 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp,
*/
void childInit(apr_pool_t* p, server_rec* s) {
gc_scoped_pool pool(p);
- ServerConf *conf = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_wiring);
- if(conf == NULL) {
+ if(ap_get_module_config(s->module_config, &mod_tuscany_wiring) == NULL) {
cfailure << "[Tuscany] Due to one or more errors mod_tuscany_wiring loading failed. Causing apache to stop loading." << endl;
exit(APEXIT_CHILDFATAL);
}
diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/login/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/login/index.html
index 14f378e968..e6b8c6fce3 100644
--- a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/login/index.html
+++ b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/login/index.html
@@ -68,6 +68,10 @@ function withVerisign() {
return 'https://pip.verisignlabs.com/';
}
+function withMySpace() {
+ return 'https://api.myspace.com/openid';
+}
+
function withGoogleApps() {
return 'https://www.google.com/accounts/o8/site-xrds?ns=2&hd=' + document.fields.domain.value;
}
@@ -86,6 +90,7 @@ function withXRDSEndpoint() {
<p>Sign in with your Yahoo account<br/><input type="button" onclick="submitSignin(withYahoo)" value="Sign in"/></p>
<p>Sign in with your MyOpenID account<br/><input type="button" onclick="submitSignin(withMyOpenID)" value="Sign in"/></p>
<p>Sign in with your Verisign account<br/><input type="button" onclick="submitSignin(withVerisign)" value="Sign in"/></p>
+<p>Sign in with your MySpace account<br/><input type="button" onclick="submitSignin(withMySpace)" value="Sign in"/></p>
<p>Sign in with a Google apps domain<br/>
<input type="text" size="20" name="domain" value="example.com"/><br/>
<input type="button" onclick="submitSignin(withGoogleApps)" value="Sign in"/></p>
diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/logout/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/logout/index.html
index 55cbfac110..02a92d1b31 100644
--- a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/logout/index.html
+++ b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/jane/logout/index.html
@@ -23,7 +23,7 @@
<form name="signout" action="/login" method="GET">
<script type="text/javascript">
function submitSignout() {
- document.cookie = 'open_id_session_id=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/';
+ document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE';
document.signout.submit();
return true;
}
diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/login/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/login/index.html
index 14f378e968..e6b8c6fce3 100644
--- a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/login/index.html
+++ b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/login/index.html
@@ -68,6 +68,10 @@ function withVerisign() {
return 'https://pip.verisignlabs.com/';
}
+function withMySpace() {
+ return 'https://api.myspace.com/openid';
+}
+
function withGoogleApps() {
return 'https://www.google.com/accounts/o8/site-xrds?ns=2&hd=' + document.fields.domain.value;
}
@@ -86,6 +90,7 @@ function withXRDSEndpoint() {
<p>Sign in with your Yahoo account<br/><input type="button" onclick="submitSignin(withYahoo)" value="Sign in"/></p>
<p>Sign in with your MyOpenID account<br/><input type="button" onclick="submitSignin(withMyOpenID)" value="Sign in"/></p>
<p>Sign in with your Verisign account<br/><input type="button" onclick="submitSignin(withVerisign)" value="Sign in"/></p>
+<p>Sign in with your MySpace account<br/><input type="button" onclick="submitSignin(withMySpace)" value="Sign in"/></p>
<p>Sign in with a Google apps domain<br/>
<input type="text" size="20" name="domain" value="example.com"/><br/>
<input type="button" onclick="submitSignin(withGoogleApps)" value="Sign in"/></p>
diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/logout/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/logout/index.html
index 55cbfac110..02a92d1b31 100644
--- a/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/logout/index.html
+++ b/sca-cpp/trunk/samples/store-cluster/htdocs/domains/joe/logout/index.html
@@ -23,7 +23,7 @@
<form name="signout" action="/login" method="GET">
<script type="text/javascript">
function submitSignout() {
- document.cookie = 'open_id_session_id=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/';
+ document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE';
document.signout.submit();
return true;
}
diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html
index 14f378e968..e6b8c6fce3 100644
--- a/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html
+++ b/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html
@@ -68,6 +68,10 @@ function withVerisign() {
return 'https://pip.verisignlabs.com/';
}
+function withMySpace() {
+ return 'https://api.myspace.com/openid';
+}
+
function withGoogleApps() {
return 'https://www.google.com/accounts/o8/site-xrds?ns=2&hd=' + document.fields.domain.value;
}
@@ -86,6 +90,7 @@ function withXRDSEndpoint() {
<p>Sign in with your Yahoo account<br/><input type="button" onclick="submitSignin(withYahoo)" value="Sign in"/></p>
<p>Sign in with your MyOpenID account<br/><input type="button" onclick="submitSignin(withMyOpenID)" value="Sign in"/></p>
<p>Sign in with your Verisign account<br/><input type="button" onclick="submitSignin(withVerisign)" value="Sign in"/></p>
+<p>Sign in with your MySpace account<br/><input type="button" onclick="submitSignin(withMySpace)" value="Sign in"/></p>
<p>Sign in with a Google apps domain<br/>
<input type="text" size="20" name="domain" value="example.com"/><br/>
<input type="button" onclick="submitSignin(withGoogleApps)" value="Sign in"/></p>
diff --git a/sca-cpp/trunk/samples/store-cluster/htdocs/logout/index.html b/sca-cpp/trunk/samples/store-cluster/htdocs/logout/index.html
index 5b58a1c38b..02a92d1b31 100644
--- a/sca-cpp/trunk/samples/store-cluster/htdocs/logout/index.html
+++ b/sca-cpp/trunk/samples/store-cluster/htdocs/logout/index.html
@@ -23,7 +23,7 @@
<form name="signout" action="/login" method="GET">
<script type="text/javascript">
function submitSignout() {
- document.cookie = 'TuscanyOpenIDAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE';
+ document.cookie = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';path=/;secure=TRUE';
document.signout.submit();
return true;
}
diff --git a/sca-cpp/trunk/ubuntu/ubuntu-install-all b/sca-cpp/trunk/ubuntu/ubuntu-install-all
index 288e73ae9a..9a717781e7 100755
--- a/sca-cpp/trunk/ubuntu/ubuntu-install-all
+++ b/sca-cpp/trunk/ubuntu/ubuntu-install-all
@@ -323,7 +323,7 @@ git clone git://git.apache.org/tuscany-sca-cpp.git
cd tuscany-sca-cpp
cp etc/git-exclude .git/info/exclude
./bootstrap
-./configure --prefix=$build/tuscany-sca-cpp-bin --with-curl=$build/curl-7.19.5-bin --with-apr=$build/httpd-2.2.16-bin --with-httpd=$build/httpd-2.2.16-bin --with-memcached=$build/memcached-1.4.4-bin --with-tinycdb=$build/tinycdb-0.77-bin --with-js-include=$build/tracemonkey-bin/include/js --with-js-lib=$build/tracemonkey-bin/lib --with-libcloud=$build/libcloud-0.3.1-bin --enable-threads --enable-python --enable-gae --with-gae=$build/google_appengine --enable-java --with-java=/usr/lib/jvm/java-6-openjdk --enable-webservice --with-libxml2=$build/libxml2-2.7.7-bin --with-axis2c=$build/axis2c-1.6.0-bin --enable-queue --with-qpidc=$build/qpidc-0.6-bin --enable-chat --with-libstrophe=$build/libstrophe-bin --with-vysper=$build/vysper-0.5 --enable-sqldb --with-pgsql=$build/postgresql-9.0-bin --enable-log --with-thrift=$build/thrift-0.2.0-bin --with-scribe=$build/scribe-2.2-bin --enable-openid --with-mod-auth-openid=$build/mod-auth-openid-bin
+./configure --prefix=$build/tuscany-sca-cpp-bin --with-curl=$build/curl-7.19.5-bin --with-apr=$build/httpd-2.2.16-bin --with-httpd=$build/httpd-2.2.16-bin --with-memcached=$build/memcached-1.4.4-bin --with-tinycdb=$build/tinycdb-0.77-bin --with-js-include=$build/tracemonkey-bin/include/js --with-js-lib=$build/tracemonkey-bin/lib --with-libcloud=$build/libcloud-0.3.1-bin --enable-threads --enable-python --enable-gae --with-gae=$build/google_appengine --enable-java --with-java=/usr/lib/jvm/java-6-openjdk --enable-webservice --with-libxml2=$build/libxml2-2.7.7-bin --with-axis2c=$build/axis2c-1.6.0-bin --enable-queue --with-qpidc=$build/qpidc-0.6-bin --enable-chat --with-libstrophe=$build/libstrophe-bin --with-vysper=$build/vysper-0.5 --enable-sqldb --with-pgsql=$build/postgresql-9.0-bin --enable-log --with-thrift=$build/thrift-0.2.0-bin --with-scribe=$build/scribe-2.2-bin --enable-openid --with-mod-auth-openid=$build/mod-auth-openid-bin --enable-oauth
make
make install
if [ "$?" != "0" ]; then