@@ -1795,11 +1795,20 @@ static void curl_free_post(void **post)
17951795}
17961796/* }}} */
17971797
1798- /* {{{ curl_free_stream
1798+ struct mime_data_cb_arg {
1799+ zend_string * filename ;
1800+ php_stream * stream ;
1801+ };
1802+
1803+ /* {{{ curl_free_cb_arg
17991804 */
1800- static void curl_free_stream (void * * post )
1805+ static void curl_free_cb_arg (void * * cb_arg_p )
18011806{
1802- php_stream_close ((php_stream * )* post );
1807+ struct mime_data_cb_arg * cb_arg = (struct mime_data_cb_arg * ) * cb_arg_p ;
1808+
1809+ ZEND_ASSERT (cb_arg -> stream == NULL );
1810+ zend_string_release (cb_arg -> filename );
1811+ efree (cb_arg );
18031812}
18041813/* }}} */
18051814
@@ -1900,11 +1909,13 @@ php_curl *alloc_curl_handle()
19001909
19011910 zend_llist_init (& ch -> to_free -> str , sizeof (char * ), (llist_dtor_func_t )curl_free_string , 0 );
19021911 zend_llist_init (& ch -> to_free -> post , sizeof (struct HttpPost * ), (llist_dtor_func_t )curl_free_post , 0 );
1903- zend_llist_init (& ch -> to_free -> stream , sizeof (php_stream * ), (llist_dtor_func_t )curl_free_stream , 0 );
1912+ zend_llist_init (& ch -> to_free -> stream , sizeof (struct mime_data_cb_arg * ), (llist_dtor_func_t )curl_free_cb_arg , 0 );
19041913
19051914 ch -> to_free -> slist = emalloc (sizeof (HashTable ));
19061915 zend_hash_init (ch -> to_free -> slist , 4 , NULL , curl_free_slist , 0 );
1907-
1916+ #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
1917+ ZVAL_UNDEF (& ch -> postfields );
1918+ #endif
19081919 return ch ;
19091920}
19101921/* }}} */
@@ -2094,62 +2105,48 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
20942105 (* source -> clone )++ ;
20952106}
20962107
2097- /* {{{ proto resource curl_copy_handle(resource ch)
2098- Copy a cURL handle along with all of it's preferences */
2099- PHP_FUNCTION (curl_copy_handle )
2108+ #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2109+ static size_t read_cb (char * buffer , size_t size , size_t nitems , void * arg ) /* {{{ */
21002110{
2101- CURL * cp ;
2102- zval * zid ;
2103- php_curl * ch , * dupch ;
2104-
2105- ZEND_PARSE_PARAMETERS_START (1 ,1 )
2106- Z_PARAM_RESOURCE (zid )
2107- ZEND_PARSE_PARAMETERS_END ();
2111+ struct mime_data_cb_arg * cb_arg = (struct mime_data_cb_arg * ) arg ;
2112+ ssize_t numread ;
21082113
2109- if ((ch = (php_curl * )zend_fetch_resource (Z_RES_P (zid ), le_curl_name , le_curl )) == NULL ) {
2110- RETURN_FALSE ;
2114+ if (cb_arg -> stream == NULL ) {
2115+ if (!(cb_arg -> stream = php_stream_open_wrapper (ZSTR_VAL (cb_arg -> filename ), "rb" , IGNORE_PATH , NULL ))) {
2116+ return CURL_READFUNC_ABORT ;
2117+ }
21112118 }
2112-
2113- cp = curl_easy_duphandle ( ch -> cp );
2114- if (! cp ) {
2115- php_error_docref ( NULL , E_WARNING , "Cannot duplicate cURL handle" ) ;
2116- RETURN_FALSE ;
2119+ numread = php_stream_read ( cb_arg -> stream , buffer , nitems * size );
2120+ if ( numread < 0 ) {
2121+ php_stream_close ( cb_arg -> stream );
2122+ cb_arg -> stream = NULL ;
2123+ return CURL_READFUNC_ABORT ;
21172124 }
2118-
2119- dupch = alloc_curl_handle ();
2120- dupch -> cp = cp ;
2121-
2122- _php_setup_easy_copy_handlers (dupch , ch );
2123-
2124- Z_ADDREF_P (zid );
2125-
2126- ZVAL_RES (return_value , zend_register_resource (dupch , le_curl ));
2127- dupch -> res = Z_RES_P (return_value );
2125+ return numread ;
21282126}
21292127/* }}} */
21302128
2131- #if LIBCURL_VERSION_NUM >= 0x073800
2132- static size_t read_cb (char * buffer , size_t size , size_t nitems , void * arg ) /* {{{ */
2129+ static int seek_cb (void * arg , curl_off_t offset , int origin ) /* {{{ */
21332130{
2134- php_stream * stream = (php_stream * ) arg ;
2135- ssize_t numread = php_stream_read ( stream , buffer , nitems * size ) ;
2131+ struct mime_data_cb_arg * cb_arg = (struct mime_data_cb_arg * ) arg ;
2132+ int res ;
21362133
2137- if (numread < 0 ) {
2138- return CURL_READFUNC_ABORT ;
2134+ if (cb_arg -> stream == NULL ) {
2135+ return CURL_SEEKFUNC_CANTSEEK ;
21392136 }
2140- return numread ;
2137+ res = php_stream_seek (cb_arg -> stream , offset , origin );
2138+ return res == SUCCESS ? CURL_SEEKFUNC_OK : CURL_SEEKFUNC_CANTSEEK ;
21412139}
21422140/* }}} */
21432141
2144- static int seek_cb (void * arg , curl_off_t offset , int origin ) /* {{{ */
2142+ static void free_cb (void * arg ) /* {{{ */
21452143{
2146- php_stream * stream = (php_stream * ) arg ;
2147- int res = php_stream_seek (stream , offset , origin );
2144+ struct mime_data_cb_arg * cb_arg = (struct mime_data_cb_arg * ) arg ;
21482145
2149- if (res ) {
2150- return CURL_SEEKFUNC_CANTSEEK ;
2146+ if (cb_arg -> stream != NULL ) {
2147+ php_stream_close (cb_arg -> stream );
2148+ cb_arg -> stream = NULL ;
21512149 }
2152- return CURL_SEEKFUNC_OK ;
21532150}
21542151/* }}} */
21552152#endif
@@ -2160,7 +2157,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
21602157 zval * current ;
21612158 HashTable * postfields ;
21622159 zend_string * string_key ;
2163- zend_ulong num_key ;
2160+ zend_ulong num_key ;
21642161#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
21652162 curl_mime * mime = NULL ;
21662163 curl_mimepart * part ;
@@ -2202,7 +2199,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
22022199 zval * prop , rv ;
22032200 char * type = NULL , * filename = NULL ;
22042201#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2205- php_stream * stream ;
2202+ struct mime_data_cb_arg * cb_arg ;
22062203#endif
22072204
22082205 prop = zend_read_property (curl_CURLFile_class , current , "name" , sizeof ("name" )- 1 , 0 , & rv );
@@ -2225,24 +2222,25 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
22252222 }
22262223
22272224#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2228- if (!(stream = php_stream_open_wrapper (ZSTR_VAL (postval ), "rb" , IGNORE_PATH , NULL ))) {
2229- zend_string_release_ex (string_key , 0 );
2230- return FAILURE ;
2231- }
2225+ zval_ptr_dtor (& ch -> postfields );
2226+ ZVAL_COPY (& ch -> postfields , zpostfields );
2227+
2228+ cb_arg = emalloc (sizeof * cb_arg );
2229+ cb_arg -> filename = zend_string_copy (postval );
2230+ cb_arg -> stream = NULL ;
2231+
22322232 part = curl_mime_addpart (mime );
22332233 if (part == NULL ) {
2234- php_stream_close (stream );
22352234 zend_string_release_ex (string_key , 0 );
22362235 return FAILURE ;
22372236 }
22382237 if ((form_error = curl_mime_name (part , ZSTR_VAL (string_key ))) != CURLE_OK
2239- || (form_error = curl_mime_data_cb (part , -1 , read_cb , seek_cb , NULL , stream )) != CURLE_OK
2238+ || (form_error = curl_mime_data_cb (part , -1 , read_cb , seek_cb , free_cb , cb_arg )) != CURLE_OK
22402239 || (form_error = curl_mime_filename (part , filename ? filename : ZSTR_VAL (postval ))) != CURLE_OK
22412240 || (form_error = curl_mime_type (part , type ? type : "application/octet-stream" )) != CURLE_OK ) {
2242- php_stream_close (stream );
22432241 error = form_error ;
22442242 }
2245- zend_llist_add_element (& ch -> to_free -> stream , & stream );
2243+ zend_llist_add_element (& ch -> to_free -> stream , & cb_arg );
22462244#else
22472245 form_error = curl_formadd (& first , & last ,
22482246 CURLFORM_COPYNAME , ZSTR_VAL (string_key ),
@@ -2310,11 +2308,60 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
23102308 zend_llist_add_element (& ch -> to_free -> post , & first );
23112309 error = curl_easy_setopt (ch -> cp , CURLOPT_HTTPPOST , first );
23122310#endif
2311+
23132312 SAVE_CURL_ERROR (ch , error );
23142313 return error == CURLE_OK ? SUCCESS : FAILURE ;
23152314}
23162315/* }}} */
23172316
2317+ /* {{{ proto resource curl_copy_handle(resource ch)
2318+ Copy a cURL handle along with all of it's preferences */
2319+ PHP_FUNCTION (curl_copy_handle )
2320+ {
2321+ CURL * cp ;
2322+ zval * zid ;
2323+ php_curl * ch , * dupch ;
2324+ #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2325+ zval * postfields ;
2326+ #endif
2327+
2328+ ZEND_PARSE_PARAMETERS_START (1 ,1 )
2329+ Z_PARAM_RESOURCE (zid )
2330+ ZEND_PARSE_PARAMETERS_END ();
2331+
2332+ if ((ch = (php_curl * )zend_fetch_resource (Z_RES_P (zid ), le_curl_name , le_curl )) == NULL ) {
2333+ RETURN_FALSE ;
2334+ }
2335+
2336+ cp = curl_easy_duphandle (ch -> cp );
2337+ if (!cp ) {
2338+ php_error_docref (NULL , E_WARNING , "Cannot duplicate cURL handle" );
2339+ RETURN_FALSE ;
2340+ }
2341+
2342+ dupch = alloc_curl_handle ();
2343+ dupch -> cp = cp ;
2344+
2345+ _php_setup_easy_copy_handlers (dupch , ch );
2346+
2347+ #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2348+ postfields = & ch -> postfields ;
2349+ if (Z_TYPE_P (postfields ) != IS_UNDEF ) {
2350+ if (build_mime_structure_from_hash (dupch , postfields ) != SUCCESS ) {
2351+ _php_curl_close_ex (dupch );
2352+ php_error_docref (NULL , E_WARNING , "Cannot rebuild mime structure" );
2353+ RETURN_FALSE ;
2354+ }
2355+ }
2356+ #endif
2357+
2358+ Z_ADDREF_P (zid );
2359+
2360+ ZVAL_RES (return_value , zend_register_resource (dupch , le_curl ));
2361+ dupch -> res = Z_RES_P (return_value );
2362+ }
2363+ /* }}} */
2364+
23182365static int _php_curl_setopt (php_curl * ch , zend_long option , zval * zvalue ) /* {{{ */
23192366{
23202367 CURLcode error = CURLE_OK ;
@@ -3613,6 +3660,9 @@ static void _php_curl_close_ex(php_curl *ch)
36133660#endif
36143661
36153662 efree (ch -> handlers );
3663+ #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
3664+ zval_ptr_dtor (& ch -> postfields );
3665+ #endif
36163666 efree (ch );
36173667}
36183668/* }}} */
0 commit comments