Skip to content

Commit 0d5d970

Browse files
committed
CURL extension update proposal.
Allowing using CURLOPT_XFERINFOFUNCTION while deprecating CURLOPT_PROGRESSFUNCTION, available since the 7.32 release.
1 parent 8683d17 commit 0d5d970

File tree

5 files changed

+117
-6
lines changed

5 files changed

+117
-6
lines changed

ext/curl/curl_private.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,8 @@ typedef struct {
7373
php_curl_read *read;
7474
zval std_err;
7575
php_curl_callback *progress;
76-
#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
76+
php_curl_callback *xferinfo;
7777
php_curl_callback *fnmatch;
78-
#endif
7978
} php_curl_handlers;
8079

8180
struct _php_curl_error {

ext/curl/interface.c

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ PHP_MINIT_FUNCTION(curl)
456456
REGISTER_CURL_CONSTANT(CURLOPT_VERBOSE);
457457
REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION);
458458
REGISTER_CURL_CONSTANT(CURLOPT_WRITEHEADER);
459+
REGISTER_CURL_CONSTANT(CURLOPT_XFERINFOFUNCTION);
459460

460461
/* */
461462
REGISTER_CURL_CONSTANT(CURLE_ABORTED_BY_CALLBACK);
@@ -1287,11 +1288,13 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
12871288
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.progress->func_name);
12881289
}
12891290

1290-
#if LIBCURL_VERSION_NUM >= 0x071500
1291+
if (curl->handlers.xferinfo) {
1292+
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.xferinfo->func_name);
1293+
}
1294+
12911295
if (curl->handlers.fnmatch) {
12921296
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.fnmatch->func_name);
12931297
}
1294-
#endif
12951298

12961299
zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.std_err);
12971300
zend_get_gc_buffer_add_zval(gc_buffer, &curl->private_data);
@@ -1496,6 +1499,54 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double
14961499
}
14971500
/* }}} */
14981501

1502+
/* {{{ curl_xferinfo */
1503+
static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
1504+
{
1505+
php_curl *ch = (php_curl *)clientp;
1506+
php_curl_callback *t = ch->handlers.xferinfo;
1507+
size_t rval = 0;
1508+
1509+
#if PHP_CURL_DEBUG
1510+
fprintf(stderr, "curl_xferinfo() called\n");
1511+
fprintf(stderr, "clientp = %x, dltotal = %ld, dlnow = %ld, ultotal = %ld, ulnow = %ld\n", clientp, dltotal, dlnow, ultotal, ulnow);
1512+
#endif
1513+
1514+
zval argv[5];
1515+
zval retval;
1516+
zend_result error;
1517+
zend_fcall_info fci;
1518+
1519+
GC_ADDREF(&ch->std);
1520+
ZVAL_OBJ(&argv[0], &ch->std);
1521+
ZVAL_LONG(&argv[1], dltotal);
1522+
ZVAL_LONG(&argv[2], dlnow);
1523+
ZVAL_LONG(&argv[3], ultotal);
1524+
ZVAL_LONG(&argv[4], ulnow);
1525+
1526+
fci.size = sizeof(fci);
1527+
ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1528+
fci.object = NULL;
1529+
fci.retval = &retval;
1530+
fci.param_count = 5;
1531+
fci.params = argv;
1532+
fci.named_params = NULL;
1533+
1534+
ch->in_callback = 1;
1535+
error = zend_call_function(&fci, &t->fci_cache);
1536+
ch->in_callback = 0;
1537+
if (error == FAILURE) {
1538+
php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_XFERINFOFUNCTION");
1539+
} else if (!Z_ISUNDEF(retval)) {
1540+
_php_curl_verify_handlers(ch, /* reporterror */ true);
1541+
if (0 != zval_get_long(&retval)) {
1542+
rval = 1;
1543+
}
1544+
}
1545+
zval_ptr_dtor(&argv[0]);
1546+
return rval;
1547+
}
1548+
/* }}} */
1549+
14991550
/* {{{ curl_read */
15001551
static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
15011552
{
@@ -1753,6 +1804,7 @@ void init_curl_handle(php_curl *ch)
17531804
ch->handlers.write_header = ecalloc(1, sizeof(php_curl_write));
17541805
ch->handlers.read = ecalloc(1, sizeof(php_curl_read));
17551806
ch->handlers.progress = NULL;
1807+
ch->handlers.xferinfo = NULL;
17561808
ch->handlers.fnmatch = NULL;
17571809
ch->clone = emalloc(sizeof(uint32_t));
17581810
*ch->clone = 1;
@@ -1925,6 +1977,14 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
19251977
curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, (void *) ch);
19261978
}
19271979

