Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Remove unnecessary file

  • Loading branch information...
commit 780f93d6644448988d988f30a18b8b04fa12924e 1 parent 28c55ef
Kris Zyp authored August 12, 2010

Showing 1 changed file with 0 additions and 437 deletions. Show diff stats Hide diff stats

  1. 437  engines/node/lib/multipart.js
437  engines/node/lib/multipart.js
... ...
@@ -1,437 +0,0 @@
1  
-
2  
-var sys = require("sys"),
3  
-  events = require("events"),
4  
-  wrapExpression = /^[ \t]+/,
5  
-  multipartExpression = new RegExp(
6  
-    "^multipart\/(" +
7  
-    "mixed|rfc822|message|digest|alternative|" +
8  
-    "related|report|signed|encrypted|form-data|" +
9  
-    "x-mixed-replace|byteranges)", "i"),
10  
-  boundaryExpression = /boundary=([^;]+)/i,
11  
-  CR = "\r",
12  
-  LF = "\n",
13  
-  CRLF = CR+LF,
14  
-  MAX_BUFFER_LENGTH = 16 * 1024,
15  
-
16  
-  // parser states.
17  
-  s = 0,
18  
-  S_NEW_PART = s++,
19  
-  S_HEADER = s++,
20  
-  S_BODY = s++;
21  
-
22  
-exports.parse = parse;
23  
-exports.cat = cat;
24  
-exports.Stream = Stream;
25  
-
26  
-// Parse a streaming message to a stream.
27  
-// If the message has a "body" and no "addListener", then
28  
-// just take it in and write() the body.
29  
-function parse (message) {
30  
-  return new Stream(message);
31  
-};
32  
-
33  
-// WARNING: DONT EVER USE THE CAT FUNCTION IN PRODUCTION WEBSITES!!
34  
-// It works pretty great, and it's a nice test function. But if
35  
-// you use this function to parse an HTTP request from a live web
36  
-// site, then you're essentially giving the world permission to
37  
-// rack up as much memory usage as they can manage.  This function
38  
-// buffers the whole message, which is very convenient, but also
39  
-// very much the wrong thing to do in most cases.
40  
-function cat (message, callback) {
41  
-  var stream = parse(message);
42  
-  stream.files = {};
43  
-  stream.fields = {};
44  
-  stream.addListener("partBegin", function (part) {
45  
-    if (part.filename) stream.files[part.filename] = part;
46  
-    if (part.name) stream.fields[part.name] = part;
47  
-  });
48  
-  stream.addListener("body", function (chunk) {
49  
-    stream.part.body = (stream.part.body || "") + chunk;
50  
-  });
51  
-  stream.addListener("error", function (e) { p.emitError(e)
52  
-    if (callback) callback(e);
53  
-  });
54  
-  stream.addListener("complete", function () {
55  
-    if (callback) callback(null, stream);
56  
-  });
57  
-};
58  
-
59  
-// events:
60  
-// "partBegin", "partEnd", "body", "complete"
61  
-// everything emits on the Stream directly.
62  
-// the stream's "parts" object is a nested collection of the header objects
63  
-// check the stream's "part" member to know what it's currently chewin on.
64  
-// this.part.parent refers to that part's containing message (which may be
65  
-// the stream itself)
66  
-// child messages inherit their parent's headers
67  
-// A non-multipart message looks just like a multipart message with a
68  
-// single part.
69  
-function Stream (message) {
70  
-  var isMultiPart = multipartHeaders(message, this),
71  
-    w = isMultiPart ? writer(this) : simpleWriter(this),
72  
-    e = ender(this);
73  
-  if (message.addListener) {
74  
-    message.addListener("data", w);
75  
-    message.addListener("end", e);
76  
-    if (message.pause && message.resume) {
77  
-      this._pause = message;
78  
-    }
79  
-  } else if (message.body) {
80  
-    var self = this;
81  
-    if (message.body.pause && message.body.resume) {
82  
-      this._pause = message.body;
83  
-    }
84  
-    if (message.body.addListener) {
85  
-      message.body.addListener("data", w);
86  
-      message.body.addListener("end", e);
87  
-    } if (message.body.forEach) {
88  
-      var p = message.body.forEach(w);
89  
-      if (p && p.addCallback) p.addCallback(e);
90  
-      else e();
91  
-    } else {
92  
-      // just write a string.
93  
-      w(message.body);
94  
-      e();
95  
-    }
96  
-  }
97  
-};
98  
-Stream.prototype = {
99  
-  __proto__ : events.EventEmitter.prototype,
100  
-  error : function (ex) {
101  
-    this._error = ex;
102  
-    this.emit("error", ex);
103  
-  },
104  
-  pause : function () {
105  
-    if (this._pause) return this._pause.pause();
106  
-    throw new Error("Unsupported");
107  
-  },
108  
-  resume : function () {
109  
-    if (this._pause) return this._pause.resume();
110  
-    throw new Error("Unsupported");
111  
-  }
112  
-};
113  
-
114  
-// check the headers of the message.  If it wants to be multipart,
115  
-// then we'll be returning true.  Regardless, if supplied, then
116  
-// stream will get a headers object that inherits from message's.
117  
-// If no stream object is supplied, then this function just inspects
118  
-// the message's headers for multipartness, and modifies the message
119  
-// directly.  This divergence is so that we can avoid modifying
120  
-// the original message when we want a wrapper, but still have the
121  
-// info available when it's one of our own objects.
122  
-function multipartHeaders (message, stream) {
123  
-  var field, val, contentType, contentDisposition = "";
124  
-  if (stream) stream.headers = {};
125  
-  for (var h in message.headers) if (message.headers.hasOwnProperty(h)) {
126  
-    val = message.headers[h];
127  
-    field = h.toLowerCase();
128  
-    if (stream) stream.headers[field] = val;
129  
-    if (field === "content-type") {
130  
-      contentType = val;
131  
-    } else if (field === "content-disposition") {
132  
-      contentDisposition = val;
133  
-    }
134  
-  }
135  
-
136  
-  if (!Array.isArray(contentDisposition)) {
137  
-    contentDisposition = contentDisposition.split(",");
138  
-  }
139  
-  contentDisposition = contentDisposition[contentDisposition.length - 1];
140  
-
141  
-  var mutate = (stream || message);
142  
-
143  
-  // Name and filename can come along with either content-disposition
144  
-  // or content-type.  Well-behaved agents use CD rather than CT,
145  
-  // but sadly not all agents are well-behaved.
146  
-  [contentDisposition, contentType].forEach(function (h) {
147  
-    if (!h) return;
148  
-    var cd = h.split(/; */);
149  
-    cd.shift();
150  
-    for (var i = 0, l = cd.length; i < l; i ++) {
151  
-      var bit = cd[i].split("="),
152  
-        name = bit.shift(),
153  
-        val = stripQuotes(bit.join("="));
154  
-      if (name === "filename" || name === "name") {
155  
-        mutate[name] = val;
156  
-      }
157  
-    }
158  
-  });
159  
-
160  
-  if (!contentType) {
161  
-    return false;
162  
-  }
163  
-
164  
-  // legacy
165  
-  // TODO: Update this when/if jsgi-style headers are supported.
166  
-  // this will keep working, but is less efficient than it could be.
167  
-  if (!Array.isArray(contentType)) {
168  
-    contentType = contentType.split(",");
169  
-  }
170  
-  contentType = contentType[contentType.length-1];
171  
-
172  
-  // make sure it's actually multipart.
173  
-  var mpType = multipartExpression.exec(contentType);
174  
-  if (!mpType) {
175  
-    return false;
176  
-  }
177  
-
178  
-  // make sure we have a boundary.
179  
-  var boundary = boundaryExpression.exec(contentType);
180  
-  if (!boundary) {
181  
-    return false;
182  
-  }
183  
-
184  
-  mutate.type = mpType[1];
185  
-  mutate.boundary = "--" + boundary[1];
186  
-  mutate.isMultiPart = true;
187  
-
188  
-  return true;
189  
-};
190  
-function simpleWriter (stream) {
191  
-  stream.part = stream;
192  
-  stream.type = false;
193  
-  var started = false;
194  
-  return function (chunk) {
195  
-    if (!started) {
196  
-      stream.emit("partBegin", stream);
197  
-      started = true;
198  
-    }
199  
-    stream.emit("body", chunk);
200  
-  };
201  
-}
202  
-function writer (stream) {
203  
-  var buffer = "",
204  
-    state = S_NEW_PART,
205  
-    part = stream.part = stream;
206  
-  stream.parts = [];
207  
-  stream.parent = stream;
208  
-  return function (chunk) {
209  
-    if (stream._error) return;
210  
-    // write to the buffer, and then process the buffer.
211  
-    buffer += chunk;
212  
-    while (buffer.length > 0) {
213  
-      while (buffer.substr(0, 2) === CRLF) buffer = buffer.substr(2);
214  
-      switch (state) {
215  
-        case S_NEW_PART:
216  
-          // part is a multipart message.
217  
-          // we're either going to start reading a new part, or we're going to
218  
-          // end the current part, depending on whether the boundary has -- at
219  
-          // the end.  either way, we expect --boundary right away.
220  
-          var boundary = part.boundary,
221  
-            len = boundary.length,
222  
-            offset = buffer.indexOf(boundary);
223  
-          if (offset === -1) {
224  
-            if (buffer.length > MAX_BUFFER_LENGTH) {
225  
-              return stream.error(new Error(
226  
-                "Malformed: boundary not found at start of message"));
227  
-            }
228  
-            // keep waiting for it.
229  
-            return;
230  
-          }
231  
-          if (offset > 0) {
232  
-            return stream.error(Error("Malformed: data before the boundary"));
233  
-          }
234  
-          if (buffer.length < (len + 2)) {
235  
-            // we'll need to see either -- or CRLF after the boundary.
236  
-            // get it on the next pass.
237  
-            return;
238  
-          }
239  
-          if (buffer.substr(len, 2) === "--") {
240  
-            // this message is done.
241  
-            // chomp off the boundary and crlf and move up
242  
-            if (part !== stream) {
243  
-              // wait to see the crlf, unless this is the top-level message.
244  
-              if (buffer.length < (len + 4)) {
245  
-                return;
246  
-              }
247  
-              if (buffer.substr(len+2, 2) !== CRLF) {
248  
-                return stream.error(new Error(
249  
-                  "Malformed: CRLF not found after boundary"));
250  
-              }
251  
-            }
252  
-            buffer = buffer.substr(len + 4);
253  
-            stream.emit("partEnd", part);
254  
-            stream.part = part = part.parent;
255  
-            state = S_NEW_PART;
256  
-            continue;
257  
-          }
258  
-          if (part !== stream) {
259  
-            // wait to see the crlf, unless this is the top-level message.
260  
-            if (buffer.length < (len + 2)) {
261  
-              return;
262  
-            }
263  
-            if (buffer.substr(len, 2) !== CRLF) {
264  
-              return stream.error(new Error(
265  
-                "Malformed: CRLF not found after boundary"));
266  
-            }
267  
-          }
268  
-          // walk past the crlf
269  
-          buffer = buffer.substr(len + 2);
270  
-          // mint a new child part, and start parsing headers.
271  
-          stream.part = part = startPart(part);
272  
-          state = S_HEADER;
273  
-        continue;
274  
-        case S_HEADER:
275  
-          // just grab everything to the double crlf.
276  
-          var headerEnd = buffer.indexOf(CRLF+CRLF);
277  
-          if (headerEnd === -1) {
278  
-            if (buffer.length > MAX_BUFFER_LENGTH) {
279  
-              return stream.error(new Error(
280  
-                "Malformed: header unreasonably long."));
281  
-            }
282  
-            return;
283  
-          }
284  
-          var headerString = buffer.substr(0, headerEnd);
285  
-          // chomp off the header and the empty line.
286  
-          buffer = buffer.substr(headerEnd + 4);
287  
-          try {
288  
-            parseHeaderString(part.headers, headerString);
289  
-          } catch (ex) {
290  
-            return stream.error(ex);
291  
-          }
292  
-          multipartHeaders(part);
293  
-
294  
-          // let the world know
295  
-          stream.emit("partBegin", part);
296  
-
297  
-          if (part.isMultiPart) {
298  
-            // it has a boundary and we're ready to grab parts out.
299  
-            state = S_NEW_PART;
300  
-          } else {
301  
-            // it doesn't have a boundary, and is about to
302  
-            // start spitting out body bits.
303  
-            state = S_BODY;
304  
-          }
305  
-        continue;
306  
-        case S_BODY:
307  
-          // look for part.parent.boundary
308  
-          var boundary = part.parent.boundary,
309  
-            offset = buffer.indexOf(boundary);
310  
-          if (offset === -1) {
311  
-            // emit and wait for more data, but be careful, because
312  
-            // we might only have half of the boundary so far.
313  
-            // make sure to leave behind the boundary's length, so that we'll
314  
-            // definitely get it next time if it's on its way.
315  
-            var emittable = buffer.length - boundary.length;
316  
-            if (buffer.substr(-1) === CR) emittable -= 1;
317  
-            if (buffer.substr(-2) === CRLF) emittable -= 2;
318  
-
319  
-            if (emittable > 0) {
320  
-              stream.emit("body", buffer.substr(0, emittable));
321  
-              buffer = buffer.substr(emittable);
322  
-            }
323  
-            // haven't seen the boundary, so wait for more bytes.
324  
-            return;
325  
-          }
326  
-          if (offset > 0) {
327  
-            var emit = buffer.substr(0, offset);
328  
-            if (emit.substr(-2) === CRLF) emit = emit.substr(0, emit.length-2);
329  
-            if (emit) stream.emit("body", emit);
330  
-            buffer = buffer.substr(offset);
331  
-          }
332  
-
333  
-          // let em know we're done.
334  
-          stream.emit("partEnd", part);
335  
-
336  
-          // now buffer starts with boundary.
337  
-          if (buffer.substr(boundary.length, 2) === "--") {
338  
-            // message end.
339  
-            // parent ends, look for a new part in the grandparent.
340  
-            stream.part = part = part.parent;
341  
-            stream.emit("partEnd", part);
342  
-            stream.part = part = part.parent;
343  
-            state = S_NEW_PART;
344  
-            buffer = buffer.substr(boundary.length + 4);
345  
-          } else {
346  
-            // another part coming for the parent message.
347  
-            stream.part = part = part.parent;
348  
-            state = S_NEW_PART;
349  
-          }
350  
-        continue;
351  
-      }
352  
-    }
353  
-  };
354  
-};
355  
-
356  
-function parseHeaderString (headers, string) {
357  
-  var lines = string.split(CRLF),
358  
-    field, value, line;
359  
-  for (var i = 0, l = lines.length; i < l; i ++) {
360  
-    line = lines[i];
361  
-    if (line.match(wrapExpression)) {
362  
-      if (!field) {
363  
-        throw new Error("Malformed. First header starts with whitespace.");
364  
-      }
365  
-      value += line.replace(wrapExpression, " ");
366  
-      continue;
367  
-    } else if (field) {
368  
-      // now that we know it's not wrapping, put it on the headers obj.
369  
-      affixHeader(headers, field, value);
370  
-    }
371  
-    line = line.split(":");
372  
-    field = line.shift().toLowerCase();
373  
-    if (!field) {
374  
-      throw new Error("Malformed: improper field name.");
375  
-    }
376  
-    value = line.join(":").replace(/^\s+/, "");
377  
-  }
378  
-  // now affix the last field.
379  
-  affixHeader(headers, field, value);
380  
-};
381  
-
382  
-function affixHeader (headers, field, value) {
383  
-  if (!headers.hasOwnProperty(field)) {
384  
-    headers[field] = value;
385  
-  } else if (Array.isArray(headers[field])) {
386  
-    headers[field].push(value);
387  
-  } else {
388  
-    headers[field] = [headers[field], value];
389  
-  }
390  
-};
391  
-
392  
-function startPart (parent) {
393  
-  var part = {
394  
-    headers : {},
395  
-    parent : parent
396  
-  };
397  
-  parent.parts = parent.parts || [];
398  
-  parent.parts.push(part);
399  
-  return part;
400  
-};
401  
-
402  
-function ender (stream) { return function () {
403  
-  if (stream._error) return;
404  
-  if (!stream.isMultiPart) stream.emit("partEnd", stream);
405  
-  stream.emit("complete");
406  
-}};
407  
-
408  
-function stripslashes(str) {
409  
-  // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
410  
-  // +   improved by: Ates Goral (http://magnetiq.com)
411  
-  // +      fixed by: Mick@el
412  
-  // +   improved by: marrtins
413  
-  // +   bugfixed by: Onno Marsman
414  
-  // +   improved by: rezna
415  
-  // +   input by: Rick Waldron
416  
-  // +   reimplemented by: Brett Zamir (http://brett-zamir.me)
417  
-  // *     example 1: stripslashes("Kevin\'s code");
418  
-  // *     returns 1: "Kevin's code"
419  
-  // *     example 2: stripslashes("Kevin\\\'s code");
420  
-  // *     returns 2: "Kevin\'s code"
421  
-  return (str+"").replace(/\\(.?)/g, function (s, n1) {
422  
-    switch(n1) {
423  
-      case "\\":
424  
-        return "\\";
425  
-      case "0":
426  
-        return "\0";
427  
-      case "":
428  
-        return "";
429  
-      default:
430  
-        return n1;
431  
-    }
432  
-  });
433  
-};
434  
-function stripQuotes (str) {
435  
-  str = stripslashes(str);
436  
-  return str.substr(1, str.length - 2);
437  
-};

0 notes on commit 780f93d

Please sign in to comment.
Something went wrong with that request. Please try again.