Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

the same field's value have different type 'enctype="multipart/form-data" ' #138

Open
blue5tar opened this Issue · 4 comments

3 participants

@blue5tar

sorry, my English is poor!!

<form method="post">
    <input type="checkbox" name="username" value="" />
    <input type="checkbox" name="username" value="" />
</form>

form.on('field', function(field, value) {
    if  (the form have  'enctype="multipart/form-data" ') {
        username is not a array 
    }
    if (the form have no 'enctype="multipart/form-data" ') {
        username is a array
    }
}
@svnlto
Collaborator

would you mind creating a test case for this?

@rcprior

Using the following script

var formidable = require('formidable'),
    http = require('http'),
    util = require('util');

http.createServer(function(req, res) {
  if (req.method.toLowerCase() == 'post') {
    // Parse an upload
    var form = new formidable.IncomingForm();

    form.parse(req, function(err, fields, files) {
      res.writeHead(200, {'content-type': 'text/plain'});
      res.end(util.inspect(fields));
    });

    return;

  } else if (req.method.toLowerCase() == 'get') {
    // Stream the form.html file
    res.writeHead(200, {'content-type': 'text/html'});
    res.write('<!DOCTYPE html>\n');
    res.end('<html><head><title>Bug</title></head><body><form method="post">' +
       '<input type="text" name="test" value="val1" />' +
       '<input type="text" name="test" value="val2" />' +
       '<input type="submit" value="Normal" />' +
       '<input type="submit" value="Multipart" formenctype="multipart/form-data" />' +
       '</form></body></html>');
  } else {
    res.writeHead(405, {'content-type': 'text/plain'});
    res.end('Method ' + req.method + ' not supported');
  }

}).listen(9000);

and point your browser at port 9000 of your server.
If you submit using the "Normal" button, no enctype is specified, and the form is submitted with enctype="application/x-www-form-urlencoded". Server will output

{ test: [ 'val1', 'val2' ] }

However, if you hit the "Multipart" button, the form is submitted with enctype="multipart/form-data", and the output will be

{ test: 'val2' }

I.e., if you have a field with multiple values (e.g., a select multiple), only the last selected value will be available.

@rcprior

To fix this issue, please apply the following patch:

--- incoming_form.js       2013-11-04 17:47:08.407799172 +0000
+++ incoming_form.js    2013-11-04 17:54:00.845847743 +0000
@@ -80,7 +80,14 @@
     var fields = {}, files = {};
     this
       .on('field', function(name, value) {
-        fields[name] = value;
+        if (fields.hasOwnProperty(name)) {
+          if (!(fields[name] instanceof Array)) {
+            fields[name] = [ fields[name] ];
+          }
+          fields[name].push(value);
+        } else {
+          fields[name] = value;
+        }
       })
       .on('file', function(name, file) {
         files[name] = file;
@rcprior

By the way, a similar problem to multi-valued fields occurs with the submission of a form with multiple file fields having the same name. In this case, several temporary files will be created, but the main script will only see the last one. The temporary files that were not seen by the main script can accumulate until they take up all disk space, thus opening a vector for a denial of service attack.
The solution is applying the same principle of normal fields to file fields (i.e., passing a vector when multiple file fields with the same name are submitted).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.