Name: js-handler/node_modules/restify/node_modules/formidable/lib/multipart_parser.js 
1:
var Buffer = require('buffer').Buffer,
2:
    s = 0,
3:
    S =
4:
    { PARSER_UNINITIALIZED: s++,
5:
      START: s++,
6:
      START_BOUNDARY: s++,
7:
      HEADER_FIELD_START: s++,
8:
      HEADER_FIELD: s++,
9:
      HEADER_VALUE_START: s++,
10:
      HEADER_VALUE: s++,
11:
      HEADER_VALUE_ALMOST_DONE: s++,
12:
      HEADERS_ALMOST_DONE: s++,
13:
      PART_DATA_START: s++,
14:
      PART_DATA: s++,
15:
      PART_END: s++,
16:
      END: s++
17:
    },
18:
 
19:
    f = 1,
20:
    F =
21:
    { PART_BOUNDARY: f,
22:
      LAST_BOUNDARY: f *= 2
23:
    },
24:
 
25:
    LF = 10,
26:
    CR = 13,
27:
    SPACE = 32,
28:
    HYPHEN = 45,
29:
    COLON = 58,
30:
    A = 97,
31:
    Z = 122,
32:
 
33:
    lower = function(c) {
34:
      return c | 0x20;
35:
    };
36:
 
37:
for (s in S) {
38:
  exports[s] = S[s];
39:
}
40:
 
41:
function MultipartParser() {
42:
  this.boundary = null;
43:
  this.boundaryChars = null;
44:
  this.lookbehind = null;
45:
  this.state = S.PARSER_UNINITIALIZED;
46:
 
47:
  this.index = null;
48:
  this.flags = 0;
49:
};
50:
exports.MultipartParser = MultipartParser;
51:
 
52:
MultipartParser.stateToString = function(stateNumber) {
53:
  for (var state in S) {
54:
    var number = S[state];
55:
    if (number === stateNumber) return state;
56:
  }
57:
};
58:
 
59:
MultipartParser.prototype.initWithBoundary = function(str) {
60:
  this.boundary = new Buffer(str.length+4);
61:
  this.boundary.write('\r\n--', 'ascii', 0);
62:
  this.boundary.write(str, 'ascii', 4);
63:
  this.lookbehind = new Buffer(this.boundary.length+8);
64:
  this.state = S.START;
65:
 
66:
  this.boundaryChars = {};
67:
  for (var i = 0; i < this.boundary.length; i++) {
68:
    this.boundaryChars[this.boundary[i]] = true;
69:
  }
70:
};
71:
 
