diff options
| -rw-r--r-- | docs/MANUAL | 7 | ||||
| -rw-r--r-- | docs/curl.1 | 6 | ||||
| -rw-r--r-- | src/main.c | 21 | ||||
| -rw-r--r-- | tests/data/test39 | 12 | 
4 files changed, 38 insertions, 8 deletions
diff --git a/docs/MANUAL b/docs/MANUAL index 26bb8f65a..86449d7d3 100644 --- a/docs/MANUAL +++ b/docs/MANUAL @@ -299,6 +299,13 @@ POST (HTTP)          curl -F "docpicture=@dog.gif" -F "catpicture=@cat.gif"  +  To send a field value literally without interpreting a leading '@' +  or '<', or an embedded ';type=', use --form-string instead of +  -F. This is recommended when the value is obtained from a user or +  some other unpredictable source. Under these circumstances, using +  -F instead of --form-string would allow a user to trick curl into +  uploading a file. +  REFERRER    A HTTP request has the option to include information about which address diff --git a/docs/curl.1 b/docs/curl.1 index 3b6fb3ce1..f216db68f 100644 --- a/docs/curl.1 +++ b/docs/curl.1 @@ -388,6 +388,12 @@ setting filename=, like this:  See further examples and details in the MANUAL.  This option can be used multiple times. +.IP "--form-string <name=string>" +(HTTP) Similar to \fI--form\fP except that the value string for the named +parameter is used literally. Leading \&'@' and \&'<' characters, and the +\&';type=' string in the value have no special meaning. Use this in +preference to \fI--form\fP if there's any possibility that the string value +may accidentally trigger the \&'@' or \&'<' features of \fI--form\f{.  .IP "-g/--globoff"  This option switches off the "URL globbing parser". When you set this option,  you can specify URLs that contain the letters {}[] without having them being diff --git a/src/main.c b/src/main.c index 0565abd42..298d40153 100644 --- a/src/main.c +++ b/src/main.c @@ -355,6 +355,7 @@ static void help(void)      "    --ftp-pasv      Use PASV instead of PORT (F)",      "    --ftp-ssl       Enable SSL/TLS for the ftp transfer (F)",      " -F/--form <name=content> Specify HTTP multipart POST data (H)", +    "    --form-string <name=string> Specify HTTP multipart POST data (H)",      " -g/--globoff       Disable URL sequences and ranges using {} and []",      " -G/--get           Send the -d data with a HTTP GET (H)",      " -h/--help          This help text", @@ -774,6 +775,9 @@ static void list_engines (const struct curl_slist *engines)   * Specify files to upload with 'name=@filename'. Supports specified   * given Content-Type of the files. Such as ';type=<content-type>'.   * + * If literal_value is set, any initial '@' or '<' in the value string + * loses its special meaning, as does any embedded ';type='. + *   * You may specify more than one file for a single name (field). Specify   * multiple files by writing it like:   * @@ -804,7 +808,8 @@ static void list_engines (const struct curl_slist *engines)  static int formparse(char *input,                       struct curl_httppost **httppost, -                     struct curl_httppost **last_post) +                     struct curl_httppost **last_post, +                     bool literal_value)  {    /* nextarg MUST be a string in the format 'name=contents' and we'll       build a linked list with the info */ @@ -829,7 +834,7 @@ static int formparse(char *input,      }      contp = contents; -    if('@' == contp[0]) { +    if('@' == contp[0] && !literal_value) {        struct multi_files *multi_start = NULL, *multi_current = NULL;        /* we use the @-letter to indicate file name(s) */        contp++; @@ -974,7 +979,7 @@ static int formparse(char *input,      else {        struct curl_forms info[4];        int i = 0; -      char *ct = strstr(contp, ";type="); +      char *ct = literal_value? NULL: strstr(contp, ";type=");        info[i].option = CURLFORM_COPYNAME;        info[i].value = name; @@ -987,7 +992,7 @@ static int formparse(char *input,          ct[0]=0; /* zero terminate here */        } -      if( contp[0]=='<' ) { +      if( contp[0]=='<' && !literal_value) {          info[i].option = CURLFORM_FILECONTENT;          info[i].value = contp+1;          i++; @@ -1280,6 +1285,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */      {"Eg","capath ",     TRUE},      {"f", "fail",        FALSE},      {"F", "form",        TRUE}, +    {"Fs","form-string", TRUE},      {"g", "globoff",     FALSE},      {"G", "get",         FALSE},      {"h", "help",        FALSE}, @@ -1361,8 +1367,10 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */    do {      /* we can loop here if we have multiple single-letters */ -    if(!longopt) +    if(!longopt) {        letter = parse?(char)*parse:'\0'; +      subletter='\0'; +    }      else {        letter = parse[0];        subletter = parse[1]; @@ -1833,7 +1841,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */           to sort this out slowly and carefully */        if(formparse(nextarg,                     &config->httppost, -                   &config->last_post)) +                   &config->last_post, +                   subletter=='s')) /* 's' means literal string */          return PARAM_BAD_USE;        if(SetHTTPrequest(HTTPREQ_POST, &config->httpreq))          return PARAM_BAD_USE; diff --git a/tests/data/test39 b/tests/data/test39 index 29f6cc398..7c0028762 100644 --- a/tests/data/test39 +++ b/tests/data/test39 @@ -19,7 +19,7 @@ http  HTTP RFC1867-type formposting with filename= and type=   </name>   <command> -http://%HOSTIP:%HTTPPORT/we/want/39 -F name=daniel -F tool=curl -F "file=@log/test39.txt;filename=fakerfile;type=moo/foobar" -F file2=@log/test39.txt +http://%HOSTIP:%HTTPPORT/we/want/39 -F name=daniel -F tool=curl --form-string "str1=@literal" --form-string "str2=<verbatim;type=xxx/yyy" -F "file=@log/test39.txt;filename=fakerfile;type=moo/foobar" -F file2=@log/test39.txt  </command>  # We create this file before the command is invoked!  <file name="log/test39.txt"> @@ -41,7 +41,7 @@ User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 z  Host: 127.0.0.1:%HTTPPORT
  Pragma: no-cache
  Accept: */*
 -Content-Length: 594
 +Content-Length: 810
  Expect: 100-continue
  Content-Type: multipart/form-data; boundary=----------------------------24e78000bd32
 @@ -54,6 +54,14 @@ Content-Disposition: form-data; name="tool"  curl
  ------------------------------24e78000bd32
 +Content-Disposition: form-data; name="str1"
 +
 +@literal
 +------------------------------24e78000bd32
 +Content-Disposition: form-data; name="str2"
 +
 +<verbatim;type=xxx/yyy
 +------------------------------24e78000bd32
  Content-Disposition: form-data; name="file"; filename="fakerfile"
  Content-Type: moo/foobar
  | 
