@@ -496,6 +496,12 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
496496 zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .xferinfo -> func_name );
497497 }
498498
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+
499505 if (curl -> handlers .fnmatch ) {
500506 zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .fnmatch -> func_name );
501507 }
@@ -939,6 +945,64 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx
939945}
940946/* }}} */
941947
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+
9421006static int curl_debug (CURL * cp , curl_infotype type , char * buf , size_t buf_len , void * ctx ) /* {{{ */
9431007{
9441008 php_curl * ch = (php_curl * )ctx ;
@@ -1120,6 +1184,9 @@ void init_curl_handle(php_curl *ch)
11201184 ch -> handlers .progress = NULL ;
11211185 ch -> handlers .xferinfo = NULL ;
11221186 ch -> handlers .fnmatch = NULL ;
1187+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
1188+ ch -> handlers .prereq = NULL ;
1189+ #endif
11231190#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
11241191 ch -> handlers .sshhostkey = NULL ;
11251192#endif
@@ -1296,6 +1363,9 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
12961363 _php_copy_callback (ch , & ch -> handlers .progress , source -> handlers .progress , CURLOPT_PROGRESSDATA );
12971364 _php_copy_callback (ch , & ch -> handlers .xferinfo , source -> handlers .xferinfo , CURLOPT_XFERINFODATA );
12981365 _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
12991369#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
13001370 _php_copy_callback (ch , & ch -> handlers .sshhostkey , source -> handlers .sshhostkey , CURLOPT_SSH_HOSTKEYDATA );
13011371#endif
@@ -2206,6 +2276,20 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
22062276 ZVAL_COPY (& ch -> handlers .xferinfo -> func_name , zvalue );
22072277 break ;
22082278
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+
22092293 /* Curl off_t options */
22102294 case CURLOPT_MAX_RECV_SPEED_LARGE :
22112295 case CURLOPT_MAX_SEND_SPEED_LARGE :
@@ -2849,6 +2933,9 @@ static void curl_free_obj(zend_object *object)
28492933#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
28502934 _php_curl_free_callback (ch -> handlers .sshhostkey );
28512935#endif
2936+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
2937+ _php_curl_free_callback (ch -> handlers .prereq );
2938+ #endif
28522939
28532940 zval_ptr_dtor (& ch -> postfields );
28542941 zval_ptr_dtor (& ch -> private_data );
@@ -2923,6 +3010,14 @@ static void _php_curl_reset_handlers(php_curl *ch)
29233010 ch -> handlers .xferinfo = NULL ;
29243011 }
29253012
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+
29263021 if (ch -> handlers .fnmatch ) {
29273022 zval_ptr_dtor (& ch -> handlers .fnmatch -> func_name );
29283023 efree (ch -> handlers .fnmatch );
0 commit comments