Skip to content

Commit

Permalink
Add clone support for Curl object
Browse files Browse the repository at this point in the history
  • Loading branch information
kocsismate committed Apr 24, 2020
1 parent abb4182 commit 20dd09b
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 17 deletions.
54 changes: 47 additions & 7 deletions ext/curl/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "php.h"
#include "Zend/zend_interfaces.h"
#include "Zend/zend_exceptions.h"

#if HAVE_CURL

Expand Down Expand Up @@ -239,6 +240,9 @@ static zend_object *curl_create_object(zend_class_entry *class_type);
static void curl_free_obj(zend_object *object);
static HashTable *curl_get_gc(zend_object *object, zval **table, int *n);
static zend_function *curl_get_constructor(zend_object *object);
static zend_object *curl_clone_obj(zend_object *object);
php_curl *alloc_curl_handle_from_zval(zval *curl);
static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields);

static const zend_function_entry curl_object_methods[] = {
PHP_FE_END
Expand Down Expand Up @@ -1203,7 +1207,7 @@ PHP_MINIT_FUNCTION(curl)
curl_object_handlers.free_obj = curl_free_obj;
curl_object_handlers.get_gc = curl_get_gc;
curl_object_handlers.get_constructor = curl_get_constructor;
curl_object_handlers.clone_obj = NULL;
curl_object_handlers.clone_obj = curl_clone_obj;

curl_multi_register_class();
curl_share_register_class();
Expand All @@ -1230,6 +1234,38 @@ static zend_function *curl_get_constructor(zend_object *object) {
return NULL;
}

static zend_object *curl_clone_obj(zend_object *object) {
php_curl *ch;
CURL *cp;
zval *postfields;
zend_object *clone_object;
php_curl *clone_ch;

clone_object = curl_create_object(curl_ce);
clone_ch = curl_from_obj(clone_object);
clone_ch = alloc_curl_handle(clone_ch);

ch = curl_from_obj(object);
cp = curl_easy_duphandle(ch->cp);
if (!cp) {
zend_throw_exception(NULL, "Cannot clone unconstructed Curl object", 0);
return &clone_ch->std;
}

clone_ch->cp = cp;
_php_setup_easy_copy_handlers(clone_ch, ch);

postfields = &clone_ch->postfields;
if (Z_TYPE_P(postfields) != IS_UNDEF) {
if (build_mime_structure_from_hash(clone_ch, postfields) != SUCCESS) {
zend_throw_exception(NULL, "Cannot clone unconstructed Curl object", 0);
return &clone_ch->std;
}
}

return &clone_ch->std;
}

static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
{
php_curl *curl = curl_from_obj(object);
Expand Down Expand Up @@ -1692,15 +1728,18 @@ PHP_FUNCTION(curl_version)
}
/* }}} */

/* {{{ alloc_curl_handle
*/
php_curl *alloc_curl_handle(zval *curl)
php_curl *alloc_curl_handle_from_zval(zval *curl)
{
php_curl *ch;

object_init_ex(curl, curl_ce);
ch = Z_CURL_P(curl);

return alloc_curl_handle(ch);
}

php_curl *alloc_curl_handle(php_curl *ch)
{
ch->to_free = ecalloc(1, sizeof(struct _php_curl_free));
ch->handlers = ecalloc(1, sizeof(php_curl_handlers));
ch->handlers->write = ecalloc(1, sizeof(php_curl_write));
Expand All @@ -1723,6 +1762,7 @@ php_curl *alloc_curl_handle(zval *curl)

return ch;
}

/* }}} */

/* {{{ create_certinfo
Expand Down Expand Up @@ -1813,7 +1853,7 @@ PHP_FUNCTION(curl_init)
RETURN_FALSE;
}

ch = alloc_curl_handle(return_value);
ch = alloc_curl_handle_from_zval(return_value);

ch->cp = cp;

Expand Down Expand Up @@ -2123,7 +2163,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
Copy a cURL handle along with all of it's preferences */
PHP_FUNCTION(curl_copy_handle)
{
php_curl *ch;
php_curl *ch;
CURL *cp;
zval *zid;
php_curl *dupch;
Expand All @@ -2141,7 +2181,7 @@ PHP_FUNCTION(curl_copy_handle)
RETURN_FALSE;
}

dupch = alloc_curl_handle(return_value);
dupch = alloc_curl_handle_from_zval(return_value);
dupch->cp = cp;

_php_setup_easy_copy_handlers(dupch, ch);
Expand Down
7 changes: 2 additions & 5 deletions ext/curl/multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,8 @@ void _php_curl_multi_cleanup_list(void *data) /* {{{ */
if (!z_ch) {
return;
}
if (!Z_RES_P(z_ch)->ptr) {
return;
}

zend_list_delete(Z_RES_P(z_ch));
zval_ptr_dtor(z_ch);
}
/* }}} */

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

parent = Z_CURL_P(pz_parent_ch);

ch = alloc_curl_handle(&pz_ch);
ch = alloc_curl_handle_from_zval(&pz_ch);
ch->cp = easy;
_php_setup_easy_copy_handlers(ch, parent);

Expand Down
3 changes: 2 additions & 1 deletion ext/curl/php_curl.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ typedef struct {
zend_object std;
} php_curlsh;

php_curl *alloc_curl_handle(zval *curl);
php_curl *alloc_curl_handle_from_zval(zval *curl);
php_curl *alloc_curl_handle(php_curl *ch);
void _php_curl_cleanup_handle(php_curl *);
void _php_curl_multi_cleanup_list(void *data);
void _php_curl_verify_handlers(php_curl *ch, int reporterror);
Expand Down
26 changes: 26 additions & 0 deletions ext/curl/tests/curl_handle_clone.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
Test that cloning of Curl objects is supported
--SKIPIF--
<?php include 'skipif.inc'; ?>
--FILE--
<?php

include 'server.inc';
$host = curl_cli_server_start();

$ch1 = curl_init();
curl_setopt($ch1, CURLOPT_URL, $host);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
curl_exec($ch1);

$ch2 = clone $ch1;
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 0);

var_dump(curl_getinfo($ch1, CURLINFO_EFFECTIVE_URL) === curl_getinfo($ch2, CURLINFO_EFFECTIVE_URL));
curl_exec($ch2);

?>
--EXPECT--
bool(true)
Hello World!
Hello World!
7 changes: 3 additions & 4 deletions ext/posix/tests/posix_ttyname_error_wrongparams.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@ PHP Testfest Berlin 2009-05-10
if (!extension_loaded('posix')) {
die('SKIP - POSIX extension not available');
}

if (!function_exists('curl_init')) {
die('SKIP - Function curl_init() not available');
if (!extension_loaded('sockets')) {
die('SKIP - Sockets extension not available');
}
?>
--FILE--
<?php
var_dump(posix_ttyname(0)); // param not a resource
try {
var_dump(posix_ttyname(curl_init())); // wrong resource type
var_dump(posix_ttyname(socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))); // wrong resource type
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
Expand Down

0 comments on commit 20dd09b

Please sign in to comment.