mirror of
https://github.com/curl/curl.git
synced 2025-01-30 14:22:33 +08:00
lib: add CURL_WRITEFUNC_ERROR to signal write callback error
Prior to this change if the user wanted to signal an error from their write callbacks they would have to use logic to return a value different from the number of bytes (nmemb) passed to the callback. Also, the inclination of some users has been to just return 0 to signal error, which is incorrect as that may be the number of bytes passed to the callback. To remedy this the user can now return CURL_WRITEFUNC_ERROR instead. Ref: https://github.com/curl/curl/issues/9873 Closes https://github.com/curl/curl/pull/9874
This commit is contained in:
parent
988c1c12f5
commit
6d75115406
@ -51,10 +51,12 @@ the header line is null-terminated!
|
||||
The pointer named \fIuserdata\fP is the one you set with the
|
||||
\fICURLOPT_HEADERDATA(3)\fP option.
|
||||
|
||||
This callback function must return the number of bytes actually taken care of.
|
||||
If that amount differs from the amount passed in to your function, it will signal
|
||||
an error to the library. This will cause the transfer to get aborted and the
|
||||
libcurl function in progress will return \fICURLE_WRITE_ERROR\fP.
|
||||
Your callback should return the number of bytes actually taken care of. If
|
||||
that amount differs from the amount passed to your callback function, it will
|
||||
signal an error condition to the library. This will cause the transfer to get
|
||||
aborted and the libcurl function used will return \fICURLE_WRITE_ERROR\fP.
|
||||
|
||||
You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
|
||||
|
||||
A complete HTTP header that is passed to this function can be up to
|
||||
\fICURL_MAX_HTTP_HEADER\fP (100K) bytes and includes the final line terminator.
|
||||
|
@ -59,6 +59,13 @@ process any pending RTP data before marking the request as finished.
|
||||
|
||||
The \fICURLOPT_INTERLEAVEDATA(3)\fP is passed in the \fIuserdata\fP argument in
|
||||
the callback.
|
||||
|
||||
Your callback should return the number of bytes actually taken care of. If
|
||||
that amount differs from the amount passed to your callback function, it will
|
||||
signal an error condition to the library. This will cause the transfer to get
|
||||
aborted and the libcurl function used will return \fICURLE_WRITE_ERROR\fP.
|
||||
|
||||
You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
|
||||
.SH DEFAULT
|
||||
NULL, the interleave data is then passed to the regular write function:
|
||||
\fICURLOPT_WRITEFUNCTION(3)\fP.
|
||||
|
@ -63,6 +63,8 @@ that amount differs from the amount passed to your callback function, it will
|
||||
signal an error condition to the library. This will cause the transfer to get
|
||||
aborted and the libcurl function used will return \fICURLE_WRITE_ERROR\fP.
|
||||
|
||||
You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
|
||||
|
||||
If your callback function returns CURL_WRITEFUNC_PAUSE it will cause this
|
||||
transfer to become paused. See \fIcurl_easy_pause(3)\fP for further details.
|
||||
|
||||
|
@ -187,6 +187,7 @@ CURL_WAIT_POLLIN 7.28.0
|
||||
CURL_WAIT_POLLOUT 7.28.0
|
||||
CURL_WAIT_POLLPRI 7.28.0
|
||||
CURL_WIN32 7.69.0
|
||||
CURL_WRITEFUNC_ERROR 7.87.0
|
||||
CURL_WRITEFUNC_PAUSE 7.18.0
|
||||
CURL_ZERO_TERMINATED 7.56.0
|
||||
CURLALTSVC_H1 7.64.1
|
||||
|
@ -256,6 +256,10 @@ typedef int (*curl_xferinfo_callback)(void *clientp,
|
||||
will signal libcurl to pause receiving on the current transfer. */
|
||||
#define CURL_WRITEFUNC_PAUSE 0x10000001
|
||||
|
||||
/* This is a magic return code for the write callback that, when returned,
|
||||
will signal an error from the callback. */
|
||||
#define CURL_WRITEFUNC_ERROR 0xFFFFFFFF
|
||||
|
||||
typedef size_t (*curl_write_callback)(char *buffer,
|
||||
size_t size,
|
||||
size_t nitems,
|
||||
|
@ -77,22 +77,14 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
const char *end = (char *)ptr + cb;
|
||||
const char *scheme = NULL;
|
||||
|
||||
/*
|
||||
* Once that libcurl has called back tool_header_cb() the returned value
|
||||
* is checked against the amount that was intended to be written, if
|
||||
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
|
||||
* point returning a value different from sz*nmemb indicates failure.
|
||||
*/
|
||||
size_t failure = (size && nmemb) ? 0 : 1;
|
||||
|
||||
if(!per->config)
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
if(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
|
||||
warnf(per->config->global, "Header data exceeds single call write "
|
||||
"limit!\n");
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -175,7 +167,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
if(outs->stream) {
|
||||
/* indication of problem, get out! */
|
||||
free(filename);
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
|
||||
outs->is_cd_filename = TRUE;
|
||||
@ -185,12 +177,12 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
outs->alloc_filename = TRUE;
|
||||
hdrcbdata->honor_cd_filename = FALSE; /* done now! */
|
||||
if(!tool_create_output_file(outs, per->config))
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!outs->stream && !tool_create_output_file(outs, per->config))
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
if(hdrcbdata->config->writeout) {
|
||||
char *value = memchr(ptr, ':', cb);
|
||||
@ -210,7 +202,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
char *value = NULL;
|
||||
|
||||
if(!outs->stream && !tool_create_output_file(outs, per->config))
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
|
||||
if(hdrcbdata->global->isatty && hdrcbdata->global->styled_output)
|
||||
value = memchr(ptr, ':', cb);
|
||||
|
@ -164,14 +164,6 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
intptr_t fhnd;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Once that libcurl has called back tool_write_cb() the returned value
|
||||
* is checked against the amount that was intended to be written, if
|
||||
* it does not match then it fails with CURLE_WRITE_ERROR. So at this
|
||||
* point returning a value different from sz*nmemb indicates failure.
|
||||
*/
|
||||
const size_t failure = bytes ? 0 : 1;
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
{
|
||||
char *tty = curlx_getenv("CURL_ISATTY");
|
||||
@ -185,13 +177,13 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
if(bytes > (size_t)CURL_MAX_HTTP_HEADER) {
|
||||
warnf(config->global, "Header data size exceeds single call write "
|
||||
"limit!\n");
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(bytes > (size_t)CURL_MAX_WRITE_SIZE) {
|
||||
warnf(config->global, "Data size exceeds single call write limit!\n");
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,13 +212,13 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
}
|
||||
if(check_fails) {
|
||||
warnf(config->global, "Invalid output struct data for write callback\n");
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!outs->stream && !tool_create_output_file(outs, per->config))
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
|
||||
if(is_tty && (outs->bytes < 2000) && !config->terminal_binary_ok) {
|
||||
/* binary output to terminal? */
|
||||
@ -235,7 +227,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
"Use \"--output -\" to tell curl to output it to your terminal "
|
||||
"anyway, or consider \"--output <FILE>\" to save to a file.\n");
|
||||
config->synthetic_error = TRUE;
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,13 +243,13 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len, NULL, 0);
|
||||
wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t));
|
||||
if(!wc_buf)
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
|
||||
/* calculate buffer size for multi-byte characters */
|
||||
wc_len = MultiByteToWideChar(CP_UTF8, 0, buffer, in_len, wc_buf, wc_len);
|
||||
if(!wc_len) {
|
||||
free(wc_buf);
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
|
||||
if(!WriteConsoleW(
|
||||
@ -267,7 +259,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
&wc_len,
|
||||
NULL)) {
|
||||
free(wc_buf);
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
free(wc_buf);
|
||||
rc = bytes;
|
||||
@ -289,7 +281,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
|
||||
/* output buffering disabled */
|
||||
int res = fflush(outs->stream);
|
||||
if(res)
|
||||
return failure;
|
||||
return CURL_WRITEFUNC_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
Loading…
Reference in New Issue
Block a user