@@ -456,6 +456,10 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n)
456456 zend_get_gc_buffer_add_zval (gc_buffer , & curl -> handlers .write_header -> stream );
457457 }
458458
459+ if (ZEND_FCC_INITIALIZED (curl -> handlers .seek )) {
460+ zend_get_gc_buffer_add_fcc (gc_buffer , & curl -> handlers .seek );
461+ }
462+
459463 if (ZEND_FCC_INITIALIZED (curl -> handlers .progress )) {
460464 zend_get_gc_buffer_add_fcc (gc_buffer , & curl -> handlers .progress );
461465 }
@@ -831,6 +835,52 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
831835}
832836/* }}} */
833837
838+ /* {{{ curl_seek */
839+ static int curl_seek (void * clientp , curl_off_t offset , int origin )
840+ {
841+ php_curl * ch = (php_curl * )clientp ;
842+ int rval = CURL_SEEKFUNC_CANTSEEK ; /* safe default if unset or the callback misbehaves */
843+
844+ #if PHP_CURL_DEBUG
845+ fprintf (stderr , "curl_seek() called\n" );
846+ fprintf (stderr , "clientp = %x, offset = %ld, origin = %d\n" , clientp , offset , origin );
847+ #endif
848+ if (!ZEND_FCC_INITIALIZED (ch -> handlers .seek )) {
849+ return rval ;
850+ }
851+
852+ zval args [3 ];
853+ zval retval ;
854+
855+ GC_ADDREF (& ch -> std );
856+ ZVAL_OBJ (& args [0 ], & ch -> std );
857+ ZVAL_LONG (& args [1 ], offset );
858+ ZVAL_LONG (& args [2 ], origin );
859+
860+ ch -> in_callback = true;
861+ zend_call_known_fcc (& ch -> handlers .seek , & retval , /* param_count */ 3 , args , /* named_params */ NULL );
862+ ch -> in_callback = false;
863+
864+ if (!Z_ISUNDEF (retval )) {
865+ _php_curl_verify_handlers (ch , /* reporterror */ true);
866+ if (Z_TYPE (retval ) == IS_LONG ) {
867+ zend_long retval_long = Z_LVAL (retval );
868+ if (retval_long == CURL_SEEKFUNC_OK || retval_long == CURL_SEEKFUNC_FAIL || retval_long == CURL_SEEKFUNC_CANTSEEK ) {
869+ rval = retval_long ;
870+ } else {
871+ zend_value_error ("The CURLOPT_SEEKFUNCTION callback must return one of CURL_SEEKFUNC_OK, CURL_SEEKFUNC_FAIL or CURL_SEEKFUNC_CANTSEEK" );
872+ }
873+ } else {
874+ zend_type_error ("The CURLOPT_SEEKFUNCTION callback must return one of CURL_SEEKFUNC_OK, CURL_SEEKFUNC_FAIL or CURL_SEEKFUNC_CANTSEEK" );
875+ }
876+ zval_ptr_dtor (& retval );
877+ }
878+
879+ zval_ptr_dtor (& args [0 ]);
880+ return rval ;
881+ }
882+ /* }}} */
883+
834884/* {{{ curl_write_header */
835885static size_t curl_write_header (char * data , size_t size , size_t nmemb , void * ctx )
836886{
@@ -1038,6 +1088,7 @@ void init_curl_handle(php_curl *ch)
10381088 ch -> handlers .write = ecalloc (1 , sizeof (php_curl_write ));
10391089 ch -> handlers .write_header = ecalloc (1 , sizeof (php_curl_write ));
10401090 ch -> handlers .read = ecalloc (1 , sizeof (php_curl_read ));
1091+ ch -> handlers .seek = empty_fcall_info_cache ;
10411092 ch -> handlers .progress = empty_fcall_info_cache ;
10421093 ch -> handlers .xferinfo = empty_fcall_info_cache ;
10431094 ch -> handlers .fnmatch = empty_fcall_info_cache ;
@@ -1208,6 +1259,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
12081259 curl_easy_setopt (ch -> cp , CURLOPT_WRITEHEADER , (void * ) ch );
12091260 curl_easy_setopt (ch -> cp , CURLOPT_DEBUGDATA , (void * ) ch );
12101261
1262+ php_curl_copy_fcc_with_option (ch , CURLOPT_SEEKDATA , & ch -> handlers .seek , & source -> handlers .seek );
12111263 php_curl_copy_fcc_with_option (ch , CURLOPT_PROGRESSDATA , & ch -> handlers .progress , & source -> handlers .progress );
12121264 php_curl_copy_fcc_with_option (ch , CURLOPT_XFERINFODATA , & ch -> handlers .xferinfo , & source -> handlers .xferinfo );
12131265 php_curl_copy_fcc_with_option (ch , CURLOPT_FNMATCH_DATA , & ch -> handlers .fnmatch , & source -> handlers .fnmatch );
@@ -1577,6 +1629,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue
15771629 HANDLE_CURL_OPTION_CALLABLE_PHP_CURL_USER (ch , CURLOPT_HEADER , write_header , PHP_CURL_IGNORE );
15781630 HANDLE_CURL_OPTION_CALLABLE_PHP_CURL_USER (ch , CURLOPT_READ , read , PHP_CURL_DIRECT );
15791631
1632+ HANDLE_CURL_OPTION_CALLABLE (ch , CURLOPT_SEEK , handlers .seek , curl_seek );
15801633 HANDLE_CURL_OPTION_CALLABLE (ch , CURLOPT_PROGRESS , handlers .progress , curl_progress );
15811634 HANDLE_CURL_OPTION_CALLABLE (ch , CURLOPT_XFERINFO , handlers .xferinfo , curl_xferinfo );
15821635 HANDLE_CURL_OPTION_CALLABLE (ch , CURLOPT_FNMATCH_ , handlers .fnmatch , curl_fnmatch );
@@ -2794,6 +2847,9 @@ static void curl_free_obj(zend_object *object)
27942847 efree (ch -> handlers .write_header );
27952848 efree (ch -> handlers .read );
27962849
2850+ if (ZEND_FCC_INITIALIZED (ch -> handlers .seek )) {
2851+ zend_fcc_dtor (& ch -> handlers .seek );
2852+ }
27972853 if (ZEND_FCC_INITIALIZED (ch -> handlers .progress )) {
27982854 zend_fcc_dtor (& ch -> handlers .progress );
27992855 }
@@ -2878,6 +2934,10 @@ static void _php_curl_reset_handlers(php_curl *ch)
28782934 ZVAL_UNDEF (& ch -> handlers .std_err );
28792935 }
28802936
2937+ if (ZEND_FCC_INITIALIZED (ch -> handlers .seek )) {
2938+ zend_fcc_dtor (& ch -> handlers .seek );
2939+ }
2940+
28812941 if (ZEND_FCC_INITIALIZED (ch -> handlers .progress )) {
28822942 zend_fcc_dtor (& ch -> handlers .progress );
28832943 }
0 commit comments