text: /*!
   * Connect - multipart
   * Copyright(c) 2010 Sencha Inc.
   * Copyright(c) 2011 TJ Holowaychuk
   * MIT Licensed
   */
  
  /**
   * Module dependencies.
   */
  
  var formidable = require('formidable')
      , _limit = require('./limit')
      , utils = require('../utils')
      , qs = require('qs');
  
  /**
   * noop middleware.
   */
  
  function noop(req, res, next) {
      next();
  }
  
  /**
   * Multipart:
   *
   * Parse multipart/form-data request bodies,
   * providing the parsed object as `req.body`
   * and `req.files`.
   *
   * Configuration:
   *
   *  The options passed are merged with [formidable](https://github.com/felixge/node-formidable)'s
   *  `IncomingForm` object, allowing you to configure the upload directory,
   *  size limits, etc. For example if you wish to change the upload dir do the following.
   *
   *     app.use(connect.multipart({ uploadDir: path }));
   *
   * Options:
   *
   *   - `limit`  byte limit defaulting to none
   *   - `defer`  defers processing and exposes the Formidable form object as `req.form`.
   *              `next()` is called without waiting for the form's "end" event.
   *              This option is useful if you need to bind to the "progress" event, for example.
   *
   * @param {Object} options
   * @return {Function}
   * @api public
   */
  
  exports = module.exports = function (options) {
      options = options || {};
  
      var limit = options.limit
          ? _limit(options.limit)
          : noop;
  
      return function multipart(req, res, next) {
          if (req._body) {
              return next();
          }
          req.body = req.body || {};
          req.files = req.files || {};
  
          if (!utils.hasBody(req)) {
              return next();
          }
  
          // ignore GET
          if ('GET' == req.method || 'HEAD' == req.method) {
              return next();
          }
  
          // check Content-Type
          if ('multipart/form-data' != utils.mime(req)) {
              return next();
          }
  
          // flag as parsed
          req._body = true;
  
          // parse
          limit(req, res, function (err) {
              if (err) {
                  return next(err);
              }
  
              var form = new formidable.IncomingForm
                  , data = {}
                  , files = {}
                  , done;
  
              Object.keys(options).forEach(function (key) {
                  form[key] = options[key];
              });
  
              function ondata(name, val, data) {
                  if (Array.isArray(data[name])) {
                      data[name].push(val);
                  } else if (data[name]) {
                      data[name] = [data[name], val];
                  } else {
                      data[name] = val;
                  }
              }
  
              form.on('field', function (name, val) {
                  ondata(name, val, data);
              });
  
              form.on('file', function (name, val) {
                  ondata(name, val, files);
              });
  
              form.on('error', function (err) {
                  if (!options.defer) {
                      err.status = 400;
                      next(err);
                  }
                  done = true;
              });
  
              form.on('end', function () {
                  if (done) {
                      return;
                  }
                  try {
                      req.body = qs.parse(data);
                      req.files = qs.parse(files);
                      if (!options.defer) {
                          next();
                      }
                  } catch (err) {
                      form.emit('error', err);
                  }
              });
  
              form.parse(req);
  
              if (options.defer) {
                  req.form = form;
                  next();
              }
          });
      }
  };
  