summaryrefslogtreecommitdiffabout
path: root/lib
Side-by-side diff
Diffstat (limited to 'lib') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/consumer.cc53
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");
}