summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--test/.gitignore2
-rw-r--r--test/Makefile.am35
-rw-r--r--test/RP-db.sql37
-rw-r--r--test/RP.cc538
-rw-r--r--test/html/2rels.html7
-rw-r--r--test/html/empty.html0
-rw-r--r--test/html/head-in-body.html10
-rw-r--r--test/html/hkn-delegate.html7
-rw-r--r--test/html/hkn-server.html7
-rw-r--r--test/html/hkn.html8
-rw-r--r--test/html/in-body.html8
-rw-r--r--test/html/spaced-link-attrs.html8
-rw-r--r--test/html/spaced-links.html8
-rw-r--r--test/html/unclosed-head.html7
-rw-r--r--test/idiscover.cc46
-rw-r--r--test/sqlite.h71
-rw-r--r--test/test.cc49
17 files changed, 693 insertions, 155 deletions
diff --git a/test/.gitignore b/test/.gitignore
index 31ae686..d07884c 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,5 +1,7 @@
/.deps
/.libs
/test
*.o
/idiscover
+/RP.cgi
+/RP-db.cc
diff --git a/test/Makefile.am b/test/Makefile.am
index b573d55..61e3787 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,16 +1,39 @@
-noinst_PROGRAMS = test idiscover
+noinst_PROGRAMS = test idiscover RP.cgi
AM_CPPFLAGS=${CPPFLAGS_DEBUG}
DEFAULT_INCLUDES = -I${top_builddir}
-INCLUDES = -I${top_srcdir}/include/ ${KONFORKA_CFLAGS} ${LIBCURL_CPPFLAGS}
+INCLUDES = -I${top_srcdir}/test/ -I${top_builddir}/include/ -I${top_srcdir}/include/ ${KONFORKA_CFLAGS} ${LIBCURL_CPPFLAGS}
test_SOURCES = test.cc
test_LDADD = ${top_builddir}/lib/libopkele.la
-EXTRA_DIST=$(addsuffix .html,$(addprefix html/, \
- empty head-in-body hkn-delegate hkn-server hkn in-body \
- unclosed-head spaced-links spaced-link-attrs 2rels \
- ))
+EXTRA_DIST= \
+ sqlite.h \
+ RP-db.sql
idiscover_SOURCES = idiscover.cc
idiscover_LDADD = ${top_builddir}/lib/libopkele.la
+
+if HAVE_SQLITE3
+if HAVE_KINGATE
+if HAVE_UUID
+
+RP_cgi_SOURCES = RP.cc
+nodist_RP_cgi_SOURCES = RP-db.cc
+RP_cgi_LDADD = ${top_builddir}/lib/libopkele.la \
+ ${SQLITE3_LIBS} ${KINGATE_LIBS} ${UUID_LIBS}
+RP_cgi_CFLAGS = ${SQLITE3_CFLAGS} ${KINGATE_CFLAGS} ${UUID_CFLAGS}
+
+RP-db.cc: RP-db.sql
+ ( \
+ echo 'const char * __RP_db_bootstrap = ' && \
+ sed -e 's/^/"/' -e 's/$$/"/' $< && \
+ echo ';' \
+ ) >$@
+
+clean-local:
+ rm -f RP-db.cc
+
+endif #HAVE_UUID
+endif #HAVE_KINGATE
+endif #HAVE_SQLITE3
diff --git a/test/RP-db.sql b/test/RP-db.sql
new file mode 100644
index 0000000..71a82d4
--- a/dev/null
+++ b/test/RP-db.sql
@@ -0,0 +1,37 @@
+CREATE TABLE assoc (
+ a_op text,
+ a_handle text NOT NULL,
+ a_type text DEFAULT 'HMAC-SHA1',
+ a_ctime text NOT NULL,
+ a_etime text NOT NULL,
+ a_secret text NOT NULL,
+ a_stateless integer NOT NULL DEFAULT 0,
+ a_itime integer,
+ UNIQUE(a_op,a_handle)
+);
+
+CREATE TABLE nonces (
+ n_op text NOT NULL,
+ n_once text NOT NULL,
+ PRIMARY KEY (n_op,n_once)
+);
+
+CREATE TABLE ht_sessions (
+ hts_id text NOT NULL PRIMARY KEY
+);
+
+CREATE TABLE auth_sessions (
+ as_id integer PRIMARY KEY AUTOINCREMENT,
+ hts_id text NOT NULL REFERENCES ht_sessions(hts_id),
+ as_normalized_id text,
+ UNIQUE (hts_id,as_id)
+);
+
+CREATE TABLE endpoints_queue (
+ as_id integer NOT NULL REFERENCES auth_sessions (as_id),
+ eq_ctime integer NOT NULL,
+ eq_ordinal integer NOT NULL,
+ eq_uri text,
+ eq_claimed_id text,
+ eq_local_id text
+);
diff --git a/test/RP.cc b/test/RP.cc
new file mode 100644
index 0000000..f2f8851
--- a/dev/null
+++ b/test/RP.cc
@@ -0,0 +1,538 @@
+#include <uuid/uuid.h>
+#include <iostream>
+#include <cassert>
+#include <stdexcept>
+#include <string>
+#include <set>
+#include <iterator>
+using namespace std;
+#include <kingate/exception.h>
+#include <kingate/plaincgi.h>
+#include <kingate/cgi_gateway.h>
+#include <opkele/exception.h>
+#include <opkele/types.h>
+#include <opkele/util.h>
+#include <opkele/uris.h>
+#include <opkele/discovery.h>
+#include <opkele/association.h>
+#include <opkele/sreg.h>
+using namespace opkele;
+#include <opkele/prequeue_rp.h>
+#include <opkele/debug.h>
+
+#include "sqlite.h"
+
+#undef DUMB_RP
+
+#ifdef DUMB_RP
+# define DUMBTHROW throw opkele::dumb_RP(OPKELE_CP_ "This RP is dumb")
+#else
+# define DUMBTHROW (void)0
+#endif
+
+template<typename IT>
+class join_iterator : public iterator<
+ input_iterator_tag,typename IT::value_type,
+ void,typename IT::pointer,typename IT::reference> {
+ public:
+ typedef pair<IT,IT> range_t;
+ typedef list<range_t> ranges_t;
+ ranges_t ranges;
+
+ join_iterator() { }
+
+ bool cleanup() {
+ bool rv = false;
+ while(!(ranges.empty() || ranges.front().first!=ranges.front().second)) {
+ ranges.pop_front(); rv = true;
+ }
+ return rv;
+ }
+
+ join_iterator<IT>& add_range(const IT& b,const IT& e) {
+ ranges.push_back(typename ranges_t::value_type(b,e));
+ cleanup();
+ return *this;
+ }
+
+ bool operator==(const join_iterator<IT>& x) const {
+ return ranges==x.ranges; }
+ bool operator!=(const join_iterator<IT>& x) const {
+ return ranges!=x.ranges; }
+
+ typename IT::reference operator*() const {
+ assert(!ranges.empty());
+ assert(ranges.front().first!=ranges.front().second);
+ return *ranges.front().first; }
+ typename IT::pointer operator->() const {
+ assert(!ranges.empty());
+ assert(ranges.front().first!=ranges.front().second);
+ return ranges.front().first.operator->(); }
+
+ join_iterator<IT>& operator++() {
+ cleanup();
+ if(ranges.empty()) return *this;
+ do {
+ ++ranges.front().first;
+ }while(cleanup() && !ranges.empty());
+ return *this;
+ }
+ join_iterator<IT> operator++(int) {
+ join_iterator<IT> rv(*this);
+ ++(*this); return rv; }
+};
+
+template<typename IT>
+class cut_prefix_filterator : public opkele::util::basic_filterator<IT> {
+ public:
+ string pfx;
+ mutable string tmp;
+
+ cut_prefix_filterator() { }
+ cut_prefix_filterator(const IT& bi,const IT&ei,const string& pfx)
+ : opkele::util::basic_filterator<IT>(bi,ei), pfx(pfx) {
+ this->prepare();
+ }
+
+ bool is_interesting() const {
+ return pfx.length()==0 || !strncmp(this->it->c_str(),pfx.c_str(),pfx.length());
+ }
+
+ typename IT::reference operator*() const {
+ assert(!this->empty);
+ tmp = *this->it; tmp.erase(0,pfx.length());
+ return tmp; }
+ typename IT::pointer operator->() const {
+ assert(!this->empty);
+ return &this->operator*(); }
+};
+
+class kingate_openid_message_t : public opkele::basic_openid_message {
+ typedef join_iterator<kingate::cgi_gateway::params_t::const_iterator> jitterator;
+ typedef opkele::util::map_keys_iterator<
+ jitterator,
+ fields_iterator::value_type,
+ fields_iterator::reference,
+ fields_iterator::pointer> keys_iterator;
+ typedef cut_prefix_filterator<keys_iterator> pfilterator;
+ public:
+ const kingate::cgi_gateway& gw;
+
+ kingate_openid_message_t(const kingate::cgi_gateway& g) : gw(g) { }
+
+ bool has_field(const string& n) const {
+ return gw.has_param("openid."+n); }
+ const string& get_field(const string& n) const {
+ return gw.get_param("openid."+n); }
+
+ fields_iterator fields_begin() const {
+ return
+ pfilterator( keys_iterator(
+ jitterator()
+ .add_range( gw.get.begin(), gw.get.end() )
+ .add_range( gw.post.begin(), gw.post.end() ),
+ jitterator()
+ ), keys_iterator(), "openid." );
+ }
+ fields_iterator fields_end() const {
+ return pfilterator();
+ }
+};
+
+class rpdb_t : public sqlite3_t {
+ public:
+ rpdb_t()
+ : sqlite3_t("/tmp/RP.db") {
+ assert(_D);
+ char **resp; int nrow,ncol; char *errm;
+ if(sqlite3_get_table(
+ _D,"SELECT a_op FROM assoc LIMIT 0",
+ &resp,&nrow,&ncol,&errm)!=SQLITE_OK) {
+ extern const char *__RP_db_bootstrap;
+ DOUT_("Bootstrapping DB");
+ if(sqlite3_exec(_D,__RP_db_bootstrap,NULL,NULL,&errm)!=SQLITE_OK)
+ throw opkele::exception(OPKELE_CP_ string("Failed to bootstrap SQLite database: ")+errm);
+ }else
+ sqlite3_free_table(resp);
+
+ }
+};
+
+class example_rp_t : public opkele::prequeue_RP {
+ public:
+ mutable rpdb_t db;
+ kingate::cookie htc;
+ long as_id;
+ int ordinal;
+ kingate::cgi_gateway& gw;
+
+ example_rp_t(kingate::cgi_gateway& gw)
+ : ordinal(0), have_eqtop(false), gw(gw), as_id(-1) {
+ try {
+ htc = gw.cookies.get_cookie("ht_session");
+ as_id = opkele::util::string_to_long(gw.get_param("asid"));
+ }catch(kingate::exception_notfound& kenf) {
+ uuid_t uuid; uuid_generate(uuid);
+ htc = kingate::cookie("ht_session",util::encode_base64(uuid,sizeof(uuid)));
+ sqlite3_mem_t<char*> S = sqlite3_mprintf(
+ "INSERT INTO ht_sessions (hts_id) VALUES (%Q)",
+ htc.get_value().c_str());
+ db.exec(S);
+ }
+ }
+
+ /* Global persistent store */
+
+ opkele::assoc_t store_assoc(
+ const string& OP,const string& handle,
+ const string& type,const secret_t& secret,
+ int expires_in) {
+ DUMBTHROW;
+ DOUT_("Storing '" << handle << "' assoc with '" << OP << "'");
+ time_t exp = time(0)+expires_in;
+ sqlite3_mem_t<char*>
+ S = sqlite3_mprintf(
+ "INSERT INTO assoc"
+ " (a_op,a_handle,a_type,a_ctime,a_etime,a_secret)"
+ " VALUES ("
+ " %Q,%Q,%Q,"
+ " datetime('now'), datetime('now','+%d seconds'),"
+ " %Q"
+ " );", OP.c_str(), handle.c_str(), type.c_str(),
+ expires_in,
+ util::encode_base64(&(secret.front()),secret.size()).c_str() );
+ db.exec(S);
+ return opkele::assoc_t(new opkele::association(
+ OP, handle, type, secret, exp, false ));
+ }
+
+ opkele::assoc_t find_assoc(
+ const string& OP) {
+ DUMBTHROW;
+ DOUT_("Looking for an assoc with '" << OP << '\'');
+ sqlite3_mem_t<char*>
+ S = sqlite3_mprintf(
+ "SELECT"
+ " a_op,a_handle,a_type,a_secret,"
+ " strftime('%%s',a_etime) AS a_etime"
+ " FROM assoc"
+ " WHERE a_op=%Q AND a_itime IS NULL AND NOT a_stateless"
+ " AND ( a_etime > datetime('now','-30 seconds') )"
+ " LIMIT 1",
+ OP.c_str());
+ sqlite3_table_t T;
+ int nr,nc;
+ db.get_table(S,T,&nr,&nc);
+ if(nr<1)
+ throw opkele::failed_lookup(OPKELE_CP_ "Couldn't find unexpired handle");
+ assert(nr==1);
+ assert(nc==5);
+ secret_t secret;
+ util::decode_base64(T.get(1,3,nc),secret);
+ DOUT_(" found '" << T.get(1,1,nc) << '\'');
+ return opkele::assoc_t(new opkele::association(
+ T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc),
+ secret, strtol(T.get(1,4,nc),0,0), false ));
+ }
+
+ opkele::assoc_t retrieve_assoc(
+ const string& OP,const string& handle) {
+ DUMBTHROW;
+ DOUT_("Retrieving assoc '" << handle << "' with '" << OP << '\'');
+ sqlite3_mem_t<char*>
+ S = sqlite3_mprintf(
+ "SELECT"
+ " a_op,a_handle,a_type,a_secret,"
+ " strftime('%%s',a_etime) AS a_etime"
+ " FROM assoc"
+ " WHERE a_op=%Q AND a_handle=%Q"
+ " AND a_itime IS NULL AND NOT a_stateless"
+ " LIMIT 1",
+ OP.c_str(),handle.c_str());
+ sqlite3_table_t T;
+ int nr,nc;
+ db.get_table(S,T,&nr,&nc);
+ if(nr<1)
+ throw opkele::failed_lookup(OPKELE_CP_ "couldn't retrieve valid association");
+ assert(nr==1); assert(nc==5);
+ secret_t secret; util::decode_base64(T.get(1,3,nc),secret);
+ DOUT_(" found. type=" << T.get(1,2,nc) << '\'');
+ return opkele::assoc_t(new opkele::association(
+ T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc),
+ secret, strtol(T.get(1,4,nc),0,0), false ));
+ }
+
+ void invalidate_assoc(
+ const string& OP,const string& handle) {
+ DUMBTHROW;
+ DOUT_("Invalidating assoc '" << handle << "' with '" << OP << '\'');
+ sqlite3_mem_t<char*>
+ S = sqlite3_mprintf(
+ "UPDATE assoc SET a_itime=datetime('now')"
+ " WHERE a_op=%Q AND a_handle=%Q",
+ OP.c_str(), handle.c_str() );
+ db.exec(S);
+ }
+
+ void check_nonce(const string& OP,const string& nonce) {
+ DOUT_("Checking nonce '" << nonce << "' from '" << OP << '\'');
+ sqlite3_mem_t<char*>
+ S = sqlite3_mprintf(
+ "SELECT 1 FROM nonces WHERE n_op=%Q AND n_once=%Q",
+ OP.c_str(), nonce.c_str());
+ sqlite3_table_t T;
+ int nr,nc;
+ db.get_table(S,T,&nr,&nc);
+ if(nr)
+ throw opkele::id_res_bad_nonce(OPKELE_CP_ "already seen that nonce");
+ sqlite3_mem_t<char*>
+ SS = sqlite3_mprintf(
+ "INSERT INTO nonces (n_op,n_once) VALUES (%Q,%Q)",
+ OP.c_str(), nonce.c_str());
+ db.exec(SS);
+ }
+
+ /* Session perisistent store */
+
+ void begin_queueing() {
+ assert(as_id>=0);
+ DOUT_("Resetting queue for session '" << htc.get_value() << "'/" << as_id);
+ sqlite3_mem_t<char*> S = sqlite3_mprintf(
+ "DELETE FROM endpoints_queue"
+ " WHERE as_id=%ld",
+ as_id);
+ db.exec(S);
+ }
+
+ void queue_endpoint(const opkele::openid_endpoint_t& ep) {
+ assert(as_id>=0);
+ DOUT_("Queueing endpoint " << ep.claimed_id << " : " << ep.local_id << " @ " << ep.uri);
+ sqlite3_mem_t<char*> S = sqlite3_mprintf(
+ "INSERT INTO endpoints_queue"
+ " (as_id,eq_ctime,eq_ordinal,eq_uri,eq_claimed_id,eq_local_id)"
+ " VALUES (%ld,strftime('%%s','now'),%d,%Q,%Q,%Q)",
+ as_id,ordinal++,
+ ep.uri.c_str(),ep.claimed_id.c_str(),ep.local_id.c_str());
+ db.exec(S);
+ }
+
+ mutable openid_endpoint_t eqtop;
+ mutable bool have_eqtop;
+
+ const openid_endpoint_t& get_endpoint() const {
+ assert(as_id>=0);
+ if(!have_eqtop) {
+ sqlite3_mem_t<char*>
+ S = sqlite3_mprintf(
+ "SELECT"
+ " eq_uri, eq_claimed_id, eq_local_id"
+ " FROM endpoints_queue"
+ " JOIN auth_sessions USING(as_id)"
+ " WHERE hts_id=%Q AND as_id=%ld"
+ " ORDER BY eq_ctime,eq_ordinal"
+ " LIMIT 1",htc.get_value().c_str(),as_id);
+ sqlite3_table_t T; int nr,nc;
+ db.get_table(S,T,&nr,&nc);
+ if(nr<1)
+ throw opkele::exception(OPKELE_CP_ "No more endpoints queued");
+ assert(nr==1); assert(nc==3);
+ eqtop.uri = T.get(1,0,nc);
+ eqtop.claimed_id = T.get(1,1,nc);
+ eqtop.local_id = T.get(1,2,nc);
+ have_eqtop = true;
+ }
+ return eqtop;
+ }
+
+ void next_endpoint() {
+ assert(as_id>=0);
+ get_endpoint();
+ have_eqtop = false;
+ sqlite3_mem_t<char*> S = sqlite3_mprintf(
+ "DELETE FROM endpoints_queue"
+ " WHERE as_id=%ld AND eq_uri=%Q AND eq_local_id=%Q",
+ htc.get_value().c_str(),as_id,
+ eqtop.uri.c_str());
+ db.exec(S);
+ }
+
+ mutable string _cid;
+ mutable string _nid;
+
+ void set_claimed_id(const string& cid) {
+ assert(as_id>=0);
+ sqlite3_mem_t<char*> S = sqlite3_mprintf(
+ "UPDATE auth_sessions"
+ " SET as_claimed_id=%Q"
+ " WHERE hts_id=%Q and as_id=%ld",
+ cid.c_str(),
+ htc.get_value().c_str(),as_id);
+ db.exec(S);
+ _cid = cid;
+ }
+ const string get_claimed_id() const {
+ assert(as_id>=0);
+ if(_cid.empty()) {
+ sqlite3_mem_t<char*> S = sqlite3_mprintf(
+ "SELECT as_claimed_id"
+ " FROM"
+ " auth_sessions"
+ " WHERE"
+ " hts_id=%Q AND as_id=%ld",
+ htc.get_value().c_str(),as_id);
+ sqlite3_table_t T; int nr,nc;
+ db.get_table(S,T,&nr,&nc);
+ assert(nr==1); assert(nc==1);
+ _cid = T.get(1,0,nc);
+ }
+ return _cid;
+ }
+ void set_normalized_id(const string& nid) {
+ assert(as_id>=0);
+ sqlite3_mem_t<char*> S = sqlite3_mprintf(
+ "UPDATE auth_sessions"
+ " SET as_normalized_id=%Q"
+ " WHERE hts_id=%Q and as_id=%ld",
+ nid.c_str(),
+ htc.get_value().c_str(),as_id);
+ db.exec(S);
+ _nid = nid;
+ }
+ const string get_normalized_id() const {
+ assert(as_id>=0);
+ if(_nid.empty()) {
+ sqlite3_mem_t<char*> S = sqlite3_mprintf(
+ "SELECT as_normalized_id"
+ " FROM"
+ " auth_sessions"
+ " WHERE"
+ " hts_id=%Q AND as_id=%ld",
+ htc.get_value().c_str(),as_id);
+ sqlite3_table_t T; int nr,nc;
+ db.get_table(S,T,&nr,&nc);
+ assert(nr==1); assert(nc==1);
+ _nid = T.get(1,0,nc);
+ }
+ return _nid;
+ }
+
+ const string get_this_url() const {
+ bool s = gw.has_meta("SSL_PROTOCOL_VERSION");
+ string rv = s?"https://":"http://";
+ rv += gw.http_request_header("Host");
+ const string& port = gw.get_meta("SERVER_PORT");
+ if( port!=(s?"443":"80") ) {
+ rv += ':'; rv += port;
+ }
+ rv += gw.get_meta("REQUEST_URI");
+ return rv;
+ }
+
+ void initiate(const string& usi) {
+ allocate_asid();
+ prequeue_RP::initiate(usi);
+ }
+
+ string get_self_url() const {
+ string rv = get_this_url();
+ string::size_type q = rv.find('?');
+ if(q!=string::npos)
+ rv.erase(q);
+ return rv;
+ }
+
+ void allocate_asid() {
+ sqlite3_mem_t<char*> S = sqlite3_mprintf(
+ "INSERT INTO auth_sessions (hts_id)"
+ " VALUES (%Q)",
+ htc.get_value().c_str());
+ db.exec(S);
+ as_id = sqlite3_last_insert_rowid(db);
+ DOUT_("Allocated authentication session id "<<as_id);
+ assert(as_id>=0);
+ }
+
+#ifdef DUMB_RP
+ virtual assoc_t associate(const string& OP) {
+ DUMBTHROW;
+ }
+#endif
+};
+
+int main(int argc,char *argv[]) {
+ try {
+ kingate::plaincgi_interface ci;
+ kingate::cgi_gateway gw(ci);
+ string op;
+ try { op = gw.get_param("op"); }catch(kingate::exception_notfound&) { }
+ if(op=="initiate") {
+ example_rp_t rp(gw);
+ string usi = gw.get_param("openid_identity");
+ rp.initiate(usi);
+ opkele::sreg_t sreg(opkele::sreg_t::fields_NONE,opkele::sreg_t::fields_ALL);
+ opkele::openid_message_t cm;
+ string loc;
+ cout <<
+ "Set-Cookie: " << rp.htc.set_cookie_header() << "\n"
+ "Status: 302 Going to OP\n"
+ "Location: " << (
+ loc = rp.checkid_(cm,opkele::mode_checkid_setup,
+ rp.get_self_url()+
+ "?op=confirm&asid="+opkele::util::long_to_string(rp.as_id),
+ rp.get_self_url(),&sreg).append_query(rp.get_endpoint().uri)
+ )
+ << "\n\n";
+ DOUT_("Going to " << loc);
+ }else if(op=="confirm") {
+ kingate_openid_message_t om(gw);
+ example_rp_t rp(gw);
+ opkele::sreg_t sreg(opkele::sreg_t::fields_NONE,opkele::sreg_t::fields_ALL);
+ rp.id_res(om,&sreg);
+ cout <<
+ "Content-Type: text/plain\n\n";
+ for(opkele::basic_openid_message::fields_iterator i=om.fields_begin();
+ i!=om.fields_end();++i) {
+ cout << *i << '=' << om.get_field(*i) << endl;
+ }
+ cout << endl
+ << "SREG fields: " << sreg.has_fields << endl;
+ }else{
+ cout <<
+ "Content-type: text/html\n\n"
+
+ "<html>"
+ "<head><title>test RP</title></head>"
+ "<body>"
+ "<form action='' method='post'>"
+ "<input type='hidden' name='op' value='initiate' />"
+ "<input type='text' name='openid_identity'/>"
+ "<input type='submit' name='submit' value='submit' />"
+ "</form>"
+ "<br/><br/>"
+ "<a href='?op=initiate&amp;openid_identity=www.myopenid.com&amp;dummy=" << time(0) << "'>login with myopenid.com account</a>"
+ "<br/>"
+ "</body"
+ "</html>"
+ ;
+ }
+#ifdef OPKELE_HAVE_KONFORKA
+ }catch(konforka::exception& e) {
+#else
+ }catch(std::exception& e){
+#endif
+ DOUT_("Oops: " << e.what());
+ cout << "Content-Type: text/plain\n\n"
+ "Exception:\n"
+ " what: " << e.what() << endl;
+#ifdef OPKELE_HAVE_KONFORKA
+ cout << " where: " << e.where() << endl;
+ if(!e._seen.empty()) {
+ cout << " seen:" << endl;
+ for(list<konforka::code_point>::const_iterator
+ i=e._seen.begin();i!=e._seen.end();++i) {
+ cout << " " << i->c_str() << endl;
+ }
+ }
+#endif
+ }
+}
diff --git a/test/html/2rels.html b/test/html/2rels.html
deleted file mode 100644
index 8773c55..0000000
--- a/test/html/2rels.html
+++ b/dev/null
@@ -1,7 +0,0 @@
-<html>
- <head>
- <link rel="openid.server openid.delegate" href="http://www.klever.net/openid.server" />
- </head>
- <body>
- </body>
-</html>
diff --git a/test/html/empty.html b/test/html/empty.html
deleted file mode 100644
index e69de29..0000000
--- a/test/html/empty.html
+++ b/dev/null
diff --git a/test/html/head-in-body.html b/test/html/head-in-body.html
deleted file mode 100644
index 0f778f3..0000000
--- a/test/html/head-in-body.html
+++ b/dev/null
@@ -1,10 +0,0 @@
-<html>
- <head>
- </head>
- <body>
- <head>
- <link rel="openid.server" href="http://www.klever.net/openid.server" />
- <link rel="openid.delegate" href="http://hacker.klever.net/" />
- </head>
- </body>
-</html>
diff --git a/test/html/hkn-delegate.html b/test/html/hkn-delegate.html
deleted file mode 100644
index 62e25a3..0000000
--- a/test/html/hkn-delegate.html
+++ b/dev/null
@@ -1,7 +0,0 @@
-<html>
- <head>
- <link rel="openid.delegate" href="http://hacker.klever.net/" />
- </head>
- <body>
- </body>
-</html>
diff --git a/test/html/hkn-server.html b/test/html/hkn-server.html
deleted file mode 100644
index e6b64e8..0000000
--- a/test/html/hkn-server.html
+++ b/dev/null
@@ -1,7 +0,0 @@
-<html>
- <head>
- <link rel="openid.server" href="http://www.klever.net/openid.server" />
- </head>
- <body>
- </body>
-</html>
diff --git a/test/html/hkn.html b/test/html/hkn.html
deleted file mode 100644
index 8d6e409..0000000
--- a/test/html/hkn.html
+++ b/dev/null
@@ -1,8 +0,0 @@
-<html>
- <head>
- <link rel="openid.server" href="http://www.klever.net/openid.server" />
- <link rel="openid.delegate" href="http://hacker.klever.net/" />
- </head>
- <body>
- </body>
-</html>
diff --git a/test/html/in-body.html b/test/html/in-body.html
deleted file mode 100644
index 53bc06d..0000000
--- a/test/html/in-body.html
+++ b/dev/null
@@ -1,8 +0,0 @@
-<html>
- <head>
- </head>
- <body>
- <link rel="openid.server" href="http://www.klever.net/openid.server" />
- <link rel="openid.delegate" href="http://hacker.klever.net/" />
- </body>
-</html>
diff --git a/test/html/spaced-link-attrs.html b/test/html/spaced-link-attrs.html
deleted file mode 100644
index 33905c0..0000000
--- a/test/html/spaced-link-attrs.html
+++ b/dev/null
@@ -1,8 +0,0 @@
-<html>
- <head>
- <link rel=" openid.server " href=" http://www.klever.net/openid.server" />
- <link rel=" openid.delegate" href="http://hacker.klever.net/ " />
- </head>
- <body>
- </body>
-</html>
diff --git a/test/html/spaced-links.html b/test/html/spaced-links.html
deleted file mode 100644
index a958907..0000000
--- a/test/html/spaced-links.html
+++ b/dev/null
@@ -1,8 +0,0 @@
-<html>
- <head>
- < link rel = "openid.server" href = "http://www.klever.net/openid.server" />
- <link rel="openid.delegate" href='http://hacker.klever.net/' />
- </head>
- <body>
- </body>
-</html>
diff --git a/test/html/unclosed-head.html b/test/html/unclosed-head.html
deleted file mode 100644
index 9c6f2ea..0000000
--- a/test/html/unclosed-head.html
+++ b/dev/null
@@ -1,7 +0,0 @@
-<html>
- <head>
- <link rel="openid.server" href="http://www.klever.net/openid.server" />
- <link rel="openid.delegate" href="http://hacker.klever.net/" />
- <body>
- </body>
-</html>
diff --git a/test/idiscover.cc b/test/idiscover.cc
index d9a7c62..44df9ce 100644
--- a/test/idiscover.cc
+++ b/test/idiscover.cc
@@ -1,54 +1,40 @@
#include <iostream>
#include <stdexcept>
#include <iterator>
#include <algorithm>
using namespace std;
#include <opkele/exception.h>
#include <opkele/discovery.h>
+#include <opkele/util.h>
-template<typename _PDT>
- ostream& operator<<(ostream& o,const opkele::xrd::priority_map<_PDT>& pm) {
- for(typename opkele::xrd::priority_map<_PDT>::const_iterator i=pm.begin();
- i!=pm.end();++i)
- o << ' ' << i->second << '[' << i->first << ']';
+namespace opkele {
+ ostream& operator<<(ostream& o,const opkele::openid_endpoint_t& oep) {
+ o
+ << " URI: " << oep.uri << endl
+ << " Claimed ID: " << oep.claimed_id << endl
+ << " Local ID: " << oep.local_id << endl;
return o;
}
-
-ostream& operator<<(ostream& o,const opkele::xrd::service_t s) {
- o << "{" << endl
- << " Type: ";
- copy(s.types.begin(),s.types.end(),
- ostream_iterator<string>(o," "));
- o << endl
- << " URI: " << s.uris << endl
- << " LocalID: " << s.local_ids << endl
- << " ProviderID: " << s.provider_id << endl;
- o << "}";
}
int main(int argc,char **argv) {
try {
if(argc<2)
throw opkele::exception(OPKELE_CP_ "Please, give me something to resolve");
for(int a=1;a<argc;++a) {
- opkele::idiscovery_t discovery(argv[a]);
- clog
- << "===============================================================" << endl
+ cout << "==============================================================" << endl
<< "User-supplied ID: " << argv[a] << endl
- << "Normalized ID: " << discovery.normalized_id << endl
- << "Canonicalized ID: " << discovery.canonicalized_id << endl
- << "The identity is " << (discovery.xri_identity?"":"not ") << "an i-name" << endl;
- if(discovery.xrd.expires)
- clog << "Information expires in " << discovery.xrd.expires-time(0) << " seconds" << endl;
- clog << endl
- << "CanonicalID: " << discovery.xrd.canonical_ids << endl
- << "LocalID: " << discovery.xrd.local_ids << endl
- << "ProviderID: " << discovery.xrd.provider_id << endl
- << "Services: " << discovery.xrd.services << endl;
+ << "Endpoints:" << endl
+ << " --" << endl;
+ string normalized = opkele::idiscover(
+ ostream_iterator<opkele::openid_endpoint_t>(cout," --\n")
+ ,argv[a]);
+ cout << "Normalized ID: " << normalized << endl;
}
}catch(exception& e) {
- cerr << "oops: " << e.what() << endl;
+ cerr << "oops, caught " << opkele::util::abi_demangle(typeid(e).name()) << endl
+ << " .what(): " << e.what() << endl;
_exit(1);
}
_exit(0);
}
diff --git a/test/sqlite.h b/test/sqlite.h
new file mode 100644
index 0000000..883a2c0
--- a/dev/null
+++ b/test/sqlite.h
@@ -0,0 +1,71 @@
+#include <sqlite3.h>
+
+class sqlite3_t {
+ public:
+ sqlite3 *_D;
+
+ sqlite3_t(const char *f)
+ : _D(0) {
+ int r = sqlite3_open(f,&_D);
+ if(r!=SQLITE_OK) {
+ string msg = sqlite3_errmsg(_D); sqlite3_close(_D);
+ throw opkele::exception(OPKELE_CP_ "Failed to open SQLite database: "+msg);
+ }
+ }
+ ~sqlite3_t() {
+ if(_D) sqlite3_close(_D);
+ }
+
+ operator const sqlite3*(void) const { return _D; }
+ operator sqlite3*(void) { return _D; }
+
+ void exec(const char *sql) {
+ assert(_D);
+ char *errm;
+ if(sqlite3_exec(_D,sql,NULL,NULL,&errm)!=SQLITE_OK)
+ throw opkele::exception(OPKELE_CP_ string("Failed to sqlite3_exec():")+errm);
+ }
+ void get_table(const char *sql,char ***resp,int *nr,int *nc) {
+ assert(_D);
+ char *errm;
+ if(sqlite3_get_table(_D,sql,resp,nr,nc,&errm)!=SQLITE_OK)
+ throw opkele::exception(OPKELE_CP_ string("Failed to sqlite3_get_table():")+errm);
+ }
+};
+
+template<typename T>
+class sqlite3_mem_t {
+ public:
+ T _M;
+
+ sqlite3_mem_t(T M) :_M(M) { }
+ ~sqlite3_mem_t() { if(_M) sqlite3_free(_M); }
+
+ operator const T&(void) const { return _M; }
+ operator T&(void) { return _M; }
+
+ sqlite3_mem_t operator=(T M) {
+ if(_M) sqlite3_free(_M);
+ _M = M;
+ }
+};
+
+class sqlite3_table_t {
+ public:
+ char **_T;
+
+ sqlite3_table_t() : _T(0) { }
+ sqlite3_table_t(char **T) : _T(T) { }
+ ~sqlite3_table_t() { if(_T) sqlite3_free_table(_T); }
+
+ operator char**&(void) { return _T; }
+
+ operator char ***(void) {
+ if(_T) sqlite3_free_table(_T);
+ return &_T; }
+
+ const char *get(int r,int c,int nc) {
+ assert(_T);
+ return _T[r*nc+c];
+ }
+};
diff --git a/test/test.cc b/test/test.cc
index 1a012b5..35f58ab 100644
--- a/test/test.cc
+++ b/test/test.cc
@@ -1,139 +1,90 @@
#include <iostream>
#include <stdexcept>
using namespace std;
#include <opkele/exception.h>
-#include <opkele/consumer.h>
#include <opkele/util.h>
#include "config.h"
class failed_test : public opkele::exception {
public:
failed_test(OPKELE_E_PARS)
: exception(OPKELE_E_CONS) { }
};
-class dummy_consumer_t : public opkele::consumer_t {
- public:
- virtual opkele::assoc_t store_assoc(const string& /* server */,const string& /* handle */,const opkele::secret_t& /* secret */,int /* expires_in */) {
- throw opkele::not_implemented(OPKELE_CP_ "Not implemented");
- }
- virtual opkele::assoc_t retrieve_assoc(const string& /* server */ ,const string& /* handle */) {
- throw opkele::not_implemented(OPKELE_CP_ "Not implemented");
- }
- virtual void invalidate_assoc(const string& /* server */,const string& /* handle */) {
- throw opkele::not_implemented(OPKELE_CP_ "Not implemented");
- }
-};
-
-
-void test_retrieve_links(const string& f,bool success,const string& s="",const string& d="") {
- dummy_consumer_t dc;
- string server, delegate;
- try {
- dc.retrieve_links("file://" OPKELE_SRC_DIR "/test/html/"+f,server,delegate);
- if(!success)
- throw failed_test(OPKELE_CP_ "Retrieved links when it shouldn't");
- if(server!=s)
- throw failed_test(OPKELE_CP_ "retrieve_links test failed, expected server '"+s+"', got '"+server+"'");
- if(delegate!=d)
- throw failed_test(OPKELE_CP_ "retrieve_links test failed, expected delegate '"+d+"', got '"+delegate+"'");
- }catch(opkele::bad_input& obi) {
- if(success)
- throw failed_test(OPKELE_CP_ "Test '"+f+"' failed due to 'bad_input'["+obi.what()+"]");
- }catch(opkele::failed_assertion& ofa) {
- if(success)
- throw failed_test(OPKELE_CP_ "Test '"+f+"' failed due to 'failed_assertion'["+ofa.what()+"]");
- }
-}
-
-void test_retrieve_links() {
- test_retrieve_links("empty.html",false);
- test_retrieve_links("in-body.html",false);
- test_retrieve_links("head-in-body.html",false);
- test_retrieve_links("hkn.html",true,"http://www.klever.net/openid.server","http://hacker.klever.net/");
- test_retrieve_links("hkn-server.html",true,"http://www.klever.net/openid.server");
- test_retrieve_links("hkn-delegate.html",false);
- test_retrieve_links("unclosed-head.html",true,"http://www.klever.net/openid.server","http://hacker.klever.net/");
- test_retrieve_links("spaced-links.html",true,"http://www.klever.net/openid.server","http://hacker.klever.net/");
- test_retrieve_links("spaced-link-attrs.html",true,"http://www.klever.net/openid.server","http://hacker.klever.net/");
- test_retrieve_links("2rels.html",true,"http://www.klever.net/openid.server","http://www.klever.net/openid.server");
-}
-
void test_rfc_3986_normalize_uri(const string &ouri,bool success,const string& nuri="") {
try {
string n = opkele::util::rfc_3986_normalize_uri(ouri);
if(!success)
throw failed_test(OPKELE_CP_ "Normalized URI when it shouldn't");
if(n!=nuri)
throw failed_test(OPKELE_CP_ "rfc_3986_test_failed for '"+ouri+"' failed, expected '"+nuri+"', got '"+n+"'");
}catch(opkele::bad_input& obi) {
if(success)
throw failed_test(OPKELE_CP_ "Test '"+ouri+"' failed due to 'bad_input'["+obi.what()+"]");
}catch(opkele::not_implemented& oni) {
if(success)
throw failed_test(OPKELE_CP_ "Test '"+ouri+"' failed due to 'not_implemented'["+oni.what()+"]");
}
}
void test_rfc_3986_normalize_uri() {
test_rfc_3986_normalize_uri(
"invalid", false );
test_rfc_3986_normalize_uri(
"ftp://hacker.klever.net/", false );
test_rfc_3986_normalize_uri(
"http://", false );
test_rfc_3986_normalize_uri(
"http:/hacker.klever.net/", false );
test_rfc_3986_normalize_uri(
"hTTp://hacker.klever.net#uh?oh", true, "http://hacker.klever.net/#uh?oh" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net?uh#oh", true, "http://hacker.klever.net/?uh#oh" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net:80/", true, "http://hacker.klever.net/" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net:80?uh", true, "http://hacker.klever.net/?uh" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net:80#uh", true, "http://hacker.klever.net/#uh" );
test_rfc_3986_normalize_uri(
"https://hacker.klever.net:443", true, "https://hacker.klever.net/" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net:?oh", true, "http://hacker.klever.net/?oh" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah%2E", true, "http://hacker.klever.net/ah." );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah/%2E/", true, "http://hacker.klever.net/ah/" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah/%2b/", true, "http://hacker.klever.net/ah/%2B/" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah/./oh?eh", true, "http://hacker.klever.net/ah/oh?eh" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah/../oh?", true, "http://hacker.klever.net/oh?" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah//oh?", true, "http://hacker.klever.net/ah/oh?" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah/?", true, "http://hacker.klever.net/ah/?" );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah/%", false );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah/%a", false );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah/%zx", false );
test_rfc_3986_normalize_uri(
"http://hacker.klever.net/ah/%5x", false );
test_rfc_3986_normalize_uri(
"Http://Hacker.Klever.Net:", true, "http://hacker.klever.net/" );
}
int main() {
try {
test_rfc_3986_normalize_uri();
- test_retrieve_links();
}catch(failed_test& ft) {
cerr << "Test failed: " << ft.what() << endl;
}catch(exception& e) {
cerr << "oops: " << e.what() << endl;
_exit(1);
}
_exit(0);
}