72:
MultipartParser.prototype.write = function(buffer) {
73:
  var self = this,
74:
      i = 0,
75:
      len = buffer.length,
76:
      prevIndex = this.index,
77:
      index = this.index,
78:
      state = this.state,
79:
      flags = this.flags,
80:
      lookbehind = this.lookbehind,
81:
      boundary = this.boundary,
82:
      boundaryChars = this.boundaryChars,
83:
      boundaryLength = this.boundary.length,
84:
      boundaryEnd = boundaryLength - 1,
85:
      bufferLength = buffer.length,
86:
      c,
87:
      cl,
88:
 
89:
      mark = function(name) {
90:
        self[name+'Mark'] = i;
91:
      },
92:
      clear = function(name) {
93:
        delete self[name+'Mark'];
94:
      },
95:
      callback = function(name, buffer, start, end) {
96:
        if (start !== undefined && start === end) {
97:
          return;
98:
        }
99:
 
100:
        var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
101:
        if (callbackSymbol in self) {
102:
          self[callbackSymbol](buffer, start, end);
103:
        }
104:
      },
105:
      dataCallback = function(name, clear) {
106:
        var markSymbol = name+'Mark';
107:
        if (!(markSymbol in self)) {
108:
          return;
109:
        }
110:
 
111:
        if (!clear) {
112:
          callback(name, buffer, self[markSymbol], buffer.length);
113:
          self[markSymbol] = 0;
114:
        } else {
115:
          callback(name, buffer, self[markSymbol], i);
116:
          delete self[markSymbol];
117:
        }
118:
      };
119:
 
120:
  for (i = 0; i < len; i++) {
121:
    c = buffer[i];
122:
    switch (state) {
123:
      case S.PARSER_UNINITIALIZED:
124:
        return i;
125:
      case S.START:
126:
        index = 0;
127:
        state = S.START_BOUNDARY;
128:
      case S.START_BOUNDARY:
129:
        if (index == boundary.length - 2) {
130:
          if (c != CR) {
131:
            return i;
132:
          }
133:
          index++;
134:
          break;
135:
        } else if (index - 1 == boundary.length - 2) {
136:
          if (c != LF) {
137:
            return i;
138:
          }
139:
          index = 0;
140:
          callback('partBegin');
141:
          state = S.HEADER_FIELD_START;
142:
          break;
143:
        }
144:
 
145:
        if (c != boundary[index+2]) {
146:
          index = -2;
147:
        }
148:
        if (c == boundary[index+2]) {
149:
          index++;
150:
        }
151:
        break;
152:
      case S.HEADER_FIELD_START:
153:
        state = S.HEADER_FIELD;
154:
        mark('headerField');
155:
        index = 0;
156:
      case S.HEADER_FIELD:
157:
        if (c == CR) {
158:
          clear('headerField');
159:
          state = S.HEADERS_ALMOST_DONE;
160:
          break;
161:
        }
162:
 
163:
        index++;
164:
        if (c == HYPHEN) {
165:
          break;
166:
        }
167:
 
168:
        if (c == COLON) {
169:
          if (index == 1) {
170:
            // empty header field
171:
            return i;
172:
          }
173:
          dataCallback('headerField', true);
174:
          state = S.HEADER_VALUE_START;
175:
          break;
176:
        }
177:
 
178:
        cl = lower(c);
179:
        if (cl < A || cl > Z) {
180:
          return i;
181:
        }
182:
        break;
183:
      case S.HEADER_VALUE_START:
184:
        if (c == SPACE) {
185:
          break;
186:
        }
187:
 
188:
        mark('headerValue');
189:
        state = S.HEADER_VALUE;
190:
      case S.HEADER_VALUE:
191:
        if (c == CR) {
192:
          dataCallback('headerValue', true);
193:
          callback('headerEnd');
194:
          state = S.HEADER_VALUE_ALMOST_DONE;
195:
        }
196:
        break;
197:
      case S.HEADER_VALUE_ALMOST_DONE:
198:
        if (c != LF) {
199:
          return i;
200:
        }
201:
        state = S.HEADER_FIELD_START;
202:
        break;
203:
      case S.HEADERS_ALMOST_DONE:
204:
        if (c != LF) {
205:
          return i;
206:
        }
207:
 
208:
        callback('headersEnd');
209:
        state = S.PART_DATA_START;
210:
        break;
211:
      case S.PART_DATA_START:
212:
        state = S.PART_DATA;
213:
        mark('partData');
214:
      case S.PART_DATA:
215:
        prevIndex = index;
216:
 
217:
        if (index == 0) {
218:
          // boyer-moore derrived algorithm to safely skip non-boundary data
219:
          i += boundaryEnd;
220:
          while (i < bufferLength && !(buffer[i] in boundaryChars)) {
221:
            i += boundaryLength;
222:
          }
223:
          i -= boundaryEnd;
224:
          c = buffer[i];
225:
        }
226:
 
227:
        if (index < boundary.length) {
228:
          if (boundary[index] == c) {
229:
            if (index == 0) {
230:
              dataCallback('partData', true);
231:
            }
232:
            index++;
233:
          } else {
234:
            index = 0;
235:
          }
236:
        } else if (index == boundary.length) {
237:
          index++;
238:
          if (c == CR) {
239:
            // CR = part boundary
240:
            flags |= F.PART_BOUNDARY;
241:
          } else if (c == HYPHEN) {
242:
            // HYPHEN = end boundary
243:
            flags |= F.LAST_BOUNDARY;
244:
          } else {
245:
            index = 0;
246:
          }
247:
        } else if (index - 1 == boundary.length)  {
248:
          if (flags & F.PART_BOUNDARY) {
249:
            index = 0;
250:
            if (c == LF) {
251:
              // unset the PART_BOUNDARY flag
252:
              flags &= ~F.PART_BOUNDARY;
253:
              callback('partEnd');
254:
              callback('partBegin');
255:
              state = S.HEADER_FIELD_START;
256:
              break;
257:
            }
258:
          } else if (flags & F.LAST_BOUNDARY) {
259:
            if (c == HYPHEN) {
260:
              callback('partEnd');
261:
              callback('end');
262:
              state = S.END;
263:
            } else {
264:
              index = 0;
265:
            }
266:
          } else {
267:
            index = 0;
268:
          }
269:
        }
270:
 
271:
        if (index > 0) {
272:
          // when matching a possible boundary, keep a lookbehind reference
273:
          // in case it turns out to be a false lead
274:
          lookbehind[index-1] = c;
275:
        } else if (prevIndex > 0) {
276:
          // if our boundary turned out to be rubbish, the captured lookbehind
277:
          // belongs to partData
278:
          callback('partData', lookbehind, 0, prevIndex);
279:
          prevIndex = 0;
280:
          mark('partData');
281:
 
282:
          // reconsider the current character even so it interrupted the sequence
283:
          // it could be the beginning of a new sequence
284:
          i--;
285:
        }
286:
 
287:
        break;
288:
      case S.END:
289:
        break;
290:
      default:
291:
        return i;
292:
    }
293:
  }
294:
 
295:
  dataCallback('headerField');
296:
  dataCallback('headerValue');
297:
  dataCallback('partData');
298:
 
299:
  this.index = index;
300:
  this.state = state;
301:
  this.flags = flags;
302:
 
303:
  return len;
304:
};
305:
 
306:
MultipartParser.prototype.end = function() {
307:
  var callback = function(self, name) {
308:
    var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
309:
    if (callbackSymbol in self) {
310:
      self[callbackSymbol]();
311:
    }
312:
  };
313:
  if ((this.state == S.HEADER_FIELD_START && this.index == 0) ||
314:
      (this.state == S.PART_DATA && this.index == this.boundary.length)) {
315:
    callback(this, 'partEnd');
316:
    callback(this, 'end');
317:
  } else if (this.state != S.END) {
318:
    return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain());
319:
  }
320:
};
321:
 
322:
MultipartParser.prototype.explain = function() {
323:
  return 'state = ' + MultipartParser.stateToString(this.state);
324:
};