summaryrefslogtreecommitdiffabout
path: root/lib/discovery.cc
authorMichael Krelin <hacker@klever.net>2009-01-21 19:48:17 (UTC)
committer Michael Krelin <hacker@klever.net>2009-01-21 19:48:17 (UTC)
commit485a0816b78fcf53a717e8e7cbeabee0b83091e7 (patch) (side-by-side diff)
tree1100501fe3590a63ac615ac23747d6d30ed8a2ae /lib/discovery.cc
parenta2a524f744849e81ec91a7afbaf641d1b57e14b1 (diff)
downloadlibopkele-485a0816b78fcf53a717e8e7cbeabee0b83091e7.zip
libopkele-485a0816b78fcf53a717e8e7cbeabee0b83091e7.tar.gz
libopkele-485a0816b78fcf53a717e8e7cbeabee0b83091e7.tar.bz2
Do not bomb out on unusual xml
In particular, properly handle directy Type child of XRD element. As usually, thanks to Joseph Smarr of Plaxo for spotting it ;-) Signed-off-by: Michael Krelin <hacker@klever.net>
Diffstat (limited to 'lib/discovery.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/discovery.cc41
1 files changed, 26 insertions, 15 deletions
diff --git a/lib/discovery.cc b/lib/discovery.cc
index cbdceb3..f8a3988 100644
--- a/lib/discovery.cc
+++ b/lib/discovery.cc
@@ -393,147 +393,158 @@ namespace opkele {
}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;
}
}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((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) ;
href.assign(ns);
string::size_type lns=href.find_last_not_of(data::_whitespace_chars);
href.erase(lns+1);
}
}
for(string::size_type ns=rels.find_first_not_of(data::_whitespace_chars);
ns!=string::npos; ns=rels.find_first_not_of(data::_whitespace_chars,ns)) {
string::size_type s = rels.find_first_of(data::_whitespace_chars,ns);
string rel;
if(s==string::npos) {
rel.assign(rels,ns,string::npos);
ns = string::npos;
}else{
rel.assign(rels,ns,s-ns);
ns = s;
}
if(rel=="openid.server")
html_openid1.uris.add(-1,xrd::uri_t(href));
else if(rel=="openid.delegate")
html_openid1.local_ids.add(-1,href);
else if(rel=="openid2.provider")
html_openid2.uris.add(-1,xrd::uri_t(href));
else if(rel=="openid2.local_id")
html_openid2.local_ids.add(-1,href);
}
}else if(is_element(n,"body")) {
skipping = -1;
}
}
void queue_endpoints(endpoint_discovery_iterator& oi,
const idiscovery_t &id,