aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/src/tool_cb_wrt.c
diff options
context:
space:
mode:
authorAlexSm <alex@ydb.tech>2024-01-18 11:28:56 +0100
committerGitHub <noreply@github.com>2024-01-18 11:28:56 +0100
commit9d0a3761b3201e0d9db879a7adf91876ebdb0564 (patch)
tree541d11ac878c18efd7ebca81e35112aa0fef995b /contrib/libs/curl/src/tool_cb_wrt.c
parent404ef8886ecc9736bc58ade6da2fbd83b486a408 (diff)
downloadydb-9d0a3761b3201e0d9db879a7adf91876ebdb0564.tar.gz
Library import 8 (#1074)
* Library import 8 * Add contrib/libs/cxxsupp/libcxx/include/__verbose_abort
Diffstat (limited to 'contrib/libs/curl/src/tool_cb_wrt.c')
-rw-r--r--contrib/libs/curl/src/tool_cb_wrt.c189
1 files changed, 139 insertions, 50 deletions
diff --git a/contrib/libs/curl/src/tool_cb_wrt.c b/contrib/libs/curl/src/tool_cb_wrt.c
index c9d1dbd1d2..98063c39c2 100644
--- a/contrib/libs/curl/src/tool_cb_wrt.c
+++ b/contrib/libs/curl/src/tool_cb_wrt.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,7 +44,7 @@
#ifndef O_BINARY
#define O_BINARY 0
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define OPENMODE S_IREAD | S_IWRITE
#else
#define OPENMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
@@ -62,14 +62,14 @@ bool tool_create_output_file(struct OutStruct *outs,
DEBUGASSERT(config);
global = config->global;
if(!fname || !*fname) {
- warnf(global, "Remote filename has no length!\n");
+ warnf(global, "Remote filename has no length");
return FALSE;
}
if(config->output_dir && outs->is_cd_filename) {
aname = aprintf("%s/%s", config->output_dir, fname);
if(!aname) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
return FALSE;
}
fname = aname;
@@ -95,12 +95,12 @@ bool tool_create_output_file(struct OutStruct *outs,
/* Guard against wraparound in new filename */
if(newlen < len) {
free(aname);
- errorf(global, "overflow in filename generation\n");
+ errorf(global, "overflow in filename generation");
return FALSE;
}
newname = malloc(newlen);
if(!newname) {
- errorf(global, "out of memory\n");
+ errorf(global, "out of memory");
free(aname);
return FALSE;
}
@@ -133,7 +133,7 @@ bool tool_create_output_file(struct OutStruct *outs,
}
if(!file) {
- warnf(global, "Failed to open the file %s: %s\n", fname,
+ warnf(global, "Failed to open the file %s: %s", fname,
strerror(errno));
free(aname);
return FALSE;
@@ -159,19 +159,11 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
struct OperationConfig *config = per->config;
size_t bytes = sz * nmemb;
bool is_tty = config->global->isatty;
-#ifdef WIN32
+#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO console_info;
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");
@@ -184,14 +176,14 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
if(config->show_headers) {
if(bytes > (size_t)CURL_MAX_HTTP_HEADER) {
warnf(config->global, "Header data size exceeds single call write "
- "limit!\n");
- return failure;
+ "limit");
+ 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;
+ warnf(config->global, "Data size exceeds single call write limit");
+ return CURL_WRITEFUNC_ERROR;
}
}
@@ -219,57 +211,154 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
check_fails = TRUE;
}
if(check_fails) {
- warnf(config->global, "Invalid output struct data for write callback\n");
- return failure;
+ warnf(config->global, "Invalid output struct data for write callback");
+ 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? */
if(memchr(buffer, 0, bytes)) {
warnf(config->global, "Binary output can mess up your terminal. "
"Use \"--output -\" to tell curl to output it to your terminal "
- "anyway, or consider \"--output <FILE>\" to save to a file.\n");
+ "anyway, or consider \"--output <FILE>\" to save to a file.");
config->synthetic_error = TRUE;
- return failure;
+ return CURL_WRITEFUNC_ERROR;
}
}
-#ifdef WIN32
+#ifdef _WIN32
fhnd = _get_osfhandle(fileno(outs->stream));
+ /* if windows console then UTF-8 must be converted to UTF-16 */
if(isatty(fileno(outs->stream)) &&
GetConsoleScreenBufferInfo((HANDLE)fhnd, &console_info)) {
- DWORD in_len = (DWORD)(sz * nmemb);
- wchar_t* wc_buf;
- DWORD wc_len;
-
- /* calculate buffer size for wide characters */
- 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;
-
- /* 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;
+ wchar_t *wc_buf;
+ DWORD wc_len, chars_written;
+ unsigned char *rbuf = (unsigned char *)buffer;
+ DWORD rlen = (DWORD)bytes;
+
+#define IS_TRAILING_BYTE(x) (0x80 <= (x) && (x) < 0xC0)
+
+ /* attempt to complete an incomplete UTF-8 sequence from previous call.
+ the sequence does not have to be well-formed. */
+ if(outs->utf8seq[0] && rlen) {
+ bool complete = false;
+ /* two byte sequence (lead byte 110yyyyy) */
+ if(0xC0 <= outs->utf8seq[0] && outs->utf8seq[0] < 0xE0) {
+ outs->utf8seq[1] = *rbuf++;
+ --rlen;
+ complete = true;
+ }
+ /* three byte sequence (lead byte 1110zzzz) */
+ else if(0xE0 <= outs->utf8seq[0] && outs->utf8seq[0] < 0xF0) {
+ if(!outs->utf8seq[1]) {
+ outs->utf8seq[1] = *rbuf++;
+ --rlen;
+ }
+ if(rlen && !outs->utf8seq[2]) {
+ outs->utf8seq[2] = *rbuf++;
+ --rlen;
+ complete = true;
+ }
+ }
+ /* four byte sequence (lead byte 11110uuu) */
+ else if(0xF0 <= outs->utf8seq[0] && outs->utf8seq[0] < 0xF8) {
+ if(!outs->utf8seq[1]) {
+ outs->utf8seq[1] = *rbuf++;
+ --rlen;
+ }
+ if(rlen && !outs->utf8seq[2]) {
+ outs->utf8seq[2] = *rbuf++;
+ --rlen;
+ }
+ if(rlen && !outs->utf8seq[3]) {
+ outs->utf8seq[3] = *rbuf++;
+ --rlen;
+ complete = true;
+ }
+ }
+
+ if(complete) {
+ WCHAR prefix[3] = {0}; /* UTF-16 (1-2 WCHARs) + NUL */
+
+ if(MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)outs->utf8seq, -1,
+ prefix, sizeof(prefix)/sizeof(prefix[0]))) {
+ DEBUGASSERT(prefix[2] == L'\0');
+ if(!WriteConsoleW(
+ (HANDLE) fhnd,
+ prefix,
+ prefix[1] ? 2 : 1,
+ &chars_written,
+ NULL)) {
+ return CURL_WRITEFUNC_ERROR;
+ }
+ }
+ /* else: UTF-8 input was not well formed and OS is pre-Vista which
+ drops invalid characters instead of writing U+FFFD to output. */
+
+ memset(outs->utf8seq, 0, sizeof(outs->utf8seq));
+ }
}
- if(!WriteConsoleW(
- (HANDLE) fhnd,
- wc_buf,
- wc_len,
- &wc_len,
- NULL)) {
+ /* suppress an incomplete utf-8 sequence at end of rbuf */
+ if(!outs->utf8seq[0] && rlen && (rbuf[rlen - 1] & 0x80)) {
+ /* check for lead byte from a two, three or four byte sequence */
+ if(0xC0 <= rbuf[rlen - 1] && rbuf[rlen - 1] < 0xF8) {
+ outs->utf8seq[0] = rbuf[rlen - 1];
+ rlen -= 1;
+ }
+ else if(rlen >= 2 && IS_TRAILING_BYTE(rbuf[rlen - 1])) {
+ /* check for lead byte from a three or four byte sequence */
+ if(0xE0 <= rbuf[rlen - 2] && rbuf[rlen - 2] < 0xF8) {
+ outs->utf8seq[0] = rbuf[rlen - 2];
+ outs->utf8seq[1] = rbuf[rlen - 1];
+ rlen -= 2;
+ }
+ else if(rlen >= 3 && IS_TRAILING_BYTE(rbuf[rlen - 2])) {
+ /* check for lead byte from a four byte sequence */
+ if(0xF0 <= rbuf[rlen - 3] && rbuf[rlen - 3] < 0xF8) {
+ outs->utf8seq[0] = rbuf[rlen - 3];
+ outs->utf8seq[1] = rbuf[rlen - 2];
+ outs->utf8seq[2] = rbuf[rlen - 1];
+ rlen -= 3;
+ }
+ }
+ }
+ }
+
+ if(rlen) {
+ /* calculate buffer size for wide characters */
+ wc_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, rlen, NULL, 0);
+ if(!wc_len)
+ return CURL_WRITEFUNC_ERROR;
+
+ wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t));
+ if(!wc_buf)
+ return CURL_WRITEFUNC_ERROR;
+
+ wc_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, rlen, wc_buf,
+ wc_len);
+ if(!wc_len) {
+ free(wc_buf);
+ return CURL_WRITEFUNC_ERROR;
+ }
+
+ if(!WriteConsoleW(
+ (HANDLE) fhnd,
+ wc_buf,
+ wc_len,
+ &chars_written,
+ NULL)) {
+ free(wc_buf);
+ return CURL_WRITEFUNC_ERROR;
+ }
free(wc_buf);
- return failure;
}
- free(wc_buf);
+
rc = bytes;
}
else
@@ -289,7 +378,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;