@@ -511,6 +511,12 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
511511 }
512512#endif
513513
514+ #if LIBCURL_VERSION_NUM >= 0x075000 /* 7.80.0 */
515+ if (curl -> handlers .prereq ) {
516+ zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .prereq -> func_name );
517+ }
518+ #endif
519+
514520 if (curl -> handlers .fnmatch ) {
515521 zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .fnmatch -> func_name );
516522 }
@@ -956,6 +962,66 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx
956962}
957963/* }}} */
958964
965+ #if LIBCURL_VERSION_NUM >= 0x075000 /* 7.80.0 */
966+ static int curl_prereqfunction (void * clientp , char * conn_primary_ip , char * conn_local_ip , int conn_primary_port , int conn_local_port )
967+ {
968+ php_curl * ch = (php_curl * )clientp ;
969+ php_curl_callback * t = ch -> handlers .prereq ;
970+
971+ int rval = CURL_PREREQFUNC_ABORT ; /* Disallow the request by default. */
972+
973+ #if PHP_CURL_DEBUG
974+ fprintf (stderr , "curl_prereqfunction() called\n" );
975+ 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 );
976+ #endif
977+
978+ zval argv [5 ];
979+ zval retval ;
980+ zend_result error ;
981+ zend_fcall_info fci ;
982+
983+ GC_ADDREF (& ch -> std );
984+ ZVAL_OBJ (& argv [0 ], & ch -> std );
985+ ZVAL_STRING (& argv [1 ], conn_primary_ip );
986+ ZVAL_STRING (& argv [2 ], conn_local_ip );
987+ ZVAL_LONG (& argv [3 ], conn_primary_port );
988+ ZVAL_LONG (& argv [4 ], conn_local_port );
989+
990+ fci .size = sizeof (fci );
991+ ZVAL_COPY_VALUE (& fci .function_name , & t -> func_name );
992+ fci .object = NULL ;
993+ fci .retval = & retval ;
994+ fci .param_count = 5 ;
995+ fci .params = argv ;
996+ fci .named_params = NULL ;
997+
998+ ch -> in_callback = 1 ;
999+ error = zend_call_function (& fci , & t -> fci_cache );
1000+ ch -> in_callback = 0 ;
1001+ if (error == FAILURE ) {
1002+ php_error_docref (NULL , E_WARNING , "Cannot call the CURLOPT_PREREQFUNCTION" );
1003+ } else if (!Z_ISUNDEF (retval )) {
1004+ _php_curl_verify_handlers (ch , true);
1005+ if (Z_TYPE (retval ) == IS_LONG ) {
1006+ zend_long retval_long = Z_LVAL (retval );
1007+ if (retval_long == CURL_PREREQFUNC_OK || retval_long == CURL_PREREQFUNC_ABORT ) {
1008+ rval = retval_long ;
1009+ } else {
1010+ zend_throw_error (NULL , "The CURLOPT_PREREQFUNCTION callback must return either CURL_PREREQFUNC_OK or CURL_PREREQFUNC_ABORT" );
1011+ }
1012+ } else {
1013+ zend_throw_error (NULL , "The CURLOPT_PREREQFUNCTION callback must return either CURL_PREREQFUNC_OK or CURL_PREREQFUNC_ABORT" );
1014+ }
1015+ }
1016+ zval_ptr_dtor (& argv [0 ]);
1017+ zval_ptr_dtor (& argv [1 ]);
1018+ zval_ptr_dtor (& argv [2 ]);
1019+
1020+ return rval ;
1021+ }
1022+
1023+ #endif
1024+
9591025static int curl_debug (CURL * cp , curl_infotype type , char * buf , size_t buf_len , void * ctx ) /* {{{ */
9601026{
9611027 php_curl * ch = (php_curl * )ctx ;
@@ -1090,6 +1156,9 @@ void init_curl_handle(php_curl *ch)
10901156 ch -> handlers .progress = NULL ;
10911157#if LIBCURL_VERSION_NUM >= 0x072000
10921158 ch -> handlers .xferinfo = NULL ;
1159+ #endif
1160+ #if LIBCURL_VERSION_NUM >= 0x075000 /* 7.80.0 */
1161+ ch -> handlers .prereq = NULL ;
10931162#endif
10941163 ch -> handlers .fnmatch = NULL ;
10951164#if LIBCURL_VERSION_NUM >= 0x075400
@@ -1272,6 +1341,9 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
12721341 _php_copy_callback (ch , & ch -> handlers .progress , source -> handlers .progress , CURLOPT_PROGRESSDATA );
12731342#if LIBCURL_VERSION_NUM >= 0x072000
12741343 _php_copy_callback (ch , & ch -> handlers .xferinfo , source -> handlers .xferinfo , CURLOPT_XFERINFODATA );
1344+ #endif
1345+ #if LIBCURL_VERSION_NUM >= 0x075000 /* 7.80.0 */
1346+ _php_copy_callback (ch , & ch -> handlers .prereq , source -> handlers .prereq , CURLOPT_PREREQFUNCTION );
12751347#endif
12761348 _php_copy_callback (ch , & ch -> handlers .fnmatch , source -> handlers .fnmatch , CURLOPT_FNMATCH_DATA );
12771349#if LIBCURL_VERSION_NUM >= 0x075400
@@ -2330,6 +2402,20 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
23302402 break ;
23312403#endif
23322404
2405+ #if LIBCURL_VERSION_NUM >= 0x075000 /* 7.80.0 */
2406+ case CURLOPT_PREREQFUNCTION :
2407+ curl_easy_setopt (ch -> cp , CURLOPT_PREREQFUNCTION , curl_prereqfunction );
2408+ curl_easy_setopt (ch -> cp , CURLOPT_PREREQDATA , ch );
2409+ if (ch -> handlers .prereq == NULL ) {
2410+ ch -> handlers .prereq = ecalloc (1 , sizeof (php_curl_callback ));
2411+ } else if (!Z_ISUNDEF (ch -> handlers .prereq -> func_name )) {
2412+ zval_ptr_dtor (& ch -> handlers .prereq -> func_name );
2413+ ch -> handlers .prereq -> fci_cache = empty_fcall_info_cache ;
2414+ }
2415+ ZVAL_COPY (& ch -> handlers .prereq -> func_name , zvalue );
2416+ break ;
2417+ #endif
2418+
23332419 /* Curl off_t options */
23342420 case CURLOPT_MAX_RECV_SPEED_LARGE :
23352421 case CURLOPT_MAX_SEND_SPEED_LARGE :
@@ -2991,6 +3077,9 @@ static void curl_free_obj(zend_object *object)
29913077#if LIBCURL_VERSION_NUM >= 0x075400
29923078 _php_curl_free_callback (ch -> handlers .sshhostkey );
29933079#endif
3080+ #if LIBCURL_VERSION_NUM >= 0x075000 /* 7.80.0 */
3081+ _php_curl_free_callback (ch -> handlers .prereq );
3082+ #endif
29943083
29953084 zval_ptr_dtor (& ch -> postfields );
29963085 zval_ptr_dtor (& ch -> private_data );
@@ -3067,6 +3156,14 @@ static void _php_curl_reset_handlers(php_curl *ch)
30673156 }
30683157#endif
30693158
3159+ #if LIBCURL_VERSION_NUM >= 0x075000 /* 7.80.0 */
3160+ if (ch -> handlers .prereq ) {
3161+ zval_ptr_dtor (& ch -> handlers .prereq -> func_name );
3162+ efree (ch -> handlers .prereq );
3163+ ch -> handlers .prereq = NULL ;
3164+ }
3165+ #endif
3166+
30703167 if (ch -> handlers .fnmatch ) {
30713168 zval_ptr_dtor (& ch -> handlers .fnmatch -> func_name );
30723169 efree (ch -> handlers .fnmatch );
0 commit comments