tool_cb_hdr: only parse etag + content-disposition for 2xx

... and ignore them for other response codes.

Reported-by: Harry Sintonen
Closes #12866
This commit is contained in:
Daniel Stenberg 2024-02-05 19:24:50 +01:00
parent 5cc2b016c3
commit 75d79a4486
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -105,12 +105,21 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
(void)fflush(heads->stream); (void)fflush(heads->stream);
} }
/* curl_easy_getinfo(per->curl, CURLINFO_SCHEME, &scheme);
* Write etag to file when --etag-save option is given. scheme = proto_token(scheme);
*/ if((scheme == proto_http || scheme == proto_https)) {
if(per->config->etag_save_file && etag_save->stream) { long response = 0;
/* match only header that start with etag (case insensitive) */ curl_easy_getinfo(per->curl, CURLINFO_RESPONSE_CODE, &response);
if(curl_strnequal(str, "etag:", 5)) {
if(response/100 != 2)
/* only care about these headers in 2xx 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 *etag_h = &str[5];
const char *eot = end - 1; const char *eot = end - 1;
if(*eot == '\n') { if(*eot == '\n') {
@ -128,77 +137,75 @@ 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 * This callback sets the filename where output shall be written when
* curl options --remote-name (-O) and --remote-header-name (-J) have * curl options --remote-name (-O) and --remote-header-name (-J) have
* been simultaneously given and additionally server returns an HTTP * been simultaneously given and additionally server returns an HTTP
* Content-Disposition header specifying a filename property. * Content-Disposition header specifying a filename property.
*/ */
curl_easy_getinfo(per->curl, CURLINFO_SCHEME, &scheme); else if(hdrcbdata->honor_cd_filename &&
scheme = proto_token(scheme); (cb > 20) && checkprefix("Content-disposition:", str)) {
if(hdrcbdata->honor_cd_filename && const char *p = str + 20;
(cb > 20) && checkprefix("Content-disposition:", str) &&
(scheme == proto_http || scheme == proto_https)) {
const char *p = str + 20;
/* look for the 'filename=' parameter /* look for the 'filename=' parameter
(encoded filenames (*=) are not supported) */ (encoded filenames (*=) are not supported) */
for(;;) { for(;;) {
char *filename; char *filename;
size_t len; size_t len;
while((p < end) && *p && !ISALPHA(*p)) while((p < end) && *p && !ISALPHA(*p))
p++;
if(p > end - 9)
break;
if(memcmp(p, "filename=", 9)) {
/* no match, find next parameter */
while((p < end) && *p && (*p != ';'))
p++; p++;
if((p < end) && *p) if(p > end - 9)
continue;
else
break; break;
}
p += 9;
/* this expression below typecasts 'cb' only to avoid if(memcmp(p, "filename=", 9)) {
warning: signed and unsigned type in conditional expression /* no match, find next parameter */
*/ while((p < end) && *p && (*p != ';'))
len = (ssize_t)cb - (p - str); p++;
filename = parse_filename(p, len); if((p < end) && *p)
if(filename) { continue;
if(outs->stream) { else
/* indication of problem, get out! */ break;
free(filename);
return CURL_WRITEFUNC_ERROR;
} }
p += 9;
if(per->config->output_dir) { /* this expression below typecasts 'cb' only to avoid
outs->filename = aprintf("%s/%s", per->config->output_dir, filename); warning: signed and unsigned type in conditional expression
free(filename); */
if(!outs->filename) 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;
}
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; return CURL_WRITEFUNC_ERROR;
} }
else break;
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; 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) { if(hdrcbdata->config->writeout) {
char *value = memchr(ptr, ':', cb); char *value = memchr(ptr, ':', cb);