diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c index 969acac1e4..1b0348d23c 100644 --- a/src/tool_cb_hdr.c +++ b/src/tool_cb_hdr.c @@ -62,6 +62,25 @@ static void write_linked_location(CURL *curl, const char *location, size_t loclen, FILE *stream); #endif +int tool_write_headers(struct HdrCbData *hdrcbdata, FILE *stream) +{ + struct curl_slist *h = hdrcbdata->headlist; + int rc = 1; + while(h) { + /* not "handled", just show it */ + size_t len = strlen(h->data); + if(len != fwrite(h->data, 1, len, stream)) + goto fail; + h = h->next; + } + rc = 0; /* success */ +fail: + curl_slist_free_all(hdrcbdata->headlist); + hdrcbdata->headlist = NULL; + return rc; +} + + /* ** callback for CURLOPT_HEADERFUNCTION */ @@ -164,63 +183,90 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) * Content-Disposition header specifying a filename property. */ - else if(hdrcbdata->honor_cd_filename && - (cb > 20) && checkprefix("Content-disposition:", str)) { - const char *p = str + 20; + else if(hdrcbdata->honor_cd_filename) { + if((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; + /* 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; - - 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; - 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(memcmp(p, "filename=", 9)) { + /* no match, find next parameter */ + while((p < end) && *p && (*p != ';')) + p++; + if((p < end) && *p) + continue; + else + break; } + p += 9; - if(per->config->output_dir) { - outs->filename = aprintf("%s/%s", per->config->output_dir, - filename); - free(filename); - if(!outs->filename) + 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; + if(tool_write_headers(&per->hdrcbdata, outs->stream)) 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(tool_write_headers(&per->hdrcbdata, outs->stream)) + return CURL_WRITEFUNC_ERROR; + } /* content-disposition handling */ + + if(hdrcbdata->honor_cd_filename && + hdrcbdata->config->show_headers) { + /* still awaiting the Content-Disposition header, store the header in + memory. Since it is not zero terminated, we need an extra dance. */ + char *clone = aprintf("%.*s", (int)cb, (char *)str); + if(clone) { + struct curl_slist *old = hdrcbdata->headlist; + hdrcbdata->headlist = curl_slist_append(old, clone); + free(clone); + if(!hdrcbdata->headlist) { + curl_slist_free_all(old); + return CURL_WRITEFUNC_ERROR; + } + } + else { + curl_slist_free_all(hdrcbdata->headlist); + hdrcbdata->headlist = NULL; + return CURL_WRITEFUNC_ERROR; + } + return cb; /* done for now */ } - if(!outs->stream && !tool_create_output_file(outs, per->config)) - return CURL_WRITEFUNC_ERROR; } } if(hdrcbdata->config->writeout) { diff --git a/src/tool_cb_hdr.h b/src/tool_cb_hdr.h index a855052d0d..7402c12a9b 100644 --- a/src/tool_cb_hdr.h +++ b/src/tool_cb_hdr.h @@ -46,9 +46,12 @@ struct HdrCbData { struct OutStruct *outs; struct OutStruct *heads; struct OutStruct *etag_save; + struct curl_slist *headlist; bool honor_cd_filename; }; +int tool_write_headers(struct HdrCbData *hdrcbdata, FILE *stream); + /* ** callback for CURLOPT_HEADERFUNCTION */ diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c index e35489a39f..f25a481503 100644 --- a/src/tool_cb_wrt.c +++ b/src/tool_cb_wrt.c @@ -345,7 +345,13 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) } else #endif + { + if(per->hdrcbdata.headlist) { + if(tool_write_headers(&per->hdrcbdata, outs->stream)) + return CURL_WRITEFUNC_ERROR; + } rc = fwrite(buffer, sz, nmemb, outs->stream); + } if(bytes == rc) /* we added this amount of data to the output */ diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 7a38992a9e..9a5de1e731 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -2763,9 +2763,7 @@ ParameterError parse_args(struct GlobalConfig *global, int argc, } if(!result && config->content_disposition) { - if(config->show_headers) - result = PARAM_CONTDISP_SHOW_HEADER; - else if(config->resume_from_current) + if(config->resume_from_current) result = PARAM_CONTDISP_RESUME_FROM; } diff --git a/src/tool_getparam.h b/src/tool_getparam.h index 9d6c72ef82..b22e60b7b3 100644 --- a/src/tool_getparam.h +++ b/src/tool_getparam.h @@ -342,7 +342,6 @@ typedef enum { PARAM_NO_PREFIX, PARAM_NUMBER_TOO_LARGE, PARAM_NO_NOT_BOOLEAN, - PARAM_CONTDISP_SHOW_HEADER, /* --include and --remote-header-name */ PARAM_CONTDISP_RESUME_FROM, /* --continue-at and --remote-header-name */ PARAM_READ_ERROR, PARAM_EXPAND_ERROR, /* --expand problem */ diff --git a/src/tool_helpers.c b/src/tool_helpers.c index 2e15144b7b..02193c3e51 100644 --- a/src/tool_helpers.c +++ b/src/tool_helpers.c @@ -67,8 +67,6 @@ const char *param2text(ParameterError error) return "too large number"; case PARAM_NO_NOT_BOOLEAN: return "used '--no-' for option that is not a boolean"; - case PARAM_CONTDISP_SHOW_HEADER: - return "showing headers and --remote-header-name cannot be combined"; case PARAM_CONTDISP_RESUME_FROM: return "--continue-at and --remote-header-name cannot be combined"; case PARAM_READ_ERROR: diff --git a/src/tool_operate.c b/src/tool_operate.c index 5b51243374..0a959a8bcd 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -770,7 +770,8 @@ skip: free(per->uploadfile); if(global->parallel) free(per->errorbuffer); - + curl_slist_free_all(per->hdrcbdata.headlist); + per->hdrcbdata.headlist = NULL; return result; } diff --git a/tests/data/DISABLED b/tests/data/DISABLED index 80f835d4b7..45b0753658 100644 --- a/tests/data/DISABLED +++ b/tests/data/DISABLED @@ -75,6 +75,7 @@ # 1021 re-added here due to flakiness 1021 1417 +1460 1533 1540 1591 diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 90442d80e3..5b028a05b2 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -170,7 +170,7 @@ test1271 test1272 test1273 test1274 test1275 test1276 test1277 test1278 \ test1279 test1280 test1281 test1282 test1283 test1284 test1285 test1286 \ test1287 test1288 test1289 test1290 test1291 test1292 test1293 test1294 \ test1295 test1296 test1297 test1298 test1299 test1300 test1301 test1302 \ -test1303 test1304 test1305 test1306 test1307 test1308 test1309 \ +test1303 test1304 test1305 test1306 test1307 test1308 test1309 test1310 \ test1311 test1312 test1313 test1314 test1315 test1316 test1317 test1318 \ test1319 test1320 test1321 test1322 test1323 test1324 test1325 test1326 \ test1327 test1328 test1329 test1330 test1331 test1332 test1333 test1334 \ @@ -193,7 +193,7 @@ test1455 test1456 test1457 test1458 test1459 test1460 test1461 test1462 \ test1463 test1464 test1465 test1466 test1467 test1468 test1469 test1470 \ test1471 test1472 test1473 test1474 test1475 test1476 test1477 test1478 \ test1479 test1480 test1481 test1482 test1483 test1484 test1485 test1486 \ -test1487 test1488 test1489 test1490 test1491 \ +test1487 test1488 test1489 test1490 test1491 test1492 \ \ test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \ diff --git a/tests/data/test1310 b/tests/data/test1310 new file mode 100644 index 0000000000..49bb0d36df --- /dev/null +++ b/tests/data/test1310 @@ -0,0 +1,63 @@ + + + +HTTP +HTTP GET +-J +--show-headers + + + +# + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Length: 6 +Connection: close +Content-Disposition: inline; filename="name%TESTNUMBER" +Content-Type: text/html + +12345 + + + +# +# Client-side + + +http + + +HTTP GET with -J + --show-headers + + +http://%HOSTIP:%HTTPPORT/junk -J -O --show-headers --output-dir %LOGDIR + + + +# +# Verify data after the test has been "shot" + + +GET /junk HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Length: 6 +Connection: close +Content-Disposition: inline; filename="name%TESTNUMBER" +Content-Type: text/html + +12345 + + + + diff --git a/tests/data/test1460 b/tests/data/test1460 index 4e85082e38..7422d4b99b 100644 --- a/tests/data/test1460 +++ b/tests/data/test1460 @@ -11,33 +11,26 @@ HTTP GET HTTP/1.1 200 swsclose - 12345 -fooo -54 3 2 1 +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake Content-Disposition: filename=name%TESTNUMBER; charset=funny; option=strange +Content-Length: 4 +hej # # Client-side -# this relies on the debug feature to allow us to set directory to store the -# -J output in - -Debug - http HTTP GET with -Ji and Content-Disposition with existing file - -CURL_TESTDIR=%LOGDIR - -http://%HOSTIP:%HTTPPORT/%TESTNUMBER -Ji -O +http://%HOSTIP:%HTTPPORT/%TESTNUMBER -Ji -O --output-dir %LOGDIR initial content @@ -47,9 +40,9 @@ initial content # # Verify data after the test has been "shot" -# Warning: --include and --remote-header-name cannot be combined. +# Warning: Failed to open the file log/name1460: File exists -2 +23 initial content diff --git a/tests/data/test1492 b/tests/data/test1492 new file mode 100644 index 0000000000..2e7e1f32ae --- /dev/null +++ b/tests/data/test1492 @@ -0,0 +1,63 @@ + + + +HTTP +HTTP GET +-J +--show-headers + + + +# + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Length: 6 +Connection: close +Content-Jisposition: inline; filename="name%TESTNUMBER" +Content-Type: text/html + +12345 + + + +# +# Client-side + + +http + + +HTTP GET with -J + --show-headers but no Content-Disposition: + + +http://%HOSTIP:%HTTPPORT/junk%TESTNUMBER -J -O --show-headers --output-dir %LOGDIR + + + +# +# Verify data after the test has been "shot" + + +GET /junk%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Length: 6 +Connection: close +Content-Jisposition: inline; filename="name%TESTNUMBER" +Content-Type: text/html + +12345 + + + +