-rw-r--r-- | lib/consumer.cc | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/lib/consumer.cc b/lib/consumer.cc index 8f66688..299b3bc 100644 --- a/lib/consumer.cc +++ b/lib/consumer.cc @@ -4,18 +4,25 @@ #include <opkele/exception.h> #include <opkele/data.h> #include <opkele/consumer.h> #include <openssl/sha.h> #include <openssl/hmac.h> #include <curl/curl.h> -#include <pcre++.h> #include <iostream> #include "config.h" +#if defined(USE_LIBPCRECPP) +# include <pcrecpp.h> +#elif defined(USE_PCREPP) +# include <pcre++.h> +#else + /* internal implementation won't be built */ +#endif + namespace opkele { using namespace std; class curl_t { public: CURL *_c; @@ -258,12 +265,13 @@ namespace opkele { return; } throw failed_check_authentication(OPKELE_CP_ "failed to verify response"); } void consumer_t::retrieve_links(const string& url,string& server,string& delegate) { +#if defined(USE_LIBPCRECPP) || defined(USE_PCREPP) server.erase(); delegate.erase(); curl_t curl = curl_easy_init(); if(!curl) throw exception_curl(OPKELE_CP_ "failed to curl_easy_init()"); string html; @@ -275,23 +283,50 @@ namespace opkele { ; if(r) throw exception_curl(OPKELE_CP_ "failed to curl_easy_setopt()",r); r = curl_easy_perform(curl); if(r && r!=CURLE_WRITE_ERROR) throw exception_curl(OPKELE_CP_ "failed to curl_easy_perform()",r); - pcrepp::Pcre bre("<body\\b",PCRE_CASELESS); // strip out everything past body + static const char *re_hdre = "<head[^>]*>", + *re_lre = "<link\\b([^>]+)>", + *re_rre = "\\brel=['\"]([^'\"]+)['\"]", + *re_hre = "\\bhref=['\"]([^'\"]+)['\"]"; +#if defined(USE_LIBPCRECPP) + static pcrecpp::RE_Options ro(PCRE_CASELESS|PCRE_DOTALL); + static pcrecpp::RE + bre("<body\\b.*",ro), hdre(re_hdre,ro), + lre(re_lre,ro), rre(re_rre), hre(re_hre,ro); + bre.Replace("",&html); + pcrecpp::StringPiece hpiece(html); + if(!hdre.FindAndConsume(&hpiece)) + throw bad_input(OPKELE_CP_ "failed to find head"); + string attrs; + while(lre.FindAndConsume(&hpiece,&attrs)) { + pcrecpp::StringPiece rel, href; + if(!(rre.PartialMatch(attrs,&rel) && hre.PartialMatch(attrs,&href))) + continue; + if(rel=="openid.server") { + href.CopyToString(&server); + if(!delegate.empty()) + break; + }else if(rel=="openid.delegate") { + href.CopyToString(&delegate); + if(!server.empty()) + break; + } + } +#elif defined(USE_PCREPP) + pcrepp::Pcre bre("<body\\b",PCRE_CASELESS); if(bre.search(html)) html.erase(bre.get_match_start()); - pcrepp::Pcre hdre("<head[^>]*>",PCRE_CASELESS); + pcrepp::Pcre hdre(re_hdre,PCRE_CASELESS); if(!hdre.search(html)) throw bad_input(OPKELE_CP_ "failed to find head"); html.erase(0,hdre.get_match_end()+1); - pcrepp::Pcre lre("<link\\b([^>]+)>",PCRE_CASELESS), - rre("\\brel=['\"]([^'\"]+)['\"]",PCRE_CASELESS), - hre("\\bhref=['\"]([^'\"]+)['\"]",PCRE_CASELESS); + pcrepp::Pcre lre(re_lre,PCRE_CASELESS), rre(re_rre,PCRE_CASELESS), hre(re_hre,PCRE_CASELESS); while(lre.search(html)) { string attrs = lre[0]; html.erase(0,lre.get_match_end()+1); if(!(rre.search(attrs)&&hre.search(attrs))) continue; if(rre[0]=="openid.server") { @@ -301,14 +336,20 @@ namespace opkele { }else if(rre[0]=="openid.delegate") { delegate = hre[0]; if(!server.empty()) break; } } +#else + #error "I must have gone crazy" +#endif if(server.empty()) throw failed_assertion(OPKELE_CP_ "The location has no openid.server declaration"); +#else /* none of the RE bindings enabled */ + throw not_implemented(OPKELE_CP_ "No internal implementation of retrieve_links were provided at compile-time"); +#endif } assoc_t consumer_t::find_assoc(const string& server) { throw failed_lookup(OPKELE_CP_ "no find_assoc() provided"); } |