You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

form-data

Package Overview
Dependencies
Maintainers
6
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

form-data - npm Package Compare versions

Comparing version

to
2.5.4

CHANGELOG.md

4

lib/browser.js

@@ -0,2 +1,4 @@

'use strict';
/* eslint-env browser */
module.exports = typeof self == 'object' ? self.FormData : window.FormData;
module.exports = typeof self === 'object' ? self.FormData : window.FormData;

@@ -0,1 +1,3 @@

'use strict';
var CombinedStream = require('combined-stream');

@@ -8,14 +10,10 @@ var util = require('util');

var fs = require('fs');
var crypto = require('crypto');
var mime = require('mime-types');
var asynckit = require('asynckit');
var hasOwn = require('hasown');
var setToStringTag = require('es-set-tostringtag');
var populate = require('./populate.js');
var Buffer = require('safe-buffer').Buffer; // eslint-disable-line no-shadow
var Buffer = require('safe-buffer').Buffer;
// Public API
module.exports = FormData;
// make it a Stream
util.inherits(FormData, CombinedStream);
/**

@@ -41,3 +39,3 @@ * Create readable "multipart/form-data" streams.

options = options || {};
for (var option in options) {
for (var option in options) { // eslint-disable-line no-restricted-syntax
this[option] = options[option];

@@ -47,6 +45,9 @@ }

// make it a Stream
util.inherits(FormData, CombinedStream);
FormData.LINE_BREAK = '\r\n';
FormData.DEFAULT_CONTENT_TYPE = 'application/octet-stream';
FormData.prototype.append = function(field, value, options) {
FormData.prototype.append = function (field, value, options) {

@@ -56,4 +57,4 @@ options = options || {};

// allow filename as single option
if (typeof options == 'string') {
options = {filename: options};
if (typeof options === 'string') {
options = { filename: options };
}

@@ -64,4 +65,4 @@

// all that streamy business can't handle numbers
if (typeof value == 'number') {
value = '' + value;
if (typeof value === 'number' || value == null) {
value = String(value);
}

@@ -71,4 +72,6 @@

if (Array.isArray(value)) {
// Please convert your array into string
// the way web server expects it
/*
* Please convert your array into string
* the way web server expects it
*/
this._error(new Error('Arrays are not supported.'));

@@ -89,11 +92,13 @@ return;

