diff --git a/docs/TODO b/docs/TODO index 3e3ea1684..099929b36 100644 --- a/docs/TODO +++ b/docs/TODO @@ -140,7 +140,6 @@ 18.4 simultaneous parallel transfers 18.5 provide formpost headers 18.6 warning when setting an option - 18.7 warning when sending binary output to terminal 18.8 offer color-coded HTTP header output 18.9 Choose the name of file in braces for complex URLs 18.10 improve how curl works in a windows console window @@ -933,11 +932,6 @@ that doesn't exist on the server, just like --ftp-create-dirs. This can be useful to tell when support for a particular feature hasn't been compiled into the library. -18.7 warning when sending binary output to terminal - - Provide a way that prompts the user for confirmation before binary data is - sent to the terminal, much in the style 'less' does it. - 18.8 offer color-coded HTTP header output By offering different color output on the header name and the header diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c index 6c08943ea..c818abf51 100644 --- a/src/tool_cb_wrt.c +++ b/src/tool_cb_wrt.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -77,6 +77,8 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) size_t rc; struct OutStruct *outs = userdata; struct OperationConfig *config = outs->config; + size_t bytes = sz * nmemb; + bool isatty = config->global->isatty; /* * Once that libcurl has called back tool_write_cb() the returned value @@ -84,21 +86,29 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) * 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 = (sz && nmemb) ? 0 : 1; + const size_t failure = bytes ? 0 : 1; if(!config) return failure; #ifdef DEBUGBUILD + { + char *tty = curlx_getenv("CURL_ISATTY"); + if(tty) { + isatty = TRUE; + curl_free(tty); + } + } + if(config->include_headers) { - if(sz * nmemb > (size_t)CURL_MAX_HTTP_HEADER) { + if(bytes > (size_t)CURL_MAX_HTTP_HEADER) { warnf(config->global, "Header data size exceeds single call write " "limit!\n"); return failure; } } else { - if(sz * nmemb > (size_t)CURL_MAX_WRITE_SIZE) { + if(bytes > (size_t)CURL_MAX_WRITE_SIZE) { warnf(config->global, "Data size exceeds single call write limit!\n"); return failure; } @@ -137,11 +147,22 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) if(!outs->stream && !tool_create_output_file(outs)) return failure; + if(isatty && (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 \" to save to a file.\n"); + config->synthetic_error = ERR_BINARY_TERMINAL; + return failure; + } + } + rc = fwrite(buffer, sz, nmemb, outs->stream); - if((sz * nmemb) == rc) + if(bytes == rc) /* we added this amount of data to the output */ - outs->bytes += (sz * nmemb); + outs->bytes += bytes; if(config->readbusy) { config->readbusy = FALSE; diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index 38777f6fd..8d74905d9 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -27,6 +27,12 @@ #include "tool_metalink.h" +typedef enum { + ERR_NONE, + ERR_BINARY_TERMINAL = 1, /* binary to terminal detected */ + ERR_LAST +} curl_error; + struct GlobalConfig; struct OperationConfig { @@ -141,6 +147,7 @@ struct OperationConfig { bool insecure_ok; /* set TRUE to allow insecure SSL connects */ bool proxy_insecure_ok; /* set TRUE to allow insecure SSL connects for proxy */ + bool terminal_binary_ok; bool verifystatus; bool create_dirs; bool ftp_create_dirs; @@ -236,6 +243,8 @@ struct OperationConfig { double expect100timeout; bool suppress_connect_headers; /* suppress proxy CONNECT response headers from user callbacks */ + curl_error synthetic_error; /* if non-zero, it overrides any libcurl + error */ struct GlobalConfig *global; struct OperationConfig *prev; struct OperationConfig *next; /* Always last in the struct */ diff --git a/src/tool_getparam.c b/src/tool_getparam.c index fabe8f04b..bcb9e1ee2 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -1554,7 +1554,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ config->proxy_insecure_ok = toggle; break; - case '9': + case '9': /* --proxy-tlsv1 */ /* TLS version 1 for proxy */ config->proxy_ssl_version = CURL_SSLVERSION_TLSv1; break; diff --git a/src/tool_help.c b/src/tool_help.c index 46aae4527..08a81f590 100644 --- a/src/tool_help.c +++ b/src/tool_help.c @@ -252,7 +252,7 @@ static const struct helptxt helptext[] = { "Use HTTP NTLM authentication"}, {" --ntlm-wb", "Use HTTP NTLM authentication with winbind"}, - {" --oauth2-bearer", + {" --oauth2-bearer ", "OAuth 2 Bearer Token"}, {"-o, --output ", "Write to file instead of stdout"}, diff --git a/src/tool_main.c b/src/tool_main.c index 7e742ffca..089a317d4 100644 --- a/src/tool_main.c +++ b/src/tool_main.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms diff --git a/src/tool_operate.c b/src/tool_operate.c index 6f1525e8b..b80a77118 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -862,6 +862,9 @@ static CURLcode operate_do(struct GlobalConfig *global, set_binmode(stdout); } + /* explicitly passed to stdout means okaying binary gunk */ + config->terminal_binary_ok = (outfile && !strcmp(outfile, "-")); + if(!config->tcp_nodelay) my_setopt(curl, CURLOPT_TCP_NODELAY, 0L); @@ -1764,7 +1767,10 @@ static CURLcode operate_do(struct GlobalConfig *global, } else #endif - if(result && global->showerror) { + if(config->synthetic_error) { + ; + } + else if(result && global->showerror) { fprintf(global->errors, "curl: (%d) %s\n", result, (errorbuffer[0]) ? errorbuffer : curl_easy_strerror(result)); if(result == CURLE_SSL_CACERT) diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index d5f892e4c..4f3428987 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -151,7 +151,7 @@ test1396 test1397 test1398 \ test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \ test1408 test1409 test1410 test1411 test1412 test1413 test1414 test1415 \ test1416 test1417 test1418 test1419 test1420 test1421 test1422 test1423 \ -test1424 \ +test1424 test1425 test1426 \ test1428 test1429 test1430 test1431 test1432 test1433 test1434 test1435 \ test1436 test1437 test1438 test1439 test1440 test1441 test1442 test1443 \ test1444 test1445 test1446 \ diff --git a/tests/data/test1425 b/tests/data/test1425 new file mode 100644 index 000000000..0044c69d5 Binary files /dev/null and b/tests/data/test1425 differ diff --git a/tests/data/test1426 b/tests/data/test1426 new file mode 100644 index 000000000..dd6a8d117 Binary files /dev/null and b/tests/data/test1426 differ