X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=http_curl_api.c;h=7f0638f08f14815f35f5ec333be584262f51c83f;hp=7a53beb10c471cfefd67d869a767e6b9bacfda4e;hb=af674f03c32f0f56b7f8c67e61c7e86b3ea23be5;hpb=c00621939ec351c74846b367765ddac4d3955eb9 diff --git a/http_curl_api.c b/http_curl_api.c index 7a53beb..7f0638f 100644 --- a/http_curl_api.c +++ b/http_curl_api.c @@ -20,14 +20,10 @@ #endif #ifdef PHP_WIN32 -# define _WINSOCKAPI_ -# define ZEND_INCLUDE_FULL_WINDOWS_HEADERS # include -# include #endif #include -#include #include "php.h" #include "php_http.h" @@ -39,10 +35,20 @@ # include "ext/standard/php_http.h" #endif -#include "ext/standard/php_smart_str.h" +#include "phpstr/phpstr.h" ZEND_DECLARE_MODULE_GLOBALS(http) +#if LIBCURL_VERSION_NUM >= 0x070c01 +# define http_curl_reset(ch) curl_easy_reset(ch) +#else +# define http_curl_reset(ch) +#endif + +#if LIBCURL_VERSION_NUM < 0x070c00 +# define curl_easy_strerror(code) "unkown error" +#endif + #define http_curl_startup(ch, clean_curl, URL, options) \ if (!ch) { \ if (!(ch = curl_easy_init())) { \ @@ -50,66 +56,37 @@ ZEND_DECLARE_MODULE_GLOBALS(http) return FAILURE; \ } \ clean_curl = 1; \ + } else { \ + http_curl_reset(ch); \ } \ - http_curl_initbuf(); \ http_curl_setopts(ch, URL, options); +#define http_curl_perform(ch, clean_curl) \ + { \ + CURLcode result; \ + if (CURLE_OK != (result = curl_easy_perform(ch))) { \ + http_curl_cleanup(ch, clean_curl); \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request: %s", curl_easy_strerror(result)); \ + return FAILURE; \ + } \ + } #define http_curl_cleanup(ch, clean_curl) \ - http_curl_freestr(); \ - http_curl_freebuf(); \ + phpstr_dtor(&HTTP_G(curlbuf)); \ + zend_llist_clean(&HTTP_G(to_free)); \ if (clean_curl) { \ curl_easy_cleanup(ch); \ ch = NULL; \ } -#define http_curl_freestr() \ - zend_llist_clean(&HTTP_G(to_free)) - -#define http_curl_initbuf() http_curl_initbuf_ex(0) - -#define http_curl_initbuf_ex(chunk_size) \ - { \ - size_t size = (chunk_size > 0) ? chunk_size : HTTP_CURLBUF_SIZE; \ - http_curl_freebuf(); \ - HTTP_G(curlbuf).data = emalloc(size); \ - HTTP_G(curlbuf).free = size; \ - HTTP_G(curlbuf).size = size; \ - } - -#define http_curl_freebuf() \ - if (HTTP_G(curlbuf).data) { \ - efree(HTTP_G(curlbuf).data); \ - HTTP_G(curlbuf).data = NULL; \ - } \ - HTTP_G(curlbuf).used = 0; \ - HTTP_G(curlbuf).free = 0; \ - HTTP_G(curlbuf).size = 0; - -#define http_curl_copybuf(data, size) \ - * size = HTTP_G(curlbuf).used; \ - * data = ecalloc(1, HTTP_G(curlbuf).used + 1); \ - memcpy(* data, HTTP_G(curlbuf).data, * size); - -#define http_curl_sizebuf(for_size) \ - { \ - size_t size = (for_size); \ - if (size > HTTP_G(curlbuf).free) { \ - size_t bsize = HTTP_G(curlbuf).size; \ - while (size > bsize) { \ - bsize *= 2; \ - } \ - HTTP_G(curlbuf).data = erealloc(HTTP_G(curlbuf).data, HTTP_G(curlbuf).used + bsize); \ - HTTP_G(curlbuf).free += bsize; \ - } \ - } - +#define http_curl_copybuf(d, l) \ + phpstr_data(&HTTP_G(curlbuf), d, l) #define http_curl_copystr(s) _http_curl_copystr((s) TSRMLS_CC) static inline char *_http_curl_copystr(const char *str TSRMLS_DC); #define http_curl_setopts(c, u, o) _http_curl_setopts((c), (u), (o) TSRMLS_CC) -static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC); +static void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC); #define http_curl_getopt(o, k) _http_curl_getopt((o), (k) TSRMLS_CC, 0) #define http_curl_getopt1(o, k, t1) _http_curl_getopt((o), (k) TSRMLS_CC, 1, (t1)) @@ -136,11 +113,7 @@ static size_t http_curl_body_callback(char *buf, size_t len, size_t n, void *s) { TSRMLS_FETCH(); - http_curl_sizebuf(len *= n); - - memcpy(HTTP_G(curlbuf).data + HTTP_G(curlbuf).used, buf, len); - HTTP_G(curlbuf).free -= len; - HTTP_G(curlbuf).used += len; + phpstr_append(&HTTP_G(curlbuf), buf, len *= n); return len; } /* }}} */ @@ -151,14 +124,11 @@ static size_t http_curl_hdrs_callback(char *buf, size_t len, size_t n, void *s) TSRMLS_FETCH(); /* discard previous headers */ - if ((HTTP_G(curlbuf).used) && (!strncmp(buf, "HTTP/1.", sizeof("HTTP/1.") - 1))) { - http_curl_initbuf(); + if (HTTP_G(curlbuf).used && (!strncmp(buf, "HTTP/1.", sizeof("HTTP/1.") - 1))) { + phpstr_free(&HTTP_G(curlbuf)); } - http_curl_sizebuf(len *= n); - memcpy(HTTP_G(curlbuf).data + HTTP_G(curlbuf).used, buf, len); - HTTP_G(curlbuf).free -= len; - HTTP_G(curlbuf).used += len; + phpstr_append(&HTTP_G(curlbuf), buf, len *= n); return len; } /* }}} */ @@ -189,8 +159,8 @@ static inline zval *_http_curl_getopt(HashTable *options, char *key TSRMLS_DC, i } /* }}} */ -/* {{{ static inline void http_curl_setopts(CURL *, char *, HashTable *) */ -static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC) +/* {{{ static void http_curl_setopts(CURL *, char *, HashTable *) */ +static void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC) { zval *zoption; zend_bool range_req = 0; @@ -203,7 +173,7 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1); curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, http_curl_body_callback); curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, http_curl_hdrs_callback); -#if defined(ZTS) && (LIBCURL_VERSION_NUM >= 71000) +#if defined(ZTS) && (LIBCURL_VERSION_NUM >= 0x070a00) curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1); #endif @@ -222,7 +192,7 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti if (zoption = http_curl_getopt1(options, "proxyauth", IS_STRING)) { curl_easy_setopt(ch, CURLOPT_PROXYUSERPWD, http_curl_copystr(Z_STRVAL_P(zoption))); } -#if LIBCURL_VERSION_NUM >= 71007 +#if LIBCURL_VERSION_NUM >= 0x070a07 /* auth method */ if (zoption = http_curl_getopt1(options, "proxyauthtype", IS_LONG)) { curl_easy_setopt(ch, CURLOPT_PROXYAUTH, Z_LVAL_P(zoption)); @@ -234,7 +204,7 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti if (zoption = http_curl_getopt1(options, "interface", IS_STRING)) { curl_easy_setopt(ch, CURLOPT_INTERFACE, http_curl_copystr(Z_STRVAL_P(zoption))); } - + /* another port */ if (zoption = http_curl_getopt1(options, "port", IS_LONG)) { curl_easy_setopt(ch, CURLOPT_PORT, Z_LVAL_P(zoption)); @@ -244,7 +214,7 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti if (zoption = http_curl_getopt1(options, "httpauth", IS_STRING)) { curl_easy_setopt(ch, CURLOPT_USERPWD, http_curl_copystr(Z_STRVAL_P(zoption))); } -#if LIBCURL_VERSION_NUM >= 71006 +#if LIBCURL_VERSION_NUM >= 0x070a06 if (zoption = http_curl_getopt1(options, "httpauthtype", IS_LONG)) { curl_easy_setopt(ch, CURLOPT_HTTPAUTH, Z_LVAL_P(zoption)); } @@ -278,7 +248,7 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti curl_easy_setopt(ch, CURLOPT_USERAGENT, http_curl_copystr(Z_STRVAL_P(zoption))); } else { curl_easy_setopt(ch, CURLOPT_USERAGENT, - "PECL::HTTP/" PHP_EXT_HTTP_VERSION " (PHP/" PHP_VERSION ")"); + "PECL::HTTP/" HTTP_PEXT_VERSION " (PHP/" PHP_VERSION ")"); } /* additional headers, array('name' => 'value') */ @@ -310,28 +280,25 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti if (zoption = http_curl_getopt1(options, "cookies", IS_ARRAY)) { char *cookie_key = NULL; long cookie_idx = 0; - smart_str qstr = {0}; + phpstr *qstr = phpstr_new(); FOREACH_KEY(zoption, cookie_key, cookie_idx) { if (cookie_key) { zval **cookie_val; if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void **) &cookie_val)) { - smart_str_appends(&qstr, cookie_key); - smart_str_appendl(&qstr, "=", 1); - smart_str_appendl(&qstr, Z_STRVAL_PP(cookie_val), Z_STRLEN_PP(cookie_val)); - smart_str_appendl(&qstr, "; ", 2); + phpstr_appendf(qstr, "%s=%s; ", cookie_key, Z_STRVAL_PP(cookie_val)); } /* reset */ cookie_key = NULL; } } - smart_str_0(&qstr); - if (qstr.c) { - curl_easy_setopt(ch, CURLOPT_COOKIE, http_curl_copystr(qstr.c)); - efree(qstr.c); + if (qstr->used) { + phpstr_fix(qstr); + curl_easy_setopt(ch, CURLOPT_COOKIE, http_curl_copystr(qstr->data)); } + phpstr_free(qstr); } /* cookiestore */ @@ -350,7 +317,7 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti if (zoption = http_curl_getopt1(options, "maxfilesize", IS_LONG)) { curl_easy_setopt(ch, CURLOPT_MAXFILESIZE, Z_LVAL_P(zoption)); } - + /* lastmodified */ if (zoption = http_curl_getopt1(options, "lastmodified", IS_LONG)) { curl_easy_setopt(ch, CURLOPT_TIMECONDITION, range_req ? CURL_TIMECOND_IFUNMODSINCE : CURL_TIMECOND_IFMODSINCE); @@ -409,14 +376,14 @@ static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC) HTTP_CURL_INFO(EFFECTIVE_URL); -#if LIBCURL_VERSION_NUM >= 71007 +#if LIBCURL_VERSION_NUM >= 0x070a07 HTTP_CURL_INFO(RESPONSE_CODE); #else HTTP_CURL_INFO_EX(HTTP_CODE, RESPONSE_CODE); #endif HTTP_CURL_INFO(HTTP_CONNECTCODE); -#if LIBCURL_VERSION_NUM >= 70500 +#if LIBCURL_VERSION_NUM >= 0x070500 HTTP_CURL_INFO(FILETIME); #endif HTTP_CURL_INFO(TOTAL_TIME); @@ -424,7 +391,7 @@ static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC) HTTP_CURL_INFO(CONNECT_TIME); HTTP_CURL_INFO(PRETRANSFER_TIME); HTTP_CURL_INFO(STARTTRANSFER_TIME); -#if LIBCURL_VERSION_NUM >= 70907 +#if LIBCURL_VERSION_NUM >= 0x070907 HTTP_CURL_INFO(REDIRECT_TIME); HTTP_CURL_INFO(REDIRECT_COUNT); #endif @@ -438,8 +405,8 @@ static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC) HTTP_CURL_INFO(REQUEST_SIZE); HTTP_CURL_INFO(SSL_VERIFYRESULT); -#if LIBCURL_VERSION_NUM >= 71203 - /*HTTP_CURL_INFO(SSL_ENGINES); +#if LIBCURL_VERSION_NUM >= 0x070c03 + /*HTTP_CURL_INFO(SSL_ENGINES); todo: CURLINFO_SLIST */ #endif @@ -447,20 +414,20 @@ static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC) HTTP_CURL_INFO(CONTENT_LENGTH_UPLOAD); HTTP_CURL_INFO(CONTENT_TYPE); -#if LIBCURL_VERSION_NUM >= 71003 +#if LIBCURL_VERSION_NUM >= 0x070a03 /*HTTP_CURL_INFO(PRIVATE);*/ #endif -#if LIBCURL_VERSION_NUM >= 71008 +#if LIBCURL_VERSION_NUM >= 0x070a08 HTTP_CURL_INFO(HTTPAUTH_AVAIL); HTTP_CURL_INFO(PROXYAUTH_AVAIL); #endif -#if LIBCURL_VERSION_NUM >= 71202 +#if LIBCURL_VERSION_NUM >= 0x070c02 /*HTTP_CURL_INFO(OS_ERRNO);*/ #endif -#if LIBCURL_VERSION_NUM >= 71203 +#if LIBCURL_VERSION_NUM >= 0x070c03 HTTP_CURL_INFO(NUM_CONNECTS); #endif } @@ -474,12 +441,7 @@ PHP_HTTP_API STATUS _http_get_ex(CURL *ch, const char *URL, HashTable *options, http_curl_startup(ch, clean_curl, URL, options); curl_easy_setopt(ch, CURLOPT_HTTPGET, 1); - - if (CURLE_OK != curl_easy_perform(ch)) { - http_curl_cleanup(ch, clean_curl); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request"); - return FAILURE; - } + http_curl_perform(ch, clean_curl); if (info) { http_curl_getinfo(ch, info); @@ -499,12 +461,7 @@ PHP_HTTP_API STATUS _http_head_ex(CURL *ch, const char *URL, HashTable *options, http_curl_startup(ch, clean_curl, URL, options); curl_easy_setopt(ch, CURLOPT_NOBODY, 1); - - if (CURLE_OK != curl_easy_perform(ch)) { - http_curl_cleanup(ch, clean_curl); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request"); - return FAILURE; - } + http_curl_perform(ch, clean_curl); if (info) { http_curl_getinfo(ch, info); @@ -527,12 +484,7 @@ PHP_HTTP_API STATUS _http_post_data_ex(CURL *ch, const char *URL, char *postdata curl_easy_setopt(ch, CURLOPT_POST, 1); curl_easy_setopt(ch, CURLOPT_POSTFIELDS, postdata); curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, postdata_len); - - if (CURLE_OK != curl_easy_perform(ch)) { - http_curl_cleanup(ch, clean_curl); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request"); - return FAILURE; - } + http_curl_perform(ch, clean_curl); if (info) { http_curl_getinfo(ch, info); @@ -549,26 +501,18 @@ PHP_HTTP_API STATUS _http_post_data_ex(CURL *ch, const char *URL, char *postdata PHP_HTTP_API STATUS _http_post_array_ex(CURL *ch, const char *URL, HashTable *postarray, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC) { - smart_str qstr = {0}; STATUS status; + char *encoded; + size_t encoded_len; - HTTP_URL_ARGSEP_OVERRIDE; - if (php_url_encode_hash_ex(postarray, &qstr, NULL,0,NULL,0,NULL,0,NULL TSRMLS_CC) != SUCCESS) { - if (qstr.c) { - efree(qstr.c); - } + if (SUCCESS != http_urlencode_hash_ex(postarray, 1, NULL, 0, &encoded, &encoded_len)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not encode post data"); - HTTP_URL_ARGSEP_RESTORE; return FAILURE; } - smart_str_0(&qstr); - HTTP_URL_ARGSEP_RESTORE; - status = http_post_data_ex(ch, URL, qstr.c, qstr.len, options, info, data, data_len); + status = http_post_data_ex(ch, URL, encoded, encoded_len, options, info, data, data_len); + efree(encoded); - if (qstr.c) { - efree(qstr.c); - } return status; } /* }}} */ @@ -583,12 +527,7 @@ PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL, http_curl_startup(ch, clean_curl, URL, options); curl_easy_setopt(ch, CURLOPT_POST, 1); curl_easy_setopt(ch, CURLOPT_HTTPPOST, curldata); - - if (CURLE_OK != curl_easy_perform(ch)) { - http_curl_cleanup(ch, clean_curl); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request"); - return FAILURE; - } + http_curl_perform(ch, clean_curl); if (info) { http_curl_getinfo(ch, info); @@ -609,4 +548,3 @@ PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL, * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ -