@@ -495,6 +495,12 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
495495 zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .xferinfo -> func_name );
496496 }
497497
498+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
499+ if (curl -> handlers .prereq ) {
500+ zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .prereq -> func_name );
501+ }
502+ #endif
503+
498504 if (curl -> handlers .fnmatch ) {
499505 zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .fnmatch -> func_name );
500506 }
@@ -938,6 +944,64 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx
938944}
939945/* }}} */
940946
947+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
948+ static int curl_prereqfunction (void * clientp , char * conn_primary_ip , char * conn_local_ip , int conn_primary_port , int conn_local_port )
949+ {
950+ php_curl * ch = (php_curl * )clientp ;
951+ php_curl_callback * t = ch -> handlers .prereq ;
952+
953+ int rval = CURL_PREREQFUNC_ABORT ; /* Disallow the request by default. */
954+
955+ #if PHP_CURL_DEBUG
956+ fprintf (stderr , "curl_prereqfunction() called\n" );
957+ 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 );
958+ #endif
959+
960+ zval argv [5 ];
961+ zval retval ;
962+
963+ zend_fcall_info fci ;
964+
965+ GC_ADDREF (& ch -> std );
966+ ZVAL_OBJ (& argv [0 ], & ch -> std );
967+ ZVAL_STRING (& argv [1 ], conn_primary_ip );
968+ ZVAL_STRING (& argv [2 ], conn_local_ip );
969+ ZVAL_LONG (& argv [3 ], conn_primary_port );
970+ ZVAL_LONG (& argv [4 ], conn_local_port );
971+
972+ fci .size = sizeof (fci );
973+ ZVAL_COPY_VALUE (& fci .function_name , & t -> func_name );
974+ fci .object = NULL ;
975+ fci .retval = & retval ;
976+ fci .param_count = 5 ;
977+ fci .params = argv ;
978+ fci .named_params = NULL ;
979+
980+ ch -> in_callback = 1 ;
981+ zend_call_function (& fci , & t -> fci_cache );
982+ ch -> in_callback = 0 ;
983+ if (!Z_ISUNDEF (retval )) {
984+ _php_curl_verify_handlers (ch , true);
985+ if (Z_TYPE (retval ) == IS_LONG ) {
986+ zend_long retval_long = Z_LVAL (retval );
987+ if (retval_long == CURL_PREREQFUNC_OK || retval_long == CURL_PREREQFUNC_ABORT ) {
988+ rval = retval_long ;
989+ } else {
990+ zend_throw_error (NULL , "The CURLOPT_PREREQFUNCTION callback must return either CURL_PREREQFUNC_OK or CURL_PREREQFUNC_ABORT" );
991+ }
992+ } else {
993+ zend_throw_error (NULL , "The CURLOPT_PREREQFUNCTION callback must return either CURL_PREREQFUNC_OK or CURL_PREREQFUNC_ABORT" );
994+ }
995+ }
996+ zval_ptr_dtor (& argv [0 ]);
997+ zval_ptr_dtor (& argv [1 ]);
998+ zval_ptr_dtor (& argv [2 ]);
999+
1000+ return rval ;
1001+ }
1002+
1003+ #endif
1004+
9411005static int curl_debug (CURL * cp , curl_infotype type , char * buf , size_t buf_len , void * ctx ) /* {{{ */
9421006{
9431007 php_curl * ch = (php_curl * )ctx ;
@@ -1057,6 +1121,9 @@ void init_curl_handle(php_curl *ch)
10571121 ch -> handlers .progress = NULL ;
10581122 ch -> handlers .xferinfo = NULL ;
10591123 ch -> handlers .fnmatch = NULL ;
1124+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
1125+ ch -> handlers .prereq = NULL ;
1126+ #endif
10601127#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
10611128 ch -> handlers .sshhostkey = NULL ;
10621129#endif
@@ -1233,6 +1300,9 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
12331300 _php_copy_callback (ch , & ch -> handlers .progress , source -> handlers .progress , CURLOPT_PROGRESSDATA );
12341301 _php_copy_callback (ch , & ch -> handlers .xferinfo , source -> handlers .xferinfo , CURLOPT_XFERINFODATA );
12351302 _php_copy_callback (ch , & ch -> handlers .fnmatch , source -> handlers .fnmatch , CURLOPT_FNMATCH_DATA );
1303+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
1304+ _php_copy_callback (ch , & ch -> handlers .prereq , source -> handlers .prereq , CURLOPT_PREREQFUNCTION );
1305+ #endif
12361306#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
12371307 _php_copy_callback (ch , & ch -> handlers .sshhostkey , source -> handlers .sshhostkey , CURLOPT_SSH_HOSTKEYDATA );
12381308#endif
@@ -2143,6 +2213,20 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
21432213 ZVAL_COPY (& ch -> handlers .xferinfo -> func_name , zvalue );
21442214 break ;
21452215
2216+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
2217+ case CURLOPT_PREREQFUNCTION :
2218+ curl_easy_setopt (ch -> cp , CURLOPT_PREREQFUNCTION , curl_prereqfunction );
2219+ curl_easy_setopt (ch -> cp , CURLOPT_PREREQDATA , ch );
2220+ if (ch -> handlers .prereq == NULL ) {
2221+ ch -> handlers .prereq = ecalloc (1 , sizeof (php_curl_callback ));
2222+ } else if (!Z_ISUNDEF (ch -> handlers .prereq -> func_name )) {
2223+ zval_ptr_dtor (& ch -> handlers .prereq -> func_name );
2224+ ch -> handlers .prereq -> fci_cache = empty_fcall_info_cache ;
2225+ }
2226+ ZVAL_COPY (& ch -> handlers .prereq -> func_name , zvalue );
2227+ break ;
2228+ #endif
2229+
21462230 /* Curl off_t options */
21472231 case CURLOPT_MAX_RECV_SPEED_LARGE :
21482232 case CURLOPT_MAX_SEND_SPEED_LARGE :
@@ -2786,6 +2870,9 @@ static void curl_free_obj(zend_object *object)
27862870#if LIBCURL_VERSION_NUM >= 0x075400 /* Available since 7.84.0 */
27872871 _php_curl_free_callback (ch -> handlers .sshhostkey );
27882872#endif
2873+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
2874+ _php_curl_free_callback (ch -> handlers .prereq );
2875+ #endif
27892876
27902877 zval_ptr_dtor (& ch -> postfields );
27912878 zval_ptr_dtor (& ch -> private_data );
@@ -2860,6 +2947,14 @@ static void _php_curl_reset_handlers(php_curl *ch)
28602947 ch -> handlers .xferinfo = NULL ;
28612948 }
28622949
2950+ #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */
2951+ if (ch -> handlers .prereq ) {
2952+ zval_ptr_dtor (& ch -> handlers .prereq -> func_name );
2953+ efree (ch -> handlers .prereq );
2954+ ch -> handlers .prereq = NULL ;
2955+ }
2956+ #endif
2957+
28632958 if (ch -> handlers .fnmatch ) {
28642959 zval_ptr_dtor (& ch -> handlers .fnmatch -> func_name );
28652960 efree (ch -> handlers .fnmatch );
0 commit comments