aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/src/tool_cb_hdr.c
diff options
context:
space:
mode:
authorMaxim Yurchuk <maxim-yurchuk@ydb.tech>2024-10-04 17:24:16 +0300
committerGitHub <noreply@github.com>2024-10-04 17:24:16 +0300
commita1e4766748b5924d3879ab6a0259b28ec3c5d535 (patch)
tree4480150864228623d6c9101a4ba8c049bda9aa90 /contrib/libs/curl/src/tool_cb_hdr.c
parent6536467764bed7822214815ce92ed4dcd5bf409b (diff)
parenta46fe128b9c9c84438fc2aac337aeefdaecb99df (diff)
downloadydb-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.c179
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 */