Skip to content

curl_seek bug #47204 #504

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions ext/curl/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,9 @@ PHP_MINIT_FUNCTION(curl)
REGISTER_CURL_CONSTANT(CURLOPT_FILETIME);
REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION);
REGISTER_CURL_CONSTANT(CURLOPT_READFUNCTION);
#if LIBCURL_VERSION_NUM > 0x071200
REGISTER_CURL_CONSTANT(CURLOPT_SEEKFUNCTION);
#endif
#if CURLOPT_PASSWDFUNCTION != 0
REGISTER_CURL_CONSTANT(CURLOPT_PASSWDFUNCTION);
#endif
Expand Down Expand Up @@ -1212,6 +1215,89 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
}
/* }}} */

#if LIBCURL_VERSION_NUM > 0x071200
/* {{{ curl_seek
*/
static int curl_seek(void *ctx, curl_off_t offset, int origin)
{
php_curl *ch = (php_curl *) ctx;
php_curl_seek *t = ch->handlers->seek;
int status = CURL_SEEKFUNC_CANTSEEK;

switch (t->method) {
case PHP_CURL_DIRECT:
if (t->fp) {
if (fseek(t->fp, offset, origin) == 0)
{
return CURL_SEEKFUNC_OK;
}
}
break;
case PHP_CURL_USER: {
zval **argv[4];
zval *handle = NULL;
zval *zfd = NULL;
zval *zoffset = NULL;
zval *zorigin = NULL;
zval *retval_ptr;
int error;
zend_fcall_info fci;
TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);

MAKE_STD_ZVAL(handle);
MAKE_STD_ZVAL(zfd);
MAKE_STD_ZVAL(zoffset);
MAKE_STD_ZVAL(zorigin);

ZVAL_RESOURCE(handle, ch->id);
zend_list_addref(ch->id);
ZVAL_RESOURCE(zfd, t->fd);
zend_list_addref(t->fd);
ZVAL_LONG(zoffset, (int) offset);
ZVAL_LONG(zorigin, (int) origin);

argv[0] = &handle;
argv[1] = &zfd;
argv[2] = &zoffset;
argv[3] = &zorigin;

fci.size = sizeof(fci);
fci.function_table = EG(function_table);
fci.function_name = t->func_name;
fci.object_ptr = NULL;
fci.retval_ptr_ptr = &retval_ptr;
fci.param_count = 4;
fci.params = argv;
fci.no_separation = 0;
fci.symbol_table = NULL;

ch->in_callback = 1;
error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
ch->in_callback = 0;
if (error == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_SEEKFUNCTION");
} else if (retval_ptr) {
if (Z_TYPE_P(retval_ptr) != IS_BOOL) {
convert_to_boolean_ex(&retval_ptr);
}
if (Z_LVAL_P(retval_ptr) == 1)
{
status = CURL_SEEKFUNC_OK;
}
zval_ptr_dtor(&retval_ptr);
}
zval_ptr_dtor(argv[0]);
zval_ptr_dtor(argv[1]);
zval_ptr_dtor(argv[2]);
zval_ptr_dtor(argv[3]);
}
break;
}
return status;
}
/* }}} */
#endif

/* {{{ curl_write_header
*/
static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx)
Expand Down Expand Up @@ -1430,6 +1516,9 @@ static void alloc_curl_handle(php_curl **ch)
(*ch)->handlers->write = ecalloc(1, sizeof(php_curl_write));
(*ch)->handlers->write_header = ecalloc(1, sizeof(php_curl_write));
(*ch)->handlers->read = ecalloc(1, sizeof(php_curl_read));
#if LIBCURL_VERSION_NUM > 0x071200
(*ch)->handlers->seek = ecalloc(1, sizeof(php_curl_seek));
#endif
(*ch)->handlers->progress = ecalloc(1, sizeof(php_curl_progress));

(*ch)->in_callback = 0;
Expand Down Expand Up @@ -1568,6 +1657,10 @@ PHP_FUNCTION(curl_init)
curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write);
curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION, curl_read);
#if LIBCURL_VERSION_NUM > 0x071200
curl_easy_setopt(ch->cp, CURLOPT_SEEKFUNCTION, curl_seek);
curl_easy_setopt(ch->cp, CURLOPT_SEEKDATA, ch);
#endif
curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch);
curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_header);
curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
Expand Down Expand Up @@ -2010,6 +2103,17 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
ch->handlers->read->func_name = *zvalue;
ch->handlers->read->method = PHP_CURL_USER;
break;
#if LIBCURL_VERSION_NUM > 0x071200
case CURLOPT_SEEKFUNCTION:
if (ch->handlers->seek->func_name) {
zval_ptr_dtor(&ch->handlers->seek->func_name);
ch->handlers->seek->fci_cache = empty_fcall_info_cache;
}
zval_add_ref(zvalue);
ch->handlers->seek->func_name = *zvalue;
ch->handlers->seek->method = PHP_CURL_USER;
break;
#endif
case CURLOPT_PROGRESSFUNCTION:
curl_easy_setopt(ch->cp, CURLOPT_PROGRESSFUNCTION, curl_progress);
curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, ch);
Expand Down
14 changes: 14 additions & 0 deletions ext/curl/php_curl.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ typedef struct {
zval *stream;
} php_curl_read;

#if LIBCURL_VERSION_NUM > 0x071200
typedef struct {
zval *func_name;
zend_fcall_info_cache fci_cache;
FILE *fp;
long fd;
int method;
zval *stream;
} php_curl_seek;
#endif

typedef struct {
zval *func_name;
zend_fcall_info_cache fci_cache;
Expand All @@ -108,6 +119,9 @@ typedef struct {
php_curl_write *write;
php_curl_write *write_header;
php_curl_read *read;
#if LIBCURL_VERSION_NUM > 0x071200
php_curl_seek *seek;
#endif
zval *passwd;
zval *std_err;
php_curl_progress *progress;
Expand Down