@@ -1791,11 +1791,30 @@ static void curl_free_post(void **post)
1791
1791
}
1792
1792
/* }}} */
1793
1793
1794
- /* {{{ curl_free_stream
1794
+ struct mime_data_cb_arg {
1795
+ php_curl * ch ;
1796
+ union {
1797
+ zval postfields ;
1798
+ struct {
1799
+ zend_string * filename ;
1800
+ php_stream * stream ;
1801
+ };
1802
+ };
1803
+ };
1804
+
1805
+ /* {{{ curl_free_cb_arg
1795
1806
*/
1796
- static void curl_free_stream (void * * post )
1807
+ static void curl_free_cb_arg (void * * cb_arg_p )
1797
1808
{
1798
- php_stream_close ((php_stream * )* post );
1809
+ struct mime_data_cb_arg * cb_arg = (struct mime_data_cb_arg * ) * cb_arg_p ;
1810
+
1811
+ if (cb_arg -> ch ) {
1812
+ Z_DELREF (cb_arg -> postfields );
1813
+ } else {
1814
+ ZEND_ASSERT (cb_arg -> stream == NULL );
1815
+ zend_string_release (cb_arg -> filename );
1816
+ }
1817
+ efree (cb_arg );
1799
1818
}
1800
1819
/* }}} */
1801
1820
@@ -1896,7 +1915,7 @@ php_curl *alloc_curl_handle()
1896
1915
1897
1916
zend_llist_init (& ch -> to_free -> str , sizeof (char * ), (llist_dtor_func_t )curl_free_string , 0 );
1898
1917
zend_llist_init (& ch -> to_free -> post , sizeof (struct HttpPost * ), (llist_dtor_func_t )curl_free_post , 0 );
1899
- zend_llist_init (& ch -> to_free -> stream , sizeof (php_stream * ), (llist_dtor_func_t )curl_free_stream , 0 );
1918
+ zend_llist_init (& ch -> to_free -> stream , sizeof (struct mime_data_cb_arg * ), (llist_dtor_func_t )curl_free_cb_arg , 0 );
1900
1919
1901
1920
ch -> to_free -> slist = emalloc (sizeof (HashTable ));
1902
1921
zend_hash_init (ch -> to_free -> slist , 4 , NULL , curl_free_slist , 0 );
@@ -2090,62 +2109,71 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
2090
2109
(* source -> clone )++ ;
2091
2110
}
2092
2111
2093
- /* {{{ proto resource curl_copy_handle(resource ch)
2094
- Copy a cURL handle along with all of it's preferences */
2095
- PHP_FUNCTION (curl_copy_handle )
2112
+ #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2113
+ static size_t read_cb (char * buffer , size_t size , size_t nitems , void * arg ) /* {{{ */
2096
2114
{
2097
- CURL * cp ;
2098
- zval * zid ;
2099
- php_curl * ch , * dupch ;
2115
+ struct mime_data_cb_arg * cb_arg = (struct mime_data_cb_arg * ) arg ;
2116
+ ssize_t numread ;
2100
2117
2101
- ZEND_PARSE_PARAMETERS_START (1 ,1 )
2102
- Z_PARAM_RESOURCE (zid )
2103
- ZEND_PARSE_PARAMETERS_END ();
2118
+ ZEND_ASSERT (!cb_arg -> ch );
2104
2119
2105
- if ((ch = (php_curl * )zend_fetch_resource (Z_RES_P (zid ), le_curl_name , le_curl )) == NULL ) {
2106
- RETURN_FALSE ;
2120
+ if (cb_arg -> stream == NULL ) {
2121
+ if (!(cb_arg -> stream = php_stream_open_wrapper (ZSTR_VAL (cb_arg -> filename ), "rb" , IGNORE_PATH , NULL ))) {
2122
+ return CURL_READFUNC_ABORT ;
2123
+ }
2107
2124
}
2108
-
2109
- cp = curl_easy_duphandle (ch -> cp );
2110
- if (!cp ) {
2111
- php_error_docref (NULL , E_WARNING , "Cannot duplicate cURL handle" );
2112
- RETURN_FALSE ;
2125
+ numread = php_stream_read (cb_arg -> stream , buffer , nitems * size );
2126
+ if (numread < 0 ) {
2127
+ php_stream_close (cb_arg -> stream );
2128
+ cb_arg -> stream = NULL ;
2113
2129
}
2130
+ return (numread >= 0 ) ? numread : CURL_READFUNC_ABORT ;
2131
+ }
2132
+ /* }}} */
2114
2133
2115
- dupch = alloc_curl_handle ();
2116
- dupch -> cp = cp ;
2117
-
2118
- _php_setup_easy_copy_handlers ( dupch , ch ) ;
2134
+ static int seek_cb ( void * arg , curl_off_t offset , int origin ) /* {{{ */
2135
+ {
2136
+ struct mime_data_cb_arg * cb_arg = ( struct mime_data_cb_arg * ) arg ;
2137
+ int res ;
2119
2138
2120
- Z_ADDREF_P ( zid );
2139
+ ZEND_ASSERT (! cb_arg -> ch );
2121
2140
2122
- ZVAL_RES (return_value , zend_register_resource (dupch , le_curl ));
2123
- dupch -> res = Z_RES_P (return_value );
2141
+ if (cb_arg -> stream == NULL ) {
2142
+ if (!(cb_arg -> stream = php_stream_open_wrapper (ZSTR_VAL (cb_arg -> filename ), "rb" , IGNORE_PATH , NULL ))) {
2143
+ return CURL_SEEKFUNC_CANTSEEK ;
2144
+ }
2145
+ }
2146
+ res = php_stream_seek (cb_arg -> stream , offset , origin );
2147
+ return res == SUCCESS ? CURL_SEEKFUNC_OK : CURL_SEEKFUNC_CANTSEEK ;
2124
2148
}
2125
2149
/* }}} */
2126
2150
2127
- #if LIBCURL_VERSION_NUM >= 0x073800
2128
- static size_t read_cb (char * buffer , size_t size , size_t nitems , void * arg ) /* {{{ */
2151
+ static void free_cb (void * arg ) /* {{{ */
2129
2152
{
2130
- php_stream * stream = (php_stream * ) arg ;
2131
- ssize_t numread = php_stream_read (stream , buffer , nitems * size );
2153
+ struct mime_data_cb_arg * cb_arg = (struct mime_data_cb_arg * ) arg ;
2132
2154
2133
- if (numread < 0 ) {
2134
- return CURL_READFUNC_ABORT ;
2155
+ ZEND_ASSERT (!cb_arg -> ch );
2156
+
2157
+ if (cb_arg -> stream != NULL ) {
2158
+ php_stream_close (cb_arg -> stream );
2159
+ cb_arg -> stream = NULL ;
2135
2160
}
2136
- return numread ;
2137
2161
}
2138
2162
/* }}} */
2139
2163
2140
- static int seek_cb ( void * arg , curl_off_t offset , int origin ) /* {{{ */
2164
+ static zval * get_postfields_of_handle ( php_curl * ch ) /* {{{ */
2141
2165
{
2142
- php_stream * stream = (php_stream * ) arg ;
2143
- int res = php_stream_seek (stream , offset , origin );
2166
+ struct mime_data_cb_arg * cb_arg , * * cb_arg_p ;
2144
2167
2145
- if (res ) {
2146
- return CURL_SEEKFUNC_CANTSEEK ;
2168
+ cb_arg_p = zend_llist_get_last (& ch -> to_free -> stream );
2169
+ while (cb_arg_p ) {
2170
+ cb_arg = * cb_arg_p ;
2171
+ if (cb_arg -> ch == ch ) {
2172
+ return & cb_arg -> postfields ;
2173
+ }
2174
+ cb_arg_p = zend_llist_get_prev (& ch -> to_free -> stream );
2147
2175
}
2148
- return CURL_SEEKFUNC_OK ;
2176
+ return NULL ;
2149
2177
}
2150
2178
/* }}} */
2151
2179
#endif
@@ -2156,7 +2184,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
2156
2184
zval * current ;
2157
2185
HashTable * postfields ;
2158
2186
zend_string * string_key ;
2159
- zend_ulong num_key ;
2187
+ zend_ulong num_key ;
2160
2188
#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2161
2189
curl_mime * mime = NULL ;
2162
2190
curl_mimepart * part ;
@@ -2198,7 +2226,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
2198
2226
zval * prop , rv ;
2199
2227
char * type = NULL , * filename = NULL ;
2200
2228
#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2201
- php_stream * stream ;
2229
+ struct mime_data_cb_arg * cb_arg ;
2202
2230
#endif
2203
2231
2204
2232
prop = zend_read_property (curl_CURLFile_class , current , "name" , sizeof ("name" )- 1 , 0 , & rv );
@@ -2221,24 +2249,28 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
2221
2249
}
2222
2250
2223
2251
#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2224
- if (!(stream = php_stream_open_wrapper (ZSTR_VAL (postval ), "rb" , IGNORE_PATH , NULL ))) {
2225
- zend_string_release_ex (string_key , 0 );
2226
- return FAILURE ;
2227
- }
2252
+ cb_arg = emalloc (sizeof * cb_arg );
2253
+ cb_arg -> ch = ch ;
2254
+ ZVAL_COPY (& cb_arg -> postfields , zpostfields );
2255
+ zend_llist_add_element (& ch -> to_free -> stream , & cb_arg );
2256
+
2257
+ cb_arg = emalloc (sizeof * cb_arg );
2258
+ cb_arg -> ch = NULL ;
2259
+ cb_arg -> filename = zend_string_copy (postval );
2260
+ cb_arg -> stream = NULL ;
2261
+
2228
2262
part = curl_mime_addpart (mime );
2229
2263
if (part == NULL ) {
2230
- php_stream_close (stream );
2231
2264
zend_string_release_ex (string_key , 0 );
2232
2265
return FAILURE ;
2233
2266
}
2234
2267
if ((form_error = curl_mime_name (part , ZSTR_VAL (string_key ))) != CURLE_OK
2235
- || (form_error = curl_mime_data_cb (part , -1 , read_cb , seek_cb , NULL , stream )) != CURLE_OK
2268
+ || (form_error = curl_mime_data_cb (part , -1 , read_cb , seek_cb , free_cb , cb_arg )) != CURLE_OK
2236
2269
|| (form_error = curl_mime_filename (part , filename ? filename : ZSTR_VAL (postval ))) != CURLE_OK
2237
2270
|| (form_error = curl_mime_type (part , type ? type : "application/octet-stream" )) != CURLE_OK ) {
2238
- php_stream_close (stream );
2239
2271
error = form_error ;
2240
2272
}
2241
- zend_llist_add_element (& ch -> to_free -> stream , & stream );
2273
+ zend_llist_add_element (& ch -> to_free -> stream , & cb_arg );
2242
2274
#else
2243
2275
form_error = curl_formadd (& first , & last ,
2244
2276
CURLFORM_COPYNAME , ZSTR_VAL (string_key ),
@@ -2306,11 +2338,60 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
2306
2338
zend_llist_add_element (& ch -> to_free -> post , & first );
2307
2339
error = curl_easy_setopt (ch -> cp , CURLOPT_HTTPPOST , first );
2308
2340
#endif
2341
+
2309
2342
SAVE_CURL_ERROR (ch , error );
2310
2343
return error == CURLE_OK ? SUCCESS : FAILURE ;
2311
2344
}
2312
2345
/* }}} */
2313
2346
2347
+ /* {{{ proto resource curl_copy_handle(resource ch)
2348
+ Copy a cURL handle along with all of it's preferences */
2349
+ PHP_FUNCTION (curl_copy_handle )
2350
+ {
2351
+ CURL * cp ;
2352
+ zval * zid ;
2353
+ php_curl * ch , * dupch ;
2354
+ #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2355
+ zval * postfields ;
2356
+ #endif
2357
+
2358
+ ZEND_PARSE_PARAMETERS_START (1 ,1 )
2359
+ Z_PARAM_RESOURCE (zid )
2360
+ ZEND_PARSE_PARAMETERS_END ();
2361
+
2362
+ if ((ch = (php_curl * )zend_fetch_resource (Z_RES_P (zid ), le_curl_name , le_curl )) == NULL ) {
2363
+ RETURN_FALSE ;
2364
+ }
2365
+
2366
+ cp = curl_easy_duphandle (ch -> cp );
2367
+ if (!cp ) {
2368
+ php_error_docref (NULL , E_WARNING , "Cannot duplicate cURL handle" );
2369
+ RETURN_FALSE ;
2370
+ }
2371
+
2372
+ dupch = alloc_curl_handle ();
2373
+ dupch -> cp = cp ;
2374
+
2375
+ _php_setup_easy_copy_handlers (dupch , ch );
2376
+
2377
+ #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2378
+ postfields = get_postfields_of_handle (ch );
2379
+ if (postfields ) {
2380
+ if (build_mime_structure_from_hash (dupch , postfields ) != SUCCESS ) {
2381
+ _php_curl_close_ex (dupch );
2382
+ php_error_docref (NULL , E_WARNING , "Cannot rebuild mime structure" );
2383
+ RETURN_FALSE ;
2384
+ }
2385
+ }
2386
+ #endif
2387
+
2388
+ Z_ADDREF_P (zid );
2389
+
2390
+ ZVAL_RES (return_value , zend_register_resource (dupch , le_curl ));
2391
+ dupch -> res = Z_RES_P (return_value );
2392
+ }
2393
+ /* }}} */
2394
+
2314
2395
static int _php_curl_setopt (php_curl * ch , zend_long option , zval * zvalue ) /* {{{ */
2315
2396
{
2316
2397
CURLcode error = CURLE_OK ;
0 commit comments