Skip to content

Commit ea77ca8

Browse files
committed
ext/curl: Convert handlers.xferinfo to just be a FCC
1 parent 537a63a commit ea77ca8

File tree

4 files changed

+52
-54
lines changed

4 files changed

+52
-54
lines changed

ext/curl/curl_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ typedef struct {
7373
php_curl_read *read;
7474
zval std_err;
7575
zend_fcall_info_cache progress;
76-
php_curl_callback *xferinfo;
76+
zend_fcall_info_cache xferinfo;
7777
php_curl_callback *fnmatch;
7878
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
7979
zend_fcall_info_cache sshhostkey;

ext/curl/interface.c

Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,8 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
492492
zend_get_gc_buffer_add_fcc(gc_buffer, &curl->handlers.progress);
493493
}
494494

495-
if (curl->handlers.xferinfo) {
496-
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.xferinfo->func_name);
495+
if (ZEND_FCC_INITIALIZED(curl->handlers.xferinfo)) {
496+
zend_get_gc_buffer_add_fcc(gc_buffer, &curl->handlers.xferinfo);
497497
}
498498

499499
if (curl->handlers.fnmatch) {
@@ -703,7 +703,6 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double
703703
static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
704704
{
705705
php_curl *ch = (php_curl *)clientp;
706-
php_curl_callback *t = ch->handlers.xferinfo;
707706
size_t rval = 0;
708707

709708
#if PHP_CURL_DEBUG
@@ -713,8 +712,6 @@ static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
713712

714713
zval argv[5];
715714
zval retval;
716-
zend_result error;
717-
zend_fcall_info fci;
718715

719716
GC_ADDREF(&ch->std);
720717
ZVAL_OBJ(&argv[0], &ch->std);
@@ -723,25 +720,18 @@ static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
723720
ZVAL_LONG(&argv[3], ultotal);
724721
ZVAL_LONG(&argv[4], ulnow);
725722

726-
fci.size = sizeof(fci);
727-
ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
728-
fci.object = NULL;
729-
fci.retval = &retval;
730-
fci.param_count = 5;
731-
fci.params = argv;
732-
fci.named_params = NULL;
723+
ch->in_callback = true;
724+
zend_call_known_fcc(&ch->handlers.xferinfo, &retval, /* param_count */ 5, argv, /* named_params */ NULL);
725+
ch->in_callback = false;
726+
727+
if (!Z_ISUNDEF(retval)) {
728+
_php_curl_verify_handlers(ch, /* reporterror */ true);
729+
/* TODO Check callback returns an int or something castable to int */
730+
if (0 != zval_get_long(&retval)) {
731+
rval = 1;
732+
}
733+
}
733734

734-
ch->in_callback = 1;
735-
error = zend_call_function(&fci, &t->fci_cache);
736-
ch->in_callback = 0;
737-
if (error == FAILURE) {
738-
php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_XFERINFOFUNCTION");
739-
} else if (!Z_ISUNDEF(retval)) {
740-
_php_curl_verify_handlers(ch, /* reporterror */ true);
741-
if (0 != zval_get_long(&retval)) {
742-
rval = 1;
743-
}
744-
}
745735
zval_ptr_dtor(&argv[0]);
746736
return rval;
747737
}
@@ -1097,7 +1087,7 @@ void init_curl_handle(php_curl *ch)
10971087
ch->handlers.write_header = ecalloc(1, sizeof(php_curl_write));
10981088
ch->handlers.read = ecalloc(1, sizeof(php_curl_read));
10991089
ch->handlers.progress = empty_fcall_info_cache;
1100-
ch->handlers.xferinfo = NULL;
1090+
ch->handlers.xferinfo = empty_fcall_info_cache;
11011091
ch->handlers.fnmatch = NULL;
11021092
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
11031093
ch->handlers.sshhostkey = empty_fcall_info_cache;
@@ -1281,7 +1271,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
12811271
curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *) ch);
12821272

12831273
php_curl_copy_fcc_with_option(ch, CURLOPT_PROGRESSDATA, &ch->handlers.progress, &source->handlers.progress);
1284-
_php_copy_callback(ch, &ch->handlers.xferinfo, source->handlers.xferinfo, CURLOPT_XFERINFODATA);
1274+
php_curl_copy_fcc_with_option(ch, CURLOPT_XFERINFODATA, &ch->handlers.xferinfo, &source->handlers.xferinfo);
12851275
_php_copy_callback(ch, &ch->handlers.fnmatch, source->handlers.fnmatch, CURLOPT_FNMATCH_DATA);
12861276
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
12871277
php_curl_copy_fcc_with_option(ch, CURLOPT_SSH_HOSTKEYDATA, &ch->handlers.sshhostkey, &source->handlers.sshhostkey);
@@ -2160,6 +2150,18 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
21602150
break;
21612151
}
21622152

