author | Michael Krelin <hacker@klever.net> | 2007-11-26 21:14:28 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2007-11-26 21:14:28 (UTC) |
commit | 34dcd4dd9af494eab2f6e47498c270d27954bf19 (patch) (side-by-side diff) | |
tree | 19eeac758bf09905e9e55a24fa2494930ee5c890 | |
parent | d788db9c490575e63506ce502a2f089eaaa624ee (diff) | |
download | libopkele-34dcd4dd9af494eab2f6e47498c270d27954bf19.zip libopkele-34dcd4dd9af494eab2f6e47498c270d27954bf19.tar.gz libopkele-34dcd4dd9af494eab2f6e47498c270d27954bf19.tar.bz2 |
encapsulated write functionality into curl_t
Signed-off-by: Michael Krelin <hacker@klever.net>
-rw-r--r-- | include/opkele/curl.h | 3 | ||||
-rw-r--r-- | lib/consumer.cc | 50 | ||||
-rw-r--r-- | lib/curl.cc | 12 |
3 files changed, 43 insertions, 22 deletions
diff --git a/include/opkele/curl.h b/include/opkele/curl.h index 6a7d084..1029b34 100644 --- a/include/opkele/curl.h +++ b/include/opkele/curl.h @@ -25,15 +25,18 @@ namespace opkele { template<typename PT> inline CURLcode easy_setopt(CURLoption o,PT p) { assert(_c); return curl_easy_setopt(_c,o,p); } CURLcode easy_perform() { assert(_c); return curl_easy_perform(_c); } template<typename IT> inline CURLcode easy_getinfo(CURLINFO i,IT p) { assert(_c); return curl_easy_getinfo(_c,i,p); } static inline CURL *easy_init() { return curl_easy_init(); } + + virtual size_t write(void *p,size_t s,size_t nm) { return 0; } + CURLcode set_write(); }; } } #endif /* __OPKELE_CURL_H */ diff --git a/lib/consumer.cc b/lib/consumer.cc index c155157..62bec71 100644 --- a/lib/consumer.cc +++ b/lib/consumer.cc @@ -13,16 +13,35 @@ #include "config.h" #include <pcre.h> namespace opkele { using namespace std; using util::curl_t; + template<int lim> + class curl_fetch_string_t : public curl_t { + public: + curl_fetch_string_t(CURL *c) + : curl_t(c) { } + ~curl_fetch_string_t() throw() { } + + string response; + + size_t write(void *p,size_t size,size_t nmemb) { + size_t bytes = size*nmemb; + size_t get = min(lim-response.length(),bytes); + response.append((const char *)p,get); + return get; + } + }; + + typedef curl_fetch_string_t<16384> curl_pick_t; + class pcre_matches_t { public: int *_ov; int _s; pcre_matches_t() : _ov(0), _s(0) { } pcre_matches_t(int s) : _ov(0), _s(s) { if(_s&1) ++_s; @@ -57,56 +76,46 @@ namespace opkele { int exec(const string& s,pcre_matches_t& m) { if(!_p) throw internal_error(OPKELE_CP_ "Trying to execute absent regexp"); return pcre_exec(_p,NULL,s.c_str(),s.length(),0,0,m._ov,m._s); } }; - static size_t _curl_tostring(void *ptr,size_t size,size_t nmemb,void *stream) { - string *str = (string*)stream; - size_t bytes = size*nmemb; - size_t get = min(16384-str->length(),bytes); - str->append((const char*)ptr,get); - return get; - } - assoc_t consumer_t::associate(const string& server) { util::dh_t dh = DH_new(); if(!dh) throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); dh->p = util::dec_to_bignum(data::_default_p); dh->g = util::dec_to_bignum(data::_default_g); if(!DH_generate_key(dh)) throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); string request = "openid.mode=associate" "&openid.assoc_type=HMAC-SHA1" "&openid.session_type=DH-SHA1" "&openid.dh_consumer_public="; request += util::url_encode(util::bignum_to_base64(dh->pub_key)); - curl_t curl = curl_t::easy_init(); + curl_pick_t curl = curl_pick_t::easy_init(); if(!curl) throw exception_curl(OPKELE_CP_ "failed to initialize curl"); - string response; CURLcode r; (r=curl.misc_sets()) || (r=curl.easy_setopt(CURLOPT_URL,server.c_str())) || (r=curl.easy_setopt(CURLOPT_POST,1)) || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) - || (r=curl.easy_setopt(CURLOPT_WRITEFUNCTION,_curl_tostring)) - || (r=curl.easy_setopt(CURLOPT_WRITEDATA,&response)) + || (r=curl.set_write()) ; if(r) throw exception_curl(OPKELE_CP_ "failed to set curly options",r); if( (r=curl.easy_perform()) ) throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); - params_t p; p.parse_keyvalues(response); + params_t p; p.parse_keyvalues(curl.response); if(p.has_param("assoc_type") && p.get_param("assoc_type")!="HMAC-SHA1") throw bad_input(OPKELE_CP_ "unsupported assoc_type"); string st; if(p.has_param("session_type")) st = p.get_param("session_type"); if((!st.empty()) && st!="DH-SHA1") throw bad_input(OPKELE_CP_ "unsupported session_type"); secret_t secret; if(st.empty()) { @@ -239,58 +248,55 @@ namespace opkele { for(params_t::const_iterator i=p.begin();i!=p.end();++i) { if(i->first!="openid.mode") { request += '&'; request += i->first; request += '='; request += util::url_encode(i->second); } } - curl_t curl = curl_t::easy_init(); + curl_pick_t curl = curl_pick_t::easy_init(); if(!curl) throw exception_curl(OPKELE_CP_ "failed to initialize curl"); - string response; CURLcode r; (r=curl.misc_sets()) || (r=curl.easy_setopt(CURLOPT_URL,server.c_str())) || (r=curl.easy_setopt(CURLOPT_POST,1)) || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) - || (r=curl.easy_setopt(CURLOPT_WRITEFUNCTION,_curl_tostring)) - || (r=curl.easy_setopt(CURLOPT_WRITEDATA,&response)) + || (r=curl.set_write()) ; if(r) throw exception_curl(OPKELE_CP_ "failed to set curly options",r); if( (r=curl.easy_perform()) ) throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); - params_t pp; pp.parse_keyvalues(response); + params_t pp; pp.parse_keyvalues(curl.response); if(pp.has_param("invalidate_handle")) invalidate_assoc(server,pp.get_param("invalidate_handle")); if(pp.has_param("is_valid")) { if(pp.get_param("is_valid")=="true") return; }else if(pp.has_param("lifetime")) { if(util::string_to_long(pp.get_param("lifetime"))) return; } throw failed_check_authentication(OPKELE_CP_ "failed to verify response"); } void consumer_t::retrieve_links(const string& url,string& server,string& delegate) { server.erase(); delegate.erase(); - curl_t curl = curl_t::easy_init(); + curl_pick_t curl = curl_pick_t::easy_init(); if(!curl) throw exception_curl(OPKELE_CP_ "failed to initialize curl"); - string html; + string& html = curl.response; CURLcode r; (r=curl.misc_sets()) || (r=curl.easy_setopt(CURLOPT_URL,url.c_str())) - || (r=curl.easy_setopt(CURLOPT_WRITEFUNCTION,_curl_tostring)) - || (r=curl.easy_setopt(CURLOPT_WRITEDATA,&html)) + || (r=curl.set_write()); ; if(r) throw exception_curl(OPKELE_CP_ "failed to set curly options",r); r = curl.easy_perform(); if(r && r!=CURLE_WRITE_ERROR) throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); static const char *re_bre = "<\\s*body\\b", *re_hdre = "<\\s*head[^>]*>", *re_lre = "<\\s*link\\b([^>]+)>", diff --git a/lib/curl.cc b/lib/curl.cc index 418aa79..3e69b47 100644 --- a/lib/curl.cc +++ b/lib/curl.cc @@ -32,11 +32,23 @@ namespace opkele { #endif #ifdef DISABLE_CURL_SSL_VERIFYPEER || (r=easy_setopt(CURLOPT_SSL_VERIFYPEER,0)) #endif ; return r; } + static size_t _write(void *p,size_t s,size_t nm,void *stream) { + return ((curl_t*)stream)->write(p,s,nm); + } + + CURLcode curl_t::set_write() { + assert(_c); + CURLcode r; + (r = easy_setopt(CURLOPT_WRITEDATA,this)) + || (r = easy_setopt(CURLOPT_WRITEFUNCTION,_write)); + return r; + } + } } |