@@ -496,6 +496,12 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
496
496
zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .xferinfo -> func_name );
497
497
}
498
498
499
+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
500
+ if (curl -> handlers .prereq ) {
501
+ zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .prereq -> func_name );
502
+ }
503
+ #endif
504
+
499
505
if (curl -> handlers .fnmatch ) {
500
506
zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .fnmatch -> func_name );
501
507
}
@@ -939,6 +945,64 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx
939
945
}
940
946
/* }}} */
941
947
948
+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
949
+ static int curl_prereqfunction (void * clientp , char * conn_primary_ip , char * conn_local_ip , int conn_primary_port , int conn_local_port )
950
+ {
951
+ php_curl * ch = (php_curl * )clientp ;
952
+ php_curl_callback * t = ch -> handlers .prereq ;
953
+
954
+ int rval = CURL_PREREQFUNC_ABORT ; /* Disallow the request by default. */
955
+
956
+ #if PHP_CURL_DEBUG
957
+ fprintf (stderr , "curl_prereqfunction() called\n" );
958
+ fprintf (stderr , "clientp = %x, conn_primary_ip = %s, conn_local_ip = %s, conn_primary_port = %d, conn_local_port = %d\n" , clientp , conn_primary_ip , conn_local_ip , c , onn_primary_port , conn_local_port );
959
+ #endif
960
+
961
+ zval argv [5 ];
962
+ zval retval ;
963
+
964
+ zend_fcall_info fci ;
965
+
966
+ GC_ADDREF (& ch -> std );
967
+ ZVAL_OBJ (& argv [0 ], & ch -> std );
968
+ ZVAL_STRING (& argv [1 ], conn_primary_ip );
969
+ ZVAL_STRING (& argv [2 ], conn_local_ip );
970
+ ZVAL_LONG (& argv [3 ], conn_primary_port );
971
+ ZVAL_LONG (& argv [4 ], conn_local_port );
972
+
973
+ fci .size = sizeof (fci );
974
+ ZVAL_COPY_VALUE (& fci .function_name , & t -> func_name );
975
+ fci .object = NULL ;
976
+ fci .retval = & retval ;
977
+ fci .param_count = 5 ;
978
+ fci .params = argv ;
979
+ fci .named_params = NULL ;
980
+
981
+ ch -> in_callback = 1 ;
982
+ zend_call_function (& fci , & t -> fci_cache );
983
+ ch -> in_callback = 0 ;
984
+ if (!Z_ISUNDEF (retval )) {
985
+ _php_curl_verify_handlers (ch , true);
986
+ if (Z_TYPE (retval ) == IS_LONG ) {
987
+ zend_long retval_long = Z_LVAL (retval );
988
+ if (retval_long == CURL_PREREQFUNC_OK || retval_long == CURL_PREREQFUNC_ABORT ) {
989
+ rval = retval_long ;
990
+ } else {
991
+ zend_throw_error (NULL , "The CURLOPT_PREREQFUNCTION callback must return either CURL_PREREQFUNC_OK or CURL_PREREQFUNC_ABORT" );
992
+ }
993
+ } else {
994
+ zend_throw_error (NULL , "The CURLOPT_PREREQFUNCTION callback must return either CURL_PREREQFUNC_OK or CURL_PREREQFUNC_ABORT" );
995
+ }
996
+ }
997
+ zval_ptr_dtor (& argv [0 ]);
998
+ zval_ptr_dtor (& argv [1 ]);
999
+ zval_ptr_dtor (& argv [2 ]);
1000
+
1001
+ return rval ;
1002
+ }
1003
+
1004
+ #endif
1005
+
942
1006
static int curl_debug (CURL * cp , curl_infotype type , char * buf , size_t buf_len , void * ctx ) /* {{{ */
943
1007
{
944
1008
php_curl * ch = (php_curl * )ctx ;
@@ -1120,6 +1184,9 @@ void init_curl_handle(php_curl *ch)
1120
1184
ch -> handlers .progress = NULL ;
1121
1185
ch -> handlers .xferinfo = NULL ;
1122
1186
ch -> handlers .fnmatch = NULL ;
1187
+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
1188
+ ch -> handlers .prereq = NULL ;
1189
+ #endif
1123
1190
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
1124
1191
ch -> handlers .sshhostkey = NULL ;
1125
1192
#endif
@@ -1296,6 +1363,9 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
1296
1363
_php_copy_callback (ch , & ch -> handlers .progress , source -> handlers .progress , CURLOPT_PROGRESSDATA );
1297
1364
_php_copy_callback (ch , & ch -> handlers .xferinfo , source -> handlers .xferinfo , CURLOPT_XFERINFODATA );
1298
1365
_php_copy_callback (ch , & ch -> handlers .fnmatch , source -> handlers .fnmatch , CURLOPT_FNMATCH_DATA );
1366
+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
1367
+ _php_copy_callback (ch , & ch -> handlers .prereq , source -> handlers .prereq , CURLOPT_PREREQFUNCTION );
1368
+ #endif
1299
1369
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
1300
1370
_php_copy_callback (ch , & ch -> handlers .sshhostkey , source -> handlers .sshhostkey , CURLOPT_SSH_HOSTKEYDATA );
1301
1371
#endif
@@ -2206,6 +2276,20 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
2206
2276
ZVAL_COPY (& ch -> handlers .xferinfo -> func_name , zvalue );
2207
2277
break ;
2208
2278
2279
+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
2280
+ case CURLOPT_PREREQFUNCTION :
2281
+ curl_easy_setopt (ch -> cp , CURLOPT_PREREQFUNCTION , curl_prereqfunction );
2282
+ curl_easy_setopt (ch -> cp , CURLOPT_PREREQDATA , ch );
2283
+ if (ch -> handlers .prereq == NULL ) {
2284
+ ch -> handlers .prereq = ecalloc (1 , sizeof (php_curl_callback ));
2285
+ } else if (!Z_ISUNDEF (ch -> handlers .prereq -> func_name )) {
2286
+ zval_ptr_dtor (& ch -> handlers .prereq -> func_name );
2287
+ ch -> handlers .prereq -> fci_cache = empty_fcall_info_cache ;
2288
+ }
2289
+ ZVAL_COPY (& ch -> handlers .prereq -> func_name , zvalue );
2290
+ break ;
2291
+ #endif
2292
+
2209
2293
/* Curl off_t options */
2210
2294
case CURLOPT_MAX_RECV_SPEED_LARGE :
2211
2295
case CURLOPT_MAX_SEND_SPEED_LARGE :
@@ -2849,6 +2933,9 @@ static void curl_free_obj(zend_object *object)
2849
2933
#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
2850
2934
_php_curl_free_callback (ch -> handlers .sshhostkey );
2851
2935
#endif
2936
+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
2937
+ _php_curl_free_callback (ch -> handlers .prereq );
2938
+ #endif
2852
2939
2853
2940
zval_ptr_dtor (& ch -> postfields );
2854
2941
zval_ptr_dtor (& ch -> private_data );
@@ -2923,6 +3010,14 @@ static void _php_curl_reset_handlers(php_curl *ch)
2923
3010
ch -> handlers .xferinfo = NULL ;
2924
3011
}
2925
3012
3013
+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
3014
+ if (ch -> handlers .prereq ) {
3015
+ zval_ptr_dtor (& ch -> handlers .prereq -> func_name );
3016
+ efree (ch -> handlers .prereq );
3017
+ ch -> handlers .prereq = NULL ;
3018
+ }
3019
+ #endif
3020
+
2926
3021
if (ch -> handlers .fnmatch ) {
2927
3022
zval_ptr_dtor (& ch -> handlers .fnmatch -> func_name );
2928
3023
efree (ch -> handlers .fnmatch );
0 commit comments