-rw-r--r-- | lib/discovery.cc | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/lib/discovery.cc b/lib/discovery.cc index bd1f917..b4ed3b6 100644 --- a/lib/discovery.cc +++ b/lib/discovery.cc @@ -254,64 +254,65 @@ namespace opkele { if(!td) throw exception_tidy(OPKELE_CP_ "failed to create htmltidy document"); #ifdef NDEBUG td.opt_set(TidyQuiet,true); td.opt_set(TidyShowWarnings,false); #else /* NDEBUG */ td.opt_set(TidyQuiet,false); td.opt_set(TidyShowWarnings,true); #endif /* NDEBUG */ td.opt_set(TidyForceOutput,true); td.opt_set(TidyXhtmlOut,true); td.opt_set(TidyDoctypeMode,TidyDoctypeOmit); td.opt_set(TidyMark,false); td.opt_set(TidyNumEntities,true); if(td.parse_string(save_html)<=0) throw exception_tidy(OPKELE_CP_ "tidy failed to parse document"); if(td.clean_and_repair()<=0) throw exception_tidy(OPKELE_CP_ "tidy failed to clean and repair"); util::tidy_buf_t tide; if(td.save_buffer(tide)<=0) throw exception_tidy(OPKELE_CP_ "tidy failed to save buffer"); prepare_to_parse(); parse(tide.c_str(),tide.size(),true); }catch(exception_tidy& et) { } } save_html.clear(); } void prepare_to_parse() { (*(expat_t*)this) = parser_create_ns(); set_user_data(); set_element_handler(); set_character_data_handler(); + set_unknown_encoding_handler(); if(xmode&xmode_html) { html_openid1.clear(); html_openid2.clear(); parser_choked = false; } cdata = 0; xrd_service = 0; skipping = 0; pt_stack.clear(); status_code = 100; status_string.clear(); } void html2xrd(endpoint_discovery_iterator& oi,idiscovery_t& id) { XRD_t& x = id.xrd; if(!html_openid2.uris.empty()) { html_openid2.types.insert(STURI_OPENID20); x.services.add(-1,html_openid2); queue_endpoints(oi,id,&op_service_types[st_index_2]); } if(!html_openid1.uris.empty()) { html_openid1.types.insert(STURI_OPENID11); x.services.add(-1,html_openid1); queue_endpoints(oi,id,&op_service_types[st_index_1]); } } size_t write(void *p,size_t s,size_t nm) { /* TODO: limit total size */ size_t bytes = s*nm; const char *inbuf = (const char*)p; if(xmode&xmode_html) { size_t mbts = save_html.capacity()-save_html.size(); size_t bts = 0; @@ -424,83 +425,98 @@ namespace opkele { cdata_buf.clear(); cdata = &cdata_buf; }else if(is_qelement(n,NSURI_XRD "\tURI")) { assert(xrd); assert(xrd_service); const char *append = element_attr(a,"append"); xrd::uri_t& uri = xrd_service->uris.add(element_priority(a),xrd::uri_t("",append?append:"")); cdata = &uri.uri; }else if(is_qelement(n,NSURI_XRD "\tLocalID") || is_qelement(n,NSURI_OPENID10 "\tDelegate") ) { assert(xrd); assert(xrd_service); cdata = &(xrd_service->local_ids.add(element_priority(a),string())); }else if(is_qelement(n,NSURI_XRD "\tProviderID")) { assert(xrd); assert(xrd_service); cdata = &(xrd_service->provider_id); }else{ skipping = 1; } }else skipping = 1; }else if(xmode&xmode_html) { html_start_element(n,a); }else{ skipping = 1; } } } void end_element(const XML_Char *n) { if(skipping<0) return; if(skipping) { --skipping; return; } if(is_qelement(n,NSURI_XRD "\tType")) { - assert(xrd); assert(xrd_service); assert(cdata==&cdata_buf); - xrd_service->types.insert(cdata_buf); + if(xrd && xrd_service) { + assert(cdata==&cdata_buf); + xrd_service->types.insert(cdata_buf); + } }else if(is_qelement(n,NSURI_XRD "\tService")) { - assert(xrd); assert(xrd_service); - assert(!pt_stack.empty()); - assert(pt_stack.back()==(NSURI_XRD "\tService")); - pt_stack.pop_back(); - xrd_service = 0; - }else if(is_qelement(n,NSURI_XRD "\tStatus")) { - assert(xrd); - if(is_qelement(pt_stack.back().c_str(),n)) { - assert(cdata==&status_string); + if(!(xrd && xrd_service)) { + skipping = -1; + }else{ + assert(!pt_stack.empty()); + assert(pt_stack.back()==(NSURI_XRD "\tService")); pt_stack.pop_back(); - if(status_code!=100) - skipping = -1; + xrd_service = 0; + } + }else if(is_qelement(n,NSURI_XRD "\tStatus")) { + if(!xrd) { + skipping=-1; + }else{ + if(is_qelement(pt_stack.back().c_str(),n)) { + assert(cdata==&status_string); + pt_stack.pop_back(); + if(status_code!=100) + skipping = -1; + } } }else if(is_qelement(n,NSURI_XRD "\tExpires")) { - assert(xrd); - xrd->expires = util::w3c_to_time(cdata_buf); + if(!xrd) { + skipping=-1; + }else{ + xrd->expires = util::w3c_to_time(cdata_buf); + } + }else if(is_qelement(n,NSURI_XRD "\tXRD")) { + assert(!pt_stack.empty()); + assert(pt_stack.back()==(NSURI_XRD "\tXRD")); + pt_stack.pop_back(); }else if((xmode&xmode_html) && is_element(n,"head")) { skipping = -1; } cdata = 0; } void character_data(const XML_Char *s,int l) { if(skipping) return; if(cdata) cdata->append(s,l); } void html_start_element(const XML_Char *n,const XML_Char **a) { if(is_element(n,"meta")) { bool heq = false; string l; for(;*a;a+=2) { if(!( strcasecmp(a[0],"http-equiv") || strcasecmp(a[1],XRDS_HEADER) )) heq = true; else if(!strcasecmp(a[0],"content")) l.assign(a[1]); } if(heq) xrds_location = l; }else if(is_element(n,"link")) { string rels; string href; for(;*a;a+=2) { if( !strcasecmp(a[0],"rel") ) { rels.assign(a[1]); }else if( !strcasecmp(a[0],"href") ) { const char *ns = a[1]; for(;*ns && isspace(*ns);++ns) ; @@ -540,48 +556,55 @@ namespace opkele { openid_endpoint_t ep; ep.claimed_id = id.canonicalized_id; for(xrd::services_t::const_iterator isvc=id.xrd.services.begin(); isvc!=id.xrd.services.end(); ++isvc) { const xrd::service_t svc = isvc->second; if(svc.types.find(st->uri)==svc.types.end()) continue; for(xrd::uris_t::const_iterator iu=svc.uris.begin();iu!=svc.uris.end();++iu) { ep.uri = iu->second.uri; if(id.xri_identity) { if(iu->second.append=="qxri") { ep.uri += id.normalized_id; } /* TODO: else handle other append attribute values */ } if(st->forceid) { ep.local_id = ep.claimed_id = st->forceid; *(oi++) = ep; }else{ if(svc.local_ids.empty()) { ep.local_id = ep.claimed_id; *(oi++) = ep; }else{ for(xrd::local_ids_t::const_iterator ilid=svc.local_ids.begin(); ilid!=svc.local_ids.end(); ++ilid) { ep.local_id = ilid->second; *(oi++) = ep; } } } } } } + int unknown_encoding(const XML_Char* /* n */,XML_Encoding *i) { + for(unsigned int ii=0;ii < sizeof(i->map)/sizeof(i->map[0]);++ii) + i->map[ii] = ii; + i->convert = 0; i->release = 0; + return XML_STATUS_OK; + } + }; string idiscover(endpoint_discovery_iterator oi,const string& identity) { idigger_t idigger; return idigger.discover(oi,identity); } void yadiscover(endpoint_discovery_iterator oi,const string& yurl,const char **types,bool redirs) try { idigger_t idigger; idigger.yadiscover(oi,yurl,types,redirs); }catch(exception_curl& ec) { if(redirs || ec._error!=CURLE_TOO_MANY_REDIRECTS) throw; } } |