Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Remove unnecessary file

  • Loading branch information...
commit 780f93d6644448988d988f30a18b8b04fa12924e 1 parent 28c55ef
@kriszyp kriszyp authored
Showing with 0 additions and 437 deletions.
  1. +0 −437 engines/node/lib/multipart.js
View
437 engines/node/lib/multipart.js
@@ -1,437 +0,0 @@
-
-var sys = require("sys"),
- events = require("events"),
- wrapExpression = /^[ \t]+/,
- multipartExpression = new RegExp(
- "^multipart\/(" +
- "mixed|rfc822|message|digest|alternative|" +
- "related|report|signed|encrypted|form-data|" +
- "x-mixed-replace|byteranges)", "i"),
- boundaryExpression = /boundary=([^;]+)/i,
- CR = "\r",
- LF = "\n",
- CRLF = CR+LF,
- MAX_BUFFER_LENGTH = 16 * 1024,
-
- // parser states.
- s = 0,
- S_NEW_PART = s++,
- S_HEADER = s++,
- S_BODY = s++;
-
-exports.parse = parse;
-exports.cat = cat;
-exports.Stream = Stream;
-
-// Parse a streaming message to a stream.
-// If the message has a "body" and no "addListener", then
-// just take it in and write() the body.
-function parse (message) {
- return new Stream(message);
-};
-
-// WARNING: DONT EVER USE THE CAT FUNCTION IN PRODUCTION WEBSITES!!
-// It works pretty great, and it's a nice test function. But if
-// you use this function to parse an HTTP request from a live web
-// site, then you're essentially giving the world permission to
-// rack up as much memory usage as they can manage. This function
-// buffers the whole message, which is very convenient, but also
-// very much the wrong thing to do in most cases.
-function cat (message, callback) {
- var stream = parse(message);
- stream.files = {};
- stream.fields = {};
- stream.addListener("partBegin", function (part) {
- if (part.filename) stream.files[part.filename] = part;
- if (part.name) stream.fields[part.name] = part;
- });
- stream.addListener("body", function (chunk) {
- stream.part.body = (stream.part.body || "") + chunk;
- });
- stream.addListener("error", function (e) { p.emitError(e)
- if (callback) callback(e);
- });
- stream.addListener("complete", function () {
- if (callback) callback(null, stream);
- });
-};
-
-// events:
-// "partBegin", "partEnd", "body", "complete"
-// everything emits on the Stream directly.
-// the stream's "parts" object is a nested collection of the header objects
-// check the stream's "part" member to know what it's currently chewin on.
-// this.part.parent refers to that part's containing message (which may be
-// the stream itself)
-// child messages inherit their parent's headers
-// A non-multipart message looks just like a multipart message with a
-// single part.
-function Stream (message) {
- var isMultiPart = multipartHeaders(message, this),
- w = isMultiPart ? writer(this) : simpleWriter(this),
- e = ender(this);
- if (message.addListener) {
- message.addListener("data", w);
- message.addListener("end", e);
- if (message.pause && message.resume) {
- this._pause = message;
- }
- } else if (message.body) {
- var self = this;
- if (message.body.pause && message.body.resume) {
- this._pause = message.body;
- }
- if (message.body.addListener) {
- message.body.addListener("data", w);
- message.body.addListener("end", e);
- } if (message.body.forEach) {
- var p = message.body.forEach(w);
- if (p && p.addCallback) p.addCallback(e);
- else e();
- } else {
- // just write a string.
- w(message.body);
- e();
- }
- }
-};
-Stream.prototype = {
- __proto__ : events.EventEmitter.prototype,
- error : function (ex) {
- this._error = ex;
- this.emit("error", ex);
- },
- pause : function () {
- if (this._pause) return this._pause.pause();
- throw new Error("Unsupported");
- },
- resume : function () {
- if (this._pause) return this._pause.resume();
- throw new Error("Unsupported");
- }
-};
-
-// check the headers of the message. If it wants to be multipart,
-// then we'll be returning true. Regardless, if supplied, then
-// stream will get a headers object that inherits from message's.
-// If no stream object is supplied, then this function just inspects
-// the message's headers for multipartness, and modifies the message
-// directly. This divergence is so that we can avoid modifying
-// the original message when we want a wrapper, but still have the
-// info available when it's one of our own objects.
-function multipartHeaders (message, stream) {
- var field, val, contentType, contentDisposition = "";
- if (stream) stream.headers = {};
- for (var h in message.headers) if (message.headers.hasOwnProperty(h)) {
- val = message.headers[h];
- field = h.toLowerCase();
- if (stream) stream.headers[field] = val;
- if (field === "content-type") {
- contentType = val;
- } else if (field === "content-disposition") {
- contentDisposition = val;
- }
- }
-
- if (!Array.isArray(contentDisposition)) {
- contentDisposition = contentDisposition.split(",");
- }
- contentDisposition = contentDisposition[contentDisposition.length - 1];
-
- var mutate = (stream || message);
-
- // Name and filename can come along with either content-disposition
- // or content-type. Well-behaved agents use CD rather than CT,
- // but sadly not all agents are well-behaved.
- [contentDisposition, contentType].forEach(function (h) {
- if (!h) return;
- var cd = h.split(/; */);
- cd.shift();
- for (var i = 0, l = cd.length; i < l; i ++) {
- var bit = cd[i].split("="),
- name = bit.shift(),
- val = stripQuotes(bit.join("="));
- if (name === "filename" || name === "name") {
- mutate[name] = val;
- }
- }
- });
-
- if (!contentType) {
- return false;
- }
-
- // legacy
- // TODO: Update this when/if jsgi-style headers are supported.
- // this will keep working, but is less efficient than it could be.
- if (!Array.isArray(contentType)) {
- contentType = contentType.split(",");
- }
- contentType = contentType[contentType.length-1];
-
- // make sure it's actually multipart.
- var mpType = multipartExpression.exec(contentType);
- if (!mpType) {
- return false;
- }
-
- // make sure we have a boundary.
- var boundary = boundaryExpression.exec(contentType);
- if (!boundary) {
- return false;
- }
-
- mutate.type = mpType[1];
- mutate.boundary = "--" + boundary[1];
- mutate.isMultiPart = true;
-
- return true;
-};
-function simpleWriter (stream) {
- stream.part = stream;
- stream.type = false;
- var started = false;
- return function (chunk) {
- if (!started) {
- stream.emit("partBegin", stream);
- started = true;
- }
- stream.emit("body", chunk);
- };
-}
-function writer (stream) {
- var buffer = "",
- state = S_NEW_PART,
- part = stream.part = stream;
- stream.parts = [];
- stream.parent = stream;
- return function (chunk) {
- if (stream._error) return;
- // write to the buffer, and then process the buffer.
- buffer += chunk;
- while (buffer.length > 0) {
- while (buffer.substr(0, 2) === CRLF) buffer = buffer.substr(2);
- switch (state) {
- case S_NEW_PART:
- // part is a multipart message.
- // we're either going to start reading a new part, or we're going to
- // end the current part, depending on whether the boundary has -- at
- // the end. either way, we expect --boundary right away.
- var boundary = part.boundary,
- len = boundary.length,
- offset = buffer.indexOf(boundary);
- if (offset === -1) {
- if (buffer.length > MAX_BUFFER_LENGTH) {
- return stream.error(new Error(
- "Malformed: boundary not found at start of message"));
- }
- // keep waiting for it.
- return;
- }
- if (offset > 0) {
- return stream.error(Error("Malformed: data before the boundary"));
- }
- if (buffer.length < (len + 2)) {
- // we'll need to see either -- or CRLF after the boundary.
- // get it on the next pass.
- return;
- }
- if (buffer.substr(len, 2) === "--") {
- // this message is done.
- // chomp off the boundary and crlf and move up
- if (part !== stream) {
- // wait to see the crlf, unless this is the top-level message.
- if (buffer.length < (len + 4)) {
- return;
- }
- if (buffer.substr(len+2, 2) !== CRLF) {
- return stream.error(new Error(
- "Malformed: CRLF not found after boundary"));
- }
- }
- buffer = buffer.substr(len + 4);
- stream.emit("partEnd", part);
- stream.part = part = part.parent;
- state = S_NEW_PART;
- continue;
- }
- if (part !== stream) {
- // wait to see the crlf, unless this is the top-level message.
- if (buffer.length < (len + 2)) {
- return;
- }
- if (buffer.substr(len, 2) !== CRLF) {
- return stream.error(new Error(
- "Malformed: CRLF not found after boundary"));
- }
- }
- // walk past the crlf
- buffer = buffer.substr(len + 2);
- // mint a new child part, and start parsing headers.
- stream.part = part = startPart(part);
- state = S_HEADER;
- continue;
- case S_HEADER:
- // just grab everything to the double crlf.
- var headerEnd = buffer.indexOf(CRLF+CRLF);
- if (headerEnd === -1) {
- if (buffer.length > MAX_BUFFER_LENGTH) {
- return stream.error(new Error(
- "Malformed: header unreasonably long."));
- }
- return;
- }
- var headerString = buffer.substr(0, headerEnd);
- // chomp off the header and the empty line.
- buffer = buffer.substr(headerEnd + 4);
- try {
- parseHeaderString(part.headers, headerString);
- } catch (ex) {
- return stream.error(ex);
- }
- multipartHeaders(part);
-
- // let the world know
- stream.emit("partBegin", part);
-
- if (part.isMultiPart) {
- // it has a boundary and we're ready to grab parts out.
- state = S_NEW_PART;
- } else {
- // it doesn't have a boundary, and is about to
- // start spitting out body bits.
- state = S_BODY;
- }
- continue;
- case S_BODY:
- // look for part.parent.boundary
- var boundary = part.parent.boundary,
- offset = buffer.indexOf(boundary);
- if (offset === -1) {
- // emit and wait for more data, but be careful, because
- // we might only have half of the boundary so far.
- // make sure to leave behind the boundary's length, so that we'll
- // definitely get it next time if it's on its way.
- var emittable = buffer.length - boundary.length;
- if (buffer.substr(-1) === CR) emittable -= 1;
- if (buffer.substr(-2) === CRLF) emittable -= 2;
-
- if (emittable > 0) {
- stream.emit("body", buffer.substr(0, emittable));
- buffer = buffer.substr(emittable);
- }
- // haven't seen the boundary, so wait for more bytes.
- return;
- }
- if (offset > 0) {
- var emit = buffer.substr(0, offset);
- if (emit.substr(-2) === CRLF) emit = emit.substr(0, emit.length-2);
- if (emit) stream.emit("body", emit);
- buffer = buffer.substr(offset);
- }
-
- // let em know we're done.
- stream.emit("partEnd", part);
-
- // now buffer starts with boundary.
- if (buffer.substr(boundary.length, 2) === "--") {
- // message end.
- // parent ends, look for a new part in the grandparent.
- stream.part = part = part.parent;
- stream.emit("partEnd", part);
- stream.part = part = part.parent;
- state = S_NEW_PART;
- buffer = buffer.substr(boundary.length + 4);
- } else {
- // another part coming for the parent message.
- stream.part = part = part.parent;
- state = S_NEW_PART;
- }
- continue;
- }
- }
- };
-};
-
-function parseHeaderString (headers, string) {
- var lines = string.split(CRLF),
- field, value, line;
- for (var i = 0, l = lines.length; i < l; i ++) {
- line = lines[i];
- if (line.match(wrapExpression)) {
- if (!field) {
- throw new Error("Malformed. First header starts with whitespace.");
- }
- value += line.replace(wrapExpression, " ");
- continue;
- } else if (field) {
- // now that we know it's not wrapping, put it on the headers obj.
- affixHeader(headers, field, value);
- }
- line = line.split(":");
- field = line.shift().toLowerCase();
- if (!field) {
- throw new Error("Malformed: improper field name.");
- }
- value = line.join(":").replace(/^\s+/, "");
- }
- // now affix the last field.
- affixHeader(headers, field, value);
-};
-
-function affixHeader (headers, field, value) {
- if (!headers.hasOwnProperty(field)) {
- headers[field] = value;
- } else if (Array.isArray(headers[field])) {
- headers[field].push(value);
- } else {
- headers[field] = [headers[field], value];
- }
-};
-
-function startPart (parent) {
- var part = {
- headers : {},
- parent : parent
- };
- parent.parts = parent.parts || [];
- parent.parts.push(part);
- return part;
-};
-
-function ender (stream) { return function () {
- if (stream._error) return;
- if (!stream.isMultiPart) stream.emit("partEnd", stream);
- stream.emit("complete");
-}};
-
-function stripslashes(str) {
- // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + improved by: Ates Goral (http://magnetiq.com)
- // + fixed by: Mick@el
- // + improved by: marrtins
- // + bugfixed by: Onno Marsman
- // + improved by: rezna
- // + input by: Rick Waldron
- // + reimplemented by: Brett Zamir (http://brett-zamir.me)
- // * example 1: stripslashes("Kevin\'s code");
- // * returns 1: "Kevin's code"
- // * example 2: stripslashes("Kevin\\\'s code");
- // * returns 2: "Kevin\'s code"
- return (str+"").replace(/\\(.?)/g, function (s, n1) {
- switch(n1) {
- case "\\":
- return "\\";
- case "0":
- return "\0";
- case "":
- return "";
- default:
- return n1;
- }
- });
-};
-function stripQuotes (str) {
- str = stripslashes(str);
- return str.substr(1, str.length - 2);
-};
Please sign in to comment.
Something went wrong with that request. Please try again.