diff options
author | Maxim Yurchuk <maxim-yurchuk@ydb.tech> | 2024-10-04 17:24:16 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-04 17:24:16 +0300 |
commit | a1e4766748b5924d3879ab6a0259b28ec3c5d535 (patch) | |
tree | 4480150864228623d6c9101a4ba8c049bda9aa90 /contrib/libs/curl/src/tool_cb_hdr.c | |
parent | 6536467764bed7822214815ce92ed4dcd5bf409b (diff) | |
parent | a46fe128b9c9c84438fc2aac337aeefdaecb99df (diff) | |
download | ydb-a1e4766748b5924d3879ab6a0259b28ec3c5d535.tar.gz |
Merge pull request #10090 from ydb-platform/mergelibs-241004-1110
Library import 241004-1110
Diffstat (limited to 'contrib/libs/curl/src/tool_cb_hdr.c')
-rw-r--r-- | contrib/libs/curl/src/tool_cb_hdr.c | 179 |
1 files changed, 105 insertions, 74 deletions
diff --git a/contrib/libs/curl/src/tool_cb_hdr.c b/contrib/libs/curl/src/tool_cb_hdr.c index 198a8d050c..969acac1e4 100644 --- a/contrib/libs/curl/src/tool_cb_hdr.c +++ b/contrib/libs/curl/src/tool_cb_hdr.c @@ -24,9 +24,10 @@ #include "tool_setup.h" #include "strcase.h" +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif -#define ENABLE_CURLX_PRINTF -/* use our own printf() functions */ #include "curlx.h" #include "tool_cfgable.h" @@ -47,7 +48,7 @@ static char *parse_filename(const char *ptr, size_t len); #else #define BOLD "\x1b[1m" /* Switch off bold by setting "all attributes off" since the explicit - bold-off code (21) isn't supported everywhere - like in the mac + bold-off code (21) is not supported everywhere - like in the mac Terminal. */ #define BOLDOFF "\x1b[0m" /* OSC 8 hyperlink escape sequence */ @@ -102,15 +103,29 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) if(rc != cb) return rc; /* flush the stream to send off what we got earlier */ - (void)fflush(heads->stream); + if(fflush(heads->stream)) { + errorf(per->config->global, "Failed writing headers to %s", + per->config->headerfile); + return CURL_WRITEFUNC_ERROR; + } } - /* - * Write etag to file when --etag-save option is given. - */ - if(per->config->etag_save_file && etag_save->stream) { - /* match only header that start with etag (case insensitive) */ - if(curl_strnequal(str, "etag:", 5)) { + curl_easy_getinfo(per->curl, CURLINFO_SCHEME, &scheme); + scheme = proto_token(scheme); + if((scheme == proto_http || scheme == proto_https)) { + long response = 0; + curl_easy_getinfo(per->curl, CURLINFO_RESPONSE_CODE, &response); + + if((response/100 != 2) && (response/100 != 3)) + /* only care about etag and content-disposition headers in 2xx and 3xx + responses */ + ; + /* + * Write etag to file when --etag-save option is given. + */ + else if(per->config->etag_save_file && etag_save->stream && + /* match only header that start with etag (case insensitive) */ + checkprefix("etag:", str)) { const char *etag_h = &str[5]; const char *eot = end - 1; if(*eot == '\n') { @@ -121,6 +136,19 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) if(eot >= etag_h) { size_t etag_length = eot - etag_h + 1; + /* + * Truncate the etag save stream, it can have an existing etag value. + */ +#ifdef HAVE_FTRUNCATE + if(ftruncate(fileno(etag_save->stream), 0)) { + return CURL_WRITEFUNC_ERROR; + } +#else + if(fseek(etag_save->stream, 0, SEEK_SET)) { + return CURL_WRITEFUNC_ERROR; + } +#endif + fwrite(etag_h, size, etag_length, etag_save->stream); /* terminate with newline */ fputc('\n', etag_save->stream); @@ -128,69 +156,72 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) } } } - } - /* - * This callback sets the filename where output shall be written when - * curl options --remote-name (-O) and --remote-header-name (-J) have - * been simultaneously given and additionally server returns an HTTP - * Content-Disposition header specifying a filename property. - */ + /* + * This callback sets the filename where output shall be written when + * curl options --remote-name (-O) and --remote-header-name (-J) have + * been simultaneously given and additionally server returns an HTTP + * Content-Disposition header specifying a filename property. + */ - curl_easy_getinfo(per->curl, CURLINFO_SCHEME, &scheme); - scheme = proto_token(scheme); - if(hdrcbdata->honor_cd_filename && - (cb > 20) && checkprefix("Content-disposition:", str) && - (scheme == proto_http || scheme == proto_https)) { - const char *p = str + 20; - - /* look for the 'filename=' parameter - (encoded filenames (*=) are not supported) */ - for(;;) { - char *filename; - size_t len; - - while((p < end) && *p && !ISALPHA(*p)) - p++; - if(p > end - 9) - break; + else if(hdrcbdata->honor_cd_filename && + (cb > 20) && checkprefix("Content-disposition:", str)) { + const char *p = str + 20; + + /* look for the 'filename=' parameter + (encoded filenames (*=) are not supported) */ + for(;;) { + char *filename; + size_t len; - if(memcmp(p, "filename=", 9)) { - /* no match, find next parameter */ - while((p < end) && *p && (*p != ';')) + while((p < end) && *p && !ISALPHA(*p)) p++; - if((p < end) && *p) - continue; - else + if(p > end - 9) break; - } - p += 9; - - /* this expression below typecasts 'cb' only to avoid - warning: signed and unsigned type in conditional expression - */ - len = (ssize_t)cb - (p - str); - filename = parse_filename(p, len); - if(filename) { - if(outs->stream) { - /* indication of problem, get out! */ - free(filename); - return CURL_WRITEFUNC_ERROR; - } - outs->is_cd_filename = TRUE; - outs->s_isreg = TRUE; - outs->fopened = FALSE; - outs->filename = filename; - outs->alloc_filename = TRUE; - hdrcbdata->honor_cd_filename = FALSE; /* done now! */ - if(!tool_create_output_file(outs, per->config)) - return CURL_WRITEFUNC_ERROR; + if(memcmp(p, "filename=", 9)) { + /* no match, find next parameter */ + while((p < end) && *p && (*p != ';')) + p++; + if((p < end) && *p) + continue; + else + break; + } + p += 9; + + len = cb - (size_t)(p - str); + filename = parse_filename(p, len); + if(filename) { + if(outs->stream) { + /* indication of problem, get out! */ + free(filename); + return CURL_WRITEFUNC_ERROR; + } + + if(per->config->output_dir) { + outs->filename = aprintf("%s/%s", per->config->output_dir, + filename); + free(filename); + if(!outs->filename) + return CURL_WRITEFUNC_ERROR; + } + else + outs->filename = filename; + + outs->is_cd_filename = TRUE; + outs->s_isreg = TRUE; + outs->fopened = FALSE; + outs->alloc_filename = TRUE; + hdrcbdata->honor_cd_filename = FALSE; /* done now! */ + if(!tool_create_output_file(outs, per->config)) + return CURL_WRITEFUNC_ERROR; + } + break; } - break; + if(!outs->stream && !tool_create_output_file(outs, per->config)) + return CURL_WRITEFUNC_ERROR; } - if(!outs->stream && !tool_create_output_file(outs, per->config)) - return CURL_WRITEFUNC_ERROR; } if(hdrcbdata->config->writeout) { char *value = memchr(ptr, ':', cb); @@ -240,7 +271,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) } /* - * Copies a file name part and returns an ALLOCATED data buffer. + * Copies a filename part and returns an ALLOCATED data buffer. */ static char *parse_filename(const char *ptr, size_t len) { @@ -281,7 +312,7 @@ static char *parse_filename(const char *ptr, size_t len) } /* If the filename contains a backslash, only use filename portion. The idea - is that even systems that don't handle backslashes as path separators + is that even systems that do not handle backslashes as path separators probably want the path removed for convenience. */ q = strrchr(p, '\\'); if(q) { @@ -292,7 +323,7 @@ static char *parse_filename(const char *ptr, size_t len) } } - /* make sure the file name doesn't end in \r or \n */ + /* make sure the filename does not end in \r or \n */ q = strchr(p, '\r'); if(q) *q = '\0'; @@ -316,17 +347,17 @@ static char *parse_filename(const char *ptr, size_t len) #endif /* _WIN32 || MSDOS */ /* in case we built debug enabled, we allow an environment variable - * named CURL_TESTDIR to prefix the given file name to put it into a + * named CURL_TESTDIR to prefix the given filename to put it into a * specific directory */ #ifdef DEBUGBUILD { - char *tdir = curlx_getenv("CURL_TESTDIR"); + char *tdir = curl_getenv("CURL_TESTDIR"); if(tdir) { char buffer[512]; /* suitably large */ msnprintf(buffer, sizeof(buffer), "%s/%s", tdir, copy); Curl_safefree(copy); - copy = strdup(buffer); /* clone the buffer, we don't use the libcurl + copy = strdup(buffer); /* clone the buffer, we do not use the libcurl aprintf() or similar since we want to use the same memory code as the "real" parse_filename function */ @@ -343,9 +374,9 @@ static char *parse_filename(const char *ptr, size_t len) * Treat the Location: header specially, by writing a special escape * sequence that adds a hyperlink to the displayed text. This makes * the absolute URL of the redirect clickable in supported terminals, - * which couldn't happen otherwise for relative URLs. The Location: + * which could not happen otherwise for relative URLs. The Location: * header is supposed to always be absolute so this theoretically - * shouldn't be needed but the real world returns plenty of relative + * should not be needed but the real world returns plenty of relative * URLs here. */ static @@ -417,7 +448,7 @@ void write_linked_location(CURL *curl, const char *location, size_t loclen, goto locdone; } - /* Not a "safe" URL: don't linkify it */ + /* Not a "safe" URL: do not linkify it */ locout: /* Write the normal output in case of error or unsafe */ |