summaryrefslogtreecommitdiffabout
path: root/test
authorMichael Krelin <hacker@klever.net>2008-01-31 22:12:24 (UTC)
committer Michael Krelin <hacker@klever.net>2008-01-31 22:12:24 (UTC)
commit0a90a7791bd329afd8955df78b8ae358adc897a8 (patch) (unidiff)
tree142bad9602519b9b92200fc7ee6e4f09ad7099bd /test
parent67133db1f33b142561575cdf99fedca8fb6ad79b (diff)
downloadlibopkele-0a90a7791bd329afd8955df78b8ae358adc897a8.zip
libopkele-0a90a7791bd329afd8955df78b8ae358adc897a8.tar.gz
libopkele-0a90a7791bd329afd8955df78b8ae358adc897a8.tar.bz2
test: moved kingate_openid_message wrapper into a separate .h
again, to be used in sample OP Signed-off-by: Michael Krelin <hacker@klever.net>
Diffstat (limited to 'test') (more/less context) (ignore whitespace changes)
-rw-r--r--test/RP.cc110
-rw-r--r--test/kingate_openid_message.h108
2 files changed, 109 insertions, 109 deletions
diff --git a/test/RP.cc b/test/RP.cc
index f2f8851..e9744a4 100644
--- a/test/RP.cc
+++ b/test/RP.cc
@@ -1,333 +1,225 @@
1#include <uuid/uuid.h> 1#include <uuid/uuid.h>
2#include <iostream> 2#include <iostream>
3#include <cassert> 3#include <cassert>
4#include <stdexcept> 4#include <stdexcept>
5#include <string> 5#include <string>
6#include <set> 6#include <set>
7#include <iterator> 7#include <iterator>
8using namespace std; 8using namespace std;
9#include <kingate/exception.h> 9#include <kingate/exception.h>
10#include <kingate/plaincgi.h> 10#include <kingate/plaincgi.h>
11#include <kingate/cgi_gateway.h> 11#include <kingate/cgi_gateway.h>
12#include <opkele/exception.h> 12#include <opkele/exception.h>
13#include <opkele/types.h> 13#include <opkele/types.h>
14#include <opkele/util.h> 14#include <opkele/util.h>
15#include <opkele/uris.h> 15#include <opkele/uris.h>
16#include <opkele/discovery.h> 16#include <opkele/discovery.h>
17#include <opkele/association.h> 17#include <opkele/association.h>
18#include <opkele/sreg.h> 18#include <opkele/sreg.h>
19using namespace opkele; 19using namespace opkele;
20#include <opkele/prequeue_rp.h> 20#include <opkele/prequeue_rp.h>
21#include <opkele/debug.h> 21#include <opkele/debug.h>
22 22
23#include "sqlite.h" 23#include "sqlite.h"
24#include "kingate_openid_message.h"
24 25
25#undef DUMB_RP 26#undef DUMB_RP
26 27
27#ifdef DUMB_RP 28#ifdef DUMB_RP
28# define DUMBTHROW throw opkele::dumb_RP(OPKELE_CP_ "This RP is dumb") 29# define DUMBTHROW throw opkele::dumb_RP(OPKELE_CP_ "This RP is dumb")
29#else 30#else
30# define DUMBTHROW (void)0 31# define DUMBTHROW (void)0
31#endif 32#endif
32 33
33template<typename IT>
34class join_iterator : public iterator<
35 input_iterator_tag,typename IT::value_type,
36 void,typename IT::pointer,typename IT::reference> {
37 public:
38 typedef pair<IT,IT> range_t;
39 typedef list<range_t> ranges_t;
40 ranges_t ranges;
41
42 join_iterator() { }
43
44 bool cleanup() {
45 bool rv = false;
46 while(!(ranges.empty() || ranges.front().first!=ranges.front().second)) {
47 ranges.pop_front(); rv = true;
48 }
49 return rv;
50 }
51
52 join_iterator<IT>& add_range(const IT& b,const IT& e) {
53 ranges.push_back(typename ranges_t::value_type(b,e));
54 cleanup();
55 return *this;
56 }
57
58 bool operator==(const join_iterator<IT>& x) const {
59 return ranges==x.ranges; }
60 bool operator!=(const join_iterator<IT>& x) const {
61 return ranges!=x.ranges; }
62
63 typename IT::reference operator*() const {
64 assert(!ranges.empty());
65 assert(ranges.front().first!=ranges.front().second);
66 return *ranges.front().first; }
67 typename IT::pointer operator->() const {
68 assert(!ranges.empty());
69 assert(ranges.front().first!=ranges.front().second);
70 return ranges.front().first.operator->(); }
71
72 join_iterator<IT>& operator++() {
73 cleanup();
74 if(ranges.empty()) return *this;
75 do {
76 ++ranges.front().first;
77 }while(cleanup() && !ranges.empty());
78 return *this;
79 }
80 join_iterator<IT> operator++(int) {
81 join_iterator<IT> rv(*this);
82 ++(*this); return rv; }
83};
84
85template<typename IT>
86class cut_prefix_filterator : public opkele::util::basic_filterator<IT> {
87 public:
88 string pfx;
89 mutable string tmp;
90
91 cut_prefix_filterator() { }
92 cut_prefix_filterator(const IT& bi,const IT&ei,const string& pfx)
93 : opkele::util::basic_filterator<IT>(bi,ei), pfx(pfx) {
94 this->prepare();
95 }
96
97 bool is_interesting() const {
98 return pfx.length()==0 || !strncmp(this->it->c_str(),pfx.c_str(),pfx.length());
99 }
100
101 typename IT::reference operator*() const {
102 assert(!this->empty);
103 tmp = *this->it; tmp.erase(0,pfx.length());
104 return tmp; }
105 typename IT::pointer operator->() const {
106 assert(!this->empty);
107 return &this->operator*(); }
108};
109
110class kingate_openid_message_t : public opkele::basic_openid_message {
111 typedef join_iterator<kingate::cgi_gateway::params_t::const_iterator> jitterator;
112 typedef opkele::util::map_keys_iterator<
113 jitterator,
114 fields_iterator::value_type,
115 fields_iterator::reference,
116 fields_iterator::pointer> keys_iterator;
117 typedef cut_prefix_filterator<keys_iterator> pfilterator;
118 public:
119 const kingate::cgi_gateway& gw;
120
121 kingate_openid_message_t(const kingate::cgi_gateway& g) : gw(g) { }
122
123 bool has_field(const string& n) const {
124 return gw.has_param("openid."+n); }
125 const string& get_field(const string& n) const {
126 return gw.get_param("openid."+n); }
127
128 fields_iterator fields_begin() const {
129 return
130 pfilterator( keys_iterator(
131 jitterator()
132 .add_range( gw.get.begin(), gw.get.end() )
133 .add_range( gw.post.begin(), gw.post.end() ),
134 jitterator()
135 ), keys_iterator(), "openid." );
136 }
137 fields_iterator fields_end() const {
138 return pfilterator();
139 }
140};
141
142class rpdb_t : public sqlite3_t { 34class rpdb_t : public sqlite3_t {
143 public: 35 public:
144 rpdb_t() 36 rpdb_t()
145 : sqlite3_t("/tmp/RP.db") { 37 : sqlite3_t("/tmp/RP.db") {
146 assert(_D); 38 assert(_D);
147 char **resp; int nrow,ncol; char *errm; 39 char **resp; int nrow,ncol; char *errm;
148 if(sqlite3_get_table( 40 if(sqlite3_get_table(
149 _D,"SELECT a_op FROM assoc LIMIT 0", 41 _D,"SELECT a_op FROM assoc LIMIT 0",
150 &resp,&nrow,&ncol,&errm)!=SQLITE_OK) { 42 &resp,&nrow,&ncol,&errm)!=SQLITE_OK) {
151 extern const char *__RP_db_bootstrap; 43 extern const char *__RP_db_bootstrap;
152 DOUT_("Bootstrapping DB"); 44 DOUT_("Bootstrapping DB");
153 if(sqlite3_exec(_D,__RP_db_bootstrap,NULL,NULL,&errm)!=SQLITE_OK) 45 if(sqlite3_exec(_D,__RP_db_bootstrap,NULL,NULL,&errm)!=SQLITE_OK)
154 throw opkele::exception(OPKELE_CP_ string("Failed to bootstrap SQLite database: ")+errm); 46 throw opkele::exception(OPKELE_CP_ string("Failed to bootstrap SQLite database: ")+errm);
155 }else 47 }else
156 sqlite3_free_table(resp); 48 sqlite3_free_table(resp);
157 49
158 } 50 }
159}; 51};
160 52
161class example_rp_t : public opkele::prequeue_RP { 53class example_rp_t : public opkele::prequeue_RP {
162 public: 54 public:
163 mutable rpdb_t db; 55 mutable rpdb_t db;
164 kingate::cookie htc; 56 kingate::cookie htc;
165 long as_id; 57 long as_id;
166 int ordinal; 58 int ordinal;
167 kingate::cgi_gateway& gw; 59 kingate::cgi_gateway& gw;
168 60
169 example_rp_t(kingate::cgi_gateway& gw) 61 example_rp_t(kingate::cgi_gateway& gw)
170 : ordinal(0), have_eqtop(false), gw(gw), as_id(-1) { 62 : ordinal(0), have_eqtop(false), gw(gw), as_id(-1) {
171 try { 63 try {
172 htc = gw.cookies.get_cookie("ht_session"); 64 htc = gw.cookies.get_cookie("ht_session");
173 as_id = opkele::util::string_to_long(gw.get_param("asid")); 65 as_id = opkele::util::string_to_long(gw.get_param("asid"));
174 }catch(kingate::exception_notfound& kenf) { 66 }catch(kingate::exception_notfound& kenf) {
175 uuid_t uuid; uuid_generate(uuid); 67 uuid_t uuid; uuid_generate(uuid);
176 htc = kingate::cookie("ht_session",util::encode_base64(uuid,sizeof(uuid))); 68 htc = kingate::cookie("ht_session",util::encode_base64(uuid,sizeof(uuid)));
177 sqlite3_mem_t<char*> S = sqlite3_mprintf( 69 sqlite3_mem_t<char*> S = sqlite3_mprintf(
178 "INSERT INTO ht_sessions (hts_id) VALUES (%Q)", 70 "INSERT INTO ht_sessions (hts_id) VALUES (%Q)",
179 htc.get_value().c_str()); 71 htc.get_value().c_str());
180 db.exec(S); 72 db.exec(S);
181 } 73 }
182 } 74 }
183 75
184 /* Global persistent store */ 76 /* Global persistent store */
185 77
186 opkele::assoc_t store_assoc( 78 opkele::assoc_t store_assoc(
187 const string& OP,const string& handle, 79 const string& OP,const string& handle,
188 const string& type,const secret_t& secret, 80 const string& type,const secret_t& secret,
189 int expires_in) { 81 int expires_in) {
190 DUMBTHROW; 82 DUMBTHROW;
191 DOUT_("Storing '" << handle << "' assoc with '" << OP << "'"); 83 DOUT_("Storing '" << handle << "' assoc with '" << OP << "'");
192 time_t exp = time(0)+expires_in; 84 time_t exp = time(0)+expires_in;
193 sqlite3_mem_t<char*> 85 sqlite3_mem_t<char*>
194 S = sqlite3_mprintf( 86 S = sqlite3_mprintf(
195 "INSERT INTO assoc" 87 "INSERT INTO assoc"
196 " (a_op,a_handle,a_type,a_ctime,a_etime,a_secret)" 88 " (a_op,a_handle,a_type,a_ctime,a_etime,a_secret)"
197 " VALUES (" 89 " VALUES ("
198 " %Q,%Q,%Q," 90 " %Q,%Q,%Q,"
199 " datetime('now'), datetime('now','+%d seconds')," 91 " datetime('now'), datetime('now','+%d seconds'),"
200 " %Q" 92 " %Q"
201 " );", OP.c_str(), handle.c_str(), type.c_str(), 93 " );", OP.c_str(), handle.c_str(), type.c_str(),
202 expires_in, 94 expires_in,
203 util::encode_base64(&(secret.front()),secret.size()).c_str() ); 95 util::encode_base64(&(secret.front()),secret.size()).c_str() );
204 db.exec(S); 96 db.exec(S);
205 return opkele::assoc_t(new opkele::association( 97 return opkele::assoc_t(new opkele::association(
206 OP, handle, type, secret, exp, false )); 98 OP, handle, type, secret, exp, false ));
207 } 99 }
208 100
209 opkele::assoc_t find_assoc( 101 opkele::assoc_t find_assoc(
210 const string& OP) { 102 const string& OP) {
211 DUMBTHROW; 103 DUMBTHROW;
212 DOUT_("Looking for an assoc with '" << OP << '\''); 104 DOUT_("Looking for an assoc with '" << OP << '\'');
213 sqlite3_mem_t<char*> 105 sqlite3_mem_t<char*>
214 S = sqlite3_mprintf( 106 S = sqlite3_mprintf(
215 "SELECT" 107 "SELECT"
216 " a_op,a_handle,a_type,a_secret," 108 " a_op,a_handle,a_type,a_secret,"
217 " strftime('%%s',a_etime) AS a_etime" 109 " strftime('%%s',a_etime) AS a_etime"
218 " FROM assoc" 110 " FROM assoc"
219 " WHERE a_op=%Q AND a_itime IS NULL AND NOT a_stateless" 111 " WHERE a_op=%Q AND a_itime IS NULL AND NOT a_stateless"
220 " AND ( a_etime > datetime('now','-30 seconds') )" 112 " AND ( a_etime > datetime('now','-30 seconds') )"
221 " LIMIT 1", 113 " LIMIT 1",
222 OP.c_str()); 114 OP.c_str());
223 sqlite3_table_t T; 115 sqlite3_table_t T;
224 int nr,nc; 116 int nr,nc;
225 db.get_table(S,T,&nr,&nc); 117 db.get_table(S,T,&nr,&nc);
226 if(nr<1) 118 if(nr<1)
227 throw opkele::failed_lookup(OPKELE_CP_ "Couldn't find unexpired handle"); 119 throw opkele::failed_lookup(OPKELE_CP_ "Couldn't find unexpired handle");
228 assert(nr==1); 120 assert(nr==1);
229 assert(nc==5); 121 assert(nc==5);
230 secret_t secret; 122 secret_t secret;
231 util::decode_base64(T.get(1,3,nc),secret); 123 util::decode_base64(T.get(1,3,nc),secret);
232 DOUT_(" found '" << T.get(1,1,nc) << '\''); 124 DOUT_(" found '" << T.get(1,1,nc) << '\'');
233 return opkele::assoc_t(new opkele::association( 125 return opkele::assoc_t(new opkele::association(
234 T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc), 126 T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc),
235 secret, strtol(T.get(1,4,nc),0,0), false )); 127 secret, strtol(T.get(1,4,nc),0,0), false ));
236 } 128 }
237 129
238 opkele::assoc_t retrieve_assoc( 130 opkele::assoc_t retrieve_assoc(
239 const string& OP,const string& handle) { 131 const string& OP,const string& handle) {
240 DUMBTHROW; 132 DUMBTHROW;
241 DOUT_("Retrieving assoc '" << handle << "' with '" << OP << '\''); 133 DOUT_("Retrieving assoc '" << handle << "' with '" << OP << '\'');
242 sqlite3_mem_t<char*> 134 sqlite3_mem_t<char*>
243 S = sqlite3_mprintf( 135 S = sqlite3_mprintf(
244 "SELECT" 136 "SELECT"
245 " a_op,a_handle,a_type,a_secret," 137 " a_op,a_handle,a_type,a_secret,"
246 " strftime('%%s',a_etime) AS a_etime" 138 " strftime('%%s',a_etime) AS a_etime"
247 " FROM assoc" 139 " FROM assoc"
248 " WHERE a_op=%Q AND a_handle=%Q" 140 " WHERE a_op=%Q AND a_handle=%Q"
249 " AND a_itime IS NULL AND NOT a_stateless" 141 " AND a_itime IS NULL AND NOT a_stateless"
250 " LIMIT 1", 142 " LIMIT 1",
251 OP.c_str(),handle.c_str()); 143 OP.c_str(),handle.c_str());
252 sqlite3_table_t T; 144 sqlite3_table_t T;
253 int nr,nc; 145 int nr,nc;
254 db.get_table(S,T,&nr,&nc); 146 db.get_table(S,T,&nr,&nc);
255 if(nr<1) 147 if(nr<1)
256 throw opkele::failed_lookup(OPKELE_CP_ "couldn't retrieve valid association"); 148 throw opkele::failed_lookup(OPKELE_CP_ "couldn't retrieve valid association");
257 assert(nr==1); assert(nc==5); 149 assert(nr==1); assert(nc==5);
258 secret_t secret; util::decode_base64(T.get(1,3,nc),secret); 150 secret_t secret; util::decode_base64(T.get(1,3,nc),secret);
259 DOUT_(" found. type=" << T.get(1,2,nc) << '\''); 151 DOUT_(" found. type=" << T.get(1,2,nc) << '\'');
260 return opkele::assoc_t(new opkele::association( 152 return opkele::assoc_t(new opkele::association(
261 T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc), 153 T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc),
262 secret, strtol(T.get(1,4,nc),0,0), false )); 154 secret, strtol(T.get(1,4,nc),0,0), false ));
263 } 155 }
264 156
265 void invalidate_assoc( 157 void invalidate_assoc(
266 const string& OP,const string& handle) { 158 const string& OP,const string& handle) {
267 DUMBTHROW; 159 DUMBTHROW;
268 DOUT_("Invalidating assoc '" << handle << "' with '" << OP << '\''); 160 DOUT_("Invalidating assoc '" << handle << "' with '" << OP << '\'');
269 sqlite3_mem_t<char*> 161 sqlite3_mem_t<char*>
270 S = sqlite3_mprintf( 162 S = sqlite3_mprintf(
271 "UPDATE assoc SET a_itime=datetime('now')" 163 "UPDATE assoc SET a_itime=datetime('now')"
272 " WHERE a_op=%Q AND a_handle=%Q", 164 " WHERE a_op=%Q AND a_handle=%Q",
273 OP.c_str(), handle.c_str() ); 165 OP.c_str(), handle.c_str() );
274 db.exec(S); 166 db.exec(S);
275 } 167 }
276 168
277 void check_nonce(const string& OP,const string& nonce) { 169 void check_nonce(const string& OP,const string& nonce) {
278 DOUT_("Checking nonce '" << nonce << "' from '" << OP << '\''); 170 DOUT_("Checking nonce '" << nonce << "' from '" << OP << '\'');
279 sqlite3_mem_t<char*> 171 sqlite3_mem_t<char*>
280 S = sqlite3_mprintf( 172 S = sqlite3_mprintf(
281 "SELECT 1 FROM nonces WHERE n_op=%Q AND n_once=%Q", 173 "SELECT 1 FROM nonces WHERE n_op=%Q AND n_once=%Q",
282 OP.c_str(), nonce.c_str()); 174 OP.c_str(), nonce.c_str());
283 sqlite3_table_t T; 175 sqlite3_table_t T;
284 int nr,nc; 176 int nr,nc;
285 db.get_table(S,T,&nr,&nc); 177 db.get_table(S,T,&nr,&nc);
286 if(nr) 178 if(nr)
287 throw opkele::id_res_bad_nonce(OPKELE_CP_ "already seen that nonce"); 179 throw opkele::id_res_bad_nonce(OPKELE_CP_ "already seen that nonce");
288 sqlite3_mem_t<char*> 180 sqlite3_mem_t<char*>
289 SS = sqlite3_mprintf( 181 SS = sqlite3_mprintf(
290 "INSERT INTO nonces (n_op,n_once) VALUES (%Q,%Q)", 182 "INSERT INTO nonces (n_op,n_once) VALUES (%Q,%Q)",
291 OP.c_str(), nonce.c_str()); 183 OP.c_str(), nonce.c_str());
292 db.exec(SS); 184 db.exec(SS);
293 } 185 }
294 186
295 /* Session perisistent store */ 187 /* Session perisistent store */
296 188
297 void begin_queueing() { 189 void begin_queueing() {
298 assert(as_id>=0); 190 assert(as_id>=0);
299 DOUT_("Resetting queue for session '" << htc.get_value() << "'/" << as_id); 191 DOUT_("Resetting queue for session '" << htc.get_value() << "'/" << as_id);
300 sqlite3_mem_t<char*> S = sqlite3_mprintf( 192 sqlite3_mem_t<char*> S = sqlite3_mprintf(
301 "DELETE FROM endpoints_queue" 193 "DELETE FROM endpoints_queue"
302 " WHERE as_id=%ld", 194 " WHERE as_id=%ld",
303 as_id); 195 as_id);
304 db.exec(S); 196 db.exec(S);
305 } 197 }
306 198
307 void queue_endpoint(const opkele::openid_endpoint_t& ep) { 199 void queue_endpoint(const opkele::openid_endpoint_t& ep) {
308 assert(as_id>=0); 200 assert(as_id>=0);
309 DOUT_("Queueing endpoint " << ep.claimed_id << " : " << ep.local_id << " @ " << ep.uri); 201 DOUT_("Queueing endpoint " << ep.claimed_id << " : " << ep.local_id << " @ " << ep.uri);
310 sqlite3_mem_t<char*> S = sqlite3_mprintf( 202 sqlite3_mem_t<char*> S = sqlite3_mprintf(
311 "INSERT INTO endpoints_queue" 203 "INSERT INTO endpoints_queue"
312 " (as_id,eq_ctime,eq_ordinal,eq_uri,eq_claimed_id,eq_local_id)" 204 " (as_id,eq_ctime,eq_ordinal,eq_uri,eq_claimed_id,eq_local_id)"
313 " VALUES (%ld,strftime('%%s','now'),%d,%Q,%Q,%Q)", 205 " VALUES (%ld,strftime('%%s','now'),%d,%Q,%Q,%Q)",
314 as_id,ordinal++, 206 as_id,ordinal++,
315 ep.uri.c_str(),ep.claimed_id.c_str(),ep.local_id.c_str()); 207 ep.uri.c_str(),ep.claimed_id.c_str(),ep.local_id.c_str());
316 db.exec(S); 208 db.exec(S);
317 } 209 }
318 210
319 mutable openid_endpoint_t eqtop; 211 mutable openid_endpoint_t eqtop;
320 mutable bool have_eqtop; 212 mutable bool have_eqtop;
321 213
322 const openid_endpoint_t& get_endpoint() const { 214 const openid_endpoint_t& get_endpoint() const {
323 assert(as_id>=0); 215 assert(as_id>=0);
324 if(!have_eqtop) { 216 if(!have_eqtop) {
325 sqlite3_mem_t<char*> 217 sqlite3_mem_t<char*>
326 S = sqlite3_mprintf( 218 S = sqlite3_mprintf(
327 "SELECT" 219 "SELECT"
328 " eq_uri, eq_claimed_id, eq_local_id" 220 " eq_uri, eq_claimed_id, eq_local_id"
329 " FROM endpoints_queue" 221 " FROM endpoints_queue"
330 " JOIN auth_sessions USING(as_id)" 222 " JOIN auth_sessions USING(as_id)"
331 " WHERE hts_id=%Q AND as_id=%ld" 223 " WHERE hts_id=%Q AND as_id=%ld"
332 " ORDER BY eq_ctime,eq_ordinal" 224 " ORDER BY eq_ctime,eq_ordinal"
333 " LIMIT 1",htc.get_value().c_str(),as_id); 225 " LIMIT 1",htc.get_value().c_str(),as_id);
diff --git a/test/kingate_openid_message.h b/test/kingate_openid_message.h
new file mode 100644
index 0000000..b3a2c9d
--- a/dev/null
+++ b/test/kingate_openid_message.h
@@ -0,0 +1,108 @@
1template<typename IT>
2class join_iterator : public iterator<
3 input_iterator_tag,typename IT::value_type,
4 void,typename IT::pointer,typename IT::reference> {
5 public:
6 typedef pair<IT,IT> range_t;
7 typedef list<range_t> ranges_t;
8 ranges_t ranges;
9
10 join_iterator() { }
11
12 bool cleanup() {
13 bool rv = false;
14 while(!(ranges.empty() || ranges.front().first!=ranges.front().second)) {
15 ranges.pop_front(); rv = true;
16 }
17 return rv;
18 }
19
20 join_iterator<IT>& add_range(const IT& b,const IT& e) {
21 ranges.push_back(typename ranges_t::value_type(b,e));
22 cleanup();
23 return *this;
24 }
25
26 bool operator==(const join_iterator<IT>& x) const {
27 return ranges==x.ranges; }
28 bool operator!=(const join_iterator<IT>& x) const {
29 return ranges!=x.ranges; }
30
31 typename IT::reference operator*() const {
32 assert(!ranges.empty());
33 assert(ranges.front().first!=ranges.front().second);
34 return *ranges.front().first; }
35 typename IT::pointer operator->() const {
36 assert(!ranges.empty());
37 assert(ranges.front().first!=ranges.front().second);
38 return ranges.front().first.operator->(); }
39
40 join_iterator<IT>& operator++() {
41 cleanup();
42 if(ranges.empty()) return *this;
43 do {
44 ++ranges.front().first;
45 }while(cleanup() && !ranges.empty());
46 return *this;
47 }
48 join_iterator<IT> operator++(int) {
49 join_iterator<IT> rv(*this);
50 ++(*this); return rv; }
51};
52
53template<typename IT>
54class cut_prefix_filterator : public opkele::util::basic_filterator<IT> {
55 public:
56 string pfx;
57 mutable string tmp;
58
59 cut_prefix_filterator() { }
60 cut_prefix_filterator(const IT& bi,const IT&ei,const string& pfx)
61 : opkele::util::basic_filterator<IT>(bi,ei), pfx(pfx) {
62 this->prepare();
63 }
64
65 bool is_interesting() const {
66 return pfx.length()==0 || !strncmp(this->it->c_str(),pfx.c_str(),pfx.length());
67 }
68
69 typename IT::reference operator*() const {
70 assert(!this->empty);
71 tmp = *this->it; tmp.erase(0,pfx.length());
72 return tmp; }
73 typename IT::pointer operator->() const {
74 assert(!this->empty);
75 return &this->operator*(); }
76};
77
78class kingate_openid_message_t : public opkele::basic_openid_message {
79 typedef join_iterator<kingate::cgi_gateway::params_t::const_iterator> jitterator;
80 typedef opkele::util::map_keys_iterator<
81 jitterator,
82 fields_iterator::value_type,
83 fields_iterator::reference,
84 fields_iterator::pointer> keys_iterator;
85 typedef cut_prefix_filterator<keys_iterator> pfilterator;
86 public:
87 const kingate::cgi_gateway& gw;
88
89 kingate_openid_message_t(const kingate::cgi_gateway& g) : gw(g) { }
90
91 bool has_field(const string& n) const {
92 return gw.has_param("openid."+n); }
93 const string& get_field(const string& n) const {
94 return gw.get_param("openid."+n); }
95
96 fields_iterator fields_begin() const {
97 return
98 pfilterator( keys_iterator(
99 jitterator()
100 .add_range( gw.get.begin(), gw.get.end() )
101 .add_range( gw.post.begin(), gw.post.end() ),
102 jitterator()
103 ), keys_iterator(), "openid." );
104 }
105 fields_iterator fields_end() const {
106 return pfilterator();
107 }
108};