Skip to content

Commit 20dd09b

Browse files
committed
Add clone support for Curl object
1 parent abb4182 commit 20dd09b

File tree

5 files changed

+80
-17
lines changed

5 files changed

+80
-17
lines changed

ext/curl/interface.c

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "php.h"
2424
#include "Zend/zend_interfaces.h"
25+
#include "Zend/zend_exceptions.h"
2526

2627
#if HAVE_CURL
2728

@@ -239,6 +240,9 @@ static zend_object *curl_create_object(zend_class_entry *class_type);
239240
static void curl_free_obj(zend_object *object);
240241
static HashTable *curl_get_gc(zend_object *object, zval **table, int *n);
241242
static zend_function *curl_get_constructor(zend_object *object);
243+
static zend_object *curl_clone_obj(zend_object *object);
244+
php_curl *alloc_curl_handle_from_zval(zval *curl);
245+
static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields);
242246

243247
static const zend_function_entry curl_object_methods[] = {
244248
PHP_FE_END
@@ -1203,7 +1207,7 @@ PHP_MINIT_FUNCTION(curl)
12031207
curl_object_handlers.free_obj = curl_free_obj;
12041208
curl_object_handlers.get_gc = curl_get_gc;
12051209
curl_object_handlers.get_constructor = curl_get_constructor;
1206-
curl_object_handlers.clone_obj = NULL;
1210+
curl_object_handlers.clone_obj = curl_clone_obj;
12071211

12081212
curl_multi_register_class();
12091213
curl_share_register_class();
@@ -1230,6 +1234,38 @@ static zend_function *curl_get_constructor(zend_object *object) {
12301234
return NULL;
12311235
}
12321236

1237+
static zend_object *curl_clone_obj(zend_object *object) {
1238+
php_curl *ch;
1239+
CURL *cp;
1240+
zval *postfields;
1241+
zend_object *clone_object;
1242+
php_curl *clone_ch;
1243+
1244+
clone_object = curl_create_object(curl_ce);
1245+
clone_ch = curl_from_obj(clone_object);
1246+
clone_ch = alloc_curl_handle(clone_ch);
1247+
1248+
ch = curl_from_obj(object);
1249+
cp = curl_easy_duphandle(ch->cp);
1250+
if (!cp) {
1251+
zend_throw_exception(NULL, "Cannot clone unconstructed Curl object", 0);
1252+
return &clone_ch->std;
1253+
}
1254+
1255+
clone_ch->cp = cp;
1256+
_php_setup_easy_copy_handlers(clone_ch, ch);
1257+
1258+
postfields = &clone_ch->postfields;
1259+
if (Z_TYPE_P(postfields) != IS_UNDEF) {
1260+
if (build_mime_structure_from_hash(clone_ch, postfields) != SUCCESS) {
1261+
zend_throw_exception(NULL, "Cannot clone unconstructed Curl object", 0);
1262+
return &clone_ch->std;
1263+
}
1264+
}
1265+
1266+
return &clone_ch->std;
1267+
}
1268+
12331269
static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
12341270
{
12351271
php_curl *curl = curl_from_obj(object);
@@ -1692,15 +1728,18 @@ PHP_FUNCTION(curl_version)
16921728
}
16931729
/* }}} */
16941730

1695-
/* {{{ alloc_curl_handle
1696-
*/
1697-
php_curl *alloc_curl_handle(zval *curl)
1731+
php_curl *alloc_curl_handle_from_zval(zval *curl)
16981732
{
16991733
php_curl *ch;
17001734

17011735
object_init_ex(curl, curl_ce);
17021736
ch = Z_CURL_P(curl);
17031737

1738+
return alloc_curl_handle(ch);
1739+
}
1740+
1741+
php_curl *alloc_curl_handle(php_curl *ch)
1742+
{
17041743
ch->to_free = ecalloc(1, sizeof(struct _php_curl_free));
17051744
ch->handlers = ecalloc(1, sizeof(php_curl_handlers));
17061745
ch->handlers->write = ecalloc(1, sizeof(php_curl_write));
@@ -1723,6 +1762,7 @@ php_curl *alloc_curl_handle(zval *curl)
17231762

17241763
return ch;
17251764
}
1765+
17261766
/* }}} */
17271767

17281768
/* {{{ create_certinfo
@@ -1813,7 +1853,7 @@ PHP_FUNCTION(curl_init)
18131853
RETURN_FALSE;
18141854
}
18151855

1816-
ch = alloc_curl_handle(return_value);
1856+
ch = alloc_curl_handle_from_zval(return_value);
18171857

18181858
ch->cp = cp;
18191859

@@ -2123,7 +2163,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
21232163
Copy a cURL handle along with all of it's preferences */
21242164
PHP_FUNCTION(curl_copy_handle)
21252165
{
2126-
php_curl *ch;
2166+
php_curl *ch;
21272167
CURL *cp;
21282168
zval *zid;
21292169
php_curl *dupch;
@@ -2141,7 +2181,7 @@ PHP_FUNCTION(curl_copy_handle)
21412181
RETURN_FALSE;
21422182
}
21432183

2144-
dupch = alloc_curl_handle(return_value);
2184+
dupch = alloc_curl_handle_from_zval(return_value);
21452185
dupch->cp = cp;
21462186

21472187
_php_setup_easy_copy_handlers(dupch, ch);

ext/curl/multi.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,8 @@ void _php_curl_multi_cleanup_list(void *data) /* {{{ */
114114
if (!z_ch) {
115115
return;
116116
}
117-
if (!Z_RES_P(z_ch)->ptr) {
118-
return;
119-
}
120117

121-
zend_list_delete(Z_RES_P(z_ch));
118+
zval_ptr_dtor(z_ch);
122119
}
123120
/* }}} */
124121

