summaryrefslogtreecommitdiffabout
path: root/lib/discovery.cc
Unidiff
Diffstat (limited to 'lib/discovery.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/discovery.cc17
1 files changed, 8 insertions, 9 deletions
diff --git a/lib/discovery.cc b/lib/discovery.cc
index b7f2db6..5913ad4 100644
--- a/lib/discovery.cc
+++ b/lib/discovery.cc
@@ -1,49 +1,48 @@
1#include <list> 1#include <list>
2#include <opkele/curl.h> 2#include <opkele/curl.h>
3#include <opkele/expat.h> 3#include <opkele/expat.h>
4#include <opkele/uris.h> 4#include <opkele/uris.h>
5#include <opkele/discovery.h> 5#include <opkele/discovery.h>
6#include <opkele/exception.h> 6#include <opkele/exception.h>
7#include <opkele/util.h> 7#include <opkele/util.h>
8#include <opkele/tidy.h> 8#include <opkele/tidy.h>
9#include <opkele/data.h>
9#include <opkele/debug.h> 10#include <opkele/debug.h>
10 11
11#include "config.h" 12#include "config.h"
12 13
13#define XRDS_HEADER "X-XRDS-Location" 14#define XRDS_HEADER "X-XRDS-Location"
14#define CT_HEADER "Content-Type" 15#define CT_HEADER "Content-Type"
15 16
16namespace opkele { 17namespace opkele {
17 using std::list; 18 using std::list;
18 using xrd::XRD_t; 19 using xrd::XRD_t;
19 using xrd::service_t; 20 using xrd::service_t;
20 21
21 /* TODO: the whole discovery thing needs cleanup and optimization due to 22 /* TODO: the whole discovery thing needs cleanup and optimization due to
22 * many changes of concept. */ 23 * many changes of concept. */
23 24
24 static const char *whitespace = " \t\r\n";
25 static const char *i_leaders = "=@+$!(";
26 static const size_t max_html = 16384; 25 static const size_t max_html = 16384;
27 26
28 static const struct service_type_t { 27 static const struct service_type_t {
29 const char *uri; 28 const char *uri;
30 const char *forceid; 29 const char *forceid;
31 } op_service_types[] = { 30 } op_service_types[] = {
32 { STURI_OPENID20_OP, IDURI_SELECT20 }, 31 { STURI_OPENID20_OP, IDURI_SELECT20 },
33 { STURI_OPENID20, 0 }, 32 { STURI_OPENID20, 0 },
34 { STURI_OPENID11, 0 }, 33 { STURI_OPENID11, 0 },
35 { STURI_OPENID10, 0 } 34 { STURI_OPENID10, 0 }
36 }; 35 };
37 enum { 36 enum {
38 st_index_1 = 2, st_index_2 = 1 37 st_index_1 = 2, st_index_2 = 1
39 }; 38 };
40 39
41 40
42 static inline bool is_qelement(const XML_Char *n,const char *qen) { 41 static inline bool is_qelement(const XML_Char *n,const char *qen) {
43 return !strcasecmp(n,qen); 42 return !strcasecmp(n,qen);
44 } 43 }
45 static inline bool is_element(const XML_Char *n,const char *en) { 44 static inline bool is_element(const XML_Char *n,const char *en) {
46 if(!strcasecmp(n,en)) return true; 45 if(!strcasecmp(n,en)) return true;
47 int nl = strlen(n), enl = strlen(en); 46 int nl = strlen(n), enl = strlen(en);
48 if( (nl>=(enl+1)) && n[nl-enl-1]=='\t' 47 if( (nl>=(enl+1)) && n[nl-enl-1]=='\t'
49 && !strcasecmp(&n[nl-enl],en) ) 48 && !strcasecmp(&n[nl-enl],en) )
@@ -107,60 +106,60 @@ namespace opkele {
107 || (r=set_header()) 106 || (r=set_header())
108 ; 107 ;
109 if(r) 108 if(r)
110 throw exception_curl(OPKELE_CP_ "failed to set curly options",r); 109 throw exception_curl(OPKELE_CP_ "failed to set curly options",r);
111 } 110 }
112 ~idigger_t() throw() { } 111 ~idigger_t() throw() { }
113 112
114 void yadiscover(endpoint_discovery_iterator oi,const string& yurl,const char **types,bool redirs) { 113 void yadiscover(endpoint_discovery_iterator oi,const string& yurl,const char **types,bool redirs) {
115 idiscovery_t idis; 114 idiscovery_t idis;
116 idis.xri_identity = false; 115 idis.xri_identity = false;
117 discover_at(idis,yurl,xmode_html|xmode_xrd|(redirs?0:xmode_noredirs)); 116 discover_at(idis,yurl,xmode_html|xmode_xrd|(redirs?0:xmode_noredirs));
118 if(!xrds_location.empty()) { 117 if(!xrds_location.empty()) {
119 idis.clear(); 118 idis.clear();
120 discover_at(idis,xrds_location,xmode_xrd); 119 discover_at(idis,xrds_location,xmode_xrd);
121 } 120 }
122 idis.normalized_id = idis.canonicalized_id = yurl; 121 idis.normalized_id = idis.canonicalized_id = yurl;
123 service_type_t st; 122 service_type_t st;
124 for(st.uri=*types;*types;st.uri=*(++types)) 123 for(st.uri=*types;*types;st.uri=*(++types))
125 queue_endpoints(oi,idis,&st); 124 queue_endpoints(oi,idis,&st);
126 } 125 }
127 126
128 string discover(endpoint_discovery_iterator& oi,const string& identity) { 127 string discover(endpoint_discovery_iterator& oi,const string& identity) {
129 string rv; 128 string rv;
130 idiscovery_t idis; 129 idiscovery_t idis;
131 string::size_type fsc = identity.find_first_not_of(whitespace); 130 string::size_type fsc = identity.find_first_not_of(data::_whitespace_chars);
132 if(fsc==string::npos) 131 if(fsc==string::npos)
133 throw bad_input(OPKELE_CP_ "whitespace-only identity"); 132 throw bad_input(OPKELE_CP_ "whitespace-only identity");
134 string::size_type lsc = identity.find_last_not_of(whitespace); 133 string::size_type lsc = identity.find_last_not_of(data::_whitespace_chars);
135 assert(lsc!=string::npos); 134 assert(lsc!=string::npos);
136 if(!strncasecmp(identity.c_str()+fsc,"xri://",sizeof("xri://")-1)) 135 if(!strncasecmp(identity.c_str()+fsc,"xri://",sizeof("xri://")-1))
137 fsc += sizeof("xri://")-1; 136 fsc += sizeof("xri://")-1;
138 if((fsc+1)>=lsc) 137 if((fsc+1)>=lsc)
139 throw bad_input(OPKELE_CP_ "not a character of importance in identity"); 138 throw bad_input(OPKELE_CP_ "not a character of importance in identity");
140 string id(identity,fsc,lsc-fsc+1); 139 string id(identity,fsc,lsc-fsc+1);
141 idis.clear(); 140 idis.clear();
142 if(strchr(i_leaders,id[0])) { 141 if(strchr(data::_iname_leaders,id[0])) {
143 /* TODO: further normalize xri identity? Like folding case 142 /* TODO: further normalize xri identity? Like folding case
144 * or whatever... */ 143 * or whatever... */
145 rv = id; 144 rv = id;
146 set<string> cids; 145 set<string> cids;
147 for(const struct service_type_t *st=op_service_types; 146 for(const struct service_type_t *st=op_service_types;
148 st<&op_service_types[sizeof(op_service_types)/sizeof(*op_service_types)];++st) { 147 st<&op_service_types[sizeof(op_service_types)/sizeof(*op_service_types)];++st) {
149 idis.clear(); 148 idis.clear();
150 discover_at( idis, 149 discover_at( idis,
151 xri_proxy + util::url_encode(id)+ 150 xri_proxy + util::url_encode(id)+
152 "?_xrd_t="+util::url_encode(st->uri)+ 151 "?_xrd_t="+util::url_encode(st->uri)+
153 "&_xrd_r=application/xrd%2Bxml" 152 "&_xrd_r=application/xrd%2Bxml"
154 ";sep=true;refs=true", 153 ";sep=true;refs=true",
155 xmode_xrd ); 154 xmode_xrd );
156 if(status_code==241) continue; 155 if(status_code==241) continue;
157 if(status_code!=100) 156 if(status_code!=100)
158 throw failed_xri_resolution(OPKELE_CP_ 157 throw failed_xri_resolution(OPKELE_CP_
159 "XRI resolution failed with '"+status_string+"' message" 158 "XRI resolution failed with '"+status_string+"' message"
160 ", while looking for SEP with type '"+st->uri+"'", status_code); 159 ", while looking for SEP with type '"+st->uri+"'", status_code);
161 if(idis.xrd.canonical_ids.empty()) 160 if(idis.xrd.canonical_ids.empty())
162 throw opkele::failed_discovery(OPKELE_CP_ "No CanonicalID for XRI identity found"); 161 throw opkele::failed_discovery(OPKELE_CP_ "No CanonicalID for XRI identity found");
163 string cid = idis.xrd.canonical_ids.begin()->second; 162 string cid = idis.xrd.canonical_ids.begin()->second;
164 if(cids.find(cid)==cids.end()) { 163 if(cids.find(cid)==cids.end()) {
165 cids.insert(cid); 164 cids.insert(cid);
166 idis.clear(); 165 idis.clear();
@@ -474,55 +473,55 @@ namespace opkele {
474 473
475 void html_start_element(const XML_Char *n,const XML_Char **a) { 474 void html_start_element(const XML_Char *n,const XML_Char **a) {
476 if(is_element(n,"meta")) { 475 if(is_element(n,"meta")) {
477 bool heq = false; 476 bool heq = false;
478 string l; 477 string l;
479 for(;*a;a+=2) { 478 for(;*a;a+=2) {
480 if(!( strcasecmp(a[0],"http-equiv") 479 if(!( strcasecmp(a[0],"http-equiv")
481 || strcasecmp(a[1],XRDS_HEADER) )) 480 || strcasecmp(a[1],XRDS_HEADER) ))
482 heq = true; 481 heq = true;
483 else if(!strcasecmp(a[0],"content")) 482 else if(!strcasecmp(a[0],"content"))
484 l.assign(a[1]); 483 l.assign(a[1]);
485 } 484 }
486 if(heq) 485 if(heq)
487 xrds_location = l; 486 xrds_location = l;
488 }else if(is_element(n,"link")) { 487 }else if(is_element(n,"link")) {
489 string rels; 488 string rels;
490 string href; 489 string href;
491 for(;*a;a+=2) { 490 for(;*a;a+=2) {
492 if( !strcasecmp(a[0],"rel") ) { 491 if( !strcasecmp(a[0],"rel") ) {
493 rels.assign(a[1]); 492 rels.assign(a[1]);
494 }else if( !strcasecmp(a[0],"href") ) { 493 }else if( !strcasecmp(a[0],"href") ) {
495 const char *ns = a[1]; 494 const char *ns = a[1];
496 for(;*ns && isspace(*ns);++ns); 495 for(;*ns && isspace(*ns);++ns);
497 href.assign(ns); 496 href.assign(ns);
498 string::size_type lns=href.find_last_not_of(whitespace); 497 string::size_type lns=href.find_last_not_of(data::_whitespace_chars);
499 href.erase(lns+1); 498 href.erase(lns+1);
500 } 499 }
501 } 500 }
502 for(string::size_type ns=rels.find_first_not_of(whitespace); 501 for(string::size_type ns=rels.find_first_not_of(data::_whitespace_chars);
503 ns!=string::npos; ns=rels.find_first_not_of(whitespace,ns)) { 502 ns!=string::npos; ns=rels.find_first_not_of(data::_whitespace_chars,ns)) {
504 string::size_type s = rels.find_first_of(whitespace,ns); 503 string::size_type s = rels.find_first_of(data::_whitespace_chars,ns);
505 string rel; 504 string rel;
506 if(s==string::npos) { 505 if(s==string::npos) {
507 rel.assign(rels,ns,string::npos); 506 rel.assign(rels,ns,string::npos);
508 ns = string::npos; 507 ns = string::npos;
509 }else{ 508 }else{
510 rel.assign(rels,ns,s-ns); 509 rel.assign(rels,ns,s-ns);
511 ns = s; 510 ns = s;
512 } 511 }
513 if(rel=="openid.server") 512 if(rel=="openid.server")
514 html_openid1.uris.add(-1,xrd::uri_t(href)); 513 html_openid1.uris.add(-1,xrd::uri_t(href));
515 else if(rel=="openid.delegate") 514 else if(rel=="openid.delegate")
516 html_openid1.local_ids.add(-1,href); 515 html_openid1.local_ids.add(-1,href);
517 else if(rel=="openid2.provider") 516 else if(rel=="openid2.provider")
518 html_openid2.uris.add(-1,xrd::uri_t(href)); 517 html_openid2.uris.add(-1,xrd::uri_t(href));
519 else if(rel=="openid2.local_id") 518 else if(rel=="openid2.local_id")
520 html_openid2.local_ids.add(-1,href); 519 html_openid2.local_ids.add(-1,href);
521 } 520 }
522 }else if(is_element(n,"body")) { 521 }else if(is_element(n,"body")) {
523 skipping = -1; 522 skipping = -1;
524 } 523 }
525 } 524 }
526 525
527 void queue_endpoints(endpoint_discovery_iterator& oi, 526 void queue_endpoints(endpoint_discovery_iterator& oi,
528 const idiscovery_t &id, 527 const idiscovery_t &id,