diff options
35 files changed, 890 insertions, 120 deletions
diff --git a/sca-cpp/trunk/modules/http/httpd-ssl-conf b/sca-cpp/trunk/modules/http/httpd-ssl-conf index e48902fd82..5f1058ea75 100755 --- a/sca-cpp/trunk/modules/http/httpd-ssl-conf +++ b/sca-cpp/trunk/modules/http/httpd-ssl-conf @@ -117,7 +117,7 @@ BrowserMatch ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-res SSLOptions -StrictRequire +OptRenegotiate # Verify client certificates -SSLVerifyClient optional +SSLVerifyClient none SSLVerifyDepth 1 # Enable SSL proxy engine @@ -195,7 +195,7 @@ SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 and ( \ ( %{SSL_CLIENT_I_DN_O} == "$org" and %{SSL_CLIENT_S_DN_OU} == "tunnel" ) or \ ( %{SSL_CLIENT_I_DN_O} == "$org" and %{SSL_CLIENT_S_DN_OU} == "proxy" and \ %{HTTP:X-Forwarded-SSL-Issuer-DN-O} == "$org" and %{HTTP:X-Forwarded-SSL-Client-DN-OU} == "server" ) or \ -%{REQUEST_URI} =~ m/^.(login|logout|openid|unprotected).*$/ ) +%{REQUEST_URI} =~ m/^.(login|logout|openid|public|ui).*$/ ) # Record received SSL client certificate info in environment vars RewriteEngine on diff --git a/sca-cpp/trunk/modules/oauth/Makefile.am b/sca-cpp/trunk/modules/oauth/Makefile.am index 84bbe32eec..6c0cd2bc57 100644 --- a/sca-cpp/trunk/modules/oauth/Makefile.am +++ b/sca-cpp/trunk/modules/oauth/Makefile.am @@ -35,7 +35,7 @@ libmod_tuscany_oauth2_la_LDFLAGS = -lxml2 -lcurl -lmozjs libmod_tuscany_oauth2.so: ln -s .libs/libmod_tuscany_oauth2.so -EXTRA_DIST = oauth.composite user-info.scm htdocs/index.html htdocs/login/index.html htdocs/logout/index.html htdocs/unprotected/index.html +EXTRA_DIST = oauth.composite user-info.scm htdocs/index.html htdocs/login/index.html htdocs/logout/index.html htdocs/public/index.html dist_noinst_SCRIPTS = start-test stop-test diff --git a/sca-cpp/trunk/modules/oauth/htdocs/index.html b/sca-cpp/trunk/modules/oauth/htdocs/index.html index 779ea74986..e8cdd2f26b 100644 --- a/sca-cpp/trunk/modules/oauth/htdocs/index.html +++ b/sca-cpp/trunk/modules/oauth/htdocs/index.html @@ -22,13 +22,14 @@ <script type="text/javascript" src="/js/ref.js"></script> <script type="text/javascript"> var protected = component("Protected"); -var userInfo = reference(protected, "userInfo"); -var user = userInfo.apply("getuser"); +var userInfo = defun(reference(protected, "userInfo"), "getuser", "getemail", "getnickname", "getfullname", "getfirstname", "getlastname", "getrealm"); +var user = userInfo.getuser(); var email = userInfo.apply("getemail"); var nickname = userInfo.apply("getnickname"); var fullname = userInfo.apply("getfullname"); var firstname = userInfo.apply("getfirstname"); var lastname = userInfo.apply("getlastname"); +var realm = userInfo.apply("getrealm"); </script> </head> <body> @@ -40,6 +41,7 @@ var lastname = userInfo.apply("getlastname"); <div>Fullname: <span id="fullname"></span></div> <div>Firstname: <span id="firstname"></span></div> <div>Lastname: <span id="lastname"></span></div> +<div>Realm: <span id="realm"></span></div> <script type="text/javascript"> document.getElementById('user').innerHTML=user; document.getElementById('email').innerHTML=email; @@ -47,9 +49,10 @@ document.getElementById('nickname').innerHTML=nickname; document.getElementById('fullname').innerHTML=fullname; document.getElementById('firstname').innerHTML=firstname; document.getElementById('lastname').innerHTML=lastname; +document.getElementById('realm').innerHTML=realm; </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> +<p><a href="public">Public 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 index 607c55ca18..8cdcb1cf64 100644 --- a/sca-cpp/trunk/modules/oauth/htdocs/login/index.html +++ b/sca-cpp/trunk/modules/oauth/htdocs/login/index.html @@ -56,12 +56,12 @@ function submitSignin2(w) { } function withFacebook() { - var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'testfacebookapp', 'https://graph.facebook.com/me']; + var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'facebook.com', 'https://graph.facebook.com/me']; return parms; } function withGithub() { - var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'testgithubapp', 'https://github.com/api/v2/json/user/show']; + var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'github.com', 'https://github.com/api/v2/json/user/show']; return parms; } @@ -77,12 +77,12 @@ function submitSignin1(w) { } function withLinkedin() { - var parms = ['https://api.linkedin.com/uas/oauth/requestToken', 'https://www.linkedin.com/uas/oauth/authorize', 'https://api.linkedin.com/uas/oauth/accessToken', 'testlinkedinapp', 'https://api.linkedin.com/v1/people/~:(id,first-name,last-name,public-profile-url)']; + var parms = ['https://api.linkedin.com/uas/oauth/requestToken', 'https://www.linkedin.com/uas/oauth/authorize', 'https://api.linkedin.com/uas/oauth/accessToken', 'linkedin.com', 'https://api.linkedin.com/v1/people/~:(id,first-name,last-name,public-profile-url)']; return parms; } function withTwitter() { - var parms = ['https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/authorize', 'https://api.twitter.com/oauth/access_token', 'testtwitterapp', 'https://api.twitter.com/1/statuses/user_timeline.json']; + var parms = ['https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/authorize', 'https://api.twitter.com/oauth/access_token', 'twitter.com', 'https://api.twitter.com/1/statuses/user_timeline.json']; return parms; } </script> diff --git a/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html b/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html index c187aa2a84..10773c4538 100644 --- a/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html +++ b/sca-cpp/trunk/modules/oauth/htdocs/login/mixed.html @@ -102,12 +102,12 @@ function submitOAuth2Signin(w) { } function withFacebook() { - var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'testfacebookapp', 'https://graph.facebook.com/me']; + var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'facebook.com', 'https://graph.facebook.com/me']; return parms; } function withGithub() { - var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'testgithubapp', 'https://github.com/api/v2/json/user/show']; + var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'github.com', 'https://github.com/api/v2/json/user/show']; return parms; } @@ -123,12 +123,12 @@ function submitOAuth1Signin(w) { } function withLinkedin() { - var parms = ['https://api.linkedin.com/uas/oauth/requestToken', 'https://www.linkedin.com/uas/oauth/authorize', 'https://api.linkedin.com/uas/oauth/accessToken', 'testlinkedinapp', 'https://api.linkedin.com/v1/people/~:(id,first-name,last-name,public-profile-url)']; + var parms = ['https://api.linkedin.com/uas/oauth/requestToken', 'https://www.linkedin.com/uas/oauth/authorize', 'https://api.linkedin.com/uas/oauth/accessToken', 'linkedin.com', 'https://api.linkedin.com/v1/people/~:(id,first-name,last-name,public-profile-url)']; return parms; } function withTwitter() { - var parms = ['https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/authorize', 'https://api.twitter.com/oauth/access_token', 'testtwitterapp', 'https://api.twitter.com/1/statuses/user_timeline.json']; + var parms = ['https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/authorize', 'https://api.twitter.com/oauth/access_token', 'twitter.com', 'https://api.twitter.com/1/statuses/user_timeline.json']; return parms; } </script> diff --git a/sca-cpp/trunk/modules/oauth/htdocs/unprotected/index.html b/sca-cpp/trunk/modules/oauth/htdocs/public/index.html index af2cd7ca19..af2cd7ca19 100644 --- a/sca-cpp/trunk/modules/oauth/htdocs/unprotected/index.html +++ b/sca-cpp/trunk/modules/oauth/htdocs/public/index.html diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp index 23ef90b0dd..22fdd0cce3 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp @@ -105,6 +105,12 @@ static int checkUserID(request_rec *r) { const failable<int> authenticated(const list<list<value> >& info, request_rec* r) { debug(info, "modoauth1::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"); + 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"); @@ -250,35 +256,53 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co /** * Extract user info from a profile/info response. - * TODO This currently only works for twitter and linkedin profiles and - * needs to be made configurable. + * TODO This currently only works for Twitter, Foursquare and LinkedIn. + * User profile parsing needs to be made configurable. */ -const failable<list<value> > profileUserInfo(const string& info) { - if (substr(info, 0, 1) == "[") { - // JSON profile +const failable<list<value> > profileUserInfo(const value& cid, const string& info) { + string b = substr(info, 0, 1); + if (b == "[") { + // Twitter JSON profile json::JSONContext cx; const list<value> infov(json::jsonValues(content(json::readJSON(mklist<string>(info), cx)))); if (isNil(infov)) return mkfailure<list<value> >("Couldn't retrieve user info"); debug(infov, "modoauth1::access_token::info"); const list<value> uv = assoc<value>("user", car(infov)); + debug(uv, "modoauth1::access_token::userInfo"); if (isNil(uv) || isNil(cdr(uv))) return mkfailure<list<value> >("Couldn't retrieve user info"); const list<value> iv = cdr(uv); - return iv; - - } else { + return cons<value>(mklist<value>("realm", cid), iv); + } + if (b == "{") { + // Foursquare JSON profile + json::JSONContext cx; + const list<value> infov(json::jsonValues(content(json::readJSON(mklist<string>(info), cx)))); + if (isNil(infov)) + return mkfailure<list<value> >("Couldn't retrieve user info"); + debug(infov, "modoauth1::access_token::info"); + const list<value> uv = assoc<value>("user", infov); + debug(uv, "modoauth1::access_token::userInfo"); + if (isNil(uv) || isNil(cdr(uv))) + return mkfailure<list<value> >("Couldn't retrieve user info"); + const list<value> iv = cdr(uv); + return cons<value>(mklist<value>("realm", cid), iv); + } + if (b == "<") { // XML profile const list<value> infov = elementsToValues(readXML(mklist<string>(info))); if (isNil(infov)) return mkfailure<list<value> >("Couldn't retrieve user info"); debug(infov, "modoauth1::access_token::info"); const list<value> pv = car(infov); + debug(pv, "modoauth1::access_token::userInfo"); if (isNil(pv) || isNil(cdr(pv))) return mkfailure<list<value> >("Couldn't retrieve user info"); const list<value> iv = cdr(pv); - return iv; + return cons<value>(mklist<value>("realm", cid), iv); } + return mkfailure<list<value> >("Couldn't retrieve user info"); } /** @@ -356,7 +380,7 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, debug(profres, "modoauth1::access_token::profres"); // Retrieve the user info from the profile - const failable<list<value> > iv = profileUserInfo(profres); + const failable<list<value> > iv = profileUserInfo(cadr(cid), profres); if (!hasContent(iv)) return mkfailure<int>(reason(iv)); diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp index 60eadc282c..bb96fcb916 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp @@ -164,6 +164,15 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co } /** + * Extract user info from a profile/info response. + * TODO This currently only works for Facebook and Gowalla. + * User profile parsing needs to be made configurable. + */ +const failable<list<value> > profileUserInfo(const value& cid, const list<value>& info) { + return cons<value>(mklist<value>("realm", cid), info); +} + +/** * Handle an access_token request. */ const failable<int> access_token(const list<list<value> >& args, request_rec* r, const ServerConf& sc) { @@ -210,10 +219,15 @@ const failable<int> access_token(const list<list<value> >& args, request_rec* r, const list<list<value> > iargs = mklist<list<value> >(tv); const string iuri = httpd::unescape(cadr(info)) + string("?") + httpd::queryString(iargs); debug(iuri, "modoauth2::access_token::infouri"); - const failable<value> iv = http::get(iuri, sc.cs); - if (!hasContent(iv)) + const failable<value> profres = http::get(iuri, sc.cs); + if (!hasContent(profres)) return mkfailure<int>("Couldn't retrieve user info"); - debug(content(iv), "modoauth2::access_token::info"); + debug(content(profres), "modoauth2::access_token::info"); + + // Retrieve the user info from the profile + const failable<list<value> > iv = profileUserInfo(cadr(cid), content(profres)); + if (!hasContent(iv)) + return mkfailure<int>(reason(iv)); // Store user info in memcached keyed by session ID const value sid = string("OAuth2_") + mkrand(); diff --git a/sca-cpp/trunk/modules/oauth/oauth-conf b/sca-cpp/trunk/modules/oauth/oauth-conf index 5c3fde2ccc..91ae1916c7 100755 --- a/sca-cpp/trunk/modules/oauth/oauth-conf +++ b/sca-cpp/trunk/modules/oauth/oauth-conf @@ -39,14 +39,17 @@ AuthOAuth On AuthOAuthLoginPage /login </Location> -# Enable unauthenticated access to unprotected areas +# Enable unauthenticated access to public areas <Location /login> AuthOAuth Off </Location> <Location /logout> AuthOAuth Off </Location> -<Location /unprotected> +<Location /public> +AuthOAuth Off +</Location> +<Location /ui> AuthOAuth Off </Location> diff --git a/sca-cpp/trunk/modules/oauth/oauth.composite b/sca-cpp/trunk/modules/oauth/oauth.composite index 0119db22c9..c2025493c8 100644 --- a/sca-cpp/trunk/modules/oauth/oauth.composite +++ b/sca-cpp/trunk/modules/oauth/oauth.composite @@ -38,6 +38,7 @@ <property name="fullname">?</property> <property name="firstname">?</property> <property name="lastname">?</property> + <property name="realm">?</property> </component> </composite> diff --git a/sca-cpp/trunk/modules/oauth/oauth.hpp b/sca-cpp/trunk/modules/oauth/oauth.hpp index ab92cbd381..cea16e035f 100644 --- a/sca-cpp/trunk/modules/oauth/oauth.hpp +++ b/sca-cpp/trunk/modules/oauth/oauth.hpp @@ -43,10 +43,15 @@ namespace oauth { /** * Return the session id from a request. */ +const char* cookieName(const char* cs) { + if (*cs != ' ') + return cs; + return cookieName(cs + 1); +} const maybe<string> sessionID(const list<string> c) { if (isNil(c)) return maybe<string>(); - const list<string> kv = tokenize("=", car(c)); + const list<string> kv = tokenize("=", cookieName(c_str(car(c)))); if (!isNil(kv) && !isNil(cdr(kv))) { if (car(kv) == "TuscanyOpenAuth") return cadr(kv); diff --git a/sca-cpp/trunk/modules/oauth/start-mixed-test b/sca-cpp/trunk/modules/oauth/start-mixed-test index 468e6861d8..e838e9bb83 100755 --- a/sca-cpp/trunk/modules/oauth/start-mixed-test +++ b/sca-cpp/trunk/modules/oauth/start-mixed-test @@ -34,10 +34,10 @@ here=`readlink -f $0`; here=`dirname $here` ./oauth-memcached-conf tmp localhost 11213 # Configure your app keys here -./oauth1-appkey-conf tmp testtwitterapp app2345 secret7890 -./oauth1-appkey-conf tmp testlinkedinapp app3456 secret4567 -./oauth2-appkey-conf tmp testfacebookapp app1234 secret6789 -./oauth2-appkey-conf tmp testgithubapp app5678 secret8901 +./oauth1-appkey-conf tmp twitter.com app2345 secret7890 +./oauth1-appkey-conf tmp linkedin.com app3456 secret4567 +./oauth2-appkey-conf tmp facebook.com app1234 secret6789 +./oauth2-appkey-conf tmp github.com app5678 secret8901 ../openid/openid-conf tmp ../openid/openid-step2-conf tmp diff --git a/sca-cpp/trunk/modules/oauth/start-test b/sca-cpp/trunk/modules/oauth/start-test index 47171a91ae..8c59009102 100755 --- a/sca-cpp/trunk/modules/oauth/start-test +++ b/sca-cpp/trunk/modules/oauth/start-test @@ -21,20 +21,20 @@ ../../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 +../../modules/http/ssl-ca-conf tmp jsdelfino.com +../../modules/http/ssl-cert-conf tmp jsdelfino.com +../../modules/http/httpd-conf tmp jsdelfino.com 8090/80 htdocs +../../modules/http/httpd-ssl-conf tmp 8453/443 ./oauth-conf tmp -./oauth-memcached-conf tmp localhost 11212 -./oauth-memcached-conf tmp localhost 11213 +./oauth-memcached-conf tmp jsdelfino.com 11212 +./oauth-memcached-conf tmp jsdelfino.com 11213 # Configure your app keys here -./oauth1-appkey-conf tmp testtwitterapp app2345 secret7890 -./oauth1-appkey-conf tmp testlinkedinapp app3456 secret4567 -./oauth2-appkey-conf tmp testfacebookapp app1234 secret6789 -./oauth2-appkey-conf tmp testgithubapp app5678 secret8901 +./oauth1-appkey-conf tmp twitter.com app2345 secret7890 +./oauth1-appkey-conf tmp linkedin.com app3456 secret4567 +./oauth2-appkey-conf tmp facebook.com app1234 secret6789 +./oauth2-appkey-conf tmp github.com app5678 secret8901 ../../modules/server/server-conf tmp ../../modules/server/scheme-conf tmp diff --git a/sca-cpp/trunk/modules/oauth/user-info.scm b/sca-cpp/trunk/modules/oauth/user-info.scm index 58a84f86b0..4960a0a455 100644 --- a/sca-cpp/trunk/modules/oauth/user-info.scm +++ b/sca-cpp/trunk/modules/oauth/user-info.scm @@ -17,18 +17,20 @@ ; OAuth support test case -(define (get id user email nickname fullname firstname lastname) (list "text/html" (list - "<html><body><p>The following info is generated on the server:</p><div>User: " (user) "</div><div>Email: " (email) "</div><div>Nickname: " (nickname) "</div><div>Fullname: " (fullname) "</div><div>Firstname: " (firstname) "</div><div>Lastname: " (lastname) "</div></body></html>"))) +(define (get id user email nickname fullname firstname lastname realm) (list "text/html" (list + "<html><body><p>The following info is generated on the server:</p><div>User: " (user) "</div><div>Email: " (email) "</div><div>Nickname: " (nickname) "</div><div>Fullname: " (fullname) "</div><div>Firstname: " (firstname) "</div><div>Lastname: " (lastname) "</div><div>Realm: " (realm) "</div></body></html>"))) -(define (getuser user email nickname fullname firstname lastname) (user)) +(define (getuser user email nickname fullname firstname lastname realm) (user)) -(define (getemail user email nickname fullname firstname lastname) (email)) +(define (getemail user email nickname fullname firstname lastname realm) (email)) -(define (getnickname user email nickname fullname firstname lastname) (nickname)) +(define (getnickname user email nickname fullname firstname lastname realm) (nickname)) -(define (getfullname user email nickname fullname firstname lastname) (fullname)) +(define (getfullname user email nickname fullname firstname lastname realm) (fullname)) -(define (getfirstname user email nickname fullname firstname lastname) (firstname)) +(define (getfirstname user email nickname fullname firstname lastname realm) (firstname)) -(define (getlastname user email nickname fullname firstname lastname) (lastname)) +(define (getlastname user email nickname fullname firstname lastname realm) (lastname)) + +(define (getrealm user email nickname fullname firstname lastname realm) (realm)) diff --git a/sca-cpp/trunk/modules/openid/Makefile.am b/sca-cpp/trunk/modules/openid/Makefile.am index ba6e523ad2..a46dd56743 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/unprotected/index.html +EXTRA_DIST = openid.composite user-info.scm htdocs/index.html htdocs/login/index.html htdocs/logout/index.html htdocs/public/index.html dist_noinst_SCRIPTS = start-test stop-test diff --git a/sca-cpp/trunk/modules/openid/htdocs/index.html b/sca-cpp/trunk/modules/openid/htdocs/index.html index c2dfc791e6..cdc65a4e37 100644 --- a/sca-cpp/trunk/modules/openid/htdocs/index.html +++ b/sca-cpp/trunk/modules/openid/htdocs/index.html @@ -22,9 +22,10 @@ <script type="text/javascript" src="/js/ref.js"></script> <script type="text/javascript"> var protected = component("Protected"); -var userInfo = reference(protected, "userInfo"); -var user = userInfo.apply("getuser"); -var email = userInfo.apply("getemail"); +var userInfo = defun(reference(protected, "userInfo"), "getuser", "getemail", "getrealm"); +var user = userInfo.getuser(); +var email = userInfo.getemail(); +var realm = userInfo.getrealm(); </script> </head> <body> @@ -32,12 +33,14 @@ var email = userInfo.apply("getemail"); <p>The following info is returned by a JSONRPC service:</p> <div id="user"></div> <div id="email"></div> +<div id="realm"></div> <script type="text/javascript"> document.getElementById('user').innerHTML="User: " + user; document.getElementById('email').innerHTML="Email: " + email; +document.getElementById('realm').innerHTML="Realm: " + realm; </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> +<p><a href="public">Public area</a></p> </body></html> diff --git a/sca-cpp/trunk/modules/openid/htdocs/unprotected/index.html b/sca-cpp/trunk/modules/openid/htdocs/public/index.html index af2cd7ca19..af2cd7ca19 100644 --- a/sca-cpp/trunk/modules/openid/htdocs/unprotected/index.html +++ b/sca-cpp/trunk/modules/openid/htdocs/public/index.html diff --git a/sca-cpp/trunk/modules/openid/openid-conf b/sca-cpp/trunk/modules/openid/openid-conf index 95cdb1945c..839b58b554 100755 --- a/sca-cpp/trunk/modules/openid/openid-conf +++ b/sca-cpp/trunk/modules/openid/openid-conf @@ -47,14 +47,17 @@ AuthOpenIDAXAdd FIRSTNAME http://axschema.org/namePerson/first AuthOpenIDAXAdd LASTNAME http://axschema.org/namePerson/last </Location> -# Enable unauthenticated access to unprotected areas +# Enable unauthenticated access to public areas <Location /login> AuthOpenIDEnabled Off </Location> <Location /logout> AuthOpenIDEnabled Off </Location> -<Location /unprotected> +<Location /public> +AuthOpenIDEnabled Off +</Location> +<Location /ui> AuthOpenIDEnabled Off </Location> diff --git a/sca-cpp/trunk/modules/openid/openid.composite b/sca-cpp/trunk/modules/openid/openid.composite index 016139a9a7..08bb74b7c7 100644 --- a/sca-cpp/trunk/modules/openid/openid.composite +++ b/sca-cpp/trunk/modules/openid/openid.composite @@ -34,6 +34,7 @@ </service> <property name="user">anonymous</property> <property name="email">anonymous@example.com</property> + <property name="realm">example.com</property> </component> </composite> diff --git a/sca-cpp/trunk/modules/openid/user-info.scm b/sca-cpp/trunk/modules/openid/user-info.scm index 69eb207be9..b1ef74c6bd 100644 --- a/sca-cpp/trunk/modules/openid/user-info.scm +++ b/sca-cpp/trunk/modules/openid/user-info.scm @@ -17,10 +17,12 @@ ; OpenID 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 (get id user email realm) (list "text/html" (list + "<html><body><p>The following info is generated on the server:</p><div>User: " (user) "</div><div>Email: " (email) "</div><div>Realm: " (realm) "</div></body></html>"))) -(define (getuser user email) (user)) +(define (getuser user email realm) (user)) -(define (getemail user email) (email)) +(define (getemail user email realm) (email)) + +(define (getrealm user email realm) (realm)) diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index 2fe4bd76e0..c2705b0538 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -395,6 +395,8 @@ const value mkpropProxy(const value& prop) { return lambda<value(const list<value>&)>(hostPropProxy(elementValue(prop))); if (scdl::name(prop) == "user") return lambda<value(const list<value>&)>(userPropProxy(elementValue(prop))); + if (scdl::name(prop) == "realm") + return lambda<value(const list<value>&)>(envPropProxy("REALM", elementValue(prop))); if (scdl::name(prop) == "email") return lambda<value(const list<value>&)>(envPropProxy("EMAIL", elementValue(prop))); if (scdl::name(prop) == "nickname") diff --git a/sca-cpp/trunk/modules/wsgi/scdl.py b/sca-cpp/trunk/modules/wsgi/scdl.py index 447dd985c2..97c2f7dd69 100644 --- a/sca-cpp/trunk/modules/wsgi/scdl.py +++ b/sca-cpp/trunk/modules/wsgi/scdl.py @@ -216,13 +216,15 @@ def mkproperty(name, l): return property(name, l) # Evaluate a property, return a lambda function returning the property -# value. The host, user and email properties are configured with the -# values from the HTTP request, if any +# value. The host, user, realm, nickname and email properties are configured +# with the values from the HTTP request, if any. def evalProperty(p): if car(p) == "host": return mkproperty(car(p), lambda: hostProperty(cadr(p), environ)) if car(p) == "user": return mkproperty(car(p), lambda: userProperty(cadr(p))) + if car(p) == "realm": + return mkproperty(car(p), lambda: hostProperty(cadr(p), environ)) if car(p) == "nickname": return mkproperty(car(p), lambda: nicknameProperty(cadr(p))) if car(p) == "email": diff --git a/sca-cpp/trunk/samples/loan-python/Makefile.am b/sca-cpp/trunk/samples/loan-python/Makefile.am new file mode 100644 index 0000000000..0d0027ce6b --- /dev/null +++ b/sca-cpp/trunk/samples/loan-python/Makefile.am @@ -0,0 +1,28 @@ +# 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_PYTHON + +dist_sample_SCRIPTS = start stop +sampledir = $(prefix)/samples/loan-python + +nobase_dist_sample_DATA = loan.py loan-approval.py util.py loan.composite htdocs/*.html + +dist_noinst_SCRIPTS = server-test +TESTS = server-test + +endif diff --git a/sca-cpp/trunk/samples/loan-python/htdocs/index.html b/sca-cpp/trunk/samples/loan-python/htdocs/index.html new file mode 100644 index 0000000000..bb05427a37 --- /dev/null +++ b/sca-cpp/trunk/samples/loan-python/htdocs/index.html @@ -0,0 +1,156 @@ +<!--
+ * 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>
+<title>Store</title>
+
+<script type="text/javascript" src="/js/ref.js"></script>
+
+<script type="text/javascript">
+var component = new tuscany.sca.Component("Store");
+
+//@Reference
+var catalog = new tuscany.sca.Reference("catalog");
+
+//@Reference
+var shoppingCart = new tuscany.sca.Reference("shoppingCart");
+
+//@Reference
+var shoppingTotal = new tuscany.sca.Reference("shoppingTotal");
+
+var catalogItems;
+
+function catalog_itemsResponse(items, exception) {
+ if (exception){
+ alert(exception.message);
+ return;
+ }
+ var catalog = "";
+ for (var i=0; i<items.length; i++) {
+ var item = items[i].name + ' - ' + items[i].price;
+ catalog += '<input name="items" type="checkbox" value="' +
+ item + '">' + item + ' <br>';
+ }
+ document.getElementById('catalog').innerHTML=catalog;
+ catalogItems = items;
+
+}
+
+function shoppingCart_getResponse(feed) {
+ if (feed != null) {
+ var entries = feed.getElementsByTagName("entry");
+ var list = "";
+ for (var i=0; i<entries.length; i++) {
+ var content = entries[i].getElementsByTagName("content")[0];
+ var name = content.getElementsByTagName("name")[0].firstChild.nodeValue;
+ var price = content.getElementsByTagName("price")[0].firstChild.nodeValue;
+ list += name + ' - ' + price + ' <br>';
+ }
+ document.getElementById("shoppingCart").innerHTML = list;
+
+ shoppingTotal.apply("total", shoppingTotal_totalResponse);
+ }
+}
+
+function shoppingTotal_totalResponse(total, exception) {
+ if (exception) {
+ alert(exception.message);
+ return;
+ }
+ document.getElementById('total').innerHTML = total;
+}
+
+function shoppingCart_postResponse(entry) {
+ shoppingCart.get("", shoppingCart_getResponse);
+}
+
+function addToCart() {
+ var items = document.catalogForm.items;
+ var j = 0;
+ for (var i=0; i<items.length; i++)
+ if (items[i].checked) {
+ var entry = '<entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><content type="application/xml">' +
+ '<item>' +
+ '<name>' + catalogItems[i].name + '</name>' +
+ '<currencyCode>' + catalogItems[i].currencyCode + '</currencyCode>' +
+ '<currencySymbol>' + catalogItems[i].currencySymbol + '</currencySymbol>' +
+ '<price>' + catalogItems[i].price + '</price>' +
+ '</item>' +
+ '</content></entry>';
+ shoppingCart.post(entry, shoppingCart_postResponse);
+ items[i].checked = false;
+ }
+}
+function checkoutCart() {
+ document.getElementById('store').innerHTML='<h2>' +
+ 'Thanks for Shopping With Us!</h2>'+
+ '<h2>Your Order</h2>'+
+ '<form name="orderForm">'+
+ document.getElementById('shoppingCart').innerHTML+
+ '<br>'+
+ document.getElementById('total').innerHTML+
+ '<br>'+
+ '<br>'+
+ '<input type="submit" value="Continue Shopping">'+
+ '</form>';
+ shoppingCart.del("", null);
+}
+function deleteCart() {
+ shoppingCart.del("", null);
+ document.getElementById('shoppingCart').innerHTML = "";
+ document.getElementById('total').innerHTML = "";
+}
+
+function init() {
+ try {
+ catalog.apply("items", catalog_itemsResponse);
+ shoppingCart.get("", shoppingCart_getResponse);
+ } catch(e){
+ alert(e);
+ }
+}
+</script>
+
+</head>
+
+<body onload="init()">
+<h1>Store</h1>
+<div id="store">
+<h2>Catalog</h2>
+<form name="catalogForm">
+<div id="catalog" ></div>
+<br>
+<input type="button" onClick="addToCart()" value="Add to Cart">
+</form>
+<br>
+
+<h2>Your Shopping Cart</h2>
+<form name="shoppingCartForm">
+<div id="shoppingCart"></div>
+<br>
+<div id="total"></div>
+<br>
+<input type="button" onClick="checkoutCart()" value="Checkout">
+<input type="button" onClick="deleteCart()" value="Empty">
+<a href="shoppingCart/">(feed)</a>
+</form>
+</div>
+
+</body>
+</html>
diff --git a/sca-cpp/trunk/samples/loan-python/loan-approval.py b/sca-cpp/trunk/samples/loan-python/loan-approval.py new file mode 100644 index 0000000000..3951f16eeb --- /dev/null +++ b/sca-cpp/trunk/samples/loan-python/loan-approval.py @@ -0,0 +1,77 @@ +# 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. + +# Loan approval service implementation +import uuid +import sys +from util import * +from loan import * + +loansId = ("loans", "1234") + +# Return the list of loans +def loans(cache): + l = cache("get", loansId) + if l is None: + return () + return l + +# Post a new loan request +def post(collection, item, cache): + id = str(uuid.uuid1()) + loans = cons(cons(id, cdr(item)), loans(cache)) + cache("put", loansId, loans) + return (id,) + +# Return the person currently processing a loan request +def processor(l): + if approver(l) is not None: + return approver(l) + return assessor(l) + +# Return a list of loans that match a given criteria +def get(r, cache): + # All the loans + if r == (): + return loans(cache) + # Loans that need approval + if car(r) == "needApproval": + return filter(lambda l: (amount(l) >= 10000 or risk(l) == "high") and approval(l) is None, loans(cache)) + # Loans that need a risk assessment + if car(r) == "needAssessment": + return filter(lambda : amount(l) < 10000 and risk(l) is None, loans(cache)) + # Loans currently under approval + if car(r) == "underApproval": + return filter(lambda l: approver(l) is not None, loans(cache)) + # Loans currently under assessment + if car(r) == "underAssessment": + return filter(lambda l: assessor(l) is not None, loans(cache)) + # Loan requests that are unassigned + if car(r) == "unassigned": + return filter(lambda l: processor(l) is None, loans(cache)) + # Loan requests that are assigned and getting processed + if car(r) == "assigned": + return filter(lambda l: processor(l) == cadr(r), loans(cache)) + # Approved loans + if car(r) == "approved": + return filter(lambda l: approval(l) == true, loans(cache)) + # Denied loans + if car(r) == "denied": + return filter(lambda l: approval(l) == false, loans(cache)) + # A particular loan + return filter(lambda l: id(l) == r, loans(cache)) + diff --git a/sca-cpp/trunk/samples/loan-python/loan.composite b/sca-cpp/trunk/samples/loan-python/loan.composite new file mode 100644 index 0000000000..0e64b5bf44 --- /dev/null +++ b/sca-cpp/trunk/samples/loan-python/loan.composite @@ -0,0 +1,46 @@ +<?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://store" + name="store"> + + <component name="LoanApprovalUI"> + <t:implementation.widget/> + <reference name="loanApproval" target="LoanApproval"/> + </component> + + <component name="LoanApproval"> + <t:implementation.python script="loan-approval.py"/> + <service name="LoanApproval"> + <t:binding.atom uri="loan-approval"/> + </service> + <reference name="cache" target="Cache"/> + </component> + + <component name="Cache"> + <implementation.cpp path="../../components/cache" library="libmemcache"/> + <service name="Cache"> + <t:binding.atom uri="cache"/> + </service> + <property name="servers">localhost:11211</property> + </component> + +</composite> diff --git a/sca-cpp/trunk/samples/loan-python/loan.py b/sca-cpp/trunk/samples/loan-python/loan.py new file mode 100644 index 0000000000..9e345cd1f6 --- /dev/null +++ b/sca-cpp/trunk/samples/loan-python/loan.py @@ -0,0 +1,45 @@ +# 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. + +from util import * + +# Loan data type + +def firstName(loan): + return assoc("'firstName", loan) + +def lastName(loan): + return assoc("'lastName", loan) + +def ssn(loan): + return assoc("'ssn", loan) + +def amount(loan): + return assoc("'amount", loan) + +def approver(loan): + return assoc("'approver", loan) + +def approval(loan): + return assoc("'approval", loan) + +def assessor(loan): + return assoc("'assessor", loan) + +def risk(loan): + return assoc("'risk", loan) + diff --git a/sca-cpp/trunk/samples/loan-python/server-test b/sca-cpp/trunk/samples/loan-python/server-test new file mode 100755 index 0000000000..1612bc59e2 --- /dev/null +++ b/sca-cpp/trunk/samples/loan-python/server-test @@ -0,0 +1,58 @@ +#!/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. + +echo "Testing..." +here=`readlink -f $0`; here=`dirname $here` +curl_prefix=`cat $here/../../modules/http/curl.prefix` + +# Setup +./start +sleep 2 + +# Test HTTP GET +$curl_prefix/bin/curl http://localhost:8090/ 2>/dev/null >tmp/index.html +diff tmp/index.html htdocs/index.html +rc=$? + +# Test Catalog +if [ "$rc" = "0" ]; then + $curl_prefix/bin/curl http://localhost:8090/references/Store/catalog -X POST -H "Content-type: application/json-rpc" --data @../store-cpp/htdocs/test/items-request.txt >tmp/items-result.txt 2>/dev/null + diff tmp/items-result.txt ../store-cpp/htdocs/test/items-result.txt + rc=$? +fi + +# Test Shopping Cart +if [ "$rc" = "0" ]; then + $curl_prefix/bin/curl http://localhost:8090/references/Store/shoppingCart -X POST -H "Content-type: application/atom+xml" --data @../store-cpp/htdocs/test/shopping-cart-entry.xml 2>/dev/null + rc=$? +fi +if [ "$rc" = "0" ]; then + $curl_prefix/bin/curl http://localhost:8090/references/Store/shoppingCart >tmp/shopping-cart-feed.xml 2>/dev/null + grep "3.55" tmp/shopping-cart-feed.xml >/dev/null + rc=$? +fi + +# Cleanup +./stop +sleep 2 + +if [ "$rc" = "0" ]; then + echo "OK" +fi +return $rc diff --git a/sca-cpp/trunk/samples/loan-python/start b/sca-cpp/trunk/samples/loan-python/start new file mode 100755 index 0000000000..e7aa7d86ca --- /dev/null +++ b/sca-cpp/trunk/samples/loan-python/start @@ -0,0 +1,31 @@ +#!/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. + +../../modules/http/httpd-conf tmp localhost 8090 htdocs +../../modules/server/server-conf tmp +../../modules/python/python-conf tmp +cat >>tmp/conf/httpd.conf <<EOF +# Configure SCA Composite +SCAContribution `pwd`/ +SCAComposite loan.composite + +EOF + +../../components/cache/memcached-start +../../modules/http/httpd-start tmp diff --git a/sca-cpp/trunk/samples/loan-python/stop b/sca-cpp/trunk/samples/loan-python/stop new file mode 100755 index 0000000000..a59273b8ed --- /dev/null +++ b/sca-cpp/trunk/samples/loan-python/stop @@ -0,0 +1,21 @@ +#!/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. + +../../modules/http/httpd-stop tmp +../../components/cache/memcached-stop diff --git a/sca-cpp/trunk/samples/loan-python/util.py b/sca-cpp/trunk/samples/loan-python/util.py new file mode 100644 index 0000000000..560101e32d --- /dev/null +++ b/sca-cpp/trunk/samples/loan-python/util.py @@ -0,0 +1,145 @@ +# 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. + +# Simple utility functions +from sys import maxint + +# Scheme-like lists +def cons(a, b): + return (a,) + b + +def car(l): + return l[0] + +def first(l): + return car(l) + +def cdr(l): + return l[1:] + +def rest(l): + return cdr(l) + +def cadr(l): + return car(cdr(l)) + +def cddr(l): + return cdr(cdr(l)) + +def caddr(l): + return car(cddr(l)) + +def append(a, b): + return a + b + +def reverse(l): + r = list(l) + r.reverse() + return tuple(r) + +def isNil(l): + if isinstance(l, streampair): + return l.isNil() + return l == () + +def isSymbol(v): + return isinstance(v, basestring) and v[0:1] == "'" + +def isList(v): + if getattr(v, '__iter__', False) == False: + return False + if isinstance(v, basestring) or isinstance(v, dict): + return False + return True + +def isTaggedList(v, t): + return isList(v) and not isNil(v) and car(v) == t + + +# Scheme-like streams +class streampair(object): + def __init__(self, car, cdr): + self.car = car + self.cdr = cdr + + def __repr__(self): + return repr(self[0:len(self)]) + + def isNil(self): + return self.cdr == () + + def __len__(self): + if self.cdr == (): + return 0 + return 1 + len(self.cdr()) + + def __getitem__(self, i): + if i == 0: + return self.car + return self.cdr()[i - 1] + + def __getslice__(self, i, j): + if isNil(self): + return () + if i > 0: + if j == maxint: + return self.cdr()[i - 1: j] + return self.cdr()[i - 1: j - 1] + if j == maxint: + return self + if j == 0: + return (self.car,) + return (self.car,) + self.cdr()[: j - 1] + + def __eq__(self, other): + sl = len(self) + ol = len(other) + if sl != ol: + return False + return self[0: sl] == other[0: ol] + + def __ne__(self, other): + return not self.__eq__(other) + +def cons_stream(car, cdr): + return streampair(car, cdr) + + +# Scheme-like associations +def assoc(k, l): + if l == (): + return None + + if k == car(car(l)): + return car(l) + return assoc(k, cdr(l)) + +# Currying / partial function application +def curry(f, *args): + return lambda *a: f(*(args + a)) + +# Split a path into a list of segments +def tokens(path): + return tuple(filter(lambda s: len(s) != 0, path.split("/"))) + +# Write a list of strings to a stream +def writeStrings(l, os): + if l == (): + return os + os.write(car(l)) + return writeStrings(cdr(l), os) + 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 16246cc621..c187aa2a84 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 @@ -17,7 +17,7 @@ under the License. --> -<html><body><h1>Sign in with an OpenID or OAuth 2.0 provider</h1> +<html><body><h1>Sign in with an OpenID or OAuth provider</h1> <script type="text/javascript"> function queryParams() { @@ -91,23 +91,44 @@ function withXRDSEndpoint() { return document.fields.endpoint.value; } -function submitOAuthSignin(w) { +function submitOAuth2Signin(w) { parms = w(); - document.oauthSignin.mod_oauth_authorize.value = parms[0]; - document.oauthSignin.mod_oauth_access_token.value = parms[1]; - document.oauthSignin.mod_oauth_client_id.value = parms[2]; - document.oauthSignin.mod_oauth_info.value = parms[3]; - document.oauthSignin.action = openauthReferrer(); - document.oauthSignin.submit(); + document.oauth2Signin.mod_oauth2_authorize.value = parms[0]; + document.oauth2Signin.mod_oauth2_access_token.value = parms[1]; + document.oauth2Signin.mod_oauth2_client_id.value = parms[2]; + document.oauth2Signin.mod_oauth2_info.value = parms[3]; + document.oauth2Signin.action = openauthReferrer(); + document.oauth2Signin.submit(); } function withFacebook() { - var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'app1234', 'https://graph.facebook.com/me']; + var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'testfacebookapp', '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']; + var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'testgithubapp', 'https://github.com/api/v2/json/user/show']; + return parms; +} + +function submitOAuth1Signin(w) { + parms = w(); + document.oauth1Signin.mod_oauth1_request_token.value = parms[0]; + document.oauth1Signin.mod_oauth1_authorize.value = parms[1]; + document.oauth1Signin.mod_oauth1_access_token.value = parms[2]; + document.oauth1Signin.mod_oauth1_client_id.value = parms[3]; + document.oauth1Signin.mod_oauth1_info.value = parms[4]; + document.oauth1Signin.action = openauthReferrer(); + document.oauth1Signin.submit(); +} + +function withLinkedin() { + var parms = ['https://api.linkedin.com/uas/oauth/requestToken', 'https://www.linkedin.com/uas/oauth/authorize', 'https://api.linkedin.com/uas/oauth/accessToken', 'testlinkedinapp', 'https://api.linkedin.com/v1/people/~:(id,first-name,last-name,public-profile-url)']; + return parms; +} + +function withTwitter() { + var parms = ['https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/authorize', 'https://api.twitter.com/oauth/access_token', 'testtwitterapp', 'https://api.twitter.com/1/statuses/user_timeline.json']; return parms; } </script> @@ -139,20 +160,32 @@ function withGithub() { <input type="text" size="50" name="endpoint" value="https://www.google.com/accounts/o8/id"/><br/> <input type="button" onclick="submitOpenIDSignin(withXRDSEndpoint)" value="Sign in"/></p> -<p>Sign in with your Facebook account<br/><input type="button" onclick="submitOAuthSignin(withFacebook)" value="Sign in"/></p> -<p>Sign in with your Github account<br/><input type="button" onclick="submitOAuthSignin(withGithub)" value="Sign in"/></p> +<p>Sign in with your Facebook account<br/><input type="button" onclick="submitOAuth2Signin(withFacebook)" value="Sign in"/></p> +<p>Sign in with your Github account<br/><input type="button" onclick="submitOAuth2Signin(withGithub)" value="Sign in"/></p> + +<p>Sign in with your Linkedin account<br/><input type="button" onclick="submitOAuth1Signin(withLinkedin)" value="Sign in"/></p> +<p>Sign in with your Twitter account<br/><input type="button" onclick="submitOAuth1Signin(withTwitter)" value="Sign in"/></p> </form> <form name="openIDSignin" action="/" method="GET"> <input type="hidden" name="openid_identifier" value=""/> </form> -<form name="oauthSignin" action="/" method="GET"> -<input type="hidden" name="mod_oauth_authorize" value=""/> -<input type="hidden" name="mod_oauth_access_token" value=""/> -<input type="hidden" name="mod_oauth_client_id" value=""/> -<input type="hidden" name="mod_oauth_info" value=""/> -<input type="hidden" name="mod_oauth_step" value="authorize"/> +<form name="oauth2Signin" action="/" method="GET"> +<input type="hidden" name="mod_oauth2_authorize" value=""/> +<input type="hidden" name="mod_oauth2_access_token" value=""/> +<input type="hidden" name="mod_oauth2_client_id" value=""/> +<input type="hidden" name="mod_oauth2_info" value=""/> +<input type="hidden" name="mod_oauth2_step" value="authorize"/> +</form> + +<form name="oauth1Signin" action="/" method="GET"> +<input type="hidden" name="mod_oauth1_request_token" value=""/> +<input type="hidden" name="mod_oauth1_authorize" value=""/> +<input type="hidden" name="mod_oauth1_access_token" value=""/> +<input type="hidden" name="mod_oauth1_client_id" value=""/> +<input type="hidden" name="mod_oauth1_info" value=""/> +<input type="hidden" name="mod_oauth1_step" value="authorize"/> </form> </body></html> 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 16246cc621..c187aa2a84 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 @@ -17,7 +17,7 @@ under the License. --> -<html><body><h1>Sign in with an OpenID or OAuth 2.0 provider</h1> +<html><body><h1>Sign in with an OpenID or OAuth provider</h1> <script type="text/javascript"> function queryParams() { @@ -91,23 +91,44 @@ function withXRDSEndpoint() { return document.fields.endpoint.value; } -function submitOAuthSignin(w) { +function submitOAuth2Signin(w) { parms = w(); - document.oauthSignin.mod_oauth_authorize.value = parms[0]; - document.oauthSignin.mod_oauth_access_token.value = parms[1]; - document.oauthSignin.mod_oauth_client_id.value = parms[2]; - document.oauthSignin.mod_oauth_info.value = parms[3]; - document.oauthSignin.action = openauthReferrer(); - document.oauthSignin.submit(); + document.oauth2Signin.mod_oauth2_authorize.value = parms[0]; + document.oauth2Signin.mod_oauth2_access_token.value = parms[1]; + document.oauth2Signin.mod_oauth2_client_id.value = parms[2]; + document.oauth2Signin.mod_oauth2_info.value = parms[3]; + document.oauth2Signin.action = openauthReferrer(); + document.oauth2Signin.submit(); } function withFacebook() { - var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'app1234', 'https://graph.facebook.com/me']; + var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'testfacebookapp', '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']; + var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'testgithubapp', 'https://github.com/api/v2/json/user/show']; + return parms; +} + +function submitOAuth1Signin(w) { + parms = w(); + document.oauth1Signin.mod_oauth1_request_token.value = parms[0]; + document.oauth1Signin.mod_oauth1_authorize.value = parms[1]; + document.oauth1Signin.mod_oauth1_access_token.value = parms[2]; + document.oauth1Signin.mod_oauth1_client_id.value = parms[3]; + document.oauth1Signin.mod_oauth1_info.value = parms[4]; + document.oauth1Signin.action = openauthReferrer(); + document.oauth1Signin.submit(); +} + +function withLinkedin() { + var parms = ['https://api.linkedin.com/uas/oauth/requestToken', 'https://www.linkedin.com/uas/oauth/authorize', 'https://api.linkedin.com/uas/oauth/accessToken', 'testlinkedinapp', 'https://api.linkedin.com/v1/people/~:(id,first-name,last-name,public-profile-url)']; + return parms; +} + +function withTwitter() { + var parms = ['https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/authorize', 'https://api.twitter.com/oauth/access_token', 'testtwitterapp', 'https://api.twitter.com/1/statuses/user_timeline.json']; return parms; } </script> @@ -139,20 +160,32 @@ function withGithub() { <input type="text" size="50" name="endpoint" value="https://www.google.com/accounts/o8/id"/><br/> <input type="button" onclick="submitOpenIDSignin(withXRDSEndpoint)" value="Sign in"/></p> -<p>Sign in with your Facebook account<br/><input type="button" onclick="submitOAuthSignin(withFacebook)" value="Sign in"/></p> -<p>Sign in with your Github account<br/><input type="button" onclick="submitOAuthSignin(withGithub)" value="Sign in"/></p> +<p>Sign in with your Facebook account<br/><input type="button" onclick="submitOAuth2Signin(withFacebook)" value="Sign in"/></p> +<p>Sign in with your Github account<br/><input type="button" onclick="submitOAuth2Signin(withGithub)" value="Sign in"/></p> + +<p>Sign in with your Linkedin account<br/><input type="button" onclick="submitOAuth1Signin(withLinkedin)" value="Sign in"/></p> +<p>Sign in with your Twitter account<br/><input type="button" onclick="submitOAuth1Signin(withTwitter)" value="Sign in"/></p> </form> <form name="openIDSignin" action="/" method="GET"> <input type="hidden" name="openid_identifier" value=""/> </form> -<form name="oauthSignin" action="/" method="GET"> -<input type="hidden" name="mod_oauth_authorize" value=""/> -<input type="hidden" name="mod_oauth_access_token" value=""/> -<input type="hidden" name="mod_oauth_client_id" value=""/> -<input type="hidden" name="mod_oauth_info" value=""/> -<input type="hidden" name="mod_oauth_step" value="authorize"/> +<form name="oauth2Signin" action="/" method="GET"> +<input type="hidden" name="mod_oauth2_authorize" value=""/> +<input type="hidden" name="mod_oauth2_access_token" value=""/> +<input type="hidden" name="mod_oauth2_client_id" value=""/> +<input type="hidden" name="mod_oauth2_info" value=""/> +<input type="hidden" name="mod_oauth2_step" value="authorize"/> +</form> + +<form name="oauth1Signin" action="/" method="GET"> +<input type="hidden" name="mod_oauth1_request_token" value=""/> +<input type="hidden" name="mod_oauth1_authorize" value=""/> +<input type="hidden" name="mod_oauth1_access_token" value=""/> +<input type="hidden" name="mod_oauth1_client_id" value=""/> +<input type="hidden" name="mod_oauth1_info" value=""/> +<input type="hidden" name="mod_oauth1_step" value="authorize"/> </form> </body></html> 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 16246cc621..c187aa2a84 100644 --- a/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html +++ b/sca-cpp/trunk/samples/store-cluster/htdocs/login/index.html @@ -17,7 +17,7 @@ under the License. --> -<html><body><h1>Sign in with an OpenID or OAuth 2.0 provider</h1> +<html><body><h1>Sign in with an OpenID or OAuth provider</h1> <script type="text/javascript"> function queryParams() { @@ -91,23 +91,44 @@ function withXRDSEndpoint() { return document.fields.endpoint.value; } -function submitOAuthSignin(w) { +function submitOAuth2Signin(w) { parms = w(); - document.oauthSignin.mod_oauth_authorize.value = parms[0]; - document.oauthSignin.mod_oauth_access_token.value = parms[1]; - document.oauthSignin.mod_oauth_client_id.value = parms[2]; - document.oauthSignin.mod_oauth_info.value = parms[3]; - document.oauthSignin.action = openauthReferrer(); - document.oauthSignin.submit(); + document.oauth2Signin.mod_oauth2_authorize.value = parms[0]; + document.oauth2Signin.mod_oauth2_access_token.value = parms[1]; + document.oauth2Signin.mod_oauth2_client_id.value = parms[2]; + document.oauth2Signin.mod_oauth2_info.value = parms[3]; + document.oauth2Signin.action = openauthReferrer(); + document.oauth2Signin.submit(); } function withFacebook() { - var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'app1234', 'https://graph.facebook.com/me']; + var parms = ['https://graph.facebook.com/oauth/authorize', 'https://graph.facebook.com/oauth/access_token', 'testfacebookapp', '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']; + var parms = ['https://github.com/login/oauth/authorize', 'https://github.com/login/oauth/access_token', 'testgithubapp', 'https://github.com/api/v2/json/user/show']; + return parms; +} + +function submitOAuth1Signin(w) { + parms = w(); + document.oauth1Signin.mod_oauth1_request_token.value = parms[0]; + document.oauth1Signin.mod_oauth1_authorize.value = parms[1]; + document.oauth1Signin.mod_oauth1_access_token.value = parms[2]; + document.oauth1Signin.mod_oauth1_client_id.value = parms[3]; + document.oauth1Signin.mod_oauth1_info.value = parms[4]; + document.oauth1Signin.action = openauthReferrer(); + document.oauth1Signin.submit(); +} + +function withLinkedin() { + var parms = ['https://api.linkedin.com/uas/oauth/requestToken', 'https://www.linkedin.com/uas/oauth/authorize', 'https://api.linkedin.com/uas/oauth/accessToken', 'testlinkedinapp', 'https://api.linkedin.com/v1/people/~:(id,first-name,last-name,public-profile-url)']; + return parms; +} + +function withTwitter() { + var parms = ['https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/authorize', 'https://api.twitter.com/oauth/access_token', 'testtwitterapp', 'https://api.twitter.com/1/statuses/user_timeline.json']; return parms; } </script> @@ -139,20 +160,32 @@ function withGithub() { <input type="text" size="50" name="endpoint" value="https://www.google.com/accounts/o8/id"/><br/> <input type="button" onclick="submitOpenIDSignin(withXRDSEndpoint)" value="Sign in"/></p> -<p>Sign in with your Facebook account<br/><input type="button" onclick="submitOAuthSignin(withFacebook)" value="Sign in"/></p> -<p>Sign in with your Github account<br/><input type="button" onclick="submitOAuthSignin(withGithub)" value="Sign in"/></p> +<p>Sign in with your Facebook account<br/><input type="button" onclick="submitOAuth2Signin(withFacebook)" value="Sign in"/></p> +<p>Sign in with your Github account<br/><input type="button" onclick="submitOAuth2Signin(withGithub)" value="Sign in"/></p> + +<p>Sign in with your Linkedin account<br/><input type="button" onclick="submitOAuth1Signin(withLinkedin)" value="Sign in"/></p> +<p>Sign in with your Twitter account<br/><input type="button" onclick="submitOAuth1Signin(withTwitter)" value="Sign in"/></p> </form> <form name="openIDSignin" action="/" method="GET"> <input type="hidden" name="openid_identifier" value=""/> </form> -<form name="oauthSignin" action="/" method="GET"> -<input type="hidden" name="mod_oauth_authorize" value=""/> -<input type="hidden" name="mod_oauth_access_token" value=""/> -<input type="hidden" name="mod_oauth_client_id" value=""/> -<input type="hidden" name="mod_oauth_info" value=""/> -<input type="hidden" name="mod_oauth_step" value="authorize"/> +<form name="oauth2Signin" action="/" method="GET"> +<input type="hidden" name="mod_oauth2_authorize" value=""/> +<input type="hidden" name="mod_oauth2_access_token" value=""/> +<input type="hidden" name="mod_oauth2_client_id" value=""/> +<input type="hidden" name="mod_oauth2_info" value=""/> +<input type="hidden" name="mod_oauth2_step" value="authorize"/> +</form> + +<form name="oauth1Signin" action="/" method="GET"> +<input type="hidden" name="mod_oauth1_request_token" value=""/> +<input type="hidden" name="mod_oauth1_authorize" value=""/> +<input type="hidden" name="mod_oauth1_access_token" value=""/> +<input type="hidden" name="mod_oauth1_client_id" value=""/> +<input type="hidden" name="mod_oauth1_info" value=""/> +<input type="hidden" name="mod_oauth1_step" value="authorize"/> </form> </body></html> diff --git a/sca-cpp/trunk/samples/store-cluster/server-ssl-conf b/sca-cpp/trunk/samples/store-cluster/server-ssl-conf index 0b54b5cbf3..06ca590efb 100755 --- a/sca-cpp/trunk/samples/store-cluster/server-ssl-conf +++ b/sca-cpp/trunk/samples/store-cluster/server-ssl-conf @@ -36,7 +36,6 @@ tar -C tmp/ssl -c `../../modules/http/ssl-cert-find tmp/ssl` | tar -C $root -x ../../modules/oauth/oauth-memcached-conf $root localhost 11211 ../../modules/oauth/oauth-memcached-conf $root localhost 11212 ../../modules/oauth/oauth-memcached-conf $root localhost 11213 -../../modules/oauth/oauth-app-conf $root app1234 secret6789 ../../modules/openid/openid-conf $root ../../modules/openid/openid-step2-conf $root ../../modules/openid/openid-memcached-conf $root localhost 11211 |