@@ -401,7 +398,7 @@ static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_hea
401398

402399
parent = Z_CURL_P(pz_parent_ch);
403400

404-
ch = alloc_curl_handle(&pz_ch);
401+
ch = alloc_curl_handle_from_zval(&pz_ch);
405402
ch->cp = easy;
406403
_php_setup_easy_copy_handlers(ch, parent);
407404

ext/curl/php_curl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ typedef struct {
151151
zend_object std;
152152
} php_curlsh;
153153

154-
php_curl *alloc_curl_handle(zval *curl);
154+
php_curl *alloc_curl_handle_from_zval(zval *curl);
155+
php_curl *alloc_curl_handle(php_curl *ch);
155156
void _php_curl_cleanup_handle(php_curl *);
156157
void _php_curl_multi_cleanup_list(void *data);
157158
void _php_curl_verify_handlers(php_curl *ch, int reporterror);

ext/curl/tests/curl_handle_clone.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Test that cloning of Curl objects is supported
3+
--SKIPIF--
4+
<?php include 'skipif.inc'; ?>
5+
--FILE--
6+
<?php
7+
8+
include 'server.inc';
9+
$host = curl_cli_server_start();
10+
11+
$ch1 = curl_init();
12+
curl_setopt($ch1, CURLOPT_URL, $host);
13+
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
14+
curl_exec($ch1);
15+
16+
$ch2 = clone $ch1;
17+
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 0);
18+
19+
var_dump(curl_getinfo($ch1, CURLINFO_EFFECTIVE_URL) === curl_getinfo($ch2, CURLINFO_EFFECTIVE_URL));
20+
curl_exec($ch2);
21+
22+
?>
23+
--EXPECT--
24+
bool(true)
25+
Hello World!
26+
Hello World!

ext/posix/tests/posix_ttyname_error_wrongparams.phpt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,15 @@ PHP Testfest Berlin 2009-05-10
1212
if (!extension_loaded('posix')) {
1313
die('SKIP - POSIX extension not available');
1414
}
15-
16-
if (!function_exists('curl_init')) {
17-
die('SKIP - Function curl_init() not available');
15+
if (!extension_loaded('sockets')) {
16+
die('SKIP - Sockets extension not available');
1817
}
1918
?>
2019
--FILE--
2120
<?php
2221
var_dump(posix_ttyname(0)); // param not a resource
2322
try {
24-
var_dump(posix_ttyname(curl_init())); // wrong resource type
23+
var_dump(posix_ttyname(socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))); // wrong resource type
2524
} catch (TypeError $e) {
2625
echo $e->getMessage(), "\n";
2726
}

0 commit comments

Comments
 (0)