1980+
if (source->handlers.xferinfo) {
1981+
ch->handlers.xferinfo = ecalloc(1, sizeof(php_curl_callback));
1982+
if (!Z_ISUNDEF(source->handlers.xferinfo->func_name)) {
1983+
ZVAL_COPY(&ch->handlers.xferinfo->func_name, &source->handlers.xferinfo->func_name);
1984+
}
1985+
curl_easy_setopt(ch->cp, CURLOPT_XFERINFODATA, (void *) ch);
1986+
}
1987+
19281988
if (source->handlers.fnmatch) {
19291989
ch->handlers.fnmatch = ecalloc(1, sizeof(php_curl_callback));
19301990
if (!Z_ISUNDEF(source->handlers.fnmatch->func_name)) {
@@ -2825,6 +2885,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
28252885
ch->handlers.progress->fci_cache = empty_fcall_info_cache;
28262886
}
28272887
ZVAL_COPY(&ch->handlers.progress->func_name, zvalue);
2888+
php_error_docref(NULL, E_DEPRECATED, "CURLOPT_PROGRESSFUNCTION is deprecated");
28282889
break;
28292890

28302891
case CURLOPT_READFUNCTION:
@@ -2853,6 +2914,18 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
28532914
ch->handlers.write->method = PHP_CURL_USER;
28542915
break;
28552916

2917+
case CURLOPT_XFERINFOFUNCTION:
2918+
curl_easy_setopt(ch->cp, CURLOPT_XFERINFOFUNCTION, curl_xferinfo);
2919+
curl_easy_setopt(ch->cp, CURLOPT_XFERINFODATA, ch);
2920+
if (ch->handlers.xferinfo == NULL) {
2921+
ch->handlers.xferinfo = ecalloc(1, sizeof(php_curl_callback));
2922+
} else if (!Z_ISUNDEF(ch->handlers.xferinfo->func_name)) {
2923+
zval_ptr_dtor(&ch->handlers.xferinfo->func_name);
2924+
ch->handlers.xferinfo->fci_cache = empty_fcall_info_cache;
2925+
}
2926+
ZVAL_COPY(&ch->handlers.xferinfo->func_name, zvalue);
2927+
break;
2928+
28562929
/* Curl off_t options */
28572930
case CURLOPT_MAX_RECV_SPEED_LARGE:
28582931
case CURLOPT_MAX_SEND_SPEED_LARGE:
@@ -3490,6 +3563,11 @@ static void curl_free_obj(zend_object *object)
34903563
efree(ch->handlers.progress);
34913564
}
34923565

3566+
if (ch->handlers.xferinfo) {
3567+
zval_ptr_dtor(&ch->handlers.xferinfo->func_name);
3568+
efree(ch->handlers.xferinfo);
3569+
}
3570+
34933571
if (ch->handlers.fnmatch) {
34943572
zval_ptr_dtor(&ch->handlers.fnmatch->func_name);
34953573
efree(ch->handlers.fnmatch);
@@ -3562,12 +3640,17 @@ static void _php_curl_reset_handlers(php_curl *ch)
35623640
ch->handlers.progress = NULL;
35633641
}
35643642

3643+
if (ch->handlers.xferinfo) {
3644+
zval_ptr_dtor(&ch->handlers.xferinfo->func_name);
3645+
efree(ch->handlers.xferinfo);
3646+
ch->handlers.xferinfo = NULL;
3647+
}
3648+
35653649
if (ch->handlers.fnmatch) {
35663650
zval_ptr_dtor(&ch->handlers.fnmatch->func_name);
35673651
efree(ch->handlers.fnmatch);
35683652
ch->handlers.fnmatch = NULL;
35693653
}
3570-
35713654
}
35723655
/* }}} */
35733656

ext/curl/sync-constants.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
const MIN_SUPPORTED_CURL_VERSION = '7.29.0';
1616

1717
const IGNORED_CONSTANTS = [
18-
'CURLOPT_PROGRESSDATA'
18+
'CURLOPT_PROGRESSDATA',
19+
'CURLOPT_XFERINFODATA'
1920
];
2021

2122
const CONSTANTS_REGEX_PATTERN = '~^CURL(?:OPT|_VERSION)_[A-Z0-9_]+$~';

ext/curl/tests/curl_copy_handle_basic_008.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Test curl_copy_handle() with CURLOPT_PROGRESSFUNCTION
33
--EXTENSIONS--
44
curl
5+
--INI--
6+
error_reporting=E_ALL&~E_DEPRECATED
57
--FILE--
68
<?php
79
include 'server.inc';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Test curl_copy_handle() with CURLOPT_XFERINFOFUNCTION
3+
--EXTENSIONS--
4+
curl
5+
--FILE--
6+
<?php
7+
include 'server.inc';
8+
$host = curl_cli_server_start();
9+
10+
$url = "{$host}/get.inc";
11+
$ch = curl_init($url);
12+
13+
curl_setopt($ch, CURLOPT_NOPROGRESS, 0);
14+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
15+
curl_setopt($ch, CURLOPT_XFERINFOFUNCTION, function() { });
16+
$ch2 = curl_copy_handle($ch);
17+
echo curl_exec($ch), PHP_EOL;
18+
unset($ch);
19+
echo curl_exec($ch2);
20+
21+
?>
22+
--EXPECT--
23+
Hello World!
24+
Hello World!
25+
Hello World!
26+
Hello World!

0 commit comments

Comments
 (0)