FormData.prototype._trackLength = function(header, value, options) {
FormData.prototype._trackLength = function (header, value, options) {
var valueLength = 0;
// used w/ getLengthSync(), when length is known.
// e.g. for streaming directly from a remote server,
// w/ a known file a size, and not wanting to wait for
// incoming file to finish to get its size.
/*
* used w/ getLengthSync(), when length is known.
* e.g. for streaming directly from a remote server,
* w/ a known file a size, and not wanting to wait for
* incoming file to finish to get its size.
*/
if (options.knownLength != null) {
valueLength += +options.knownLength;
valueLength += Number(options.knownLength);
} else if (Buffer.isBuffer(value)) {

@@ -108,8 +113,6 @@ valueLength = value.length;

// @check why add CRLF? does this account for custom/multiple CRLFs?
this._overheadLength +=
Buffer.byteLength(header) +
FormData.LINE_BREAK.length;
this._overheadLength += Buffer.byteLength(header) + FormData.LINE_BREAK.length;
// empty or either doesn't have path or not an http response
if (!value || ( !value.path && !(value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) )) {
if (!value || (!value.path && !(value.readable && hasOwn(value, 'httpVersion')))) {
return;

@@ -124,17 +127,21 @@ }

FormData.prototype._lengthRetriever = function(value, callback) {
if (Object.prototype.hasOwnProperty.call(value, 'fd')) {
FormData.prototype._lengthRetriever = function (value, callback) {
if (hasOwn(value, 'fd')) {
// take read range into a account
// `end` = Infinity –> read file till the end
//
// TODO: Looks like there is bug in Node fs.createReadStream
// it doesn't respect `end` options without `start` options
// Fix it when node fixes it.
// https://github.com/joyent/node/issues/7819
if (value.end != undefined && value.end != Infinity && value.start != undefined) {
/*
* take read range into a account
* `end` = Infinity –> read file till the end
*
* TODO: Looks like there is bug in Node fs.createReadStream
* it doesn't respect `end` options without `start` options
* Fix it when node fixes it.
* https://github.com/joyent/node/issues/7819
*/
if (value.end != null && value.end !== Infinity && value.start != null) {
// when end specified
// no need to calculate range
// inclusive, starts with 0
/*
* when end specified
* no need to calculate range
* inclusive, starts with 0
*/
callback(null, value.end + 1 - (value.start ? value.start : 0));

@@ -145,3 +152,3 @@

// still need to fetch file size from fs
fs.stat(value.path, function(err, stat) {
fs.stat(value.path, function (err, stat) {

@@ -162,11 +169,11 @@ var fileSize;

// or http response
} else if (Object.prototype.hasOwnProperty.call(value, 'httpVersion')) {
callback(null, +value.headers['content-length']);
} else if (hasOwn(value, 'httpVersion')) {
callback(null, Number(value.headers['content-length']));
// or request stream http://github.com/mikeal/request
} else if (Object.prototype.hasOwnProperty.call(value, 'httpModule')) {
} else if (hasOwn(value, 'httpModule')) {
// wait till response come back
value.on('response', function(response) {
value.on('response', function (response) {
value.pause();
callback(null, +response.headers['content-length']);
callback(null, Number(response.headers['content-length']));
});

@@ -181,7 +188,9 @@ value.resume();

FormData.prototype._multiPartHeader = function(field, value, options) {
// custom header specified (as string)?
// it becomes responsible for boundary
// (e.g. to handle extra CRLFs on .NET servers)
if (typeof options.header == 'string') {
FormData.prototype._multiPartHeader = function (field, value, options) {
/*
* custom header specified (as string)?
* it becomes responsible for boundary
* (e.g. to handle extra CRLFs on .NET servers)
*/
if (typeof options.header === 'string') {
return options.header;

@@ -194,11 +203,11 @@ }

var contents = '';
var headers = {
var headers = {
// add custom disposition as third element or keep it two elements if not
'Content-Disposition': ['form-data', 'name="' + field + '"'].concat(contentDisposition || []),
// if no content type. allow it to be empty array
'Content-Type': [].concat(contentType || [])
'Content-Type': [].concat(contentType || []),
};
// allow custom headers.
if (typeof options.header == 'object') {
if (typeof options.header === 'object') {
populate(headers, options.header);

@@ -208,4 +217,4 @@ }

var header;
for (var prop in headers) {
if (Object.prototype.hasOwnProperty.call(headers, prop)) {
for (var prop in headers) { // eslint-disable-line no-restricted-syntax
if (hasOwn(headers, prop)) {
header = headers[prop];

@@ -215,3 +224,3 @@

if (header == null) {
continue;
continue; // eslint-disable-line no-continue, no-restricted-syntax
}

@@ -234,17 +243,17 @@

FormData.prototype._getContentDisposition = function(value, options) {
FormData.prototype._getContentDisposition = function (value, options) {
var filename
, contentDisposition
;
var filename,
contentDisposition;
if (typeof options.filepath === 'string') {
// custom filepath for relative paths
filename = path.normalize(options.filepath).replace(/\\/g, '/');
} else if (options.filename || value.name || value.path) {
// custom filename take precedence
// formidable and the browser add a name property
// fs- and request- streams have path property
filename = path.basename(options.filename || value.name || value.path);
} else if (value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) {
} else if (options.filename || (value && (value.name || value.path))) {
/*
* custom filename take precedence
* formidable and the browser add a name property
* fs- and request- streams have path property
*/
filename = path.basename(options.filename || (value && (value.name || value.path)));
} else if (value && value.readable && hasOwn(value, 'httpVersion')) {
// or try http response

@@ -261,3 +270,3 @@ filename = path.basename(value.client._httpMessage.path || '');

FormData.prototype._getContentType = function(value, options) {
FormData.prototype._getContentType = function (value, options) {

@@ -268,3 +277,3 @@ // use custom content-type above all

// or try `name` from formidable, browser
if (!contentType && value.name) {
if (!contentType && value && value.name) {
contentType = mime.lookup(value.name);

@@ -274,3 +283,3 @@ }

// or try `path` from fs-, request- streams
if (!contentType && value.path) {
if (!contentType && value && value.path) {
contentType = mime.lookup(value.path);

@@ -280,3 +289,3 @@ }

// or if it's http-reponse
if (!contentType && value.readable && Object.prototype.hasOwnProperty.call(value, 'httpVersion')) {
if (!contentType && value && value.readable && hasOwn(value, 'httpVersion')) {
contentType = value.headers['content-type'];

@@ -291,3 +300,3 @@ }

// fallback to the default content type if `value` is not simple value
if (!contentType && typeof value == 'object') {
if (!contentType && value && typeof value === 'object') {
contentType = FormData.DEFAULT_CONTENT_TYPE;

@@ -299,7 +308,7 @@ }

FormData.prototype._multiPartFooter = function() {
return function(next) {
FormData.prototype._multiPartFooter = function () {
return function (next) {
var footer = FormData.LINE_BREAK;
var lastPart = (this._streams.length === 0);
var lastPart = this._streams.length === 0;
if (lastPart) {

@@ -313,14 +322,14 @@ footer += this._lastBoundary();

FormData.prototype._lastBoundary = function() {
FormData.prototype._lastBoundary = function () {
return '--' + this.getBoundary() + '--' + FormData.LINE_BREAK;
};
FormData.prototype.getHeaders = function(userHeaders) {
FormData.prototype.getHeaders = function (userHeaders) {
var header;
var formHeaders = {
'content-type': 'multipart/form-data; boundary=' + this.getBoundary()
'content-type': 'multipart/form-data; boundary=' + this.getBoundary(),
};
for (header in userHeaders) {
if (Object.prototype.hasOwnProperty.call(userHeaders, header)) {
for (header in userHeaders) { // eslint-disable-line no-restricted-syntax
if (hasOwn(userHeaders, header)) {
formHeaders[header.toLowerCase()] = userHeaders[header];

@@ -333,3 +342,10 @@ }

FormData.prototype.getBoundary = function() {
FormData.prototype.setBoundary = function (boundary) {
if (typeof boundary !== 'string') {
throw new TypeError('FormData boundary must be a string');
}
this._boundary = boundary;
};
FormData.prototype.getBoundary = function () {
if (!this._boundary) {

@@ -342,4 +358,4 @@ this._generateBoundary();

FormData.prototype.getBuffer = function() {
var dataBuffer = new Buffer.alloc(0);
FormData.prototype.getBuffer = function () {
var dataBuffer = Buffer.alloc(0);
var boundary = this.getBoundary();

@@ -352,11 +368,11 @@

// Add content to the buffer.
if(Buffer.isBuffer(this._streams[i])) {
dataBuffer = Buffer.concat( [dataBuffer, this._streams[i]]);
}else {
dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(this._streams[i])]);
if (Buffer.isBuffer(this._streams[i])) {
dataBuffer = Buffer.concat([dataBuffer, this._streams[i]]);
} else {
dataBuffer = Buffer.concat([dataBuffer, Buffer.from(this._streams[i])]);
}
// Add break after content.
if (typeof this._streams[i] !== 'string' || this._streams[i].substring( 2, boundary.length + 2 ) !== boundary) {
dataBuffer = Buffer.concat( [dataBuffer, Buffer.from(FormData.LINE_BREAK)] );
if (typeof this._streams[i] !== 'string' || this._streams[i].substring(2, boundary.length + 2) !== boundary) {
dataBuffer = Buffer.concat([dataBuffer, Buffer.from(FormData.LINE_BREAK)]);
}

@@ -367,24 +383,24 @@ }

// Add the footer and return the Buffer object.
return Buffer.concat( [dataBuffer, Buffer.from(this._lastBoundary())] );
return Buffer.concat([dataBuffer, Buffer.from(this._lastBoundary())]);
};
FormData.prototype._generateBoundary = function() {
FormData.prototype._generateBoundary = function () {
// This generates a 50 character boundary similar to those used by Firefox.
// They are optimized for boyer-moore parsing.
var boundary = '--------------------------';
for (var i = 0; i < 24; i++) {
boundary += Math.floor(Math.random() * 10).toString(16);
}
this._boundary = boundary;
this._boundary = '--------------------------' + crypto.randomBytes(12).toString('hex');
};
// Note: getLengthSync DOESN'T calculate streams length
// As workaround one can calculate file size manually
// and add it as knownLength option
FormData.prototype.getLengthSync = function() {
/*
* Note: getLengthSync DOESN'T calculate streams length
* As workaround one can calculate file size manually
* and add it as knownLength option
*/
FormData.prototype.getLengthSync = function () {
var knownLength = this._overheadLength + this._valueLength;
// Don't get confused, there are 3 "internal" streams for each keyval pair
// so it basically checks if there is any value added to the form
/*
* Don't get confused, there are 3 "internal" streams for each keyval pair
* so it basically checks if there is any value added to the form
*/
if (this._streams.length) {

@@ -396,5 +412,7 @@ knownLength += this._lastBoundary().length;

if (!this.hasKnownLength()) {
// Some async length retrievers are present
// therefore synchronous length calculation is false.
// Please use getLength(callback) to get proper length
/*
* Some async length retrievers are present
* therefore synchronous length calculation is false.
* Please use getLength(callback) to get proper length
*/
this._error(new Error('Cannot calculate proper length in synchronous way.'));

@@ -406,6 +424,8 @@ }

// Public API to check if length of added values is known
// https://github.com/form-data/form-data/issues/196
// https://github.com/form-data/form-data/issues/262
FormData.prototype.hasKnownLength = function() {
/*
* Public API to check if length of added values is known
* https://github.com/form-data/form-data/issues/196
* https://github.com/form-data/form-data/issues/262
*/
FormData.prototype.hasKnownLength = function () {
var hasKnownLength = true;

@@ -420,3 +440,3 @@

FormData.prototype.getLength = function(cb) {
FormData.prototype.getLength = function (cb) {
var knownLength = this._overheadLength + this._valueLength;

@@ -433,3 +453,3 @@

asynckit.parallel(this._valuesToMeasure, this._lengthRetriever, function(err, values) {
asynckit.parallel(this._valuesToMeasure, this._lengthRetriever, function (err, values) {
if (err) {

@@ -440,3 +460,3 @@ cb(err);

values.forEach(function(length) {
values.forEach(function (length) {
knownLength += length;

@@ -449,11 +469,12 @@ });

FormData.prototype.submit = function(params, cb) {
var request
, options
, defaults = {method: 'post'}
;
FormData.prototype.submit = function (params, cb) {
var request;
var options;
var defaults = { method: 'post' };
// parse provided url if it's string
// or treat it as options object
if (typeof params == 'string') {
/*
* parse provided url if it's string
* or treat it as options object
*/
if (typeof params === 'string') {

@@ -465,3 +486,3 @@ params = parseUrl(params);

host: params.hostname,
protocol: params.protocol
protocol: params.protocol,
}, defaults);

@@ -475,3 +496,3 @@

if (!options.port) {
options.port = options.protocol == 'https:' ? 443 : 80;
options.port = options.protocol === 'https:' ? 443 : 80;
}

@@ -484,3 +505,3 @@ }

// https if specified, fallback to http in any other case
if (options.protocol == 'https:') {
if (options.protocol === 'https:') {
request = https.request(options);

@@ -492,3 +513,3 @@ } else {

// get content length and fire away
this.getLength(function(err, length) {
this.getLength(function (err, length) {
if (err) {

@@ -512,3 +533,3 @@ this._error(err);

FormData.prototype._error = function(err) {
FormData.prototype._error = function (err) {
if (!this.error) {

@@ -525,1 +546,3 @@ this.error = err;

setToStringTag(FormData, 'FormData');
module.exports = FormData;

@@ -0,6 +1,6 @@

'use strict';
// populates missing values
module.exports = function(dst, src) {
Object.keys(src).forEach(function(prop)
{
module.exports = function (dst, src) {
Object.keys(src).forEach(function (prop) {
dst[prop] = dst[prop] || src[prop];

@@ -7,0 +7,0 @@ });

@@ -5,3 +5,3 @@ {

"description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.",
"version": "2.5.3",
"version": "2.5.4",
"repository": {

@@ -23,3 +23,2 @@ "type": "git",

"report": "istanbul report lcov text",
"ci-lint": "is-node-modern 8 && npm run lint || is-node-not-modern 8",
"ci-test": "npm run tests-only && npm run browser && npm run report",

@@ -34,10 +33,8 @@ "predebug": "rimraf coverage test/tmp",

"restore-readme": "mv README.md.bak README.md",
"prepublish": "in-publish && npm run update-readme || not-in-publish",
"postpublish": "npm run restore-readme"
"prepublish": "not-in-publish || npm run prepublishOnly",
"prepublishOnly": "npm run update-readme",
"postpublish": "npm run restore-readme",
"version": "auto-changelog && git add CHANGELOG.md",
"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
},
"pre-commit": [
"lint",
"ci-test",
"check"
],
"engines": {

@@ -50,2 +47,3 @@ "node": ">= 0.12"

"es-set-tostringtag": "^2.1.0",
"has-own": "^1.0.1",
"mime-types": "^2.1.35",

@@ -55,5 +53,4 @@ "safe-buffer": "^5.2.1"

"devDependencies": {
"@types/combined-stream": "^1.0.6",
"@types/mime-types": "^2.1.4",
"@types/node": "^12.20.55",
"@ljharb/eslint-config": "^21.2.0",
"auto-changelog": "^2.5.0",
"browserify": "^13.3.0",

@@ -63,3 +60,4 @@ "browserify-istanbul": "^2.0.0",

"cross-spawn": "^4.0.2",
"eslint": "^6.8.0",
"encoding": "^0.1.13",
"eslint": "=8.8.0",
"fake": "^0.2.2",

@@ -69,4 +67,4 @@ "far": "^0.0.7",

"in-publish": "^2.0.1",
"is-node-modern": "^1.0.0",
"istanbul": "^0.4.5",
"js-randomness-predictor": "^1.5.5",
"obake": "^0.1.2",

@@ -76,8 +74,17 @@ "phantomjs-prebuilt": "^2.1.16",

"pre-commit": "^1.2.2",
"puppeteer": "^1.20.0",
"request": "~2.87.0",
"rimraf": "^2.7.1",
"tape": "^5.9.0",
"typescript": "^3.9.10"
"semver": "^6.3.1",
"tape": "^5.9.0"
},
"license": "MIT"
"license": "MIT",
"auto-changelog": {
"output": "CHANGELOG.md",
"template": "keepachangelog",
"unreleased": false,
"commitLimit": false,
"backfillLimit": false,
"hideCredit": true
}
}