@goa/busboy
Version:
[fork] A Streaming Parser For HTML Form Data For Node.JS.
711 lines (709 loc) • 20.7 kB
JavaScript
'use strict';
const stream = require('stream');
const events = require('events');
const t = stream.Readable, w = stream.Writable;
const C = events.EventEmitter;
/*
MIT streamsearch by Brian White
https://github.com/mscdex/streamsearch
*/
function D(a, c, d, e, f) {
for (var b = 0; b < f; ++b, ++c, ++e) {
if (a[c] !== d[e]) {
return !1;
}
}
return !0;
}
function J(a, c) {
var d = c.length, e = a.h, f = e.length, b = -a.a, h = e[f - 1], g = a.g, k = a.f;
if (0 > b) {
for (; 0 > b && b <= d - f;) {
var n = b + f - 1;
n = 0 > n ? a.f[a.a + n] : c[n];
if (n === h && K(a, c, b, f - 1)) {
return a.a = 0, ++a.c, b > -a.a ? a.emit("info", !0, k, 0, a.a + b) : a.emit("info", !0), a.b = b + f;
}
b += g[n];
}
if (0 > b) {
for (; 0 > b && !K(a, c, b, d - b);) {
b++;
}
}
if (0 <= b) {
a.emit("info", !1, k, 0, a.a), a.a = 0;
} else {
return e = a.a + b, 0 < e && a.emit("info", !1, k, 0, e), k.copy(k, 0, e, a.a - e), a.a -= e, c.copy(k, a.a), a.a += d, a.b = d;
}
}
for (0 <= b && (b += a.b); b <= d - f;) {
n = c[b + f - 1];
if (n === h && c[b] === e[0] && D(e, 0, c, b, f - 1)) {
return ++a.c, 0 < b ? a.emit("info", !0, c, a.b, b) : a.emit("info", !0), a.b = b + f;
}
b += g[n];
}
if (b < d) {
for (; b < d && (c[b] !== e[0] || !D(c, b, e, 0, d - b));) {
++b;
}
b < d && (c.copy(k, 0, b, b + (d - b)), a.a = d - b);
}
0 < b && a.emit("info", !1, c, a.b, b < d ? b : d);
return a.b = d;
}
function K(a, c, d, e) {
for (var f = 0; f < e;) {
var b = d + f;
if ((0 > b ? a.f[a.a + b] : c[b]) === a.h[f]) {
++f;
} else {
return !1;
}
}
return !0;
}
class L extends C {
constructor(a) {
super();
"string" === typeof a && (a = new Buffer(a));
var c, d = a.length;
this.i = Infinity;
this.c = 0;
this.g = Array(256);
this.a = 0;
this.h = a;
this.b = 0;
this.f = new Buffer(d);
for (c = 0; 256 > c; ++c) {
this.g[c] = d;
}
if (1 <= d) {
for (c = 0; c < d - 1; ++c) {
this.g[a[c]] = d - 1 - c;
}
}
}
push(a, c = 0) {
Buffer.isBuffer(a) || (a = new Buffer(a, "binary"));
var d = a.length;
for (this.b = c; e !== d && this.c < this.i;) {
var e = J(this, a);
}
return e;
}
}
;class M extends t {
constructor(a) {
super(a);
}
_read() {
}
}
;const aa = Buffer.from("\r\n\r\n"), ba = /\r\n/g, ca = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/;
function da(a) {
a.g = !1;
a.b = "";
a.a = {};
a = a.f;
a.a = 0;
a.c = 0;
a.b = 0;
}
class ea extends C {
constructor(a = {}) {
super();
({maxHeaderPairs:a = 2000} = a);
this.c = 0;
this.h = !1;
this.i = 0;
this.maxHeaderPairs = a;
this.b = "";
this.a = {};
this.g = !1;
this.f = new L(aa);
this.f.on("info", (c, d, e, f) => {
d && !this.h && (81920 < this.c + (f - e) ? (f = 81920 - this.c, this.c = 81920) : this.c += f - e, 81920 === this.c && (this.h = !0), this.b += d.toString("binary", e, f));
if (c) {
if (this.b && this.i !== this.maxHeaderPairs) {
c = this.b.split(ba);
d = c.length;
f = !1;
for (let h = 0; h < d; ++h) {
if (0 !== c[h].length) {
if ("\t" == c[h][0] || " " == c[h][0]) {
this.a[b][this.a[b].length - 1] += c[h];
} else {
if (e = ca.exec(c[h])) {
var b = e[1].toLowerCase();
e[2] ? void 0 === this.a[b] ? this.a[b] = [e[2]] : this.a[b].push(e[2]) : this.a[b] = [""];
if (++this.i === this.maxHeaderPairs) {
break;
}
} else {
this.b = c[h];
f = !0;
break;
}
}
}
}
f || (this.b = "");
}
this.f.c = this.f.i;
b = this.a;
this.a = {};
this.b = "";
this.g = !0;
this.c = this.i = 0;
this.h = !1;
this.emit("header", b);
}
});
}
push(a) {
a = this.f.push(a);
if (this.g) {
return a;
}
}
}
;/*
MIT dicer by Brian White
https://github.com/mscdex/dicer
*/
const fa = Buffer.from("-"), ha = Buffer.from("\r\n"), ia = () => {
};
function ja(a) {
a.a = void 0;
a.h = void 0;
a.g = void 0;
}
function N(a, c, d, e, f) {
var b, h = 0, g = !0;
if (!a.a && a.o && d) {
for (; 2 > a.f && e + h < f;) {
if (45 === d[e + h]) {
++h, ++a.f;
} else {
a.f && (b = fa);
a.f = 0;
break;
}
}
2 === a.f && (e + h < f && a._events.trailer && a.emit("trailer", d.slice(e + h, f)), ja(a), a.s = !0, 0 === a.u && (a.b = !0, a.emit("finish"), a.b = !1));
if (a.f) {
return;
}
}
a.o && (a.o = !1);
a.a || (a.a = new M(a.C), a.a._read = () => {
O(a);
}, h = a.c ? "preamble" : "part", a._events[h] ? a.emit(h, a.a) : a._ignore(), a.c || (a.i = !0));
d && e < f && !a.j && (a.c || !a.i ? (b && (g = a.a.push(b)), g = a.a.push(d.slice(e, f)), g || (a.m = !0)) : !a.c && a.i && (b && a.g.push(b), b = a.g.push(d.slice(e, f)), !a.i && void 0 !== b && b < f && N(a, !1, d, e + b, f)));
c && (da(a.g), a.c ? a.c = !1 : (++a.u, a.a.on("end", () => {
0 === --a.u && (a.s ? (a.b = !0, a.emit("finish"), a.b = !1) : O(a));
})), a.a.push(null), a.a = void 0, a.j = !1, a.o = !0, a.f = 0);
}
function O(a) {
if (a.m && (a.m = !1, a.l)) {
const c = a.l;
a.l = void 0;
c();
}
}
class ka extends w {
constructor(a) {
super(a);
if (!a || !a.headerFirst && "string" != typeof a.boundary) {
throw new TypeError("Boundary required");
}
"string" == typeof a.boundary ? this.setBoundary(a.boundary) : this.h = void 0;
this.D = a.headerFirst;
this.u = this.f = 0;
this.b = this.s = !1;
this.c = !0;
this.o = !1;
this.i = this.B = !0;
this.l = this.a = void 0;
this.j = !1;
this.C = "number" == typeof a.partHwm ? {highWaterMark:a.partHwm} : {};
this.m = !1;
this.g = new ea(a);
this.g.on("header", c => {
this.i = !1;
this.a.emit("header", c);
});
}
emit(a) {
"finish" != a || this.b ? w.prototype.emit.apply(this, arguments) : this.s || process.nextTick(() => {
this.emit("error", Error("Unexpected end of multipart data"));
this.a && !this.j ? (this.a.emit("error", Error((this.c ? "Preamble" : "Part") + " terminated early due to unexpected end of multipart data")), this.a.push(null), process.nextTick(() => {
this.b = !0;
this.emit("finish");
this.b = !1;
})) : (this.b = !0, this.emit("finish"), this.b = !1);
});
return !1;
}
_write(a, c, d) {
if (!this.g && !this.h) {
return d();
}
if (this.D && this.c) {
if (this.a || (this.a = new M(this.C), this._events.preamble ? this.emit("preamble", this.a) : this._ignore()), c = this.g.push(a), !this.i && void 0 !== c && c < a.length) {
a = a.slice(c);
} else {
return d();
}
}
this.B && (this.h.push(ha), this.B = !1);
this.h.push(a);
this.m ? this.l = d : d();
}
setBoundary(a) {
this.h = new L("\r\n--" + a);
this.h.on("info", (c, d, e, f) => {
N(this, c, d, e, f);
});
}
_ignore() {
this.a && !this.j && (this.j = !0, this.a.on("error", ia), this.a.resume());
}
}
;const {TextDecoder:P} = require("text-decoding"), Q = /%([a-fA-F0-9]{2})/g;
function R(a, c) {
return String.fromCharCode(parseInt(c, 16));
}
function S(a) {
let c = [], d = "key", e = "", f = !1, b = !1, h = 0, g = "";
for (var k = 0, n = a.length; k < n; ++k) {
if ("\\" === a[k] && f) {
if (b) {
b = !1;
} else {
b = !0;
continue;
}
} else {
if ('"' == a[k]) {
if (b) {
b = !1;
} else {
f ? (f = !1, d = "key") : f = !0;
continue;
}
} else {
if (b && f && (g += "\\"), b = !1, ("charset" === d || "lang" === d) && "'" === a[k]) {
"charset" === d ? (d = "lang", e = g.substring(1)) : d = "value";
g = "";
continue;
} else {
if ("key" == d && ("*" == a[k] || "=" == a[k]) && c.length) {
d = "*" == a[k] ? "charset" : "value";
c[h] = [g, void 0];
g = "";
continue;
} else {
if (!f && ";" == a[k]) {
d = "key";
e ? (g.length && (g = T(g.replace(Q, R), e)), e = "") : g.length && (g = T(g, "utf8"));
void 0 === c[h] ? c[h] = g : c[h][1] = g;
g = "";
++h;
continue;
} else {
if (!f && (" " === a[k] || "\t" === a[k])) {
continue;
}
}
}
}
}
}
g += a[k];
}
e && g.length ? g = T(g.replace(Q, R), e) : g && (g = T(g, "utf8"));
void 0 === c[h] ? g && (c[h] = g) : c[h][1] = g;
return c;
}
function T(a, c) {
let d;
if (a) {
try {
d = (new P(c)).decode(Buffer.from(a, "binary"));
} catch (e) {
}
}
return "string" == typeof d ? d : a;
}
const la = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ma = /\+/g;
class na {
constructor() {
this.a = void 0;
}
write(a) {
a = a.replace(ma, " ");
for (var c = "", d = 0, e = 0, f = a.length; d < f; ++d) {
void 0 !== this.a ? la[a.charCodeAt(d)] ? (this.a += a[d], ++e, 2 === this.a.length && (c += String.fromCharCode(parseInt(this.a, 16)), this.a = void 0)) : (c += "%" + this.a, this.a = void 0, --d) : "%" == a[d] && (d > e && (c += a.substring(e, d), e = d), this.a = "", ++e);
}
e < f && void 0 === this.a && (c += a.substring(e));
return c;
}
}
function oa(a) {
if ("string" != typeof a) {
return "";
}
for (let c = a.length - 1; 0 <= c; --c) {
switch(a.charCodeAt(c)) {
case 47:
case 92:
return a = a.slice(c + 1), ".." == a || "." == a ? "" : a;
}
}
return ".." == a || "." == a ? "" : a;
}
const U = a => {
const {fieldSize:c = 1048576, fieldNameSize:d = 100, fileSize:e = Infinity, files:f = Infinity, fields:b = Infinity, parts:h = Infinity} = a;
return {v:c, F:e, G:f, w:b, H:h, A:d};
};
class pa extends w {
constructor(a = {}) {
super({...a.highWaterMark ? {highWaterMark:a.highWaterMark} : {}});
this.a = !1;
this.b = void 0;
this.j = this.i = this.f = this.h = !1;
this.c = a;
if (a.headers && "string" == typeof a.headers["content-type"]) {
a: {
a = a.headers;
this.b = void 0;
if (a["content-type"]) {
const c = S(a["content-type"]);
let d, e;
for (let f = 0; f < this.g.length && (e = this.g[f], "function" == typeof e.detect ? d = e.detect(c) : d = e.detect.test(c[0]), !d); ++f) {
}
if (d) {
this.b = new e(this, {limits:this.c.limits, headers:a, parsedConType:c, highWaterMark:this.c.highWaterMark, fileHwm:this.c.fileHwm, defCharset:this.c.defCharset, preservePath:this.c.preservePath});
break a;
}
}
throw Error("Unsupported content type: " + a["content-type"]);
}
} else {
throw Error("Missing Content-Type");
}
}
emit(a, ...c) {
if ("finish" == a) {
if (!this.a) {
return this.b && this.b.end(), !1;
}
if (this.h) {
return !1;
}
this.h = !0;
}
return super.emit(a, ...c);
}
get g() {
return [];
}
_write(a, c, d) {
if (!this.b) {
return d(Error("Not ready to parse. Missing Content-Type?"));
}
this.b.write(a, d);
}
}
;const qa = /^boundary$/i, ra = /^form-data$/i, sa = /^charset$/i, ta = /^filename$/i, ua = /^name$/i;
class va {
static get detect() {
return /^multipart\/form-data/i;
}
constructor(a, {limits:c = {}, preservePath:d, fileHwm:e, parsedConType:f = [], highWaterMark:b}) {
function h() {
0 === x && E && !a.a && (E = !1, process.nextTick(() => {
a.a = !0;
a.emit("finish");
}));
}
let g, k;
[, f] = f.find(l => Array.isArray(l) && qa.test(l[0])) || [];
if ("string" != typeof f) {
throw Error("Multipart: Boundary not found");
}
const {H:n, G:wa, F:V, w:xa, v:F} = U(c);
let y, W = 0, X = 0, x = 0, z, E = !1;
this.c = this.f = !1;
this.a = void 0;
this.h = 0;
this.g = a;
this.b = new ka({boundary:f, maxHeaderPairs:c.headerPairs, highWaterMark:b, fileHwm:e});
this.b.on("drain", () => {
this.f = !1;
if (this.a && !this.c) {
const l = this.a;
this.a = void 0;
l();
}
}).on("error", l => {
a.emit("error", l);
}).on("finish", () => {
E = !0;
h();
});
const Y = l => {
if (++this.h > n) {
return this.b.removeListener("part", Y), this.b.on("part", Z), a.j = !0, a.emit("partsLimit"), Z(l);
}
if (z) {
const m = z;
m.emit("end");
m.removeAllListeners("end");
}
l.on("header", m => {
let A = "text/plain", G = "7bit", H;
let B = 0;
if (m["content-type"]) {
var q = S(m["content-type"][0]);
if (q[0]) {
for (A = q[0].toLowerCase(), g = 0, k = q.length; g < k && !sa.test(q[g][0]); ++g) {
}
}
}
if (m["content-disposition"]) {
q = S(m["content-disposition"][0]);
if (!ra.test(q[0])) {
return Z(l);
}
g = 0;
for (k = q.length; g < k; ++g) {
if (ua.test(q[g][0])) {
H = q[g][1];
} else {
if (ta.test(q[g][0])) {
var v = q[g][1];
d || (v = oa(v));
}
}
}
} else {
return Z(l);
}
m["content-transfer-encoding"] && (G = m["content-transfer-encoding"][0].toLowerCase());
if ("application/octet-stream" == A || void 0 !== v) {
if (W == wa) {
return a.i || (a.i = !0, a.emit("filesLimit")), Z(l);
}
++W;
if (!a._events.file) {
this.b._ignore();
return;
}
++x;
const p = new ya({highWaterMark:e});
y = p;
p.on("end", () => {
--x;
this.c = !1;
h();
if (this.a && !this.f) {
const r = this.a;
this.a = void 0;
r();
}
});
p._read = () => {
if (this.c && (this.c = !1, this.a && !this.f)) {
const r = this.a;
this.a = void 0;
r();
}
};
a.emit("file", H, p, v, G, A, l);
m = r => {
if ((B += r.length) > V) {
const u = V - (B - r.length);
0 < u && p.push(r.slice(0, u));
p.emit("limit");
p.truncated = !0;
l.removeAllListeners("data");
} else {
p.push(r) || (this.c = !0);
}
};
v = () => {
y = void 0;
p.push(null);
};
} else {
if (X == xa) {
return a.f || (a.f = !0, a.emit("fieldsLimit")), Z(l);
}
++X;
++x;
const p = [];
let r = !1;
z = l;
m = u => {
let I = u;
B += u.length;
B > F && (I = Buffer.from(u, 0, F).slice(0, F), r = !0, l.removeAllListeners("data"));
p.push(I);
};
v = () => {
z = void 0;
var u = Buffer.concat(p);
try {
u = (new P(void 0)).decode(u);
} catch (I) {
}
a.emit("field", H, u, !1, r, G, A);
--x;
h();
};
}
l._readableState.sync = !1;
l.on("data", m);
l.on("end", v);
}).on("error", m => {
y && y.emit("error", m);
});
};
this.b.on("part", Y);
}
end() {
0 !== this.h || this.g.a ? this.b.writable && this.b.end() : process.nextTick(() => {
this.g.a = !0;
this.g.emit("finish");
});
}
write(a, c) {
(a = this.b.write(a)) && !this.c ? c() : (this.f = !a, this.a = c);
}
}
function Z(a) {
a.resume();
}
class ya extends t {
constructor(a) {
super(a);
this.truncated = !1;
}
_read() {
}
}
;const za = /^charset$/i;
class Aa {
static get detect() {
return /^application\/x-www-form-urlencoded/i;
}
constructor(a, {limits:c = {}, parsedConType:d, defCharset:e = "utf8"}) {
this.f = a;
this.h = void 0;
const {v:f, A:b, w:h} = U(c);
this.v = f;
this.A = b;
this.w = h;
a = e;
for (let g = 0, k = d.length; g < k; ++g) {
if (Array.isArray(d[g]) && za.test(d[g][0])) {
a = d[g][1].toLowerCase();
break;
}
}
this.g = new na;
this.j = a;
this.m = 0;
this.o = "key";
this.b = !0;
this.s = this.l = 0;
this.c = this.a = "";
this.u = this.i = !1;
}
write(a, c) {
if (this.m === this.w) {
return this.f.f || (this.f.f = !0, this.f.emit("fieldsLimit")), c();
}
for (var d, e, f, b = 0, h = a.length; b < h;) {
if ("key" == this.o) {
d = e = void 0;
for (f = b; f < h; ++f) {
this.b || ++b;
if (61 === a[f]) {
d = f;
break;
} else {
if (38 === a[f]) {
e = f;
break;
}
}
if (this.b && this.l === this.A) {
this.h = !0;
break;
} else {
this.b && ++this.l;
}
}
if (void 0 !== d) {
d > b && (this.a += this.g.write(a.toString("binary", b, d))), this.o = "val", this.h = !1, this.b = !0, this.c = "", this.s = 0, this.u = !1, this.g.a = void 0, b = d + 1;
} else {
if (void 0 !== e) {
if (++this.m, d = this.i, b = e > b ? this.a += this.g.write(a.toString("binary", b, e)) : this.a, this.h = !1, this.b = !0, this.a = "", this.l = 0, this.i = !1, this.g.a = void 0, b.length && this.f.emit("field", T(b, this.j), "", d, !1), b = e + 1, this.m === this.w) {
return c();
}
} else {
this.h ? (f > b && (this.a += this.g.write(a.toString("binary", b, f))), b = f, (this.l = this.a.length) === this.A && (this.b = !1, this.i = !0)) : (b < h && (this.a += this.g.write(a.toString("binary", b))), b = h);
}
}
} else {
e = void 0;
for (f = b; f < h; ++f) {
this.b || ++b;
if (38 === a[f]) {
e = f;
break;
}
if (this.b && this.s === this.v) {
this.h = !0;
break;
} else {
this.b && ++this.s;
}
}
if (void 0 !== e) {
if (++this.m, e > b && (this.c += this.g.write(a.toString("binary", b, e))), this.f.emit("field", T(this.a, this.j), T(this.c, this.j), this.i, this.u), this.o = "key", this.h = !1, this.b = !0, this.a = "", this.l = 0, this.i = !1, this.g.a = void 0, b = e + 1, this.m === this.w) {
return c();
}
} else {
if (this.h) {
if (f > b && (this.c += this.g.write(a.toString("binary", b, f))), b = f, "" === this.c && 0 === this.v || (this.s = this.c.length) === this.v) {
this.b = !1, this.u = !0;
}
} else {
b < h && (this.c += this.g.write(a.toString("binary", b))), b = h;
}
}
}
}
c();
}
end() {
this.f.a || ("key" == this.o && 0 < this.a.length ? this.f.emit("field", T(this.a, this.j), "", this.i, !1) : "val" == this.o && this.f.emit("field", T(this.a, this.j), T(this.c, this.j), this.i, this.u), this.f.a = !0, this.f.emit("finish"));
}
}
;class Ba extends pa {
constructor(a) {
super(a);
}
get g() {
return [va, Aa];
}
}
;module.exports = Ba;
//# sourceMappingURL=busboy.js.map