X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=php_http_client_curl.c;h=9081978433c7b025c34def624de117295f329428;hp=52e5e0278788af16cb082dbaaa4a7a4901f9693a;hb=cad11028f2e3b91d515f22e3a7d41181ff517414;hpb=a00df7ba31ebf62332b6592ce52ffc96e1bf2b3b diff --git a/php_http_client_curl.c b/php_http_client_curl.c index 52e5e02..9081978 100644 --- a/php_http_client_curl.c +++ b/php_http_client_curl.c @@ -6,7 +6,7 @@ | modification, are permitted provided that the conditions mentioned | | in the accompanying LICENSE file are met. | +--------------------------------------------------------------------+ - | Copyright (c) 2004-2013, Michael Wallner | + | Copyright (c) 2004-2014, Michael Wallner | +--------------------------------------------------------------------+ */ @@ -17,25 +17,32 @@ #if PHP_HTTP_HAVE_EVENT # if !PHP_HTTP_HAVE_EVENT2 && /* just be really sure */ !(LIBEVENT_VERSION_NUMBER >= 0x02000000) -# include +# include # define event_base_new event_init # define event_assign(e, b, s, a, cb, d) do {\ event_set(e, s, a, cb, d); \ event_base_set(b, e); \ } while(0) -# else -# if PHP_HTTP_HAVE_EVENT2 -# include -# include -# else -# error "libevent presence is unknown" -# endif -# endif +# else +# if PHP_HTTP_HAVE_EVENT2 +# include +# include +# else +# error "libevent presence is unknown" +# endif +# endif # ifndef DBG_EVENTS # define DBG_EVENTS 0 # endif #endif +#ifdef PHP_HTTP_HAVE_OPENSSL +# include +#endif +#ifdef PHP_HTTP_HAVE_GNUTLS +# include +#endif + typedef struct php_http_client_curl { CURLM *handle; @@ -176,14 +183,22 @@ static size_t php_http_curle_read_callback(void *data, size_t len, size_t n, voi { php_http_message_body_t *body = ctx; - if (body) { - TSRMLS_FETCH_FROM_CTX(body->ts); - return php_stream_read(php_http_message_body_stream(body), data, len * n); + if (body && body->stream_id) { + php_stream *s = php_http_message_body_stream(body); + + if (s) { + TSRMLS_FETCH_FROM_CTX(body->ts); + return php_stream_read(s, data, len * n); + } else abort(); } return 0; } +#if PHP_HTTP_CURL_VERSION(7,32,0) +static int php_http_curle_xferinfo_callback(void *ctx, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +#else static int php_http_curle_progress_callback(void *ctx, double dltotal, double dlnow, double ultotal, double ulnow) +#endif { php_http_client_curl_handler_t *h = ctx; zend_bool update = 0; @@ -254,6 +269,8 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, h->progress.info = "blacklist check"; } else if (php_memnstr(data, ZEND_STRL("SSL"), data + length)) { h->progress.info = "ssl negotiation"; + } else if (php_memnstr(data, ZEND_STRL("upload"), data + length)) { + h->progress.info = "uploaded"; } else if (php_memnstr(data, ZEND_STRL("left intact"), data + length)) { h->progress.info = "not disconnected"; } else if (php_memnstr(data, ZEND_STRL("closed"), data + length)) { @@ -265,6 +282,7 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, } else { #if PHP_DEBUG h->progress.info = data; + data[length - 1] = '\0'; #endif } if (h->client->callback.progress.func) { @@ -467,6 +485,87 @@ static STATUS php_http_curle_get_info(CURL *ch, HashTable *info) /* END::CURLINFO */ +#if PHP_HTTP_CURL_VERSION(7,34,0) + { + int i; + zval *ti_array; + struct curl_tlssessioninfo *ti; + + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_TLS_SESSION, &ti)) { + const char *backend; + + MAKE_STD_ZVAL(subarray); + ZVAL_NULL(subarray); + MAKE_STD_ZVAL(ti_array); + array_init(ti_array); + + switch (ti->backend) { + case CURLSSLBACKEND_NONE: + backend = "none"; + break; + case CURLSSLBACKEND_OPENSSL: + backend = "openssl"; +#ifdef PHP_HTTP_HAVE_OPENSSL + { + SSL_CTX *ctx = ti->internals; + + array_init(subarray); + add_assoc_long_ex(subarray, ZEND_STRS("number"), SSL_CTX_sess_number(ctx)); + add_assoc_long_ex(subarray, ZEND_STRS("connect"), SSL_CTX_sess_connect(ctx)); + add_assoc_long_ex(subarray, ZEND_STRS("connect_good"), SSL_CTX_sess_connect_good(ctx)); + add_assoc_long_ex(subarray, ZEND_STRS("connect_renegotiate"), SSL_CTX_sess_connect_renegotiate(ctx)); + add_assoc_long_ex(subarray, ZEND_STRS("hits"), SSL_CTX_sess_hits(ctx)); + add_assoc_long_ex(subarray, ZEND_STRS("cache_full"), SSL_CTX_sess_cache_full(ctx)); + } +#endif + break; + case CURLSSLBACKEND_GNUTLS: + backend = "gnutls"; +#ifdef PHP_HTTP_HAVE_GNUTLS + { + gnutls_session_t sess = ti->internals; + char *desc; + + array_init(subarray); + if ((desc = gnutls_session_get_desc(sess))) { + add_assoc_string_ex(subarray, ZEND_STRS("desc"), desc, 1); + gnutls_free(desc); + } + add_assoc_bool_ex(subarray, ZEND_STRS("resumed"), gnutls_session_is_resumed(sess)); + } +#endif + break; + case CURLSSLBACKEND_NSS: + backend = "nss"; + break; + case CURLSSLBACKEND_QSOSSL: + backend = "qsossl"; + break; + case CURLSSLBACKEND_GSKIT: + backend = "gskit"; + break; + case CURLSSLBACKEND_POLARSSL: + backend = "polarssl"; + break; + case CURLSSLBACKEND_CYASSL: + backend = "cyassl"; + break; + case CURLSSLBACKEND_SCHANNEL: + backend = "schannel"; + break; + case CURLSSLBACKEND_DARWINSSL: + backend = "darwinssl"; + break; + default: + backend = "unknown"; + } + add_assoc_string_ex(ti_array, ZEND_STRS("backend"), estrdup(backend), 0); + add_assoc_zval_ex(ti_array, ZEND_STRS("internals"), subarray); + add_assoc_zval_ex(&array, "tls_session", sizeof("tls_session"), ti_array); + } + } +#endif + #if PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL) { int i; @@ -1096,7 +1195,11 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC) /* useragent */ if ((opt = php_http_option_register(registry, ZEND_STRL("useragent"), CURLOPT_USERAGENT, IS_STRING))) { /* don't check strlen, to allow sending no useragent at all */ - ZVAL_STRING(&opt->defval, "PECL::HTTP/" PHP_PECL_HTTP_VERSION " (PHP/" PHP_VERSION ")", 0); + ZVAL_STRING(&opt->defval, + "PECL_HTTP/" PHP_PECL_HTTP_VERSION " " + "PHP/" PHP_VERSION " " + "libcurl/" LIBCURL_VERSION + , 0); } /* resume */ @@ -1408,9 +1511,14 @@ static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_htt curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, php_http_curle_raw_callback); curl_easy_setopt(handle, CURLOPT_READFUNCTION, php_http_curle_read_callback); curl_easy_setopt(handle, CURLOPT_IOCTLFUNCTION, php_http_curle_ioctl_callback); +#if PHP_HTTP_CURL_VERSION(7,32,0) + curl_easy_setopt(handle, CURLOPT_XFERINFOFUNCTION, php_http_curle_xferinfo_callback); + curl_easy_setopt(handle, CURLOPT_XFERINFODATA, handler); +#else curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, php_http_curle_progress_callback); - curl_easy_setopt(handle, CURLOPT_DEBUGDATA, handler); curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, handler); +#endif + curl_easy_setopt(handle, CURLOPT_DEBUGDATA, handler); php_http_client_curl_handler_reset(handler); @@ -1488,8 +1596,8 @@ static STATUS php_http_client_curl_handler_prepare(php_http_client_curl_handler_ } } php_http_buffer_dtor(&header); - curl_easy_setopt(curl->handle, CURLOPT_HTTPHEADER, curl->options.headers); } + curl_easy_setopt(curl->handle, CURLOPT_HTTPHEADER, curl->options.headers); /* attach request body */ if ((body_size = php_http_message_body_size(msg->body))) { @@ -1504,6 +1612,11 @@ static STATUS php_http_client_curl_handler_prepare(php_http_client_curl_handler_ curl_easy_setopt(curl->handle, CURLOPT_READDATA, msg->body); curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, body_size); curl_easy_setopt(curl->handle, CURLOPT_POSTFIELDSIZE, body_size); + } else { + curl_easy_setopt(curl->handle, CURLOPT_IOCTLDATA, NULL); + curl_easy_setopt(curl->handle, CURLOPT_READDATA, NULL); + curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, 0L); + curl_easy_setopt(curl->handle, CURLOPT_POSTFIELDSIZE, 0L); } php_http_options_apply(&php_http_curle_options, enqueue->options, curl); @@ -1516,7 +1629,11 @@ static void php_http_client_curl_handler_dtor(php_http_client_curl_handler_t *ha TSRMLS_FETCH_FROM_CTX(handler->client->ts); curl_easy_setopt(handler->handle, CURLOPT_NOPROGRESS, 1L); +#if PHP_HTTP_CURL_VERSION(7,32,0) + curl_easy_setopt(handler->handle, CURLOPT_XFERINFOFUNCTION, NULL); +#else curl_easy_setopt(handler->handle, CURLOPT_PROGRESSFUNCTION, NULL); +#endif curl_easy_setopt(handler->handle, CURLOPT_VERBOSE, 0L); curl_easy_setopt(handler->handle, CURLOPT_DEBUGFUNCTION, NULL); @@ -1798,7 +1915,7 @@ static STATUS php_http_client_curl_exec(php_http_client_t *h) /* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "WinSock error: %d", WSAGetLastError()); #else - php_error_docref(NULL TSRMLS_CC, E_WARNING, strerror(errno)); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno)); #endif return FAILURE; } @@ -1980,7 +2097,11 @@ PHP_MINIT_FUNCTION(http_client_curl) PHP_MSHUTDOWN_FUNCTION(http_client_curl) { + php_persistent_handle_cleanup(ZEND_STRL("http\\Client\\Curl"), NULL, 0 TSRMLS_CC); + php_persistent_handle_cleanup(ZEND_STRL("http\\Client\\Curl\\Request"), NULL, 0 TSRMLS_CC); + php_http_options_dtor(&php_http_curle_options); + return SUCCESS; }