Skip to content

Commit

Permalink
Merge pull request #39 from hapijs/node14
Browse files Browse the repository at this point in the history
node 14. Closes #38
  • Loading branch information
hueniverse committed Jul 17, 2020
2 parents b99eebf + ec61203 commit ff5363e
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 146 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -2,6 +2,7 @@ language: node_js

node_js:
- "12"
- "14"
- "node"

sudo: false
Expand Down
284 changes: 138 additions & 146 deletions lib/index.js
Expand Up @@ -57,7 +57,7 @@ exports.Dispenser = internals.Dispenser = class extends Stream.Writable {

constructor(options) {

super();
super({ autoDestroy: false });

Hoek.assert(options !== null && typeof options === 'object', 'options must be an object');
const settings = Hoek.applyToDefaults(internals.defaults, options);
Expand Down Expand Up @@ -147,227 +147,219 @@ exports.Dispenser = internals.Dispenser = class extends Stream.Writable {
req.once('aborted', onReqAborted);
});
}
};

_write(buffer, encoding, next) {

internals.Dispenser.prototype._write = function (buffer, encoding, next) {
if (this._error) {
return next();
}

if (this._error) {
this._parts.write(buffer);
return next();
}

this._parts.write(buffer);
return next();
};

_emit(...args) {

internals.Dispenser.prototype._emit = function (...args) {
if (this._error) {
return;
}

if (this._error) {
return;
this.emit(...args);
}

this.emit(...args);
};


internals.Dispenser.prototype._abort = function (err) {
_abort(err) {

this._emit('error', err);
this._error = err;
};
this._emit('error', err);
this._error = err;
}

_onPartEnd() {

internals.Dispenser.prototype._onPartEnd = function () {
this._lines.flush();

this._lines.flush();
if (this._state === internals.state.preamble) {
if (this._held) {
const last = this._held.length - 1;

if (this._state === internals.state.preamble) {
if (this._held) {
const last = this._held.length - 1;
if (this._held[last] !== '\n' ||
this._held[last - 1] !== '\r') {

if (this._held[last] !== '\n' ||
this._held[last - 1] !== '\r') {
return this._abort(Boom.badRequest('Preamble missing CRLF terminator'));
}

return this._abort(Boom.badRequest('Preamble missing CRLF terminator'));
this._emit('preamble', this._held.slice(0, -2));
this._held = '';
}

this._emit('preamble', this._held.slice(0, -2));
this._held = '';
this._parts.needle(Buffer.from('\r\n--' + this._boundary)); // CRLF no longer optional
}

this._parts.needle(Buffer.from('\r\n--' + this._boundary)); // CRLF no longer optional
}

this._state = internals.state.boundary;
this._state = internals.state.boundary;

if (this._stream) {
this._stream.end();
this._stream = null;
}
else if (this._name) {
this._emit('field', this._name, this._held);
this._name = '';
this._held = '';
if (this._stream) {
this._stream.end();
this._stream = null;
}
else if (this._name) {
this._emit('field', this._name, this._held);
this._name = '';
this._held = '';
}
}
};


internals.Dispenser.prototype._onPart = function (chunk) {
_onPart(chunk) {

if (this._state === internals.state.preamble) {
this._held = this._held + chunk.toString();
}
else if (this._state === internals.state.payload) {
if (this._stream) {
this._stream.write(chunk); // Stream payload
if (this._state === internals.state.preamble) {
this._held = this._held + chunk.toString();
}
else if (this._state === internals.state.payload) {
if (this._stream) {
this._stream.write(chunk); // Stream payload
}
else {
this._held = this._held + chunk.toString();
}
}
else {
this._held = this._held + chunk.toString();
this._lines.write(chunk); // Look for boundary
}
}
else {
this._lines.write(chunk); // Look for boundary
}
};

_onLineEnd() {

internals.Dispenser.prototype._onLineEnd = function () {
// Boundary whitespace

// Boundary whitespace

if (this._state === internals.state.boundary) {
if (this._held) {
this._held = this._held.replace(/[\t ]/g, ''); // trim() removes new lines
if (this._state === internals.state.boundary) {
if (this._held) {
if (this._held === '--') {
this._state = internals.state.epilogue;
this._held = '';
this._held = this._held.replace(/[\t ]/g, ''); // trim() removes new lines
if (this._held) {
if (this._held === '--') {
this._state = internals.state.epilogue;
this._held = '';

return;
}
return;
}

return this._abort(Boom.badRequest('Only white space allowed after boundary'));
return this._abort(Boom.badRequest('Only white space allowed after boundary'));
}
}
}

this._state = internals.state.header;
this._state = internals.state.header;

return;
}
return;
}

// Part headers

// Part headers
if (this._state === internals.state.header) {

if (this._state === internals.state.header) {
// Header

// Header
if (this._held) {

if (this._held) {
// Header continuation

// Header continuation
if (this._held[0] === ' ' ||
this._held[0] === '\t') {

if (this._held[0] === ' ' ||
this._held[0] === '\t') {
if (!this._pendingHeader) {
return this._abort(Boom.badRequest('Invalid header continuation without valid declaration on previous line'));
}

if (!this._pendingHeader) {
return this._abort(Boom.badRequest('Invalid header continuation without valid declaration on previous line'));
this._pendingHeader = this._pendingHeader + ' ' + this._held.slice(1); // Drop tab
this._held = '';
return;
}

this._pendingHeader = this._pendingHeader + ' ' + this._held.slice(1); // Drop tab
// Start of new header

this._flushHeader();
this._pendingHeader = this._held;
this._held = '';

return;
}

// Start of new header
// End of headers

this._flushHeader();
this._pendingHeader = this._held;
this._held = '';

return;
}

// End of headers
this._state = internals.state.payload;

this._flushHeader();
let disposition;

this._state = internals.state.payload;

let disposition;
try {
disposition = Content.disposition(this._headers['content-disposition']);
}
catch (err) {
return this._abort(err);
}

try {
disposition = Content.disposition(this._headers['content-disposition']);
}
catch (err) {
return this._abort(err);
}
if (disposition.filename !== undefined) {
const stream = new Stream.PassThrough();
const transferEncoding = this._headers['content-transfer-encoding'];

if (disposition.filename !== undefined) {
const stream = new Stream.PassThrough();
const transferEncoding = this._headers['content-transfer-encoding'];
if (transferEncoding &&
transferEncoding.toLowerCase() === 'base64') {

if (transferEncoding &&
transferEncoding.toLowerCase() === 'base64') {
this._stream = new B64.Decoder();
this._stream.pipe(stream);
}
else {
this._stream = stream;
}

this._stream = new B64.Decoder();
this._stream.pipe(stream);
stream.name = disposition.name;
stream.filename = disposition.filename;
stream.headers = this._headers;
this._headers = {};
this._emit('part', stream);
}
else {
this._stream = stream;
this._name = disposition.name;
}

stream.name = disposition.name;
stream.filename = disposition.filename;
stream.headers = this._headers;
this._headers = {};
this._emit('part', stream);
}
else {
this._name = disposition.name;
this._lines.flush();
return;
}

this._lines.flush();
return;
}

// Epilogue

this._held = this._held + '\r\n'; // Put the new line back
};
// Epilogue

this._held = this._held + '\r\n'; // Put the new line back
}

internals.Dispenser.prototype._onLine = function (chunk) {
_onLine(chunk) {

if (this._stream) {
this._stream.write(chunk); // Stream payload
}
else {
this._held = this._held + chunk.toString(); // Reading header or field
if (this._stream) {
this._stream.write(chunk); // Stream payload
}
else {
this._held = this._held + chunk.toString(); // Reading header or field
}
}
};

_flushHeader() {

internals.Dispenser.prototype._flushHeader = function () {
if (!this._pendingHeader) {
return;
}

if (!this._pendingHeader) {
return;
}
const sep = this._pendingHeader.indexOf(':');

const sep = this._pendingHeader.indexOf(':');
if (sep === -1) {
return this._abort(Boom.badRequest('Invalid header missing colon separator'));
}

if (sep === -1) {
return this._abort(Boom.badRequest('Invalid header missing colon separator'));
}
if (!sep) {
return this._abort(Boom.badRequest('Invalid header missing field name'));
}

if (!sep) {
return this._abort(Boom.badRequest('Invalid header missing field name'));
}
const name = this._pendingHeader.slice(0, sep).toLowerCase();
if (name === '__proto__') {
return this._abort(Boom.badRequest('Invalid header'));
}

const name = this._pendingHeader.slice(0, sep).toLowerCase();
if (name === '__proto__') {
return this._abort(Boom.badRequest('Invalid header'));
this._headers[name] = this._pendingHeader.slice(sep + 1).trim();
this._pendingHeader = '';
}

this._headers[name] = this._pendingHeader.slice(sep + 1).trim();
this._pendingHeader = '';
};

0 comments on commit ff5363e

Please sign in to comment.