#41712 [Com]: [PATCH] Add CURL Progress Function Callback
ID: 41712 Comment by: frase at cs dot wisc dot edu Reported By: sdteffen at gmail dot com Status: Assigned Bug Type: Feature/Change Request Operating System: SuSE Linux 10.2 PHP Version: 5CVS-2007-06-16 (CVS) Assigned To: iliaa New Comment: What happened here? A patch was offered for this feature almost two years ago, and was assigned to the maintainer a week later. The next six months saw some tweaks and corrections, and yet here we are two years later with this still languishing in "assigned" limbo, neither accepted and merged nor rejected and closed. Ilia? Tony? Bueller? Previous Comments: [2009-02-20 09:27:43] php41712 at brainpower dot no-ip dot org can somewone submit this to the php code as this will help a lot of users [2008-02-16 15:00:15] sdteffen at gmail dot com The last patch is missing the changes to php_curl.h from the previous patch. A file containing the complete patch with changes for both files can be found under this URL: http://sdteffen.de/php/php_curl_progress_callback.patch [2008-02-06 21:35:33] renatobraga at gmail dot com Thanks Steffen, Worked like a charm [2008-02-06 18:14:12] sdteffen at gmail dot com I've updated the patch to pass the return value from the callback function as Renato suggested: --- php-5.2.5.orig/ext/curl/interface.c 2007-10-13 13:35:35.0 +0200 +++ php-5.2.5.patch/ext/curl/interface.c2008-02-06 18:43:41.0 +0100 @@ -368,6 +368,7 @@ REGISTER_CURL_CONSTANT(CURLOPT_HEADER); REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER); REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS); + REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION); REGISTER_CURL_CONSTANT(CURLOPT_NOBODY); REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR); REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD); @@ -780,6 +781,87 @@ } /* }}} */ +/* {{{ curl_progress + */ +static size_t curl_progress(void *clientp, +double dltotal, +double dlnow, +double ultotal, +double ulnow) +{ + php_curl *ch = (php_curl *) clientp; + php_curl_progress *t = ch->handlers->progress; + int length = -1; + size_t rval = 0; + +#if PHP_CURL_DEBUG + fprintf(stderr, "curl_progress() called\n"); + fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow); +#endif + + switch (t->method) { + case PHP_CURL_USER: { + zval **argv[4]; + zval *zdltotal = NULL; + zval *zdlnow = NULL; + zval *zultotal = NULL; + zval *zulnow = NULL; + zval *retval_ptr; + int error; + zend_fcall_info fci; + TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); + + MAKE_STD_ZVAL(zdltotal); + MAKE_STD_ZVAL(zdlnow); + MAKE_STD_ZVAL(zultotal); + MAKE_STD_ZVAL(zulnow); + + ZVAL_LONG(zdltotal, dltotal); + ZVAL_LONG(zdlnow, dlnow); + ZVAL_LONG(zultotal, ultotal); + ZVAL_LONG(zulnow, ulnow); + + argv[0] = &zdltotal; + argv[1] = &zdlnow; + argv[2] = &zultotal; + argv[3] = &zulnow; + + fci.size = sizeof(fci); + fci.function_table = EG(function_table); + fci.function_name = t->func_name; + fci.object_pp = 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_READFUNCTION"); + length = -1; + } else if (retval_ptr) { + if (Z_TYPE_P(retval_ptr) != IS_LONG) { + convert_to_long_ex(&retval_ptr); + } +
#41712 [Com]: [PATCH] Add CURL Progress Function Callback
ID: 41712 Comment by: php41712 at brainpower dot no-ip dot org Reported By: sdteffen at gmail dot com Status: Assigned Bug Type: Feature/Change Request Operating System: SuSE Linux 10.2 PHP Version: 5CVS-2007-06-16 (CVS) Assigned To: iliaa New Comment: can somewone submit this to the php code as this will help a lot of users Previous Comments: [2008-02-16 15:00:15] sdteffen at gmail dot com The last patch is missing the changes to php_curl.h from the previous patch. A file containing the complete patch with changes for both files can be found under this URL: http://sdteffen.de/php/php_curl_progress_callback.patch [2008-02-06 21:35:33] renatobraga at gmail dot com Thanks Steffen, Worked like a charm [2008-02-06 18:14:12] sdteffen at gmail dot com I've updated the patch to pass the return value from the callback function as Renato suggested: --- php-5.2.5.orig/ext/curl/interface.c 2007-10-13 13:35:35.0 +0200 +++ php-5.2.5.patch/ext/curl/interface.c2008-02-06 18:43:41.0 +0100 @@ -368,6 +368,7 @@ REGISTER_CURL_CONSTANT(CURLOPT_HEADER); REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER); REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS); + REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION); REGISTER_CURL_CONSTANT(CURLOPT_NOBODY); REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR); REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD); @@ -780,6 +781,87 @@ } /* }}} */ +/* {{{ curl_progress + */ +static size_t curl_progress(void *clientp, +double dltotal, +double dlnow, +double ultotal, +double ulnow) +{ + php_curl *ch = (php_curl *) clientp; + php_curl_progress *t = ch->handlers->progress; + int length = -1; + size_t rval = 0; + +#if PHP_CURL_DEBUG + fprintf(stderr, "curl_progress() called\n"); + fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow); +#endif + + switch (t->method) { + case PHP_CURL_USER: { + zval **argv[4]; + zval *zdltotal = NULL; + zval *zdlnow = NULL; + zval *zultotal = NULL; + zval *zulnow = NULL; + zval *retval_ptr; + int error; + zend_fcall_info fci; + TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); + + MAKE_STD_ZVAL(zdltotal); + MAKE_STD_ZVAL(zdlnow); + MAKE_STD_ZVAL(zultotal); + MAKE_STD_ZVAL(zulnow); + + ZVAL_LONG(zdltotal, dltotal); + ZVAL_LONG(zdlnow, dlnow); + ZVAL_LONG(zultotal, ultotal); + ZVAL_LONG(zulnow, ulnow); + + argv[0] = &zdltotal; + argv[1] = &zdlnow; + argv[2] = &zultotal; + argv[3] = &zulnow; + + fci.size = sizeof(fci); + fci.function_table = EG(function_table); + fci.function_name = t->func_name; + fci.object_pp = 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_READFUNCTION"); + length = -1; + } else if (retval_ptr) { + if (Z_TYPE_P(retval_ptr) != IS_LONG) { + convert_to_long_ex(&retval_ptr); + } + if(0 != Z_LVAL_P(retval_ptr)) + rval = 1; + 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 rval; +} +/* }}} */ + +
#41712 [Com]: [PATCH] Add CURL Progress Function Callback
ID: 41712 Comment by: renatobraga at gmail dot com Reported By: sdteffen at gmail dot com Status: Assigned Bug Type: Feature/Change Request Operating System: SuSE Linux 10.2 PHP Version: 5CVS-2007-06-16 (CVS) Assigned To: iliaa New Comment: Thanks Steffen, Worked like a charm Previous Comments: [2008-02-06 18:14:12] sdteffen at gmail dot com I've updated the patch to pass the return value from the callback function as Renato suggested: --- php-5.2.5.orig/ext/curl/interface.c 2007-10-13 13:35:35.0 +0200 +++ php-5.2.5.patch/ext/curl/interface.c2008-02-06 18:43:41.0 +0100 @@ -368,6 +368,7 @@ REGISTER_CURL_CONSTANT(CURLOPT_HEADER); REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER); REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS); + REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION); REGISTER_CURL_CONSTANT(CURLOPT_NOBODY); REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR); REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD); @@ -780,6 +781,87 @@ } /* }}} */ +/* {{{ curl_progress + */ +static size_t curl_progress(void *clientp, +double dltotal, +double dlnow, +double ultotal, +double ulnow) +{ + php_curl *ch = (php_curl *) clientp; + php_curl_progress *t = ch->handlers->progress; + int length = -1; + size_t rval = 0; + +#if PHP_CURL_DEBUG + fprintf(stderr, "curl_progress() called\n"); + fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow); +#endif + + switch (t->method) { + case PHP_CURL_USER: { + zval **argv[4]; + zval *zdltotal = NULL; + zval *zdlnow = NULL; + zval *zultotal = NULL; + zval *zulnow = NULL; + zval *retval_ptr; + int error; + zend_fcall_info fci; + TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); + + MAKE_STD_ZVAL(zdltotal); + MAKE_STD_ZVAL(zdlnow); + MAKE_STD_ZVAL(zultotal); + MAKE_STD_ZVAL(zulnow); + + ZVAL_LONG(zdltotal, dltotal); + ZVAL_LONG(zdlnow, dlnow); + ZVAL_LONG(zultotal, ultotal); + ZVAL_LONG(zulnow, ulnow); + + argv[0] = &zdltotal; + argv[1] = &zdlnow; + argv[2] = &zultotal; + argv[3] = &zulnow; + + fci.size = sizeof(fci); + fci.function_table = EG(function_table); + fci.function_name = t->func_name; + fci.object_pp = 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_READFUNCTION"); + length = -1; + } else if (retval_ptr) { + if (Z_TYPE_P(retval_ptr) != IS_LONG) { + convert_to_long_ex(&retval_ptr); + } + if(0 != Z_LVAL_P(retval_ptr)) + rval = 1; + 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 rval; +} +/* }}} */ + + /* {{{ curl_read */ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) @@ -1068,6 +1150,7 @@ (*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)); + (*ch)->handlers->progress = ecalloc(1, sizeof(php_curl_progress)); (*ch)->in_callback = 0; (*ch)->header.str_len = 0; @@ -1422,6 +1505,17 @@ ch->handlers->read->fu
#41712 [Com]: [PATCH] Add CURL Progress Function Callback
ID: 41712 Comment by: renatobraga at gmail dot com Reported By: sdteffen at gmail dot com Status: Assigned Bug Type: Feature/Change Request Operating System: SuSE Linux 10.2 PHP Version: 5CVS-2007-06-16 (CVS) Assigned To: iliaa New Comment: Hi, this patch isn't working for return values as you can see: "Returning a non-zero nonzero value from this callback will cause libcurl to abort the transfer and return CURLE_ABORTED_BY_CALLBACK." Nothing happens if i return a nonzero value. Can you fix it? Regards, Renato Previous Comments: [2007-09-25 09:22:29] top dot quack at freenet dot de Thanks to Steffen, the patch is now working properly and displays the upload progress as expected: curl_progress_callback Download: 0 / 0 bytes, Upload: 636 / 1179391 bytes curl_progress_callback Download: 0 / 0 bytes, Upload: 17020 / 1179391 bytes curl_progress_callback Download: 0 / 0 bytes, Upload: 33404 / 1179391 bytes Please include that bugfix as soon as possible into the new php versions. [2007-09-24 21:26:20] sdteffen at gmail dot com The progress function only returned 3 values instead of 4. The following revised patch fixes this problem (it completely replaces the previous patch): diff -u php-5.2.3/ext/curl/interface.c php-5.2.3.patched/ext/curl/interface.c --- php-5.2.3/ext/curl/interface.c 2007-05-22 10:39:20.0 +0200 +++ php-5.2.3.patched/ext/curl/interface.c 2007-06-16 13:30:05.0 +0200 @@ -368,6 +368,7 @@ REGISTER_CURL_CONSTANT(CURLOPT_HEADER); REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER); REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS); + REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION); REGISTER_CURL_CONSTANT(CURLOPT_NOBODY); REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR); REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD); @@ -777,6 +778,80 @@ } /* }}} */ +/* {{{ curl_progress + */ +static size_t curl_progress(void *clientp, +double dltotal, +double dlnow, +double ultotal, +double ulnow) +{ + php_curl *ch = (php_curl *) clientp; + php_curl_progress *t = ch->handlers->progress; + int length = -1; + +#if PHP_CURL_DEBUG + fprintf(stderr, "curl_progress() called\n"); + fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow); +#endif + + switch (t->method) { + case PHP_CURL_USER: { + zval **argv[4]; + zval *zdltotal = NULL; + zval *zdlnow = NULL; + zval *zultotal = NULL; + zval *zulnow = NULL; + zval *retval_ptr; + int error; + zend_fcall_info fci; + TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); + + MAKE_STD_ZVAL(zdltotal); + MAKE_STD_ZVAL(zdlnow); + MAKE_STD_ZVAL(zultotal); + MAKE_STD_ZVAL(zulnow); + + ZVAL_LONG(zdltotal, dltotal); + ZVAL_LONG(zdlnow, dlnow); + ZVAL_LONG(zultotal, ultotal); + ZVAL_LONG(zulnow, ulnow); + + argv[0] = &zdltotal; + argv[1] = &zdlnow; + argv[2] = &zultotal; + argv[3] = &zulnow; + + fci.size = sizeof(fci); + fci.function_table = EG(function_table); + fci.function_name = t->func_name; + fci.object_pp = 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_READFUNCTION"); + length = -1; + } + + zval_ptr_dtor(argv[0]); + zval_ptr_dtor(argv[1]); + zval_ptr_dtor(argv[2]); + zval_ptr_dtor(argv[3]); + break; + } + } + return 0; +} +/* }}} */ + + /* {{{ curl_read */ static size_t curl_read(char *data, size_t size, size_
#41712 [Com]: [PATCH] Add CURL Progress Function Callback
ID: 41712 Comment by: top dot quack at freenet dot de Reported By: sdteffen at gmail dot com Status: Assigned Bug Type: Feature/Change Request Operating System: SuSE Linux 10.2 PHP Version: 5CVS-2007-06-16 (CVS) Assigned To: iliaa New Comment: Thanks to Steffen, the patch is now working properly and displays the upload progress as expected: curl_progress_callback Download: 0 / 0 bytes, Upload: 636 / 1179391 bytes curl_progress_callback Download: 0 / 0 bytes, Upload: 17020 / 1179391 bytes curl_progress_callback Download: 0 / 0 bytes, Upload: 33404 / 1179391 bytes Please include that bugfix as soon as possible into the new php versions. Previous Comments: [2007-09-24 21:26:20] sdteffen at gmail dot com The progress function only returned 3 values instead of 4. The following revised patch fixes this problem (it completely replaces the previous patch): diff -u php-5.2.3/ext/curl/interface.c php-5.2.3.patched/ext/curl/interface.c --- php-5.2.3/ext/curl/interface.c 2007-05-22 10:39:20.0 +0200 +++ php-5.2.3.patched/ext/curl/interface.c 2007-06-16 13:30:05.0 +0200 @@ -368,6 +368,7 @@ REGISTER_CURL_CONSTANT(CURLOPT_HEADER); REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER); REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS); + REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION); REGISTER_CURL_CONSTANT(CURLOPT_NOBODY); REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR); REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD); @@ -777,6 +778,80 @@ } /* }}} */ +/* {{{ curl_progress + */ +static size_t curl_progress(void *clientp, +double dltotal, +double dlnow, +double ultotal, +double ulnow) +{ + php_curl *ch = (php_curl *) clientp; + php_curl_progress *t = ch->handlers->progress; + int length = -1; + +#if PHP_CURL_DEBUG + fprintf(stderr, "curl_progress() called\n"); + fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow); +#endif + + switch (t->method) { + case PHP_CURL_USER: { + zval **argv[4]; + zval *zdltotal = NULL; + zval *zdlnow = NULL; + zval *zultotal = NULL; + zval *zulnow = NULL; + zval *retval_ptr; + int error; + zend_fcall_info fci; + TSRMLS_FETCH_FROM_CTX(ch->thread_ctx); + + MAKE_STD_ZVAL(zdltotal); + MAKE_STD_ZVAL(zdlnow); + MAKE_STD_ZVAL(zultotal); + MAKE_STD_ZVAL(zulnow); + + ZVAL_LONG(zdltotal, dltotal); + ZVAL_LONG(zdlnow, dlnow); + ZVAL_LONG(zultotal, ultotal); + ZVAL_LONG(zulnow, ulnow); + + argv[0] = &zdltotal; + argv[1] = &zdlnow; + argv[2] = &zultotal; + argv[3] = &zulnow; + + fci.size = sizeof(fci); + fci.function_table = EG(function_table); + fci.function_name = t->func_name; + fci.object_pp = 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_READFUNCTION"); + length = -1; + } + + zval_ptr_dtor(argv[0]); + zval_ptr_dtor(argv[1]); + zval_ptr_dtor(argv[2]); + zval_ptr_dtor(argv[3]); + break; + } + } + return 0; +} +/* }}} */ + + /* {{{ curl_read */ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) @@ -1065,6 +1140,7 @@ (*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)); + (*ch)->handlers->progress = ecalloc(1, sizeof(php_curl_progress)); (*ch)->in_callback = 0; (*ch)->header.str_l