|
|
| version 1.28, 2013/07/05 21:09:57 | version 1.35, 2015/10/26 01:21:53 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: @b curl parser class. | Parser: @b curl parser class. |
| Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) | Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) |
| */ | */ |
| #include "pa_config_includes.h" | #include "pa_config_includes.h" |
| Line 11 | Line 11 |
| #include "pa_vfile.h" | #include "pa_vfile.h" |
| #include "pa_charsets.h" | #include "pa_charsets.h" |
| #include "pa_vstring.h" | #include "pa_vstring.h" |
| #include "pa_vdate.h" | |
| #include "pa_vtable.h" | #include "pa_vtable.h" |
| #include "pa_common.h" | #include "pa_common.h" |
| #include "pa_http.h" | #include "pa_http.h" |
| Line 122 public: | Line 123 public: |
| }; | }; |
| bool curl_linked = false; | bool curl_linked = false; |
| #ifdef WIN32 | const char *curl_library="libcurl" LT_MODULE_EXT; |
| const char *curl_library="libcurl.dll"; | |
| #else | |
| const char *curl_library="libcurl.so"; | |
| #endif | |
| const char *curl_status = 0; | const char *curl_status = 0; |
| Line 302 public: | Line 299 public: |
| } *curl_options=0; | } *curl_options=0; |
| class CurlInfo { | |
| public: | |
| enum OptionType { | |
| CURL_STRING, | |
| CURL_INT, | |
| CURL_DOUBLE | |
| }; | |
| CURLINFO id; | |
| OptionType type; | |
| CurlInfo(CURLINFO aid, OptionType atype): id(aid), type(atype) {} | |
| }; | |
| class CurlInfoHash: public HashString<CurlInfo*> { | |
| public: | |
| CurlInfoHash() { | |
| #define CURL_INF(type, name) put(str_lower(#name),new CurlInfo(CURLINFO_##name, CurlInfo::type)); | |
| CURL_INF(CURL_DOUBLE, APPCONNECT_TIME); | |
| CURL_INF(CURL_DOUBLE, CONNECT_TIME); | |
| CURL_INF(CURL_DOUBLE, CONTENT_LENGTH_DOWNLOAD); | |
| CURL_INF(CURL_DOUBLE, CONTENT_LENGTH_UPLOAD); | |
| CURL_INF(CURL_STRING, CONTENT_TYPE); | |
| CURL_INF(CURL_STRING, EFFECTIVE_URL); | |
| CURL_INF(CURL_INT, HEADER_SIZE); | |
| CURL_INF(CURL_INT, HTTPAUTH_AVAIL); | |
| CURL_INF(CURL_DOUBLE, NAMELOOKUP_TIME); | |
| CURL_INF(CURL_INT, NUM_CONNECTS); | |
| CURL_INF(CURL_INT, OS_ERRNO); | |
| CURL_INF(CURL_DOUBLE, PRETRANSFER_TIME); | |
| CURL_INF(CURL_STRING, PRIMARY_IP); | |
| CURL_INF(CURL_INT, PROXYAUTH_AVAIL); | |
| CURL_INF(CURL_INT, REDIRECT_COUNT); | |
| CURL_INF(CURL_DOUBLE, REDIRECT_TIME); | |
| CURL_INF(CURL_STRING, REDIRECT_URL); | |
| CURL_INF(CURL_INT, REQUEST_SIZE); | |
| CURL_INF(CURL_INT, RESPONSE_CODE); | |
| CURL_INF(CURL_DOUBLE, SIZE_DOWNLOAD); | |
| CURL_INF(CURL_DOUBLE, SIZE_UPLOAD); | |
| CURL_INF(CURL_DOUBLE, SPEED_DOWNLOAD); | |
| CURL_INF(CURL_DOUBLE, SPEED_UPLOAD); | |
| CURL_INF(CURL_INT, SSL_VERIFYRESULT); | |
| CURL_INF(CURL_DOUBLE, STARTTRANSFER_TIME); | |
| CURL_INF(CURL_DOUBLE, TOTAL_TIME); | |
| } | |
| } *curl_infos=0; | |
| static const char *curl_urlencode(const String &s, Request& r){ | static const char *curl_urlencode(const String &s, Request& r){ |
| if(options().charset){ | if(options().charset){ |
| Temp_client_charset temp(r.charsets, *options().charset); | Temp_client_charset temp(r.charsets, *options().charset); |
| Line 478 static void curl_setopt(HashStringValue: | Line 523 static void curl_setopt(HashStringValue: |
| break; | break; |
| } | } |
| case CurlOption::PARSER_CHARSET:{ | case CurlOption::PARSER_CHARSET:{ |
| // 'charset' parser option | // 'charset' parser option should be processed before other options |
| options().charset=&::charsets.get(v.as_string().change_case(r.charsets.source(), String::CC_UPPER)); | |
| break; | break; |
| } | } |
| case CurlOption::PARSER_RESPONSE_CHARSET:{ | case CurlOption::PARSER_RESPONSE_CHARSET:{ |
| Line 497 static void _curl_options(Request& r, Me | Line 541 static void _curl_options(Request& r, Me |
| if(curl_options==0) | if(curl_options==0) |
| curl_options=new CurlOptionHash(); | curl_options=new CurlOptionHash(); |
| if(HashStringValue* options=params.as_hash(0)) | if(HashStringValue* options_hash=params.as_hash(0)){ |
| options->for_each<Request&>(curl_setopt, r); | if(Value* value=options_hash->get("charset")){ |
| // charset should be handled first as params may require transcode | |
| Value &v=r.process_to_value(*value); | |
| options().charset=&::charsets.get(v.as_string().change_case(r.charsets.source(), String::CC_UPPER)); | |
| } | |
| options_hash->for_each<Request&>(curl_setopt, r); | |
| } | |
| } | |
| #define CURL_GETINFO(arg) \ | |
| if((res=f_curl_easy_getinfo(curl(), info->id, &arg)) != CURLE_OK){ \ | |
| throw Exception("curl", 0, "failed to get %s info: %s", key.cstr(), f_curl_easy_strerror(res)); \ | |
| } | |
| static Value *curl_getinfo(const String::Body &key, CurlInfo *info=0) { | |
| if(info==0 && !(info=curl_infos->get(key))) | |
| throw Exception("curl", 0, "called with invalid parameter '%s'", key.cstr()); | |
| CURLcode res; | |
| switch (info->type){ | |
| case CurlInfo::CURL_STRING:{ | |
| char *str=0; | |
| CURL_GETINFO(str); | |
| return new VString(str ? *new String(pa_strdup(str), String::L_TAINTED) : String::Empty); | |
| } | |
| case CurlInfo::CURL_INT:{ | |
| long l=0; | |
| CURL_GETINFO(l); | |
| return new VInt(l); | |
| } | |
| case CurlInfo::CURL_DOUBLE:{ | |
| double d=0; | |
| CURL_GETINFO(d); | |
| return new VDouble(d); | |
| } | |
| } | |
| return VVoid::get(); | |
| } | |
| static void _curl_info(Request& r, MethodParams& params){ | |
| if(curl_infos==0) | |
| curl_infos=new CurlInfoHash(); | |
| if(params.count()==1){ | |
| const String &name=params.as_string(0, "name must be string"); | |
| r.write_assign_lang(*curl_getinfo(name)); | |
| } else { | |
| VHash& result=*new VHash; | |
| for(CurlInfoHash::Iterator i(*curl_infos); i; i.next() ){ | |
| result.get_hash()->put(i.key(), curl_getinfo(i.key(), i.value())); | |
| } | |
| r.write_no_lang(result); | |
| } | |
| } | } |
| Line 589 static void _curl_load_action(Request& r | Line 684 static void _curl_load_action(Request& r |
| case CURLE_SSL_CACERT: | case CURLE_SSL_CACERT: |
| case CURLE_SSL_ENGINE_INITFAILED: | case CURLE_SSL_ENGINE_INITFAILED: |
| ex_type = "curl.ssl"; break; | ex_type = "curl.ssl"; break; |
| default: break; | |
| } | } |
| throw Exception( ex_type ? ex_type : "curl.fail", 0, "%s", f_curl_easy_strerror(res)); | throw Exception( ex_type ? ex_type : "curl.fail", 0, "%s", f_curl_easy_strerror(res)); |
| } | } |
| Line 660 MCurl::MCurl(): Methoded("curl") { | Line 756 MCurl::MCurl(): Methoded("curl") { |
| add_native_method("session", Method::CT_STATIC, _curl_session, 1, 1); | add_native_method("session", Method::CT_STATIC, _curl_session, 1, 1); |
| add_native_method("version", Method::CT_STATIC, _curl_version, 0, 0); | add_native_method("version", Method::CT_STATIC, _curl_version, 0, 0); |
| add_native_method("options", Method::CT_STATIC, _curl_options, 1, 1); | add_native_method("options", Method::CT_STATIC, _curl_options, 1, 1); |
| add_native_method("info", Method::CT_STATIC, _curl_info, 0, 1); | |
| add_native_method("load", Method::CT_STATIC, _curl_load, 0, 1); | add_native_method("load", Method::CT_STATIC, _curl_load, 0, 1); |
| } | } |