diff --git a/src/tool_formparse.c b/src/tool_formparse.c index 0f0962ce0d..004ad6ff4c 100644 --- a/src/tool_formparse.c +++ b/src/tool_formparse.c @@ -28,6 +28,7 @@ #include "tool_getparam.h" #include "tool_paramhlp.h" #include "tool_formparse.h" +#include "tool_parsecfg.h" #include "memdebug.h" /* keep this as LAST include */ @@ -417,65 +418,63 @@ static int slist_append(struct curl_slist **plist, const char *data) } /* Read headers from a file and append to list. */ -static int read_field_headers(const char *filename, FILE *fp, - struct curl_slist **pheaders) +static int read_field_headers(FILE *fp, struct curl_slist **pheaders) { - size_t hdrlen = 0; - size_t pos = 0; - bool incomment = FALSE; - int lineno = 1; - char hdrbuf[999] = ""; /* Max. header length + 1. */ + struct dynbuf line; + bool error = FALSE; + int err = 0; - for(;;) { - int c = getc(fp); - if(c == EOF || (!pos && !ISSPACE(c))) { - /* Strip and flush the current header. */ - while(hdrlen && ISSPACE(hdrbuf[hdrlen - 1])) - hdrlen--; - if(hdrlen) { - hdrbuf[hdrlen] = '\0'; - if(slist_append(pheaders, hdrbuf)) { - errorf("Out of memory for field headers"); - return -1; - } - hdrlen = 0; + curlx_dyn_init(&line, 8092); + while(my_get_line(fp, &line, &error)) { + const char *ptr = curlx_dyn_ptr(&line); + size_t len = curlx_dyn_len(&line); + bool folded = FALSE; + if(ptr[0] == '#') /* comment */ + continue; + else if(ptr[0] == ' ') /* a continuation from the line before */ + folded = TRUE; + /* trim off trailing CRLFs and whitespaces */ + while(len && (ISNEWLINE(ptr[len -1]) || ISBLANK(ptr[len - 1]))) + len--; + + if(!len) + continue; + curlx_dyn_setlen(&line, len); /* set the new length */ + + if(folded && *pheaders) { + /* append this new line onto the previous line */ + struct dynbuf amend; + struct curl_slist *l = *pheaders; + curlx_dyn_init(&amend, 8092); + /* find the last node */ + while(l && l->next) + l = l->next; + /* add both parts */ + if(curlx_dyn_add(&amend, l->data) || curlx_dyn_addn(&amend, ptr, len)) { + err = -1; + break; + } + curl_free(l->data); + /* we use maprintf here to make it a libcurl alloc, to match the previous + curl_slist_append */ + l->data = curl_maprintf("%s", curlx_dyn_ptr(&amend)); + curlx_dyn_free(&amend); + if(!l->data) { + errorf("Out of memory for field headers"); + err = 1; } } - - switch(c) { - case EOF: - if(ferror(fp)) { - char errbuf[STRERROR_LEN]; - errorf("Header file %s read error: %s", filename, - curlx_strerror(errno, errbuf, sizeof(errbuf))); - return -1; - } - return 0; /* Done. */ - case '\r': - continue; /* Ignore. */ - case '\n': - pos = 0; - incomment = FALSE; - lineno++; - continue; - case '#': - if(!pos) - incomment = TRUE; + else { + err = slist_append(pheaders, ptr); + } + if(err) { + errorf("Out of memory for field headers"); + err = -1; break; } - - pos++; - if(!incomment) { - if(hdrlen == sizeof(hdrbuf) - 1) { - warnf("File %s line %d: header too long (truncated)", - filename, lineno); - c = ' '; - } - if(hdrlen <= sizeof(hdrbuf) - 1) - hdrbuf[hdrlen++] = (char) c; - } } - /* NOTREACHED */ + curlx_dyn_free(&line); + return err; } static int get_param_part(char endchar, @@ -572,7 +571,7 @@ static int get_param_part(char endchar, curlx_strerror(errno, errbuf, sizeof(errbuf))); } else { - int i = read_field_headers(hdrfile, fp, &headers); + int i = read_field_headers(fp, &headers); curlx_fclose(fp); if(i) { diff --git a/tests/data/test646 b/tests/data/test646 index 4f26dbdf92..fe86e32775 100644 --- a/tests/data/test646 +++ b/tests/data/test646 @@ -42,7 +42,7 @@ It may contain any type of data. X-fileheader1: This is a header from a file # This line is another comment. It precedes a folded header. -X-fileheader2: This is #a +X-fileheader2: This is #a folded header