summaryrefslogtreecommitdiffabout
path: root/lib/discovery.cc
Side-by-side diff
Diffstat (limited to 'lib/discovery.cc') (more/less context) (show whitespace changes)
-rw-r--r--lib/discovery.cc2
1 files changed, 1 insertions, 1 deletions
diff --git a/lib/discovery.cc b/lib/discovery.cc
index 6f58339..6f9926c 100644
--- a/lib/discovery.cc
+++ b/lib/discovery.cc
@@ -237,193 +237,193 @@ namespace opkele {
r = easy_perform();
if(r && r!=CURLE_WRITE_ERROR)
throw exception_curl(OPKELE_CP_ "failed to perform curly request",r);
if(!parser_choked) {
parse(0,0,true);
}else{
/* TODO: do not bother if we've seen xml */
try {
util::tidy_doc_t td = util::tidy_doc_t::create();
if(!td)
throw exception_tidy(OPKELE_CP_ "failed to create htmltidy document");
#ifndef NDEBUG
td.opt_set(TidyQuiet,false);
td.opt_set(TidyShowWarnings,false);
#endif /* NDEBUG */
td.opt_set(TidyForceOutput,true);
td.opt_set(TidyXhtmlOut,true);
td.opt_set(TidyDoctypeMode,TidyDoctypeOmit);
td.opt_set(TidyMark,false);
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();
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;
if(mbts>0) {
bts = (bytes>mbts)?mbts:bytes;
save_html.append(inbuf,bts);
}
if(skipping<0) return bts;
}
if(skipping<0) return 0;
bool rp = parse(inbuf,bytes,false);
if(!rp) {
parser_choked = true;
skipping = -1;
if(!(xmode&xmode_html))
bytes = 0;
}
return bytes;
}
size_t header(void *p,size_t s,size_t nm) {
size_t bytes = s*nm;
const char *h = (const char*)p;
const char *colon = (const char*)memchr(p,':',bytes);
const char *space = (const char*)memchr(p,' ',bytes);
if(space && ( (!colon) || space<colon ) ) {
xrds_location.clear(); http_content_type.clear();
}else if(colon) {
const char *hv = ++colon;
- int hnl = colon-h;
+ size_t hnl = colon-h;
int rb;
for(rb = bytes-hnl-1;rb>0 && isspace(*hv);++hv,--rb);
while(rb>0 && isspace(hv[rb-1])) --rb;
if(rb) {
if( (hnl>=sizeof(XRDS_HEADER))
&& !strncasecmp(h,XRDS_HEADER":",
sizeof(XRDS_HEADER)) ) {
xrds_location.assign(hv,rb);
}else if( (hnl>=sizeof(CT_HEADER))
&& !strncasecmp(h,CT_HEADER":",
sizeof(CT_HEADER)) ) {
const char *sc = (const char*)memchr(
hv,';',rb);
http_content_type.assign(hv,sc?(sc-hv):rb);
}
}
}
return curl_t::header(p,s,nm);
}
void start_element(const XML_Char *n,const XML_Char **a) {
if(skipping<0) return;
if(skipping) {
if(xmode&xmode_html)
html_start_element(n,a);
++skipping; return;
}
if(pt_stack.empty()) {
if(is_qelement(n,NSURI_XRDS "\tXRDS"))
return;
if(is_qelement(n,NSURI_XRD "\tXRD")) {
assert(xrd);
xrd->clear();
pt_stack.push_back(n);
}else if(xmode&xmode_html) {
html_start_element(n,a);
}else{
skipping = -1;
}
}else{
int pt_s = pt_stack.size();
if(pt_s==1) {
if(is_qelement(n,NSURI_XRD "\tCanonicalID")) {
assert(xrd);
cdata = &(xrd->canonical_ids.add(element_priority(a),string()));
}else if(is_qelement(n,NSURI_XRD "\tLocalID")) {
assert(xrd);
cdata = &(xrd->local_ids.add(element_priority(a),string()));
}else if(is_qelement(n,NSURI_XRD "\tProviderID")) {
assert(xrd);
cdata = &(xrd->provider_id);
}else if(is_qelement(n,NSURI_XRD "\tService")) {
assert(xrd);
xrd_service = &(xrd->services.add(element_priority(a),
service_t()));
pt_stack.push_back(n);
}else if(is_qelement(n,NSURI_XRD "\tStatus")) {
for(;*a;) {
if(!strcasecmp(*(a++),"code")) {
if(sscanf(*(a++),"%ld",&status_code)==1 && status_code!=100) {
cdata = &status_string;
pt_stack.push_back(n);
break;
}
}else
++a;
}
}else if(is_qelement(n,NSURI_XRD "\tExpires")) {
assert(xrd);
cdata_buf.clear();
cdata = &cdata_buf;
}else if(xmode&xmode_html) {
html_start_element(n,a);
}else{
skipping = 1;
}
}else if(pt_s==2) {
if(is_qelement(pt_stack.back().c_str(), NSURI_XRD "\tService")) {
if(is_qelement(n,NSURI_XRD "\tType")) {
assert(xrd); assert(xrd_service);
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;