2153+
case CURLOPT_XFERINFOFUNCTION: {
2154+
/* Check value is actually a callable and set it */
2155+
const char option_name[] = "CURLOPT_XFERINFOFUNCTION";
2156+
bool result = php_curl_set_callable_handler(&ch->handlers.xferinfo, zvalue, is_array_config, option_name);
2157+
if (!result) {
2158+
return FAILURE;
2159+
}
2160+
curl_easy_setopt(ch->cp, CURLOPT_XFERINFOFUNCTION, curl_xferinfo);
2161+
curl_easy_setopt(ch->cp, CURLOPT_XFERINFODATA, ch);
2162+
break;
2163+
}
2164+
21632165
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
21642166
case CURLOPT_SSH_HOSTKEYFUNCTION: {
21652167
/* Check value is actually a callable and set it */
@@ -2200,18 +2202,6 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
22002202
ch->handlers.write->method = PHP_CURL_USER;
22012203
break;
22022204

2203-
case CURLOPT_XFERINFOFUNCTION:
2204-
curl_easy_setopt(ch->cp, CURLOPT_XFERINFOFUNCTION, curl_xferinfo);
2205-
curl_easy_setopt(ch->cp, CURLOPT_XFERINFODATA, ch);
2206-
if (ch->handlers.xferinfo == NULL) {
2207-
ch->handlers.xferinfo = ecalloc(1, sizeof(php_curl_callback));
2208-
} else if (!Z_ISUNDEF(ch->handlers.xferinfo->func_name)) {
2209-
zval_ptr_dtor(&ch->handlers.xferinfo->func_name);
2210-
ch->handlers.xferinfo->fci_cache = empty_fcall_info_cache;
2211-
}
2212-
ZVAL_COPY(&ch->handlers.xferinfo->func_name, zvalue);
2213-
break;
2214-
22152205
/* Curl off_t options */
22162206
case CURLOPT_MAX_RECV_SPEED_LARGE:
22172207
case CURLOPT_MAX_SEND_SPEED_LARGE:
@@ -2852,7 +2842,9 @@ static void curl_free_obj(zend_object *object)
28522842
if (ZEND_FCC_INITIALIZED(ch->handlers.progress)) {
28532843
zend_fcc_dtor(&ch->handlers.progress);
28542844
}
2855-
_php_curl_free_callback(ch->handlers.xferinfo);
2845+
if (ZEND_FCC_INITIALIZED(ch->handlers.xferinfo)) {
2846+
zend_fcc_dtor(&ch->handlers.xferinfo);
2847+
}
28562848
_php_curl_free_callback(ch->handlers.fnmatch);
28572849
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
28582850
if (ZEND_FCC_INITIALIZED(ch->handlers.sshhostkey)) {
@@ -2925,10 +2917,9 @@ static void _php_curl_reset_handlers(php_curl *ch)
29252917
zend_fcc_dtor(&ch->handlers.progress);
29262918
}
29272919

2928-
if (ch->handlers.xferinfo) {
2929-
zval_ptr_dtor(&ch->handlers.xferinfo->func_name);
2930-
efree(ch->handlers.xferinfo);
2931-
ch->handlers.xferinfo = NULL;
2920+
if (ZEND_FCC_INITIALIZED(ch->handlers.xferinfo)) {
2921+
zend_fcc_dtor(&ch->handlers.xferinfo);
2922+
ch->handlers.xferinfo.function_handler = NULL;
29322923
}
29332924

29342925
if (ch->handlers.fnmatch) {

ext/curl/tests/curl_copy_handle_xferinfo.phpt

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,23 @@ Test curl_copy_handle() with CURLOPT_XFERINFOFUNCTION
44
curl
55
--FILE--
66
<?php
7-
include 'server.inc';
8-
$host = curl_cli_server_start();
7+
include 'server.inc';
8+
$host = curl_cli_server_start();
99

10-
$url = "{$host}/get.inc";
11-
$ch = curl_init($url);
10+
$url = "{$host}/get.inc";
11+
$ch = curl_init($url);
1212

13-
curl_setopt($ch, CURLOPT_NOPROGRESS, 0);
14-
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
15-
curl_setopt($ch, CURLOPT_XFERINFOFUNCTION, function() { static $done = false; if (!$done) { echo "Download progress!\n"; $done = true; } });
16-
$ch2 = curl_copy_handle($ch);
17-
echo curl_exec($ch), PHP_EOL;
18-
unset($ch);
19-
echo curl_exec($ch2);
13+
function foo() {
14+
static $done = false; if (!$done) { echo "Download progress!\n"; $done = true; }
15+
}
16+
17+
curl_setopt($ch, CURLOPT_NOPROGRESS, 0);
18+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
19+
curl_setopt($ch, CURLOPT_XFERINFOFUNCTION, 'foo');
20+
$ch2 = curl_copy_handle($ch);
21+
echo curl_exec($ch), PHP_EOL;
22+
unset($ch);
23+
echo curl_exec($ch2);
2024

2125
?>
2226
--EXPECT--

ext/curl/tests/curl_setopt_callables.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ $url = "{$host}/get.inc";
2525
$ch = curl_init($url);
2626
testOption($ch, CURLOPT_PROGRESSFUNCTION);
2727
testOption($ch, CURLOPT_SSH_HOSTKEYFUNCTION);
28+
testOption($ch, CURLOPT_XFERINFOFUNCTION);
2829

2930
?>
3031
--EXPECT--
3132
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_PROGRESSFUNCTION, function "undefined" not found or invalid function name
3233
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_PROGRESSFUNCTION, function "undefined" not found or invalid function name
3334
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_SSH_HOSTKEYFUNCTION, function "undefined" not found or invalid function name
3435
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_SSH_HOSTKEYFUNCTION, function "undefined" not found or invalid function name
36+
TypeError: curl_setopt(): Argument #3 ($value) must be a valid callback for option CURLOPT_XFERINFOFUNCTION, function "undefined" not found or invalid function name
37+
TypeError: curl_setopt_array(): Argument #2 ($options) must be a valid callback for option CURLOPT_XFERINFOFUNCTION, function "undefined" not found or invalid function name

0 commit comments

Comments
 (0)