From: Michael Wallner Date: Wed, 8 Jun 2022 15:22:34 +0000 (+0200) Subject: Backport v4 updates X-Git-Tag: v4.2.3~4^2 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=e3976774f27b4129cbfd7d227aaa7e177f1b735c;hp=d943313475c4e659a15f126e855b988a602c5697;p=m6w6%2Fext-http Backport v4 updates --- diff --git a/.gitignore b/.gitignore index c7fc94c..5ebf7aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,9 @@ .cproject .deps +*.dep .libs/ .project -Makefile +/Makefile Makefile.fragments Makefile.global Makefile.objects @@ -10,6 +11,7 @@ acinclude.m4 aclocal.m4 autom4te.cache/ build/ +config.cache config.guess config.h config.h.in @@ -18,6 +20,7 @@ config.nice config.status config.sub configure +configure.ac configure.in http.la install-sh diff --git a/autoconf/pecl/libbrotli.m4 b/autoconf/pecl/libbrotli.m4 index f8916e2..aee9483 100644 --- a/autoconf/pecl/libbrotli.m4 +++ b/autoconf/pecl/libbrotli.m4 @@ -6,7 +6,7 @@ AC_DEFUN([PECL_CHECK_LIBBROTLI], [ PECL_CHECK_DONE(libbrotlidec, [$PECL_VAR([HAVE_LIBBROTLI_DEC])]) PECL_CHECK_LIBBROTLI_ENC([$1], [$2]) PECL_CHECK_DONE(libbrotlienc, [$PECL_VAR([HAVE_LIBBROTLI_ENC])]) - + if $PECL_VAR([HAVE_LIBBROTLI_COMMON]) \ && $PECL_VAR([HAVE_LIBBROTLI_DEC]) \ && $PECL_VAR([HAVE_LIBBROTLI_ENC]); then @@ -14,11 +14,16 @@ AC_DEFUN([PECL_CHECK_LIBBROTLI], [ else PECL_VAR([HAVE_LIBBROTLI])=false fi + dnl config.m4 calls PECL_CHECK_DONE once more + PECL_COUNT_CHECKS([+1]) + PECL_SAVE_ENV([CPPFLAGS], [libbrotli]) + PECL_SAVE_ENV([LDFLAGS], [libbrotli]) + PECL_SAVE_ENV([LIBS], [libbrotli]) ]) AC_DEFUN([PECL_CHECK_LIBBROTLI_COMMON], [ PECL_CHECK_PKGCONFIG(libbrotlicommon, [$1]) - + PECL_HAVE_VERSION(libbrotlicommon, ifelse($2,,1.0,$2), [ PECL_VAR([HAVE_LIBBROTLI_COMMON])=true ], [ @@ -28,7 +33,7 @@ AC_DEFUN([PECL_CHECK_LIBBROTLI_COMMON], [ AC_DEFUN([PECL_CHECK_LIBBROTLI_DEC], [ PECL_CHECK_PKGCONFIG(libbrotlidec, [$1]) - + PECL_HAVE_VERSION(libbrotlidec, ifelse($2,,1.0,$2), [ PECL_VAR([HAVE_LIBBROTLI_DEC])=true ], [ @@ -38,7 +43,7 @@ AC_DEFUN([PECL_CHECK_LIBBROTLI_DEC], [ AC_DEFUN([PECL_CHECK_LIBBROTLI_ENC], [ PECL_CHECK_PKGCONFIG(libbrotlienc, [$1]) - + PECL_HAVE_VERSION(libbrotlienc, ifelse($2,,1.0,$2), [ PECL_VAR([HAVE_LIBBROTLI_ENC])=true ], [ diff --git a/autoconf/pecl/libcurl.m4 b/autoconf/pecl/libcurl.m4 index fce6437..8de9499 100644 --- a/autoconf/pecl/libcurl.m4 +++ b/autoconf/pecl/libcurl.m4 @@ -7,7 +7,7 @@ dnl AC_DEFUN([PECL_HAVE_LIBCURL_FEATURE], [dnl AC_REQUIRE([PECL_PROG_EGREP])dnl AC_CACHE_CHECK([for $1 feature in libcurl], PECL_CACHE_VAR([HAVE_LIBCURL_FEATURE_$1]), [ - if $CURL_CONFIG --feature | $EGREP -q $1; then + if $CURL_CONFIG --feature | $EGREP -qi $1; then PECL_CACHE_VAR([HAVE_LIBCURL_FEATURE_$1])=yes else PECL_CACHE_VAR([HAVE_LIBCURL_FEATURE_$1])=no @@ -160,6 +160,48 @@ AC_DEFUN([PECL_HAVE_LIBCURL_SSL], [dnl fi fi ]) + + PECL_HAVE_CONST([curl/curl.h], [CURL_LOCK_DATA_SSL_SESSION], int, [ + AC_CACHE_CHECK([whether curl_share accepts CURL_LOCK_DATA_SSL_SESSION], PECL_CACHE_VAR([LIBCURL_SHARE_SSL]), [ + PECL_CACHE_VAR([LIBCURL_SHARE_SSL])= + AC_TRY_RUN([ + #include + int main(int argc, char *argv[]) { + CURLSH *ch = curl_share_init(); + return curl_share_setopt(ch, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); + } + ], [ + PECL_CACHE_VAR([LIBCURL_SHARE_SSL])=yes + ], [ + PECL_CACHE_VAR([LIBCURL_SHARE_SSL])=no + ]) + ]) + if test "$PECL_CACHE_VAR([LIBCURL_SHARE_SSL])" = yes; then + PECL_DEFINE([HAVE_LIBCURL_SHARE_SSL], [1]) + fi + ]) + + if test "$PECL_VAR([LIBCURL_SSLLIB])" == "OpenSSL"; then + PECL_HAVE_CONST([curl/curl.h], [CURLOPT_TLS13_CIPHERS], int, [ + AC_CACHE_CHECK([whether curl_easy_setopt accepts CURLOPT_TLS13_CIPHERS], PECL_CACHE_VAR([LIBCURL_TLS13_CIPHERS]), [ + PECL_CACHE_VAR([LIBCURL_TLS13_CIPHERS])= + AC_TRY_RUN([ + #include + int main(int argc, char *argv[]) { + CURL *ch = curl_easy_init(); + return curl_easy_setopt(ch, CURLSHOPT_TLS13_CIPHERS, ""); + } + ], [ + PECL_CACHE_VAR([LIBCURL_TLS13_CIPHERS])=yes + ], [ + PECL_CACHE_VAR([LIBCURL_TLS13_CIPHERS])=no + ]) + ]) + if test "$PECL_CACHE_VAR([LIBCURL_TLS13_CIPHERS])" = yes; then + PECL_DEFINE([HAVE_LIBCURL_TLS13_CIPHERS], [1]) + fi + ]) + fi ]) ]) dnl @@ -225,4 +267,4 @@ AC_DEFUN([PECL_CHECK_LIBCURL], [dnl ifelse([$2],,,[ PECL_HAVE_VERSION([libcurl], [$2]) ]) -]) \ No newline at end of file +]) diff --git a/autoconf/pecl/pecl.m4 b/autoconf/pecl/pecl.m4 index ffa45ac..d8735b0 100644 --- a/autoconf/pecl/pecl.m4 +++ b/autoconf/pecl/pecl.m4 @@ -70,6 +70,12 @@ AC_DEFUN([PECL_RESTORE_ENV], [ $1=$PECL_SAVE_VAR([$2_$1]) ]) dnl +dnl PECL_COUNT_CHECKS(incdec) +dnl +AC_DEFUN([PECL_COUNT_CHECKS], [ + PECL_VAR([_checks])=$(($PECL_VAR([_checks])$1)) +]) +dnl dnl PECL_EVAL_LIBLINE(libline) dnl AC_DEFUN([PECL_EVAL_LIBLINE], [ @@ -244,6 +250,7 @@ dnl dnl PECL_CHECK_CUSTOM(name, path, header, lib, version) dnl AC_DEFUN([PECL_CHECK_CUSTOM], [ + PECL_COUNT_CHECKS([+1]) PECL_SAVE_ENV([CPPFLAGS], [$1]) PECL_SAVE_ENV([LDFLAGS], [$1]) PECL_SAVE_ENV([LIBS], [$1]) @@ -260,10 +267,10 @@ AC_DEFUN([PECL_CHECK_CUSTOM], [ done ]) if test -n "$PECL_CACHE_VAR([$1_prefix])"; then - CPPFLAGS="-I$PECL_CACHE_VAR([$1_prefix])/include" - LDFLAGS="-L$PECL_CACHE_VAR([$1_prefix])/$PHP_LIBDIR" - LIBS="-l$4" - PECL_EVAL_LIBLINE([$LDFLAGS $LIBS]) + CPPFLAGS="$CPPFLAGS -I$PECL_CACHE_VAR([$1_prefix])/include" + LDFLAGS="$LDFLAGS -L$PECL_CACHE_VAR([$1_prefix])/$PHP_LIBDIR" + LIBS="$LIBS -l$4" + dnl PECL_EVAL_LIBLINE([$LDFLAGS $LIBS]) AC_CACHE_VAL(PECL_CACHE_VAR([$1_version]), [ pushd $PECL_CACHE_VAR([$1_prefix]) >/dev/null @@ -288,11 +295,11 @@ dnl dnl PECL_CHECK_CONFIG(name, prog-config, version-flag, cppflags-flag, ldflags-flag, libs-flag) dnl AC_DEFUN([PECL_CHECK_CONFIG], [ + PECL_COUNT_CHECKS([+1]) PECL_SAVE_ENV([CPPFLAGS], [$1]) PECL_SAVE_ENV([LDFLAGS], [$1]) PECL_SAVE_ENV([LIBS], [$1]) - AC_MSG_CHECKING([for $1]) ifelse($2, [$PKG_CONFIG $1], [ AC_CACHE_VAL(PECL_CACHE_VAR([$1_exists]), [ @@ -311,20 +318,22 @@ AC_DEFUN([PECL_CHECK_CONFIG], [ AC_CACHE_VAL(PECL_CACHE_VAR([$1_cppflags]), [ PECL_CACHE_VAR([$1_cppflags])=$($2 $4) ]) - CPPFLAGS=$PECL_CACHE_VAR([$1_cppflags]) + CPPFLAGS="$CPPFLAGS $PECL_CACHE_VAR([$1_cppflags])" AC_CACHE_VAL(PECL_CACHE_VAR([$1_ldflags]), [ PECL_CACHE_VAR([$1_ldflags])=$($2 $5) ]) - LDFLAGS=$PECL_CACHE_VAR([$1_ldflags]) + LDFLAGS="$LDFLAGS $PECL_CACHE_VAR([$1_ldflags])" AC_CACHE_VAL(PECL_CACHE_VAR([$1_libs]), [ PECL_CACHE_VAR([$1_libs])=$($2 $6) ]) - LIBS=$PECL_CACHE_VAR([$1_libs]) - PECL_EVAL_LIBLINE([$LDFLAGS $LIBS]) + LIBS="$LIBS $PECL_CACHE_VAR([$1_libs])" + dnl PECL_EVAL_LIBLINE([$LDFLAGS $LIBS]) ifelse($2, [$PKG_CONFIG $1], [ fi ]) + AC_MSG_RESULT([${PECL_CHECKED_VERSION([$1]):-no}]) + if test -n "$PECL_CHECKED_VERSION([$1])"; then PECL_VAR([HAVE_$1])=true PECL_DEFINE([HAVE_$1]) @@ -332,8 +341,6 @@ AC_DEFUN([PECL_CHECK_CONFIG], [ else PECL_VAR([HAVE_$1])=false fi - - AC_MSG_RESULT([${PECL_CHECKED_VERSION([$1]):-no}]) ]) dnl dnl PECL_CHECK_PKGCONFIG(pkg[, additional-pkg-config-path]) @@ -355,9 +362,25 @@ dnl dnl PECL_CHECK_DONE(name, success[, incline, libline]) dnl AC_DEFUN([PECL_CHECK_DONE], [ - if $2; then - incline=$CPPFLAGS - libline="$LDFLAGS $LIBS" + PECL_COUNT_CHECKS([-1]) + success=$2 + if $success && test -n "$LDFLAGS$LIBS"; then + AC_MSG_CHECKING([whether $1 can be linked]) + AC_TRY_LINK([], [], [success=yes], [success=no]) + AC_MSG_RESULT([$success]) + if ! $success; then + AC_MSG_WARN([$1 was found, but fails to link with:]) + AC_MSG_WARN([ LDFLAGS='$LDFLAGS']) + AC_MSG_WARN([ LIBS='$LIBS']) + AC_MSG_WARN([Missing or updated library paths?]) + fi + fi + if $success; then + _cppflags=$PECL_SAVE_VAR([$1_CPPFLAGS]) + _ldflags=$PECL_SAVE_VAR([$1_LDFLAGS]) + _libs=$PECL_SAVE_VAR([$1_LIBS]) + incline=${CPPFLAGS:${#_cppflags}} + libline=["${LDFLAGS:${#_ldflags}} ${LIBS:${#_libs}}"] PECL_DEFINE([HAVE_$1]) else incline=$3 diff --git a/config9.m4 b/config9.m4 index 4f6d589..89d7b28 100644 --- a/config9.m4 +++ b/config9.m4 @@ -24,26 +24,30 @@ if test "$PHP_HTTP" != "no"; then AC_CHECK_LIB(nsl, getdomainname) ]) AC_CHECK_FUNCS(mbrtowc mbtowc iswalnum inet_pton) + + CFLAGS="$CFLAGS -Wno-strict-prototypes" dnl ZLIB PHP_ARG_WITH([http-zlib-dir], [whether/where to check for zlib], - [ --with-http-zlib-dir[=DIR] HTTP: where to find zlib], $PHP_HTTP, no) + [ --with-http-zlib-dir[=DIR] HTTP: where to find zlib], $PHP_HTTP) PECL_CHECK_ZLIB([$PHP_HTTP_ZLIB_DIR], [1.2.0.4]) PECL_CHECK_DONE(zlib, $PECL_VAR([HAVE_ZLIB])) - + dnl BROTLI PHP_ARG_WITH([http-libbrotli-dir], [whether/where to check for libbrotli], - [ --with-http-libbrotli-dir[=DIR] HTTP: where to find libbrotli], $PHP_HTTP, no) + [ --with-http-libbrotli-dir[=DIR] HTTP: where to find libbrotli], $PHP_HTTP) PECL_CHECK_LIBBROTLI([$PHP_HTTP_LIBBROTLI_DIR], [1.0]) PECL_CHECK_DONE(libbrotli, $PECL_VAR([HAVE_LIBBROTLI])) dnl CURL PHP_ARG_WITH([http-libcurl-dir], [whether/where to check for libcurl], - [ --with-http-libcurl-dir[=DIR] HTTP: where to find libcurl], $PHP_HTTP, no) + [ --with-http-libcurl-dir[=DIR] HTTP: where to find libcurl], $PHP_HTTP) if test "$PHP_HTTP_LIBCURL_DIR" != "no"; then PECL_CHECK_LIBCURL([$PHP_HTTP_LIBCURL_DIR], [7.18.2]) PECL_HAVE_LIBCURL_PROTOCOL([HTTP], [ PECL_HAVE_LIBCURL_FEATURE([HTTP2]) + PECL_HAVE_LIBCURL_FEATURE([ALT-SVC]) + PECL_HAVE_LIBCURL_FEATURE([HSTS]) PECL_HAVE_LIBCURL_ARES PECL_HAVE_LIBCURL_SSL PECL_HAVE_LIBCURL_CA diff --git a/package.xml b/package.xml index e0c0916..0576cf2 100644 --- a/package.xml +++ b/package.xml @@ -31,10 +31,10 @@ https://mdref.m6w6.name/http mike@php.net yes - 2022-02-25 + 2022-06-10 - 3.2.5 - 3.2.0 + 3.3.0 + 3.3.0 stable @@ -42,7 +42,7 @@ https://mdref.m6w6.name/http BSD-2-Clause @@ -250,6 +250,7 @@ https://mdref.m6w6.name/http + @@ -286,6 +287,7 @@ https://mdref.m6w6.name/http + diff --git a/php_http.h b/php_http.h index c2a5b95..d57f6e4 100644 --- a/php_http.h +++ b/php_http.h @@ -13,7 +13,7 @@ #ifndef PHP_EXT_HTTP_H #define PHP_EXT_HTTP_H -#define PHP_PECL_HTTP_VERSION "3.2.5" +#define PHP_PECL_HTTP_VERSION "3.3.0dev" extern zend_module_entry http_module_entry; #define phpext_http_ptr &http_module_entry diff --git a/scripts/gen_curlinfo.php b/scripts/gen_curlinfo.php index 9fae4cb..92ff65e 100755 --- a/scripts/gen_curlinfo.php +++ b/scripts/gen_curlinfo.php @@ -31,14 +31,17 @@ function file_re($file, $pattern, $all = true) { $ifdefs = array( 'PRIMARY_IP' => 'PHP_HTTP_CURL_VERSION(7,19,0)', 'APPCONNECT_TIME' => 'PHP_HTTP_CURL_VERSION(7,19,0)', - 'CONDITION_UNMET' => 'PHP_HTTP_CURL_VERSION(7,19,4)', - 'PRIMARY_PORT' => 'PHP_HTTP_CURL_VERSION(7,21,0)', - 'LOCAL_PORT' => 'PHP_HTTP_CURL_VERSION(7,21,0)', - 'LOCAL_IP' => 'PHP_HTTP_CURL_VERSION(7,21,0)', + 'CONDITION_UNMET' => 'PHP_HTTP_CURL_VERSION(7,19,4)', + 'PRIMARY_PORT' => 'PHP_HTTP_CURL_VERSION(7,21,0)', + 'LOCAL_PORT' => 'PHP_HTTP_CURL_VERSION(7,21,0)', + 'LOCAL_IP' => 'PHP_HTTP_CURL_VERSION(7,21,0)', 'HTTP_VERSION' => 'PHP_HTTP_CURL_VERSION(7,50,0)', 'PROXY_SSL_VERIFYRESULT' => 'PHP_HTTP_CURL_VERSION(7,52,0)', 'PROTOCOL' => 'PHP_HTTP_CURL_VERSION(7,52,0)', 'SCHEME' => 'PHP_HTTP_CURL_VERSION(7,52,0)', + 'RETRY_AFTER' => 'PHP_HTTP_CURL_VERSION(7,66,0)', + 'EFFECTIVE_METHOD' => 'PHP_HTTP_CURL_VERSION(7,72,0)', + 'PROXY_ERROR' => 'PHP_HTTP_CURL_VERSION(7,73,0)', ); $exclude = array( 'ACTIVESOCKET', @@ -79,6 +82,12 @@ $templates = array( zend_hash_str_update(info, "%s", lenof("%2$s"), &tmp); } ', +'OFF_T' => +' if (CURLE_OK == curl_easy_getinfo(ch, %s, &o)) { + ZVAL_LONG(&tmp, o); + zend_hash_str_update(info, "%s", lenof("%2$s"), &tmp); + } +', 'SLIST' => ' if (CURLE_OK == curl_easy_getinfo(ch, %s, &s)) { array_init(&tmp); @@ -93,12 +102,12 @@ $templates = array( ', ); -$infos = file_re('curl.h', '/^\s*(CURLINFO_(\w+))\s*=\s*CURLINFO_(STRING|LONG|DOUBLE|SLIST)\s*\+\s*\d+\s*,?\s*$/m'); +$infos = file_re('curl.h', '/^\s*(CURLINFO_(\w+))\s*=\s*CURLINFO_(STRING|LONG|DOUBLE|SLIST|OFF_T)\s*\+\s*\d+\s*,?\s*$/m'); ob_start(); foreach ($infos as $info) { list(, $full, $short, $type) = $info; - if (in_array($short, $exclude)) continue; + if (in_array($short, $exclude) || substr($short, -2) === "_T") continue; if (isset($ifdefs[$short])) printf("#if %s\n", $ifdefs[$short]); printf($templates[$type], $full, strtolower((isset($translate[$short])) ? $translate[$short] : $short)); if (isset($ifdefs[$short])) printf("#endif\n"); diff --git a/src/php_http_client.c b/src/php_http_client.c index 9551dd0..d2f6204 100644 --- a/src/php_http_client.c +++ b/src/php_http_client.c @@ -254,6 +254,20 @@ ZEND_RESULT_CODE php_http_client_dequeue(php_http_client_t *h, php_http_message_ return FAILURE; } +ZEND_RESULT_CODE php_http_client_requeue(php_http_client_t *h, php_http_message_t *request) +{ + if (h->ops->dequeue) { + php_http_client_enqueue_t *enqueue = php_http_client_enqueued(h, request, NULL); + + if (!enqueue) { + php_error_docref(NULL, E_WARNING, "Failed to requeue request; request not in queue"); + return FAILURE; + } + return h->ops->requeue(h, enqueue); + } + return FAILURE; +} + php_http_client_enqueue_t *php_http_client_enqueued(php_http_client_t *h, void *compare_arg, php_http_client_enqueue_cmp_func_t compare_func) { zend_llist_element *el = NULL; @@ -633,9 +647,8 @@ static PHP_METHOD(HttpClient, reset) RETVAL_ZVAL(getThis(), 1, 0); } -static HashTable *combined_options(zval *client, zval *request) +static HashTable *combined_options(HashTable *options, zval *client, zval *request) { - HashTable *options; unsigned num_options = 0; zval z_roptions, z_options_tmp, *z_coptions = zend_read_property(php_http_client_class_entry, client, ZEND_STRL("options"), 0, &z_options_tmp); @@ -650,8 +663,12 @@ static HashTable *combined_options(zval *client, zval *request) num_options = num; } } - ALLOC_HASHTABLE(options); - ZEND_INIT_SYMTABLE_EX(options, num_options, 0); + if (options) { + zend_hash_clean(options); + } else { + ALLOC_HASHTABLE(options); + ZEND_INIT_SYMTABLE_EX(options, num_options, 0); + } if (Z_TYPE_P(z_coptions) == IS_ARRAY) { array_copy(Z_ARRVAL_P(z_coptions), options); } @@ -714,7 +731,7 @@ static PHP_METHOD(HttpClient, enqueue) Z_ADDREF_P(request); q.request = msg_obj->message; - q.options = combined_options(getThis(), request); + q.options = combined_options(NULL, getThis(), request); q.dtor = msg_queue_dtor; q.opaque = msg_obj; q.closure.fci = fci; @@ -770,19 +787,33 @@ static PHP_METHOD(HttpClient, requeue) zend_fcall_info_cache fcc = empty_fcall_info_cache; php_http_client_object_t *obj; php_http_message_object_t *msg_obj; - php_http_client_enqueue_t q; + php_http_client_enqueue_t q, *e; php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "O|f", &request, php_http_get_client_request_class_entry(), &fci, &fcc), invalid_arg, return); obj = PHP_HTTP_OBJ(NULL, getThis()); msg_obj = PHP_HTTP_OBJ(NULL, request); - if (php_http_client_enqueued(obj->client, msg_obj->message, NULL)) { - php_http_expect(SUCCESS == php_http_client_dequeue(obj->client, msg_obj->message), runtime, return); + if ((e = php_http_client_enqueued(obj->client, msg_obj->message, NULL))) { + combined_options(e->options, getThis(), request); + php_http_expect(SUCCESS == php_http_client_requeue(obj->client, msg_obj->message), runtime, return); + if (fci.size) { + if (e->closure.fci.size) { + zval_ptr_dtor(&e->closure.fci.function_name); + if (e->closure.fci.object) { + zend_object_release(e->closure.fci.object); + } + } + Z_TRY_ADDREF(fci.function_name); + if (fci.object) { + GC_ADDREF(fci.object); + } + } + RETURN_ZVAL(getThis(), 1, 0); } q.request = msg_obj->message; - q.options = combined_options(getThis(), request); + q.options = combined_options(NULL, getThis(), request); q.dtor = msg_queue_dtor; q.opaque = msg_obj; q.closure.fci = fci; diff --git a/src/php_http_client.h b/src/php_http_client.h index fd77204..da53b4d 100644 --- a/src/php_http_client.h +++ b/src/php_http_client.h @@ -47,6 +47,7 @@ typedef int (*php_http_client_once_func_t)(struct php_http_client *p); typedef ZEND_RESULT_CODE (*php_http_client_wait_func_t)(struct php_http_client *p, struct timeval *custom_timeout); typedef ZEND_RESULT_CODE (*php_http_client_enqueue_func_t)(struct php_http_client *p, php_http_client_enqueue_t *enqueue); typedef ZEND_RESULT_CODE (*php_http_client_dequeue_func_t)(struct php_http_client *p, php_http_client_enqueue_t *enqueue); +typedef ZEND_RESULT_CODE (*php_http_client_requeue_func_t)(struct php_http_client *p, php_http_client_enqueue_t *enqueue); typedef ZEND_RESULT_CODE (*php_http_client_setopt_func_t)(struct php_http_client *p, php_http_client_setopt_opt_t opt, void *arg); typedef ZEND_RESULT_CODE (*php_http_client_getopt_func_t)(struct php_http_client *h, php_http_client_getopt_opt_t opt, void *arg, void **res); @@ -61,6 +62,7 @@ typedef struct php_http_client_ops { php_http_client_once_func_t once; php_http_client_enqueue_func_t enqueue; php_http_client_dequeue_func_t dequeue; + php_http_client_requeue_func_t requeue; php_http_client_setopt_func_t setopt; php_http_client_getopt_func_t getopt; } php_http_client_ops_t; diff --git a/src/php_http_client_curl.c b/src/php_http_client_curl.c index 619826a..46502ba 100644 --- a/src/php_http_client_curl.c +++ b/src/php_http_client_curl.c @@ -17,6 +17,8 @@ #if PHP_HTTP_HAVE_LIBCURL +#define DEBUG_COOKIES 0 + #if PHP_HTTP_HAVE_LIBCURL_OPENSSL # include #endif @@ -311,14 +313,14 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data, return 0; } -static int php_http_curle_header_callback(char *data, size_t n, size_t l, void *arg) +static size_t php_http_curle_header_callback(char *data, size_t n, size_t l, void *arg) { php_http_client_curl_handler_t *h = arg; return php_http_buffer_append(&h->response.headers, data, n * l); } -static int php_http_curle_body_callback(char *data, size_t n, size_t l, void *arg) +static size_t php_http_curle_body_callback(char *data, size_t n, size_t l, void *arg) { php_http_client_curl_handler_t *h = arg; @@ -330,8 +332,11 @@ static ZEND_RESULT_CODE php_http_curle_get_info(CURL *ch, HashTable *info) char *c = NULL; long l = 0; double d = 0; + curl_off_t o = 0; struct curl_slist *s = NULL, *p = NULL; - zval tmp = {{0}}; + zval tmp; + + ZVAL_NULL(&tmp); /* BEGIN::CURLINFO */ if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_EFFECTIVE_URL, &c)) { @@ -508,6 +513,24 @@ static ZEND_RESULT_CODE php_http_curle_get_info(CURL *ch, HashTable *info) zend_hash_str_update(info, "scheme", lenof("scheme"), &tmp); } #endif +#if PHP_HTTP_CURL_VERSION(7,66,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_RETRY_AFTER, &o)) { + ZVAL_LONG(&tmp, o); + zend_hash_str_update(info, "retry_after", lenof("retry_after"), &tmp); + } +#endif +#if PHP_HTTP_CURL_VERSION(7,72,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_EFFECTIVE_METHOD, &c)) { + ZVAL_STRING(&tmp, STR_PTR(c)); + zend_hash_str_update(info, "effective_method", lenof("effective_method"), &tmp); + } +#endif +#if PHP_HTTP_CURL_VERSION(7,73,0) + if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_PROXY_ERROR, &l)) { + ZVAL_LONG(&tmp, l); + zend_hash_str_update(info, "proxy_error", lenof("proxy_error"), &tmp); + } +#endif /* END::CURLINFO */ @@ -791,13 +814,14 @@ static php_http_options_t php_http_curle_options, php_http_curlm_options; #define PHP_HTTP_CURLE_OPTION_CHECK_STRLEN 0x0001 #define PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR 0x0002 #define PHP_HTTP_CURLE_OPTION_TRANSFORM_MS 0x0004 +#define PHP_HTTP_CURLE_OPTION_IGNORE_RC 0x0008 static ZEND_RESULT_CODE php_http_curle_option_set_ssl_verifyhost(php_http_option_t *opt, zval *val, void *userdata) { php_http_client_curl_handler_t *curl = userdata; CURL *ch = curl->handle; - if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, Z_TYPE_P(val) == IS_TRUE ? 2 : 0)) { + if (CURLE_OK != curl_easy_setopt(ch, opt->option, Z_TYPE_P(val) == IS_TRUE ? 2 : 0)) { return FAILURE; } return SUCCESS; @@ -812,6 +836,9 @@ static ZEND_RESULT_CODE php_http_curle_option_set_cookiesession(php_http_option_ return FAILURE; } if (Z_TYPE_P(val) == IS_TRUE) { +#if DEBUG_COOKIES + fprintf(stderr, "CURLOPT_COOKIELIST: SESS\n"); +#endif if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIELIST, "SESS")) { return FAILURE; } @@ -834,9 +861,19 @@ static ZEND_RESULT_CODE php_http_curle_option_set_cookiestore(php_http_option_t } else { storage->cookiestore = NULL; } - if ( CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEFILE, storage->cookiestore) - || CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEJAR, storage->cookiestore) - ) { + +#if DEBUG_COOKIES + fprintf(stderr, "CURLOPT_COOKIEFILE: %s\n", storage->cookiestore); +#endif + // does NOT enable ch->data.cookies until transfer; adds to ch->stsate.cookielist + if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEFILE, storage->cookiestore ? storage->cookiestore : "")) { + return FAILURE; + } +#if DEBUG_COOKIES + fprintf(stderr, "CURLOPT_COOKIEJAR: %s\n", storage->cookiestore); +#endif + // enables ch->data.cookies + if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEJAR, storage->cookiestore)) { return FAILURE; } @@ -928,6 +965,21 @@ static ZEND_RESULT_CODE php_http_curle_option_set_lastmodified(php_http_option_t return SUCCESS; } +#if PHP_HTTP_CURL_VERSION(7,64,1) +static ZEND_RESULT_CODE php_http_curle_option_set_altsvc_ctrl(php_http_option_t *opt, zval *val, void *userdata) +{ + php_http_client_curl_handler_t *curl = userdata; + CURL *ch = curl->handle; + + if (Z_LVAL_P(val)) { + if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_ALTSVC_CTRL, Z_LVAL_P(val))) { + return FAILURE; + } + } + return SUCCESS; +} +#endif + static ZEND_RESULT_CODE php_http_curle_option_set_compress(php_http_option_t *opt, zval *val, void *userdata) { php_http_client_curl_handler_t *curl = userdata; @@ -1151,7 +1203,7 @@ static ZEND_RESULT_CODE php_http_curle_option_set_ssl_tlsauthtype(php_http_optio if (val && Z_LVAL_P(val)) { switch (Z_LVAL_P(val)) { case CURL_TLSAUTH_SRP: - if (CURLE_OK == curl_easy_setopt(ch, CURLOPT_TLSAUTH_TYPE, PHP_HTTP_LIBCURL_TLSAUTH_SRP)) { + if (CURLE_OK == curl_easy_setopt(ch, opt->option, PHP_HTTP_LIBCURL_TLSAUTH_SRP)) { return SUCCESS; } /* no break */ @@ -1159,7 +1211,7 @@ static ZEND_RESULT_CODE php_http_curle_option_set_ssl_tlsauthtype(php_http_optio return FAILURE; } } - if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_TLSAUTH_TYPE, PHP_HTTP_LIBCURL_TLSAUTH_DEF)) { + if (CURLE_OK != curl_easy_setopt(ch, opt->option, PHP_HTTP_LIBCURL_TLSAUTH_DEF)) { return FAILURE; } return SUCCESS; @@ -1189,6 +1241,9 @@ static void php_http_curle_options_init(php_http_options_t *registry) #if PHP_HTTP_CURL_VERSION(7,19,4) php_http_option_register(registry, ZEND_STRL("noproxy"), CURLOPT_NOPROXY, IS_STRING); #endif +#if PHP_HTTP_CURL_VERSION(7,55,0) + php_http_option_register(registry, ZEND_STRL("socks5_auth"), CURLOPT_SOCKS5_AUTH, IS_LONG); +#endif #if PHP_HTTP_CURL_VERSION(7,37,0) if ((opt = php_http_option_register(registry, ZEND_STRL("proxyheader"), CURLOPT_PROXYHEADER, IS_ARRAY))) { @@ -1202,13 +1257,22 @@ static void php_http_curle_options_init(php_http_options_t *registry) opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } #endif +#if PHP_HTTP_CURL_VERSION(7,60,0) + php_http_option_register(registry, ZEND_STRL("haproxy_protocol"), CURLOPT_HAPROXYPROTOCOL, _IS_BOOL); +#endif + /* unix sockets */ #if PHP_HTTP_CURL_VERSION(7,40,0) if (PHP_HTTP_CURL_FEATURE(CURL_VERSION_UNIX_SOCKETS)) { if ((opt = php_http_option_register(registry, ZEND_STRL("unix_socket_path"), CURLOPT_UNIX_SOCKET_PATH, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } +#if PHP_HTTP_CURL_VERSION(7,53,0) + if ((opt = php_http_option_register(registry, ZEND_STRL("abstract_unix_socket"), CURLOPT_ABSTRACT_UNIX_SOCKET, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } +#endif } #endif @@ -1240,6 +1304,13 @@ static void php_http_curle_options_init(php_http_options_t *registry) } # endif #endif +#if PHP_HTTP_CURL_VERSION(7,60,0) + php_http_option_register(registry, ZEND_STRL("dns_shuffle_addresses"), CURLOPT_DNS_SHUFFLE_ADDRESSES, _IS_BOOL); +#endif +#if PHP_HTTP_CURL_VERSION(7,62,0) + php_http_option_register(registry, ZEND_STRL("doh_url"), CURLOPT_DOH_URL, IS_STRING); +#endif + /* limits */ php_http_option_register(registry, ZEND_STRL("low_speed_limit"), CURLOPT_LOW_SPEED_LIMIT, IS_LONG); @@ -1258,6 +1329,11 @@ static void php_http_curle_options_init(php_http_options_t *registry) */ php_http_option_register(registry, ZEND_STRL("fresh_connect"), CURLOPT_FRESH_CONNECT, _IS_BOOL); php_http_option_register(registry, ZEND_STRL("forbid_reuse"), CURLOPT_FORBID_REUSE, _IS_BOOL); +#if PHP_HTTP_CURL_VERSION(7,65,0) + if ((opt = php_http_option_register(registry, ZEND_STRL("maxage_conn"), CURLOPT_MAXAGE_CONN, IS_LONG))) { + ZVAL_LONG(&opt->defval, 118); + } +#endif /* outgoing interface */ php_http_option_register(registry, ZEND_STRL("interface"), CURLOPT_INTERFACE, IS_STRING); @@ -1286,6 +1362,14 @@ static void php_http_curle_options_init(php_http_options_t *registry) opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } #endif +#if PHP_HTTP_CURL_VERSION(7,61,0) + if ((opt = php_http_option_register(registry, ZEND_STRL("xoauth2_bearer"), CURLOPT_XOAUTH2_BEARER, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } +#endif +#if PHP_HTTP_CURL_VERSION(7,75,0) + php_http_option_register(registry, ZEND_STRL("aws_sigv4"), CURLOPT_AWS_SIGV4, IS_STRING); +#endif /* redirects */ if ((opt = php_http_option_register(registry, ZEND_STRL("redirect"), CURLOPT_FOLLOWLOCATION, IS_LONG))) { @@ -1371,6 +1455,9 @@ static void php_http_curle_options_init(php_http_options_t *registry) /* http protocol version */ php_http_option_register(registry, ZEND_STRL("protocol"), CURLOPT_HTTP_VERSION, IS_LONG); +#if PHP_HTTP_CURL_VERSION(7,64,0) + php_http_option_register(registry, ZEND_STRL("http09_allowed"), CURLOPT_HTTP09_ALLOWED, _IS_BOOL); +#endif /* timeouts */ if ((opt = php_http_option_register(registry, ZEND_STRL("timeout"), CURLOPT_TIMEOUT_MS, IS_DOUBLE))) { @@ -1397,119 +1484,251 @@ static void php_http_curle_options_init(php_http_options_t *registry) if ((opt = php_http_option_register(registry, ZEND_STRL("tcp_keepintvl"), CURLOPT_TCP_KEEPINTVL, IS_LONG))) { Z_LVAL(opt->defval) = 60; } +#endif +#if PHP_HTTP_CURL_VERSION(7,49,0) +# if defined(linux) || defined(__APPLE__) + /* CURLOPT_TCP_FASTOPEN is not supported (yet) on Windows */ + php_http_option_register(registry, ZEND_STRL("tcp_fastopen"), CURLOPT_TCP_FASTOPEN, _IS_BOOL); +# endif #endif /* ssl */ if (PHP_HTTP_CURL_FEATURE(CURL_VERSION_SSL)) { - if ((opt = php_http_option_register(registry, ZEND_STRL("ssl"), 0, IS_ARRAY))) { - registry = &opt->suboptions; + php_http_option_t *ssl_opt, *proxy_opt; - if ((opt = php_http_option_register(registry, ZEND_STRL("cert"), CURLOPT_SSLCERT, IS_STRING))) { + if ((ssl_opt = php_http_option_register(registry, ZEND_STRL("ssl"), 0, IS_ARRAY))) { + php_http_options_t *ssl_registry = &ssl_opt->suboptions; + + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("cert"), CURLOPT_SSLCERT, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } - if ((opt = php_http_option_register(registry, ZEND_STRL("certtype"), CURLOPT_SSLCERTTYPE, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("certtype"), CURLOPT_SSLCERTTYPE, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; ZVAL_PSTRING(&opt->defval, "PEM"); } - if ((opt = php_http_option_register(registry, ZEND_STRL("key"), CURLOPT_SSLKEY, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("key"), CURLOPT_SSLKEY, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } - if ((opt = php_http_option_register(registry, ZEND_STRL("keytype"), CURLOPT_SSLKEYTYPE, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("keytype"), CURLOPT_SSLKEYTYPE, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; ZVAL_PSTRING(&opt->defval, "PEM"); } - if ((opt = php_http_option_register(registry, ZEND_STRL("keypasswd"), CURLOPT_SSLKEYPASSWD, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("keypasswd"), CURLOPT_SSLKEYPASSWD, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } - php_http_option_register(registry, ZEND_STRL("engine"), CURLOPT_SSLENGINE, IS_STRING); - php_http_option_register(registry, ZEND_STRL("version"), CURLOPT_SSLVERSION, IS_LONG); - if ((opt = php_http_option_register(registry, ZEND_STRL("verifypeer"), CURLOPT_SSL_VERIFYPEER, _IS_BOOL))) { + php_http_option_register(ssl_registry, ZEND_STRL("engine"), CURLOPT_SSLENGINE, IS_STRING); + php_http_option_register(ssl_registry, ZEND_STRL("version"), CURLOPT_SSLVERSION, IS_LONG); + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("verifypeer"), CURLOPT_SSL_VERIFYPEER, _IS_BOOL))) { ZVAL_BOOL(&opt->defval, 1); } - if ((opt = php_http_option_register(registry, ZEND_STRL("verifyhost"), CURLOPT_SSL_VERIFYHOST, _IS_BOOL))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("verifyhost"), CURLOPT_SSL_VERIFYHOST, _IS_BOOL))) { ZVAL_BOOL(&opt->defval, 1); opt->setter = php_http_curle_option_set_ssl_verifyhost; } #if PHP_HTTP_CURL_VERSION(7,41,0) && (PHP_HTTP_HAVE_LIBCURL_OPENSSL || PHP_HTTP_HAVE_LIBCURL_NSS || PHP_HTTP_HAVE_LIBCURL_GNUTLS) - php_http_option_register(registry, ZEND_STRL("verifystatus"), CURLOPT_SSL_VERIFYSTATUS, _IS_BOOL); + php_http_option_register(ssl_registry, ZEND_STRL("verifystatus"), CURLOPT_SSL_VERIFYSTATUS, _IS_BOOL); #endif - php_http_option_register(registry, ZEND_STRL("cipher_list"), CURLOPT_SSL_CIPHER_LIST, IS_STRING); + php_http_option_register(ssl_registry, ZEND_STRL("cipher_list"), CURLOPT_SSL_CIPHER_LIST, IS_STRING); #if PHP_HTTP_HAVE_LIBCURL_CAINFO - if ((opt = php_http_option_register(registry, ZEND_STRL("cainfo"), CURLOPT_CAINFO, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("cainfo"), CURLOPT_CAINFO, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; -#ifdef PHP_HTTP_CAINFO - ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAINFO); -#endif +# ifdef PHP_HTTP_CAINFO + ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAINFO); +# endif } #endif #if PHP_HTTP_HAVE_LIBCURL_CAPATH - if ((opt = php_http_option_register(registry, ZEND_STRL("capath"), CURLOPT_CAPATH, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("capath"), CURLOPT_CAPATH, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; -#ifdef PHP_HTTP_CAPATH - ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAPATH); -#endif +# ifdef PHP_HTTP_CAPATH + ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAPATH); +# endif } #endif - if ((opt = php_http_option_register(registry, ZEND_STRL("random_file"), CURLOPT_RANDOM_FILE, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("random_file"), CURLOPT_RANDOM_FILE, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } - if ((opt = php_http_option_register(registry, ZEND_STRL("egdsocket"), CURLOPT_EGDSOCKET, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("egdsocket"), CURLOPT_EGDSOCKET, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } #if PHP_HTTP_CURL_VERSION(7,19,0) - if ((opt = php_http_option_register(registry, ZEND_STRL("issuercert"), CURLOPT_ISSUERCERT, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("issuercert"), CURLOPT_ISSUERCERT, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } # if PHP_HTTP_HAVE_LIBCURL_OPENSSL - if ((opt = php_http_option_register(registry, ZEND_STRL("crlfile"), CURLOPT_CRLFILE, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("crlfile"), CURLOPT_CRLFILE, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } # endif #endif #if (PHP_HTTP_CURL_VERSION(7,19,1) && PHP_HTTP_HAVE_LIBCURL_OPENSSL) || (PHP_HTTP_CURL_VERSION(7,34,0) && PHP_HTTP_HAVE_LIBCURL_NSS) || (PHP_HTTP_CURL_VERSION(7,42,0) && defined(PHP_HTTP_HAVE_LIBCURL_GNUTLS)) || (PHP_HTTP_CURL_VERSION(7,39,0) && defined(PHP_HTTP_HAVE_LIBCURL_GSKIT)) - if ((opt = php_http_option_register(registry, ZEND_STRL("certinfo"), CURLOPT_CERTINFO, _IS_BOOL))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("certinfo"), CURLOPT_CERTINFO, _IS_BOOL))) { ZVAL_FALSE(&opt->defval); } #endif #if PHP_HTTP_CURL_VERSION(7,36,0) - if ((opt = php_http_option_register(registry, ZEND_STRL("enable_npn"), CURLOPT_SSL_ENABLE_NPN, _IS_BOOL))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("enable_npn"), CURLOPT_SSL_ENABLE_NPN, _IS_BOOL))) { ZVAL_BOOL(&opt->defval, 1); } - if ((opt = php_http_option_register(registry, ZEND_STRL("enable_alpn"), CURLOPT_SSL_ENABLE_ALPN, _IS_BOOL))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("enable_alpn"), CURLOPT_SSL_ENABLE_ALPN, _IS_BOOL))) { ZVAL_BOOL(&opt->defval, 1); } #endif #if PHP_HTTP_CURL_VERSION(7,39,0) /* FIXME: see http://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html#AVAILABILITY */ - if ((opt = php_http_option_register(registry, ZEND_STRL("pinned_publickey"), CURLOPT_PINNEDPUBLICKEY, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("pinned_publickey"), CURLOPT_PINNEDPUBLICKEY, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; } #endif #if PHP_HTTP_CURL_VERSION(7,21,4) && PHP_HTTP_HAVE_LIBCURL_TLSAUTH_TYPE - if ((opt = php_http_option_register(registry, ZEND_STRL("tlsauthtype"), CURLOPT_TLSAUTH_TYPE, IS_LONG))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("tlsauthtype"), CURLOPT_TLSAUTH_TYPE, IS_LONG))) { opt->setter = php_http_curle_option_set_ssl_tlsauthtype; } - if ((opt = php_http_option_register(registry, ZEND_STRL("tlsauthuser"), CURLOPT_TLSAUTH_USERNAME, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("tlsauthuser"), CURLOPT_TLSAUTH_USERNAME, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } - if ((opt = php_http_option_register(registry, ZEND_STRL("tlsauthpass"), CURLOPT_TLSAUTH_PASSWORD, IS_STRING))) { + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("tlsauthpass"), CURLOPT_TLSAUTH_PASSWORD, IS_STRING))) { opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; } #endif #if PHP_HTTP_CURL_VERSION(7,42,0) && (PHP_HTTP_HAVE_LIBCURL_NSS || PHP_HTTP_HAVE_LIBCURL_SECURETRANSPORT) - php_http_option_register(registry, ZEND_STRL("falsestart"), CURLOPT_SSL_FALSESTART, _IS_BOOL); + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("falsestart"), CURLOPT_SSL_FALSESTART, _IS_BOOL))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_IGNORE_RC; + } +#endif +#if PHP_HTTP_CURL_VERSION(7,61,0) && PHP_HTTP_HAVE_LIBCURL_TLS13_CIPHERS + if ((opt = php_http_option_register(ssl_registry, ZEND_STRL("tls13_ciphers"), CURLOPT_TLS13_CIPHERS, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } #endif } + +#if PHP_HTTP_CURL_VERSION(7,52,0) + /* proxy_ssl */ + if ((proxy_opt = php_http_option_register(registry, ZEND_STRL("proxy_ssl"), 0, IS_ARRAY))) { + php_http_options_t *proxy_registry = &proxy_opt->suboptions; + + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("cert"), CURLOPT_PROXY_SSLCERT, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("certtype"), CURLOPT_PROXY_SSLCERTTYPE, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + ZVAL_PSTRING(&opt->defval, "PEM"); + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("key"), CURLOPT_PROXY_SSLKEY, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("keytype"), CURLOPT_PROXY_SSLKEYTYPE, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + ZVAL_PSTRING(&opt->defval, "PEM"); + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("keypasswd"), CURLOPT_PROXY_KEYPASSWD, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } + php_http_option_register(proxy_registry, ZEND_STRL("version"), CURLOPT_PROXY_SSLVERSION, IS_LONG); + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("verifypeer"), CURLOPT_PROXY_SSL_VERIFYPEER, _IS_BOOL))) { + ZVAL_BOOL(&opt->defval, 1); + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("verifyhost"), CURLOPT_PROXY_SSL_VERIFYHOST, _IS_BOOL))) { + ZVAL_BOOL(&opt->defval, 1); + opt->setter = php_http_curle_option_set_ssl_verifyhost; + } + php_http_option_register(proxy_registry, ZEND_STRL("cipher_list"), CURLOPT_PROXY_SSL_CIPHER_LIST, IS_STRING); +# if PHP_HTTP_CURL_VERSION(7,71,0) + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("issuercert"), CURLOPT_PROXY_ISSUERCERT, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } +# endif +# if PHP_HTTP_HAVE_LIBCURL_OPENSSL + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("crlfile"), CURLOPT_PROXY_CRLFILE, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } +# endif +# if PHP_HTTP_HAVE_LIBCURL_CAINFO + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("cainfo"), CURLOPT_PROXY_CAINFO, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; +# ifdef PHP_HTTP_CAINFO + ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAINFO); +# endif + } +# endif +# if PHP_HTTP_HAVE_LIBCURL_CAPATH + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("capath"), CURLOPT_PROXY_CAPATH, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; +# ifdef PHP_HTTP_CAPATH + ZVAL_PSTRING(&opt->defval, PHP_HTTP_CAPATH); +# endif + } +# endif + +# if PHP_HTTP_HAVE_LIBCURL_TLSAUTH_TYPE + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("tlsauthtype"), CURLOPT_PROXY_TLSAUTH_TYPE, IS_LONG))) { + opt->setter = php_http_curle_option_set_ssl_tlsauthtype; + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("tlsauthuser"), CURLOPT_PROXY_TLSAUTH_USERNAME, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("tlsauthpass"), CURLOPT_PROXY_TLSAUTH_PASSWORD, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } +# endif +# if PHP_HTTP_CURL_VERSION(7,59,0) + /* FIXME: see http://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html#AVAILABILITY */ + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("pinned_publickey"), CURLOPT_PROXY_PINNEDPUBLICKEY, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } +# endif +# if PHP_HTTP_CURL_VERSION(7,61,0) && PHP_HTTP_HAVE_LIBCURL_TLS13_CIPHERS + if ((opt = php_http_option_register(proxy_registry, ZEND_STRL("tls13_ciphers"), CURLOPT_PROXY_TLS13_CIPHERS, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN; + } +# endif + } +#endif + } + +#if PHP_HTTP_CURL_VERSION(7,64,1) +# if !PHP_HTTP_HAVE_LIBCURL_ALT_SVC + if (PHP_HTTP_CURL_FEATURE(CURL_VERSION_ALTSVC)) { +# endif + if ((opt = php_http_option_register(registry, ZEND_STRL("altsvc_ctrl"), CURLOPT_ALTSVC_CTRL, IS_LONG))) { + opt->setter = php_http_curle_option_set_altsvc_ctrl; } + if ((opt = php_http_option_register(registry, ZEND_STRL("altsvc"), CURLOPT_ALTSVC, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } +# if !PHP_HTTP_HAVE_LIBCURL_ALT_SVC + } +# endif +#endif +#if PHP_HTTP_CURL_VERSION(7,74,0) +# if !PHP_HTTP_HAVE_LIBCURL_HSTS + if (PHP_HTTP_CURL_FEATURE(CURL_VERSION_HSTS)) { +# endif + php_http_option_register(registry, ZEND_STRL("hsts_ctrl"), CURLOPT_HSTS_CTRL, IS_LONG); + if ((opt = php_http_option_register(registry, ZEND_STRL("hsts"), CURLOPT_HSTS, IS_STRING))) { + opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR; + } +# if !PHP_HTTP_HAVE_LIBCURL_HSTS + } +# endif +#endif } static zval *php_http_curle_get_option(php_http_option_t *opt, HashTable *options, void *userdata) @@ -1607,12 +1826,16 @@ static ZEND_RESULT_CODE php_http_curle_set_option(php_http_option_t *opt, zval * break; } if (rv != SUCCESS) { - php_error_docref(NULL, E_NOTICE, "Could not set option %s (%s)", opt->name->val, curl_easy_strerror(rc)); + if (opt->flags & PHP_HTTP_CURLE_OPTION_IGNORE_RC) { + rv = SUCCESS; + } else { + php_error_docref(NULL, E_NOTICE, "Could not set option %s (%s)", opt->name->val, curl_easy_strerror(rc)); + } } return rv; } -#if PHP_HTTP_CURL_VERSION(7,30,0) +#if PHP_HTTP_CURL_VERSION(7,30,0) && !PHP_HTTP_CURL_VERSION(7,62,0) static ZEND_RESULT_CODE php_http_curlm_option_set_pipelining_bl(php_http_option_t *opt, zval *value, void *userdata) { php_http_client_t *client = userdata; @@ -1714,7 +1937,7 @@ static ZEND_RESULT_CODE php_http_curlm_option_set_share_cookies(php_http_option_ return SUCCESS; } -#if PHP_HTTP_CURL_VERSION(7,23,0) +#if PHP_HTTP_HAVE_LIBCURL_SHARE_SSL static ZEND_RESULT_CODE php_http_curlm_option_set_share_ssl(php_http_option_t *opt, zval *value, void *userdata) { php_http_client_t *client = userdata; @@ -1747,38 +1970,38 @@ static void php_http_curlm_options_init(php_http_options_t *registry) /* set max number of connections to a single host */ #if PHP_HTTP_CURL_VERSION(7,30,0) php_http_option_register(registry, ZEND_STRL("max_host_connections"), CURLMOPT_MAX_HOST_CONNECTIONS, IS_LONG); -#endif - /* maximum number of requests in a pipeline */ -#if PHP_HTTP_CURL_VERSION(7,30,0) - if ((opt = php_http_option_register(registry, ZEND_STRL("max_pipeline_length"), CURLMOPT_MAX_PIPELINE_LENGTH, IS_LONG))) { - ZVAL_LONG(&opt->defval, 5); - } #endif /* max simultaneously open connections */ #if PHP_HTTP_CURL_VERSION(7,30,0) php_http_option_register(registry, ZEND_STRL("max_total_connections"), CURLMOPT_MAX_TOTAL_CONNECTIONS, IS_LONG); #endif +#if PHP_HTTP_CURL_VERSION(7,67,0) + if ((opt = php_http_option_register(registry, ZEND_STRL("max_concurrent_streams"), CURLMOPT_MAX_CONCURRENT_STREAMS, IS_LONG))) { + ZVAL_LONG(&opt->defval, 100); + } +#endif + +#if !PHP_HTTP_CURL_VERSION(7,62,0) /* enable/disable HTTP pipelining */ php_http_option_register(registry, ZEND_STRL("pipelining"), CURLMOPT_PIPELINING, _IS_BOOL); +# if PHP_HTTP_CURL_VERSION(7,30,0) + /* maximum number of requests in a pipeline */ + if ((opt = php_http_option_register(registry, ZEND_STRL("max_pipeline_length"), CURLMOPT_MAX_PIPELINE_LENGTH, IS_LONG))) { + ZVAL_LONG(&opt->defval, 5); + } /* chunk length threshold for pipelining */ -#if PHP_HTTP_CURL_VERSION(7,30,0) php_http_option_register(registry, ZEND_STRL("chunk_length_penalty_size"), CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, IS_LONG); -#endif /* size threshold for pipelining penalty */ -#if PHP_HTTP_CURL_VERSION(7,30,0) php_http_option_register(registry, ZEND_STRL("content_length_penalty_size"), CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, IS_LONG); -#endif /* pipelining server blacklist */ -#if PHP_HTTP_CURL_VERSION(7,30,0) if ((opt = php_http_option_register(registry, ZEND_STRL("pipelining_server_bl"), CURLMOPT_PIPELINING_SERVER_BL, IS_ARRAY))) { opt->setter = php_http_curlm_option_set_pipelining_bl; } -#endif /* pipelining host blacklist */ -#if PHP_HTTP_CURL_VERSION(7,30,0) if ((opt = php_http_option_register(registry, ZEND_STRL("pipelining_site_bl"), CURLMOPT_PIPELINING_SITE_BL, IS_ARRAY))) { opt->setter = php_http_curlm_option_set_pipelining_bl; } +# endif #endif /* events */ if ((opt = php_http_option_register(registry, ZEND_STRL("use_eventloop"), 0, 0))) { @@ -1789,7 +2012,7 @@ static void php_http_curlm_options_init(php_http_options_t *registry) opt->setter = php_http_curlm_option_set_share_cookies; ZVAL_TRUE(&opt->defval); } -#if PHP_HTTP_CURL_VERSION(7,23,0) +#if PHP_HTTP_HAVE_LIBCURL_SHARE_SSL if ((opt = php_http_option_register(registry, ZEND_STRL("share_ssl"), 0, _IS_BOOL))) { opt->setter = php_http_curlm_option_set_share_ssl; ZVAL_TRUE(&opt->defval); @@ -1847,9 +2070,10 @@ static ZEND_RESULT_CODE php_http_curlm_set_option(php_http_option_t *opt, zval * /* client ops */ -static ZEND_RESULT_CODE php_http_client_curl_handler_reset(php_http_client_curl_handler_t *curl) +static ZEND_RESULT_CODE php_http_client_curl_handler_reset(php_http_client_curl_handler_t *handler) { - CURL *ch = curl->handle; + php_http_client_curl_t *curl = handler->client->ctx; + CURL *ch = handler->handle; php_http_curle_storage_t *st; if ((st = php_http_curle_get_storage(ch))) { @@ -1878,27 +2102,61 @@ static ZEND_RESULT_CODE php_http_client_curl_handler_reset(php_http_client_curl_ #endif #if PHP_HTTP_CURL_VERSION(7,21,3) - if (curl->options.resolve) { - curl_slist_free_all(curl->options.resolve); - curl->options.resolve = NULL; + if (handler->options.resolve) { + curl_slist_free_all(handler->options.resolve); + handler->options.resolve = NULL; } #endif - curl->options.retry.count = 0; - curl->options.retry.delay = 0; - curl->options.redirects = 0; - curl->options.encode_cookies = 1; + handler->options.retry.count = 0; + handler->options.retry.delay = 0; + handler->options.redirects = 0; + handler->options.encode_cookies = 1; - if (curl->options.headers) { - curl_slist_free_all(curl->options.headers); - curl->options.headers = NULL; + if (handler->options.headers) { + curl_slist_free_all(handler->options.headers); + handler->options.headers = NULL; + } + if (handler->options.proxyheaders) { + curl_slist_free_all(handler->options.proxyheaders); + handler->options.proxyheaders = NULL; } - if (curl->options.proxyheaders) { - curl_slist_free_all(curl->options.proxyheaders); - curl->options.proxyheaders = NULL; + + php_http_buffer_reset(&handler->options.cookies); + php_http_buffer_reset(&handler->options.ranges); + + if (php_http_message_body_size(handler->response.body)) { + php_http_message_body_free(&handler->response.body); + handler->response.body = php_http_message_body_init(NULL, NULL); } + php_http_buffer_reset(&handler->response.headers); - php_http_buffer_reset(&curl->options.cookies); - php_http_buffer_reset(&curl->options.ranges); +#if ZTS + curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L); +#endif + curl_easy_setopt(ch, CURLOPT_HEADER, 0L); + curl_easy_setopt(ch, CURLOPT_FILETIME, 1L); + curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1L); + curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, php_http_curle_header_callback); + curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, php_http_curle_body_callback); + curl_easy_setopt(ch, CURLOPT_DEBUGFUNCTION, php_http_curle_raw_callback); + curl_easy_setopt(ch, CURLOPT_READFUNCTION, php_http_curle_read_callback); + curl_easy_setopt(ch, CURLOPT_SEEKFUNCTION, php_http_curle_seek_callback); +#if PHP_HTTP_CURL_VERSION(7,32,0) + curl_easy_setopt(ch, CURLOPT_XFERINFOFUNCTION, php_http_curle_xferinfo_callback); + curl_easy_setopt(ch, CURLOPT_XFERINFODATA, handler); +#else + curl_easy_setopt(ch, CURLOPT_PROGRESSFUNCTION, php_http_curle_progress_callback); + curl_easy_setopt(ch, CURLOPT_PROGRESSDATA, handler); +#endif + curl_easy_setopt(ch, CURLOPT_DEBUGDATA, handler); + curl_easy_setopt(ch, CURLOPT_WRITEDATA, handler); + curl_easy_setopt(ch, CURLOPT_HEADERDATA, handler); +#if DEBUG_COOKIES + fprintf(stderr, "CURLOPT_SHARE: %p\n", curl->handle->share); +#endif + curl_easy_setopt(ch, CURLOPT_SHARE, curl->handle->share); return SUCCESS; } @@ -1906,7 +2164,6 @@ static ZEND_RESULT_CODE php_http_client_curl_handler_reset(php_http_client_curl_ static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_http_client_t *h, php_resource_factory_t *rf) { void *handle; - php_http_client_curl_t *curl = h->ctx; php_http_client_curl_handler_t *handler; if (!(handle = php_resource_factory_handle_ctor(rf, NULL))) { @@ -1924,31 +2181,6 @@ static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_htt php_http_buffer_init(&handler->options.ranges); zend_hash_init(&handler->options.cache, 0, NULL, ZVAL_PTR_DTOR, 0); -#if ZTS - curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L); -#endif - curl_easy_setopt(handle, CURLOPT_HEADER, 0L); - curl_easy_setopt(handle, CURLOPT_FILETIME, 1L); - curl_easy_setopt(handle, CURLOPT_AUTOREFERER, 1L); - curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, php_http_curle_header_callback); - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, php_http_curle_body_callback); - 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_SEEKFUNCTION, php_http_curle_seek_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_PROGRESSDATA, handler); -#endif - curl_easy_setopt(handle, CURLOPT_DEBUGDATA, handler); - curl_easy_setopt(handle, CURLOPT_WRITEDATA, handler); - curl_easy_setopt(handle, CURLOPT_HEADERDATA, handler); - curl_easy_setopt(handle, CURLOPT_SHARE, curl->handle->share); - php_http_client_curl_handler_reset(handler); return handler; @@ -1974,7 +2206,9 @@ static ZEND_RESULT_CODE php_http_client_curl_handler_prepare(php_http_client_cur curl_easy_setopt(curl->handle, CURLOPT_URL, storage->url); /* apply options */ - php_http_options_apply(&php_http_curle_options, enqueue->options, curl); + if (SUCCESS != php_http_options_apply(&php_http_curle_options, enqueue->options, curl)) { + return FAILURE; + } /* request headers */ php_http_message_update_headers(msg); @@ -2072,11 +2306,18 @@ static void php_http_client_curl_handler_clear(php_http_client_curl_handler_t *h #endif curl_easy_setopt(handler->handle, CURLOPT_VERBOSE, 0L); curl_easy_setopt(handler->handle, CURLOPT_DEBUGFUNCTION, NULL); + /* see gh issue #84 */ +#if DEBUG_COOKIES + fprintf(stderr, "CURLOPT_COOKIELIST: FLUSH\n"); + fprintf(stderr, "CURLOPT_SHARE: (null)\n"); +#endif curl_easy_setopt(handler->handle, CURLOPT_COOKIELIST, "FLUSH"); curl_easy_setopt(handler->handle, CURLOPT_SHARE, NULL); - /* see gh issue #84 */ #if PHP_HTTP_CURL_VERSION(7,63,0) && !PHP_HTTP_CURL_VERSION(7,65,0) - curl_easy_setopt(handler->handle, CURLOPT_COOKIEJAR, NULL); + { + php_http_curle_storage_t *st = php_http_curle_get_storage(handler->handle); + curl_easy_setopt(handler->handle, CURLOPT_COOKIEJAR, st ? st->cookiestore : NULL); + } #endif } @@ -2157,6 +2398,17 @@ static void queue_dtor(php_http_client_enqueue_t *e) php_http_client_curl_handler_dtor(handler); } +static void retire_ch(php_persistent_handle_factory_t *f, void **handle) +{ + CURL *ch = *handle; + /* erase all cookies */ + if (ch) { + curl_easy_reset(ch); + curl_easy_setopt(ch, CURLOPT_COOKIELIST, "ALL"); + curl_easy_setopt(ch, CURLOPT_COOKIEFILE, NULL); + } +} + static php_resource_factory_t *create_rf(php_http_client_t *h, php_http_client_enqueue_t *enqueue) { php_persistent_handle_factory_t *pf = NULL; @@ -2187,7 +2439,7 @@ static php_resource_factory_t *create_rf(php_http_client_t *h, php_http_client_e id_len = spprintf(&id_str, 0, "%.*s:%s:%d", (int) phf->ident->len, phf->ident->val, STR_PTR(url->host), port); id = php_http_cs2zs(id_str, id_len); - pf = php_persistent_handle_concede(NULL, PHP_HTTP_G->client.curl.driver.request_name, id, NULL, NULL); + pf = php_persistent_handle_concede(NULL, PHP_HTTP_G->client.curl.driver.request_name, id, NULL, retire_ch); zend_string_release(id); } @@ -2245,6 +2497,43 @@ static ZEND_RESULT_CODE php_http_client_curl_enqueue(php_http_client_t *h, php_h return SUCCESS; } +static ZEND_RESULT_CODE php_http_client_curl_requeue(php_http_client_t *h, php_http_client_enqueue_t *enqueue) +{ + CURLMcode rs; + php_http_client_curl_t *curl = h->ctx; + php_http_client_curl_handler_t *handler = enqueue->opaque; + php_http_client_progress_state_t *progress; + + if (SUCCESS != php_http_client_curl_handler_reset(handler)) { + return FAILURE; + } + + if (SUCCESS != php_http_client_curl_handler_prepare(handler, enqueue)) { + return FAILURE; + } + + if (CURLM_OK != (rs = curl_multi_remove_handle(curl->handle->multi, handler->handle))) { + php_error_docref(NULL, E_WARNING, "Could not dequeue request: %s", curl_multi_strerror(rs)); + return FAILURE; + } + + if (CURLM_OK != (rs = curl_multi_add_handle(curl->handle->multi, handler->handle))) { + zend_llist_del_element(&h->requests, handler->handle, (int (*)(void *, void *)) compare_queue); + php_error_docref(NULL, E_WARNING, "Could not enqueue request: %s", curl_multi_strerror(rs)); + return FAILURE; + } + + ++curl->unfinished; + + if (h->callback.progress.func && SUCCESS == php_http_client_getopt(h, PHP_HTTP_CLIENT_OPT_PROGRESS_INFO, enqueue->request, &progress)) { + progress->info = "start"; + h->callback.progress.func(h->callback.progress.arg, h, &handler->queue, progress); + progress->started = 1; + } + + return SUCCESS; +} + static ZEND_RESULT_CODE php_http_client_curl_dequeue(php_http_client_t *h, php_http_client_enqueue_t *enqueue) { CURLMcode rs; @@ -2361,17 +2650,19 @@ static ZEND_RESULT_CODE php_http_client_curl_setopt(php_http_client_t *h, php_ht { php_http_client_curl_t *curl = h->ctx; + (void) curl; + switch (opt) { case PHP_HTTP_CLIENT_OPT_CONFIGURATION: return php_http_options_apply(&php_http_curlm_options, (HashTable *) arg, h); break; - +#if !PHP_HTTP_CURL_VERSION(7,62,0) case PHP_HTTP_CLIENT_OPT_ENABLE_PIPELINING: if (CURLM_OK != curl_multi_setopt(curl->handle->multi, CURLMOPT_PIPELINING, (long) *((zend_bool *) arg))) { return FAILURE; } break; - +#endif case PHP_HTTP_CLIENT_OPT_USE_EVENTS: #if PHP_HTTP_HAVE_LIBEVENT return php_http_curlm_use_eventloop(h, (*(zend_bool *) arg) @@ -2465,6 +2756,7 @@ static php_http_client_ops_t php_http_client_curl_ops = { php_http_client_curl_once, php_http_client_curl_enqueue, php_http_client_curl_dequeue, + php_http_client_curl_requeue, php_http_client_curl_setopt, php_http_client_curl_getopt }; @@ -2474,13 +2766,13 @@ php_http_client_ops_t *php_http_client_curl_get_ops(void) return &php_http_client_curl_ops; } -#define REGISTER_NS_STRING_OR_NULL_CONSTANT(ns, name, str, flags) \ - do { \ - if ((str) != NULL) { \ - REGISTER_NS_STRING_CONSTANT(ns, name, str, flags); \ - } else { \ - REGISTER_NS_NULL_CONSTANT(ns, name, flags); \ - } \ +#define REGISTER_NS_STRING_OR_NULL_CONSTANT(ns, name, str, flags) \ + do { \ + if ((str) != NULL) { \ + REGISTER_NS_STRING_CONSTANT(ns, name, str, flags); \ + } else { \ + REGISTER_NS_NULL_CONSTANT(ns, name, flags); \ + } \ } while (0) PHP_MINIT_FUNCTION(http_client_curl) @@ -2518,6 +2810,13 @@ PHP_MINIT_FUNCTION(http_client_curl) } if ((info = curl_version_info(CURLVERSION_NOW))) { + char tmp_ver[0x20], *tmp_ptr, *tmp_end; +#define tmp_ver_init() do {\ + tmp_ver[0] = 0; \ + tmp_ptr = &tmp_ver[0]; \ + tmp_end = &tmp_ver[sizeof(tmp_ver) - 1]; \ +} while (0) + /* * Feature constants */ @@ -2525,9 +2824,6 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "IPV6", CURL_VERSION_IPV6, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "KERBEROS4", CURL_VERSION_KERBEROS4, CONST_CS|CONST_PERSISTENT); -#if PHP_HTTP_CURL_VERSION(7,40,0) - REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "KERBEROS5", CURL_VERSION_KERBEROS5, CONST_CS|CONST_PERSISTENT); -#endif REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "SSL", CURL_VERSION_SSL, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "LIBZ", CURL_VERSION_LIBZ, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "NTLM", CURL_VERSION_NTLM, CONST_CS|CONST_PERSISTENT); @@ -2537,9 +2833,6 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "LARGEFILE", CURL_VERSION_LARGEFILE, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "IDN", CURL_VERSION_IDN, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "SSPI", CURL_VERSION_SSPI, CONST_CS|CONST_PERSISTENT); -#if PHP_HTTP_CURL_VERSION(7,38,0) - REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "GSSAPI", CURL_VERSION_GSSAPI, CONST_CS|CONST_PERSISTENT); -#endif #if PHP_HTTP_CURL_VERSION(7,21,4) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "TLSAUTH_SRP", CURL_VERSION_TLSAUTH_SRP, CONST_CS|CONST_PERSISTENT); #endif @@ -2549,28 +2842,75 @@ PHP_MINIT_FUNCTION(http_client_curl) #if PHP_HTTP_CURL_VERSION(7,33,0) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "HTTP2", CURL_VERSION_HTTP2, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,38,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "GSSAPI", CURL_VERSION_GSSAPI, CONST_CS|CONST_PERSISTENT); +#endif #if PHP_HTTP_CURL_VERSION(7,40,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "KERBEROS5", CURL_VERSION_KERBEROS5, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "UNIX_SOCKETS", CURL_VERSION_UNIX_SOCKETS, CONST_CS|CONST_PERSISTENT); #endif #if PHP_HTTP_CURL_VERSION(7,47,0) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "PSL", CURL_VERSION_PSL, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,52,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "HTTPS_PROXY", CURL_VERSION_HTTPS_PROXY, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,56,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "MULTI_SSL", CURL_VERSION_MULTI_SSL, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,57,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "BROTLI", CURL_VERSION_BROTLI, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,64,1) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "ALTSVC", CURL_VERSION_ALTSVC, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,66,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "HTTP3", CURL_VERSION_HTTP3, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,72,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "ZSTD", CURL_VERSION_ZSTD, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "UNICODE", CURL_VERSION_UNICODE, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,74,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl\\Features", "HSTS", CURL_VERSION_HSTS, CONST_CS|CONST_PERSISTENT); +#endif + /* * Version constants */ REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl", "VERSIONS", curl_version(), CONST_CS|CONST_PERSISTENT); -#if CURLVERSION_NOW >= 0 - REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl\\Versions", "CURL", (char *) info->version, CONST_CS|CONST_PERSISTENT); - REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "SSL", (char *) info->ssl_version, CONST_CS|CONST_PERSISTENT); - REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "LIBZ", (char *) info->libz_version, CONST_CS|CONST_PERSISTENT); -# if CURLVERSION_NOW >= 1 - REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "ARES", (char *) info->ares, CONST_CS|CONST_PERSISTENT); -# if CURLVERSION_NOW >= 2 - REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "IDN", (char *) info->libidn, CONST_CS|CONST_PERSISTENT); -# endif -# endif + REGISTER_NS_STRING_CONSTANT("http\\Client\\Curl\\Versions", "CURL", info->version, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "SSL", info->ssl_version, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "LIBZ", info->libz_version, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "ARES", info->ares, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "IDN", info->libidn, CONST_CS|CONST_PERSISTENT); + tmp_ver_init(); + if (info->iconv_ver_num) { + tmp_ptr = zend_print_ulong_to_buf(tmp_end, info->iconv_ver_num & 0xf); + tmp_end = tmp_ptr - 1; + tmp_ptr = zend_print_ulong_to_buf(tmp_end, info->iconv_ver_num >> 8); + *tmp_end = '.'; + } + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "ICONV", *tmp_ptr ? tmp_ptr : NULL, CONST_CS|CONST_PERSISTENT); +#if PHP_HTTP_CURL_VERSION(7,57,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "BROTLI", info->brotli_version, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,66,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "NGHTTP2", info->nghttp2_version, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "QUIC", info->quic_version, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,70,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "CAINFO", info->cainfo, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "CAPATH", info->capath, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,72,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "ZSTD", info->zstd_version, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,75,0) + REGISTER_NS_STRING_OR_NULL_CONSTANT("http\\Client\\Curl\\Versions", "HYPER", info->hyper_version, CONST_CS|CONST_PERSISTENT); +#endif + } /* @@ -2583,6 +2923,12 @@ PHP_MINIT_FUNCTION(http_client_curl) #endif #if PHP_HTTP_CURL_VERSION(7,47,0) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_2TLS", CURL_HTTP_VERSION_2TLS, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,49,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_2_PRIOR_KNOWLEDGE", CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,66,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_3", CURL_HTTP_VERSION_3, CONST_CS|CONST_PERSISTENT); #endif REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HTTP_VERSION_ANY", CURL_HTTP_VERSION_NONE, CONST_CS|CONST_PERSISTENT); @@ -2594,6 +2940,9 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_0", CURL_SSLVERSION_TLSv1_0, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_1", CURL_SSLVERSION_TLSv1_1, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_2", CURL_SSLVERSION_TLSv1_2, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,52,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_TLSv1_3", CURL_SSLVERSION_TLSv1_3, CONST_CS|CONST_PERSISTENT); #endif REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_SSLv2", CURL_SSLVERSION_SSLv2, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_SSLv3", CURL_SSLVERSION_SSLv3, CONST_CS|CONST_PERSISTENT); @@ -2602,6 +2951,14 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "TLSAUTH_SRP", CURL_TLSAUTH_SRP, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,54,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_DEFAULT", CURL_SSLVERSION_MAX_DEFAULT, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_TLSv1_0", CURL_SSLVERSION_MAX_TLSv1_0, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_TLSv1_1", CURL_SSLVERSION_MAX_TLSv1_1, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_TLSv1_2", CURL_SSLVERSION_MAX_TLSv1_2, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "SSL_VERSION_MAX_TLSv1_3", CURL_SSLVERSION_MAX_TLSv1_3, CONST_CS|CONST_PERSISTENT); +#endif + /* * DNS IPvX resolving */ @@ -2612,6 +2969,7 @@ PHP_MINIT_FUNCTION(http_client_curl) /* * Auth Constants */ + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_NONE", CURLAUTH_NONE, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_BASIC", CURLAUTH_BASIC, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_DIGEST", CURLAUTH_DIGEST, CONST_CS|CONST_PERSISTENT); #if PHP_HTTP_CURL_VERSION(7,19,3) @@ -2621,6 +2979,12 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_GSSNEG", CURLAUTH_GSSNEGOTIATE, CONST_CS|CONST_PERSISTENT); #if PHP_HTTP_CURL_VERSION(7,38,0) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_SPNEGO", CURLAUTH_NEGOTIATE, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,61,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_BEARER", CURLAUTH_BEARER, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,75,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AWS_SIGV4", CURLAUTH_AWS_SIGV4, CONST_CS|CONST_PERSISTENT); #endif REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "AUTH_ANY", CURLAUTH_ANY, CONST_CS|CONST_PERSISTENT); @@ -2628,8 +2992,8 @@ PHP_MINIT_FUNCTION(http_client_curl) * Proxy Type Constants */ REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS4", CURLPROXY_SOCKS4, CONST_CS|CONST_PERSISTENT); - REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS4A", CURLPROXY_SOCKS5, CONST_CS|CONST_PERSISTENT); - REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS5_HOSTNAME", CURLPROXY_SOCKS5, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS4A", CURLPROXY_SOCKS4A, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS5_HOSTNAME", CURLPROXY_SOCKS5_HOSTNAME, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_SOCKS5", CURLPROXY_SOCKS5, CONST_CS|CONST_PERSISTENT); REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "PROXY_HTTP", CURLPROXY_HTTP, CONST_CS|CONST_PERSISTENT); #if PHP_HTTP_CURL_VERSION(7,19,4) @@ -2648,6 +3012,16 @@ PHP_MINIT_FUNCTION(http_client_curl) REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "POSTREDIR_ALL", CURL_REDIR_POST_ALL, CONST_CS|CONST_PERSISTENT); #endif +#if PHP_HTTP_CURL_VERSION(7,64,1) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "ALTSVC_READONLYFILE", CURLALTSVC_READONLYFILE, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "ALTSVC_H1", CURLALTSVC_H1, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "ALTSVC_H2", CURLALTSVC_H2, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "ALTSVC_H3", CURLALTSVC_H3, CONST_CS|CONST_PERSISTENT); +#endif +#if PHP_HTTP_CURL_VERSION(7,74,0) + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HSTS_ENABLE", CURLHSTS_ENABLE, CONST_CS|CONST_PERSISTENT); + REGISTER_NS_LONG_CONSTANT("http\\Client\\Curl", "HSTS_READONLYFILE", CURLHSTS_READONLYFILE, CONST_CS|CONST_PERSISTENT); +#endif return SUCCESS; } diff --git a/src/php_http_cookie.c b/src/php_http_cookie.c index 1186ca0..cd3198c 100644 --- a/src/php_http_cookie.c +++ b/src/php_http_cookie.c @@ -17,16 +17,16 @@ php_http_cookie_list_t *php_http_cookie_list_init(php_http_cookie_list_t *list) if (!list) { list = emalloc(sizeof(*list)); } - + zend_hash_init(&list->cookies, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(&list->extras, 0, NULL, ZVAL_PTR_DTOR, 0); - + list->path = NULL; list->domain = NULL; list->expires = -1; list->max_age = -1; list->flags = 0; - + return list; } @@ -51,7 +51,7 @@ void php_http_cookie_list_dtor(php_http_cookie_list_t *list) if (list) { zend_hash_destroy(&list->cookies); zend_hash_destroy(&list->extras); - + PTR_SET(list->path, NULL); PTR_SET(list->domain, NULL); } @@ -206,15 +206,15 @@ void php_http_cookie_list_to_struct(php_http_cookie_list_t *list, zval *strct) { zval cookies, extras, tmp; HashTable *ht = HASH_OF(strct); - + array_init_size(&cookies, zend_hash_num_elements(&list->cookies)); array_copy(&list->cookies, Z_ARRVAL(cookies)); zend_symtable_str_update(ht, ZEND_STRL("cookies"), &cookies); - + array_init_size(&extras, zend_hash_num_elements(&list->extras)); array_copy(&list->extras, Z_ARRVAL(extras)); zend_symtable_str_update(ht, ZEND_STRL("extras"), &extras); - + ZVAL_LONG(&tmp, list->flags); zend_symtable_str_update(ht, ZEND_STRL("flags"), &tmp); ZVAL_LONG(&tmp, list->expires); @@ -286,22 +286,22 @@ php_http_cookie_list_t *php_http_cookie_list_from_struct(php_http_cookie_list_t list->domain = estrndup(str->val, str->len); zend_string_release(str); } - + return list; } static inline void append_encoded(php_http_buffer_t *buf, const char *key, size_t key_len, const char *val, size_t val_len) { zend_string *enc_str[2]; - + enc_str[0] = php_raw_url_encode(key, key_len); enc_str[1] = php_raw_url_encode(val, val_len); - + php_http_buffer_append(buf, enc_str[0]->val, enc_str[0]->len); php_http_buffer_appends(buf, "="); php_http_buffer_append(buf, enc_str[1]->val, enc_str[1]->len); php_http_buffer_appends(buf, "; "); - + zend_string_release(enc_str[0]); zend_string_release(enc_str[1]); } @@ -311,7 +311,7 @@ void php_http_cookie_list_to_string(php_http_cookie_list_t *list, char **str, si php_http_buffer_t buf; zend_hash_key key; zval *val; - + php_http_buffer_init(&buf); ZEND_HASH_FOREACH_KEY_VAL(&list->cookies, key.h, key.key, val) @@ -325,7 +325,7 @@ void php_http_cookie_list_to_string(php_http_cookie_list_t *list, char **str, si zend_string_release(str); } ZEND_HASH_FOREACH_END(); - + if (list->domain && *list->domain) { php_http_buffer_appendf(&buf, "domain=%s; ", list->domain); } @@ -340,7 +340,7 @@ void php_http_cookie_list_to_string(php_http_cookie_list_t *list, char **str, si if (list->max_age >= 0) { php_http_buffer_appendf(&buf, "max-age=%ld; ", list->max_age); } - + ZEND_HASH_FOREACH_KEY_VAL(&list->extras, key.h, key.key, val) { zend_string *str = zval_get_string(val); @@ -352,14 +352,14 @@ void php_http_cookie_list_to_string(php_http_cookie_list_t *list, char **str, si zend_string_release(str); } ZEND_HASH_FOREACH_END(); - + if (list->flags & PHP_HTTP_COOKIE_SECURE) { php_http_buffer_appends(&buf, "secure; "); } if (list->flags & PHP_HTTP_COOKIE_HTTPONLY) { php_http_buffer_appends(&buf, "httpOnly; "); } - + php_http_buffer_fix(&buf); *str = buf.data; *len = buf.used; @@ -943,7 +943,7 @@ static PHP_METHOD(HttpCookie, setFlags) } ZEND_BEGIN_ARG_INFO_EX(ai_HttpCookie_toString, 0, 0, 0) -ZEND_END_ARG_INFO();; +ZEND_END_ARG_INFO(); static PHP_METHOD(HttpCookie, toString) { php_http_cookie_object_t *obj; diff --git a/src/php_http_env.c b/src/php_http_env.c index 4afcd31..fdbdd92 100644 --- a/src/php_http_env.c +++ b/src/php_http_env.c @@ -15,6 +15,12 @@ PHP_RSHUTDOWN_FUNCTION(http_env) +{ + php_http_env_reset(); + return SUCCESS; +} + +void php_http_env_reset() { if (PHP_HTTP_G->env.request.headers) { zend_hash_destroy(PHP_HTTP_G->env.request.headers); @@ -24,13 +30,10 @@ PHP_RSHUTDOWN_FUNCTION(http_env) if (PHP_HTTP_G->env.request.body) { php_http_message_body_free(&PHP_HTTP_G->env.request.body); } - if (PHP_HTTP_G->env.server_var) { zval_ptr_dtor(PHP_HTTP_G->env.server_var); PHP_HTTP_G->env.server_var = NULL; } - - return SUCCESS; } void php_http_env_get_request_headers(HashTable *headers) @@ -774,6 +777,15 @@ static PHP_METHOD(HttpEnv, negotiate) } } +ZEND_BEGIN_ARG_INFO(ai_HttpEnv_reset, 0) +ZEND_END_ARG_INFO(); +static PHP_METHOD(HttpEnv, reset) +{ + zend_parse_parameters_none(); + php_http_env_reset(); +} + + static zend_function_entry php_http_env_methods[] = { PHP_ME(HttpEnv, getRequestHeader, ai_HttpEnv_getRequestHeader, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(HttpEnv, getRequestBody, ai_HttpEnv_getRequestBody, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) @@ -792,6 +804,8 @@ static zend_function_entry php_http_env_methods[] = { PHP_ME(HttpEnv, negotiateCharset, ai_HttpEnv_negotiateCharset, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(HttpEnv, negotiate, ai_HttpEnv_negotiate, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(HttpEnv, reset, ai_HttpEnv_reset, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + EMPTY_FUNCTION_ENTRY }; diff --git a/src/php_http_env.h b/src/php_http_env.h index 8292744..d71ec47 100644 --- a/src/php_http_env.h +++ b/src/php_http_env.h @@ -75,6 +75,7 @@ static inline zend_bool php_http_env_got_server_var(const char *v) return NULL != php_http_env_get_server_var(v, strlen(v), 1); } +PHP_HTTP_API void php_http_env_reset(); PHP_HTTP_API zend_class_entry *php_http_env_get_class_entry(void); PHP_MINIT_FUNCTION(http_env); diff --git a/src/php_http_header.c b/src/php_http_header.c index 4c9a702..7044c21 100644 --- a/src/php_http_header.c +++ b/src/php_http_header.c @@ -17,18 +17,18 @@ ZEND_RESULT_CODE php_http_header_parse(const char *header, size_t length, HashTa php_http_header_parser_t ctx; php_http_buffer_t buf; php_http_header_parser_state_t rs; - + if (!php_http_buffer_from_string_ex(&buf, header, length)) { php_error_docref(NULL, E_WARNING, "Could not allocate buffer"); return FAILURE; } - + if (!php_http_header_parser_init(&ctx)) { php_http_buffer_dtor(&buf); php_error_docref(NULL, E_WARNING, "Could not initialize header parser"); return FAILURE; } - + rs = php_http_header_parser_parse(&ctx, &buf, PHP_HTTP_HEADER_PARSER_CLEANUP, headers, callback_func, callback_data); php_http_header_parser_dtor(&ctx); php_http_buffer_dtor(&buf); @@ -327,21 +327,21 @@ ZEND_END_ARG_INFO(); PHP_METHOD(HttpHeader, getParams) { zval value_tmp, zctor, zparams_obj, *zargs = NULL; - + ZVAL_STRINGL(&zctor, "__construct", lenof("__construct")); - + object_init_ex(&zparams_obj, php_http_params_get_class_entry()); - + zargs = (zval *) ecalloc(ZEND_NUM_ARGS()+1, sizeof(zval)); ZVAL_COPY_VALUE(&zargs[0], zend_read_property(php_http_header_class_entry, getThis(), ZEND_STRL("value"), 0, &value_tmp)); if (ZEND_NUM_ARGS()) { zend_get_parameters_array(ZEND_NUM_ARGS(), ZEND_NUM_ARGS(), &zargs[1]); } - + if (SUCCESS == call_user_function(NULL, &zparams_obj, &zctor, return_value, ZEND_NUM_ARGS()+1, zargs)) { RETVAL_ZVAL(&zparams_obj, 0, 1); } - + zval_ptr_dtor(&zctor); if (zargs) { efree(zargs); @@ -436,4 +436,3 @@ PHP_MINIT_FUNCTION(http_header) * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ - diff --git a/src/php_http_header_parser.c b/src/php_http_header_parser.c index cd76b76..6700c49 100644 --- a/src/php_http_header_parser.c +++ b/src/php_http_header_parser.c @@ -40,7 +40,13 @@ php_http_header_parser_t *php_http_header_parser_init(php_http_header_parser_t * return parser; } -#define php_http_header_parser_state_push(parser, state) zend_ptr_stack_push(&(parser)->stack, (void *) (state)), (state) +static inline php_http_header_parser_state_t +php_http_header_parser_state_push(php_http_header_parser_t *parser, php_http_header_parser_state_t state) +{ + zend_ptr_stack_push(&(parser)->stack, (void *) (state)); + return state; +} + #define php_http_header_parser_state_ex(parser) ((parser)->stack.top \ ? (php_http_header_parser_state_t) (parser)->stack.elements[(parser)->stack.top - 1] \ : PHP_HTTP_HEADER_PARSER_STATE_START) @@ -428,7 +434,7 @@ static zend_function_entry php_http_header_parser_methods[] = { PHP_ME(HttpHeaderParser, getState, ai_HttpHeaderParser_getState, ZEND_ACC_PUBLIC) PHP_ME(HttpHeaderParser, parse, ai_HttpHeaderParser_parse, ZEND_ACC_PUBLIC) PHP_ME(HttpHeaderParser, stream, ai_HttpHeaderParser_stream, ZEND_ACC_PUBLIC) - {NULL, NULL, NULL} + {0} }; PHP_MINIT_FUNCTION(http_header_parser) diff --git a/src/php_http_message.c b/src/php_http_message.c index 371ecb7..2014aac 100644 --- a/src/php_http_message.c +++ b/src/php_http_message.c @@ -332,7 +332,7 @@ static void message_headers(php_http_message_t *msg, php_http_buffer_t *str) char *tmp = NULL; size_t len = 0; - php_http_info_to_string((php_http_info_t *) msg, &tmp, &len, PHP_HTTP_CRLF TSRMLS_CC); + php_http_info_to_string((php_http_info_t *) msg, &tmp, &len, PHP_HTTP_CRLF); php_http_message_update_headers(msg); php_http_buffer_append(str, tmp, len); @@ -648,15 +648,15 @@ static void php_http_message_object_prophandler_set_headers(php_http_message_obj } } static void php_http_message_object_prophandler_get_body(php_http_message_object_t *obj, zval *return_value) { - if (obj->body) { - zval tmp; + zval tmp; - ZVAL_COPY_VALUE(&tmp, return_value); - RETVAL_OBJECT(&obj->body->zo, 1); - zval_ptr_dtor(&tmp); - } else { - RETVAL_NULL(); + if (!obj->body) { + RETURN_NULL(); } + + ZVAL_COPY_VALUE(&tmp, return_value); + RETVAL_OBJECT(&obj->body->zo, 1); + zval_ptr_dtor(&tmp); } static void php_http_message_object_prophandler_set_body(php_http_message_object_t *obj, zval *value) { php_http_message_object_set_body(obj, value); @@ -689,6 +689,8 @@ static void php_http_message_object_prophandler_set_parent_message(php_http_mess do { \ if (!obj->message) { \ obj->message = php_http_message_init(NULL, 0, NULL); \ + } else if (!obj->body && php_http_message_body_size(obj->message->body)) { \ + php_http_message_object_init_body_object(obj); \ } \ } while(0) @@ -958,7 +960,9 @@ static HashTable *php_http_message_object_get_debug_info(zval *object, int *is_t size_t ver_len, url_len = 0; PHP_HTTP_MESSAGE_OBJECT_INIT(obj); - *is_temp = 0; + if (is_temp) { + *is_temp = 0; + } #define UPDATE_PROP(name_str, action_with_tmp) \ do { \ diff --git a/src/php_http_message_parser.c b/src/php_http_message_parser.c index 517806d..55087e0 100644 --- a/src/php_http_message_parser.c +++ b/src/php_http_message_parser.c @@ -57,7 +57,13 @@ php_http_message_parser_t *php_http_message_parser_init(php_http_message_parser_ return parser; } -#define php_http_message_parser_state_push(parser, state) zend_ptr_stack_push(&(parser)->stack, (void *) (state)), (state) +static inline php_http_message_parser_state_t +php_http_message_parser_state_push(php_http_message_parser_t *parser, php_http_message_parser_state_t state) +{ + zend_ptr_stack_push(&parser->stack, (void *) state); + return state; +} + #define php_http_message_parser_state_pop(parser) ((parser)->stack.top \ ? (php_http_message_parser_state_t) zend_ptr_stack_pop(&parser->stack) \ : PHP_HTTP_MESSAGE_PARSER_STATE_START) @@ -644,7 +650,7 @@ static zend_function_entry php_http_message_parser_methods[] = { PHP_ME(HttpMessageParser, getState, ai_HttpMessageParser_getState, ZEND_ACC_PUBLIC) PHP_ME(HttpMessageParser, parse, ai_HttpMessageParser_parse, ZEND_ACC_PUBLIC) PHP_ME(HttpMessageParser, stream, ai_HttpMessageParser_stream, ZEND_ACC_PUBLIC) - {NULL, NULL, NULL} + {0} }; PHP_MINIT_FUNCTION(http_message_parser) diff --git a/src/php_http_params.c b/src/php_http_params.c index 92c1441..75a9e38 100644 --- a/src/php_http_params.c +++ b/src/php_http_params.c @@ -677,8 +677,9 @@ static void skip_sep(size_t skip, php_http_params_state_t *state, php_http_param HashTable *php_http_params_parse(HashTable *params, const php_http_params_opts_t *opts) { - php_http_params_state_t state = {{NULL,0}, {NULL,0}, {NULL,0}, {NULL,0}, {NULL,NULL,NULL}, 0, 0}; + php_http_params_state_t state; + memset(&state, 0, sizeof(state)); state.input.str = opts->input.str; state.input.len = opts->input.len; diff --git a/src/php_http_querystring.c b/src/php_http_querystring.c index 391bccf..b1c6a66 100644 --- a/src/php_http_querystring.c +++ b/src/php_http_querystring.c @@ -98,7 +98,7 @@ ZEND_RESULT_CODE php_http_querystring_xlate(zval *dst, zval *src, const char *ie zval *entry; zend_string *xkey, *xstr; php_http_arrkey_t key; - + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(src), key.h, key.key, entry) { if (key.key) { @@ -107,7 +107,7 @@ ZEND_RESULT_CODE php_http_querystring_xlate(zval *dst, zval *src, const char *ie return FAILURE; } } - + if (Z_TYPE_P(entry) == IS_STRING) { if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_P(entry), Z_STRLEN_P(entry), &xstr, oe, ie)) { if (key.key) { @@ -123,7 +123,7 @@ ZEND_RESULT_CODE php_http_querystring_xlate(zval *dst, zval *src, const char *ie } } else if (Z_TYPE_P(entry) == IS_ARRAY) { zval subarray; - + array_init(&subarray); if (key.key) { add_assoc_zval_ex(dst, xkey->val, xkey->len, &subarray); @@ -137,7 +137,7 @@ ZEND_RESULT_CODE php_http_querystring_xlate(zval *dst, zval *src, const char *ie return FAILURE; } } - + if (key.key) { zend_string_release(xkey); } @@ -357,7 +357,7 @@ PHP_METHOD(HttpQueryString, __construct) { zval *params = NULL; zend_error_handling zeh; - + php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|z", ¶ms), invalid_arg, return); zend_replace_error_handling(EH_THROW, php_http_get_exception_bad_querystring_class_entry(), &zeh); @@ -447,7 +447,7 @@ PHP_METHOD(HttpQueryString, get) zend_long type = 0; zend_bool del = 0; zval *ztype = NULL, *defval = NULL; - + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|szzb", &name_str, &name_len, &ztype, &defval, &del)) { if (name_str && name_len) { if (ztype) { @@ -455,7 +455,7 @@ PHP_METHOD(HttpQueryString, get) type = Z_LVAL_P(ztype); } else if(Z_TYPE_P(ztype) == IS_STRING) { switch (Z_STRVAL_P(ztype)[0]) { - case 'B': + case 'B': case 'b': type = PHP_HTTP_QUERYSTRING_TYPE_BOOL; break; case 'L': case 'l': @@ -464,7 +464,7 @@ PHP_METHOD(HttpQueryString, get) case 'd': case 'D': case 'F': - case 'f': type = PHP_HTTP_QUERYSTRING_TYPE_FLOAT; break; + case 'f': type = PHP_HTTP_QUERYSTRING_TYPE_FLOAT; break; case 'S': case 's': type = PHP_HTTP_QUERYSTRING_TYPE_STRING; break; case 'A': @@ -487,11 +487,11 @@ ZEND_END_ARG_INFO(); PHP_METHOD(HttpQueryString, set) { zval *params; - + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "z", ¶ms)) { return; } - + php_http_querystring_set(getThis(), params, QS_MERGE); RETVAL_ZVAL(getThis(), 1, 0); } @@ -505,7 +505,7 @@ PHP_METHOD(HttpQueryString, mod) zend_error_handling zeh; php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "z", ¶ms), invalid_arg, return); - + zend_replace_error_handling(EH_THROW, php_http_get_exception_bad_querystring_class_entry(), &zeh); ZVAL_OBJ(return_value, Z_OBJ_HT_P(instance)->clone_obj(instance)); /* make sure we do not inherit the reference to _GET */ @@ -562,7 +562,7 @@ PHP_METHOD(HttpQueryString, xlate) php_http_querystring_set(getThis(), &na, 0); RETVAL_ZVAL(getThis(), 1, 0); - + zval_ptr_dtor(&na); } #endif /* HAVE_ICONV */ @@ -606,8 +606,8 @@ PHP_METHOD(HttpQueryString, offsetGet) if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "S", &offset)) { return; } - qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0, &qa_tmp); + ZVAL_DEREF(qa); if (Z_TYPE_P(qa) == IS_ARRAY) { @@ -625,7 +625,7 @@ PHP_METHOD(HttpQueryString, offsetSet) { zend_string *offset; zval *value, param, znull; - + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &offset, &value)) { return; } @@ -653,8 +653,8 @@ PHP_METHOD(HttpQueryString, offsetExists) if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "S", &offset)) { return; } - qa = zend_read_property(php_http_querystring_class_entry, getThis(), ZEND_STRL("queryArray"), 0, &qa_tmp); + ZVAL_DEREF(qa); if (Z_TYPE_P(qa) == IS_ARRAY) { @@ -672,7 +672,7 @@ PHP_METHOD(HttpQueryString, offsetUnset) { zend_string *offset; zval param, znull; - + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "S", &offset)) { return; } diff --git a/src/php_http_url.c b/src/php_http_url.c index 24a13ff..32bae58 100644 --- a/src/php_http_url.c +++ b/src/php_http_url.c @@ -1021,7 +1021,7 @@ static ZEND_RESULT_CODE parse_uidn_2003(struct parse_state *state, size_t prev_l # endif efree(uhost_str); - if (error > U_ZERO_ERROR) { + if (rc > U_ZERO_ERROR) { goto error; } @@ -2108,4 +2108,3 @@ PHP_MINIT_FUNCTION(http_url) * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ - diff --git a/tests/client002.phpt b/tests/client002.phpt index 6f01a44..5b0b2aa 100644 --- a/tests/client002.phpt +++ b/tests/client002.phpt @@ -16,8 +16,10 @@ class Observer implements SplObserver { function update(SplSubject $client, http\Client\Request $request = null, StdClass $progress = null) { echo "P"; - if ($progress->info !== "prepare" && $client->getProgressInfo($request) != $progress) { - var_dump($progress); + /* fence against buggy infof() calls in some curl versions */ + $compare = $client->getProgressInfo($request); + if ($progress->info !== "prepare" && $compare && $compare != $progress) { + var_dump($progress, $compare); } } } diff --git a/tests/client009.phpt b/tests/client009.phpt index 6aea225..0eb08f7 100644 --- a/tests/client009.phpt +++ b/tests/client009.phpt @@ -19,24 +19,33 @@ function x($a) { } server("env.inc", function($port) { + $client = new http\Client; + $client->setCookies(array("test" => "bar")); + $client->addCookies(array("foo" => "test")); $request = new http\Client\Request("GET", "http://localhost:$port"); + $client->enqueue($request); + $client->send(); + echo $client->getResponse()->getBody()->toString(); - foreach (http\Client::getAvailableDrivers() as $driver) { - $client = new http\Client($driver); - $client->setCookies(array("test" => "bar")); - $client->addCookies(array("foo" => "test")); - $client->enqueue($request); - $client->send(); - var_dump($client->getResponse()->getBody()->toString()); - $request->setOptions(array("cookies" => x($client->getCookies()))); - $client->requeue($request); - $client->send(); - var_dump($client->getResponse()->getBody()->toString()); - } + $request->setOptions(array("cookies" => x($client->getCookies()))); + $client->requeue($request); + $client->send(); + + echo $client->getResponse()->getBody()->toString(); }); ?> Done ---EXPECTREGEX-- +--EXPECT-- Test -(?:string\(46\) "Array\n\(\n \[test\] \=\> bar\n \[foo\] \=\> test\n\)\n"\nstring\(46\) "Array\n\(\n \[test\] \=\> test\n \[foo\] \=\> bar\n\)\n"\n)+Done +Array +( + [test] => bar + [foo] => test +) +Array +( + [test] => test + [foo] => bar +) +Done diff --git a/tests/client012.phpt b/tests/client012.phpt index bb599db..0e72628 100644 --- a/tests/client012.phpt +++ b/tests/client012.phpt @@ -6,6 +6,8 @@ include "skipif.inc"; skip_online_test(); skip_client_test(); skip_curl_test("7.34.0"); +if (strpos(http\Client\Curl\Versions\SSL, "SecureTransport") !== false) + die("skip SecureTransport\n"); ?> --FILE-- getTransferInfo($req)->tls_session["backend"]) { case "openssl": case "gnutls": if (count($observer->data) < 1) { - die("failed count(ssl.internals) >= 1\n"); + printf("%s: failed count(ssl.internals) >= 1\n", $client->getTransferInfo($req)->tls_session["backend"]); + var_dump($observer); + exit; } break; default: diff --git a/tests/client021.phpt b/tests/client021.phpt index 702685d..aaf4625 100644 --- a/tests/client021.phpt +++ b/tests/client021.phpt @@ -4,6 +4,9 @@ client cookies --FILE-- --FILE-- -enablePipelining(false); --EXPECTF-- Test -Deprecated: Function http\Client::enableEvents() is deprecated in %sclient024.php on line %d +Deprecated: %s http\Client::enableEvents() is deprecated in %sclient024.php on line %d -Deprecated: Function http\Client::enablePipelining() is deprecated in %sclient024.php on line %d +Deprecated: %s http\Client::enablePipelining() is deprecated in %sclient024.php on line %d ===DONE=== diff --git a/tests/client027.phpt b/tests/client027.phpt index d33a58d..b87fa65 100644 --- a/tests/client027.phpt +++ b/tests/client027.phpt @@ -15,20 +15,22 @@ echo "Test\n"; server("cookie.inc", function($port) { $client = new http\Client(null, "cookies"); - $client->configure(array("pipelining" => false)); + $client->configure(array("pipelining" => false, "share_cookies" => false)); + $request = new http\Client\Request("GET", "http://localhost:$port?r1"); $client->enqueue($request); $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); - } + dump_responses($client, ["counter" => 1]); + $client->requeue($request); + $client->send(); + dump_responses($client, ["counter" => 2]); + $client->dequeue($request); + $request = new http\Client\Request("GET", "http://localhost:$port?r2"); $client->enqueue($request); $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); - } + dump_responses($client, ["counter" => 1]); }); ?> @@ -44,7 +46,7 @@ Set-Cookie: counter=2; X-Original-Transfer-Encoding: chunked Etag: "" -Set-Cookie: counter=2; +Set-Cookie: counter=1; X-Original-Transfer-Encoding: chunked ===DONE=== diff --git a/tests/client031.phpt b/tests/client031.phpt index 3211735..73ce7e4 100644 --- a/tests/client031.phpt +++ b/tests/client031.phpt @@ -16,32 +16,29 @@ echo "Test\n"; server("cookie.inc", function($port) { $client = new http\Client(null, "cookies"); $client->configure(array("share_cookies" => false)); + $request = new http\Client\Request("GET", "http://localhost:$port"); $client->enqueue($request); $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); - } + dump_responses($client, ["counter" => 1]); + /* requeue the previous request */ $client->requeue($request); - $request = new http\Client\Request("GET", "http://localhost:$port"); - $client->enqueue($request); - $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); - } - $request = new http\Client\Request("GET", "http://localhost:$port"); - $client->enqueue($request); $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); + dump_responses($client, ["counter" => 2]); + + for($i = 0; $i < 3; ++$i) { + /* new requests */ + $request = new http\Client\Request("GET", "http://localhost:$port"); + $client->enqueue($request); + $client->send(); + dump_responses($client, ["counter" => 1]); } - $request = new http\Client\Request("GET", "http://localhost:$port"); - $client->enqueue($request); + + /* requeue the previous request */ + $client->requeue($request); $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); - } + dump_responses($client, ["counter" => 2]); }); ?> @@ -53,11 +50,11 @@ Set-Cookie: counter=1; X-Original-Transfer-Encoding: chunked Etag: "" -Set-Cookie: counter=1; +Set-Cookie: counter=2; X-Original-Transfer-Encoding: chunked Etag: "" -Set-Cookie: counter=2; +Set-Cookie: counter=1; X-Original-Transfer-Encoding: chunked Etag: "" @@ -68,4 +65,8 @@ Etag: "" Set-Cookie: counter=1; X-Original-Transfer-Encoding: chunked +Etag: "" +Set-Cookie: counter=2; +X-Original-Transfer-Encoding: chunked + ===DONE=== diff --git a/tests/client032.phpt b/tests/client032.phpt index d8dfb2b..954a68e 100644 --- a/tests/client032.phpt +++ b/tests/client032.phpt @@ -16,32 +16,29 @@ echo "Test\n"; server("cookie.inc", function($port) { $client = new http\Client(null, "cookies"); $client->configure(array("share_cookies" => true)); + $request = new http\Client\Request("GET", "http://localhost:$port"); $client->enqueue($request); $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); - } + dump_responses($client, ["counter" => 1]); + /* requeue the previous request */ $client->requeue($request); - $request = new http\Client\Request("GET", "http://localhost:$port"); - $client->enqueue($request); - $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); - } - $request = new http\Client\Request("GET", "http://localhost:$port"); - $client->enqueue($request); $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); + dump_responses($client, ["counter" => 2]); + + for($i = 3; $i < 6; ++$i) { + /* new requests */ + $request = new http\Client\Request("GET", "http://localhost:$port"); + $client->enqueue($request); + $client->send(); + dump_responses($client, ["counter" => $i]); } - $request = new http\Client\Request("GET", "http://localhost:$port"); - $client->enqueue($request); + + /* requeue the previous request */ + $client->requeue($request); $client->send(); - while (($r = $client->getResponse())) { - dump_headers(null, $r->getHeaders()); - } + dump_responses($client, ["counter" => $i]); }); ?> @@ -57,15 +54,19 @@ Set-Cookie: counter=2; X-Original-Transfer-Encoding: chunked Etag: "" -Set-Cookie: counter=2; +Set-Cookie: counter=3; X-Original-Transfer-Encoding: chunked Etag: "" -Set-Cookie: counter=3; +Set-Cookie: counter=4; X-Original-Transfer-Encoding: chunked Etag: "" -Set-Cookie: counter=4; +Set-Cookie: counter=5; +X-Original-Transfer-Encoding: chunked + +Etag: "" +Set-Cookie: counter=6; X-Original-Transfer-Encoding: chunked ===DONE=== diff --git a/tests/envreset001.phpt b/tests/envreset001.phpt new file mode 100644 index 0000000..547fef0 --- /dev/null +++ b/tests/envreset001.phpt @@ -0,0 +1,65 @@ +--TEST-- +env reset +--SKIPIF-- + +--POST-- +a=b +--ENV-- +HTTP_HOST=foo.bar +HTTP_ACCEPT=*/* +--FILE-- + +==DONE== +--EXPECTF-- +NULL +string(%d) "foo.bar" +string(%d) "application/x-www-form-urlencoded" +array(4) { + ["Accept"]=> + string(3) "*/*" + ["Content-Length"]=> + string(1) "3" + ["Content-Type"]=> + string(33) "application/x-www-form-urlencoded" + ["Host"]=> + string(7) "foo.bar" +} +NULL +string(%d) "foo.bar" +string(%d) "yesyes" +NULL +string(%d) "application/x-www-form-urlencoded" +array(4) { + ["Accept"]=> + string(3) "*/*" + ["Content-Length"]=> + string(1) "3" + ["Content-Type"]=> + string(33) "application/x-www-form-urlencoded" + ["Nono"]=> + string(6) "yesyes" +} +==DONE== diff --git a/tests/gh-issue11.phpt b/tests/gh-issue11.phpt index aba014a..16948cc 100644 --- a/tests/gh-issue11.phpt +++ b/tests/gh-issue11.phpt @@ -3,7 +3,7 @@ crash when query string has nested array keys --SKIPIF-- --FILE-- --FILE-- - diff --git a/tests/helper/dump.inc b/tests/helper/dump.inc index 452a715..5612d06 100644 --- a/tests/helper/dump.inc +++ b/tests/helper/dump.inc @@ -24,4 +24,17 @@ function dump_message($stream, http\Message $msg, $parent = false) { } } -?> \ No newline at end of file +function dump_responses($client, array $expect_cookie = []) { + while (($r = $client->getResponse())) { + dump_headers(null, $r->getHeaders()); + if ($expect_cookie) { + $got_cookies = array_merge(...array_map(fn($c) => $c->getCookies(), $r->getCookies())); + if ($expect_cookie != $got_cookies) { + var_dump($expect_cookie, $got_cookies); + echo $r->toString(true); + } + } + } + +} +?> diff --git a/tests/message002.phpt b/tests/message002.phpt index 573fdbd..da0b799 100644 --- a/tests/message002.phpt +++ b/tests/message002.phpt @@ -42,7 +42,8 @@ object(%s)#%d (13) { ["type":protected]=> int(1) ["body":protected]=> - NULL + object(http\Message\Body)#3 (0) { + } ["requestMethod":protected]=> string(4) "POST" ["requestUrl":protected]=> diff --git a/tests/skipif.inc b/tests/skipif.inc index 85dbac2..76c3bd7 100644 --- a/tests/skipif.inc +++ b/tests/skipif.inc @@ -1,13 +1,17 @@ =")) { + die("skip need at least libcurl version $version\n"); } } @@ -49,7 +53,7 @@ function skip_http2_test($message = "skip need http2 support") { if (!(http\Client\Curl\FEATURES & http\Client\Curl\Features\HTTP2)) { die("$message (FEATURES & HTTP2)\n"); } - foreach (explode(":", $_ENV["PATH"]) as $path) { + foreach (explode(":", getenv("PATH")) as $path) { if (is_executable($path . "/nghttpd")) { return; } diff --git a/tests/urlparser004.phpt b/tests/urlparser004.phpt index 36d6983..4eab3b7 100644 --- a/tests/urlparser004.phpt +++ b/tests/urlparser004.phpt @@ -11,7 +11,8 @@ if (!defined("http\\Url::PARSE_MBLOC") or --FILE-- --FILE--