From: Michael Wallner Date: Wed, 3 Oct 2007 10:55:13 +0000 (+0000) Subject: - provide persistent storage for things curl might use on curl_easy_cleanup X-Git-Tag: RELEASE_1_6_0RC1~4 X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=commitdiff_plain;h=d8d4c50ac3637c4fafae5cec91501795b334c11e - provide persistent storage for things curl might use on curl_easy_cleanup --- diff --git a/http_request_api.c b/http_request_api.c index 9ccda2c..33450a3 100644 --- a/http_request_api.c +++ b/http_request_api.c @@ -84,6 +84,51 @@ static struct gcry_thread_cbs http_gnutls_tsl = { #endif /* }}} */ +/* safe curl wrappers */ +#define init_curl_storage(ch) \ + {\ + http_request_storage *st = pecalloc(1, sizeof(http_request_storage), 1); \ + curl_easy_setopt(ch, CURLOPT_PRIVATE, st); \ + curl_easy_setopt(ch, CURLOPT_ERRORBUFFER, st->errorbuffer); \ + } + +static void *safe_curl_init(void) +{ + CURL *ch; + + if ((ch = curl_easy_init())) { + init_curl_storage(ch); + return ch; + } + return NULL; +} +static void *safe_curl_copy(void *p) +{ + CURL *ch; + + if ((ch = curl_easy_duphandle(p))) { + init_curl_storage(ch); + return ch; + } + return NULL; +} +static void safe_curl_dtor(void *p) { + http_request_storage *st = http_request_storage_get(p); + + curl_easy_cleanup(p); + + if (st) { + if (st->url) { + pefree(st->url, 1); + } + if (st->cookiestore) { + pefree(st->cookiestore, 1); + } + pefree(st, 1); + } +} +/* }}} */ + /* {{{ MINIT */ PHP_MINIT_FUNCTION(http_request) { @@ -110,7 +155,7 @@ PHP_MINIT_FUNCTION(http_request) return FAILURE; } - if (SUCCESS != http_persistent_handle_provide("http_request", curl_easy_init, curl_easy_cleanup, curl_easy_duphandle)) { + if (SUCCESS != http_persistent_handle_provide("http_request", safe_curl_init, safe_curl_dtor, safe_curl_copy)) { return FAILURE; } @@ -200,9 +245,7 @@ PHP_HTTP_API CURL * _http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC /* set context */ if (request) { - curl_easy_setopt(ch, CURLOPT_PRIVATE, request); curl_easy_setopt(ch, CURLOPT_DEBUGDATA, request); - curl_easy_setopt(ch, CURLOPT_ERRORBUFFER, request->_error); /* attach curl handle */ request->ch = ch; @@ -311,11 +354,23 @@ PHP_HTTP_API void _http_request_reset(http_request *request) phpstr_dtor(&request->conv.request); phpstr_dtor(&request->conv.response); http_request_body_dtor(request->body); + http_request_defaults(request); if (request->ch) { - http_request_defaults(request); + http_request_storage *st = http_request_storage_get(request->ch); + + if (st) { + if (st->url) { + pefree(st->url, 1); + st->url = NULL; + } + if (st->cookiestore) { + pefree(st->cookiestore, 1); + st->cookiestore = NULL; + } + st->errorbuffer[0] = '\0'; + } } - request->_error[0] = '\0'; } /* }}} */ @@ -468,13 +523,22 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti { zval *zoption; zend_bool range_req = 0; + http_request_storage *storage; TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); HTTP_CHECK_CURL_INIT(request->ch, http_curl_init(request), return FAILURE); + if (!(storage = http_request_storage_get(request->ch))) { + return FAILURE; + } + /* set options */ - HTTP_CURL_OPT(CURLOPT_URL, request->url); + if (storage->url) { + pefree(storage->url, 1); + } + storage->url = pestrdup(request->url, 1); + HTTP_CURL_OPT(CURLOPT_URL, storage->url); /* progress callback */ if ((zoption = http_request_option(request, options, "onprogress", -1))) { @@ -757,8 +821,12 @@ PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *opti if (Z_STRLEN_P(zoption)) { HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(zoption), return FAILURE); } - HTTP_CURL_OPT(CURLOPT_COOKIEFILE, Z_STRVAL_P(zoption)); - HTTP_CURL_OPT(CURLOPT_COOKIEJAR, Z_STRVAL_P(zoption)); + if (storage->cookiestore) { + pefree(storage->cookiestore, 1); + } + storage->cookiestore = pestrndup(Z_STRVAL_P(zoption), Z_STRLEN_P(zoption), 1); + HTTP_CURL_OPT(CURLOPT_COOKIEFILE, storage->cookiestore); + HTTP_CURL_OPT(CURLOPT_COOKIEJAR, storage->cookiestore); } /* maxfilesize */ @@ -894,7 +962,7 @@ PHP_HTTP_API void _http_request_exec(http_request *request) retry: if (CURLE_OK != (result = curl_easy_perform(request->ch))) { - http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(result), request->_error, request->url); + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(result), http_request_storage_get(request->ch)->errorbuffer, request->url); if (request->_retry.count > tries++) { switch (result) { diff --git a/http_request_info.c b/http_request_info.c index 1100211..1d12f36 100644 --- a/http_request_info.c +++ b/http_request_info.c @@ -125,7 +125,7 @@ PHP_HTTP_API void _http_request_info(http_request *request, HashTable *info) } #endif /* END */ - add_assoc_string_ex(&array, "error", sizeof("error"), request->_error, 1); + add_assoc_string_ex(&array, "error", sizeof("error"), http_request_storage_get(request->ch)->errorbuffer, 1); } /* }}} */ diff --git a/http_request_pool_api.c b/http_request_pool_api.c index ce1257e..e5482b4 100644 --- a/http_request_pool_api.c +++ b/http_request_pool_api.c @@ -382,9 +382,8 @@ void _http_request_pool_responsehandler(http_request_pool *pool) msg = curl_multi_info_read(pool->ch, &remaining); if (msg && CURLMSG_DONE == msg->msg) { if (CURLE_OK != msg->data.result) { - http_request *r = NULL; - curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &r); - http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(msg->data.result), r?r->_error:"", r?r->url:""); + http_request_storage *st = http_request_storage_get(msg->easy_handle); + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(msg->data.result), st?st->errorbuffer:"", st?st->url:""); } http_request_pool_apply_with_arg(pool, _http_request_pool_apply_responsehandler, msg->easy_handle); } diff --git a/php_http_request_api.h b/php_http_request_api.h index 22a4972..dfb2e32 100644 --- a/php_http_request_api.h +++ b/php_http_request_api.h @@ -57,6 +57,31 @@ typedef struct _http_request_t { } http_request; +#ifndef pestrndup +# define pestrndup(s,l,p) _pestrndup((s),(l),(p)) +static inline void *_pestrndup(const void *s, size_t l, int p) +{ + void *d = pemalloc(l+1, p); + memcpy(d, s, l); + ((char *) d)[l] = '\0'; + return d; +} +#endif + +/* CURLOPT_PRIVATE storage living as long as a CURL handle */ +typedef struct _http_request_storage_t { + char *url; + char *cookiestore; + char errorbuffer[CURL_ERROR_SIZE]; +} http_request_storage; + +static inline http_request_storage *http_request_storage_get(CURL *ch) +{ + http_request_storage *st = NULL; + curl_easy_getinfo(ch, CURLINFO_PRIVATE, &st); + return st; +} + #define http_curl_init(r) http_curl_init_ex(NULL, (r)) #define http_curl_init_ex(c, r) _http_curl_init_ex((c), (r) TSRMLS_CC) PHP_HTTP_API CURL *_http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC);