From c1c27625c797cfb7b21128484b4990446c1e92d9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 17 May 2018 13:56:35 +0200 Subject: curl: show headers in bold The feature is only enabled if the output is believed to be a tty. -J: There's some minor differences and improvements in -J handling, as now J should work with -i and it actually creates a file first using the initial name and then *renames* that to the one found in Content-Disposition (if any). -i: only shows headers for HTTP transfers now (as documented). Previously it would also show for pieces of the transfer that were HTTP (for example when doing FTP over a HTTP proxy). -i: now shows trailers as well. Previously they were not shown at all. --libcurl: the CURLOPT_HEADER is no longer set, as the header output is now done in the header callback. --- src/tool_cb_hdr.c | 63 +++++++++++++++++++++++++++++++++++++++++++---------- src/tool_cb_hdr.h | 4 +++- src/tool_cb_wrt.c | 13 ++++++----- src/tool_cb_wrt.h | 4 ++-- src/tool_cfgable.h | 2 +- src/tool_getparam.c | 12 +++++----- src/tool_operate.c | 15 +++++-------- tests/data/test1116 | 2 ++ tests/data/test1319 | 3 --- tests/data/test1321 | 3 --- tests/data/test1400 | 1 - tests/data/test1401 | 1 - tests/data/test1402 | 1 - tests/data/test1403 | 1 - tests/data/test1404 | 1 - tests/data/test1405 | 1 - tests/data/test1406 | 1 - tests/data/test1407 | 1 - tests/data/test1417 | 1 + tests/data/test1420 | 1 - tests/data/test2010 | 4 ++-- tests/data/test266 | 1 + 22 files changed, 81 insertions(+), 55 deletions(-) diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c index 7f2181f40..4e9e49a6d 100644 --- a/src/tool_cb_hdr.c +++ b/src/tool_cb_hdr.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2018, 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 @@ -31,11 +31,20 @@ #include "tool_doswin.h" #include "tool_msgs.h" #include "tool_cb_hdr.h" +#include "tool_cb_wrt.h" #include "memdebug.h" /* keep this as LAST include */ static char *parse_filename(const char *ptr, size_t len); +#ifdef WIN32 +#define BOLD +#define BOLDOFF +#else +#define BOLD "\x1b[1m" +#define BOLDOFF "\x1b[21m" +#endif + /* ** callback for CURLOPT_HEADERFUNCTION */ @@ -48,7 +57,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) const char *str = ptr; const size_t cb = size * nmemb; const char *end = (char *)ptr + cb; - char *url = NULL; + long protocol = 0; /* * Once that libcurl has called back tool_header_cb() the returned value @@ -88,12 +97,15 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) * Content-Disposition header specifying a filename property. */ + curl_easy_getinfo(outs->config->easy, CURLINFO_PROTOCOL, &protocol); if(hdrcbdata->honor_cd_filename && (cb > 20) && checkprefix("Content-disposition:", str) && - !curl_easy_getinfo(outs->config->easy, CURLINFO_EFFECTIVE_URL, &url) && - url && (checkprefix("http://", url) || checkprefix("https://", url))) { + (protocol & (CURLPROTO_HTTPS|CURLPROTO_HTTP))) { const char *p = str + 20; + if(!outs->stream && !tool_create_output_file(outs, FALSE)) + return failure; + /* look for the 'filename=' parameter (encoded filenames (*=) are not supported) */ for(;;) { @@ -119,19 +131,49 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) len = (ssize_t)cb - (p - str); filename = parse_filename(p, len); if(filename) { - outs->filename = filename; - outs->alloc_filename = TRUE; + if(outs->stream) { + /* already opened and possibly written to */ + if(outs->fopened) + fclose(outs->stream); + outs->stream = NULL; + + /* rename the initial file name to the new file name */ + rename(outs->filename, filename); + if(outs->alloc_filename) + free(outs->filename); + } outs->is_cd_filename = TRUE; outs->s_isreg = TRUE; outs->fopened = FALSE; - outs->stream = NULL; - hdrcbdata->honor_cd_filename = FALSE; - break; + outs->filename = filename; + outs->alloc_filename = TRUE; + hdrcbdata->honor_cd_filename = FALSE; /* done now! */ + if(!tool_create_output_file(outs, TRUE)) + return failure; } - return failure; + break; } } + if(hdrcbdata->config->show_headers && + (protocol & (CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_RTSP))) { + /* bold headers only happen for HTTP(S) and RTSP */ + char *value = NULL; + + if(!outs->stream && !tool_create_output_file(outs, FALSE)) + return failure; + + if(hdrcbdata->global->isatty) + value = memchr(ptr, ':', cb); + if(value) { + size_t namelen = value - ptr; + fprintf(outs->stream, BOLD "%.*s" BOLDOFF ":", namelen, ptr); + fwrite(&value[1], cb - namelen - 1, 1, outs->stream); + } + else + /* not "handled", just show it */ + fwrite(ptr, cb, 1, outs->stream); + } return cb; } @@ -233,4 +275,3 @@ static char *parse_filename(const char *ptr, size_t len) return copy; } - diff --git a/src/tool_cb_hdr.h b/src/tool_cb_hdr.h index 32032e980..e1b9a920e 100644 --- a/src/tool_cb_hdr.h +++ b/src/tool_cb_hdr.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2018, 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 @@ -39,6 +39,8 @@ */ struct HdrCbData { + struct GlobalConfig *global; + struct OperationConfig *config; struct OutStruct *outs; struct OutStruct *heads; bool honor_cd_filename; diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c index 6716ba5cd..476fef9a4 100644 --- a/src/tool_cb_wrt.c +++ b/src/tool_cb_wrt.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2018, 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 @@ -32,7 +32,8 @@ #include "memdebug.h" /* keep this as LAST include */ /* create a local file for writing, return TRUE on success */ -bool tool_create_output_file(struct OutStruct *outs) +bool tool_create_output_file(struct OutStruct *outs, + bool append) { struct GlobalConfig *global = outs->config->global; FILE *file; @@ -42,7 +43,7 @@ bool tool_create_output_file(struct OutStruct *outs) return FALSE; } - if(outs->is_cd_filename) { + if(outs->is_cd_filename && !append) { /* don't overwrite existing files */ file = fopen(outs->filename, "rb"); if(file) { @@ -54,7 +55,7 @@ bool tool_create_output_file(struct OutStruct *outs) } /* open file for writing */ - file = fopen(outs->filename, "wb"); + file = fopen(outs->filename, append?"ab":"wb"); if(!file) { warnf(global, "Failed to create the file %s: %s\n", outs->filename, strerror(errno)); @@ -97,7 +98,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) } } - if(config->include_headers) { + if(config->show_headers) { if(bytes > (size_t)CURL_MAX_HTTP_HEADER) { warnf(config->global, "Header data size exceeds single call write " "limit!\n"); @@ -141,7 +142,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) } #endif - if(!outs->stream && !tool_create_output_file(outs)) + if(!outs->stream && !tool_create_output_file(outs, FALSE)) return failure; if(is_tty && (outs->bytes < 2000) && !config->terminal_binary_ok) { diff --git a/src/tool_cb_wrt.h b/src/tool_cb_wrt.h index 4ccbf3a5f..2b6e98ae4 100644 --- a/src/tool_cb_wrt.h +++ b/src/tool_cb_wrt.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2018, 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 @@ -30,7 +30,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata); /* create a local file for writing, return TRUE on success */ -bool tool_create_output_file(struct OutStruct *outs); +bool tool_create_output_file(struct OutStruct *outs, bool append); #endif /* HEADER_CURL_TOOL_CB_WRT_H */ diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index 96618f8b1..3bd908879 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -100,7 +100,7 @@ struct OperationConfig { bool use_ascii; /* select ascii or text transfer */ bool autoreferer; /* automatically set referer */ bool failonerror; /* fail on (HTTP) errors */ - bool include_headers; /* send headers to data output */ + bool show_headers; /* show headers to data output */ bool no_body; /* don't get the body */ bool dirlistonly; /* only get the FTP dir list */ bool followlocation; /* follow http redirects */ diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 19454c84a..60a88e266 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -1722,24 +1722,22 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ } break; case 'i': - config->include_headers = toggle; /* include the headers as well in the - general output stream */ + config->show_headers = toggle; /* show the headers as well in the + general output stream */ break; case 'j': config->cookiesession = toggle; break; - case 'I': - /* - * no_body will imply include_headers later on - */ + case 'I': /* --head */ config->no_body = toggle; + config->show_headers = toggle; if(SetHTTPrequest(config, (config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET, &config->httpreq)) return PARAM_BAD_USE; break; case 'J': /* --remote-header-name */ - if(config->include_headers) { + if(config->show_headers) { warnf(global, "--include and --remote-header-name cannot be combined.\n"); return PARAM_BAD_USE; diff --git a/src/tool_operate.c b/src/tool_operate.c index 626c30888..5be862228 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2018, 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 @@ -851,15 +851,8 @@ static CURLcode operate_do(struct GlobalConfig *global, my_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize); my_setopt_str(curl, CURLOPT_URL, this_url); /* what to fetch */ my_setopt(curl, CURLOPT_NOPROGRESS, global->noprogress?1L:0L); - if(config->no_body) { + if(config->no_body) my_setopt(curl, CURLOPT_NOBODY, 1L); - my_setopt(curl, CURLOPT_HEADER, 1L); - } - /* If --metalink is used, we ignore --include (headers in - output) option because mixing headers to the body will - confuse XML parser and/or hash check will fail. */ - else if(!config->use_metalink) - my_setopt(curl, CURLOPT_HEADER, config->include_headers?1L:0L); if(config->oauth_bearer) my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer); @@ -1373,6 +1366,8 @@ static CURLcode operate_do(struct GlobalConfig *global, hdrcbdata.outs = &outs; hdrcbdata.heads = &heads; + hdrcbdata.global = global; + hdrcbdata.config = config; my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb); my_setopt(curl, CURLOPT_HEADERDATA, &hdrcbdata); @@ -1523,7 +1518,7 @@ static CURLcode operate_do(struct GlobalConfig *global, /* do not create (or even overwrite) the file in case we get no data because of unmet condition */ curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &cond_unmet); - if(!cond_unmet && !tool_create_output_file(&outs)) + if(!cond_unmet && !tool_create_output_file(&outs, FALSE)) result = CURLE_WRITE_ERROR; } diff --git a/tests/data/test1116 b/tests/data/test1116 index a9af3e61b..b72cbd60e 100644 --- a/tests/data/test1116 +++ b/tests/data/test1116 @@ -34,6 +34,8 @@ Transfer-Encoding: chunked Connection: mooo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc +chunky-trailer: header data +another-header: yes diff --git a/tests/data/test1319 b/tests/data/test1319 index 0520b1b32..f50c53165 100644 --- a/tests/data/test1319 +++ b/tests/data/test1319 @@ -31,9 +31,6 @@ body -HTTP/1.1 200 Mighty fine indeed -pop3: sure hit me - From: me@somewhere To: fake@nowhere diff --git a/tests/data/test1321 b/tests/data/test1321 index 266fd8828..ee1b47857 100644 --- a/tests/data/test1321 +++ b/tests/data/test1321 @@ -27,9 +27,6 @@ body yours sincerely -HTTP/1.1 200 Mighty fine indeed -imap: sure hit me - From: me@somewhere To: fake@nowhere diff --git a/tests/data/test1400 b/tests/data/test1400 index 0cef18dfd..10faef39b 100644 --- a/tests/data/test1400 +++ b/tests/data/test1400 @@ -70,7 +70,6 @@ int main(int argc, char *argv[]) hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1400"); - curl_easy_setopt(hnd, CURLOPT_HEADER, 1L); curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); diff --git a/tests/data/test1401 b/tests/data/test1401 index de4d0aa4f..f330931c9 100644 --- a/tests/data/test1401 +++ b/tests/data/test1401 @@ -82,7 +82,6 @@ int main(int argc, char *argv[]) hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1401"); - curl_easy_setopt(hnd, CURLOPT_HEADER, 1L); curl_easy_setopt(hnd, CURLOPT_USERPWD, "fake:user"); curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC); curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist1); diff --git a/tests/data/test1402 b/tests/data/test1402 index d2b05f562..9a9428376 100644 --- a/tests/data/test1402 +++ b/tests/data/test1402 @@ -75,7 +75,6 @@ int main(int argc, char *argv[]) hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1402"); - curl_easy_setopt(hnd, CURLOPT_HEADER, 1L); curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "foo=bar&baz=quux"); curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)16); curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); diff --git a/tests/data/test1403 b/tests/data/test1403 index b08728314..79cdf4964 100644 --- a/tests/data/test1403 +++ b/tests/data/test1403 @@ -72,7 +72,6 @@ int main(int argc, char *argv[]) hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1403?foo=bar&baz=quux"); - curl_easy_setopt(hnd, CURLOPT_HEADER, 1L); curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); diff --git a/tests/data/test1404 b/tests/data/test1404 index 53ab37b49..9c6f2e726 100644 --- a/tests/data/test1404 +++ b/tests/data/test1404 @@ -121,7 +121,6 @@ int main(int argc, char *argv[]) hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1404"); - curl_easy_setopt(hnd, CURLOPT_HEADER, 1L); mime1 = curl_mime_init(hnd); part1 = curl_mime_addpart(mime1); curl_mime_data(part1, "value", CURL_ZERO_TERMINATED); diff --git a/tests/data/test1405 b/tests/data/test1405 index f3ad3e795..73769eed1 100644 --- a/tests/data/test1405 +++ b/tests/data/test1405 @@ -85,7 +85,6 @@ int main(int argc, char *argv[]) hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_URL, "ftp://%HOSTIP:%FTPPORT/1405"); - curl_easy_setopt(hnd, CURLOPT_HEADER, 1L); curl_easy_setopt(hnd, CURLOPT_QUOTE, slist1); curl_easy_setopt(hnd, CURLOPT_POSTQUOTE, slist2); curl_easy_setopt(hnd, CURLOPT_PREQUOTE, slist3); diff --git a/tests/data/test1406 b/tests/data/test1406 index 033957f60..796dd2254 100644 --- a/tests/data/test1406 +++ b/tests/data/test1406 @@ -78,7 +78,6 @@ int main(int argc, char *argv[]) curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, (curl_off_t)38); curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/1406"); - curl_easy_setopt(hnd, CURLOPT_HEADER, 1L); curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L); curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); diff --git a/tests/data/test1407 b/tests/data/test1407 index 5a3de1b17..9800eeef3 100644 --- a/tests/data/test1407 +++ b/tests/data/test1407 @@ -59,7 +59,6 @@ int main(int argc, char *argv[]) hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_URL, "pop3://%HOSTIP:%POP3PORT/1407"); - curl_easy_setopt(hnd, CURLOPT_HEADER, 1L); curl_easy_setopt(hnd, CURLOPT_DIRLISTONLY, 1L); curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret"); curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); diff --git a/tests/data/test1417 b/tests/data/test1417 index 13ba6b168..4d3971ea8 100644 --- a/tests/data/test1417 +++ b/tests/data/test1417 @@ -35,6 +35,7 @@ Trailer: chunky-trailer Connection: mooo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc +chunky-trailer: header data diff --git a/tests/data/test1420 b/tests/data/test1420 index 38139e0b0..a5e1c5214 100644 --- a/tests/data/test1420 +++ b/tests/data/test1420 @@ -65,7 +65,6 @@ int main(int argc, char *argv[]) hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); curl_easy_setopt(hnd, CURLOPT_URL, "imap://%HOSTIP:%IMAPPORT/1420/;UID=1"); - curl_easy_setopt(hnd, CURLOPT_HEADER, 1L); curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret"); curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); diff --git a/tests/data/test2010 b/tests/data/test2010 index b8b3ddcc2..91a83f4dc 100644 --- a/tests/data/test2010 +++ b/tests/data/test2010 @@ -35,10 +35,10 @@ Metalink http -Metalink local XML file, HTTP resource, using -o fname -i -D file +Metalink local XML file, HTTP resource, using -o fname -D file ---metalink file://%PWD/log/test2010.metalink -i -o log/outfile2010 -D log/heads2010 +--metalink file://%PWD/log/test2010.metalink -o log/outfile2010 -D log/heads2010 # local metalink file written before test command runs diff --git a/tests/data/test266 b/tests/data/test266 index d520be0f4..6b07a782b 100644 --- a/tests/data/test266 +++ b/tests/data/test266 @@ -35,6 +35,7 @@ Trailer: chunky-trailer Connection: mooo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc +chunky-trailer: header data -- cgit v1.2.3