summaryrefslogtreecommitdiff
path: root/node_modules/express
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2012-09-24 16:22:07 -0400
committerJules Laplace <jules@okfoc.us>2012-09-24 16:22:07 -0400
commit686106d544ecc3b6ffd4db2b665d3bc879a58d8c (patch)
treea5b5e50237cef70e12f0745371896e96f5f6d578 /node_modules/express
ok
Diffstat (limited to 'node_modules/express')
-rw-r--r--node_modules/express/.npmignore7
-rw-r--r--node_modules/express/History.md805
-rw-r--r--node_modules/express/LICENSE22
-rw-r--r--node_modules/express/Makefile29
-rw-r--r--node_modules/express/Readme.md145
-rwxr-xr-xnode_modules/express/bin/express416
-rw-r--r--node_modules/express/index.js2
-rw-r--r--node_modules/express/lib/express.js79
-rw-r--r--node_modules/express/lib/http.js582
-rw-r--r--node_modules/express/lib/https.js52
-rw-r--r--node_modules/express/lib/request.js323
-rw-r--r--node_modules/express/lib/response.js460
-rw-r--r--node_modules/express/lib/router/collection.js53
-rw-r--r--node_modules/express/lib/router/index.js398
-rw-r--r--node_modules/express/lib/router/methods.js70
-rw-r--r--node_modules/express/lib/router/route.js88
-rw-r--r--node_modules/express/lib/utils.js152
-rw-r--r--node_modules/express/lib/view.js460
-rw-r--r--node_modules/express/lib/view/partial.js40
-rw-r--r--node_modules/express/lib/view/view.js210
-rw-r--r--node_modules/express/node_modules/connect/.npmignore11
-rw-r--r--node_modules/express/node_modules/connect/LICENSE24
-rw-r--r--node_modules/express/node_modules/connect/index.js2
-rw-r--r--node_modules/express/node_modules/connect/lib/cache.js81
-rw-r--r--node_modules/express/node_modules/connect/lib/connect.js106
-rw-r--r--node_modules/express/node_modules/connect/lib/http.js217
-rw-r--r--node_modules/express/node_modules/connect/lib/https.js47
-rw-r--r--node_modules/express/node_modules/connect/lib/index.js46
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/basicAuth.js93
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/bodyParser.js196
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/compiler.js163
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/cookieParser.js46
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/csrf.js105
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/directory.js222
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/errorHandler.js100
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/favicon.js76
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/limit.js80
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/logger.js299
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/methodOverride.js38
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/profiler.js100
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/query.js40
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/responseTime.js34
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/router.js379
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/session.js345
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/session/cookie.js126
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/session/memory.js131
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/session/session.js137
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/session/store.js87
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/static.js225
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/staticCache.js175
-rw-r--r--node_modules/express/node_modules/connect/lib/middleware/vhost.js44
-rw-r--r--node_modules/express/node_modules/connect/lib/patch.js79
-rw-r--r--node_modules/express/node_modules/connect/lib/public/directory.html75
-rw-r--r--node_modules/express/node_modules/connect/lib/public/error.html13
-rw-r--r--node_modules/express/node_modules/connect/lib/public/favicon.icobin0 -> 1406 bytes
-rw-r--r--node_modules/express/node_modules/connect/lib/public/style.css141
-rw-r--r--node_modules/express/node_modules/connect/lib/utils.js451
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/.npmignore4
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml4
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/Makefile14
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/Readme.md303
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/TODO3
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js70
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/example/post.js43
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js48
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/index.js1
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js61
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js378
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js3
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js312
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js25
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js6
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/package.json32
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/common.js19
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt1
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt1
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md3
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js3
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js21
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js72
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js89
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js24
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js80
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js104
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js726
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js50
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js45
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js72
-rwxr-xr-xnode_modules/express/node_modules/connect/node_modules/formidable/test/run.js2
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js63
-rw-r--r--node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js47
-rw-r--r--node_modules/express/node_modules/connect/package.json49
-rw-r--r--node_modules/express/node_modules/mime/LICENSE19
-rw-r--r--node_modules/express/node_modules/mime/README.md50
-rw-r--r--node_modules/express/node_modules/mime/mime.js92
-rw-r--r--node_modules/express/node_modules/mime/package.json40
-rw-r--r--node_modules/express/node_modules/mime/test.js79
-rw-r--r--node_modules/express/node_modules/mime/types/mime.types1479
-rw-r--r--node_modules/express/node_modules/mime/types/node.types43
-rw-r--r--node_modules/express/node_modules/mkdirp/.gitignore.orig2
-rw-r--r--node_modules/express/node_modules/mkdirp/.gitignore.rej5
-rw-r--r--node_modules/express/node_modules/mkdirp/.npmignore2
-rw-r--r--node_modules/express/node_modules/mkdirp/LICENSE21
-rw-r--r--node_modules/express/node_modules/mkdirp/README.markdown54
-rw-r--r--node_modules/express/node_modules/mkdirp/examples/pow.js6
-rw-r--r--node_modules/express/node_modules/mkdirp/examples/pow.js.orig6
-rw-r--r--node_modules/express/node_modules/mkdirp/examples/pow.js.rej19
-rw-r--r--node_modules/express/node_modules/mkdirp/index.js79
-rw-r--r--node_modules/express/node_modules/mkdirp/package.json40
-rw-r--r--node_modules/express/node_modules/mkdirp/test/chmod.js38
-rw-r--r--node_modules/express/node_modules/mkdirp/test/clobber.js37
-rw-r--r--node_modules/express/node_modules/mkdirp/test/mkdirp.js28
-rw-r--r--node_modules/express/node_modules/mkdirp/test/perm.js32
-rw-r--r--node_modules/express/node_modules/mkdirp/test/perm_sync.js39
-rw-r--r--node_modules/express/node_modules/mkdirp/test/race.js41
-rw-r--r--node_modules/express/node_modules/mkdirp/test/rel.js32
-rw-r--r--node_modules/express/node_modules/mkdirp/test/sync.js27
-rw-r--r--node_modules/express/node_modules/mkdirp/test/umask.js28
-rw-r--r--node_modules/express/node_modules/mkdirp/test/umask_sync.js27
-rw-r--r--node_modules/express/node_modules/qs/.gitmodules6
-rw-r--r--node_modules/express/node_modules/qs/.npmignore1
-rw-r--r--node_modules/express/node_modules/qs/.travis.yml4
-rw-r--r--node_modules/express/node_modules/qs/History.md73
-rw-r--r--node_modules/express/node_modules/qs/Makefile5
-rw-r--r--node_modules/express/node_modules/qs/Readme.md54
-rw-r--r--node_modules/express/node_modules/qs/benchmark.js17
-rw-r--r--node_modules/express/node_modules/qs/examples.js51
-rw-r--r--node_modules/express/node_modules/qs/index.js2
-rw-r--r--node_modules/express/node_modules/qs/lib/querystring.js264
-rw-r--r--node_modules/express/node_modules/qs/package.json33
-rw-r--r--node_modules/express/node_modules/qs/test/mocha.opts2
-rw-r--r--node_modules/express/node_modules/qs/test/parse.js167
-rw-r--r--node_modules/express/node_modules/qs/test/stringify.js103
-rw-r--r--node_modules/express/package.json74
-rw-r--r--node_modules/express/testing/foo/app.js35
-rw-r--r--node_modules/express/testing/foo/package.json9
-rw-r--r--node_modules/express/testing/foo/public/stylesheets/style.css8
-rw-r--r--node_modules/express/testing/foo/routes/index.js10
-rw-r--r--node_modules/express/testing/foo/views/index.jade2
-rw-r--r--node_modules/express/testing/foo/views/layout.jade6
-rw-r--r--node_modules/express/testing/index.js43
-rw-r--r--node_modules/express/testing/public/test.txt2971
-rw-r--r--node_modules/express/testing/views/page.html1
-rw-r--r--node_modules/express/testing/views/page.jade3
-rw-r--r--node_modules/express/testing/views/test.md1
-rw-r--r--node_modules/express/testing/views/user/index.jade1
-rw-r--r--node_modules/express/testing/views/user/list.jade1
147 files changed, 18017 insertions, 0 deletions
diff --git a/node_modules/express/.npmignore b/node_modules/express/.npmignore
new file mode 100644
index 0000000..74bd365
--- /dev/null
+++ b/node_modules/express/.npmignore
@@ -0,0 +1,7 @@
+.git*
+docs/
+examples/
+support/
+test/
+testing.js
+.DS_Store
diff --git a/node_modules/express/History.md b/node_modules/express/History.md
new file mode 100644
index 0000000..113ae6f
--- /dev/null
+++ b/node_modules/express/History.md
@@ -0,0 +1,805 @@
+
+2.5.8 / 2012-02-08
+==================
+
+ * Update mkdirp dep. Closes #991
+
+2.5.7 / 2012-02-06
+==================
+
+ * Fixed `app.all` duplicate DELETE requests [mscdex]
+
+2.5.6 / 2012-01-13
+==================
+
+ * Updated hamljs dev dep. Closes #953
+
+2.5.5 / 2012-01-08
+==================
+
+ * Fixed: set `filename` on cached templates [matthewleon]
+
+2.5.4 / 2012-01-02
+==================
+
+ * Fixed `express(1)` eol on 0.4.x. Closes #947
+
+2.5.3 / 2011-12-30
+==================
+
+ * Fixed `req.is()` when a charset is present
+
+2.5.2 / 2011-12-10
+==================
+
+ * Fixed: express(1) LF -> CRLF for windows
+
+2.5.1 / 2011-11-17
+==================
+
+ * Changed: updated connect to 1.8.x
+ * Removed sass.js support from express(1)
+
+2.5.0 / 2011-10-24
+==================
+
+ * Added ./routes dir for generated app by default
+ * Added npm install reminder to express(1) app gen
+ * Added 0.5.x support
+ * Removed `make test-cov` since it wont work with node 0.5.x
+ * Fixed express(1) public dir for windows. Closes #866
+
+2.4.7 / 2011-10-05
+==================
+
+ * Added mkdirp to express(1). Closes #795
+ * Added simple _json-config_ example
+ * Added shorthand for the parsed request's pathname via `req.path`
+ * Changed connect dep to 1.7.x to fix npm issue...
+ * Fixed `res.redirect()` __HEAD__ support. [reported by xerox]
+ * Fixed `req.flash()`, only escape args
+ * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie]
+
+2.4.6 / 2011-08-22
+==================
+
+ * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode]
+
+2.4.5 / 2011-08-19
+==================
+
+ * Added support for routes to handle errors. Closes #809
+ * Added `app.routes.all()`. Closes #803
+ * Added "basepath" setting to work in conjunction with reverse proxies etc.
+ * Refactored `Route` to use a single array of callbacks
+ * Added support for multiple callbacks for `app.param()`. Closes #801
+Closes #805
+ * Changed: removed .call(self) for route callbacks
+ * Dependency: `qs >= 0.3.1`
+ * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808
+
+2.4.4 / 2011-08-05
+==================
+
+ * Fixed `res.header()` intention of a set, even when `undefined`
+ * Fixed `*`, value no longer required
+ * Fixed `res.send(204)` support. Closes #771
+
+2.4.3 / 2011-07-14
+==================
+
+ * Added docs for `status` option special-case. Closes #739
+ * Fixed `options.filename`, exposing the view path to template engines
+
+2.4.2. / 2011-07-06
+==================
+
+ * Revert "removed jsonp stripping" for XSS
+
+2.4.1 / 2011-07-06
+==================
+
+ * Added `res.json()` JSONP support. Closes #737
+ * Added _extending-templates_ example. Closes #730
+ * Added "strict routing" setting for trailing slashes
+ * Added support for multiple envs in `app.configure()` calls. Closes #735
+ * Changed: `res.send()` using `res.json()`
+ * Changed: when cookie `path === null` don't default it
+ * Changed; default cookie path to "home" setting. Closes #731
+ * Removed _pids/logs_ creation from express(1)
+
+2.4.0 / 2011-06-28
+==================
+
+ * Added chainable `res.status(code)`
+ * Added `res.json()`, an explicit version of `res.send(obj)`
+ * Added simple web-service example
+
+2.3.12 / 2011-06-22
+==================
+
+ * \#express is now on freenode! come join!
+ * Added `req.get(field, param)`
+ * Added links to Japanese documentation, thanks @hideyukisaito!
+ * Added; the `express(1)` generated app outputs the env
+ * Added `content-negotiation` example
+ * Dependency: connect >= 1.5.1 < 2.0.0
+ * Fixed view layout bug. Closes #720
+ * Fixed; ignore body on 304. Closes #701
+
+2.3.11 / 2011-06-04
+==================
+
+ * Added `npm test`
+ * Removed generation of dummy test file from `express(1)`
+ * Fixed; `express(1)` adds express as a dep
+ * Fixed; prune on `prepublish`
+
+2.3.10 / 2011-05-27
+==================
+
+ * Added `req.route`, exposing the current route
+ * Added _package.json_ generation support to `express(1)`
+ * Fixed call to `app.param()` function for optional params. Closes #682
+
+2.3.9 / 2011-05-25
+==================
+
+ * Fixed bug-ish with `../' in `res.partial()` calls
+
+2.3.8 / 2011-05-24
+==================
+
+ * Fixed `app.options()`
+
+2.3.7 / 2011-05-23
+==================
+
+ * Added route `Collection`, ex: `app.get('/user/:id').remove();`
+ * Added support for `app.param(fn)` to define param logic
+ * Removed `app.param()` support for callback with return value
+ * Removed module.parent check from express(1) generated app. Closes #670
+ * Refactored router. Closes #639
+
+2.3.6 / 2011-05-20
+==================
+
+ * Changed; using devDependencies instead of git submodules
+ * Fixed redis session example
+ * Fixed markdown example
+ * Fixed view caching, should not be enabled in development
+
+2.3.5 / 2011-05-20
+==================
+
+ * Added export `.view` as alias for `.View`
+
+2.3.4 / 2011-05-08
+==================
+
+ * Added `./examples/say`
+ * Fixed `res.sendfile()` bug preventing the transfer of files with spaces
+
+2.3.3 / 2011-05-03
+==================
+
+ * Added "case sensitive routes" option.
+ * Changed; split methods supported per rfc [slaskis]
+ * Fixed route-specific middleware when using the same callback function several times
+
+2.3.2 / 2011-04-27
+==================
+
+ * Fixed view hints
+
+2.3.1 / 2011-04-26
+==================
+
+ * Added `app.match()` as `app.match.all()`
+ * Added `app.lookup()` as `app.lookup.all()`
+ * Added `app.remove()` for `app.remove.all()`
+ * Added `app.remove.VERB()`
+ * Fixed template caching collision issue. Closes #644
+ * Moved router over from connect and started refactor
+
+2.3.0 / 2011-04-25
+==================
+
+ * Added options support to `res.clearCookie()`
+ * Added `res.helpers()` as alias of `res.locals()`
+ * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0`
+ * Changed; auto set Content-Type in res.attachement [Aaron Heckmann]
+ * Renamed "cache views" to "view cache". Closes #628
+ * Fixed caching of views when using several apps. Closes #637
+ * Fixed gotcha invoking `app.param()` callbacks once per route middleware.
+Closes #638
+ * Fixed partial lookup precedence. Closes #631
+Shaw]
+
+2.2.2 / 2011-04-12
+==================
+
+ * Added second callback support for `res.download()` connection errors
+ * Fixed `filename` option passing to template engine
+
+2.2.1 / 2011-04-04
+==================
+
+ * Added `layout(path)` helper to change the layout within a view. Closes #610
+ * Fixed `partial()` collection object support.
+ Previously only anything with `.length` would work.
+ When `.length` is present one must still be aware of holes,
+ however now `{ collection: {foo: 'bar'}}` is valid, exposes
+ `keyInCollection` and `keysInCollection`.
+
+ * Performance improved with better view caching
+ * Removed `request` and `response` locals
+ * Changed; errorHandler page title is now `Express` instead of `Connect`
+
+2.2.0 / 2011-03-30
+==================
+
+ * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606
+ * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606
+ * Added `app.VERB(path)` as alias of `app.lookup.VERB()`.
+ * Dependency `connect >= 1.2.0`
+
+2.1.1 / 2011-03-29
+==================
+
+ * Added; expose `err.view` object when failing to locate a view
+ * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann]
+ * Fixed; `res.send(undefined)` responds with 204 [aheckmann]
+
+2.1.0 / 2011-03-24
+==================
+
+ * Added `<root>/_?<name>` partial lookup support. Closes #447
+ * Added `request`, `response`, and `app` local variables
+ * Added `settings` local variable, containing the app's settings
+ * Added `req.flash()` exception if `req.session` is not available
+ * Added `res.send(bool)` support (json response)
+ * Fixed stylus example for latest version
+ * Fixed; wrap try/catch around `res.render()`
+
+2.0.0 / 2011-03-17
+==================
+
+ * Fixed up index view path alternative.
+ * Changed; `res.locals()` without object returns the locals
+
+2.0.0rc3 / 2011-03-17
+==================
+
+ * Added `res.locals(obj)` to compliment `res.local(key, val)`
+ * Added `res.partial()` callback support
+ * Fixed recursive error reporting issue in `res.render()`
+
+2.0.0rc2 / 2011-03-17
+==================
+
+ * Changed; `partial()` "locals" are now optional
+ * Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01]
+ * Fixed .filename view engine option [reported by drudge]
+ * Fixed blog example
+ * Fixed `{req,res}.app` reference when mounting [Ben Weaver]
+
+2.0.0rc / 2011-03-14
+==================
+
+ * Fixed; expose `HTTPSServer` constructor
+ * Fixed express(1) default test charset. Closes #579 [reported by secoif]
+ * Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP]
+
+2.0.0beta3 / 2011-03-09
+==================
+
+ * Added support for `res.contentType()` literal
+ The original `res.contentType('.json')`,
+ `res.contentType('application/json')`, and `res.contentType('json')`
+ will work now.
+ * Added `res.render()` status option support back
+ * Added charset option for `res.render()`
+ * Added `.charset` support (via connect 1.0.4)
+ * Added view resolution hints when in development and a lookup fails
+ * Added layout lookup support relative to the page view.
+ For example while rendering `./views/user/index.jade` if you create
+ `./views/user/layout.jade` it will be used in favour of the root layout.
+ * Fixed `res.redirect()`. RFC states absolute url [reported by unlink]
+ * Fixed; default `res.send()` string charset to utf8
+ * Removed `Partial` constructor (not currently used)
+
+2.0.0beta2 / 2011-03-07
+==================
+
+ * Added res.render() `.locals` support back to aid in migration process
+ * Fixed flash example
+
+2.0.0beta / 2011-03-03
+==================
+
+ * Added HTTPS support
+ * Added `res.cookie()` maxAge support
+ * Added `req.header()` _Referrer_ / _Referer_ special-case, either works
+ * Added mount support for `res.redirect()`, now respects the mount-point
+ * Added `union()` util, taking place of `merge(clone())` combo
+ * Added stylus support to express(1) generated app
+ * Added secret to session middleware used in examples and generated app
+ * Added `res.local(name, val)` for progressive view locals
+ * Added default param support to `req.param(name, default)`
+ * Added `app.disabled()` and `app.enabled()`
+ * Added `app.register()` support for omitting leading ".", either works
+ * Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539
+ * Added `app.param()` to map route params to async/sync logic
+ * Added; aliased `app.helpers()` as `app.locals()`. Closes #481
+ * Added extname with no leading "." support to `res.contentType()`
+ * Added `cache views` setting, defaulting to enabled in "production" env
+ * Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_.
+ * Added `req.accepts()` support for extensions
+ * Changed; `res.download()` and `res.sendfile()` now utilize Connect's
+ static file server `connect.static.send()`.
+ * Changed; replaced `connect.utils.mime()` with npm _mime_ module
+ * Changed; allow `req.query` to be pre-defined (via middleware or other parent
+ * Changed view partial resolution, now relative to parent view
+ * Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`.
+ * Fixed `req.param()` bug returning Array.prototype methods. Closes #552
+ * Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()`
+ * Fixed; using _qs_ module instead of _querystring_
+ * Fixed; strip unsafe chars from jsonp callbacks
+ * Removed "stream threshold" setting
+
+1.0.8 / 2011-03-01
+==================
+
+ * Allow `req.query` to be pre-defined (via middleware or other parent app)
+ * "connect": ">= 0.5.0 < 1.0.0". Closes #547
+ * Removed the long deprecated __EXPRESS_ENV__ support
+
+1.0.7 / 2011-02-07
+==================
+
+ * Fixed `render()` setting inheritance.
+ Mounted apps would not inherit "view engine"
+
+1.0.6 / 2011-02-07
+==================
+
+ * Fixed `view engine` setting bug when period is in dirname
+
+1.0.5 / 2011-02-05
+==================
+
+ * Added secret to generated app `session()` call
+
+1.0.4 / 2011-02-05
+==================
+
+ * Added `qs` dependency to _package.json_
+ * Fixed namespaced `require()`s for latest connect support
+
+1.0.3 / 2011-01-13
+==================
+
+ * Remove unsafe characters from JSONP callback names [Ryan Grove]
+
+1.0.2 / 2011-01-10
+==================
+
+ * Removed nested require, using `connect.router`
+
+1.0.1 / 2010-12-29
+==================
+
+ * Fixed for middleware stacked via `createServer()`
+ previously the `foo` middleware passed to `createServer(foo)`
+ would not have access to Express methods such as `res.send()`
+ or props like `req.query` etc.
+
+1.0.0 / 2010-11-16
+==================
+
+ * Added; deduce partial object names from the last segment.
+ For example by default `partial('forum/post', postObject)` will
+ give you the _post_ object, providing a meaningful default.
+ * Added http status code string representation to `res.redirect()` body
+ * Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__.
+ * Added `req.is()` to aid in content negotiation
+ * Added partial local inheritance [suggested by masylum]. Closes #102
+ providing access to parent template locals.
+ * Added _-s, --session[s]_ flag to express(1) to add session related middleware
+ * Added _--template_ flag to express(1) to specify the
+ template engine to use.
+ * Added _--css_ flag to express(1) to specify the
+ stylesheet engine to use (or just plain css by default).
+ * Added `app.all()` support [thanks aheckmann]
+ * Added partial direct object support.
+ You may now `partial('user', user)` providing the "user" local,
+ vs previously `partial('user', { object: user })`.
+ * Added _route-separation_ example since many people question ways
+ to do this with CommonJS modules. Also view the _blog_ example for
+ an alternative.
+ * Performance; caching view path derived partial object names
+ * Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454
+ * Fixed jsonp support; _text/javascript_ as per mailinglist discussion
+
+1.0.0rc4 / 2010-10-14
+==================
+
+ * Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0
+ * Added route-middleware support (very helpful, see the [docs](http://expressjs.com/guide.html#Route-Middleware))
+ * Added _jsonp callback_ setting to enable/disable jsonp autowrapping [Dav Glass]
+ * Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass]
+ * Added `partial()` support for array-like collections. Closes #434
+ * Added support for swappable querystring parsers
+ * Added session usage docs. Closes #443
+ * Added dynamic helper caching. Closes #439 [suggested by maritz]
+ * Added authentication example
+ * Added basic Range support to `res.sendfile()` (and `res.download()` etc)
+ * Changed; `express(1)` generated app using 2 spaces instead of 4
+ * Default env to "development" again [aheckmann]
+ * Removed _context_ option is no more, use "scope"
+ * Fixed; exposing _./support_ libs to examples so they can run without installs
+ * Fixed mvc example
+
+1.0.0rc3 / 2010-09-20
+==================
+
+ * Added confirmation for `express(1)` app generation. Closes #391
+ * Added extending of flash formatters via `app.flashFormatters`
+ * Added flash formatter support. Closes #411
+ * Added streaming support to `res.sendfile()` using `sys.pump()` when >= "stream threshold"
+ * Added _stream threshold_ setting for `res.sendfile()`
+ * Added `res.send()` __HEAD__ support
+ * Added `res.clearCookie()`
+ * Added `res.cookie()`
+ * Added `res.render()` headers option
+ * Added `res.redirect()` response bodies
+ * Added `res.render()` status option support. Closes #425 [thanks aheckmann]
+ * Fixed `res.sendfile()` responding with 403 on malicious path
+ * Fixed `res.download()` bug; when an error occurs remove _Content-Disposition_
+ * Fixed; mounted apps settings now inherit from parent app [aheckmann]
+ * Fixed; stripping Content-Length / Content-Type when 204
+ * Fixed `res.send()` 204. Closes #419
+ * Fixed multiple _Set-Cookie_ headers via `res.header()`. Closes #402
+ * Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo]
+
+
+1.0.0rc2 / 2010-08-17
+==================
+
+ * Added `app.register()` for template engine mapping. Closes #390
+ * Added `res.render()` callback support as second argument (no options)
+ * Added callback support to `res.download()`
+ * Added callback support for `res.sendfile()`
+ * Added support for middleware access via `express.middlewareName()` vs `connect.middlewareName()`
+ * Added "partials" setting to docs
+ * Added default expresso tests to `express(1)` generated app. Closes #384
+ * Fixed `res.sendfile()` error handling, defer via `next()`
+ * Fixed `res.render()` callback when a layout is used [thanks guillermo]
+ * Fixed; `make install` creating ~/.node_libraries when not present
+ * Fixed issue preventing error handlers from being defined anywhere. Closes #387
+
+1.0.0rc / 2010-07-28
+==================
+
+ * Added mounted hook. Closes #369
+ * Added connect dependency to _package.json_
+
+ * Removed "reload views" setting and support code
+ development env never caches, production always caches.
+
+ * Removed _param_ in route callbacks, signature is now
+ simply (req, res, next), previously (req, res, params, next).
+ Use _req.params_ for path captures, _req.query_ for GET params.
+
+ * Fixed "home" setting
+ * Fixed middleware/router precedence issue. Closes #366
+ * Fixed; _configure()_ callbacks called immediately. Closes #368
+
+1.0.0beta2 / 2010-07-23
+==================
+
+ * Added more examples
+ * Added; exporting `Server` constructor
+ * Added `Server#helpers()` for view locals
+ * Added `Server#dynamicHelpers()` for dynamic view locals. Closes #349
+ * Added support for absolute view paths
+ * Added; _home_ setting defaults to `Server#route` for mounted apps. Closes #363
+ * Added Guillermo Rauch to the contributor list
+ * Added support for "as" for non-collection partials. Closes #341
+ * Fixed _install.sh_, ensuring _~/.node_libraries_ exists. Closes #362 [thanks jf]
+ * Fixed `res.render()` exceptions, now passed to `next()` when no callback is given [thanks guillermo]
+ * Fixed instanceof `Array` checks, now `Array.isArray()`
+ * Fixed express(1) expansion of public dirs. Closes #348
+ * Fixed middleware precedence. Closes #345
+ * Fixed view watcher, now async [thanks aheckmann]
+
+1.0.0beta / 2010-07-15
+==================
+
+ * Re-write
+ - much faster
+ - much lighter
+ - Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs
+
+0.14.0 / 2010-06-15
+==================
+
+ * Utilize relative requires
+ * Added Static bufferSize option [aheckmann]
+ * Fixed caching of view and partial subdirectories [aheckmann]
+ * Fixed mime.type() comments now that ".ext" is not supported
+ * Updated haml submodule
+ * Updated class submodule
+ * Removed bin/express
+
+0.13.0 / 2010-06-01
+==================
+
+ * Added node v0.1.97 compatibility
+ * Added support for deleting cookies via Request#cookie('key', null)
+ * Updated haml submodule
+ * Fixed not-found page, now using using charset utf-8
+ * Fixed show-exceptions page, now using using charset utf-8
+ * Fixed view support due to fs.readFile Buffers
+ * Changed; mime.type() no longer accepts ".type" due to node extname() changes
+
+0.12.0 / 2010-05-22
+==================
+
+ * Added node v0.1.96 compatibility
+ * Added view `helpers` export which act as additional local variables
+ * Updated haml submodule
+ * Changed ETag; removed inode, modified time only
+ * Fixed LF to CRLF for setting multiple cookies
+ * Fixed cookie complation; values are now urlencoded
+ * Fixed cookies parsing; accepts quoted values and url escaped cookies
+
+0.11.0 / 2010-05-06
+==================
+
+ * Added support for layouts using different engines
+ - this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' })
+ - this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml'
+ - this.render('page.html.haml', { layout: false }) // no layout
+ * Updated ext submodule
+ * Updated haml submodule
+ * Fixed EJS partial support by passing along the context. Issue #307
+
+0.10.1 / 2010-05-03
+==================
+
+ * Fixed binary uploads.
+
+0.10.0 / 2010-04-30
+==================
+
+ * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s
+ encoding is set to 'utf8' or 'utf-8'.
+ * Added "encoding" option to Request#render(). Closes #299
+ * Added "dump exceptions" setting, which is enabled by default.
+ * Added simple ejs template engine support
+ * Added error reponse support for text/plain, application/json. Closes #297
+ * Added callback function param to Request#error()
+ * Added Request#sendHead()
+ * Added Request#stream()
+ * Added support for Request#respond(304, null) for empty response bodies
+ * Added ETag support to Request#sendfile()
+ * Added options to Request#sendfile(), passed to fs.createReadStream()
+ * Added filename arg to Request#download()
+ * Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request
+ * Performance enhanced by preventing several calls to toLowerCase() in Router#match()
+ * Changed; Request#sendfile() now streams
+ * Changed; Renamed Request#halt() to Request#respond(). Closes #289
+ * Changed; Using sys.inspect() instead of JSON.encode() for error output
+ * Changed; run() returns the http.Server instance. Closes #298
+ * Changed; Defaulting Server#host to null (INADDR_ANY)
+ * Changed; Logger "common" format scale of 0.4f
+ * Removed Logger "request" format
+ * Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found
+ * Fixed several issues with http client
+ * Fixed Logger Content-Length output
+ * Fixed bug preventing Opera from retaining the generated session id. Closes #292
+
+0.9.0 / 2010-04-14
+==================
+
+ * Added DSL level error() route support
+ * Added DSL level notFound() route support
+ * Added Request#error()
+ * Added Request#notFound()
+ * Added Request#render() callback function. Closes #258
+ * Added "max upload size" setting
+ * Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254
+ * Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js
+ * Added callback function support to Request#halt() as 3rd/4th arg
+ * Added preprocessing of route param wildcards using param(). Closes #251
+ * Added view partial support (with collections etc)
+ * Fixed bug preventing falsey params (such as ?page=0). Closes #286
+ * Fixed setting of multiple cookies. Closes #199
+ * Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml)
+ * Changed; session cookie is now httpOnly
+ * Changed; Request is no longer global
+ * Changed; Event is no longer global
+ * Changed; "sys" module is no longer global
+ * Changed; moved Request#download to Static plugin where it belongs
+ * Changed; Request instance created before body parsing. Closes #262
+ * Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253
+ * Changed; Pre-caching view partials in memory when "cache view partials" is enabled
+ * Updated support to node --version 0.1.90
+ * Updated dependencies
+ * Removed set("session cookie") in favour of use(Session, { cookie: { ... }})
+ * Removed utils.mixin(); use Object#mergeDeep()
+
+0.8.0 / 2010-03-19
+==================
+
+ * Added coffeescript example app. Closes #242
+ * Changed; cache api now async friendly. Closes #240
+ * Removed deprecated 'express/static' support. Use 'express/plugins/static'
+
+0.7.6 / 2010-03-19
+==================
+
+ * Added Request#isXHR. Closes #229
+ * Added `make install` (for the executable)
+ * Added `express` executable for setting up simple app templates
+ * Added "GET /public/*" to Static plugin, defaulting to <root>/public
+ * Added Static plugin
+ * Fixed; Request#render() only calls cache.get() once
+ * Fixed; Namespacing View caches with "view:"
+ * Fixed; Namespacing Static caches with "static:"
+ * Fixed; Both example apps now use the Static plugin
+ * Fixed set("views"). Closes #239
+ * Fixed missing space for combined log format
+ * Deprecated Request#sendfile() and 'express/static'
+ * Removed Server#running
+
+0.7.5 / 2010-03-16
+==================
+
+ * Added Request#flash() support without args, now returns all flashes
+ * Updated ext submodule
+
+0.7.4 / 2010-03-16
+==================
+
+ * Fixed session reaper
+ * Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft)
+
+0.7.3 / 2010-03-16
+==================
+
+ * Added package.json
+ * Fixed requiring of haml / sass due to kiwi removal
+
+0.7.2 / 2010-03-16
+==================
+
+ * Fixed GIT submodules (HAH!)
+
+0.7.1 / 2010-03-16
+==================
+
+ * Changed; Express now using submodules again until a PM is adopted
+ * Changed; chat example using millisecond conversions from ext
+
+0.7.0 / 2010-03-15
+==================
+
+ * Added Request#pass() support (finds the next matching route, or the given path)
+ * Added Logger plugin (default "common" format replaces CommonLogger)
+ * Removed Profiler plugin
+ * Removed CommonLogger plugin
+
+0.6.0 / 2010-03-11
+==================
+
+ * Added seed.yml for kiwi package management support
+ * Added HTTP client query string support when method is GET. Closes #205
+
+ * Added support for arbitrary view engines.
+ For example "foo.engine.html" will now require('engine'),
+ the exports from this module are cached after the first require().
+
+ * Added async plugin support
+
+ * Removed usage of RESTful route funcs as http client
+ get() etc, use http.get() and friends
+
+ * Removed custom exceptions
+
+0.5.0 / 2010-03-10
+==================
+
+ * Added ext dependency (library of js extensions)
+ * Removed extname() / basename() utils. Use path module
+ * Removed toArray() util. Use arguments.values
+ * Removed escapeRegexp() util. Use RegExp.escape()
+ * Removed process.mixin() dependency. Use utils.mixin()
+ * Removed Collection
+ * Removed ElementCollection
+ * Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com) ;)
+
+0.4.0 / 2010-02-11
+==================
+
+ * Added flash() example to sample upload app
+ * Added high level restful http client module (express/http)
+ * Changed; RESTful route functions double as HTTP clients. Closes #69
+ * Changed; throwing error when routes are added at runtime
+ * Changed; defaulting render() context to the current Request. Closes #197
+ * Updated haml submodule
+
+0.3.0 / 2010-02-11
+==================
+
+ * Updated haml / sass submodules. Closes #200
+ * Added flash message support. Closes #64
+ * Added accepts() now allows multiple args. fixes #117
+ * Added support for plugins to halt. Closes #189
+ * Added alternate layout support. Closes #119
+ * Removed Route#run(). Closes #188
+ * Fixed broken specs due to use(Cookie) missing
+
+0.2.1 / 2010-02-05
+==================
+
+ * Added "plot" format option for Profiler (for gnuplot processing)
+ * Added request number to Profiler plugin
+ * Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8
+ * Fixed issue with routes not firing when not files are present. Closes #184
+ * Fixed process.Promise -> events.Promise
+
+0.2.0 / 2010-02-03
+==================
+
+ * Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180
+ * Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174
+ * Added expiration support to cache api with reaper. Closes #133
+ * Added cache Store.Memory#reap()
+ * Added Cache; cache api now uses first class Cache instances
+ * Added abstract session Store. Closes #172
+ * Changed; cache Memory.Store#get() utilizing Collection
+ * Renamed MemoryStore -> Store.Memory
+ * Fixed use() of the same plugin several time will always use latest options. Closes #176
+
+0.1.0 / 2010-02-03
+==================
+
+ * Changed; Hooks (before / after) pass request as arg as well as evaluated in their context
+ * Updated node support to 0.1.27 Closes #169
+ * Updated dirname(__filename) -> __dirname
+ * Updated libxmljs support to v0.2.0
+ * Added session support with memory store / reaping
+ * Added quick uid() helper
+ * Added multi-part upload support
+ * Added Sass.js support / submodule
+ * Added production env caching view contents and static files
+ * Added static file caching. Closes #136
+ * Added cache plugin with memory stores
+ * Added support to StaticFile so that it works with non-textual files.
+ * Removed dirname() helper
+ * Removed several globals (now their modules must be required)
+
+0.0.2 / 2010-01-10
+==================
+
+ * Added view benchmarks; currently haml vs ejs
+ * Added Request#attachment() specs. Closes #116
+ * Added use of node's parseQuery() util. Closes #123
+ * Added `make init` for submodules
+ * Updated Haml
+ * Updated sample chat app to show messages on load
+ * Updated libxmljs parseString -> parseHtmlString
+ * Fixed `make init` to work with older versions of git
+ * Fixed specs can now run independant specs for those who cant build deps. Closes #127
+ * Fixed issues introduced by the node url module changes. Closes 126.
+ * Fixed two assertions failing due to Collection#keys() returning strings
+ * Fixed faulty Collection#toArray() spec due to keys() returning strings
+ * Fixed `make test` now builds libxmljs.node before testing
+
+0.0.1 / 2010-01-03
+==================
+
+ * Initial release
diff --git a/node_modules/express/LICENSE b/node_modules/express/LICENSE
new file mode 100644
index 0000000..36075a3
--- /dev/null
+++ b/node_modules/express/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2009-2011 TJ Holowaychuk <tj@vision-media.ca>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/node_modules/express/Makefile b/node_modules/express/Makefile
new file mode 100644
index 0000000..dfbfd67
--- /dev/null
+++ b/node_modules/express/Makefile
@@ -0,0 +1,29 @@
+
+DOCS = $(shell find docs/*.md)
+HTMLDOCS = $(DOCS:.md=.html)
+TESTS = $(shell find test/*.test.js)
+
+test:
+ @NODE_ENV=test ./node_modules/.bin/expresso $(TESTS)
+
+docs: $(HTMLDOCS)
+ @ echo "... generating TOC"
+ @./support/toc.js docs/guide.html
+
+%.html: %.md
+ @echo "... $< -> $@"
+ @markdown $< \
+ | cat docs/layout/head.html - docs/layout/foot.html \
+ > $@
+
+site:
+ rm -fr /tmp/docs \
+ && cp -fr docs /tmp/docs \
+ && git checkout gh-pages \
+ && cp -fr /tmp/docs/* . \
+ && echo "done"
+
+docclean:
+ rm -f docs/*.{1,html}
+
+.PHONY: site test docs docclean \ No newline at end of file
diff --git a/node_modules/express/Readme.md b/node_modules/express/Readme.md
new file mode 100644
index 0000000..d2c64c7
--- /dev/null
+++ b/node_modules/express/Readme.md
@@ -0,0 +1,145 @@
+
+# Express
+
+ Insanely fast (and small) server-side JavaScript web development framework
+ built on [node](http://nodejs.org) and [Connect](http://github.com/senchalabs/connect).
+
+ var app = express.createServer();
+
+ app.get('/', function(req, res){
+ res.send('Hello World');
+ });
+
+ app.listen(3000);
+
+## Installation
+
+ $ npm install express
+
+or to access the `express(1)` executable install globally:
+
+ $ npm install -g express
+
+## Quick Start
+
+ The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:
+
+ Create the app:
+
+ $ npm install -g express
+ $ express /tmp/foo && cd /tmp/foo
+
+ Install dependencies:
+
+ $ npm install -d
+
+ Start the server:
+
+ $ node app.js
+
+## Features
+
+ * Robust routing
+ * Redirection helpers
+ * Dynamic view helpers
+ * Content negotiation
+ * Focus on high performance
+ * View rendering and partials support
+ * Environment based configuration
+ * Session based flash notifications
+ * Built on [Connect](http://github.com/senchalabs/connect)
+ * High test coverage
+ * Executable for generating applications quickly
+ * Application level view options
+
+Via Connect:
+
+ * Session support
+ * Cache API
+ * Mime helpers
+ * ETag support
+ * Persistent flash notifications
+ * Cookie support
+ * JSON-RPC
+ * Logging
+ * and _much_ more!
+
+## Contributors
+
+The following are the major contributors of Express (in no specific order).
+
+ * TJ Holowaychuk ([visionmedia](http://github.com/visionmedia))
+ * Ciaran Jessup ([ciaranj](http://github.com/ciaranj))
+ * Aaron Heckmann ([aheckmann](http://github.com/aheckmann))
+ * Guillermo Rauch ([guille](http://github.com/guille))
+
+## More Information
+
+ * #express on freenode
+ * [express-expose](http://github.com/visionmedia/express-expose) expose objects, functions, modules and more to client-side js with ease
+ * [express-configure](http://github.com/visionmedia/express-configuration) async configuration support
+ * [express-messages](http://github.com/visionmedia/express-messages) flash notification rendering helper
+ * [express-namespace](http://github.com/visionmedia/express-namespace) namespaced route support
+ * [express-params](https://github.com/visionmedia/express-params) param pre-condition functions
+ * [express-mongoose](https://github.com/LearnBoost/express-mongoose) plugin for easy rendering of Mongoose async Query results
+ * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
+ * [Google Group](http://groups.google.com/group/express-js) for discussion
+ * Visit the [Wiki](http://github.com/visionmedia/express/wiki)
+ * [日本語ドキュメンテーション](http://hideyukisaito.com/doc/expressjs/) by [hideyukisaito](https://github.com/hideyukisaito)
+ * Screencast - [Introduction](http://bit.ly/eRYu0O)
+ * Screencast - [View Partials](http://bit.ly/dU13Fx)
+ * Screencast - [Route Specific Middleware](http://bit.ly/hX4IaH)
+ * Screencast - [Route Path Placeholder Preconditions](http://bit.ly/eNqmVs)
+
+## Node Compatibility
+
+Express 1.x is compatible with node 0.2.x and connect < 1.0.
+
+Express 2.x is compatible with node 0.4.x or 0.6.x, and connect 1.x
+
+Express 3.x (master) will be compatible with node 0.6.x and connect 2.x
+
+## Viewing Examples
+
+First install the dev dependencies to install all the example / test suite deps:
+
+ $ npm install
+
+then run whichever tests you want:
+
+ $ node examples/jade/app.js
+
+## Running Tests
+
+To run the test suite first invoke the following command within the repo, installing the development dependencies:
+
+ $ npm install
+
+then run the tests:
+
+ $ make test
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2009-2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/express/bin/express b/node_modules/express/bin/express
new file mode 100755
index 0000000..2c902c3
--- /dev/null
+++ b/node_modules/express/bin/express
@@ -0,0 +1,416 @@
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+ , os = require('os')
+ , exec = require('child_process').exec
+ , mkdirp = require('mkdirp');
+
+/**
+ * Framework version.
+ */
+
+var version = '2.5.8';
+
+/**
+ * Add session support.
+ */
+
+var sessions = false;
+
+/**
+ * CSS engine to utilize.
+ */
+
+var cssEngine;
+
+/**
+ * End-of-line code.
+ */
+
+var eol = os.platform
+ ? ('win32' == os.platform() ? '\r\n' : '\n')
+ : '\n';
+
+/**
+ * Template engine to utilize.
+ */
+
+var templateEngine = 'jade';
+
+/**
+ * Usage documentation.
+ */
+
+var usage = ''
+ + '\n'
+ + ' Usage: express [options] [path]\n'
+ + '\n'
+ + ' Options:\n'
+ + ' -s, --sessions add session support\n'
+ + ' -t, --template <engine> add template <engine> support (jade|ejs). default=jade\n'
+ + ' -c, --css <engine> add stylesheet <engine> support (stylus). default=plain css\n'
+ + ' -v, --version output framework version\n'
+ + ' -h, --help output help information\n'
+ ;
+
+/**
+ * Routes index template.
+ */
+
+var index = [
+ ''
+ , '/*'
+ , ' * GET home page.'
+ , ' */'
+ , ''
+ , 'exports.index = function(req, res){'
+ , ' res.render(\'index\', { title: \'Express\' })'
+ , '};'
+].join(eol);
+
+/**
+ * Jade layout template.
+ */
+
+var jadeLayout = [
+ '!!!'
+ , 'html'
+ , ' head'
+ , ' title= title'
+ , ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')'
+ , ' body!= body'
+].join(eol);
+
+/**
+ * Jade index template.
+ */
+
+var jadeIndex = [
+ 'h1= title'
+ , 'p Welcome to #{title}'
+].join(eol);
+
+/**
+ * EJS layout template.
+ */
+
+var ejsLayout = [
+ '<!DOCTYPE html>'
+ , '<html>'
+ , ' <head>'
+ , ' <title><%= title %></title>'
+ , ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
+ , ' </head>'
+ , ' <body>'
+ , ' <%- body %>'
+ , ' </body>'
+ , '</html>'
+].join(eol);
+
+/**
+ * EJS index template.
+ */
+
+var ejsIndex = [
+ '<h1><%= title %></h1>'
+ , '<p>Welcome to <%= title %></p>'
+ ].join(eol);
+
+/**
+ * Default css template.
+ */
+
+var css = [
+ 'body {'
+ , ' padding: 50px;'
+ , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
+ , '}'
+ , ''
+ , 'a {'
+ , ' color: #00B7FF;'
+ , '}'
+].join(eol);
+
+/**
+ * Default stylus template.
+ */
+
+var stylus = [
+ 'body'
+ , ' padding: 50px'
+ , ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif'
+ , 'a'
+ , ' color: #00B7FF'
+].join(eol);
+
+/**
+ * App template.
+ */
+
+var app = [
+ ''
+ , '/**'
+ , ' * Module dependencies.'
+ , ' */'
+ , ''
+ , 'var express = require(\'express\')'
+ , ' , routes = require(\'./routes\');'
+ , ''
+ , 'var app = module.exports = express.createServer();'
+ , ''
+ , '// Configuration'
+ , ''
+ , 'app.configure(function(){'
+ , ' app.set(\'views\', __dirname + \'/views\');'
+ , ' app.set(\'view engine\', \':TEMPLATE\');'
+ , ' app.use(express.bodyParser());'
+ , ' app.use(express.methodOverride());{sess}{css}'
+ , ' app.use(app.router);'
+ , ' app.use(express.static(__dirname + \'/public\'));'
+ , '});'
+ , ''
+ , 'app.configure(\'development\', function(){'
+ , ' app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));'
+ , '});'
+ , ''
+ , 'app.configure(\'production\', function(){'
+ , ' app.use(express.errorHandler());'
+ , '});'
+ , ''
+ , '// Routes'
+ , ''
+ , 'app.get(\'/\', routes.index);'
+ , ''
+ , 'app.listen(3000);'
+ , 'console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);'
+ , ''
+].join(eol);
+
+// Parse arguments
+
+var args = process.argv.slice(2)
+ , path = '.';
+
+while (args.length) {
+ var arg = args.shift();
+ switch (arg) {
+ case '-h':
+ case '--help':
+ abort(usage);
+ break;
+ case '-v':
+ case '--version':
+ abort(version);
+ break;
+ case '-s':
+ case '--session':
+ case '--sessions':
+ sessions = true;
+ break;
+ case '-c':
+ case '--css':
+ args.length
+ ? (cssEngine = args.shift())
+ : abort('--css requires an argument');
+ break;
+ case '-t':
+ case '--template':
+ args.length
+ ? (templateEngine = args.shift())
+ : abort('--template requires an argument');
+ break;
+ default:
+ path = arg;
+ }
+}
+
+// Generate application
+
+(function createApplication(path) {
+ emptyDirectory(path, function(empty){
+ if (empty) {
+ createApplicationAt(path);
+ } else {
+ confirm('destination is not empty, continue? ', function(ok){
+ if (ok) {
+ process.stdin.destroy();
+ createApplicationAt(path);
+ } else {
+ abort('aborting');
+ }
+ });
+ }
+ });
+})(path);
+
+/**
+ * Create application at the given directory `path`.
+ *
+ * @param {String} path
+ */
+
+function createApplicationAt(path) {
+ console.log();
+ process.on('exit', function(){
+ console.log();
+ console.log(' dont forget to install dependencies:');
+ console.log(' $ cd %s && npm install', path);
+ console.log();
+ });
+
+ mkdir(path, function(){
+ mkdir(path + '/public');
+ mkdir(path + '/public/javascripts');
+ mkdir(path + '/public/images');
+ mkdir(path + '/public/stylesheets', function(){
+ switch (cssEngine) {
+ case 'stylus':
+ write(path + '/public/stylesheets/style.styl', stylus);
+ break;
+ default:
+ write(path + '/public/stylesheets/style.css', css);
+ }
+ });
+
+ mkdir(path + '/routes', function(){
+ write(path + '/routes/index.js', index);
+ });
+
+ mkdir(path + '/views', function(){
+ switch (templateEngine) {
+ case 'ejs':
+ write(path + '/views/layout.ejs', ejsLayout);
+ write(path + '/views/index.ejs', ejsIndex);
+ break;
+ case 'jade':
+ write(path + '/views/layout.jade', jadeLayout);
+ write(path + '/views/index.jade', jadeIndex);
+ break;
+ }
+ });
+
+ // CSS Engine support
+ switch (cssEngine) {
+ case 'stylus':
+ app = app.replace('{css}', eol + ' app.use(require(\'stylus\').middleware({ src: __dirname + \'/public\' }));');
+ break;
+ default:
+ app = app.replace('{css}', '');
+ }
+
+ // Session support
+ app = app.replace('{sess}', sessions
+ ? eol + ' app.use(express.cookieParser());' + eol + ' app.use(express.session({ secret: \'your secret here\' }));'
+ : '');
+
+ // Template support
+ app = app.replace(':TEMPLATE', templateEngine);
+
+ // package.json
+ var json = '{' + eol;
+ json += ' "name": "application-name"' + eol;
+ json += ' , "version": "0.0.1"' + eol;
+ json += ' , "private": true' + eol;
+ json += ' , "dependencies": {' + eol;
+ json += ' "express": "' + version + '"' + eol;
+ if (cssEngine) json += ' , "' + cssEngine + '": ">= 0.0.1"' + eol;
+ if (templateEngine) json += ' , "' + templateEngine + '": ">= 0.0.1"' + eol;
+ json += ' }' + eol;
+ json += '}';
+
+
+ write(path + '/package.json', json);
+ write(path + '/app.js', app);
+ });
+}
+
+/**
+ * Check if the given directory `path` is empty.
+ *
+ * @param {String} path
+ * @param {Function} fn
+ */
+
+function emptyDirectory(path, fn) {
+ fs.readdir(path, function(err, files){
+ if (err && 'ENOENT' != err.code) throw err;
+ fn(!files || !files.length);
+ });
+}
+
+/**
+ * echo str > path.
+ *
+ * @param {String} path
+ * @param {String} str
+ */
+
+function write(path, str) {
+ fs.writeFile(path, str);
+ console.log(' \x1b[36mcreate\x1b[0m : ' + path);
+}
+
+/**
+ * Prompt confirmation with the given `msg`.
+ *
+ * @param {String} msg
+ * @param {Function} fn
+ */
+
+function confirm(msg, fn) {
+ prompt(msg, function(val){
+ fn(/^ *y(es)?/i.test(val));
+ });
+}
+
+/**
+ * Prompt input with the given `msg` and callback `fn`.
+ *
+ * @param {String} msg
+ * @param {Function} fn
+ */
+
+function prompt(msg, fn) {
+ // prompt
+ if (' ' == msg[msg.length - 1]) {
+ process.stdout.write(msg);
+ } else {
+ console.log(msg);
+ }
+
+ // stdin
+ process.stdin.setEncoding('ascii');
+ process.stdin.once('data', function(data){
+ fn(data);
+ }).resume();
+}
+
+/**
+ * Mkdir -p.
+ *
+ * @param {String} path
+ * @param {Function} fn
+ */
+
+function mkdir(path, fn) {
+ mkdirp(path, 0755, function(err){
+ if (err) throw err;
+ console.log(' \033[36mcreate\033[0m : ' + path);
+ fn && fn();
+ });
+}
+
+/**
+ * Exit with the given `str`.
+ *
+ * @param {String} str
+ */
+
+function abort(str) {
+ console.error(str);
+ process.exit(1);
+}
diff --git a/node_modules/express/index.js b/node_modules/express/index.js
new file mode 100644
index 0000000..8d81ea7
--- /dev/null
+++ b/node_modules/express/index.js
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/express'); \ No newline at end of file
diff --git a/node_modules/express/lib/express.js b/node_modules/express/lib/express.js
new file mode 100644
index 0000000..0a0d5ad
--- /dev/null
+++ b/node_modules/express/lib/express.js
@@ -0,0 +1,79 @@
+
+/*!
+ * Express
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var connect = require('connect')
+ , HTTPSServer = require('./https')
+ , HTTPServer = require('./http')
+ , Route = require('./router/route')
+
+/**
+ * Re-export connect auto-loaders.
+ *
+ * This prevents the need to `require('connect')` in order
+ * to access core middleware, so for example `express.logger()` instead
+ * of `require('connect').logger()`.
+ */
+
+var exports = module.exports = connect.middleware;
+
+/**
+ * Framework version.
+ */
+
+exports.version = '2.5.8';
+
+/**
+ * Shortcut for `new Server(...)`.
+ *
+ * @param {Function} ...
+ * @return {Server}
+ * @api public
+ */
+
+exports.createServer = function(options){
+ if ('object' == typeof options) {
+ return new HTTPSServer(options, Array.prototype.slice.call(arguments, 1));
+ } else {
+ return new HTTPServer(Array.prototype.slice.call(arguments));
+ }
+};
+
+/**
+ * Expose constructors.
+ */
+
+exports.HTTPServer = HTTPServer;
+exports.HTTPSServer = HTTPSServer;
+exports.Route = Route;
+
+/**
+ * View extensions.
+ */
+
+exports.View =
+exports.view = require('./view');
+
+/**
+ * Response extensions.
+ */
+
+require('./response');
+
+/**
+ * Request extensions.
+ */
+
+require('./request');
+
+// Error handler title
+
+exports.errorHandler.title = 'Express';
+
diff --git a/node_modules/express/lib/http.js b/node_modules/express/lib/http.js
new file mode 100644
index 0000000..da2158f
--- /dev/null
+++ b/node_modules/express/lib/http.js
@@ -0,0 +1,582 @@
+/*!
+ * Express - HTTPServer
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('qs')
+ , connect = require('connect')
+ , router = require('./router')
+ , Router = require('./router')
+ , view = require('./view')
+ , toArray = require('./utils').toArray
+ , methods = router.methods.concat('del', 'all')
+ , url = require('url')
+ , utils = connect.utils;
+
+/**
+ * Expose `HTTPServer`.
+ */
+
+exports = module.exports = HTTPServer;
+
+/**
+ * Server proto.
+ */
+
+var app = HTTPServer.prototype;
+
+/**
+ * Initialize a new `HTTPServer` with optional `middleware`.
+ *
+ * @param {Array} middleware
+ * @api public
+ */
+
+function HTTPServer(middleware){
+ connect.HTTPServer.call(this, []);
+ this.init(middleware);
+};
+
+/**
+ * Inherit from `connect.HTTPServer`.
+ */
+
+app.__proto__ = connect.HTTPServer.prototype;
+
+/**
+ * Initialize the server.
+ *
+ * @param {Array} middleware
+ * @api private
+ */
+
+app.init = function(middleware){
+ var self = this;
+ this.cache = {};
+ this.settings = {};
+ this.redirects = {};
+ this.isCallbacks = {};
+ this._locals = {};
+ this.dynamicViewHelpers = {};
+ this.errorHandlers = [];
+
+ this.set('env', process.env.NODE_ENV || 'development');
+
+ // expose objects to each other
+ this.use(function(req, res, next){
+ req.query = req.query || {};
+ res.setHeader('X-Powered-By', 'Express');
+ req.app = res.app = self;
+ req.res = res;
+ res.req = req;
+ req.next = next;
+ // assign req.query
+ if (req.url.indexOf('?') > 0) {
+ var query = url.parse(req.url).query;
+ req.query = qs.parse(query);
+ }
+ next();
+ });
+
+ // apply middleware
+ if (middleware) middleware.forEach(self.use.bind(self));
+
+ // router
+ this.routes = new Router(this);
+ this.__defineGetter__('router', function(){
+ this.__usedRouter = true;
+ return self.routes.middleware;
+ });
+
+ // default locals
+ this.locals({
+ settings: this.settings
+ , app: this
+ });
+
+ // default development configuration
+ this.configure('development', function(){
+ this.enable('hints');
+ });
+
+ // default production configuration
+ this.configure('production', function(){
+ this.enable('view cache');
+ });
+
+ // register error handlers on "listening"
+ // so that they disregard definition position.
+ this.on('listening', this.registerErrorHandlers.bind(this));
+
+ // route manipulation methods
+ methods.forEach(function(method){
+ self.lookup[method] = function(path){
+ return self.routes.lookup(method, path);
+ };
+
+ self.match[method] = function(path){
+ return self.routes.match(method, path);
+ };
+
+ self.remove[method] = function(path){
+ return self.routes.lookup(method, path).remove();
+ };
+ });
+
+ // del -> delete
+ self.lookup.del = self.lookup.delete;
+ self.match.del = self.match.delete;
+ self.remove.del = self.remove.delete;
+};
+
+/**
+ * Remove routes matching the given `path`.
+ *
+ * @param {Route} path
+ * @return {Boolean}
+ * @api public
+ */
+
+app.remove = function(path){
+ return this.routes.lookup('all', path).remove();
+};
+
+/**
+ * Lookup routes defined with a path
+ * equivalent to `path`.
+ *
+ * @param {Stirng} path
+ * @return {Array}
+ * @api public
+ */
+
+app.lookup = function(path){
+ return this.routes.lookup('all', path);
+};
+
+/**
+ * Lookup routes matching the given `url`.
+ *
+ * @param {Stirng} url
+ * @return {Array}
+ * @api public
+ */
+
+app.match = function(url){
+ return this.routes.match('all', url);
+};
+
+/**
+ * When using the vhost() middleware register error handlers.
+ */
+
+app.onvhost = function(){
+ this.registerErrorHandlers();
+};
+
+/**
+ * Register error handlers.
+ *
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.registerErrorHandlers = function(){
+ this.errorHandlers.forEach(function(fn){
+ this.use(function(err, req, res, next){
+ fn.apply(this, arguments);
+ });
+ }, this);
+ return this;
+};
+
+/**
+ * Proxy `connect.HTTPServer#use()` to apply settings to
+ * mounted applications.
+ *
+ * @param {String|Function|Server} route
+ * @param {Function|Server} middleware
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.use = function(route, middleware){
+ var app, base, handle;
+
+ if ('string' != typeof route) {
+ middleware = route, route = '/';
+ }
+
+ // express app
+ if (middleware.handle && middleware.set) app = middleware;
+
+ // restore .app property on req and res
+ if (app) {
+ app.route = route;
+ middleware = function(req, res, next) {
+ var orig = req.app;
+ app.handle(req, res, function(err){
+ req.app = res.app = orig;
+ next(err);
+ });
+ };
+ }
+
+ connect.HTTPServer.prototype.use.call(this, route, middleware);
+
+ // mounted an app, invoke the hook
+ // and adjust some settings
+ if (app) {
+ base = this.set('basepath') || this.route;
+ if ('/' == base) base = '';
+ base = base + (app.set('basepath') || app.route);
+ app.set('basepath', base);
+ app.parent = this;
+ if (app.__mounted) app.__mounted.call(app, this);
+ }
+
+ return this;
+};
+
+/**
+ * Assign a callback `fn` which is called
+ * when this `Server` is passed to `Server#use()`.
+ *
+ * Examples:
+ *
+ * var app = express.createServer()
+ * , blog = express.createServer();
+ *
+ * blog.mounted(function(parent){
+ * // parent is app
+ * // "this" is blog
+ * });
+ *
+ * app.use(blog);
+ *
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.mounted = function(fn){
+ this.__mounted = fn;
+ return this;
+};
+
+/**
+ * See: view.register.
+ *
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.register = function(){
+ view.register.apply(this, arguments);
+ return this;
+};
+
+/**
+ * Register the given view helpers `obj`. This method
+ * can be called several times to apply additional helpers.
+ *
+ * @param {Object} obj
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.helpers =
+app.locals = function(obj){
+ utils.merge(this._locals, obj);
+ return this;
+};
+
+/**
+ * Register the given dynamic view helpers `obj`. This method
+ * can be called several times to apply additional helpers.
+ *
+ * @param {Object} obj
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.dynamicHelpers = function(obj){
+ utils.merge(this.dynamicViewHelpers, obj);
+ return this;
+};
+
+/**
+ * Map the given param placeholder `name`(s) to the given callback(s).
+ *
+ * Param mapping is used to provide pre-conditions to routes
+ * which us normalized placeholders. This callback has the same
+ * signature as regular middleware, for example below when ":userId"
+ * is used this function will be invoked in an attempt to load the user.
+ *
+ * app.param('userId', function(req, res, next, id){
+ * User.find(id, function(err, user){
+ * if (err) {
+ * next(err);
+ * } else if (user) {
+ * req.user = user;
+ * next();
+ * } else {
+ * next(new Error('failed to load user'));
+ * }
+ * });
+ * });
+ *
+ * Passing a single function allows you to map logic
+ * to the values passed to `app.param()`, for example
+ * this is useful to provide coercion support in a concise manner.
+ *
+ * The following example maps regular expressions to param values
+ * ensuring that they match, otherwise passing control to the next
+ * route:
+ *
+ * app.param(function(name, regexp){
+ * if (regexp instanceof RegExp) {
+ * return function(req, res, next, val){
+ * var captures;
+ * if (captures = regexp.exec(String(val))) {
+ * req.params[name] = captures;
+ * next();
+ * } else {
+ * next('route');
+ * }
+ * }
+ * }
+ * });
+ *
+ * We can now use it as shown below, where "/commit/:commit" expects
+ * that the value for ":commit" is at 5 or more digits. The capture
+ * groups are then available as `req.params.commit` as we defined
+ * in the function above.
+ *
+ * app.param('commit', /^\d{5,}$/);
+ *
+ * For more of this useful functionality take a look
+ * at [express-params](http://github.com/visionmedia/express-params).
+ *
+ * @param {String|Array|Function} name
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.param = function(name, fn){
+ var self = this
+ , fns = [].slice.call(arguments, 1);
+
+ // array
+ if (Array.isArray(name)) {
+ name.forEach(function(name){
+ fns.forEach(function(fn){
+ self.param(name, fn);
+ });
+ });
+ // param logic
+ } else if ('function' == typeof name) {
+ this.routes.param(name);
+ // single
+ } else {
+ if (':' == name[0]) name = name.substr(1);
+ fns.forEach(function(fn){
+ self.routes.param(name, fn);
+ });
+ }
+
+ return this;
+};
+
+/**
+ * Assign a custom exception handler callback `fn`.
+ * These handlers are always _last_ in the middleware stack.
+ *
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.error = function(fn){
+ this.errorHandlers.push(fn);
+ return this;
+};
+
+/**
+ * Register the given callback `fn` for the given `type`.
+ *
+ * @param {String} type
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.is = function(type, fn){
+ if (!fn) return this.isCallbacks[type];
+ this.isCallbacks[type] = fn;
+ return this;
+};
+
+/**
+ * Assign `setting` to `val`, or return `setting`'s value.
+ * Mounted servers inherit their parent server's settings.
+ *
+ * @param {String} setting
+ * @param {String} val
+ * @return {Server|Mixed} for chaining, or the setting value
+ * @api public
+ */
+
+app.set = function(setting, val){
+ if (val === undefined) {
+ if (this.settings.hasOwnProperty(setting)) {
+ return this.settings[setting];
+ } else if (this.parent) {
+ return this.parent.set(setting);
+ }
+ } else {
+ this.settings[setting] = val;
+ return this;
+ }
+};
+
+/**
+ * Check if `setting` is enabled.
+ *
+ * @param {String} setting
+ * @return {Boolean}
+ * @api public
+ */
+
+app.enabled = function(setting){
+ return !!this.set(setting);
+};
+
+/**
+ * Check if `setting` is disabled.
+ *
+ * @param {String} setting
+ * @return {Boolean}
+ * @api public
+ */
+
+app.disabled = function(setting){
+ return !this.set(setting);
+};
+
+/**
+ * Enable `setting`.
+ *
+ * @param {String} setting
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.enable = function(setting){
+ return this.set(setting, true);
+};
+
+/**
+ * Disable `setting`.
+ *
+ * @param {String} setting
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.disable = function(setting){
+ return this.set(setting, false);
+};
+
+/**
+ * Redirect `key` to `url`.
+ *
+ * @param {String} key
+ * @param {String} url
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.redirect = function(key, url){
+ this.redirects[key] = url;
+ return this;
+};
+
+/**
+ * Configure callback for zero or more envs,
+ * when no env is specified that callback will
+ * be invoked for all environments. Any combination
+ * can be used multiple times, in any order desired.
+ *
+ * Examples:
+ *
+ * app.configure(function(){
+ * // executed for all envs
+ * });
+ *
+ * app.configure('stage', function(){
+ * // executed staging env
+ * });
+ *
+ * app.configure('stage', 'production', function(){
+ * // executed for stage and production
+ * });
+ *
+ * @param {String} env...
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.configure = function(env, fn){
+ var envs = 'all'
+ , args = toArray(arguments);
+ fn = args.pop();
+ if (args.length) envs = args;
+ if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this);
+ return this;
+};
+
+/**
+ * Delegate `.VERB(...)` calls to `.route(VERB, ...)`.
+ */
+
+methods.forEach(function(method){
+ app[method] = function(path){
+ if (1 == arguments.length) return this.routes.lookup(method, path);
+ var args = [method].concat(toArray(arguments));
+ if (!this.__usedRouter) this.use(this.router);
+ return this.routes._route.apply(this.routes, args);
+ }
+});
+
+/**
+ * Special-cased "all" method, applying the given route `path`,
+ * middleware, and callback to _every_ HTTP method.
+ *
+ * @param {String} path
+ * @param {Function} ...
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.all = function(path){
+ var args = arguments;
+ if (1 == args.length) return this.routes.lookup('all', path);
+ methods.forEach(function(method){
+ if ('all' == method || 'del' == method) return;
+ app[method].apply(this, args);
+ }, this);
+ return this;
+};
+
+// del -> delete alias
+
+app.del = app.delete;
+
diff --git a/node_modules/express/lib/https.js b/node_modules/express/lib/https.js
new file mode 100644
index 0000000..8a8c008
--- /dev/null
+++ b/node_modules/express/lib/https.js
@@ -0,0 +1,52 @@
+
+/*!
+ * Express - HTTPSServer
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var connect = require('connect')
+ , HTTPServer = require('./http')
+ , https = require('https');
+
+/**
+ * Expose `HTTPSServer`.
+ */
+
+exports = module.exports = HTTPSServer;
+
+/**
+ * Server proto.
+ */
+
+var app = HTTPSServer.prototype;
+
+/**
+ * Initialize a new `HTTPSServer` with the
+ * given `options`, and optional `middleware`.
+ *
+ * @param {Object} options
+ * @param {Array} middleware
+ * @api public
+ */
+
+function HTTPSServer(options, middleware){
+ connect.HTTPSServer.call(this, options, []);
+ this.init(middleware);
+};
+
+/**
+ * Inherit from `connect.HTTPSServer`.
+ */
+
+app.__proto__ = connect.HTTPSServer.prototype;
+
+// mixin HTTPServer methods
+
+Object.keys(HTTPServer.prototype).forEach(function(method){
+ app[method] = HTTPServer.prototype[method];
+});
diff --git a/node_modules/express/lib/request.js b/node_modules/express/lib/request.js
new file mode 100644
index 0000000..1d5ab40
--- /dev/null
+++ b/node_modules/express/lib/request.js
@@ -0,0 +1,323 @@
+
+/*!
+ * Express - request
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+ , req = http.IncomingMessage.prototype
+ , utils = require('./utils')
+ , parse = require('url').parse
+ , mime = require('mime');
+
+/**
+ * Default flash formatters.
+ *
+ * @type Object
+ */
+
+var flashFormatters = exports.flashFormatters = {
+ s: function(val){
+ return String(val);
+ }
+};
+
+/**
+ * Return request header or optional default.
+ *
+ * The `Referrer` header field is special-cased,
+ * both `Referrer` and `Referer` will yield are
+ * interchangeable.
+ *
+ * Examples:
+ *
+ * req.header('Content-Type');
+ * // => "text/plain"
+ *
+ * req.header('content-type');
+ * // => "text/plain"
+ *
+ * req.header('Accept');
+ * // => undefined
+ *
+ * req.header('Accept', 'text/html');
+ * // => "text/html"
+ *
+ * @param {String} name
+ * @param {String} defaultValue
+ * @return {String}
+ * @api public
+ */
+
+req.header = function(name, defaultValue){
+ switch (name = name.toLowerCase()) {
+ case 'referer':
+ case 'referrer':
+ return this.headers.referrer
+ || this.headers.referer
+ || defaultValue;
+ default:
+ return this.headers[name] || defaultValue;
+ }
+};
+
+/**
+ * Get `field`'s `param` value, defaulting to ''.
+ *
+ * Examples:
+ *
+ * req.get('content-disposition', 'filename');
+ * // => "something.png"
+ *
+ * @param {String} field
+ * @param {String} param
+ * @return {String}
+ * @api public
+ */
+
+req.get = function(field, param){
+ var val = this.header(field);
+ if (!val) return '';
+ var regexp = new RegExp(param + ' *= *(?:"([^"]+)"|([^;]+))', 'i');
+ if (!regexp.exec(val)) return '';
+ return RegExp.$1 || RegExp.$2;
+};
+
+/**
+ * Short-hand for `require('url').parse(req.url).pathname`.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('path', function(){
+ return parse(this.url).pathname;
+});
+
+/**
+ * Check if the _Accept_ header is present, and includes the given `type`.
+ *
+ * When the _Accept_ header is not present `true` is returned. Otherwise
+ * the given `type` is matched by an exact match, and then subtypes. You
+ * may pass the subtype such as "html" which is then converted internally
+ * to "text/html" using the mime lookup table.
+ *
+ * Examples:
+ *
+ * // Accept: text/html
+ * req.accepts('html');
+ * // => true
+ *
+ * // Accept: text/*; application/json
+ * req.accepts('html');
+ * req.accepts('text/html');
+ * req.accepts('text/plain');
+ * req.accepts('application/json');
+ * // => true
+ *
+ * req.accepts('image/png');
+ * req.accepts('png');
+ * // => false
+ *
+ * @param {String} type
+ * @return {Boolean}
+ * @api public
+ */
+
+req.accepts = function(type){
+ var accept = this.header('Accept');
+
+ // normalize extensions ".json" -> "json"
+ if (type && '.' == type[0]) type = type.substr(1);
+
+ // when Accept does not exist, or is '*/*' return true
+ if (!accept || '*/*' == accept) {
+ return true;
+ } else if (type) {
+ // allow "html" vs "text/html" etc
+ if (!~type.indexOf('/')) type = mime.lookup(type);
+
+ // check if we have a direct match
+ if (~accept.indexOf(type)) return true;
+
+ // check if we have type/*
+ type = type.split('/')[0] + '/*';
+ return !!~accept.indexOf(type);
+ } else {
+ return false;
+ }
+};
+
+/**
+ * Return the value of param `name` when present or `defaultValue`.
+ *
+ * - Checks route placeholders, ex: _/user/:id_
+ * - Checks query string params, ex: ?id=12
+ * - Checks urlencoded body params, ex: id=12
+ *
+ * To utilize urlencoded request bodies, `req.body`
+ * should be an object. This can be done by using
+ * the `connect.bodyParser` middleware.
+ *
+ * @param {String} name
+ * @param {Mixed} defaultValue
+ * @return {String}
+ * @api public
+ */
+
+req.param = function(name, defaultValue){
+ // route params like /user/:id
+ if (this.params && this.params.hasOwnProperty(name) && undefined !== this.params[name]) {
+ return this.params[name];
+ }
+ // query string params
+ if (undefined !== this.query[name]) {
+ return this.query[name];
+ }
+ // request body params via connect.bodyParser
+ if (this.body && undefined !== this.body[name]) {
+ return this.body[name];
+ }
+ return defaultValue;
+};
+
+/**
+ * Queue flash `msg` of the given `type`.
+ *
+ * Examples:
+ *
+ * req.flash('info', 'email sent');
+ * req.flash('error', 'email delivery failed');
+ * req.flash('info', 'email re-sent');
+ * // => 2
+ *
+ * req.flash('info');
+ * // => ['email sent', 'email re-sent']
+ *
+ * req.flash('info');
+ * // => []
+ *
+ * req.flash();
+ * // => { error: ['email delivery failed'], info: [] }
+ *
+ * Formatting:
+ *
+ * Flash notifications also support arbitrary formatting support.
+ * For example you may pass variable arguments to `req.flash()`
+ * and use the %s specifier to be replaced by the associated argument:
+ *
+ * req.flash('info', 'email has been sent to %s.', userName);
+ *
+ * To add custom formatters use the `exports.flashFormatters` object.
+ *
+ * @param {String} type
+ * @param {String} msg
+ * @return {Array|Object|Number}
+ * @api public
+ */
+
+req.flash = function(type, msg){
+ if (this.session === undefined) throw Error('req.flash() requires sessions');
+ var msgs = this.session.flash = this.session.flash || {};
+ if (type && msg) {
+ var i = 2
+ , args = arguments
+ , formatters = this.app.flashFormatters || {};
+ formatters.__proto__ = flashFormatters;
+ msg = utils.miniMarkdown(msg);
+ msg = msg.replace(/%([a-zA-Z])/g, function(_, format){
+ var formatter = formatters[format];
+ if (formatter) return formatter(utils.escape(args[i++]));
+ });
+ return (msgs[type] = msgs[type] || []).push(msg);
+ } else if (type) {
+ var arr = msgs[type];
+ delete msgs[type];
+ return arr || [];
+ } else {
+ this.session.flash = {};
+ return msgs;
+ }
+};
+
+/**
+ * Check if the incoming request contains the "Content-Type"
+ * header field, and it contains the give mime `type`.
+ *
+ * Examples:
+ *
+ * // With Content-Type: text/html; charset=utf-8
+ * req.is('html');
+ * req.is('text/html');
+ * // => true
+ *
+ * // When Content-Type is application/json
+ * req.is('json');
+ * req.is('application/json');
+ * // => true
+ *
+ * req.is('html');
+ * // => false
+ *
+ * Ad-hoc callbacks can also be registered with Express, to perform
+ * assertions again the request, for example if we need an expressive
+ * way to check if our incoming request is an image, we can register "an image"
+ * callback:
+ *
+ * app.is('an image', function(req){
+ * return 0 == req.headers['content-type'].indexOf('image');
+ * });
+ *
+ * Now within our route callbacks, we can use to to assert content types
+ * such as "image/jpeg", "image/png", etc.
+ *
+ * app.post('/image/upload', function(req, res, next){
+ * if (req.is('an image')) {
+ * // do something
+ * } else {
+ * next();
+ * }
+ * });
+ *
+ * @param {String} type
+ * @return {Boolean}
+ * @api public
+ */
+
+req.is = function(type){
+ var fn = this.app.is(type);
+ if (fn) return fn(this);
+ var ct = this.headers['content-type'];
+ if (!ct) return false;
+ ct = ct.split(';')[0];
+ if (!~type.indexOf('/')) type = mime.lookup(type);
+ if (~type.indexOf('*')) {
+ type = type.split('/');
+ ct = ct.split('/');
+ if ('*' == type[0] && type[1] == ct[1]) return true;
+ if ('*' == type[1] && type[0] == ct[0]) return true;
+ return false;
+ }
+ return !! ~ct.indexOf(type);
+};
+
+// Callback for isXMLHttpRequest / xhr
+
+function isxhr() {
+ return this.header('X-Requested-With', '').toLowerCase() === 'xmlhttprequest';
+}
+
+/**
+ * Check if the request was an _XMLHttpRequest_.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('isXMLHttpRequest', isxhr);
+req.__defineGetter__('xhr', isxhr);
diff --git a/node_modules/express/lib/response.js b/node_modules/express/lib/response.js
new file mode 100644
index 0000000..a671771
--- /dev/null
+++ b/node_modules/express/lib/response.js
@@ -0,0 +1,460 @@
+
+/*!
+ * Express - response
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+ , http = require('http')
+ , path = require('path')
+ , connect = require('connect')
+ , utils = connect.utils
+ , parseRange = require('./utils').parseRange
+ , res = http.ServerResponse.prototype
+ , send = connect.static.send
+ , mime = require('mime')
+ , basename = path.basename
+ , join = path.join;
+
+/**
+ * Send a response with the given `body` and optional `headers` and `status` code.
+ *
+ * Examples:
+ *
+ * res.send();
+ * res.send(new Buffer('wahoo'));
+ * res.send({ some: 'json' });
+ * res.send('<p>some html</p>');
+ * res.send('Sorry, cant find that', 404);
+ * res.send('text', { 'Content-Type': 'text/plain' }, 201);
+ * res.send(404);
+ *
+ * @param {String|Object|Number|Buffer} body or status
+ * @param {Object|Number} headers or status
+ * @param {Number} status
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.send = function(body, headers, status){
+ // allow status as second arg
+ if ('number' == typeof headers) {
+ status = headers,
+ headers = null;
+ }
+
+ // default status
+ status = status || this.statusCode;
+
+ // allow 0 args as 204
+ if (!arguments.length || undefined === body) status = 204;
+
+ // determine content type
+ switch (typeof body) {
+ case 'number':
+ if (!this.header('Content-Type')) {
+ this.contentType('.txt');
+ }
+ body = http.STATUS_CODES[status = body];
+ break;
+ case 'string':
+ if (!this.header('Content-Type')) {
+ this.charset = this.charset || 'utf-8';
+ this.contentType('.html');
+ }
+ break;
+ case 'boolean':
+ case 'object':
+ if (Buffer.isBuffer(body)) {
+ if (!this.header('Content-Type')) {
+ this.contentType('.bin');
+ }
+ } else {
+ return this.json(body, headers, status);
+ }
+ break;
+ }
+
+ // populate Content-Length
+ if (undefined !== body && !this.header('Content-Length')) {
+ this.header('Content-Length', Buffer.isBuffer(body)
+ ? body.length
+ : Buffer.byteLength(body));
+ }
+
+ // merge headers passed
+ if (headers) {
+ var fields = Object.keys(headers);
+ for (var i = 0, len = fields.length; i < len; ++i) {
+ var field = fields[i];
+ this.header(field, headers[field]);
+ }
+ }
+
+ // strip irrelevant headers
+ if (204 == status || 304 == status) {
+ this.removeHeader('Content-Type');
+ this.removeHeader('Content-Length');
+ body = '';
+ }
+
+ // respond
+ this.statusCode = status;
+ this.end('HEAD' == this.req.method ? null : body);
+ return this;
+};
+
+/**
+ * Send JSON response with `obj`, optional `headers`, and optional `status`.
+ *
+ * Examples:
+ *
+ * res.json(null);
+ * res.json({ user: 'tj' });
+ * res.json('oh noes!', 500);
+ * res.json('I dont have that', 404);
+ *
+ * @param {Mixed} obj
+ * @param {Object|Number} headers or status
+ * @param {Number} status
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.json = function(obj, headers, status){
+ var body = JSON.stringify(obj)
+ , callback = this.req.query.callback
+ , jsonp = this.app.enabled('jsonp callback');
+
+ this.charset = this.charset || 'utf-8';
+ this.header('Content-Type', 'application/json');
+
+ if (callback && jsonp) {
+ this.header('Content-Type', 'text/javascript');
+ body = callback.replace(/[^\w$.]/g, '') + '(' + body + ');';
+ }
+
+ return this.send(body, headers, status);
+};
+
+/**
+ * Set status `code`.
+ *
+ * @param {Number} code
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.status = function(code){
+ this.statusCode = code;
+ return this;
+};
+
+/**
+ * Transfer the file at the given `path`. Automatically sets
+ * the _Content-Type_ response header field. `next()` is called
+ * when `path` is a directory, or when an error occurs.
+ *
+ * Options:
+ *
+ * - `maxAge` defaulting to 0
+ * - `root` root directory for relative filenames
+ *
+ * @param {String} path
+ * @param {Object|Function} options or fn
+ * @param {Function} fn
+ * @api public
+ */
+
+res.sendfile = function(path, options, fn){
+ var next = this.req.next;
+ options = options || {};
+
+ // support function as second arg
+ if ('function' == typeof options) {
+ fn = options;
+ options = {};
+ }
+
+ options.path = encodeURIComponent(path);
+ options.callback = fn;
+ send(this.req, this, next, options);
+};
+
+/**
+ * Set _Content-Type_ response header passed through `mime.lookup()`.
+ *
+ * Examples:
+ *
+ * var filename = 'path/to/image.png';
+ * res.contentType(filename);
+ * // res.headers['Content-Type'] is now "image/png"
+ *
+ * res.contentType('.html');
+ * res.contentType('html');
+ * res.contentType('json');
+ * res.contentType('png');
+ *
+ * @param {String} type
+ * @return {String} the resolved mime type
+ * @api public
+ */
+
+res.contentType = function(type){
+ return this.header('Content-Type', mime.lookup(type));
+};
+
+/**
+ * Set _Content-Disposition_ header to _attachment_ with optional `filename`.
+ *
+ * @param {String} filename
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.attachment = function(filename){
+ if (filename) this.contentType(filename);
+ this.header('Content-Disposition', filename
+ ? 'attachment; filename="' + basename(filename) + '"'
+ : 'attachment');
+ return this;
+};
+
+/**
+ * Transfer the file at the given `path`, with optional
+ * `filename` as an attachment and optional callback `fn(err)`,
+ * and optional `fn2(err)` which is invoked when an error has
+ * occurred after header has been sent.
+ *
+ * @param {String} path
+ * @param {String|Function} filename or fn
+ * @param {Function} fn
+ * @param {Function} fn2
+ * @api public
+ */
+
+res.download = function(path, filename, fn, fn2){
+ var self = this;
+
+ // support callback as second arg
+ if ('function' == typeof filename) {
+ fn2 = fn;
+ fn = filename;
+ filename = null;
+ }
+
+ // transfer the file
+ this.attachment(filename || path).sendfile(path, function(err){
+ var sentHeader = self._header;
+ if (err) {
+ if (!sentHeader) self.removeHeader('Content-Disposition');
+ if (sentHeader) {
+ fn2 && fn2(err);
+ } else if (fn) {
+ fn(err);
+ } else {
+ self.req.next(err);
+ }
+ } else if (fn) {
+ fn();
+ }
+ });
+};
+
+/**
+ * Set or get response header `name` with optional `val`.
+ *
+ * @param {String} name
+ * @param {String} val
+ * @return {ServerResponse} for chaining
+ * @api public
+ */
+
+res.header = function(name, val){
+ if (1 == arguments.length) return this.getHeader(name);
+ this.setHeader(name, val);
+ return this;
+};
+
+/**
+ * Clear cookie `name`.
+ *
+ * @param {String} name
+ * @param {Object} options
+ * @api public
+ */
+
+res.clearCookie = function(name, options){
+ var opts = { expires: new Date(1) };
+ this.cookie(name, '', options
+ ? utils.merge(options, opts)
+ : opts);
+};
+
+/**
+ * Set cookie `name` to `val`, with the given `options`.
+ *
+ * Options:
+ *
+ * - `maxAge` max-age in milliseconds, converted to `expires`
+ * - `path` defaults to the "basepath" setting which is typically "/"
+ *
+ * Examples:
+ *
+ * // "Remember Me" for 15 minutes
+ * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
+ *
+ * // save as above
+ * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
+ *
+ * @param {String} name
+ * @param {String} val
+ * @param {Options} options
+ * @api public
+ */
+
+res.cookie = function(name, val, options){
+ options = options || {};
+ if ('maxAge' in options) options.expires = new Date(Date.now() + options.maxAge);
+ if (undefined === options.path) options.path = this.app.set('basepath');
+ var cookie = utils.serializeCookie(name, val, options);
+ this.header('Set-Cookie', cookie);
+};
+
+/**
+ * Redirect to the given `url` with optional response `status`
+ * defauling to 302.
+ *
+ * The given `url` can also be the name of a mapped url, for
+ * example by default express supports "back" which redirects
+ * to the _Referrer_ or _Referer_ headers or the application's
+ * "basepath" setting. Express also supports "basepath" out of the box,
+ * which can be set via `app.set('basepath', '/blog');`, and defaults
+ * to '/'.
+ *
+ * Redirect Mapping:
+ *
+ * To extend the redirect mapping capabilities that Express provides,
+ * we may use the `app.redirect()` method:
+ *
+ * app.redirect('google', 'http://google.com');
+ *
+ * Now in a route we may call:
+ *
+ * res.redirect('google');
+ *
+ * We may also map dynamic redirects:
+ *
+ * app.redirect('comments', function(req, res){
+ * return '/post/' + req.params.id + '/comments';
+ * });
+ *
+ * So now we may do the following, and the redirect will dynamically adjust to
+ * the context of the request. If we called this route with _GET /post/12_ our
+ * redirect _Location_ would be _/post/12/comments_.
+ *
+ * app.get('/post/:id', function(req, res){
+ * res.redirect('comments');
+ * });
+ *
+ * Unless an absolute `url` is given, the app's mount-point
+ * will be respected. For example if we redirect to `/posts`,
+ * and our app is mounted at `/blog` we will redirect to `/blog/posts`.
+ *
+ * @param {String} url
+ * @param {Number} code
+ * @api public
+ */
+
+res.redirect = function(url, status){
+ var app = this.app
+ , req = this.req
+ , base = app.set('basepath') || app.route
+ , status = status || 302
+ , head = 'HEAD' == req.method
+ , body;
+
+ // Setup redirect map
+ var map = {
+ back: req.header('Referrer', base)
+ , home: base
+ };
+
+ // Support custom redirect map
+ map.__proto__ = app.redirects;
+
+ // Attempt mapped redirect
+ var mapped = 'function' == typeof map[url]
+ ? map[url](req, this)
+ : map[url];
+
+ // Perform redirect
+ url = mapped || url;
+
+ // Relative
+ if (!~url.indexOf('://')) {
+ // Respect mount-point
+ if ('/' != base && 0 != url.indexOf(base)) url = base + url;
+
+ // Absolute
+ var host = req.headers.host
+ , tls = req.connection.encrypted;
+ url = 'http' + (tls ? 's' : '') + '://' + host + url;
+ }
+
+ // Support text/{plain,html} by default
+ if (req.accepts('html')) {
+ body = '<p>' + http.STATUS_CODES[status] + '. Redirecting to <a href="' + url + '">' + url + '</a></p>';
+ this.header('Content-Type', 'text/html');
+ } else {
+ body = http.STATUS_CODES[status] + '. Redirecting to ' + url;
+ this.header('Content-Type', 'text/plain');
+ }
+
+ // Respond
+ this.statusCode = status;
+ this.header('Location', url);
+ this.end(head ? null : body);
+};
+
+/**
+ * Assign the view local variable `name` to `val` or return the
+ * local previously assigned to `name`.
+ *
+ * @param {String} name
+ * @param {Mixed} val
+ * @return {Mixed} val
+ * @api public
+ */
+
+res.local = function(name, val){
+ this._locals = this._locals || {};
+ return undefined === val
+ ? this._locals[name]
+ : this._locals[name] = val;
+};
+
+/**
+ * Assign several locals with the given `obj`,
+ * or return the locals.
+ *
+ * @param {Object} obj
+ * @return {Object|Undefined}
+ * @api public
+ */
+
+res.locals =
+res.helpers = function(obj){
+ if (obj) {
+ for (var key in obj) {
+ this.local(key, obj[key]);
+ }
+ } else {
+ return this._locals;
+ }
+};
diff --git a/node_modules/express/lib/router/collection.js b/node_modules/express/lib/router/collection.js
new file mode 100644
index 0000000..991a9a2
--- /dev/null
+++ b/node_modules/express/lib/router/collection.js
@@ -0,0 +1,53 @@
+
+/*!
+ * Express - router - Collection
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Expose `Collection`.
+ */
+
+module.exports = Collection;
+
+/**
+ * Initialize a new route `Collection`
+ * with the given `router`.
+ *
+ * @param {Router} router
+ * @api private
+ */
+
+function Collection(router) {
+ Array.apply(this, arguments);
+ this.router = router;
+}
+
+/**
+ * Inherit from `Array.prototype`.
+ */
+
+Collection.prototype.__proto__ = Array.prototype;
+
+/**
+ * Remove the routes in this collection.
+ *
+ * @return {Collection} of routes removed
+ * @api public
+ */
+
+Collection.prototype.remove = function(){
+ var router = this.router
+ , len = this.length
+ , ret = new Collection(this.router);
+
+ for (var i = 0; i < len; ++i) {
+ if (router.remove(this[i])) {
+ ret.push(this[i]);
+ }
+ }
+
+ return ret;
+};
+
diff --git a/node_modules/express/lib/router/index.js b/node_modules/express/lib/router/index.js
new file mode 100644
index 0000000..ff1498b
--- /dev/null
+++ b/node_modules/express/lib/router/index.js
@@ -0,0 +1,398 @@
+
+/*!
+ * Express - Router
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Route = require('./route')
+ , Collection = require('./collection')
+ , utils = require('../utils')
+ , parse = require('url').parse
+ , toArray = utils.toArray;
+
+/**
+ * Expose `Router` constructor.
+ */
+
+exports = module.exports = Router;
+
+/**
+ * Expose HTTP methods.
+ */
+
+var methods = exports.methods = require('./methods');
+
+/**
+ * Initialize a new `Router` with the given `app`.
+ *
+ * @param {express.HTTPServer} app
+ * @api private
+ */
+
+function Router(app) {
+ var self = this;
+ this.app = app;
+ this.routes = {};
+ this.params = {};
+ this._params = [];
+
+ this.middleware = function(req, res, next){
+ self._dispatch(req, res, next);
+ };
+}
+
+/**
+ * Register a param callback `fn` for the given `name`.
+ *
+ * @param {String|Function} name
+ * @param {Function} fn
+ * @return {Router} for chaining
+ * @api public
+ */
+
+Router.prototype.param = function(name, fn){
+ // param logic
+ if ('function' == typeof name) {
+ this._params.push(name);
+ return;
+ }
+
+ // apply param functions
+ var params = this._params
+ , len = params.length
+ , ret;
+
+ for (var i = 0; i < len; ++i) {
+ if (ret = params[i](name, fn)) {
+ fn = ret;
+ }
+ }
+
+ // ensure we end up with a
+ // middleware function
+ if ('function' != typeof fn) {
+ throw new Error('invalid param() call for ' + name + ', got ' + fn);
+ }
+
+ (this.params[name] = this.params[name] || []).push(fn);
+ return this;
+};
+
+/**
+ * Return a `Collection` of all routes defined.
+ *
+ * @return {Collection}
+ * @api public
+ */
+
+Router.prototype.all = function(){
+ return this.find(function(){
+ return true;
+ });
+};
+
+/**
+ * Remove the given `route`, returns
+ * a bool indicating if the route was present
+ * or not.
+ *
+ * @param {Route} route
+ * @return {Boolean}
+ * @api public
+ */
+
+Router.prototype.remove = function(route){
+ var routes = this.routes[route.method]
+ , len = routes.length;
+
+ for (var i = 0; i < len; ++i) {
+ if (route == routes[i]) {
+ routes.splice(i, 1);
+ return true;
+ }
+ }
+};
+
+/**
+ * Return routes with route paths matching `path`.
+ *
+ * @param {String} method
+ * @param {String} path
+ * @return {Collection}
+ * @api public
+ */
+
+Router.prototype.lookup = function(method, path){
+ return this.find(function(route){
+ return path == route.path
+ && (route.method == method
+ || method == 'all');
+ });
+};
+
+/**
+ * Return routes with regexps that match the given `url`.
+ *
+ * @param {String} method
+ * @param {String} url
+ * @return {Collection}
+ * @api public
+ */
+
+Router.prototype.match = function(method, url){
+ return this.find(function(route){
+ return route.match(url)
+ && (route.method == method
+ || method == 'all');
+ });
+};
+
+/**
+ * Find routes based on the return value of `fn`
+ * which is invoked once per route.
+ *
+ * @param {Function} fn
+ * @return {Collection}
+ * @api public
+ */
+
+Router.prototype.find = function(fn){
+ var len = methods.length
+ , ret = new Collection(this)
+ , method
+ , routes
+ , route;
+
+ for (var i = 0; i < len; ++i) {
+ method = methods[i];
+ routes = this.routes[method];
+ if (!routes) continue;
+ for (var j = 0, jlen = routes.length; j < jlen; ++j) {
+ route = routes[j];
+ if (fn(route)) ret.push(route);
+ }
+ }
+
+ return ret;
+};
+
+/**
+ * Route dispatcher aka the route "middleware".
+ *
+ * @param {IncomingMessage} req
+ * @param {ServerResponse} res
+ * @param {Function} next
+ * @api private
+ */
+
+Router.prototype._dispatch = function(req, res, next){
+ var params = this.params
+ , self = this;
+
+ // route dispatch
+ (function pass(i, err){
+ var paramCallbacks
+ , paramIndex = 0
+ , paramVal
+ , route
+ , keys
+ , key
+ , ret;
+
+ // match next route
+ function nextRoute(err) {
+ pass(req._route_index + 1, err);
+ }
+
+ // match route
+ req.route = route = self._match(req, i);
+
+ // implied OPTIONS
+ if (!route && 'OPTIONS' == req.method) return self._options(req, res);
+
+ // no route
+ if (!route) return next(err);
+
+ // we have a route
+ // start at param 0
+ req.params = route.params;
+ keys = route.keys;
+ i = 0;
+
+ // param callbacks
+ function param(err) {
+ paramIndex = 0;
+ key = keys[i++];
+ paramVal = key && req.params[key.name];
+ paramCallbacks = key && params[key.name];
+
+ try {
+ if ('route' == err) {
+ nextRoute();
+ } else if (err) {
+ i = 0;
+ callbacks(err);
+ } else if (paramCallbacks && undefined !== paramVal) {
+ paramCallback();
+ } else if (key) {
+ param();
+ } else {
+ i = 0;
+ callbacks();
+ }
+ } catch (err) {
+ param(err);
+ }
+ };
+
+ param(err);
+
+ // single param callbacks
+ function paramCallback(err) {
+ var fn = paramCallbacks[paramIndex++];
+ if (err || !fn) return param(err);
+ fn(req, res, paramCallback, paramVal, key.name);
+ }
+
+ // invoke route callbacks
+ function callbacks(err) {
+ var fn = route.callbacks[i++];
+ try {
+ if ('route' == err) {
+ nextRoute();
+ } else if (err && fn) {
+ if (fn.length < 4) return callbacks(err);
+ fn(err, req, res, callbacks);
+ } else if (fn) {
+ fn(req, res, callbacks);
+ } else {
+ nextRoute(err);
+ }
+ } catch (err) {
+ callbacks(err);
+ }
+ }
+ })(0);
+};
+
+/**
+ * Respond to __OPTIONS__ method.
+ *
+ * @param {IncomingMessage} req
+ * @param {ServerResponse} res
+ * @api private
+ */
+
+Router.prototype._options = function(req, res){
+ var path = parse(req.url).pathname
+ , body = this._optionsFor(path).join(',');
+ res.send(body, { Allow: body });
+};
+
+/**
+ * Return an array of HTTP verbs or "options" for `path`.
+ *
+ * @param {String} path
+ * @return {Array}
+ * @api private
+ */
+
+Router.prototype._optionsFor = function(path){
+ var self = this;
+ return methods.filter(function(method){
+ var routes = self.routes[method];
+ if (!routes || 'options' == method) return;
+ for (var i = 0, len = routes.length; i < len; ++i) {
+ if (routes[i].match(path)) return true;
+ }
+ }).map(function(method){
+ return method.toUpperCase();
+ });
+};
+
+/**
+ * Attempt to match a route for `req`
+ * starting from offset `i`.
+ *
+ * @param {IncomingMessage} req
+ * @param {Number} i
+ * @return {Route}
+ * @api private
+ */
+
+Router.prototype._match = function(req, i){
+ var method = req.method.toLowerCase()
+ , url = parse(req.url)
+ , path = url.pathname
+ , routes = this.routes
+ , captures
+ , route
+ , keys;
+
+ // pass HEAD to GET routes
+ if ('head' == method) method = 'get';
+
+ // routes for this method
+ if (routes = routes[method]) {
+
+ // matching routes
+ for (var len = routes.length; i < len; ++i) {
+ route = routes[i];
+ if (captures = route.match(path)) {
+ keys = route.keys;
+ route.params = [];
+
+ // params from capture groups
+ for (var j = 1, jlen = captures.length; j < jlen; ++j) {
+ var key = keys[j-1]
+ , val = 'string' == typeof captures[j]
+ ? decodeURIComponent(captures[j])
+ : captures[j];
+ if (key) {
+ route.params[key.name] = val;
+ } else {
+ route.params.push(val);
+ }
+ }
+
+ // all done
+ req._route_index = i;
+ return route;
+ }
+ }
+ }
+};
+
+/**
+ * Route `method`, `path`, and one or more callbacks.
+ *
+ * @param {String} method
+ * @param {String} path
+ * @param {Function} callback...
+ * @return {Router} for chaining
+ * @api private
+ */
+
+Router.prototype._route = function(method, path, callbacks){
+ var app = this.app
+ , callbacks = utils.flatten(toArray(arguments, 2));
+
+ // ensure path was given
+ if (!path) throw new Error('app.' + method + '() requires a path');
+
+ // create the route
+ var route = new Route(method, path, callbacks, {
+ sensitive: app.enabled('case sensitive routes')
+ , strict: app.enabled('strict routing')
+ });
+
+ // add it
+ (this.routes[method] = this.routes[method] || [])
+ .push(route);
+ return this;
+};
diff --git a/node_modules/express/lib/router/methods.js b/node_modules/express/lib/router/methods.js
new file mode 100644
index 0000000..e19787b
--- /dev/null
+++ b/node_modules/express/lib/router/methods.js
@@ -0,0 +1,70 @@
+
+/*!
+ * Express - router - methods
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Hypertext Transfer Protocol -- HTTP/1.1
+ * http://www.ietf.org/rfc/rfc2616.txt
+ */
+
+var RFC2616 = ['OPTIONS', 'GET', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT'];
+
+/**
+ * HTTP Extensions for Distributed Authoring -- WEBDAV
+ * http://www.ietf.org/rfc/rfc2518.txt
+ */
+
+var RFC2518 = ['PROPFIND', 'PROPPATCH', 'MKCOL', 'COPY', 'MOVE', 'LOCK', 'UNLOCK'];
+
+/**
+ * Versioning Extensions to WebDAV
+ * http://www.ietf.org/rfc/rfc3253.txt
+ */
+
+var RFC3253 = ['VERSION-CONTROL', 'REPORT', 'CHECKOUT', 'CHECKIN', 'UNCHECKOUT', 'MKWORKSPACE', 'UPDATE', 'LABEL', 'MERGE', 'BASELINE-CONTROL', 'MKACTIVITY'];
+
+/**
+ * Ordered Collections Protocol (WebDAV)
+ * http://www.ietf.org/rfc/rfc3648.txt
+ */
+
+var RFC3648 = ['ORDERPATCH'];
+
+/**
+ * Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol
+ * http://www.ietf.org/rfc/rfc3744.txt
+ */
+
+var RFC3744 = ['ACL'];
+
+/**
+ * Web Distributed Authoring and Versioning (WebDAV) SEARCH
+ * http://www.ietf.org/rfc/rfc5323.txt
+ */
+
+var RFC5323 = ['SEARCH'];
+
+/**
+ * PATCH Method for HTTP
+ * http://www.ietf.org/rfc/rfc5789.txt
+ */
+
+var RFC5789 = ['PATCH'];
+
+/**
+ * Expose the methods.
+ */
+
+module.exports = [].concat(
+ RFC2616
+ , RFC2518
+ , RFC3253
+ , RFC3648
+ , RFC3744
+ , RFC5323
+ , RFC5789).map(function(method){
+ return method.toLowerCase();
+ });
diff --git a/node_modules/express/lib/router/route.js b/node_modules/express/lib/router/route.js
new file mode 100644
index 0000000..7f2965c
--- /dev/null
+++ b/node_modules/express/lib/router/route.js
@@ -0,0 +1,88 @@
+
+/*!
+ * Express - router - Route
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Expose `Route`.
+ */
+
+module.exports = Route;
+
+/**
+ * Initialize `Route` with the given HTTP `method`, `path`,
+ * and an array of `callbacks` and `options`.
+ *
+ * Options:
+ *
+ * - `sensitive` enable case-sensitive routes
+ * - `strict` enable strict matching for trailing slashes
+ *
+ * @param {String} method
+ * @param {String} path
+ * @param {Array} callbacks
+ * @param {Object} options.
+ * @api private
+ */
+
+function Route(method, path, callbacks, options) {
+ options = options || {};
+ this.path = path;
+ this.method = method;
+ this.callbacks = callbacks;
+ this.regexp = normalize(path
+ , this.keys = []
+ , options.sensitive
+ , options.strict);
+}
+
+/**
+ * Check if this route matches `path` and return captures made.
+ *
+ * @param {String} path
+ * @return {Array}
+ * @api private
+ */
+
+Route.prototype.match = function(path){
+ return this.regexp.exec(path);
+};
+
+/**
+ * Normalize the given path string,
+ * returning a regular expression.
+ *
+ * An empty array should be passed,
+ * which will contain the placeholder
+ * key names. For example "/user/:id" will
+ * then contain ["id"].
+ *
+ * @param {String|RegExp} path
+ * @param {Array} keys
+ * @param {Boolean} sensitive
+ * @param {Boolean} strict
+ * @return {RegExp}
+ * @api private
+ */
+
+function normalize(path, keys, sensitive, strict) {
+ if (path instanceof RegExp) return path;
+ path = path
+ .concat(strict ? '' : '/?')
+ .replace(/\/\(/g, '(?:/')
+ .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional){
+ keys.push({ name: key, optional: !! optional });
+ slash = slash || '';
+ return ''
+ + (optional ? '' : slash)
+ + '(?:'
+ + (optional ? slash : '')
+ + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')'
+ + (optional || '');
+ })
+ .replace(/([\/.])/g, '\\$1')
+ .replace(/\*/g, '(.*)');
+ return new RegExp('^' + path + '$', sensitive ? '' : 'i');
+}
diff --git a/node_modules/express/lib/utils.js b/node_modules/express/lib/utils.js
new file mode 100644
index 0000000..d579f7c
--- /dev/null
+++ b/node_modules/express/lib/utils.js
@@ -0,0 +1,152 @@
+
+/*!
+ * Express - Utils
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Check if `path` looks absolute.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.isAbsolute = function(path){
+ if ('/' == path[0]) return true;
+ if (':' == path[1] && '\\' == path[2]) return true;
+};
+
+/**
+ * Merge object `b` with `a` giving precedence to
+ * values in object `a`.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Object} a
+ * @api private
+ */
+
+exports.union = function(a, b){
+ if (a && b) {
+ var keys = Object.keys(b)
+ , len = keys.length
+ , key;
+ for (var i = 0; i < len; ++i) {
+ key = keys[i];
+ if (!a.hasOwnProperty(key)) {
+ a[key] = b[key];
+ }
+ }
+ }
+ return a;
+};
+
+/**
+ * Flatten the given `arr`.
+ *
+ * @param {Array} arr
+ * @return {Array}
+ * @api private
+ */
+
+exports.flatten = function(arr, ret){
+ var ret = ret || []
+ , len = arr.length;
+ for (var i = 0; i < len; ++i) {
+ if (Array.isArray(arr[i])) {
+ exports.flatten(arr[i], ret);
+ } else {
+ ret.push(arr[i]);
+ }
+ }
+ return ret;
+};
+
+/**
+ * Parse mini markdown implementation.
+ * The following conversions are supported,
+ * primarily for the "flash" middleware:
+ *
+ * _foo_ or *foo* become <em>foo</em>
+ * __foo__ or **foo** become <strong>foo</strong>
+ * [A](B) becomes <a href="B">A</a>
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.miniMarkdown = function(str){
+ return String(str)
+ .replace(/(__|\*\*)(.*?)\1/g, '<strong>$2</strong>')
+ .replace(/(_|\*)(.*?)\1/g, '<em>$2</em>')
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
+};
+
+/**
+ * Escape special characters in the given string of html.
+ *
+ * @param {String} html
+ * @return {String}
+ * @api private
+ */
+
+exports.escape = function(html) {
+ return String(html)
+ .replace(/&/g, '&amp;')
+ .replace(/"/g, '&quot;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;');
+};
+
+/**
+ * Parse "Range" header `str` relative to the given file `size`.
+ *
+ * @param {Number} size
+ * @param {String} str
+ * @return {Array}
+ * @api private
+ */
+
+exports.parseRange = function(size, str){
+ var valid = true;
+ var arr = str.substr(6).split(',').map(function(range){
+ var range = range.split('-')
+ , start = parseInt(range[0], 10)
+ , end = parseInt(range[1], 10);
+
+ // -500
+ if (isNaN(start)) {
+ start = size - end;
+ end = size - 1;
+ // 500-
+ } else if (isNaN(end)) {
+ end = size - 1;
+ }
+
+ // Invalid
+ if (isNaN(start) || isNaN(end) || start > end) valid = false;
+
+ return { start: start, end: end };
+ });
+ return valid ? arr : undefined;
+};
+
+/**
+ * Fast alternative to `Array.prototype.slice.call()`.
+ *
+ * @param {Arguments} args
+ * @param {Number} n
+ * @return {Array}
+ * @api public
+ */
+
+exports.toArray = function(args, i){
+ var arr = []
+ , len = args.length
+ , i = i || 0;
+ for (; i < len; ++i) arr.push(args[i]);
+ return arr;
+};
diff --git a/node_modules/express/lib/view.js b/node_modules/express/lib/view.js
new file mode 100644
index 0000000..5258249
--- /dev/null
+++ b/node_modules/express/lib/view.js
@@ -0,0 +1,460 @@
+
+/*!
+ * Express - view
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var path = require('path')
+ , extname = path.extname
+ , dirname = path.dirname
+ , basename = path.basename
+ , utils = require('connect').utils
+ , View = require('./view/view')
+ , partial = require('./view/partial')
+ , union = require('./utils').union
+ , merge = utils.merge
+ , http = require('http')
+ , res = http.ServerResponse.prototype;
+
+/**
+ * Expose constructors.
+ */
+
+exports = module.exports = View;
+
+/**
+ * Export template engine registrar.
+ */
+
+exports.register = View.register;
+
+/**
+ * Lookup and compile `view` with cache support by supplying
+ * both the `cache` object and `cid` string,
+ * followed by `options` passed to `exports.lookup()`.
+ *
+ * @param {String} view
+ * @param {Object} cache
+ * @param {Object} cid
+ * @param {Object} options
+ * @return {View}
+ * @api private
+ */
+
+exports.compile = function(view, cache, cid, options){
+ if (cache && cid && cache[cid]){
+ options.filename = cache[cid].path;
+ return cache[cid];
+ }
+
+ // lookup
+ view = exports.lookup(view, options);
+
+ // hints
+ if (!view.exists) {
+ if (options.hint) hintAtViewPaths(view.original, options);
+ var err = new Error('failed to locate view "' + view.original.view + '"');
+ err.view = view.original;
+ throw err;
+ }
+
+ // compile
+ options.filename = view.path;
+ view.fn = view.templateEngine.compile(view.contents, options);
+ cache[cid] = view;
+
+ return view;
+};
+
+/**
+ * Lookup `view`, returning an instanceof `View`.
+ *
+ * Options:
+ *
+ * - `root` root directory path
+ * - `defaultEngine` default template engine
+ * - `parentView` parent `View` object
+ * - `cache` cache object
+ * - `cacheid` optional cache id
+ *
+ * Lookup:
+ *
+ * - partial `_<name>`
+ * - any `<name>/index`
+ * - non-layout `../<name>/index`
+ * - any `<root>/<name>`
+ * - partial `<root>/_<name>`
+ *
+ * @param {String} view
+ * @param {Object} options
+ * @return {View}
+ * @api private
+ */
+
+exports.lookup = function(view, options){
+ var orig = view = new View(view, options)
+ , partial = options.isPartial
+ , layout = options.isLayout;
+
+ // Try _ prefix ex: ./views/_<name>.jade
+ // taking precedence over the direct path
+ if (partial) {
+ view = new View(orig.prefixPath, options);
+ if (!view.exists) view = orig;
+ }
+
+ // Try index ex: ./views/user/index.jade
+ if (!layout && !view.exists) view = new View(orig.indexPath, options);
+
+ // Try ../<name>/index ex: ../user/index.jade
+ // when calling partial('user') within the same dir
+ if (!layout && !view.exists) view = new View(orig.upIndexPath, options);
+
+ // Try root ex: <root>/user.jade
+ if (!view.exists) view = new View(orig.rootPath, options);
+
+ // Try root _ prefix ex: <root>/_user.jade
+ if (!view.exists && partial) view = new View(view.prefixPath, options);
+
+ view.original = orig;
+ return view;
+};
+
+/**
+ * Partial render helper.
+ *
+ * @api private
+ */
+
+function renderPartial(res, view, options, parentLocals, parent){
+ var collection, object, locals;
+
+ if (options) {
+ // collection
+ if (options.collection) {
+ collection = options.collection;
+ delete options.collection;
+ } else if ('length' in options) {
+ collection = options;
+ options = {};
+ }
+
+ // locals
+ if (options.locals) {
+ locals = options.locals;
+ delete options.locals;
+ }
+
+ // object
+ if ('Object' != options.constructor.name) {
+ object = options;
+ options = {};
+ } else if (undefined != options.object) {
+ object = options.object;
+ delete options.object;
+ }
+ } else {
+ options = {};
+ }
+
+ // Inherit locals from parent
+ union(options, parentLocals);
+
+ // Merge locals
+ if (locals) merge(options, locals);
+
+ // Partials dont need layouts
+ options.isPartial = true;
+ options.layout = false;
+
+ // Deduce name from view path
+ var name = options.as || partial.resolveObjectName(view);
+
+ // Render partial
+ function render(){
+ if (object) {
+ if ('string' == typeof name) {
+ options[name] = object;
+ } else if (name === global) {
+ merge(options, object);
+ }
+ }
+ return res.render(view, options, null, parent, true);
+ }
+
+ // Collection support
+ if (collection) {
+ var len = collection.length
+ , buf = ''
+ , keys
+ , key
+ , val;
+
+ options.collectionLength = len;
+
+ if ('number' == typeof len || Array.isArray(collection)) {
+ for (var i = 0; i < len; ++i) {
+ val = collection[i];
+ options.firstInCollection = i == 0;
+ options.indexInCollection = i;
+ options.lastInCollection = i == len - 1;
+ object = val;
+ buf += render();
+ }
+ } else {
+ keys = Object.keys(collection);
+ len = keys.length;
+ options.collectionLength = len;
+ options.collectionKeys = keys;
+ for (var i = 0; i < len; ++i) {
+ key = keys[i];
+ val = collection[key];
+ options.keyInCollection = key;
+ options.firstInCollection = i == 0;
+ options.indexInCollection = i;
+ options.lastInCollection = i == len - 1;
+ object = val;
+ buf += render();
+ }
+ }
+
+ return buf;
+ } else {
+ return render();
+ }
+};
+
+/**
+ * Render `view` partial with the given `options`. Optionally a
+ * callback `fn(err, str)` may be passed instead of writing to
+ * the socket.
+ *
+ * Options:
+ *
+ * - `object` Single object with name derived from the view (unless `as` is present)
+ *
+ * - `as` Variable name for each `collection` value, defaults to the view name.
+ * * as: 'something' will add the `something` local variable
+ * * as: this will use the collection value as the template context
+ * * as: global will merge the collection value's properties with `locals`
+ *
+ * - `collection` Array of objects, the name is derived from the view name itself.
+ * For example _video.html_ will have a object _video_ available to it.
+ *
+ * @param {String} view
+ * @param {Object|Array|Function} options, collection, callback, or object
+ * @param {Function} fn
+ * @return {String}
+ * @api public
+ */
+
+res.partial = function(view, options, fn){
+ var app = this.app
+ , options = options || {}
+ , viewEngine = app.set('view engine')
+ , parent = {};
+
+ // accept callback as second argument
+ if ('function' == typeof options) {
+ fn = options;
+ options = {};
+ }
+
+ // root "views" option
+ parent.dirname = app.set('views') || process.cwd() + '/views';
+
+ // utilize "view engine" option
+ if (viewEngine) parent.engine = viewEngine;
+
+ // render the partial
+ try {
+ var str = renderPartial(this, view, options, null, parent);
+ } catch (err) {
+ if (fn) {
+ fn(err);
+ } else {
+ this.req.next(err);
+ }
+ return;
+ }
+
+ // callback or transfer
+ if (fn) {
+ fn(null, str);
+ } else {
+ this.send(str);
+ }
+};
+
+/**
+ * Render `view` with the given `options` and optional callback `fn`.
+ * When a callback function is given a response will _not_ be made
+ * automatically, however otherwise a response of _200_ and _text/html_ is given.
+ *
+ * Options:
+ *
+ * - `scope` Template evaluation context (the value of `this`)
+ * - `debug` Output debugging information
+ * - `status` Response status code
+ *
+ * @param {String} view
+ * @param {Object|Function} options or callback function
+ * @param {Function} fn
+ * @api public
+ */
+
+res.render = function(view, opts, fn, parent, sub){
+ // support callback function as second arg
+ if ('function' == typeof opts) {
+ fn = opts, opts = null;
+ }
+
+ try {
+ return this._render(view, opts, fn, parent, sub);
+ } catch (err) {
+ // callback given
+ if (fn) {
+ fn(err);
+ // unwind to root call to prevent multiple callbacks
+ } else if (sub) {
+ throw err;
+ // root template, next(err)
+ } else {
+ this.req.next(err);
+ }
+ }
+};
+
+// private render()
+
+res._render = function(view, opts, fn, parent, sub){
+ var options = {}
+ , self = this
+ , app = this.app
+ , helpers = app._locals
+ , dynamicHelpers = app.dynamicViewHelpers
+ , viewOptions = app.set('view options')
+ , root = app.set('views') || process.cwd() + '/views';
+
+ // cache id
+ var cid = app.enabled('view cache')
+ ? view + (parent ? ':' + parent.path : '')
+ : false;
+
+ // merge "view options"
+ if (viewOptions) merge(options, viewOptions);
+
+ // merge res._locals
+ if (this._locals) merge(options, this._locals);
+
+ // merge render() options
+ if (opts) merge(options, opts);
+
+ // merge render() .locals
+ if (opts && opts.locals) merge(options, opts.locals);
+
+ // status support
+ if (options.status) this.statusCode = options.status;
+
+ // capture attempts
+ options.attempts = [];
+
+ var partial = options.isPartial
+ , layout = options.layout;
+
+ // Layout support
+ if (true === layout || undefined === layout) {
+ layout = 'layout';
+ }
+
+ // Default execution scope to a plain object
+ options.scope = options.scope || {};
+
+ // Populate view
+ options.parentView = parent;
+
+ // "views" setting
+ options.root = root;
+
+ // "view engine" setting
+ options.defaultEngine = app.set('view engine');
+
+ // charset option
+ if (options.charset) this.charset = options.charset;
+
+ // Dynamic helper support
+ if (false !== options.dynamicHelpers) {
+ // cache
+ if (!this.__dynamicHelpers) {
+ this.__dynamicHelpers = {};
+ for (var key in dynamicHelpers) {
+ this.__dynamicHelpers[key] = dynamicHelpers[key].call(
+ this.app
+ , this.req
+ , this);
+ }
+ }
+
+ // apply
+ merge(options, this.__dynamicHelpers);
+ }
+
+ // Merge view helpers
+ union(options, helpers);
+
+ // Always expose partial() as a local
+ options.partial = function(path, opts){
+ return renderPartial(self, path, opts, options, view);
+ };
+
+ // View lookup
+ options.hint = app.enabled('hints');
+ view = exports.compile(view, app.cache, cid, options);
+
+ // layout helper
+ options.layout = function(path){
+ layout = path;
+ };
+
+ // render
+ var str = view.fn.call(options.scope, options);
+
+ // layout expected
+ if (layout) {
+ options.isLayout = true;
+ options.layout = false;
+ options.body = str;
+ this.render(layout, options, fn, view, true);
+ // partial return
+ } else if (partial) {
+ return str;
+ // render complete, and
+ // callback given
+ } else if (fn) {
+ fn(null, str);
+ // respond
+ } else {
+ this.send(str);
+ }
+}
+
+/**
+ * Hint at view path resolution, outputting the
+ * paths that Express has tried.
+ *
+ * @api private
+ */
+
+function hintAtViewPaths(view, options) {
+ console.error();
+ console.error('failed to locate view "' + view.view + '", tried:');
+ options.attempts.forEach(function(path){
+ console.error(' - %s', path);
+ });
+ console.error();
+}
diff --git a/node_modules/express/lib/view/partial.js b/node_modules/express/lib/view/partial.js
new file mode 100644
index 0000000..7d2f69b
--- /dev/null
+++ b/node_modules/express/lib/view/partial.js
@@ -0,0 +1,40 @@
+
+/*!
+ * Express - view - Partial
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Memory cache.
+ */
+
+var cache = {};
+
+/**
+ * Resolve partial object name from the view path.
+ *
+ * Examples:
+ *
+ * "user.ejs" becomes "user"
+ * "forum thread.ejs" becomes "forumThread"
+ * "forum/thread/post.ejs" becomes "post"
+ * "blog-post.ejs" becomes "blogPost"
+ *
+ * @return {String}
+ * @api private
+ */
+
+exports.resolveObjectName = function(view){
+ return cache[view] || (cache[view] = view
+ .split('/')
+ .slice(-1)[0]
+ .split('.')[0]
+ .replace(/^_/, '')
+ .replace(/[^a-zA-Z0-9 ]+/g, ' ')
+ .split(/ +/).map(function(word, i){
+ return i
+ ? word[0].toUpperCase() + word.substr(1)
+ : word;
+ }).join(''));
+}; \ No newline at end of file
diff --git a/node_modules/express/lib/view/view.js b/node_modules/express/lib/view/view.js
new file mode 100644
index 0000000..7d9392c
--- /dev/null
+++ b/node_modules/express/lib/view/view.js
@@ -0,0 +1,210 @@
+
+/*!
+ * Express - View
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var path = require('path')
+ , utils = require('../utils')
+ , extname = path.extname
+ , dirname = path.dirname
+ , basename = path.basename
+ , fs = require('fs')
+ , stat = fs.statSync;
+
+/**
+ * Expose `View`.
+ */
+
+exports = module.exports = View;
+
+/**
+ * Require cache.
+ */
+
+var cache = {};
+
+/**
+ * Initialize a new `View` with the given `view` path and `options`.
+ *
+ * @param {String} view
+ * @param {Object} options
+ * @api private
+ */
+
+function View(view, options) {
+ options = options || {};
+ this.view = view;
+ this.root = options.root;
+ this.relative = false !== options.relative;
+ this.defaultEngine = options.defaultEngine;
+ this.parent = options.parentView;
+ this.basename = basename(view);
+ this.engine = this.resolveEngine();
+ this.extension = '.' + this.engine;
+ this.name = this.basename.replace(this.extension, '');
+ this.path = this.resolvePath();
+ this.dirname = dirname(this.path);
+ if (options.attempts) {
+ if (!~options.attempts.indexOf(this.path))
+ options.attempts.push(this.path);
+ }
+};
+
+/**
+ * Check if the view path exists.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('exists', function(){
+ try {
+ stat(this.path);
+ return true;
+ } catch (err) {
+ return false;
+ }
+});
+
+/**
+ * Resolve view engine.
+ *
+ * @return {String}
+ * @api private
+ */
+
+View.prototype.resolveEngine = function(){
+ // Explicit
+ if (~this.basename.indexOf('.')) return extname(this.basename).substr(1);
+ // Inherit from parent
+ if (this.parent) return this.parent.engine;
+ // Default
+ return this.defaultEngine;
+};
+
+/**
+ * Resolve view path.
+ *
+ * @return {String}
+ * @api private
+ */
+
+View.prototype.resolvePath = function(){
+ var path = this.view;
+ // Implicit engine
+ if (!~this.basename.indexOf('.')) path += this.extension;
+ // Absolute
+ if (utils.isAbsolute(path)) return path;
+ // Relative to parent
+ if (this.relative && this.parent) return this.parent.dirname + '/' + path;
+ // Relative to root
+ return this.root
+ ? this.root + '/' + path
+ : path;
+};
+
+/**
+ * Get view contents. This is a one-time hit, so we
+ * can afford to be sync.
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('contents', function(){
+ return fs.readFileSync(this.path, 'utf8');
+});
+
+/**
+ * Get template engine api, cache exports to reduce
+ * require() calls.
+ *
+ * @return {Object}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('templateEngine', function(){
+ var ext = this.extension;
+ return cache[ext] || (cache[ext] = require(this.engine));
+});
+
+/**
+ * Return root path alternative.
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('rootPath', function(){
+ this.relative = false;
+ return this.resolvePath();
+});
+
+/**
+ * Return index path alternative.
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('indexPath', function(){
+ return this.dirname
+ + '/' + this.basename.replace(this.extension, '')
+ + '/index' + this.extension;
+});
+
+/**
+ * Return ../<name>/index path alternative.
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('upIndexPath', function(){
+ return this.dirname + '/../' + this.name + '/index' + this.extension;
+});
+
+/**
+ * Return _ prefix path alternative
+ *
+ * @return {String}
+ * @api public
+ */
+
+View.prototype.__defineGetter__('prefixPath', function(){
+ return this.dirname + '/_' + this.basename;
+});
+
+/**
+ * Register the given template engine `exports`
+ * as `ext`. For example we may wish to map ".html"
+ * files to jade:
+ *
+ * app.register('.html', require('jade'));
+ *
+ * or
+ *
+ * app.register('html', require('jade'));
+ *
+ * This is also useful for libraries that may not
+ * match extensions correctly. For example my haml.js
+ * library is installed from npm as "hamljs" so instead
+ * of layout.hamljs, we can register the engine as ".haml":
+ *
+ * app.register('.haml', require('haml-js'));
+ *
+ * @param {String} ext
+ * @param {Object} obj
+ * @api public
+ */
+
+exports.register = function(ext, exports) {
+ if ('.' != ext[0]) ext = '.' + ext;
+ cache[ext] = exports;
+};
diff --git a/node_modules/express/node_modules/connect/.npmignore b/node_modules/express/node_modules/connect/.npmignore
new file mode 100644
index 0000000..b04a224
--- /dev/null
+++ b/node_modules/express/node_modules/connect/.npmignore
@@ -0,0 +1,11 @@
+*.markdown
+*.md
+.git*
+Makefile
+benchmarks/
+docs/
+examples/
+install.sh
+support/
+test/
+.DS_Store
diff --git a/node_modules/express/node_modules/connect/LICENSE b/node_modules/express/node_modules/connect/LICENSE
new file mode 100644
index 0000000..0c5d22d
--- /dev/null
+++ b/node_modules/express/node_modules/connect/LICENSE
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2010 Sencha Inc.
+Copyright (c) 2011 LearnBoost
+Copyright (c) 2011 TJ Holowaychuk
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/index.js b/node_modules/express/node_modules/connect/index.js
new file mode 100644
index 0000000..7477048
--- /dev/null
+++ b/node_modules/express/node_modules/connect/index.js
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/connect'); \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/cache.js b/node_modules/express/node_modules/connect/lib/cache.js
new file mode 100644
index 0000000..4aa026e
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/cache.js
@@ -0,0 +1,81 @@
+
+/*!
+ * Connect - Cache
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Expose `Cache`.
+ */
+
+module.exports = Cache;
+
+/**
+ * LRU cache store.
+ *
+ * @param {Number} limit
+ * @api private
+ */
+
+function Cache(limit) {
+ this.store = {};
+ this.keys = [];
+ this.limit = limit;
+}
+
+/**
+ * Touch `key`, promoting the object.
+ *
+ * @param {String} key
+ * @param {Number} i
+ * @api private
+ */
+
+Cache.prototype.touch = function(key, i){
+ this.keys.splice(i,1);
+ this.keys.push(key);
+};
+
+/**
+ * Remove `key`.
+ *
+ * @param {String} key
+ * @api private
+ */
+
+Cache.prototype.remove = function(key){
+ delete this.store[key];
+};
+
+/**
+ * Get the object stored for `key`.
+ *
+ * @param {String} key
+ * @return {Array}
+ * @api private
+ */
+
+Cache.prototype.get = function(key){
+ return this.store[key];
+};
+
+/**
+ * Add a cache `key`.
+ *
+ * @param {String} key
+ * @return {Array}
+ * @api private
+ */
+
+Cache.prototype.add = function(key){
+ // initialize store
+ var len = this.keys.push(key);
+
+ // limit reached, invalid LRU
+ if (len > this.limit) this.remove(this.keys.shift());
+
+ var arr = this.store[key] = [];
+ arr.createdAt = new Date;
+ return arr;
+};
diff --git a/node_modules/express/node_modules/connect/lib/connect.js b/node_modules/express/node_modules/connect/lib/connect.js
new file mode 100644
index 0000000..630a285
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/connect.js
@@ -0,0 +1,106 @@
+
+/*!
+ * Connect
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var HTTPServer = require('./http').Server
+ , HTTPSServer = require('./https').Server
+ , fs = require('fs');
+
+// node patches
+
+require('./patch');
+
+// expose createServer() as the module
+
+exports = module.exports = createServer;
+
+/**
+ * Framework version.
+ */
+
+exports.version = '1.8.6';
+
+/**
+ * Initialize a new `connect.HTTPServer` with the middleware
+ * passed to this function. When an object is passed _first_,
+ * we assume these are the tls options, and return a `connect.HTTPSServer`.
+ *
+ * Examples:
+ *
+ * An example HTTP server, accepting several middleware.
+ *
+ * var server = connect.createServer(
+ * connect.logger()
+ * , connect.static(__dirname + '/public')
+ * );
+ *
+ * An HTTPS server, utilizing the same middleware as above.
+ *
+ * var server = connect.createServer(
+ * { key: key, cert: cert }
+ * , connect.logger()
+ * , connect.static(__dirname + '/public')
+ * );
+ *
+ * Alternatively with connect 1.0 we may omit `createServer()`.
+ *
+ * connect(
+ * connect.logger()
+ * , connect.static(__dirname + '/public')
+ * ).listen(3000);
+ *
+ * @param {Object|Function} ...
+ * @return {Server}
+ * @api public
+ */
+
+function createServer() {
+ if ('object' == typeof arguments[0]) {
+ return new HTTPSServer(arguments[0], Array.prototype.slice.call(arguments, 1));
+ } else {
+ return new HTTPServer(Array.prototype.slice.call(arguments));
+ }
+};
+
+// support connect.createServer()
+
+exports.createServer = createServer;
+
+// auto-load getters
+
+exports.middleware = {};
+
+/**
+ * Auto-load bundled middleware with getters.
+ */
+
+fs.readdirSync(__dirname + '/middleware').forEach(function(filename){
+ if (/\.js$/.test(filename)) {
+ var name = filename.substr(0, filename.lastIndexOf('.'));
+ exports.middleware.__defineGetter__(name, function(){
+ return require('./middleware/' + name);
+ });
+ }
+});
+
+// expose utils
+
+exports.utils = require('./utils');
+
+// expose getters as first-class exports
+
+exports.utils.merge(exports, exports.middleware);
+
+// expose constructors
+
+exports.HTTPServer = HTTPServer;
+exports.HTTPSServer = HTTPSServer;
+
diff --git a/node_modules/express/node_modules/connect/lib/http.js b/node_modules/express/node_modules/connect/lib/http.js
new file mode 100644
index 0000000..09898e2
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/http.js
@@ -0,0 +1,217 @@
+
+/*!
+ * Connect - HTTPServer
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+ , parse = require('url').parse
+ , assert = require('assert');
+
+// environment
+
+var env = process.env.NODE_ENV || 'development';
+
+/**
+ * Initialize a new `Server` with the given `middleware`.
+ *
+ * Examples:
+ *
+ * var server = connect.createServer(
+ * connect.favicon()
+ * , connect.logger()
+ * , connect.static(__dirname + '/public')
+ * );
+ *
+ * @params {Array} middleware
+ * @return {Server}
+ * @api public
+ */
+
+var Server = exports.Server = function HTTPServer(middleware) {
+ this.stack = [];
+ middleware.forEach(function(fn){
+ this.use(fn);
+ }, this);
+ http.Server.call(this, this.handle);
+};
+
+/**
+ * Inherit from `http.Server.prototype`.
+ */
+
+Server.prototype.__proto__ = http.Server.prototype;
+
+/**
+ * Utilize the given middleware `handle` to the given `route`,
+ * defaulting to _/_. This "route" is the mount-point for the
+ * middleware, when given a value other than _/_ the middleware
+ * is only effective when that segment is present in the request's
+ * pathname.
+ *
+ * For example if we were to mount a function at _/admin_, it would
+ * be invoked on _/admin_, and _/admin/settings_, however it would
+ * not be invoked for _/_, or _/posts_.
+ *
+ * This is effectively the same as passing middleware to `connect.createServer()`,
+ * however provides a progressive api.
+ *
+ * Examples:
+ *
+ * var server = connect.createServer();
+ * server.use(connect.favicon());
+ * server.use(connect.logger());
+ * server.use(connect.static(__dirname + '/public'));
+ *
+ * If we wanted to prefix static files with _/public_, we could
+ * "mount" the `static()` middleware:
+ *
+ * server.use('/public', connect.static(__dirname + '/public'));
+ *
+ * This api is chainable, meaning the following is valid:
+ *
+ * connect.createServer()
+ * .use(connect.favicon())
+ * .use(connect.logger())
+ * .use(connect.static(__dirname + '/public'))
+ * .listen(3000);
+ *
+ * @param {String|Function} route or handle
+ * @param {Function} handle
+ * @return {Server}
+ * @api public
+ */
+
+Server.prototype.use = function(route, handle){
+ this.route = '/';
+
+ // default route to '/'
+ if ('string' != typeof route) {
+ handle = route;
+ route = '/';
+ }
+
+ // wrap sub-apps
+ if ('function' == typeof handle.handle) {
+ var server = handle;
+ server.route = route;
+ handle = function(req, res, next) {
+ server.handle(req, res, next);
+ };
+ }
+
+ // wrap vanilla http.Servers
+ if (handle instanceof http.Server) {
+ handle = handle.listeners('request')[0];
+ }
+
+ // normalize route to not trail with slash
+ if ('/' == route[route.length - 1]) {
+ route = route.substr(0, route.length - 1);
+ }
+
+ // add the middleware
+ this.stack.push({ route: route, handle: handle });
+
+ // allow chaining
+ return this;
+};
+
+/**
+ * Handle server requests, punting them down
+ * the middleware stack.
+ *
+ * @api private
+ */
+
+Server.prototype.handle = function(req, res, out) {
+ var writeHead = res.writeHead
+ , stack = this.stack
+ , removed = ''
+ , index = 0;
+
+ function next(err) {
+ var layer, path, c;
+ req.url = removed + req.url;
+ req.originalUrl = req.originalUrl || req.url;
+ removed = '';
+
+ layer = stack[index++];
+
+ // all done
+ if (!layer || res.headerSent) {
+ // but wait! we have a parent
+ if (out) return out(err);
+
+ // error
+ if (err) {
+ var msg = 'production' == env
+ ? 'Internal Server Error'
+ : err.stack || err.toString();
+
+ // output to stderr in a non-test env
+ if ('test' != env) console.error(err.stack || err.toString());
+
+ // unable to respond
+ if (res.headerSent) return req.socket.destroy();
+
+ res.statusCode = 500;
+ res.setHeader('Content-Type', 'text/plain');
+ if ('HEAD' == req.method) return res.end();
+ res.end(msg);
+ } else {
+ res.statusCode = 404;
+ res.setHeader('Content-Type', 'text/plain');
+ if ('HEAD' == req.method) return res.end();
+ res.end('Cannot ' + req.method + ' ' + req.url);
+ }
+ return;
+ }
+
+ try {
+ path = parse(req.url).pathname;
+ if (undefined == path) path = '/';
+
+ // skip this layer if the route doesn't match.
+ if (0 != path.indexOf(layer.route)) return next(err);
+
+ c = path[layer.route.length];
+ if (c && '/' != c && '.' != c) return next(err);
+
+ // Call the layer handler
+ // Trim off the part of the url that matches the route
+ removed = layer.route;
+ req.url = req.url.substr(removed.length);
+
+ // Ensure leading slash
+ if ('/' != req.url[0]) req.url = '/' + req.url;
+
+ var arity = layer.handle.length;
+ if (err) {
+ if (arity === 4) {
+ layer.handle(err, req, res, next);
+ } else {
+ next(err);
+ }
+ } else if (arity < 4) {
+ layer.handle(req, res, next);
+ } else {
+ next();
+ }
+ } catch (e) {
+ if (e instanceof assert.AssertionError) {
+ console.error(e.stack + '\n');
+ next(e);
+ } else {
+ next(e);
+ }
+ }
+ }
+ next();
+}; \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/https.js b/node_modules/express/node_modules/connect/lib/https.js
new file mode 100644
index 0000000..9b09fa4
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/https.js
@@ -0,0 +1,47 @@
+
+/*!
+ * Connect - HTTPServer
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var HTTPServer = require('./http').Server
+ , https = require('https');
+
+/**
+ * Initialize a new `Server` with the given
+ *`options` and `middleware`. The HTTPS api
+ * is identical to the [HTTP](http.html) server,
+ * however TLS `options` must be provided before
+ * passing in the optional middleware.
+ *
+ * @params {Object} options
+ * @params {Array} middleawre
+ * @return {Server}
+ * @api public
+ */
+
+var Server = exports.Server = function HTTPSServer(options, middleware) {
+ this.stack = [];
+ middleware.forEach(function(fn){
+ this.use(fn);
+ }, this);
+ https.Server.call(this, options, this.handle);
+};
+
+/**
+ * Inherit from `http.Server.prototype`.
+ */
+
+Server.prototype.__proto__ = https.Server.prototype;
+
+// mixin HTTPServer methods
+
+Object.keys(HTTPServer.prototype).forEach(function(method){
+ Server.prototype[method] = HTTPServer.prototype[method];
+}); \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/index.js b/node_modules/express/node_modules/connect/lib/index.js
new file mode 100644
index 0000000..77b14c3
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/index.js
@@ -0,0 +1,46 @@
+
+/**
+ * # Connect
+ *
+ * Connect is a middleware framework for node,
+ * shipping with over 11 bundled middleware and a rich choice of
+ * [3rd-party middleware](https://github.com/senchalabs/connect/wiki).
+ *
+ * Installation:
+ *
+ * $ npm install connect
+ *
+ * API:
+ *
+ * - [connect](connect.html) general
+ * - [http](http.html) http server
+ * - [https](https.html) https server
+ *
+ * Middleware:
+ *
+ * - [logger](middleware-logger.html) request logger with custom format support
+ * - [csrf](middleware-csrf.html) Cross-site request forgery protection
+ * - [basicAuth](middleware-basicAuth.html) basic http authentication
+ * - [bodyParser](middleware-bodyParser.html) extensible request body parser
+ * - [cookieParser](middleware-cookieParser.html) cookie parser
+ * - [session](middleware-session.html) session management support with bundled [MemoryStore](middleware-session-memory.html)
+ * - [compiler](middleware-compiler.html) static asset compiler (sass, less, coffee-script, etc)
+ * - [methodOverride](middleware-methodOverride.html) faux HTTP method support
+ * - [responseTime](middleware-responseTime.html) calculates response-time and exposes via X-Response-Time
+ * - [router](middleware-router.html) provides rich Sinatra / Express-like routing
+ * - [staticCache](middleware-staticCache.html) memory cache layer for the static() middleware
+ * - [static](middleware-static.html) streaming static file server supporting `Range` and more
+ * - [directory](middleware-directory.html) directory listing middleware
+ * - [vhost](middleware-vhost.html) virtual host sub-domain mapping middleware
+ * - [favicon](middleware-favicon.html) efficient favicon server (with default icon)
+ * - [limit](middleware-limit.html) limit the bytesize of request bodies
+ * - [profiler](middleware-profiler.html) request profiler reporting response-time, memory usage, etc
+ * - [query](middleware-query.html) automatic querystring parser, populating `req.query`
+ * - [errorHandler](middleware-errorHandler.html) flexible error handler
+ *
+ * Internals:
+ *
+ * - connect [utilities](utils.html)
+ * - node monkey [patches](patch.html)
+ *
+ */ \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js b/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js
new file mode 100644
index 0000000..3ff472b
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js
@@ -0,0 +1,93 @@
+
+/*!
+ * Connect - basicAuth
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+ , unauthorized = utils.unauthorized
+ , badRequest = utils.badRequest;
+
+/**
+ * Enfore basic authentication by providing a `callback(user, pass)`,
+ * which must return `true` in order to gain access. Alternatively an async
+ * method is provided as well, invoking `callback(user, pass, callback)`. Populates
+ * `req.remoteUser`. The final alternative is simply passing username / password
+ * strings.
+ *
+ * Examples:
+ *
+ * connect(connect.basicAuth('username', 'password'));
+ *
+ * connect(
+ * connect.basicAuth(function(user, pass){
+ * return 'tj' == user & 'wahoo' == pass;
+ * })
+ * );
+ *
+ * connect(
+ * connect.basicAuth(function(user, pass, fn){
+ * User.authenticate({ user: user, pass: pass }, fn);
+ * })
+ * );
+ *
+ * @param {Function|String} callback or username
+ * @param {String} realm
+ * @api public
+ */
+
+module.exports = function basicAuth(callback, realm) {
+ var username, password;
+
+ // user / pass strings
+ if ('string' == typeof callback) {
+ username = callback;
+ password = realm;
+ if ('string' != typeof password) throw new Error('password argument required');
+ realm = arguments[2];
+ callback = function(user, pass){
+ return user == username && pass == password;
+ }
+ }
+
+ realm = realm || 'Authorization Required';
+
+ return function(req, res, next) {
+ var authorization = req.headers.authorization;
+
+ if (req.remoteUser) return next();
+ if (!authorization) return unauthorized(res, realm);
+
+ var parts = authorization.split(' ')
+ , scheme = parts[0]
+ , credentials = new Buffer(parts[1], 'base64').toString().split(':');
+
+ if ('Basic' != scheme) return badRequest(res);
+
+ // async
+ if (callback.length >= 3) {
+ var pause = utils.pause(req);
+ callback(credentials[0], credentials[1], function(err, user){
+ if (err || !user) return unauthorized(res, realm);
+ req.remoteUser = user;
+ next();
+ pause.resume();
+ });
+ // sync
+ } else {
+ if (callback(credentials[0], credentials[1])) {
+ req.remoteUser = credentials[0];
+ next();
+ } else {
+ unauthorized(res, realm);
+ }
+ }
+ }
+};
+
diff --git a/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js b/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js
new file mode 100644
index 0000000..a52568c
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js
@@ -0,0 +1,196 @@
+
+/*!
+ * Connect - bodyParser
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('qs')
+ , formidable = require('formidable');
+
+/**
+ * Extract the mime type from the given request's
+ * _Content-Type_ header.
+ *
+ * @param {IncomingMessage} req
+ * @return {String}
+ * @api private
+ */
+
+function mime(req) {
+ var str = req.headers['content-type'] || '';
+ return str.split(';')[0];
+}
+
+/**
+ * Parse request bodies.
+ *
+ * By default _application/json_, _application/x-www-form-urlencoded_,
+ * and _multipart/form-data_ are supported, however you may map `connect.bodyParser.parse[contentType]`
+ * to a function receiving `(req, options, callback)`.
+ *
+ * Examples:
+ *
+ * connect.createServer(
+ * connect.bodyParser()
+ * , function(req, res) {
+ * res.end('viewing user ' + req.body.user.name);
+ * }
+ * );
+ *
+ * $ curl -d 'user[name]=tj' http://localhost/
+ * $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://localhost/
+ *
+ * Multipart req.files:
+ *
+ * As a security measure files are stored in a separate object, stored
+ * as `req.files`. This prevents attacks that may potentially alter
+ * filenames, and depending on the application gain access to restricted files.
+ *
+ * Multipart configuration:
+ *
+ * The `options` passed are provided to each parser function.
+ * The _multipart/form-data_ parser merges these with formidable's
+ * IncomingForm object, allowing you to tweak the upload directory,
+ * size limits, etc. For example you may wish to retain the file extension
+ * and change the upload directory:
+ *
+ * server.use(bodyParser({ uploadDir: '/www/mysite.com/uploads' }));
+ *
+ * View [node-formidable](https://github.com/felixge/node-formidable) for more information.
+ *
+ * If you wish to use formidable directly within your app, and do not
+ * desire this behaviour for multipart requests simply remove the
+ * parser:
+ *
+ * delete connect.bodyParser.parse['multipart/form-data'];
+ *
+ * Or
+ *
+ * delete express.bodyParser.parse['multipart/form-data'];
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function bodyParser(options){
+ options = options || {};
+ return function bodyParser(req, res, next) {
+ if (req.body) return next();
+ req.body = {};
+
+ if ('GET' == req.method || 'HEAD' == req.method) return next();
+ var parser = exports.parse[mime(req)];
+ if (parser) {
+ parser(req, options, next);
+ } else {
+ next();
+ }
+ }
+};
+
+/**
+ * Parsers.
+ */
+
+exports.parse = {};
+
+/**
+ * Parse application/x-www-form-urlencoded.
+ */
+
+exports.parse['application/x-www-form-urlencoded'] = function(req, options, fn){
+ var buf = '';
+ req.setEncoding('utf8');
+ req.on('data', function(chunk){ buf += chunk });
+ req.on('end', function(){
+ try {
+ req.body = buf.length
+ ? qs.parse(buf)
+ : {};
+ fn();
+ } catch (err){
+ fn(err);
+ }
+ });
+};
+
+/**
+ * Parse application/json.
+ */
+
+exports.parse['application/json'] = function(req, options, fn){
+ var buf = '';
+ req.setEncoding('utf8');
+ req.on('data', function(chunk){ buf += chunk });
+ req.on('end', function(){
+ try {
+ req.body = buf.length
+ ? JSON.parse(buf)
+ : {};
+ fn();
+ } catch (err){
+ fn(err);
+ }
+ });
+};
+
+/**
+ * Parse multipart/form-data.
+ *
+ * TODO: make multiple support optional
+ * TODO: revisit "error" flag if it's a formidable bug
+ */
+
+exports.parse['multipart/form-data'] = function(req, options, fn){
+ var form = new formidable.IncomingForm
+ , data = {}
+ , files = {}
+ , done;
+
+ Object.keys(options).forEach(function(key){
+ form[key] = options[key];
+ });
+
+ function ondata(name, val, data){
+ if (Array.isArray(data[name])) {
+ data[name].push(val);
+ } else if (data[name]) {
+ data[name] = [data[name], val];
+ } else {
+ data[name] = val;
+ }
+ }
+
+ form.on('field', function(name, val){
+ ondata(name, val, data);
+ });
+
+ form.on('file', function(name, val){
+ ondata(name, val, files);
+ });
+
+ form.on('error', function(err){
+ fn(err);
+ done = true;
+ });
+
+ form.on('end', function(){
+ if (done) return;
+ try {
+ req.body = qs.parse(data);
+ req.files = qs.parse(files);
+ fn();
+ } catch (err) {
+ fn(err);
+ }
+ });
+
+ form.parse(req);
+}; \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/compiler.js b/node_modules/express/node_modules/connect/lib/middleware/compiler.js
new file mode 100644
index 0000000..dc4dd66
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/compiler.js
@@ -0,0 +1,163 @@
+
+/*!
+ * Connect - compiler
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+ , path = require('path')
+ , parse = require('url').parse;
+
+/**
+ * Require cache.
+ */
+
+var cache = {};
+
+/**
+ * Setup compiler.
+ *
+ * Options:
+ *
+ * - `src` Source directory, defaults to **CWD**.
+ * - `dest` Destination directory, defaults `src`.
+ * - `enable` Array of enabled compilers.
+ *
+ * Compilers:
+ *
+ * - `sass` Compiles sass to css
+ * - `less` Compiles less to css
+ * - `coffeescript` Compiles coffee to js
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+exports = module.exports = function compiler(options){
+ options = options || {};
+
+ var srcDir = options.src || process.cwd()
+ , destDir = options.dest || srcDir
+ , enable = options.enable;
+
+ if (!enable || enable.length === 0) {
+ throw new Error('compiler\'s "enable" option is not set, nothing will be compiled.');
+ }
+
+ return function compiler(req, res, next){
+ if ('GET' != req.method) return next();
+ var pathname = parse(req.url).pathname;
+ for (var i = 0, len = enable.length; i < len; ++i) {
+ var name = enable[i]
+ , compiler = compilers[name];
+ if (compiler.match.test(pathname)) {
+ var src = (srcDir + pathname).replace(compiler.match, compiler.ext)
+ , dest = destDir + pathname;
+
+ // Compare mtimes
+ fs.stat(src, function(err, srcStats){
+ if (err) {
+ if ('ENOENT' == err.code) {
+ next();
+ } else {
+ next(err);
+ }
+ } else {
+ fs.stat(dest, function(err, destStats){
+ if (err) {
+ // Oh snap! it does not exist, compile it
+ if ('ENOENT' == err.code) {
+ compile();
+ } else {
+ next(err);
+ }
+ } else {
+ // Source has changed, compile it
+ if (srcStats.mtime > destStats.mtime) {
+ compile();
+ } else {
+ // Defer file serving
+ next();
+ }
+ }
+ });
+ }
+ });
+
+ // Compile to the destination
+ function compile() {
+ fs.readFile(src, 'utf8', function(err, str){
+ if (err) {
+ next(err);
+ } else {
+ compiler.compile(str, function(err, str){
+ if (err) {
+ next(err);
+ } else {
+ fs.writeFile(dest, str, 'utf8', function(err){
+ next(err);
+ });
+ }
+ });
+ }
+ });
+ }
+ return;
+ }
+ }
+ next();
+ };
+};
+
+/**
+ * Bundled compilers:
+ *
+ * - [sass](http://github.com/visionmedia/sass.js) to _css_
+ * - [less](http://github.com/cloudhead/less.js) to _css_
+ * - [coffee](http://github.com/jashkenas/coffee-script) to _js_
+ */
+
+var compilers = exports.compilers = {
+ sass: {
+ match: /\.css$/,
+ ext: '.sass',
+ compile: function(str, fn){
+ var sass = cache.sass || (cache.sass = require('sass'));
+ try {
+ fn(null, sass.render(str));
+ } catch (err) {
+ fn(err);
+ }
+ }
+ },
+ less: {
+ match: /\.css$/,
+ ext: '.less',
+ compile: function(str, fn){
+ var less = cache.less || (cache.less = require('less'));
+ try {
+ less.render(str, fn);
+ } catch (err) {
+ fn(err);
+ }
+ }
+ },
+ coffeescript: {
+ match: /\.js$/,
+ ext: '.coffee',
+ compile: function(str, fn){
+ var coffee = cache.coffee || (cache.coffee = require('coffee-script'));
+ try {
+ fn(null, coffee.compile(str));
+ } catch (err) {
+ fn(err);
+ }
+ }
+ }
+}; \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js b/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js
new file mode 100644
index 0000000..d6b69de
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js
@@ -0,0 +1,46 @@
+
+/*!
+ * Connect - cookieParser
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('./../utils');
+
+/**
+ * Parse _Cookie_ header and populate `req.cookies`
+ * with an object keyed by the cookie names.
+ *
+ * Examples:
+ *
+ * connect.createServer(
+ * connect.cookieParser()
+ * , function(req, res, next){
+ * res.end(JSON.stringify(req.cookies));
+ * }
+ * );
+ *
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function cookieParser(){
+ return function cookieParser(req, res, next) {
+ var cookie = req.headers.cookie;
+ if (req.cookies) return next();
+ req.cookies = {};
+ if (cookie) {
+ try {
+ req.cookies = utils.parseCookie(cookie);
+ } catch (err) {
+ return next(err);
+ }
+ }
+ next();
+ };
+}; \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/csrf.js b/node_modules/express/node_modules/connect/lib/middleware/csrf.js
new file mode 100644
index 0000000..1dcf0d1
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/csrf.js
@@ -0,0 +1,105 @@
+
+/*!
+ * Connect - csrf
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+ , crypto = require('crypto');
+
+/**
+ * CRSF protection middleware.
+ *
+ * By default this middleware generates a token named "_csrf"
+ * which should be added to requests which mutate
+ * state, within a hidden form field, query-string etc. This
+ * token is validated against the visitor's `req.session._csrf`
+ * property which is re-generated per request.
+ *
+ * The default `value` function checks `req.body` generated
+ * by the `bodyParser()` middleware, `req.query` generated
+ * by `query()`, and the "X-CSRF-Token" header field.
+ *
+ * This middleware requires session support, thus should be added
+ * somewhere _below_ `session()` and `cookieParser()`.
+ *
+ * Examples:
+ *
+ * var form = '\n\
+ * <form action="/" method="post">\n\
+ * <input type="hidden" name="_csrf" value="{token}" />\n\
+ * <input type="text" name="user[name]" value="{user}" />\n\
+ * <input type="password" name="user[pass]" />\n\
+ * <input type="submit" value="Login" />\n\
+ * </form>\n\
+ * ';
+ *
+ * connect(
+ * connect.cookieParser()
+ * , connect.session({ secret: 'keyboard cat' })
+ * , connect.bodyParser()
+ * , connect.csrf()
+ *
+ * , function(req, res, next){
+ * if ('POST' != req.method) return next();
+ * req.session.user = req.body.user;
+ * next();
+ * }
+ *
+ * , function(req, res){
+ * res.setHeader('Content-Type', 'text/html');
+ * var body = form
+ * .replace('{token}', req.session._csrf)
+ * .replace('{user}', req.session.user && req.session.user.name || '');
+ * res.end(body);
+ * }
+ * ).listen(3000);
+ *
+ * Options:
+ *
+ * - `value` a function accepting the request, returning the token
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+module.exports = function csrf(options) {
+ var options = options || {}
+ , value = options.value || defaultValue;
+
+ return function(req, res, next){
+ // generate CSRF token
+ var token = req.session._csrf || (req.session._csrf = utils.uid(24));
+
+ // ignore GET (for now)
+ if ('GET' == req.method) return next();
+
+ // determine value
+ var val = value(req);
+
+ // check
+ if (val != token) return utils.forbidden(res);
+
+ next();
+ }
+};
+
+/**
+ * Default value function, checking the `req.body`
+ * and `req.query` for the CSRF token.
+ *
+ * @param {IncomingMessage} req
+ * @return {String}
+ * @api private
+ */
+
+function defaultValue(req) {
+ return (req.body && req.body._csrf)
+ || (req.query && req.query._csrf)
+ || (req.headers['x-csrf-token']);
+} \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/directory.js b/node_modules/express/node_modules/connect/lib/middleware/directory.js
new file mode 100644
index 0000000..df5b5e6
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/directory.js
@@ -0,0 +1,222 @@
+
+/*!
+ * Connect - directory
+ * Copyright(c) 2011 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+// TODO: icon / style for directories
+// TODO: arrow key navigation
+// TODO: make icons extensible
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+ , parse = require('url').parse
+ , utils = require('../utils')
+ , path = require('path')
+ , normalize = path.normalize
+ , extname = path.extname
+ , join = path.join;
+
+/**
+ * Icon cache.
+ */
+
+var cache = {};
+
+/**
+ * Serve directory listings with the given `root` path.
+ *
+ * Options:
+ *
+ * - `hidden` display hidden (dot) files. Defaults to false.
+ * - `icons` display icons. Defaults to false.
+ * - `filter` Apply this filter function to files. Defaults to false.
+ *
+ * @param {String} root
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function directory(root, options){
+ options = options || {};
+
+ // root required
+ if (!root) throw new Error('directory() root path required');
+ var hidden = options.hidden
+ , icons = options.icons
+ , filter = options.filter
+ , root = normalize(root);
+
+ return function directory(req, res, next) {
+ var accept = req.headers.accept || 'text/plain'
+ , url = parse(req.url)
+ , dir = decodeURIComponent(url.pathname)
+ , path = normalize(join(root, dir))
+ , originalUrl = parse(req.originalUrl)
+ , originalDir = decodeURIComponent(originalUrl.pathname)
+ , showUp = path != root && path != root + '/';
+
+ // null byte(s)
+ if (~path.indexOf('\0')) return utils.badRequest(res);
+
+ // malicious path
+ if (0 != path.indexOf(root)) return utils.forbidden(res);
+
+ // check if we have a directory
+ fs.stat(path, function(err, stat){
+ if (err) return 'ENOENT' == err.code
+ ? next()
+ : next(err);
+
+ if (!stat.isDirectory()) return next();
+
+ // fetch files
+ fs.readdir(path, function(err, files){
+ if (err) return next(err);
+ if (!hidden) files = removeHidden(files);
+ if (filter) files = files.filter(filter);
+ files.sort();
+ // content-negotiation
+ for (var key in exports) {
+ if (~accept.indexOf(key) || ~accept.indexOf('*/*')) {
+ exports[key](req, res, files, next, originalDir, showUp, icons);
+ return;
+ }
+ }
+ utils.notAcceptable(res);
+ });
+ });
+ };
+};
+
+/**
+ * Respond with text/html.
+ */
+
+exports.html = function(req, res, files, next, dir, showUp, icons){
+ fs.readFile(__dirname + '/../public/directory.html', 'utf8', function(err, str){
+ if (err) return next(err);
+ fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){
+ if (err) return next(err);
+ if (showUp) files.unshift('..');
+ str = str
+ .replace('{style}', style)
+ .replace('{files}', html(files, dir, icons))
+ .replace('{directory}', dir)
+ .replace('{linked-path}', htmlPath(dir));
+ res.setHeader('Content-Type', 'text/html');
+ res.setHeader('Content-Length', str.length);
+ res.end(str);
+ });
+ });
+};
+
+/**
+ * Respond with application/json.
+ */
+
+exports.json = function(req, res, files){
+ files = JSON.stringify(files);
+ res.setHeader('Content-Type', 'application/json');
+ res.setHeader('Content-Length', files.length);
+ res.end(files);
+};
+
+/**
+ * Respond with text/plain.
+ */
+
+exports.plain = function(req, res, files){
+ files = files.join('\n') + '\n';
+ res.setHeader('Content-Type', 'text/plain');
+ res.setHeader('Content-Length', files.length);
+ res.end(files);
+};
+
+/**
+ * Map html `dir`, returning a linked path.
+ */
+
+function htmlPath(dir) {
+ var curr = [];
+ return dir.split('/').map(function(part){
+ curr.push(part);
+ return '<a href="' + curr.join('/') + '">' + part + '</a>';
+ }).join(' / ');
+}
+
+/**
+ * Map html `files`, returning an html unordered list.
+ */
+
+function html(files, dir, useIcons) {
+ return '<ul id="files">' + files.map(function(file){
+ var icon = ''
+ , classes = [];
+
+ if (useIcons && '..' != file) {
+ icon = icons[extname(file)] || icons.default;
+ icon = '<img src="data:image/png;base64,' + load(icon) + '" />';
+ classes.push('icon');
+ }
+
+ return '<li><a href="'
+ + join(dir, file)
+ + '" class="'
+ + classes.join(' ') + '"'
+ + ' title="' + file + '">'
+ + icon + file + '</a></li>';
+
+ }).join('\n') + '</ul>';
+}
+
+/**
+ * Load and cache the given `icon`.
+ *
+ * @param {String} icon
+ * @return {String}
+ * @api private
+ */
+
+function load(icon) {
+ if (cache[icon]) return cache[icon];
+ return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64');
+}
+
+/**
+ * Filter "hidden" `files`, aka files
+ * beginning with a `.`.
+ *
+ * @param {Array} files
+ * @return {Array}
+ * @api private
+ */
+
+function removeHidden(files) {
+ return files.filter(function(file){
+ return '.' != file[0];
+ });
+}
+
+/**
+ * Icon map.
+ */
+
+var icons = {
+ '.js': 'page_white_code_red.png'
+ , '.c': 'page_white_c.png'
+ , '.h': 'page_white_h.png'
+ , '.cc': 'page_white_cplusplus.png'
+ , '.php': 'page_white_php.png'
+ , '.rb': 'page_white_ruby.png'
+ , '.cpp': 'page_white_cplusplus.png'
+ , '.swf': 'page_white_flash.png'
+ , '.pdf': 'page_white_acrobat.png'
+ , 'default': 'page_white.png'
+};
diff --git a/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js b/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js
new file mode 100644
index 0000000..f2fc44f
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js
@@ -0,0 +1,100 @@
+/*!
+ * Connect - errorHandler
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+ , url = require('url')
+ , fs = require('fs');
+
+/**
+ * Flexible error handler, providing (_optional_) stack traces
+ * and error message responses for requests accepting text, html,
+ * or json.
+ *
+ * Options:
+ *
+ * - `showStack`, `stack` respond with both the error message and stack trace. Defaults to `false`
+ * - `showMessage`, `message`, respond with the exception message only. Defaults to `false`
+ * - `dumpExceptions`, `dump`, dump exceptions to stderr (without terminating the process). Defaults to `false`
+ *
+ * Text:
+ *
+ * By default, and when _text/plain_ is accepted a simple stack trace
+ * or error message will be returned.
+ *
+ * JSON:
+ *
+ * When _application/json_ is accepted, connect will respond with
+ * an object in the form of `{ "error": error }`.
+ *
+ * HTML:
+ *
+ * When accepted connect will output a nice html stack trace.
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function errorHandler(options){
+ options = options || {};
+
+ // defaults
+ var showStack = options.showStack || options.stack
+ , showMessage = options.showMessage || options.message
+ , dumpExceptions = options.dumpExceptions || options.dump
+ , formatUrl = options.formatUrl;
+
+ return function errorHandler(err, req, res, next){
+ res.statusCode = 500;
+ if (dumpExceptions) console.error(err.stack);
+ if (showStack) {
+ var accept = req.headers.accept || '';
+ // html
+ if (~accept.indexOf('html')) {
+ fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){
+ fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){
+ var stack = (err.stack || '')
+ .split('\n').slice(1)
+ .map(function(v){ return '<li>' + v + '</li>'; }).join('');
+ html = html
+ .replace('{style}', style)
+ .replace('{stack}', stack)
+ .replace('{title}', exports.title)
+ .replace(/\{error\}/g, utils.escape(err.toString()));
+ res.setHeader('Content-Type', 'text/html');
+ res.end(html);
+ });
+ });
+ // json
+ } else if (~accept.indexOf('json')) {
+ var json = JSON.stringify({ error: err });
+ res.setHeader('Content-Type', 'application/json');
+ res.end(json);
+ // plain text
+ } else {
+ res.writeHead(500, { 'Content-Type': 'text/plain' });
+ res.end(err.stack);
+ }
+ } else {
+ var body = showMessage
+ ? err.toString()
+ : 'Internal Server Error';
+ res.setHeader('Content-Type', 'text/plain');
+ res.end(body);
+ }
+ };
+};
+
+/**
+ * Template title.
+ */
+
+exports.title = 'Connect'; \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/favicon.js b/node_modules/express/node_modules/connect/lib/middleware/favicon.js
new file mode 100644
index 0000000..8eeafba
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/favicon.js
@@ -0,0 +1,76 @@
+
+/*!
+ * Connect - favicon
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+ , utils = require('../utils');
+
+/**
+ * Favicon cache.
+ */
+
+var icon;
+
+/**
+ * By default serves the connect favicon, or the favicon
+ * located by the given `path`.
+ *
+ * Options:
+ *
+ * - `maxAge` cache-control max-age directive, defaulting to 1 day
+ *
+ * Examples:
+ *
+ * connect.createServer(
+ * connect.favicon()
+ * );
+ *
+ * connect.createServer(
+ * connect.favicon(__dirname + '/public/favicon.ico')
+ * );
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function favicon(path, options){
+ var options = options || {}
+ , path = path || __dirname + '/../public/favicon.ico'
+ , maxAge = options.maxAge || 86400000;
+
+ return function favicon(req, res, next){
+ if ('/favicon.ico' == req.url) {
+ if (icon) {
+ res.writeHead(200, icon.headers);
+ res.end(icon.body);
+ } else {
+ fs.readFile(path, function(err, buf){
+ if (err) return next(err);
+ icon = {
+ headers: {
+ 'Content-Type': 'image/x-icon'
+ , 'Content-Length': buf.length
+ , 'ETag': '"' + utils.md5(buf) + '"'
+ , 'Cache-Control': 'public, max-age=' + (maxAge / 1000)
+ },
+ body: buf
+ };
+ res.writeHead(200, icon.headers);
+ res.end(icon.body);
+ });
+ }
+ } else {
+ next();
+ }
+ };
+}; \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/limit.js b/node_modules/express/node_modules/connect/lib/middleware/limit.js
new file mode 100644
index 0000000..a604ffb
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/limit.js
@@ -0,0 +1,80 @@
+
+/*!
+ * Connect - limit
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Limit request bodies to the given size in `bytes`.
+ *
+ * A string representation of the bytesize may also be passed,
+ * for example "5mb", "200kb", "1gb", etc.
+ *
+ * Examples:
+ *
+ * var server = connect(
+ * connect.limit('5.5mb')
+ * ).listen(3000);
+ *
+ * @param {Number|String} bytes
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function limit(bytes){
+ if ('string' == typeof bytes) bytes = parse(bytes);
+ if ('number' != typeof bytes) throw new Error('limit() bytes required');
+ return function limit(req, res, next){
+ var received = 0
+ , len = req.headers['content-length']
+ ? parseInt(req.headers['content-length'], 10)
+ : null;
+
+ // deny the request
+ function deny() {
+ req.destroy();
+ }
+
+ // self-awareness
+ if (req._limit) return next();
+ req._limit = true;
+
+ // limit by content-length
+ if (len && len > bytes) {
+ res.statusCode = 413;
+ res.end('Request Entity Too Large');
+ return;
+ }
+
+ // limit
+ req.on('data', function(chunk){
+ received += chunk.length;
+ if (received > bytes) deny();
+ });
+
+ next();
+ };
+};
+
+/**
+ * Parse byte `size` string.
+ *
+ * @param {String} size
+ * @return {Number}
+ * @api private
+ */
+
+function parse(size) {
+ var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb)$/)
+ , n = parseFloat(parts[1])
+ , type = parts[2];
+
+ var map = {
+ kb: 1024
+ , mb: 1024 * 1024
+ , gb: 1024 * 1024 * 1024
+ };
+
+ return map[type] * n;
+} \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/logger.js b/node_modules/express/node_modules/connect/lib/middleware/logger.js
new file mode 100644
index 0000000..75cc5aa
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/logger.js
@@ -0,0 +1,299 @@
+
+/*!
+ * Connect - logger
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Log buffer.
+ */
+
+var buf = [];
+
+/**
+ * Default log buffer duration.
+ */
+
+var defaultBufferDuration = 1000;
+
+/**
+ * Log requests with the given `options` or a `format` string.
+ *
+ * Options:
+ *
+ * - `format` Format string, see below for tokens
+ * - `stream` Output stream, defaults to _stdout_
+ * - `buffer` Buffer duration, defaults to 1000ms when _true_
+ * - `immediate` Write log line on request instead of response (for response times)
+ *
+ * Tokens:
+ *
+ * - `:req[header]` ex: `:req[Accept]`
+ * - `:res[header]` ex: `:res[Content-Length]`
+ * - `:http-version`
+ * - `:response-time`
+ * - `:remote-addr`
+ * - `:date`
+ * - `:method`
+ * - `:url`
+ * - `:referrer`
+ * - `:user-agent`
+ * - `:status`
+ *
+ * Formats:
+ *
+ * Pre-defined formats that ship with connect:
+ *
+ * - `default` ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'
+ * - `short` ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'
+ * - `tiny` ':method :url :status :res[content-length] - :response-time ms'
+ * - `dev` concise output colored by response status for development use
+ *
+ * Examples:
+ *
+ * connect.logger() // default
+ * connect.logger('short')
+ * connect.logger('tiny')
+ * connect.logger('dev')
+ * connect.logger(':method :url - :referrer')
+ * connect.logger(':req[content-type] -> :res[content-type]')
+ * connect.logger(function(req, res){ return 'some format string' })
+ *
+ * Defining Tokens:
+ *
+ * To define a token, simply invoke `connect.logger.token()` with the
+ * name and a callback function. The value returned is then available
+ * as ":type" in this case.
+ *
+ * connect.logger.token('type', function(req, res){ return req.headers['content-type']; })
+ *
+ * Defining Formats:
+ *
+ * All default formats are defined this way, however it's public API as well:
+ *
+ * connect.logger.format('name', 'string or function')
+ *
+ * @param {String|Function|Object} format or options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function logger(options) {
+ if ('object' == typeof options) {
+ options = options || {};
+ } else if (options) {
+ options = { format: options };
+ } else {
+ options = {};
+ }
+
+ // output on request instead of response
+ var immediate = options.immediate;
+
+ // format name
+ var fmt = exports[options.format] || options.format || exports.default;
+
+ // compile format
+ if ('function' != typeof fmt) fmt = compile(fmt);
+
+ // options
+ var stream = options.stream || process.stdout
+ , buffer = options.buffer;
+
+ // buffering support
+ if (buffer) {
+ var realStream = stream
+ , interval = 'number' == typeof buffer
+ ? buffer
+ : defaultBufferDuration;
+
+ // flush interval
+ setInterval(function(){
+ if (buf.length) {
+ realStream.write(buf.join(''), 'ascii');
+ buf.length = 0;
+ }
+ }, interval);
+
+ // swap the stream
+ stream = {
+ write: function(str){
+ buf.push(str);
+ }
+ };
+ }
+
+ return function logger(req, res, next) {
+ req._startTime = new Date;
+
+ // mount safety
+ if (req._logging) return next();
+
+ // flag as logging
+ req._logging = true;
+
+ // immediate
+ if (immediate) {
+ var line = fmt(exports, req, res);
+ if (null == line) return;
+ stream.write(line + '\n', 'ascii');
+ } else {
+ // proxy end to output loggging
+ var end = res.end;
+ res.end = function(chunk, encoding){
+ res.end = end;
+ res.end(chunk, encoding);
+ var line = fmt(exports, req, res);
+ if (null == line) return;
+ stream.write(line + '\n', 'ascii');
+ };
+ }
+
+
+ next();
+ };
+};
+
+/**
+ * Compile `fmt` into a function.
+ *
+ * @param {String} fmt
+ * @return {Function}
+ * @api private
+ */
+
+function compile(fmt) {
+ fmt = fmt.replace(/"/g, '\\"');
+ var js = ' return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg){
+ return '"\n + (tokens["' + name + '"](req, res, "' + arg + '") || "-") + "';
+ }) + '";'
+ return new Function('tokens, req, res', js);
+};
+
+/**
+ * Define a token function with the given `name`,
+ * and callback `fn(req, res)`.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @return {Object} exports for chaining
+ * @api public
+ */
+
+exports.token = function(name, fn) {
+ exports[name] = fn;
+ return this;
+};
+
+/**
+ * Define a `fmt` with the given `name`.
+ *
+ * @param {String} name
+ * @param {String|Function} fmt
+ * @return {Object} exports for chaining
+ * @api public
+ */
+
+exports.format = function(name, str){
+ exports[name] = str;
+ return this;
+};
+
+// default format
+
+exports.format('default', ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"');
+
+// short format
+
+exports.format('short', ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms');
+
+// tiny format
+
+exports.format('tiny', ':method :url :status :res[content-length] - :response-time ms');
+
+// dev (colored)
+
+exports.format('dev', function(tokens, req, res){
+ var status = res.statusCode
+ , color = 32;
+
+ if (status >= 500) color = 31
+ else if (status >= 400) color = 33
+ else if (status >= 300) color = 36;
+
+ return '\033[90m' + req.method
+ + ' ' + req.originalUrl + ' '
+ + '\033[' + color + 'm' + res.statusCode
+ + ' \033[90m'
+ + (new Date - req._startTime)
+ + 'ms\033[0m';
+});
+
+// request url
+
+exports.token('url', function(req){
+ return req.originalUrl;
+});
+
+// request method
+
+exports.token('method', function(req){
+ return req.method;
+});
+
+// response time in milliseconds
+
+exports.token('response-time', function(req){
+ return new Date - req._startTime;
+});
+
+// UTC date
+
+exports.token('date', function(){
+ return new Date().toUTCString();
+});
+
+// response status code
+
+exports.token('status', function(req, res){
+ return res.statusCode;
+});
+
+// normalized referrer
+
+exports.token('referrer', function(req){
+ return req.headers['referer'] || req.headers['referrer'];
+});
+
+// remote address
+
+exports.token('remote-addr', function(req){
+ return req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress));
+});
+
+// HTTP version
+
+exports.token('http-version', function(req){
+ return req.httpVersionMajor + '.' + req.httpVersionMinor;
+});
+
+// UA string
+
+exports.token('user-agent', function(req){
+ return req.headers['user-agent'];
+});
+
+// request header
+
+exports.token('req', function(req, res, field){
+ return req.headers[field.toLowerCase()];
+});
+
+// response header
+
+exports.token('res', function(req, res, field){
+ return (res._headers || {})[field.toLowerCase()];
+});
+
diff --git a/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js b/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js
new file mode 100644
index 0000000..db4e9f3
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js
@@ -0,0 +1,38 @@
+
+/*!
+ * Connect - methodOverride
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Provides faux HTTP method support.
+ *
+ * Pass an optional `key` to use when checking for
+ * a method override, othewise defaults to _\_method_.
+ * The original method is available via `req.originalMethod`.
+ *
+ * @param {String} key
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function methodOverride(key){
+ key = key || "_method";
+ return function methodOverride(req, res, next) {
+ req.originalMethod = req.originalMethod || req.method;
+
+ // req.body
+ if (req.body && key in req.body) {
+ req.method = req.body[key].toUpperCase();
+ delete req.body[key];
+ // check X-HTTP-Method-Override
+ } else if (req.headers['x-http-method-override']) {
+ req.method = req.headers['x-http-method-override'].toUpperCase();
+ }
+
+ next();
+ };
+};
+
diff --git a/node_modules/express/node_modules/connect/lib/middleware/profiler.js b/node_modules/express/node_modules/connect/lib/middleware/profiler.js
new file mode 100644
index 0000000..b0b5bac
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/profiler.js
@@ -0,0 +1,100 @@
+
+/*!
+ * Connect - profiler
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Profile the duration of a request.
+ *
+ * Typically this middleware should be utilized
+ * _above_ all others, as it proxies the `res.end()`
+ * method, being first allows it to encapsulate all
+ * other middleware.
+ *
+ * Example Output:
+ *
+ * GET /
+ * response time 2ms
+ * memory rss 52.00kb
+ * memory vsize 2.07mb
+ * heap before 3.76mb / 8.15mb
+ * heap after 3.80mb / 8.15mb
+ *
+ * @api public
+ */
+
+module.exports = function profiler(){
+ return function(req, res, next){
+ var end = res.end
+ , start = snapshot();
+
+ // state snapshot
+ function snapshot() {
+ return {
+ mem: process.memoryUsage()
+ , time: new Date
+ };
+ }
+
+ // proxy res.end()
+ res.end = function(data, encoding){
+ res.end = end;
+ res.end(data, encoding);
+ compare(req, start, snapshot())
+ };
+
+ next();
+ }
+};
+
+/**
+ * Compare `start` / `end` snapshots.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} start
+ * @param {Object} end
+ * @api private
+ */
+
+function compare(req, start, end) {
+ console.log();
+ row(req.method, req.url);
+ row('response time:', (end.time - start.time) + 'ms');
+ row('memory rss:', formatBytes(end.mem.rss - start.mem.rss));
+ row('memory vsize:', formatBytes(end.mem.vsize - start.mem.vsize));
+ row('heap before:', formatBytes(start.mem.heapUsed) + ' / ' + formatBytes(start.mem.heapTotal));
+ row('heap after:', formatBytes(end.mem.heapUsed) + ' / ' + formatBytes(end.mem.heapTotal));
+ console.log();
+}
+
+/**
+ * Row helper
+ *
+ * @param {String} key
+ * @param {String} val
+ * @api private
+ */
+
+function row(key, val) {
+ console.log(' \033[90m%s\033[0m \033[36m%s\033[0m', key, val);
+}
+
+/**
+ * Format byte-size.
+ *
+ * @param {Number} bytes
+ * @return {String}
+ * @api private
+ */
+
+function formatBytes(bytes) {
+ var kb = 1024
+ , mb = 1024 * kb
+ , gb = 1024 * mb;
+ if (bytes < kb) return bytes + 'b';
+ if (bytes < mb) return (bytes / kb).toFixed(2) + 'kb';
+ if (bytes < gb) return (bytes / mb).toFixed(2) + 'mb';
+ return (bytes / gb).toFixed(2) + 'gb';
+};
diff --git a/node_modules/express/node_modules/connect/lib/middleware/query.js b/node_modules/express/node_modules/connect/lib/middleware/query.js
new file mode 100644
index 0000000..d3b1acd
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/query.js
@@ -0,0 +1,40 @@
+
+/*!
+ * Connect - query
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('qs')
+ , parse = require('url').parse;
+
+/**
+ * Automatically parse the query-string when available,
+ * populating the `req.query` object.
+ *
+ * Examples:
+ *
+ * connect(
+ * connect.query()
+ * , function(req, res){
+ * res.end(JSON.stringify(req.query));
+ * }
+ * ).listen(3000);
+ *
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function query(){
+ return function query(req, res, next){
+ req.query = ~req.url.indexOf('?')
+ ? qs.parse(parse(req.url).query)
+ : {};
+ next();
+ };
+};
diff --git a/node_modules/express/node_modules/connect/lib/middleware/responseTime.js b/node_modules/express/node_modules/connect/lib/middleware/responseTime.js
new file mode 100644
index 0000000..2b2133a
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/responseTime.js
@@ -0,0 +1,34 @@
+
+/*!
+ * Connect - responseTime
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Adds the `X-Response-Time` header displaying the response
+ * duration in milliseconds.
+ *
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function responseTime(){
+ return function(req, res, next){
+ var writeHead = res.writeHead
+ , start = new Date;
+
+ if (res._responseTime) return next();
+ res._responseTime = true;
+
+ // proxy writeHead to calculate duration
+ res.writeHead = function(status, headers){
+ var duration = new Date - start;
+ res.setHeader('X-Response-Time', duration + 'ms');
+ res.writeHead = writeHead;
+ res.writeHead(status, headers);
+ };
+
+ next();
+ };
+};
diff --git a/node_modules/express/node_modules/connect/lib/middleware/router.js b/node_modules/express/node_modules/connect/lib/middleware/router.js
new file mode 100644
index 0000000..a07452e
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/router.js
@@ -0,0 +1,379 @@
+
+/*!
+ * Connect - router
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+ , parse = require('url').parse;
+
+/**
+ * Expose router.
+ */
+
+exports = module.exports = router;
+
+/**
+ * Supported HTTP / WebDAV methods.
+ */
+
+var _methods = exports.methods = [
+ 'get'
+ , 'post'
+ , 'put'
+ , 'delete'
+ , 'connect'
+ , 'options'
+ , 'trace'
+ , 'copy'
+ , 'lock'
+ , 'mkcol'
+ , 'move'
+ , 'propfind'
+ , 'proppatch'
+ , 'unlock'
+ , 'report'
+ , 'mkactivity'
+ , 'checkout'
+ , 'merge'
+];
+
+/**
+ * Provides Sinatra and Express-like routing capabilities.
+ *
+ * Examples:
+ *
+ * connect.router(function(app){
+ * app.get('/user/:id', function(req, res, next){
+ * // populates req.params.id
+ * });
+ * app.put('/user/:id', function(req, res, next){
+ * // populates req.params.id
+ * });
+ * })
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @api public
+ */
+
+function router(fn){
+ var self = this
+ , methods = {}
+ , routes = {}
+ , params = {};
+
+ if (!fn) throw new Error('router provider requires a callback function');
+
+ // Generate method functions
+ _methods.forEach(function(method){
+ methods[method] = generateMethodFunction(method.toUpperCase());
+ });
+
+ // Alias del -> delete
+ methods.del = methods.delete;
+
+ // Apply callback to all methods
+ methods.all = function(){
+ var args = arguments;
+ _methods.forEach(function(name){
+ methods[name].apply(this, args);
+ });
+ return self;
+ };
+
+ // Register param callback
+ methods.param = function(name, fn){
+ params[name] = fn;
+ };
+
+ fn.call(this, methods);
+
+ function generateMethodFunction(name) {
+ var localRoutes = routes[name] = routes[name] || [];
+ return function(path, fn){
+ var keys = []
+ , middleware = [];
+
+ // slice middleware
+ if (arguments.length > 2) {
+ middleware = Array.prototype.slice.call(arguments, 1, arguments.length);
+ fn = middleware.pop();
+ middleware = utils.flatten(middleware);
+ }
+
+ fn.middleware = middleware;
+
+ if (!path) throw new Error(name + ' route requires a path');
+ if (!fn) throw new Error(name + ' route ' + path + ' requires a callback');
+ var regexp = path instanceof RegExp
+ ? path
+ : normalizePath(path, keys);
+ localRoutes.push({
+ fn: fn
+ , path: regexp
+ , keys: keys
+ , orig: path
+ , method: name
+ });
+ return self;
+ };
+ }
+
+ function router(req, res, next){
+ var route
+ , self = this;
+
+ (function pass(i){
+ if (route = match(req, routes, i)) {
+ var i = 0
+ , keys = route.keys;
+
+ req.params = route.params;
+
+ // Param preconditions
+ (function param(err) {
+ try {
+ var key = keys[i++]
+ , val = req.params[key]
+ , fn = params[key];
+
+ if ('route' == err) {
+ pass(req._route_index + 1);
+ // Error
+ } else if (err) {
+ next(err);
+ // Param has callback
+ } else if (fn) {
+ // Return style
+ if (1 == fn.length) {
+ req.params[key] = fn(val);
+ param();
+ // Middleware style
+ } else {
+ fn(req, res, param, val);
+ }
+ // Finished processing params
+ } else if (!key) {
+ // route middleware
+ i = 0;
+ (function nextMiddleware(err){
+ var fn = route.middleware[i++];
+ if ('route' == err) {
+ pass(req._route_index + 1);
+ } else if (err) {
+ next(err);
+ } else if (fn) {
+ fn(req, res, nextMiddleware);
+ } else {
+ route.call(self, req, res, function(err){
+ if (err) {
+ next(err);
+ } else {
+ pass(req._route_index + 1);
+ }
+ });
+ }
+ })();
+ // More params
+ } else {
+ param();
+ }
+ } catch (err) {
+ next(err);
+ }
+ })();
+ } else if ('OPTIONS' == req.method) {
+ options(req, res, routes);
+ } else {
+ next();
+ }
+ })();
+ };
+
+ router.remove = function(path, method){
+ var fns = router.lookup(path, method);
+ fns.forEach(function(fn){
+ routes[fn.method].splice(fn.index, 1);
+ });
+ };
+
+ router.lookup = function(path, method, ret){
+ ret = ret || [];
+
+ // method specific lookup
+ if (method) {
+ method = method.toUpperCase();
+ if (routes[method]) {
+ routes[method].forEach(function(route, i){
+ if (path == route.orig) {
+ var fn = route.fn;
+ fn.regexp = route.path;
+ fn.keys = route.keys;
+ fn.path = route.orig;
+ fn.method = route.method;
+ fn.index = i;
+ ret.push(fn);
+ }
+ });
+ }
+ // global lookup
+ } else {
+ _methods.forEach(function(method){
+ router.lookup(path, method, ret);
+ });
+ }
+
+ return ret;
+ };
+
+ router.match = function(url, method, ret){
+ var ret = ret || []
+ , i = 0
+ , fn
+ , req;
+
+ // method specific matches
+ if (method) {
+ method = method.toUpperCase();
+ req = { url: url, method: method };
+ while (fn = match(req, routes, i)) {
+ i = req._route_index + 1;
+ ret.push(fn);
+ }
+ // global matches
+ } else {
+ _methods.forEach(function(method){
+ router.match(url, method, ret);
+ });
+ }
+
+ return ret;
+ };
+
+ return router;
+}
+
+/**
+ * Respond to OPTIONS.
+ *
+ * @param {ServerRequest} req
+ * @param {ServerResponse} req
+ * @param {Array} routes
+ * @api private
+ */
+
+function options(req, res, routes) {
+ var pathname = parse(req.url).pathname
+ , body = optionsFor(pathname, routes).join(',');
+ res.writeHead(200, {
+ 'Content-Length': body.length
+ , 'Allow': body
+ });
+ res.end(body);
+}
+
+/**
+ * Return OPTIONS array for the given `path`, matching `routes`.
+ *
+ * @param {String} path
+ * @param {Array} routes
+ * @return {Array}
+ * @api private
+ */
+
+function optionsFor(path, routes) {
+ return _methods.filter(function(method){
+ var arr = routes[method.toUpperCase()];
+ for (var i = 0, len = arr.length; i < len; ++i) {
+ if (arr[i].path.test(path)) return true;
+ }
+ }).map(function(method){
+ return method.toUpperCase();
+ });
+}
+
+/**
+ * Normalize the given path string,
+ * returning a regular expression.
+ *
+ * An empty array should be passed,
+ * which will contain the placeholder
+ * key names. For example "/user/:id" will
+ * then contain ["id"].
+ *
+ * @param {String} path
+ * @param {Array} keys
+ * @return {RegExp}
+ * @api private
+ */
+
+function normalizePath(path, keys) {
+ path = path
+ .concat('/?')
+ .replace(/\/\(/g, '(?:/')
+ .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional){
+ keys.push(key);
+ slash = slash || '';
+ return ''
+ + (optional ? '' : slash)
+ + '(?:'
+ + (optional ? slash : '')
+ + (format || '') + (capture || '([^/]+?)') + ')'
+ + (optional || '');
+ })
+ .replace(/([\/.])/g, '\\$1')
+ .replace(/\*/g, '(.+)');
+ return new RegExp('^' + path + '$', 'i');
+}
+
+/**
+ * Attempt to match the given request to
+ * one of the routes. When successful
+ * a route function is returned.
+ *
+ * @param {ServerRequest} req
+ * @param {Object} routes
+ * @return {Function}
+ * @api private
+ */
+
+function match(req, routes, i) {
+ var captures
+ , method = req.method
+ , i = i || 0;
+ if ('HEAD' == method) method = 'GET';
+ if (routes = routes[method]) {
+ var url = parse(req.url)
+ , pathname = url.pathname;
+ for (var len = routes.length; i < len; ++i) {
+ var route = routes[i]
+ , fn = route.fn
+ , path = route.path
+ , keys = fn.keys = route.keys;
+ if (captures = path.exec(pathname)) {
+ fn.method = method;
+ fn.params = [];
+ for (var j = 1, len = captures.length; j < len; ++j) {
+ var key = keys[j-1],
+ val = typeof captures[j] === 'string'
+ ? decodeURIComponent(captures[j])
+ : captures[j];
+ if (key) {
+ fn.params[key] = val;
+ } else {
+ fn.params.push(val);
+ }
+ }
+ req._route_index = i;
+ return fn;
+ }
+ }
+ }
+}
diff --git a/node_modules/express/node_modules/connect/lib/middleware/session.js b/node_modules/express/node_modules/connect/lib/middleware/session.js
new file mode 100644
index 0000000..6616fad
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/session.js
@@ -0,0 +1,345 @@
+
+/*!
+ * Connect - session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Session = require('./session/session')
+ , MemoryStore = require('./session/memory')
+ , Cookie = require('./session/cookie')
+ , Store = require('./session/store')
+ , utils = require('./../utils')
+ , parse = require('url').parse
+ , crypto = require('crypto');
+
+// environment
+
+var env = process.env.NODE_ENV;
+
+/**
+ * Expose the middleware.
+ */
+
+exports = module.exports = session;
+
+/**
+ * Expose constructors.
+ */
+
+exports.Store = Store;
+exports.Cookie = Cookie;
+exports.Session = Session;
+exports.MemoryStore = MemoryStore;
+
+/**
+ * Warning message for `MemoryStore` usage in production.
+ */
+
+var warning = 'Warning: connection.session() MemoryStore is not\n'
+ + 'designed for a production environment, as it will leak\n'
+ + 'memory, and obviously only work within a single process.';
+
+/**
+ * Default finger-printing function.
+ */
+
+function defaultFingerprint(req) {
+ return '';
+};
+
+/**
+ * Paths to ignore.
+ */
+
+exports.ignore = [];
+
+/**
+ * Setup session store with the given `options`.
+ *
+ * Session data is _not_ saved in the cookie itself, however
+ * cookies are used, so we must use the [cookieParser()](middleware-cookieParser.html)
+ * middleware _before_ `session()`.
+ *
+ * Examples:
+ *
+ * connect.createServer(
+ * connect.cookieParser()
+ * , connect.session({ secret: 'keyboard cat' })
+ * );
+ *
+ * Options:
+ *
+ * - `key` cookie name defaulting to `connect.sid`
+ * - `store` Session store instance
+ * - `fingerprint` Custom fingerprint generating function
+ * - `cookie` Session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: 14400000 }`
+ * - `secret` Secret string used to compute hash
+ *
+ * Ignore Paths:
+ *
+ * By default `/favicon.ico` is the only ignored path, all others
+ * will utilize sessions, to manipulate the paths ignored, use
+ * `connect.session.ignore.push('/my/path')`. This works for _full_
+ * pathnames only, not segments nor substrings.
+ *
+ * connect.session.ignore.push('/robots.txt');
+ *
+ * ## req.session
+ *
+ * To store or access session data, simply use the request property `req.session`,
+ * which is (generally) serialized as JSON by the store, so nested objects
+ * are typically fine. For example below is a user-specific view counter:
+ *
+ * connect(
+ * connect.cookieParser()
+ * , connect.session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }})
+ * , connect.favicon()
+ * , function(req, res, next){
+ * var sess = req.session;
+ * if (sess.views) {
+ * res.setHeader('Content-Type', 'text/html');
+ * res.write('<p>views: ' + sess.views + '</p>');
+ * res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>');
+ * res.end();
+ * sess.views++;
+ * } else {
+ * sess.views = 1;
+ * res.end('welcome to the session demo. refresh!');
+ * }
+ * }
+ * ).listen(3000);
+ *
+ * ## Session#regenerate()
+ *
+ * To regenerate the session simply invoke the method, once complete
+ * a new SID and `Session` instance will be initialized at `req.session`.
+ *
+ * req.session.regenerate(function(err){
+ * // will have a new session here
+ * });
+ *
+ * ## Session#destroy()
+ *
+ * Destroys the session, removing `req.session`, will be re-generated next request.
+ *
+ * req.session.destroy(function(err){
+ * // cannot access session here
+ * });
+ *
+ * ## Session#reload()
+ *
+ * Reloads the session data.
+ *
+ * req.session.reload(function(err){
+ * // session updated
+ * });
+ *
+ * ## Session#save()
+ *
+ * Save the session.
+ *
+ * req.session.save(function(err){
+ * // session saved
+ * });
+ *
+ * ## Session#touch()
+ *
+ * Updates the `.maxAge`, and `.lastAccess` properties. Typically this is
+ * not necessary to call, as the session middleware does this for you.
+ *
+ * ## Session#cookie
+ *
+ * Each session has a unique cookie object accompany it. This allows
+ * you to alter the session cookie per visitor. For example we can
+ * set `req.session.cookie.expires` to `false` to enable the cookie
+ * to remain for only the duration of the user-agent.
+ *
+ * ## Session#maxAge
+ *
+ * Alternatively `req.session.cookie.maxAge` will return the time
+ * remaining in milliseconds, which we may also re-assign a new value
+ * to adjust the `.expires` property appropriately. The following
+ * are essentially equivalent
+ *
+ * var hour = 3600000;
+ * req.session.cookie.expires = new Date(Date.now() + hour);
+ * req.session.cookie.maxAge = hour;
+ *
+ * For example when `maxAge` is set to `60000` (one minute), and 30 seconds
+ * has elapsed it will return `30000` until the current request has completed,
+ * at which time `req.session.touch()` is called to update `req.session.lastAccess`,
+ * and reset `req.session.maxAge` to its original value.
+ *
+ * req.session.cookie.maxAge;
+ * // => 30000
+ *
+ * Session Store Implementation:
+ *
+ * Every session store _must_ implement the following methods
+ *
+ * - `.get(sid, callback)`
+ * - `.set(sid, session, callback)`
+ * - `.destroy(sid, callback)`
+ *
+ * Recommended methods include, but are not limited to:
+ *
+ * - `.length(callback)`
+ * - `.clear(callback)`
+ *
+ * For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo.
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+function session(options){
+ var options = options || {}
+ , key = options.key || 'connect.sid'
+ , secret = options.secret
+ , store = options.store || new MemoryStore
+ , fingerprint = options.fingerprint || defaultFingerprint
+ , cookie = options.cookie;
+
+ // notify user that this store is not
+ // meant for a production environment
+ if ('production' == env && store instanceof MemoryStore) {
+ console.warn(warning);
+ }
+
+ // ensure secret is present
+ if (!secret) {
+ throw new Error('connect.session({ secret: "string" }) required for security');
+ }
+
+ // session hashing function
+ store.hash = function(req, base) {
+ return crypto
+ .createHmac('sha256', secret)
+ .update(base + fingerprint(req))
+ .digest('base64')
+ .replace(/=*$/, '');
+ };
+
+ // generates the new session
+ store.generate = function(req){
+ var base = utils.uid(24);
+ var sessionID = base + '.' + store.hash(req, base);
+ req.sessionID = sessionID;
+ req.session = new Session(req);
+ req.session.cookie = new Cookie(cookie);
+ };
+
+ return function session(req, res, next) {
+ // self-awareness
+ if (req.session) return next();
+
+ // parse url
+ var url = parse(req.url)
+ , path = url.pathname;
+
+ // ignorable paths
+ if (~exports.ignore.indexOf(path)) return next();
+
+ // expose store
+ req.sessionStore = store;
+
+ // proxy writeHead() to Set-Cookie
+ var writeHead = res.writeHead;
+ res.writeHead = function(status, headers){
+ if (req.session) {
+ var cookie = req.session.cookie;
+ // only send secure session cookies when there is a secure connection.
+ // proxySecure is a custom attribute to allow for a reverse proxy
+ // to handle SSL connections and to communicate to connect over HTTP that
+ // the incoming connection is secure.
+ var secured = cookie.secure && (req.connection.encrypted || req.connection.proxySecure);
+ if (secured || !cookie.secure) {
+ res.setHeader('Set-Cookie', cookie.serialize(key, req.sessionID));
+ }
+ }
+
+ res.writeHead = writeHead;
+ return res.writeHead(status, headers);
+ };
+
+ // proxy end() to commit the session
+ var end = res.end;
+ res.end = function(data, encoding){
+ res.end = end;
+ if (req.session) {
+ // HACK: ensure Set-Cookie for implicit writeHead()
+ if (!res._header) res._implicitHeader();
+ req.session.resetMaxAge();
+ req.session.save(function(){
+ res.end(data, encoding);
+ });
+ } else {
+ res.end(data, encoding);
+ }
+ };
+
+ // session hashing
+ function hash(base) {
+ return store.hash(req, base);
+ }
+
+ // generate the session
+ function generate() {
+ store.generate(req);
+ }
+
+ // get the sessionID from the cookie
+ req.sessionID = req.cookies[key];
+
+ // make a new session if the browser doesn't send a sessionID
+ if (!req.sessionID) {
+ generate();
+ next();
+ return;
+ }
+
+ // check the fingerprint
+ var parts = req.sessionID.split('.');
+ if (parts[1] != hash(parts[0])) {
+ generate();
+ next();
+ return;
+ }
+
+ // generate the session object
+ var pause = utils.pause(req);
+ store.get(req.sessionID, function(err, sess){
+ // proxy to resume() events
+ var _next = next;
+ next = function(err){
+ _next(err);
+ pause.resume();
+ }
+
+ // error handling
+ if (err) {
+ if ('ENOENT' == err.code) {
+ generate();
+ next();
+ } else {
+ next(err);
+ }
+ // no session
+ } else if (!sess) {
+ generate();
+ next();
+ // populate req.session
+ } else {
+ store.createSession(req, sess);
+ next();
+ }
+ });
+ };
+};
diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js b/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js
new file mode 100644
index 0000000..793c2e9
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js
@@ -0,0 +1,126 @@
+
+/*!
+ * Connect - session - Cookie
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../../utils');
+
+/**
+ * Initialize a new `Cookie` with the given `options`.
+ *
+ * @param {Object} options
+ * @api private
+ */
+
+var Cookie = module.exports = function Cookie(options) {
+ this.path = '/';
+ this.httpOnly = true;
+ this.maxAge = 14400000;
+ if (options) utils.merge(this, options);
+ this.originalMaxAge = undefined == this.originalMaxAge
+ ? this.maxAge
+ : this.originalMaxAge;
+};
+
+/**
+ * Prototype.
+ */
+
+Cookie.prototype = {
+
+ /**
+ * Set expires `date`.
+ *
+ * @param {Date} date
+ * @api public
+ */
+
+ set expires(date) {
+ this._expires = date;
+ this.originalMaxAge = this.maxAge;
+ },
+
+ /**
+ * Get expires `date`.
+ *
+ * @return {Date}
+ * @api public
+ */
+
+ get expires() {
+ return this._expires;
+ },
+
+ /**
+ * Set expires via max-age in `ms`.
+ *
+ * @param {Number} ms
+ * @api public
+ */
+
+ set maxAge(ms) {
+ this.expires = 'number' == typeof ms
+ ? new Date(Date.now() + ms)
+ : ms;
+ },
+
+ /**
+ * Get expires max-age in `ms`.
+ *
+ * @return {Number}
+ * @api public
+ */
+
+ get maxAge() {
+ return this.expires instanceof Date
+ ? this.expires.valueOf() - Date.now()
+ : this.expires;
+ },
+
+ /**
+ * Return cookie data object.
+ *
+ * @return {Object}
+ * @api private
+ */
+
+ get data() {
+ return {
+ originalMaxAge: this.originalMaxAge
+ , expires: this._expires
+ , secure: this.secure
+ , httpOnly: this.httpOnly
+ , domain: this.domain
+ , path: this.path
+ }
+ },
+
+ /**
+ * Return a serialized cookie string.
+ *
+ * @return {String}
+ * @api public
+ */
+
+ serialize: function(name, val){
+ return utils.serializeCookie(name, val, this.data);
+ },
+
+ /**
+ * Return JSON representation of this cookie.
+ *
+ * @return {Object}
+ * @api private
+ */
+
+ toJSON: function(){
+ return this.data;
+ }
+};
diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/memory.js b/node_modules/express/node_modules/connect/lib/middleware/session/memory.js
new file mode 100644
index 0000000..ec569f5
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/session/memory.js
@@ -0,0 +1,131 @@
+
+/*!
+ * Connect - session - MemoryStore
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Store = require('./store')
+ , utils = require('../../utils')
+ , Session = require('./session');
+
+/**
+ * Initialize a new `MemoryStore`.
+ *
+ * @api public
+ */
+
+var MemoryStore = module.exports = function MemoryStore() {
+ this.sessions = {};
+};
+
+/**
+ * Inherit from `Store.prototype`.
+ */
+
+MemoryStore.prototype.__proto__ = Store.prototype;
+
+/**
+ * Attempt to fetch session by the given `sid`.
+ *
+ * @param {String} sid
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.get = function(sid, fn){
+ var self = this;
+ process.nextTick(function(){
+ var expires
+ , sess = self.sessions[sid];
+ if (sess) {
+ sess = JSON.parse(sess);
+ expires = 'string' == typeof sess.cookie.expires
+ ? new Date(sess.cookie.expires)
+ : sess.cookie.expires;
+ if (!expires || new Date < expires) {
+ fn(null, sess);
+ } else {
+ self.destroy(sid, fn);
+ }
+ } else {
+ fn();
+ }
+ });
+};
+
+/**
+ * Commit the given `sess` object associated with the given `sid`.
+ *
+ * @param {String} sid
+ * @param {Session} sess
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.set = function(sid, sess, fn){
+ var self = this;
+ process.nextTick(function(){
+ self.sessions[sid] = JSON.stringify(sess);
+ fn && fn();
+ });
+};
+
+/**
+ * Destroy the session associated with the given `sid`.
+ *
+ * @param {String} sid
+ * @api public
+ */
+
+MemoryStore.prototype.destroy = function(sid, fn){
+ var self = this;
+ process.nextTick(function(){
+ delete self.sessions[sid];
+ fn && fn();
+ });
+};
+
+/**
+ * Invoke the given callback `fn` with all active sessions.
+ *
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.all = function(fn){
+ var arr = []
+ , keys = Object.keys(this.sessions);
+ for (var i = 0, len = keys.length; i < len; ++i) {
+ arr.push(this.sessions[keys[i]]);
+ }
+ fn(null, arr);
+};
+
+/**
+ * Clear all sessions.
+ *
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.clear = function(fn){
+ this.sessions = {};
+ fn && fn();
+};
+
+/**
+ * Fetch number of sessions.
+ *
+ * @param {Function} fn
+ * @api public
+ */
+
+MemoryStore.prototype.length = function(fn){
+ fn(null, Object.keys(this.sessions).length);
+};
diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/session.js b/node_modules/express/node_modules/connect/lib/middleware/session/session.js
new file mode 100644
index 0000000..4e7e1a6
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/session/session.js
@@ -0,0 +1,137 @@
+
+/*!
+ * Connect - session - Session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../../utils')
+ , Cookie = require('./cookie');
+
+/**
+ * Create a new `Session` with the given request and `data`.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} data
+ * @api private
+ */
+
+var Session = module.exports = function Session(req, data) {
+ Object.defineProperty(this, 'req', { value: req });
+ Object.defineProperty(this, 'id', { value: req.sessionID });
+ if ('object' == typeof data) {
+ utils.merge(this, data);
+ } else {
+ this.lastAccess = Date.now();
+ }
+};
+
+/**
+ * Update `.lastAccess` timestamp,
+ * and reset `.cookie.maxAge` to prevent
+ * the cookie from expiring when the
+ * session is still active.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.touch = function(){
+ return this
+ .resetLastAccess()
+ .resetMaxAge();
+};
+
+/**
+ * Update `.lastAccess` timestamp.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.resetLastAccess = function(){
+ this.lastAccess = Date.now();
+ return this;
+};
+
+/**
+ * Reset `.maxAge` to `.originalMaxAge`.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.resetMaxAge = function(){
+ this.cookie.maxAge = this.cookie.originalMaxAge;
+ return this;
+};
+
+/**
+ * Save the session data with optional callback `fn(err)`.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.save = function(fn){
+ this.req.sessionStore.set(this.id, this, fn || function(){});
+ return this;
+};
+
+/**
+ * Re-loads the session data _without_ altering
+ * the maxAge or lastAccess properties. Invokes the
+ * callback `fn(err)`, after which time if no exception
+ * has occurred the `req.session` property will be
+ * a new `Session` object, although representing the
+ * same session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.reload = function(fn){
+ var req = this.req
+ , store = this.req.sessionStore;
+ store.get(this.id, function(err, sess){
+ if (err) return fn(err);
+ if (!sess) return fn(new Error('failed to load session'));
+ store.createSession(req, sess);
+ fn();
+ });
+ return this;
+};
+
+/**
+ * Destroy `this` session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.destroy = function(fn){
+ delete this.req.session;
+ this.req.sessionStore.destroy(this.id, fn);
+ return this;
+};
+
+/**
+ * Regenerate this request's session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+Session.prototype.regenerate = function(fn){
+ this.req.sessionStore.regenerate(this.req, fn);
+ return this;
+};
diff --git a/node_modules/express/node_modules/connect/lib/middleware/session/store.js b/node_modules/express/node_modules/connect/lib/middleware/session/store.js
new file mode 100644
index 0000000..6a3d47d
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/session/store.js
@@ -0,0 +1,87 @@
+
+/*!
+ * Connect - session - Store
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter
+ , Session = require('./session')
+ , Cookie = require('./cookie')
+ , utils = require('../../utils');
+
+/**
+ * Initialize abstract `Store`.
+ *
+ * @api private
+ */
+
+var Store = module.exports = function Store(options){};
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+Store.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Re-generate the given requests's session.
+ *
+ * @param {IncomingRequest} req
+ * @return {Function} fn
+ * @api public
+ */
+
+Store.prototype.regenerate = function(req, fn){
+ var self = this;
+ this.destroy(req.sessionID, function(err){
+ self.generate(req);
+ fn(err);
+ });
+};
+
+/**
+ * Load a `Session` instance via the given `sid`
+ * and invoke the callback `fn(err, sess)`.
+ *
+ * @param {String} sid
+ * @param {Function} fn
+ * @api public
+ */
+
+Store.prototype.load = function(sid, fn){
+ var self = this;
+ this.get(sid, function(err, sess){
+ if (err) return fn(err);
+ if (!sess) return fn();
+ var req = { sessionID: sid, sessionStore: self };
+ sess = self.createSession(req, sess, false);
+ fn(null, sess);
+ });
+};
+
+/**
+ * Create session from JSON `sess` data.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} sess
+ * @return {Session}
+ * @api private
+ */
+
+Store.prototype.createSession = function(req, sess, update){
+ var expires = sess.cookie.expires
+ , orig = sess.cookie.originalMaxAge
+ , update = null == update ? true : false;
+ sess.cookie = new Cookie(sess.cookie);
+ if ('string' == typeof expires) sess.cookie.expires = new Date(expires);
+ sess.cookie.originalMaxAge = orig;
+ req.session = new Session(req, sess);
+ if (update) req.session.resetLastAccess();
+ return req.session;
+}; \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/static.js b/node_modules/express/node_modules/connect/lib/middleware/static.js
new file mode 100644
index 0000000..b9c2c86
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/static.js
@@ -0,0 +1,225 @@
+
+/*!
+ * Connect - staticProvider
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+ , path = require('path')
+ , join = path.join
+ , basename = path.basename
+ , normalize = path.normalize
+ , utils = require('../utils')
+ , Buffer = require('buffer').Buffer
+ , parse = require('url').parse
+ , mime = require('mime');
+
+/**
+ * Static file server with the given `root` path.
+ *
+ * Examples:
+ *
+ * var oneDay = 86400000;
+ *
+ * connect(
+ * connect.static(__dirname + '/public')
+ * ).listen(3000);
+ *
+ * connect(
+ * connect.static(__dirname + '/public', { maxAge: oneDay })
+ * ).listen(3000);
+ *
+ * Options:
+ *
+ * - `maxAge` Browser cache maxAge in milliseconds. defaults to 0
+ * - `hidden` Allow transfer of hidden files. defaults to false
+ * - `redirect` Redirect to trailing "/" when the pathname is a dir
+ *
+ * @param {String} root
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function static(root, options){
+ options = options || {};
+
+ // root required
+ if (!root) throw new Error('static() root path required');
+ options.root = root;
+
+ return function static(req, res, next) {
+ options.path = req.url;
+ options.getOnly = true;
+ send(req, res, next, options);
+ };
+};
+
+/**
+ * Expose mime module.
+ */
+
+exports.mime = mime;
+
+/**
+ * Respond with 416 "Requested Range Not Satisfiable"
+ *
+ * @param {ServerResponse} res
+ * @api private
+ */
+
+function invalidRange(res) {
+ var body = 'Requested Range Not Satisfiable';
+ res.setHeader('Content-Type', 'text/plain');
+ res.setHeader('Content-Length', body.length);
+ res.statusCode = 416;
+ res.end(body);
+}
+
+/**
+ * Attempt to tranfer the requseted file to `res`.
+ *
+ * @param {ServerRequest}
+ * @param {ServerResponse}
+ * @param {Function} next
+ * @param {Object} options
+ * @api private
+ */
+
+var send = exports.send = function(req, res, next, options){
+ options = options || {};
+ if (!options.path) throw new Error('path required');
+
+ // setup
+ var maxAge = options.maxAge || 0
+ , ranges = req.headers.range
+ , head = 'HEAD' == req.method
+ , get = 'GET' == req.method
+ , root = options.root ? normalize(options.root) : null
+ , redirect = false === options.redirect ? false : true
+ , getOnly = options.getOnly
+ , fn = options.callback
+ , hidden = options.hidden
+ , done;
+
+ // replace next() with callback when available
+ if (fn) next = fn;
+
+ // ignore non-GET requests
+ if (getOnly && !get && !head) return next();
+
+ // parse url
+ var url = parse(options.path)
+ , path = decodeURIComponent(url.pathname)
+ , type;
+
+ // null byte(s)
+ if (~path.indexOf('\0')) return utils.badRequest(res);
+
+ // when root is not given, consider .. malicious
+ if (!root && ~path.indexOf('..')) return utils.forbidden(res);
+
+ // join / normalize from optional root dir
+ path = normalize(join(root, path));
+
+ // malicious path
+ if (root && 0 != path.indexOf(root)) return fn
+ ? fn(new Error('Forbidden'))
+ : utils.forbidden(res);
+
+ // index.html support
+ if (normalize('/') == path[path.length - 1]) path += 'index.html';
+
+ // "hidden" file
+ if (!hidden && '.' == basename(path)[0]) return next();
+
+ fs.stat(path, function(err, stat){
+ // mime type
+ type = mime.lookup(path);
+
+ // ignore ENOENT
+ if (err) {
+ if (fn) return fn(err);
+ return 'ENOENT' == err.code
+ ? next()
+ : next(err);
+ // redirect directory in case index.html is present
+ } else if (stat.isDirectory()) {
+ if (!redirect) return next();
+ res.statusCode = 301;
+ res.setHeader('Location', url.pathname + '/');
+ res.end('Redirecting to ' + url.pathname + '/');
+ return;
+ }
+
+ // header fields
+ if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString());
+ if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000));
+ if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
+ if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat));
+ if (!res.getHeader('content-type')) {
+ var charset = mime.charsets.lookup(type);
+ res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
+ }
+ res.setHeader('Accept-Ranges', 'bytes');
+
+ // conditional GET support
+ if (utils.conditionalGET(req)) {
+ if (!utils.modified(req, res)) {
+ req.emit('static');
+ return utils.notModified(res);
+ }
+ }
+
+ var opts = {};
+ var chunkSize = stat.size;
+
+ // we have a Range request
+ if (ranges) {
+ ranges = utils.parseRange(stat.size, ranges);
+ // valid
+ if (ranges) {
+ // TODO: stream options
+ // TODO: multiple support
+ opts.start = ranges[0].start;
+ opts.end = ranges[0].end;
+ chunkSize = opts.end - opts.start + 1;
+ res.statusCode = 206;
+ res.setHeader('Content-Range', 'bytes '
+ + opts.start
+ + '-'
+ + opts.end
+ + '/'
+ + stat.size);
+ // invalid
+ } else {
+ return fn
+ ? fn(new Error('Requested Range Not Satisfiable'))
+ : invalidRange(res);
+ }
+ }
+
+ res.setHeader('Content-Length', chunkSize);
+
+ // transfer
+ if (head) return res.end();
+
+ // stream
+ var stream = fs.createReadStream(path, opts);
+ req.emit('static', stream);
+ stream.pipe(res);
+
+ // callback
+ if (fn) {
+ function callback(err) { done || fn(err); done = true }
+ req.on('close', callback);
+ stream.on('end', callback);
+ }
+ });
+};
diff --git a/node_modules/express/node_modules/connect/lib/middleware/staticCache.js b/node_modules/express/node_modules/connect/lib/middleware/staticCache.js
new file mode 100644
index 0000000..9ea8eb7
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/staticCache.js
@@ -0,0 +1,175 @@
+
+/*!
+ * Connect - staticCache
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+ , utils = require('../utils')
+ , Cache = require('../cache')
+ , url = require('url')
+ , fs = require('fs');
+
+/**
+ * Enables a memory cache layer on top of
+ * the `static()` middleware, serving popular
+ * static files.
+ *
+ * By default a maximum of 128 objects are
+ * held in cache, with a max of 256k each,
+ * totalling ~32mb.
+ *
+ * A Least-Recently-Used (LRU) cache algo
+ * is implemented through the `Cache` object,
+ * simply rotating cache objects as they are
+ * hit. This means that increasingly popular
+ * objects maintain their positions while
+ * others get shoved out of the stack and
+ * garbage collected.
+ *
+ * Benchmarks:
+ *
+ * static(): 2700 rps
+ * node-static: 5300 rps
+ * static() + staticCache(): 7500 rps
+ *
+ * Options:
+ *
+ * - `maxObjects` max cache objects [128]
+ * - `maxLength` max cache object length 256kb
+ *
+ * @param {Type} name
+ * @return {Type}
+ * @api public
+ */
+
+module.exports = function staticCache(options){
+ var options = options || {}
+ , cache = new Cache(options.maxObjects || 128)
+ , maxlen = options.maxLength || 1024 * 256;
+
+ return function staticCache(req, res, next){
+ var path = url.parse(req.url).pathname
+ , ranges = req.headers.range
+ , hit = cache.get(path)
+ , hitCC
+ , uaCC
+ , header
+ , age;
+
+ // cache static
+ req.on('static', function(stream){
+ var headers = res._headers
+ , cc = utils.parseCacheControl(headers['cache-control'] || '')
+ , contentLength = headers['content-length']
+ , hit;
+
+ // ignore larger files
+ if (!contentLength || contentLength > maxlen) return;
+
+ // dont cache items we shouldn't be
+ if ( cc['no-cache']
+ || cc['no-store']
+ || cc['private']
+ || cc['must-revalidate']) return;
+
+ // if already in cache then validate
+ if (hit = cache.get(path)){
+ if (headers.etag == hit[0].etag) {
+ hit[0].date = new Date;
+ return;
+ } else {
+ cache.remove(path);
+ }
+ }
+
+ // validation notifiactions don't contain a steam
+ if (null == stream) return;
+
+ // add the cache object
+ var arr = cache.add(path);
+ arr.push(headers);
+
+ // store the chunks
+ stream.on('data', function(chunk){
+ arr.push(chunk);
+ });
+
+ // flag it as complete
+ stream.on('end', function(){
+ arr.complete = true;
+ });
+ });
+
+ // cache hit, doesnt support range requests
+ if (hit && hit.complete && !ranges) {
+ header = utils.merge({}, hit[0]);
+ header.Age = age = (new Date - new Date(header.date)) / 1000 | 0;
+ header.date = new Date().toUTCString();
+
+ // parse cache-controls
+ hitCC = utils.parseCacheControl(header['cache-control'] || '');
+ uaCC = utils.parseCacheControl(req.headers['cache-control'] || '');
+
+ // check if we must revalidate(bypass)
+ if (hitCC['no-cache'] || uaCC['no-cache']) return next();
+
+ // check freshness of entity
+ if (isStale(hitCC, age) || isStale(uaCC, age)) return next();
+
+ // conditional GET support
+ if (utils.conditionalGET(req)) {
+ if (!utils.modified(req, res, header)) {
+ header['content-length'] = 0;
+ res.writeHead(304, header);
+ return res.end();
+ }
+ }
+
+ // HEAD support
+ if ('HEAD' == req.method) {
+ header['content-length'] = 0;
+ res.writeHead(200, header);
+ return res.end();
+ }
+
+ // respond with cache
+ res.writeHead(200, header);
+
+ // backpressure
+ function write(i) {
+ var buf = hit[i];
+ if (!buf) return res.end();
+ if (false === res.write(buf)) {
+ res.once('drain', function(){
+ write(++i);
+ });
+ } else {
+ write(++i);
+ }
+ }
+
+ return write(1);
+ }
+
+ next();
+ }
+};
+
+/**
+ * Check if cache item is stale
+ *
+ * @param {Object} cc
+ * @param {Number} age
+ * @return {Boolean}
+ * @api private
+ */
+
+function isStale(cc, age) {
+ return cc['max-age'] && cc['max-age'] <= age;
+} \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/middleware/vhost.js b/node_modules/express/node_modules/connect/lib/middleware/vhost.js
new file mode 100644
index 0000000..913d756
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/middleware/vhost.js
@@ -0,0 +1,44 @@
+
+/*!
+ * Connect - vhost
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Setup vhost for the given `hostname` and `server`.
+ *
+ * Examples:
+ *
+ * connect(
+ * connect.vhost('foo.com',
+ * connect.createServer(...middleware...)
+ * ),
+ * connect.vhost('bar.com',
+ * connect.createServer(...middleware...)
+ * )
+ * );
+ *
+ * @param {String} hostname
+ * @param {Server} server
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function vhost(hostname, server){
+ if (!hostname) throw new Error('vhost hostname required');
+ if (!server) throw new Error('vhost server required');
+ var regexp = new RegExp('^' + hostname.replace(/[*]/g, '(.*?)') + '$');
+ if (server.onvhost) server.onvhost(hostname);
+ return function vhost(req, res, next){
+ if (!req.headers.host) return next();
+ var host = req.headers.host.split(':')[0];
+ if (req.subdomains = regexp.exec(host)) {
+ req.subdomains = req.subdomains[0].split('.').slice(0, -1);
+ server.emit("request", req, res);
+ } else {
+ next();
+ }
+ };
+};
diff --git a/node_modules/express/node_modules/connect/lib/patch.js b/node_modules/express/node_modules/connect/lib/patch.js
new file mode 100644
index 0000000..a6ff297
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/patch.js
@@ -0,0 +1,79 @@
+
+/*!
+ * Connect
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+ , res = http.OutgoingMessage.prototype;
+
+// original setHeader()
+
+var setHeader = res.setHeader;
+
+// original _renderHeaders()
+
+var _renderHeaders = res._renderHeaders;
+
+if (res._hasConnectPatch) return;
+
+/**
+ * Provide a public "header sent" flag
+ * until node does.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+res.__defineGetter__('headerSent', function(){
+ return this._headerSent;
+});
+
+/**
+ * Set header `field` to `val`, special-casing
+ * the `Set-Cookie` field for multiple support.
+ *
+ * @param {String} field
+ * @param {String} val
+ * @api public
+ */
+
+res.setHeader = function(field, val){
+ var key = field.toLowerCase()
+ , prev;
+
+ // special-case Set-Cookie
+ if (this._headers && 'set-cookie' == key) {
+ if (prev = this.getHeader(field)) {
+ val = Array.isArray(prev)
+ ? prev.concat(val)
+ : [prev, val];
+ }
+ // charset
+ } else if ('content-type' == key && this.charset) {
+ val += '; charset=' + this.charset;
+ }
+
+ return setHeader.call(this, field, val);
+};
+
+/**
+ * Proxy `res.end()` to expose a 'header' event,
+ * allowing arbitrary augmentation before the header
+ * fields are written to the socket.
+ *
+ * NOTE: this _only_ supports node's progressive header
+ * field API aka `res.setHeader()`.
+ */
+
+res._renderHeaders = function(){
+ this.emit('header');
+ return _renderHeaders.call(this);
+};
+
+res._hasConnectPatch = true;
diff --git a/node_modules/express/node_modules/connect/lib/public/directory.html b/node_modules/express/node_modules/connect/lib/public/directory.html
new file mode 100644
index 0000000..15164bb
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/public/directory.html
@@ -0,0 +1,75 @@
+<html>
+ <head>
+ <title>listing directory {directory}</title>
+ <style>{style}</style>
+ <script>
+ function $(id){
+ var el = 'string' == typeof id
+ ? document.getElementById(id)
+ : id;
+
+ el.on = function(event, fn){
+ if ('content loaded' == event) event = 'DOMContentLoaded';
+ el.addEventListener(event, fn, false);
+ };
+
+ el.all = function(selector){
+ return $(el.querySelectorAll(selector));
+ };
+
+ el.each = function(fn){
+ for (var i = 0, len = el.length; i < len; ++i) {
+ fn($(el[i]), i);
+ }
+ };
+
+ el.getClasses = function(){
+ return this.getAttribute('class').split(/\s+/);
+ };
+
+ el.addClass = function(name){
+ var classes = this.getAttribute('class');
+ el.setAttribute('class', classes
+ ? classes + ' ' + name
+ : name);
+ };
+
+ el.removeClass = function(name){
+ var classes = this.getClasses().filter(function(curr){
+ return curr != name;
+ });
+ this.setAttribute('class', classes);
+ };
+
+ return el;
+ }
+
+ function search() {
+ var str = $('search').value
+ , links = $('files').all('a');
+
+ links.each(function(link){
+ var text = link.textContent;
+
+ if ('..' == text) return;
+ if (str.length && ~text.indexOf(str)) {
+ link.addClass('highlight');
+ } else {
+ link.removeClass('highlight');
+ }
+ });
+ }
+
+ $(window).on('content loaded', function(){
+ $('search').on('keyup', search);
+ });
+ </script>
+ </head>
+ <body class="directory">
+ <input id="search" type="text" placeholder="Search" autocomplete="off" />
+ <div id="wrapper">
+ <h1>{linked-path}</h1>
+ {files}
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/public/error.html b/node_modules/express/node_modules/connect/lib/public/error.html
new file mode 100644
index 0000000..34e0df5
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/public/error.html
@@ -0,0 +1,13 @@
+<html>
+ <head>
+ <title>{error}</title>
+ <style>{style}</style>
+ </head>
+ <body>
+ <div id="wrapper">
+ <h1>{title}</h1>
+ <h2><em>500</em> {error}</h2>
+ <ul id="stacktrace">{stack}</ul>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/lib/public/favicon.ico b/node_modules/express/node_modules/connect/lib/public/favicon.ico
new file mode 100644
index 0000000..895fc96
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/public/favicon.ico
Binary files differ
diff --git a/node_modules/express/node_modules/connect/lib/public/style.css b/node_modules/express/node_modules/connect/lib/public/style.css
new file mode 100644
index 0000000..32b6507
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/public/style.css
@@ -0,0 +1,141 @@
+body {
+ margin: 0;
+ padding: 80px 100px;
+ font: 13px "Helvetica Neue", "Lucida Grande", "Arial";
+ background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9));
+ background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9);
+ background-repeat: no-repeat;
+ color: #555;
+ -webkit-font-smoothing: antialiased;
+}
+h1, h2, h3 {
+ margin: 0;
+ font-size: 22px;
+ color: #343434;
+}
+h1 em, h2 em {
+ padding: 0 5px;
+ font-weight: normal;
+}
+h1 {
+ font-size: 60px;
+}
+h2 {
+ margin-top: 10px;
+}
+h3 {
+ margin: 5px 0 10px 0;
+ padding-bottom: 5px;
+ border-bottom: 1px solid #eee;
+ font-size: 18px;
+}
+ul {
+ margin: 0;
+ padding: 0;
+}
+ul li {
+ margin: 5px 0;
+ padding: 3px 8px;
+ list-style: none;
+}
+ul li:hover {
+ cursor: pointer;
+ color: #2e2e2e;
+}
+ul li .path {
+ padding-left: 5px;
+ font-weight: bold;
+}
+ul li .line {
+ padding-right: 5px;
+ font-style: italic;
+}
+ul li:first-child .path {
+ padding-left: 0;
+}
+p {
+ line-height: 1.5;
+}
+a {
+ color: #555;
+ text-decoration: none;
+}
+a:hover {
+ color: #303030;
+}
+#stacktrace {
+ margin-top: 15px;
+}
+.directory h1 {
+ margin-bottom: 15px;
+ font-size: 18px;
+}
+ul#files {
+ width: 100%;
+ height: 500px;
+}
+ul#files li {
+ padding: 0;
+}
+ul#files li img {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+}
+ul#files li a {
+ position: relative;
+ display: block;
+ margin: 1px;
+ width: 30%;
+ height: 25px;
+ line-height: 25px;
+ text-indent: 8px;
+ float: left;
+ border: 1px solid transparent;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+ul#files li a.icon {
+ text-indent: 25px;
+}
+ul#files li a:focus,
+ul#files li a:hover {
+ outline: none;
+ background: rgba(255,255,255,0.65);
+ border: 1px solid #ececec;
+}
+ul#files li a.highlight {
+ -webkit-transition: background .4s ease-in-out;
+ background: #ffff4f;
+ border-color: #E9DC51;
+}
+#search {
+ display: block;
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ width: 90px;
+ -webkit-transition: width ease 0.2s, opacity ease 0.4s;
+ -moz-transition: width ease 0.2s, opacity ease 0.4s;
+ -webkit-border-radius: 32px;
+ -moz-border-radius: 32px;
+ -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03);
+ -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03);
+ -webkit-font-smoothing: antialiased;
+ text-align: left;
+ font: 13px "Helvetica Neue", Arial, sans-serif;
+ padding: 4px 10px;
+ border: none;
+ background: transparent;
+ margin-bottom: 0;
+ outline: none;
+ opacity: 0.7;
+ color: #888;
+}
+#search:focus {
+ width: 120px;
+ opacity: 1.0;
+}
diff --git a/node_modules/express/node_modules/connect/lib/utils.js b/node_modules/express/node_modules/connect/lib/utils.js
new file mode 100644
index 0000000..d0bc172
--- /dev/null
+++ b/node_modules/express/node_modules/connect/lib/utils.js
@@ -0,0 +1,451 @@
+
+/*!
+ * Connect - utils
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var crypto = require('crypto')
+ , Path = require('path')
+ , fs = require('fs');
+
+/**
+ * Flatten the given `arr`.
+ *
+ * @param {Array} arr
+ * @return {Array}
+ * @api private
+ */
+
+exports.flatten = function(arr, ret){
+ var ret = ret || []
+ , len = arr.length;
+ for (var i = 0; i < len; ++i) {
+ if (Array.isArray(arr[i])) {
+ exports.flatten(arr[i], ret);
+ } else {
+ ret.push(arr[i]);
+ }
+ }
+ return ret;
+};
+
+/**
+ * Return md5 hash of the given string and optional encoding,
+ * defaulting to hex.
+ *
+ * utils.md5('wahoo');
+ * // => "e493298061761236c96b02ea6aa8a2ad"
+ *
+ * @param {String} str
+ * @param {String} encoding
+ * @return {String}
+ * @api public
+ */
+
+exports.md5 = function(str, encoding){
+ return crypto
+ .createHash('md5')
+ .update(str)
+ .digest(encoding || 'hex');
+};
+
+/**
+ * Merge object b with object a.
+ *
+ * var a = { foo: 'bar' }
+ * , b = { bar: 'baz' };
+ *
+ * utils.merge(a, b);
+ * // => { foo: 'bar', bar: 'baz' }
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Object}
+ * @api public
+ */
+
+exports.merge = function(a, b){
+ if (a && b) {
+ for (var key in b) {
+ a[key] = b[key];
+ }
+ }
+ return a;
+};
+
+/**
+ * Escape the given string of `html`.
+ *
+ * @param {String} html
+ * @return {String}
+ * @api public
+ */
+
+exports.escape = function(html){
+ return String(html)
+ .replace(/&(?!\w+;)/g, '&amp;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;')
+ .replace(/"/g, '&quot;');
+};
+
+
+/**
+ * Return a unique identifier with the given `len`.
+ *
+ * utils.uid(10);
+ * // => "FDaS435D2z"
+ *
+ * @param {Number} len
+ * @return {String}
+ * @api public
+ */
+
+exports.uid = function(len) {
+ var buf = []
+ , chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
+ , charlen = chars.length;
+
+ for (var i = 0; i < len; ++i) {
+ buf.push(chars[getRandomInt(0, charlen - 1)]);
+ }
+
+ return buf.join('');
+};
+
+/**
+ * Parse the given cookie string into an object.
+ *
+ * @param {String} str
+ * @return {Object}
+ * @api public
+ */
+
+exports.parseCookie = function(str){
+ var obj = {}
+ , pairs = str.split(/[;,] */);
+ for (var i = 0, len = pairs.length; i < len; ++i) {
+ var pair = pairs[i]
+ , eqlIndex = pair.indexOf('=')
+ , key = pair.substr(0, eqlIndex).trim().toLowerCase()
+ , val = pair.substr(++eqlIndex, pair.length).trim();
+
+ // quoted values
+ if ('"' == val[0]) val = val.slice(1, -1);
+
+ // only assign once
+ if (undefined == obj[key]) {
+ val = val.replace(/\+/g, ' ');
+ try {
+ obj[key] = decodeURIComponent(val);
+ } catch (err) {
+ if (err instanceof URIError) {
+ obj[key] = val;
+ } else {
+ throw err;
+ }
+ }
+ }
+ }
+ return obj;
+};
+
+/**
+ * Serialize the given object into a cookie string.
+ *
+ * utils.serializeCookie('name', 'tj', { httpOnly: true })
+ * // => "name=tj; httpOnly"
+ *
+ * @param {String} name
+ * @param {String} val
+ * @param {Object} obj
+ * @return {String}
+ * @api public
+ */
+
+exports.serializeCookie = function(name, val, obj){
+ var pairs = [name + '=' + encodeURIComponent(val)]
+ , obj = obj || {};
+
+ if (obj.domain) pairs.push('domain=' + obj.domain);
+ if (obj.path) pairs.push('path=' + obj.path);
+ if (obj.expires) pairs.push('expires=' + obj.expires.toUTCString());
+ if (obj.httpOnly) pairs.push('httpOnly');
+ if (obj.secure) pairs.push('secure');
+
+ return pairs.join('; ');
+};
+
+/**
+ * Pause `data` and `end` events on the given `obj`.
+ * Middleware performing async tasks _should_ utilize
+ * this utility (or similar), to re-emit data once
+ * the async operation has completed, otherwise these
+ * events may be lost.
+ *
+ * var pause = utils.pause(req);
+ * fs.readFile(path, function(){
+ * next();
+ * pause.resume();
+ * });
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api public
+ */
+
+exports.pause = function(obj){
+ var onData
+ , onEnd
+ , events = [];
+
+ // buffer data
+ obj.on('data', onData = function(data, encoding){
+ events.push(['data', data, encoding]);
+ });
+
+ // buffer end
+ obj.on('end', onEnd = function(data, encoding){
+ events.push(['end', data, encoding]);
+ });
+
+ return {
+ end: function(){
+ obj.removeListener('data', onData);
+ obj.removeListener('end', onEnd);
+ },
+ resume: function(){
+ this.end();
+ for (var i = 0, len = events.length; i < len; ++i) {
+ obj.emit.apply(obj, events[i]);
+ }
+ }
+ };
+};
+
+/**
+ * Check `req` and `res` to see if it has been modified.
+ *
+ * @param {IncomingMessage} req
+ * @param {ServerResponse} res
+ * @return {Boolean}
+ * @api public
+ */
+
+exports.modified = function(req, res, headers) {
+ var headers = headers || res._headers || {}
+ , modifiedSince = req.headers['if-modified-since']
+ , lastModified = headers['last-modified']
+ , noneMatch = req.headers['if-none-match']
+ , etag = headers['etag'];
+
+ if (noneMatch) noneMatch = noneMatch.split(/ *, */);
+
+ // check If-None-Match
+ if (noneMatch && etag && ~noneMatch.indexOf(etag)) {
+ return false;
+ }
+
+ // check If-Modified-Since
+ if (modifiedSince && lastModified) {
+ modifiedSince = new Date(modifiedSince);
+ lastModified = new Date(lastModified);
+ // Ignore invalid dates
+ if (!isNaN(modifiedSince.getTime())) {
+ if (lastModified <= modifiedSince) return false;
+ }
+ }
+
+ return true;
+};
+
+/**
+ * Strip `Content-*` headers from `res`.
+ *
+ * @param {ServerResponse} res
+ * @api public
+ */
+
+exports.removeContentHeaders = function(res){
+ Object.keys(res._headers).forEach(function(field){
+ if (0 == field.indexOf('content')) {
+ res.removeHeader(field);
+ }
+ });
+};
+
+/**
+ * Check if `req` is a conditional GET request.
+ *
+ * @param {IncomingMessage} req
+ * @return {Boolean}
+ * @api public
+ */
+
+exports.conditionalGET = function(req) {
+ return req.headers['if-modified-since']
+ || req.headers['if-none-match'];
+};
+
+/**
+ * Respond with 403 "Forbidden".
+ *
+ * @param {ServerResponse} res
+ * @api public
+ */
+
+exports.forbidden = function(res) {
+ var body = 'Forbidden';
+ res.setHeader('Content-Type', 'text/plain');
+ res.setHeader('Content-Length', body.length);
+ res.statusCode = 403;
+ res.end(body);
+};
+
+/**
+ * Respond with 401 "Unauthorized".
+ *
+ * @param {ServerResponse} res
+ * @param {String} realm
+ * @api public
+ */
+
+exports.unauthorized = function(res, realm) {
+ res.statusCode = 401;
+ res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"');
+ res.end('Unauthorized');
+};
+
+/**
+ * Respond with 400 "Bad Request".
+ *
+ * @param {ServerResponse} res
+ * @api public
+ */
+
+exports.badRequest = function(res) {
+ res.statusCode = 400;
+ res.end('Bad Request');
+};
+
+/**
+ * Respond with 304 "Not Modified".
+ *
+ * @param {ServerResponse} res
+ * @param {Object} headers
+ * @api public
+ */
+
+exports.notModified = function(res) {
+ exports.removeContentHeaders(res);
+ res.statusCode = 304;
+ res.end();
+};
+
+/**
+ * Return an ETag in the form of `"<size>-<mtime>"`
+ * from the given `stat`.
+ *
+ * @param {Object} stat
+ * @return {String}
+ * @api public
+ */
+
+exports.etag = function(stat) {
+ return '"' + stat.size + '-' + Number(stat.mtime) + '"';
+};
+
+/**
+ * Parse "Range" header `str` relative to the given file `size`.
+ *
+ * @param {Number} size
+ * @param {String} str
+ * @return {Array}
+ * @api public
+ */
+
+exports.parseRange = function(size, str){
+ var valid = true;
+ var arr = str.substr(6).split(',').map(function(range){
+ var range = range.split('-')
+ , start = parseInt(range[0], 10)
+ , end = parseInt(range[1], 10);
+
+ // -500
+ if (isNaN(start)) {
+ start = size - end;
+ end = size - 1;
+ // 500-
+ } else if (isNaN(end)) {
+ end = size - 1;
+ }
+
+ // Invalid
+ if (isNaN(start) || isNaN(end) || start > end) valid = false;
+
+ return { start: start, end: end };
+ });
+ return valid ? arr : undefined;
+};
+
+/**
+ * Parse the given Cache-Control `str`.
+ *
+ * @param {String} str
+ * @return {Object}
+ * @api public
+ */
+
+exports.parseCacheControl = function(str){
+ var directives = str.split(',')
+ , obj = {};
+
+ for(var i = 0, len = directives.length; i < len; i++) {
+ var parts = directives[i].split('=')
+ , key = parts.shift().trim()
+ , val = parseInt(parts.shift(), 10);
+
+ obj[key] = isNaN(val) ? true : val;
+ }
+
+ return obj;
+};
+
+
+/**
+ * Convert array-like object to an `Array`.
+ *
+ * node-bench measured "16.5 times faster than Array.prototype.slice.call()"
+ *
+ * @param {Object} obj
+ * @return {Array}
+ * @api public
+ */
+
+var toArray = exports.toArray = function(obj){
+ var len = obj.length
+ , arr = new Array(len);
+ for (var i = 0; i < len; ++i) {
+ arr[i] = obj[i];
+ }
+ return arr;
+};
+
+/**
+ * Retrun a random int, used by `utils.uid()`
+ *
+ * @param {Number} min
+ * @param {Number} max
+ * @return {Number}
+ * @api private
+ */
+
+function getRandomInt(min, max) {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+}
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore b/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore
new file mode 100644
index 0000000..4fbabb3
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore
@@ -0,0 +1,4 @@
+/test/tmp/
+*.upload
+*.un~
+*.http
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml b/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml
new file mode 100644
index 0000000..f1d0f13
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+ - 0.4
+ - 0.6
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/Makefile b/node_modules/express/node_modules/connect/node_modules/formidable/Makefile
new file mode 100644
index 0000000..8945872
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/Makefile
@@ -0,0 +1,14 @@
+SHELL := /bin/bash
+
+test:
+ @./test/run.js
+
+build: npm test
+
+npm:
+ npm install .
+
+clean:
+ rm test/tmp/*
+
+.PHONY: test clean build
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md b/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md
new file mode 100644
index 0000000..cfa2462
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md
@@ -0,0 +1,303 @@
+# Formidable
+
+[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)
+
+## Purpose
+
+A node.js module for parsing form data, especially file uploads.
+
+## Current status
+
+This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading
+and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from
+a large variety of clients and is considered production-ready.
+
+## Features
+
+* Fast (~500mb/sec), non-buffering multipart parser
+* Automatically writing file uploads to disk
+* Low memory footprint
+* Graceful error handling
+* Very high test coverage
+
+## Changelog
+
+### v1.0.9
+
+* Emit progress when content length header parsed (Tim Koschützki)
+* Fix Readme syntax due to GitHub changes (goob)
+* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara)
+
+### v1.0.8
+
+* Strip potentially unsafe characters when using `keepExtensions: true`.
+* Switch to utest / urun for testing
+* Add travis build
+
+### v1.0.7
+
+* Remove file from package that was causing problems when installing on windows. (#102)
+* Fix typos in Readme (Jason Davies).
+
+### v1.0.6
+
+* Do not default to the default to the field name for file uploads where
+ filename="".
+
+### v1.0.5
+
+* Support filename="" in multipart parts
+* Explain unexpected end() errors in parser better
+
+**Note:** Starting with this version, formidable emits 'file' events for empty
+file input fields. Previously those were incorrectly emitted as regular file
+input fields with value = "".
+
+### v1.0.4
+
+* Detect a good default tmp directory regardless of platform. (#88)
+
+### v1.0.3
+
+* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)
+* Small performance improvements
+* New test suite and fixture system
+
+### v1.0.2
+
+* Exclude node\_modules folder from git
+* Implement new `'aborted'` event
+* Fix files in example folder to work with recent node versions
+* Make gently a devDependency
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)
+
+### v1.0.1
+
+* Fix package.json to refer to proper main directory. (#68, Dean Landolt)
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)
+
+### v1.0.0
+
+* Add support for multipart boundaries that are quoted strings. (Jeff Craig)
+
+This marks the beginning of development on version 2.0 which will include
+several architectural improvements.
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)
+
+### v0.9.11
+
+* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki)
+* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class
+
+**Important:** The old property names of the File class will be removed in a
+future release.
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)
+
+### Older releases
+
+These releases were done before starting to maintain the above Changelog:
+
+* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)
+* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)
+* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)
+* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)
+* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)
+* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)
+* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)
+* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)
+* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)
+* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)
+
+## Installation
+
+Via [npm](http://github.com/isaacs/npm):
+
+ npm install formidable@latest
+
+Manually:
+
+ git clone git://github.com/felixge/node-formidable.git formidable
+ vim my.js
+ # var formidable = require('./formidable');
+
+Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.
+
+## Example
+
+Parse an incoming file upload.
+
+ var formidable = require('formidable'),
+ http = require('http'),
+
+ util = require('util');
+
+ http.createServer(function(req, res) {
+ if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
+ // parse a file upload
+ var form = new formidable.IncomingForm();
+ form.parse(req, function(err, fields, files) {
+ res.writeHead(200, {'content-type': 'text/plain'});
+ res.write('received upload:\n\n');
+ res.end(util.inspect({fields: fields, files: files}));
+ });
+ return;
+ }
+
+ // show a file upload form
+ res.writeHead(200, {'content-type': 'text/html'});
+ res.end(
+ '<form action="/upload" enctype="multipart/form-data" method="post">'+
+ '<input type="text" name="title"><br>'+
+ '<input type="file" name="upload" multiple="multiple"><br>'+
+ '<input type="submit" value="Upload">'+
+ '</form>'
+ );
+ }).listen(80);
+
+## API
+
+### formidable.IncomingForm
+
+__new formidable.IncomingForm()__
+
+Creates a new incoming form.
+
+__incomingForm.encoding = 'utf-8'__
+
+The encoding to use for incoming form fields.
+
+__incomingForm.uploadDir = process.env.TMP || '/tmp' || process.cwd()__
+
+The directory for placing file uploads in. You can move them later on using
+`fs.rename()`. The default directory is picked at module load time depending on
+the first existing directory from those listed above.
+
+__incomingForm.keepExtensions = false__
+
+If you want the files written to `incomingForm.uploadDir` to include the extensions of the original files, set this property to `true`.
+
+__incomingForm.type__
+
+Either 'multipart' or 'urlencoded' depending on the incoming request.
+
+__incomingForm.maxFieldsSize = 2 * 1024 * 1024__
+
+Limits the amount of memory a field (not file) can allocate in bytes.
+If this value is exceeded, an `'error'` event is emitted. The default
+size is 2MB.
+
+__incomingForm.bytesReceived__
+
+The amount of bytes received for this form so far.
+
+__incomingForm.bytesExpected__
+
+The expected number of bytes in this form.
+
+__incomingForm.parse(request, [cb])__
+
+Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback:
+
+ incomingForm.parse(req, function(err, fields, files) {
+ // ...
+ });
+
+__incomingForm.onPart(part)__
+
+You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing.
+
+ incomingForm.onPart = function(part) {
+ part.addListener('data', function() {
+ // ...
+ });
+ }
+
+If you want to use formidable to only handle certain parts for you, you can do so:
+
+ incomingForm.onPart = function(part) {
+ if (!part.filename) {
+ // let formidable handle all non-file parts
+ incomingForm.handlePart(part);
+ }
+ }
+
+Check the code in this method for further inspiration.
+
+__Event: 'progress' (bytesReceived, bytesExpected)__
+
+Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.
+
+__Event: 'field' (name, value)__
+
+Emitted whenever a field / value pair has been received.
+
+__Event: 'fileBegin' (name, file)__
+
+Emitted whenever a new file is detected in the upload stream. Use this even if
+you want to stream the file to somewhere else while buffering the upload on
+the file system.
+
+__Event: 'file' (name, file)__
+
+Emitted whenever a field / file pair has been received. `file` is an instance of `File`.
+
+__Event: 'error' (err)__
+
+Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.
+
+__Event: 'aborted'__
+
+Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).
+
+__Event: 'end' ()__
+
+Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.
+
+### formidable.File
+
+__file.size = 0__
+
+The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.
+
+__file.path = null__
+
+The path this file is being written to. You can modify this in the `'fileBegin'` event in
+case you are unhappy with the way formidable generates a temporary path for your files.
+
+__file.name = null__
+
+The name this file had according to the uploading client.
+
+__file.type = null__
+
+The mime type of this file, according to the uploading client.
+
+__file.lastModifiedDate = null__
+
+A date object (or `null`) containing the time this file was last written to. Mostly
+here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
+
+## License
+
+Formidable is licensed under the MIT license.
+
+## Ports
+
+* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable
+
+## Credits
+
+* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/TODO b/node_modules/express/node_modules/connect/node_modules/formidable/TODO
new file mode 100644
index 0000000..e1107f2
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/TODO
@@ -0,0 +1,3 @@
+- Better bufferMaxSize handling approach
+- Add tests for JSON parser pull request and merge it
+- Implement QuerystringParser the same way as MultipartParser
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js
new file mode 100644
index 0000000..bff41f1
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js
@@ -0,0 +1,70 @@
+require('../test/common');
+var multipartParser = require('../lib/multipart_parser'),
+ MultipartParser = multipartParser.MultipartParser,
+ parser = new MultipartParser(),
+ Buffer = require('buffer').Buffer,
+ boundary = '-----------------------------168072824752491622650073',
+ mb = 100,
+ buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+ callbacks =
+ { partBegin: -1,
+ partEnd: -1,
+ headerField: -1,
+ headerValue: -1,
+ partData: -1,
+ end: -1,
+ };
+
+
+parser.initWithBoundary(boundary);
+parser.onHeaderField = function() {
+ callbacks.headerField++;
+};
+
+parser.onHeaderValue = function() {
+ callbacks.headerValue++;
+};
+
+parser.onPartBegin = function() {
+ callbacks.partBegin++;
+};
+
+parser.onPartData = function() {
+ callbacks.partData++;
+};
+
+parser.onPartEnd = function() {
+ callbacks.partEnd++;
+};
+
+parser.onEnd = function() {
+ callbacks.end++;
+};
+
+var start = +new Date(),
+ nparsed = parser.write(buffer),
+ duration = +new Date - start,
+ mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+console.log(mbPerSec+' mb/sec');
+
+assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+ var head =
+ '--'+boundary+'\r\n'
+ + 'content-disposition: form-data; name="field1"\r\n'
+ + '\r\n'
+ , tail = '\r\n--'+boundary+'--\r\n'
+ , buffer = new Buffer(size);
+
+ buffer.write(head, 'ascii', 0);
+ buffer.write(tail, 'ascii', buffer.length - tail.length);
+ return buffer;
+}
+
+process.on('exit', function() {
+ for (var k in callbacks) {
+ assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+ }
+});
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js
new file mode 100644
index 0000000..f6c15a6
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js
@@ -0,0 +1,43 @@
+require('../test/common');
+var http = require('http'),
+ util = require('util'),
+ formidable = require('formidable'),
+ server;
+
+server = http.createServer(function(req, res) {
+ if (req.url == '/') {
+ res.writeHead(200, {'content-type': 'text/html'});
+ res.end(
+ '<form action="/post" method="post">'+
+ '<input type="text" name="title"><br>'+
+ '<input type="text" name="data[foo][]"><br>'+
+ '<input type="submit" value="Submit">'+
+ '</form>'
+ );
+ } else if (req.url == '/post') {
+ var form = new formidable.IncomingForm(),
+ fields = [];
+
+ form
+ .on('error', function(err) {
+ res.writeHead(200, {'content-type': 'text/plain'});
+ res.end('error:\n\n'+util.inspect(err));
+ })
+ .on('field', function(field, value) {
+ console.log(field, value);
+ fields.push([field, value]);
+ })
+ .on('end', function() {
+ console.log('-> post done');
+ res.writeHead(200, {'content-type': 'text/plain'});
+ res.end('received fields:\n\n '+util.inspect(fields));
+ });
+ form.parse(req);
+ } else {
+ res.writeHead(404, {'content-type': 'text/plain'});
+ res.end('404');
+ }
+});
+server.listen(TEST_PORT);
+
+console.log('listening on http://localhost:'+TEST_PORT+'/');
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js b/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js
new file mode 100644
index 0000000..050cdd9
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js
@@ -0,0 +1,48 @@
+require('../test/common');
+var http = require('http'),
+ util = require('util'),
+ formidable = require('formidable'),
+ server;
+
+server = http.createServer(function(req, res) {
+ if (req.url == '/') {
+ res.writeHead(200, {'content-type': 'text/html'});
+ res.end(
+ '<form action="/upload" enctype="multipart/form-data" method="post">'+
+ '<input type="text" name="title"><br>'+
+ '<input type="file" name="upload" multiple="multiple"><br>'+
+ '<input type="submit" value="Upload">'+
+ '</form>'
+ );
+ } else if (req.url == '/upload') {
+ var form = new formidable.IncomingForm(),
+ files = [],
+ fields = [];
+
+ form.uploadDir = TEST_TMP;
+
+ form
+ .on('field', function(field, value) {
+ console.log(field, value);
+ fields.push([field, value]);
+ })
+ .on('file', function(field, file) {
+ console.log(field, file);
+ files.push([field, file]);
+ })
+ .on('end', function() {
+ console.log('-> upload done');
+ res.writeHead(200, {'content-type': 'text/plain'});
+ res.write('received fields:\n\n '+util.inspect(fields));
+ res.write('\n\n');
+ res.end('received files:\n\n '+util.inspect(files));
+ });
+ form.parse(req);
+ } else {
+ res.writeHead(404, {'content-type': 'text/plain'});
+ res.end('404');
+ }
+});
+server.listen(TEST_PORT);
+
+console.log('listening on http://localhost:'+TEST_PORT+'/');
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/index.js
new file mode 100644
index 0000000..be41032
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/index.js
@@ -0,0 +1 @@
+module.exports = require('./lib/formidable'); \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js
new file mode 100644
index 0000000..6dc8720
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js
@@ -0,0 +1,61 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var util = require('./util'),
+ WriteStream = require('fs').WriteStream,
+ EventEmitter = require('events').EventEmitter;
+
+function File(properties) {
+ EventEmitter.call(this);
+
+ this.size = 0;
+ this.path = null;
+ this.name = null;
+ this.type = null;
+ this.lastModifiedDate = null;
+
+ this._writeStream = null;
+
+ for (var key in properties) {
+ this[key] = properties[key];
+ }
+
+ this._backwardsCompatibility();
+}
+module.exports = File;
+util.inherits(File, EventEmitter);
+
+// @todo Next release: Show error messages when accessing these
+File.prototype._backwardsCompatibility = function() {
+ var self = this;
+ this.__defineGetter__('length', function() {
+ return self.size;
+ });
+ this.__defineGetter__('filename', function() {
+ return self.name;
+ });
+ this.__defineGetter__('mime', function() {
+ return self.type;
+ });
+};
+
+File.prototype.open = function() {
+ this._writeStream = new WriteStream(this.path);
+};
+
+File.prototype.write = function(buffer, cb) {
+ var self = this;
+ this._writeStream.write(buffer, function() {
+ self.lastModifiedDate = new Date();
+ self.size += buffer.length;
+ self.emit('progress', self.size);
+ cb();
+ });
+};
+
+File.prototype.end = function(cb) {
+ var self = this;
+ this._writeStream.end(function() {
+ self.emit('end');
+ cb();
+ });
+};
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js
new file mode 100644
index 0000000..b1e2bfb
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js
@@ -0,0 +1,378 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var fs = require('fs');
+var util = require('./util'),
+ path = require('path'),
+ File = require('./file'),
+ MultipartParser = require('./multipart_parser').MultipartParser,
+ QuerystringParser = require('./querystring_parser').QuerystringParser,
+ StringDecoder = require('string_decoder').StringDecoder,
+ EventEmitter = require('events').EventEmitter;
+
+function IncomingForm() {
+ if (!(this instanceof IncomingForm)) return new IncomingForm;
+ EventEmitter.call(this);
+
+ this.error = null;
+ this.ended = false;
+
+ this.maxFieldsSize = 2 * 1024 * 1024;
+ this.keepExtensions = false;
+ this.uploadDir = IncomingForm.UPLOAD_DIR;
+ this.encoding = 'utf-8';
+ this.headers = null;
+ this.type = null;
+
+ this.bytesReceived = null;
+ this.bytesExpected = null;
+
+ this._parser = null;
+ this._flushing = 0;
+ this._fieldsSize = 0;
+};
+util.inherits(IncomingForm, EventEmitter);
+exports.IncomingForm = IncomingForm;
+
+IncomingForm.UPLOAD_DIR = (function() {
+ var dirs = [process.env.TMP, '/tmp', process.cwd()];
+ for (var i = 0; i < dirs.length; i++) {
+ var dir = dirs[i];
+ var isDirectory = false;
+
+ try {
+ isDirectory = fs.statSync(dir).isDirectory();
+ } catch (e) {}
+
+ if (isDirectory) return dir;
+ }
+})();
+
+IncomingForm.prototype.parse = function(req, cb) {
+ this.pause = function() {
+ try {
+ req.pause();
+ } catch (err) {
+ // the stream was destroyed
+ if (!this.ended) {
+ // before it was completed, crash & burn
+ this._error(err);
+ }
+ return false;
+ }
+ return true;
+ };
+
+ this.resume = function() {
+ try {
+ req.resume();
+ } catch (err) {
+ // the stream was destroyed
+ if (!this.ended) {
+ // before it was completed, crash & burn
+ this._error(err);
+ }
+ return false;
+ }
+
+ return true;
+ };
+
+ this.writeHeaders(req.headers);
+
+ var self = this;
+ req
+ .on('error', function(err) {
+ self._error(err);
+ })
+ .on('aborted', function() {
+ self.emit('aborted');
+ })
+ .on('data', function(buffer) {
+ self.write(buffer);
+ })
+ .on('end', function() {
+ if (self.error) {
+ return;
+ }
+
+ var err = self._parser.end();
+ if (err) {
+ self._error(err);
+ }
+ });
+
+ if (cb) {
+ var fields = {}, files = {};
+ this
+ .on('field', function(name, value) {
+ fields[name] = value;
+ })
+ .on('file', function(name, file) {
+ files[name] = file;
+ })
+ .on('error', function(err) {
+ cb(err, fields, files);
+ })
+ .on('end', function() {
+ cb(null, fields, files);
+ });
+ }
+
+ return this;
+};
+
+IncomingForm.prototype.writeHeaders = function(headers) {
+ this.headers = headers;
+ this._parseContentLength();
+ this._parseContentType();
+};
+
+IncomingForm.prototype.write = function(buffer) {
+ if (!this._parser) {
+ this._error(new Error('unintialized parser'));
+ return;
+ }
+
+ this.bytesReceived += buffer.length;
+ this.emit('progress', this.bytesReceived, this.bytesExpected);
+
+ var bytesParsed = this._parser.write(buffer);
+ if (bytesParsed !== buffer.length) {
+ this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed'));
+ }
+
+ return bytesParsed;
+};
+
+IncomingForm.prototype.pause = function() {
+ // this does nothing, unless overwritten in IncomingForm.parse
+ return false;
+};
+
+IncomingForm.prototype.resume = function() {
+ // this does nothing, unless overwritten in IncomingForm.parse
+ return false;
+};
+
+IncomingForm.prototype.onPart = function(part) {
+ // this method can be overwritten by the user
+ this.handlePart(part);
+};
+
+IncomingForm.prototype.handlePart = function(part) {
+ var self = this;
+
+ if (part.filename === undefined) {
+ var value = ''
+ , decoder = new StringDecoder(this.encoding);
+
+ part.on('data', function(buffer) {
+ self._fieldsSize += buffer.length;
+ if (self._fieldsSize > self.maxFieldsSize) {
+ self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data'));
+ return;
+ }
+ value += decoder.write(buffer);
+ });
+
+ part.on('end', function() {
+ self.emit('field', part.name, value);
+ });
+ return;
+ }
+
+ this._flushing++;
+
+ var file = new File({
+ path: this._uploadPath(part.filename),
+ name: part.filename,
+ type: part.mime,
+ });
+
+ this.emit('fileBegin', part.name, file);
+
+ file.open();
+
+ part.on('data', function(buffer) {
+ self.pause();
+ file.write(buffer, function() {
+ self.resume();
+ });
+ });
+
+ part.on('end', function() {
+ file.end(function() {
+ self._flushing--;
+ self.emit('file', part.name, file);
+ self._maybeEnd();
+ });
+ });
+};
+
+IncomingForm.prototype._parseContentType = function() {
+ if (!this.headers['content-type']) {
+ this._error(new Error('bad content-type header, no content-type'));
+ return;
+ }
+
+ if (this.headers['content-type'].match(/urlencoded/i)) {
+ this._initUrlencoded();
+ return;
+ }
+
+ if (this.headers['content-type'].match(/multipart/i)) {
+ var m;
+ if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) {
+ this._initMultipart(m[1] || m[2]);
+ } else {
+ this._error(new Error('bad content-type header, no multipart boundary'));
+ }
+ return;
+ }
+
+ this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type']));
+};
+
+IncomingForm.prototype._error = function(err) {
+ if (this.error) {
+ return;
+ }
+
+ this.error = err;
+ this.pause();
+ this.emit('error', err);
+};
+
+IncomingForm.prototype._parseContentLength = function() {
+ if (this.headers['content-length']) {
+ this.bytesReceived = 0;
+ this.bytesExpected = parseInt(this.headers['content-length'], 10);
+ this.emit('progress', this.bytesReceived, this.bytesExpected);
+ }
+};
+
+IncomingForm.prototype._newParser = function() {
+ return new MultipartParser();
+};
+
+IncomingForm.prototype._initMultipart = function(boundary) {
+ this.type = 'multipart';
+
+ var parser = new MultipartParser(),
+ self = this,
+ headerField,
+ headerValue,
+ part;
+
+ parser.initWithBoundary(boundary);
+
+ parser.onPartBegin = function() {
+ part = new EventEmitter();
+ part.headers = {};
+ part.name = null;
+ part.filename = null;
+ part.mime = null;
+ headerField = '';
+ headerValue = '';
+ };
+
+ parser.onHeaderField = function(b, start, end) {
+ headerField += b.toString(self.encoding, start, end);
+ };
+
+ parser.onHeaderValue = function(b, start, end) {
+ headerValue += b.toString(self.encoding, start, end);
+ };
+
+ parser.onHeaderEnd = function() {
+ headerField = headerField.toLowerCase();
+ part.headers[headerField] = headerValue;
+
+ var m;
+ if (headerField == 'content-disposition') {
+ if (m = headerValue.match(/name="([^"]+)"/i)) {
+ part.name = m[1];
+ }
+
+ part.filename = self._fileName(headerValue);
+ } else if (headerField == 'content-type') {
+ part.mime = headerValue;
+ }
+
+ headerField = '';
+ headerValue = '';
+ };
+
+ parser.onHeadersEnd = function() {
+ self.onPart(part);
+ };
+
+ parser.onPartData = function(b, start, end) {
+ part.emit('data', b.slice(start, end));
+ };
+
+ parser.onPartEnd = function() {
+ part.emit('end');
+ };
+
+ parser.onEnd = function() {
+ self.ended = true;
+ self._maybeEnd();
+ };
+
+ this._parser = parser;
+};
+
+IncomingForm.prototype._fileName = function(headerValue) {
+ var m = headerValue.match(/filename="(.*?)"($|; )/i)
+ if (!m) return;
+
+ var filename = m[1].substr(m[1].lastIndexOf('\\') + 1);
+ filename = filename.replace(/%22/g, '"');
+ filename = filename.replace(/&#([\d]{4});/g, function(m, code) {
+ return String.fromCharCode(code);
+ });
+ return filename;
+};
+
+IncomingForm.prototype._initUrlencoded = function() {
+ this.type = 'urlencoded';
+
+ var parser = new QuerystringParser()
+ , self = this;
+
+ parser.onField = function(key, val) {
+ self.emit('field', key, val);
+ };
+
+ parser.onEnd = function() {
+ self.ended = true;
+ self._maybeEnd();
+ };
+
+ this._parser = parser;
+};
+
+IncomingForm.prototype._uploadPath = function(filename) {
+ var name = '';
+ for (var i = 0; i < 32; i++) {
+ name += Math.floor(Math.random() * 16).toString(16);
+ }
+
+ if (this.keepExtensions) {
+ var ext = path.extname(filename);
+ ext = ext.replace(/(\.[a-z0-9]+).*/, '$1')
+
+ name += ext;
+ }
+
+ return path.join(this.uploadDir, name);
+};
+
+IncomingForm.prototype._maybeEnd = function() {
+ if (!this.ended || this._flushing) {
+ return;
+ }
+
+ this.emit('end');
+};
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js
new file mode 100644
index 0000000..7a6e3e1
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js
@@ -0,0 +1,3 @@
+var IncomingForm = require('./incoming_form').IncomingForm;
+IncomingForm.IncomingForm = IncomingForm;
+module.exports = IncomingForm;
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js
new file mode 100644
index 0000000..9ca567c
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js
@@ -0,0 +1,312 @@
+var Buffer = require('buffer').Buffer,
+ s = 0,
+ S =
+ { PARSER_UNINITIALIZED: s++,
+ START: s++,
+ START_BOUNDARY: s++,
+ HEADER_FIELD_START: s++,
+ HEADER_FIELD: s++,
+ HEADER_VALUE_START: s++,
+ HEADER_VALUE: s++,
+ HEADER_VALUE_ALMOST_DONE: s++,
+ HEADERS_ALMOST_DONE: s++,
+ PART_DATA_START: s++,
+ PART_DATA: s++,
+ PART_END: s++,
+ END: s++,
+ },
+
+ f = 1,
+ F =
+ { PART_BOUNDARY: f,
+ LAST_BOUNDARY: f *= 2,
+ },
+
+ LF = 10,
+ CR = 13,
+ SPACE = 32,
+ HYPHEN = 45,
+ COLON = 58,
+ A = 97,
+ Z = 122,
+
+ lower = function(c) {
+ return c | 0x20;
+ };
+
+for (var s in S) {
+ exports[s] = S[s];
+}
+
+function MultipartParser() {
+ this.boundary = null;
+ this.boundaryChars = null;
+ this.lookbehind = null;
+ this.state = S.PARSER_UNINITIALIZED;
+
+ this.index = null;
+ this.flags = 0;
+};
+exports.MultipartParser = MultipartParser;
+
+MultipartParser.stateToString = function(stateNumber) {
+ for (var state in S) {
+ var number = S[state];
+ if (number === stateNumber) return state;
+ }
+};
+
+MultipartParser.prototype.initWithBoundary = function(str) {
+ this.boundary = new Buffer(str.length+4);
+ this.boundary.write('\r\n--', 'ascii', 0);
+ this.boundary.write(str, 'ascii', 4);
+ this.lookbehind = new Buffer(this.boundary.length+8);
+ this.state = S.START;
+
+ this.boundaryChars = {};
+ for (var i = 0; i < this.boundary.length; i++) {
+ this.boundaryChars[this.boundary[i]] = true;
+ }
+};
+
+MultipartParser.prototype.write = function(buffer) {
+ var self = this,
+ i = 0,
+ len = buffer.length,
+ prevIndex = this.index,
+ index = this.index,
+ state = this.state,
+ flags = this.flags,
+ lookbehind = this.lookbehind,
+ boundary = this.boundary,
+ boundaryChars = this.boundaryChars,
+ boundaryLength = this.boundary.length,
+ boundaryEnd = boundaryLength - 1,
+ bufferLength = buffer.length,
+ c,
+ cl,
+
+ mark = function(name) {
+ self[name+'Mark'] = i;
+ },
+ clear = function(name) {
+ delete self[name+'Mark'];
+ },
+ callback = function(name, buffer, start, end) {
+ if (start !== undefined && start === end) {
+ return;
+ }
+
+ var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
+ if (callbackSymbol in self) {
+ self[callbackSymbol](buffer, start, end);
+ }
+ },
+ dataCallback = function(name, clear) {
+ var markSymbol = name+'Mark';
+ if (!(markSymbol in self)) {
+ return;
+ }
+
+ if (!clear) {
+ callback(name, buffer, self[markSymbol], buffer.length);
+ self[markSymbol] = 0;
+ } else {
+ callback(name, buffer, self[markSymbol], i);
+ delete self[markSymbol];
+ }
+ };
+
+ for (i = 0; i < len; i++) {
+ c = buffer[i];
+ switch (state) {
+ case S.PARSER_UNINITIALIZED:
+ return i;
+ case S.START:
+ index = 0;
+ state = S.START_BOUNDARY;
+ case S.START_BOUNDARY:
+ if (index == boundary.length - 2) {
+ if (c != CR) {
+ return i;
+ }
+ index++;
+ break;
+ } else if (index - 1 == boundary.length - 2) {
+ if (c != LF) {
+ return i;
+ }
+ index = 0;
+ callback('partBegin');
+ state = S.HEADER_FIELD_START;
+ break;
+ }
+
+ if (c != boundary[index+2]) {
+ return i;
+ }
+ index++;
+ break;
+ case S.HEADER_FIELD_START:
+ state = S.HEADER_FIELD;
+ mark('headerField');
+ index = 0;
+ case S.HEADER_FIELD:
+ if (c == CR) {
+ clear('headerField');
+ state = S.HEADERS_ALMOST_DONE;
+ break;
+ }
+
+ index++;
+ if (c == HYPHEN) {
+ break;
+ }
+
+ if (c == COLON) {
+ if (index == 1) {
+ // empty header field
+ return i;
+ }
+ dataCallback('headerField', true);
+ state = S.HEADER_VALUE_START;
+ break;
+ }
+
+ cl = lower(c);
+ if (cl < A || cl > Z) {
+ return i;
+ }
+ break;
+ case S.HEADER_VALUE_START:
+ if (c == SPACE) {
+ break;
+ }
+
+ mark('headerValue');
+ state = S.HEADER_VALUE;
+ case S.HEADER_VALUE:
+ if (c == CR) {
+ dataCallback('headerValue', true);
+ callback('headerEnd');
+ state = S.HEADER_VALUE_ALMOST_DONE;
+ }
+ break;
+ case S.HEADER_VALUE_ALMOST_DONE:
+ if (c != LF) {
+ return i;
+ }
+ state = S.HEADER_FIELD_START;
+ break;
+ case S.HEADERS_ALMOST_DONE:
+ if (c != LF) {
+ return i;
+ }
+
+ callback('headersEnd');
+ state = S.PART_DATA_START;
+ break;
+ case S.PART_DATA_START:
+ state = S.PART_DATA
+ mark('partData');
+ case S.PART_DATA:
+ prevIndex = index;
+
+ if (index == 0) {
+ // boyer-moore derrived algorithm to safely skip non-boundary data
+ i += boundaryEnd;
+ while (i < bufferLength && !(buffer[i] in boundaryChars)) {
+ i += boundaryLength;
+ }
+ i -= boundaryEnd;
+ c = buffer[i];
+ }
+
+ if (index < boundary.length) {
+ if (boundary[index] == c) {
+ if (index == 0) {
+ dataCallback('partData', true);
+ }
+ index++;
+ } else {
+ index = 0;
+ }
+ } else if (index == boundary.length) {
+ index++;
+ if (c == CR) {
+ // CR = part boundary
+ flags |= F.PART_BOUNDARY;
+ } else if (c == HYPHEN) {
+ // HYPHEN = end boundary
+ flags |= F.LAST_BOUNDARY;
+ } else {
+ index = 0;
+ }
+ } else if (index - 1 == boundary.length) {
+ if (flags & F.PART_BOUNDARY) {
+ index = 0;
+ if (c == LF) {
+ // unset the PART_BOUNDARY flag
+ flags &= ~F.PART_BOUNDARY;
+ callback('partEnd');
+ callback('partBegin');
+ state = S.HEADER_FIELD_START;
+ break;
+ }
+ } else if (flags & F.LAST_BOUNDARY) {
+ if (c == HYPHEN) {
+ callback('partEnd');
+ callback('end');
+ state = S.END;
+ } else {
+ index = 0;
+ }
+ } else {
+ index = 0;
+ }
+ }
+
+ if (index > 0) {
+ // when matching a possible boundary, keep a lookbehind reference
+ // in case it turns out to be a false lead
+ lookbehind[index-1] = c;
+ } else if (prevIndex > 0) {
+ // if our boundary turned out to be rubbish, the captured lookbehind
+ // belongs to partData
+ callback('partData', lookbehind, 0, prevIndex);
+ prevIndex = 0;
+ mark('partData');
+
+ // reconsider the current character even so it interrupted the sequence
+ // it could be the beginning of a new sequence
+ i--;
+ }
+
+ break;
+ case S.END:
+ break;
+ default:
+ return i;
+ }
+ }
+
+ dataCallback('headerField');
+ dataCallback('headerValue');
+ dataCallback('partData');
+
+ this.index = index;
+ this.state = state;
+ this.flags = flags;
+
+ return len;
+};
+
+MultipartParser.prototype.end = function() {
+ if (this.state != S.END) {
+ return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain());
+ }
+};
+
+MultipartParser.prototype.explain = function() {
+ return 'state = ' + MultipartParser.stateToString(this.state);
+};
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js
new file mode 100644
index 0000000..63f109e
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js
@@ -0,0 +1,25 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+// This is a buffering parser, not quite as nice as the multipart one.
+// If I find time I'll rewrite this to be fully streaming as well
+var querystring = require('querystring');
+
+function QuerystringParser() {
+ this.buffer = '';
+};
+exports.QuerystringParser = QuerystringParser;
+
+QuerystringParser.prototype.write = function(buffer) {
+ this.buffer += buffer.toString('ascii');
+ return buffer.length;
+};
+
+QuerystringParser.prototype.end = function() {
+ var fields = querystring.parse(this.buffer);
+ for (var field in fields) {
+ this.onField(field, fields[field]);
+ }
+ this.buffer = '';
+
+ this.onEnd();
+}; \ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js b/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js
new file mode 100644
index 0000000..e9493e9
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js
@@ -0,0 +1,6 @@
+// Backwards compatibility ...
+try {
+ module.exports = require('util');
+} catch (e) {
+ module.exports = require('sys');
+}
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/package.json b/node_modules/express/node_modules/connect/node_modules/formidable/package.json
new file mode 100644
index 0000000..97e98fb
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "formidable",
+ "version": "1.0.9",
+ "dependencies": {},
+ "devDependencies": {
+ "gently": "0.8.0",
+ "findit": "0.1.1",
+ "hashish": "0.0.4",
+ "urun": "0.0.4",
+ "utest": "0.0.3"
+ },
+ "directories": {
+ "lib": "./lib"
+ },
+ "main": "./lib/index",
+ "scripts": {
+ "test": "make test"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "_id": "formidable@1.0.9",
+ "optionalDependencies": {},
+ "_engineSupported": true,
+ "_npmVersion": "1.1.12",
+ "_nodeVersion": "v0.6.14",
+ "_defaultsLoaded": true,
+ "dist": {
+ "shasum": "50cb64f10788073052dda301e3ef0ba99cbb75e9"
+ },
+ "_from": "formidable@1.0.x"
+}
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js
new file mode 100644
index 0000000..eb432ad
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js
@@ -0,0 +1,19 @@
+var mysql = require('..');
+var path = require('path');
+
+var root = path.join(__dirname, '../');
+exports.dir = {
+ root : root,
+ lib : root + '/lib',
+ fixture : root + '/test/fixture',
+ tmp : root + '/test/tmp',
+};
+
+exports.port = 13532;
+
+exports.formidable = require('..');
+exports.assert = require('assert');
+
+exports.require = function(lib) {
+ return require(exports.dir.lib + '/' + lib);
+};
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt
new file mode 100644
index 0000000..e7a4785
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt
@@ -0,0 +1 @@
+I am a text file with a funky name!
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt
new file mode 100644
index 0000000..9b6903e
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt
@@ -0,0 +1 @@
+I am a plain text file
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md
new file mode 100644
index 0000000..3c9dbe3
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md
@@ -0,0 +1,3 @@
+* Opera does not allow submitting this file, it shows a warning to the
+ user that the file could not be found instead. Tested in 9.8, 11.51 on OSX.
+ Reported to Opera on 08.09.2011 (tracking email DSK-346009@bugs.opera.com).
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js
new file mode 100644
index 0000000..0bae449
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js
@@ -0,0 +1,3 @@
+module.exports['generic.http'] = [
+ {type: 'file', name: 'upload', filename: '', fixture: 'plain.txt'},
+];
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js
new file mode 100644
index 0000000..eb76fdc
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js
@@ -0,0 +1,21 @@
+var properFilename = 'funkyfilename.txt';
+
+function expect(filename) {
+ return [
+ {type: 'field', name: 'title', value: 'Weird filename'},
+ {type: 'file', name: 'upload', filename: filename, fixture: properFilename},
+ ];
+};
+
+var webkit = " ? % * | \" < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt";
+var ffOrIe = " ? % * | \" < > . ☃ ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt";
+
+module.exports = {
+ 'osx-chrome-13.http' : expect(webkit),
+ 'osx-firefox-3.6.http' : expect(ffOrIe),
+ 'osx-safari-5.http' : expect(webkit),
+ 'xp-chrome-12.http' : expect(webkit),
+ 'xp-ie-7.http' : expect(ffOrIe),
+ 'xp-ie-8.http' : expect(ffOrIe),
+ 'xp-safari-5.http' : expect(webkit),
+};
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js
new file mode 100644
index 0000000..a476169
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js
@@ -0,0 +1,72 @@
+exports['rfc1867'] =
+ { boundary: 'AaB03x',
+ raw:
+ '--AaB03x\r\n'+
+ 'content-disposition: form-data; name="field1"\r\n'+
+ '\r\n'+
+ 'Joe Blow\r\nalmost tricked you!\r\n'+
+ '--AaB03x\r\n'+
+ 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
+ 'Content-Type: text/plain\r\n'+
+ '\r\n'+
+ '... contents of file1.txt ...\r\r\n'+
+ '--AaB03x--\r\n',
+ parts:
+ [ { headers: {
+ 'content-disposition': 'form-data; name="field1"',
+ },
+ data: 'Joe Blow\r\nalmost tricked you!',
+ },
+ { headers: {
+ 'content-disposition': 'form-data; name="pics"; filename="file1.txt"',
+ 'Content-Type': 'text/plain',
+ },
+ data: '... contents of file1.txt ...\r',
+ }
+ ]
+ };
+
+exports['noTrailing\r\n'] =
+ { boundary: 'AaB03x',
+ raw:
+ '--AaB03x\r\n'+
+ 'content-disposition: form-data; name="field1"\r\n'+
+ '\r\n'+
+ 'Joe Blow\r\nalmost tricked you!\r\n'+
+ '--AaB03x\r\n'+
+ 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
+ 'Content-Type: text/plain\r\n'+
+ '\r\n'+
+ '... contents of file1.txt ...\r\r\n'+
+ '--AaB03x--',
+ parts:
+ [ { headers: {
+ 'content-disposition': 'form-data; name="field1"',
+ },
+ data: 'Joe Blow\r\nalmost tricked you!',
+ },
+ { headers: {
+ 'content-disposition': 'form-data; name="pics"; filename="file1.txt"',
+ 'Content-Type': 'text/plain',
+ },
+ data: '... contents of file1.txt ...\r',
+ }
+ ]
+ };
+
+exports['emptyHeader'] =
+ { boundary: 'AaB03x',
+ raw:
+ '--AaB03x\r\n'+
+ 'content-disposition: form-data; name="field1"\r\n'+
+ ': foo\r\n'+
+ '\r\n'+
+ 'Joe Blow\r\nalmost tricked you!\r\n'+
+ '--AaB03x\r\n'+
+ 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
+ 'Content-Type: text/plain\r\n'+
+ '\r\n'+
+ '... contents of file1.txt ...\r\r\n'+
+ '--AaB03x--\r\n',
+ expectError: true,
+ };
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js
new file mode 100644
index 0000000..66ad259
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js
@@ -0,0 +1,89 @@
+var hashish = require('hashish');
+var fs = require('fs');
+var findit = require('findit');
+var path = require('path');
+var http = require('http');
+var net = require('net');
+var assert = require('assert');
+
+var common = require('../common');
+var formidable = common.formidable;
+
+var server = http.createServer();
+server.listen(common.port, findFixtures);
+
+function findFixtures() {
+ var fixtures = [];
+ findit
+ .sync(common.dir.fixture + '/js')
+ .forEach(function(jsPath) {
+ if (!/\.js$/.test(jsPath)) return;
+
+ var group = path.basename(jsPath, '.js');
+ hashish.forEach(require(jsPath), function(fixture, name) {
+ fixtures.push({
+ name : group + '/' + name,
+ fixture : fixture,
+ });
+ });
+ });
+
+ testNext(fixtures);
+}
+
+function testNext(fixtures) {
+ var fixture = fixtures.shift();
+ if (!fixture) return server.close();
+
+ var name = fixture.name;
+ var fixture = fixture.fixture;
+
+ uploadFixture(name, function(err, parts) {
+ if (err) throw err;
+
+ fixture.forEach(function(expectedPart, i) {
+ var parsedPart = parts[i];
+ assert.equal(parsedPart.type, expectedPart.type);
+ assert.equal(parsedPart.name, expectedPart.name);
+
+ if (parsedPart.type === 'file') {
+ var filename = parsedPart.value.name;
+ assert.equal(filename, expectedPart.filename);
+ }
+ });
+
+ testNext(fixtures);
+ });
+};
+
+function uploadFixture(name, cb) {
+ server.once('request', function(req, res) {
+ var form = new formidable.IncomingForm();
+ form.uploadDir = common.dir.tmp;
+ form.parse(req);
+
+ function callback() {
+ var realCallback = cb;
+ cb = function() {};
+ realCallback.apply(null, arguments);
+ }
+
+ var parts = [];
+ form
+ .on('error', callback)
+ .on('fileBegin', function(name, value) {
+ parts.push({type: 'file', name: name, value: value});
+ })
+ .on('field', function(name, value) {
+ parts.push({type: 'field', name: name, value: value});
+ })
+ .on('end', function() {
+ callback(null, parts);
+ });
+ });
+
+ var socket = net.createConnection(common.port);
+ var file = fs.createReadStream(common.dir.fixture + '/http/' + name);
+
+ file.pipe(socket);
+}
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js
new file mode 100644
index 0000000..2b98598
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js
@@ -0,0 +1,24 @@
+var path = require('path'),
+ fs = require('fs');
+
+try {
+ global.Gently = require('gently');
+} catch (e) {
+ throw new Error('this test suite requires node-gently');
+}
+
+exports.lib = path.join(__dirname, '../../lib');
+
+global.GENTLY = new Gently();
+
+global.assert = require('assert');
+global.TEST_PORT = 13532;
+global.TEST_FIXTURES = path.join(__dirname, '../fixture');
+global.TEST_TMP = path.join(__dirname, '../tmp');
+
+// Stupid new feature in node that complains about gently attaching too many
+// listeners to process 'exit'. This is a workaround until I can think of a
+// better way to deal with this.
+if (process.setMaxListeners) {
+ process.setMaxListeners(10000);
+}
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js
new file mode 100644
index 0000000..75232aa
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js
@@ -0,0 +1,80 @@
+var common = require('../common');
+var CHUNK_LENGTH = 10,
+ multipartParser = require(common.lib + '/multipart_parser'),
+ MultipartParser = multipartParser.MultipartParser,
+ parser = new MultipartParser(),
+ fixtures = require(TEST_FIXTURES + '/multipart'),
+ Buffer = require('buffer').Buffer;
+
+Object.keys(fixtures).forEach(function(name) {
+ var fixture = fixtures[name],
+ buffer = new Buffer(Buffer.byteLength(fixture.raw, 'binary')),
+ offset = 0,
+ chunk,
+ nparsed,
+
+ parts = [],
+ part = null,
+ headerField,
+ headerValue,
+ endCalled = '';
+
+ parser.initWithBoundary(fixture.boundary);
+ parser.onPartBegin = function() {
+ part = {headers: {}, data: ''};
+ parts.push(part);
+ headerField = '';
+ headerValue = '';
+ };
+
+ parser.onHeaderField = function(b, start, end) {
+ headerField += b.toString('ascii', start, end);
+ };
+
+ parser.onHeaderValue = function(b, start, end) {
+ headerValue += b.toString('ascii', start, end);
+ }
+
+ parser.onHeaderEnd = function() {
+ part.headers[headerField] = headerValue;
+ headerField = '';
+ headerValue = '';
+ };
+
+ parser.onPartData = function(b, start, end) {
+ var str = b.toString('ascii', start, end);
+ part.data += b.slice(start, end);
+ }
+
+ parser.onEnd = function() {
+ endCalled = true;
+ }
+
+ buffer.write(fixture.raw, 'binary', 0);
+
+ while (offset < buffer.length) {
+ if (offset + CHUNK_LENGTH < buffer.length) {
+ chunk = buffer.slice(offset, offset+CHUNK_LENGTH);
+ } else {
+ chunk = buffer.slice(offset, buffer.length);
+ }
+ offset = offset + CHUNK_LENGTH;
+
+ nparsed = parser.write(chunk);
+ if (nparsed != chunk.length) {
+ if (fixture.expectError) {
+ return;
+ }
+ puts('-- ERROR --');
+ p(chunk.toString('ascii'));
+ throw new Error(chunk.length+' bytes written, but only '+nparsed+' bytes parsed!');
+ }
+ }
+
+ if (fixture.expectError) {
+ throw new Error('expected parse error did not happen');
+ }
+
+ assert.ok(endCalled);
+ assert.deepEqual(parts, fixture.parts);
+});
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js
new file mode 100644
index 0000000..52ceedb
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js
@@ -0,0 +1,104 @@
+var common = require('../common');
+var WriteStreamStub = GENTLY.stub('fs', 'WriteStream');
+
+var File = require(common.lib + '/file'),
+ EventEmitter = require('events').EventEmitter,
+ file,
+ gently;
+
+function test(test) {
+ gently = new Gently();
+ file = new File();
+ test();
+ gently.verify(test.name);
+}
+
+test(function constructor() {
+ assert.ok(file instanceof EventEmitter);
+ assert.strictEqual(file.size, 0);
+ assert.strictEqual(file.path, null);
+ assert.strictEqual(file.name, null);
+ assert.strictEqual(file.type, null);
+ assert.strictEqual(file.lastModifiedDate, null);
+
+ assert.strictEqual(file._writeStream, null);
+
+ (function testSetProperties() {
+ var file2 = new File({foo: 'bar'});
+ assert.equal(file2.foo, 'bar');
+ })();
+});
+
+test(function open() {
+ var WRITE_STREAM;
+ file.path = '/foo';
+
+ gently.expect(WriteStreamStub, 'new', function (path) {
+ WRITE_STREAM = this;
+ assert.strictEqual(path, file.path);
+ });
+
+ file.open();
+ assert.strictEqual(file._writeStream, WRITE_STREAM);
+});
+
+test(function write() {
+ var BUFFER = {length: 10},
+ CB_STUB,
+ CB = function() {
+ CB_STUB.apply(this, arguments);
+ };
+
+ file._writeStream = {};
+
+ gently.expect(file._writeStream, 'write', function (buffer, cb) {
+ assert.strictEqual(buffer, BUFFER);
+
+ gently.expect(file, 'emit', function (event, bytesWritten) {
+ assert.ok(file.lastModifiedDate instanceof Date);
+ assert.equal(event, 'progress');
+ assert.equal(bytesWritten, file.size);
+ });
+
+ CB_STUB = gently.expect(function writeCb() {
+ assert.equal(file.size, 10);
+ });
+
+ cb();
+
+ gently.expect(file, 'emit', function (event, bytesWritten) {
+ assert.equal(event, 'progress');
+ assert.equal(bytesWritten, file.size);
+ });
+
+ CB_STUB = gently.expect(function writeCb() {
+ assert.equal(file.size, 20);
+ });
+
+ cb();
+ });
+
+ file.write(BUFFER, CB);
+});
+
+test(function end() {
+ var CB_STUB,
+ CB = function() {
+ CB_STUB.apply(this, arguments);
+ };
+
+ file._writeStream = {};
+
+ gently.expect(file._writeStream, 'end', function (cb) {
+ gently.expect(file, 'emit', function (event) {
+ assert.equal(event, 'end');
+ });
+
+ CB_STUB = gently.expect(function endCb() {
+ });
+
+ cb();
+ });
+
+ file.end(CB);
+});
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js
new file mode 100644
index 0000000..b64df8b
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js
@@ -0,0 +1,726 @@
+var common = require('../common');
+var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'),
+ QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'),
+ EventEmitterStub = GENTLY.stub('events', 'EventEmitter'),
+ FileStub = GENTLY.stub('./file');
+
+var formidable = require(common.lib + '/index'),
+ IncomingForm = formidable.IncomingForm,
+ events = require('events'),
+ fs = require('fs'),
+ path = require('path'),
+ Buffer = require('buffer').Buffer,
+ fixtures = require(TEST_FIXTURES + '/multipart'),
+ form,
+ gently;
+
+function test(test) {
+ gently = new Gently();
+ gently.expect(EventEmitterStub, 'call');
+ form = new IncomingForm();
+ test();
+ gently.verify(test.name);
+}
+
+test(function constructor() {
+ assert.strictEqual(form.error, null);
+ assert.strictEqual(form.ended, false);
+ assert.strictEqual(form.type, null);
+ assert.strictEqual(form.headers, null);
+ assert.strictEqual(form.keepExtensions, false);
+ assert.strictEqual(form.uploadDir, '/tmp');
+ assert.strictEqual(form.encoding, 'utf-8');
+ assert.strictEqual(form.bytesReceived, null);
+ assert.strictEqual(form.bytesExpected, null);
+ assert.strictEqual(form.maxFieldsSize, 2 * 1024 * 1024);
+ assert.strictEqual(form._parser, null);
+ assert.strictEqual(form._flushing, 0);
+ assert.strictEqual(form._fieldsSize, 0);
+ assert.ok(form instanceof EventEmitterStub);
+ assert.equal(form.constructor.name, 'IncomingForm');
+
+ (function testSimpleConstructor() {
+ gently.expect(EventEmitterStub, 'call');
+ var form = IncomingForm();
+ assert.ok(form instanceof IncomingForm);
+ })();
+
+ (function testSimpleConstructorShortcut() {
+ gently.expect(EventEmitterStub, 'call');
+ var form = formidable();
+ assert.ok(form instanceof IncomingForm);
+ })();
+});
+
+test(function parse() {
+ var REQ = {headers: {}}
+ , emit = {};
+
+ gently.expect(form, 'writeHeaders', function(headers) {
+ assert.strictEqual(headers, REQ.headers);
+ });
+
+ var events = ['error', 'aborted', 'data', 'end'];
+ gently.expect(REQ, 'on', events.length, function(event, fn) {
+ assert.equal(event, events.shift());
+ emit[event] = fn;
+ return this;
+ });
+
+ form.parse(REQ);
+
+ (function testPause() {
+ gently.expect(REQ, 'pause');
+ assert.strictEqual(form.pause(), true);
+ })();
+
+ (function testPauseCriticalException() {
+ form.ended = false;
+
+ var ERR = new Error('dasdsa');
+ gently.expect(REQ, 'pause', function() {
+ throw ERR;
+ });
+
+ gently.expect(form, '_error', function(err) {
+ assert.strictEqual(err, ERR);
+ });
+
+ assert.strictEqual(form.pause(), false);
+ })();
+
+ (function testPauseHarmlessException() {
+ form.ended = true;
+
+ var ERR = new Error('dasdsa');
+ gently.expect(REQ, 'pause', function() {
+ throw ERR;
+ });
+
+ assert.strictEqual(form.pause(), false);
+ })();
+
+ (function testResume() {
+ gently.expect(REQ, 'resume');
+ assert.strictEqual(form.resume(), true);
+ })();
+
+ (function testResumeCriticalException() {
+ form.ended = false;
+
+ var ERR = new Error('dasdsa');
+ gently.expect(REQ, 'resume', function() {
+ throw ERR;
+ });
+
+ gently.expect(form, '_error', function(err) {
+ assert.strictEqual(err, ERR);
+ });
+
+ assert.strictEqual(form.resume(), false);
+ })();
+
+ (function testResumeHarmlessException() {
+ form.ended = true;
+
+ var ERR = new Error('dasdsa');
+ gently.expect(REQ, 'resume', function() {
+ throw ERR;
+ });
+
+ assert.strictEqual(form.resume(), false);
+ })();
+
+ (function testEmitError() {
+ var ERR = new Error('something bad happened');
+ gently.expect(form, '_error',function(err) {
+ assert.strictEqual(err, ERR);
+ });
+ emit.error(ERR);
+ })();
+
+ (function testEmitAborted() {
+ gently.expect(form, 'emit',function(event) {
+ assert.equal(event, 'aborted');
+ });
+
+ emit.aborted();
+ })();
+
+
+ (function testEmitData() {
+ var BUFFER = [1, 2, 3];
+ gently.expect(form, 'write', function(buffer) {
+ assert.strictEqual(buffer, BUFFER);
+ });
+ emit.data(BUFFER);
+ })();
+
+ (function testEmitEnd() {
+ form._parser = {};
+
+ (function testWithError() {
+ var ERR = new Error('haha');
+ gently.expect(form._parser, 'end', function() {
+ return ERR;
+ });
+
+ gently.expect(form, '_error', function(err) {
+ assert.strictEqual(err, ERR);
+ });
+
+ emit.end();
+ })();
+
+ (function testWithoutError() {
+ gently.expect(form._parser, 'end');
+ emit.end();
+ })();
+
+ (function testAfterError() {
+ form.error = true;
+ emit.end();
+ })();
+ })();
+
+ (function testWithCallback() {
+ gently.expect(EventEmitterStub, 'call');
+ var form = new IncomingForm(),
+ REQ = {headers: {}},
+ parseCalled = 0;
+
+ gently.expect(form, 'writeHeaders');
+ gently.expect(REQ, 'on', 4, function() {
+ return this;
+ });
+
+ gently.expect(form, 'on', 4, function(event, fn) {
+ if (event == 'field') {
+ fn('field1', 'foo');
+ fn('field1', 'bar');
+ fn('field2', 'nice');
+ }
+
+ if (event == 'file') {
+ fn('file1', '1');
+ fn('file1', '2');
+ fn('file2', '3');
+ }
+
+ if (event == 'end') {
+ fn();
+ }
+ return this;
+ });
+
+ form.parse(REQ, gently.expect(function parseCbOk(err, fields, files) {
+ assert.deepEqual(fields, {field1: 'bar', field2: 'nice'});
+ assert.deepEqual(files, {file1: '2', file2: '3'});
+ }));
+
+ gently.expect(form, 'writeHeaders');
+ gently.expect(REQ, 'on', 4, function() {
+ return this;
+ });
+
+ var ERR = new Error('test');
+ gently.expect(form, 'on', 3, function(event, fn) {
+ if (event == 'field') {
+ fn('foo', 'bar');
+ }
+
+ if (event == 'error') {
+ fn(ERR);
+ gently.expect(form, 'on');
+ }
+ return this;
+ });
+
+ form.parse(REQ, gently.expect(function parseCbErr(err, fields, files) {
+ assert.strictEqual(err, ERR);
+ assert.deepEqual(fields, {foo: 'bar'});
+ }));
+ })();
+});
+
+test(function pause() {
+ assert.strictEqual(form.pause(), false);
+});
+
+test(function resume() {
+ assert.strictEqual(form.resume(), false);
+});
+
+
+test(function writeHeaders() {
+ var HEADERS = {};
+ gently.expect(form, '_parseContentLength');
+ gently.expect(form, '_parseContentType');
+
+ form.writeHeaders(HEADERS);
+ assert.strictEqual(form.headers, HEADERS);
+});
+
+test(function write() {
+ var parser = {},
+ BUFFER = [1, 2, 3];
+
+ form._parser = parser;
+ form.bytesExpected = 523423;
+
+ (function testBasic() {
+ gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
+ assert.equal(event, 'progress');
+ assert.equal(bytesReceived, BUFFER.length);
+ assert.equal(bytesExpected, form.bytesExpected);
+ });
+
+ gently.expect(parser, 'write', function(buffer) {
+ assert.strictEqual(buffer, BUFFER);
+ return buffer.length;
+ });
+
+ assert.equal(form.write(BUFFER), BUFFER.length);
+ assert.equal(form.bytesReceived, BUFFER.length);
+ })();
+
+ (function testParserError() {
+ gently.expect(form, 'emit');
+
+ gently.expect(parser, 'write', function(buffer) {
+ assert.strictEqual(buffer, BUFFER);
+ return buffer.length - 1;
+ });
+
+ gently.expect(form, '_error', function(err) {
+ assert.ok(err.message.match(/parser error/i));
+ });
+
+ assert.equal(form.write(BUFFER), BUFFER.length - 1);
+ assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length);
+ })();
+
+ (function testUninitialized() {
+ delete form._parser;
+
+ gently.expect(form, '_error', function(err) {
+ assert.ok(err.message.match(/unintialized parser/i));
+ });
+ form.write(BUFFER);
+ })();
+});
+
+test(function parseContentType() {
+ var HEADERS = {};
+
+ form.headers = {'content-type': 'application/x-www-form-urlencoded'};
+ gently.expect(form, '_initUrlencoded');
+ form._parseContentType();
+
+ // accept anything that has 'urlencoded' in it
+ form.headers = {'content-type': 'broken-client/urlencoded-stupid'};
+ gently.expect(form, '_initUrlencoded');
+ form._parseContentType();
+
+ var BOUNDARY = '---------------------------57814261102167618332366269';
+ form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY};
+
+ gently.expect(form, '_initMultipart', function(boundary) {
+ assert.equal(boundary, BOUNDARY);
+ });
+ form._parseContentType();
+
+ (function testQuotedBoundary() {
+ form.headers = {'content-type': 'multipart/form-data; boundary="' + BOUNDARY + '"'};
+
+ gently.expect(form, '_initMultipart', function(boundary) {
+ assert.equal(boundary, BOUNDARY);
+ });
+ form._parseContentType();
+ })();
+
+ (function testNoBoundary() {
+ form.headers = {'content-type': 'multipart/form-data'};
+
+ gently.expect(form, '_error', function(err) {
+ assert.ok(err.message.match(/no multipart boundary/i));
+ });
+ form._parseContentType();
+ })();
+
+ (function testNoContentType() {
+ form.headers = {};
+
+ gently.expect(form, '_error', function(err) {
+ assert.ok(err.message.match(/no content-type/i));
+ });
+ form._parseContentType();
+ })();
+
+ (function testUnknownContentType() {
+ form.headers = {'content-type': 'invalid'};
+
+ gently.expect(form, '_error', function(err) {
+ assert.ok(err.message.match(/unknown content-type/i));
+ });
+ form._parseContentType();
+ })();
+});
+
+test(function parseContentLength() {
+ var HEADERS = {};
+
+ form.headers = {};
+ form._parseContentLength();
+ assert.strictEqual(form.bytesReceived, null);
+ assert.strictEqual(form.bytesExpected, null);
+
+ form.headers['content-length'] = '8';
+ gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
+ assert.equal(event, 'progress');
+ assert.equal(bytesReceived, 0);
+ assert.equal(bytesExpected, 8);
+ });
+ form._parseContentLength();
+ assert.strictEqual(form.bytesReceived, 0);
+ assert.strictEqual(form.bytesExpected, 8);
+
+ // JS can be evil, lets make sure we are not
+ form.headers['content-length'] = '08';
+ gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
+ assert.equal(event, 'progress');
+ assert.equal(bytesReceived, 0);
+ assert.equal(bytesExpected, 8);
+ });
+ form._parseContentLength();
+ assert.strictEqual(form.bytesExpected, 8);
+});
+
+test(function _initMultipart() {
+ var BOUNDARY = '123',
+ PARSER;
+
+ gently.expect(MultipartParserStub, 'new', function() {
+ PARSER = this;
+ });
+
+ gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) {
+ assert.equal(boundary, BOUNDARY);
+ });
+
+ form._initMultipart(BOUNDARY);
+ assert.equal(form.type, 'multipart');
+ assert.strictEqual(form._parser, PARSER);
+
+ (function testRegularField() {
+ var PART;
+ gently.expect(EventEmitterStub, 'new', function() {
+ PART = this;
+ });
+
+ gently.expect(form, 'onPart', function(part) {
+ assert.strictEqual(part, PART);
+ assert.deepEqual
+ ( part.headers
+ , { 'content-disposition': 'form-data; name="field1"'
+ , 'foo': 'bar'
+ }
+ );
+ assert.equal(part.name, 'field1');
+
+ var strings = ['hello', ' world'];
+ gently.expect(part, 'emit', 2, function(event, b) {
+ assert.equal(event, 'data');
+ assert.equal(b.toString(), strings.shift());
+ });
+
+ gently.expect(part, 'emit', function(event, b) {
+ assert.equal(event, 'end');
+ });
+ });
+
+ PARSER.onPartBegin();
+ PARSER.onHeaderField(new Buffer('content-disposition'), 0, 10);
+ PARSER.onHeaderField(new Buffer('content-disposition'), 10, 19);
+ PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 0, 14);
+ PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 14, 24);
+ PARSER.onHeaderEnd();
+ PARSER.onHeaderField(new Buffer('foo'), 0, 3);
+ PARSER.onHeaderValue(new Buffer('bar'), 0, 3);
+ PARSER.onHeaderEnd();
+ PARSER.onHeadersEnd();
+ PARSER.onPartData(new Buffer('hello world'), 0, 5);
+ PARSER.onPartData(new Buffer('hello world'), 5, 11);
+ PARSER.onPartEnd();
+ })();
+
+ (function testFileField() {
+ var PART;
+ gently.expect(EventEmitterStub, 'new', function() {
+ PART = this;
+ });
+
+ gently.expect(form, 'onPart', function(part) {
+ assert.deepEqual
+ ( part.headers
+ , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'
+ , 'content-type': 'text/plain'
+ }
+ );
+ assert.equal(part.name, 'field2');
+ assert.equal(part.filename, 'Sun"et.jpg');
+ assert.equal(part.mime, 'text/plain');
+
+ gently.expect(part, 'emit', function(event, b) {
+ assert.equal(event, 'data');
+ assert.equal(b.toString(), '... contents of file1.txt ...');
+ });
+
+ gently.expect(part, 'emit', function(event, b) {
+ assert.equal(event, 'end');
+ });
+ });
+
+ PARSER.onPartBegin();
+ PARSER.onHeaderField(new Buffer('content-disposition'), 0, 19);
+ PARSER.onHeaderValue(new Buffer('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'), 0, 85);
+ PARSER.onHeaderEnd();
+ PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12);
+ PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10);
+ PARSER.onHeaderEnd();
+ PARSER.onHeadersEnd();
+ PARSER.onPartData(new Buffer('... contents of file1.txt ...'), 0, 29);
+ PARSER.onPartEnd();
+ })();
+
+ (function testEnd() {
+ gently.expect(form, '_maybeEnd');
+ PARSER.onEnd();
+ assert.ok(form.ended);
+ })();
+});
+
+test(function _fileName() {
+ // TODO
+ return;
+});
+
+test(function _initUrlencoded() {
+ var PARSER;
+
+ gently.expect(QuerystringParserStub, 'new', function() {
+ PARSER = this;
+ });
+
+ form._initUrlencoded();
+ assert.equal(form.type, 'urlencoded');
+ assert.strictEqual(form._parser, PARSER);
+
+ (function testOnField() {
+ var KEY = 'KEY', VAL = 'VAL';
+ gently.expect(form, 'emit', function(field, key, val) {
+ assert.equal(field, 'field');
+ assert.equal(key, KEY);
+ assert.equal(val, VAL);
+ });
+
+ PARSER.onField(KEY, VAL);
+ })();
+
+ (function testOnEnd() {
+ gently.expect(form, '_maybeEnd');
+
+ PARSER.onEnd();
+ assert.equal(form.ended, true);
+ })();
+});
+
+test(function _error() {
+ var ERR = new Error('bla');
+
+ gently.expect(form, 'pause');
+ gently.expect(form, 'emit', function(event, err) {
+ assert.equal(event, 'error');
+ assert.strictEqual(err, ERR);
+ });
+
+ form._error(ERR);
+ assert.strictEqual(form.error, ERR);
+
+ // make sure _error only does its thing once
+ form._error(ERR);
+});
+
+test(function onPart() {
+ var PART = {};
+ gently.expect(form, 'handlePart', function(part) {
+ assert.strictEqual(part, PART);
+ });
+
+ form.onPart(PART);
+});
+
+test(function handlePart() {
+ (function testUtf8Field() {
+ var PART = new events.EventEmitter();
+ PART.name = 'my_field';
+
+ gently.expect(form, 'emit', function(event, field, value) {
+ assert.equal(event, 'field');
+ assert.equal(field, 'my_field');
+ assert.equal(value, 'hello world: €');
+ });
+
+ form.handlePart(PART);
+ PART.emit('data', new Buffer('hello'));
+ PART.emit('data', new Buffer(' world: '));
+ PART.emit('data', new Buffer([0xE2]));
+ PART.emit('data', new Buffer([0x82, 0xAC]));
+ PART.emit('end');
+ })();
+
+ (function testBinaryField() {
+ var PART = new events.EventEmitter();
+ PART.name = 'my_field2';
+
+ gently.expect(form, 'emit', function(event, field, value) {
+ assert.equal(event, 'field');
+ assert.equal(field, 'my_field2');
+ assert.equal(value, 'hello world: '+new Buffer([0xE2, 0x82, 0xAC]).toString('binary'));
+ });
+
+ form.encoding = 'binary';
+ form.handlePart(PART);
+ PART.emit('data', new Buffer('hello'));
+ PART.emit('data', new Buffer(' world: '));
+ PART.emit('data', new Buffer([0xE2]));
+ PART.emit('data', new Buffer([0x82, 0xAC]));
+ PART.emit('end');
+ })();
+
+ (function testFieldSize() {
+ form.maxFieldsSize = 8;
+ var PART = new events.EventEmitter();
+ PART.name = 'my_field';
+
+ gently.expect(form, '_error', function(err) {
+ assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data');
+ });
+
+ form.handlePart(PART);
+ form._fieldsSize = 1;
+ PART.emit('data', new Buffer(7));
+ PART.emit('data', new Buffer(1));
+ })();
+
+ (function testFilePart() {
+ var PART = new events.EventEmitter(),
+ FILE = new events.EventEmitter(),
+ PATH = '/foo/bar';
+
+ PART.name = 'my_file';
+ PART.filename = 'sweet.txt';
+ PART.mime = 'sweet.txt';
+
+ gently.expect(form, '_uploadPath', function(filename) {
+ assert.equal(filename, PART.filename);
+ return PATH;
+ });
+
+ gently.expect(FileStub, 'new', function(properties) {
+ assert.equal(properties.path, PATH);
+ assert.equal(properties.name, PART.filename);
+ assert.equal(properties.type, PART.mime);
+ FILE = this;
+
+ gently.expect(form, 'emit', function (event, field, file) {
+ assert.equal(event, 'fileBegin');
+ assert.strictEqual(field, PART.name);
+ assert.strictEqual(file, FILE);
+ });
+
+ gently.expect(FILE, 'open');
+ });
+
+ form.handlePart(PART);
+ assert.equal(form._flushing, 1);
+
+ var BUFFER;
+ gently.expect(form, 'pause');
+ gently.expect(FILE, 'write', function(buffer, cb) {
+ assert.strictEqual(buffer, BUFFER);
+ gently.expect(form, 'resume');
+ // @todo handle cb(new Err)
+ cb();
+ });
+
+ PART.emit('data', BUFFER = new Buffer('test'));
+
+ gently.expect(FILE, 'end', function(cb) {
+ gently.expect(form, 'emit', function(event, field, file) {
+ assert.equal(event, 'file');
+ assert.strictEqual(file, FILE);
+ });
+
+ gently.expect(form, '_maybeEnd');
+
+ cb();
+ assert.equal(form._flushing, 0);
+ });
+
+ PART.emit('end');
+ })();
+});
+
+test(function _uploadPath() {
+ (function testUniqueId() {
+ var UUID_A, UUID_B;
+ gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) {
+ assert.equal(uploadDir, form.uploadDir);
+ UUID_A = uuid;
+ });
+ form._uploadPath();
+
+ gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) {
+ UUID_B = uuid;
+ });
+ form._uploadPath();
+
+ assert.notEqual(UUID_A, UUID_B);
+ })();
+
+ (function testFileExtension() {
+ form.keepExtensions = true;
+ var FILENAME = 'foo.jpg',
+ EXT = '.bar';
+
+ gently.expect(GENTLY.hijacked.path, 'extname', function(filename) {
+ assert.equal(filename, FILENAME);
+ gently.restore(path, 'extname');
+
+ return EXT;
+ });
+
+ gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, name) {
+ assert.equal(path.extname(name), EXT);
+ });
+ form._uploadPath(FILENAME);
+ })();
+});
+
+test(function _maybeEnd() {
+ gently.expect(form, 'emit', 0);
+ form._maybeEnd();
+
+ form.ended = true;
+ form._flushing = 1;
+ form._maybeEnd();
+
+ gently.expect(form, 'emit', function(event) {
+ assert.equal(event, 'end');
+ });
+
+ form.ended = true;
+ form._flushing = 0;
+ form._maybeEnd();
+});
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js
new file mode 100644
index 0000000..d8dc968
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js
@@ -0,0 +1,50 @@
+var common = require('../common');
+var multipartParser = require(common.lib + '/multipart_parser'),
+ MultipartParser = multipartParser.MultipartParser,
+ events = require('events'),
+ Buffer = require('buffer').Buffer,
+ parser;
+
+function test(test) {
+ parser = new MultipartParser();
+ test();
+}
+
+test(function constructor() {
+ assert.equal(parser.boundary, null);
+ assert.equal(parser.state, 0);
+ assert.equal(parser.flags, 0);
+ assert.equal(parser.boundaryChars, null);
+ assert.equal(parser.index, null);
+ assert.equal(parser.lookbehind, null);
+ assert.equal(parser.constructor.name, 'MultipartParser');
+});
+
+test(function initWithBoundary() {
+ var boundary = 'abc';
+ parser.initWithBoundary(boundary);
+ assert.deepEqual(Array.prototype.slice.call(parser.boundary), [13, 10, 45, 45, 97, 98, 99]);
+ assert.equal(parser.state, multipartParser.START);
+
+ assert.deepEqual(parser.boundaryChars, {10: true, 13: true, 45: true, 97: true, 98: true, 99: true});
+});
+
+test(function parserError() {
+ var boundary = 'abc',
+ buffer = new Buffer(5);
+
+ parser.initWithBoundary(boundary);
+ buffer.write('--ad', 'ascii', 0);
+ assert.equal(parser.write(buffer), 3);
+});
+
+test(function end() {
+ (function testError() {
+ assert.equal(parser.end().message, 'MultipartParser.end(): stream ended unexpectedly: ' + parser.explain());
+ })();
+
+ (function testRegular() {
+ parser.state = multipartParser.END;
+ assert.strictEqual(parser.end(), undefined);
+ })();
+});
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js
new file mode 100644
index 0000000..54d3e2d
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js
@@ -0,0 +1,45 @@
+var common = require('../common');
+var QuerystringParser = require(common.lib + '/querystring_parser').QuerystringParser,
+ Buffer = require('buffer').Buffer,
+ gently,
+ parser;
+
+function test(test) {
+ gently = new Gently();
+ parser = new QuerystringParser();
+ test();
+ gently.verify(test.name);
+}
+
+test(function constructor() {
+ assert.equal(parser.buffer, '');
+ assert.equal(parser.constructor.name, 'QuerystringParser');
+});
+
+test(function write() {
+ var a = new Buffer('a=1');
+ assert.equal(parser.write(a), a.length);
+
+ var b = new Buffer('&b=2');
+ parser.write(b);
+ assert.equal(parser.buffer, a + b);
+});
+
+test(function end() {
+ var FIELDS = {a: ['b', {c: 'd'}], e: 'f'};
+
+ gently.expect(GENTLY.hijacked.querystring, 'parse', function(str) {
+ assert.equal(str, parser.buffer);
+ return FIELDS;
+ });
+
+ gently.expect(parser, 'onField', Object.keys(FIELDS).length, function(key, val) {
+ assert.deepEqual(FIELDS[key], val);
+ });
+
+ gently.expect(parser, 'onEnd');
+
+ parser.buffer = 'my buffer';
+ parser.end();
+ assert.equal(parser.buffer, '');
+});
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js
new file mode 100644
index 0000000..fcfdb94
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js
@@ -0,0 +1,72 @@
+var common = require('../common');
+var BOUNDARY = '---------------------------10102754414578508781458777923',
+ FIXTURE = TEST_FIXTURES+'/multi_video.upload',
+ fs = require('fs'),
+ util = require(common.lib + '/util'),
+ http = require('http'),
+ formidable = require(common.lib + '/index'),
+ server = http.createServer();
+
+server.on('request', function(req, res) {
+ var form = new formidable.IncomingForm(),
+ uploads = {};
+
+ form.uploadDir = TEST_TMP;
+ form.parse(req);
+
+ form
+ .on('fileBegin', function(field, file) {
+ assert.equal(field, 'upload');
+
+ var tracker = {file: file, progress: [], ended: false};
+ uploads[file.filename] = tracker;
+ file
+ .on('progress', function(bytesReceived) {
+ tracker.progress.push(bytesReceived);
+ assert.equal(bytesReceived, file.length);
+ })
+ .on('end', function() {
+ tracker.ended = true;
+ });
+ })
+ .on('field', function(field, value) {
+ assert.equal(field, 'title');
+ assert.equal(value, '');
+ })
+ .on('file', function(field, file) {
+ assert.equal(field, 'upload');
+ assert.strictEqual(uploads[file.filename].file, file);
+ })
+ .on('end', function() {
+ assert.ok(uploads['shortest_video.flv']);
+ assert.ok(uploads['shortest_video.flv'].ended);
+ assert.ok(uploads['shortest_video.flv'].progress.length > 3);
+ assert.equal(uploads['shortest_video.flv'].progress.slice(-1), uploads['shortest_video.flv'].file.length);
+ assert.ok(uploads['shortest_video.mp4']);
+ assert.ok(uploads['shortest_video.mp4'].ended);
+ assert.ok(uploads['shortest_video.mp4'].progress.length > 3);
+
+ server.close();
+ res.writeHead(200);
+ res.end('good');
+ });
+});
+
+server.listen(TEST_PORT, function() {
+ var client = http.createClient(TEST_PORT),
+ stat = fs.statSync(FIXTURE),
+ headers = {
+ 'content-type': 'multipart/form-data; boundary='+BOUNDARY,
+ 'content-length': stat.size,
+ }
+ request = client.request('POST', '/', headers),
+ fixture = new fs.ReadStream(FIXTURE);
+
+ fixture
+ .on('data', function(b) {
+ request.write(b);
+ })
+ .on('end', function() {
+ request.end();
+ });
+});
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js
new file mode 100755
index 0000000..50b2361
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('urun')(__dirname)
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js
new file mode 100644
index 0000000..bcf61d7
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js
@@ -0,0 +1,63 @@
+var common = require('../common');
+var test = require('utest');
+var assert = common.assert;
+var IncomingForm = common.require('incoming_form').IncomingForm;
+var path = require('path');
+
+var from;
+test('IncomingForm', {
+ before: function() {
+ form = new IncomingForm();
+ },
+
+ '#_fileName with regular characters': function() {
+ var filename = 'foo.txt';
+ assert.equal(form._fileName(makeHeader(filename)), 'foo.txt');
+ },
+
+ '#_fileName with unescaped quote': function() {
+ var filename = 'my".txt';
+ assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
+ },
+
+ '#_fileName with escaped quote': function() {
+ var filename = 'my%22.txt';
+ assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
+ },
+
+ '#_fileName with bad quote and additional sub-header': function() {
+ var filename = 'my".txt';
+ var header = makeHeader(filename) + '; foo="bar"';
+ assert.equal(form._fileName(header), filename);
+ },
+
+ '#_fileName with semicolon': function() {
+ var filename = 'my;.txt';
+ assert.equal(form._fileName(makeHeader(filename)), 'my;.txt');
+ },
+
+ '#_fileName with utf8 character': function() {
+ var filename = 'my&#9731;.txt';
+ assert.equal(form._fileName(makeHeader(filename)), 'my☃.txt');
+ },
+
+ '#_uploadPath strips harmful characters from extension when keepExtensions': function() {
+ form.keepExtensions = true;
+
+ var ext = path.extname(form._uploadPath('fine.jpg?foo=bar'));
+ assert.equal(ext, '.jpg');
+
+ var ext = path.extname(form._uploadPath('fine?foo=bar'));
+ assert.equal(ext, '');
+
+ var ext = path.extname(form._uploadPath('super.cr2+dsad'));
+ assert.equal(ext, '.cr2');
+
+ var ext = path.extname(form._uploadPath('super.bar'));
+ assert.equal(ext, '.bar');
+ },
+});
+
+function makeHeader(filename) {
+ return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"';
+}
diff --git a/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js b/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js
new file mode 100644
index 0000000..9f1cef8
--- /dev/null
+++ b/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js
@@ -0,0 +1,47 @@
+var http = require('http');
+var fs = require('fs');
+var connections = 0;
+
+var server = http.createServer(function(req, res) {
+ var socket = req.socket;
+ console.log('Request: %s %s -> %s', req.method, req.url, socket.filename);
+
+ req.on('end', function() {
+ if (req.url !== '/') {
+ res.end(JSON.stringify({
+ method: req.method,
+ url: req.url,
+ filename: socket.filename,
+ }));
+ return;
+ }
+
+ res.writeHead(200, {'content-type': 'text/html'});
+ res.end(
+ '<form action="/upload" enctype="multipart/form-data" method="post">'+
+ '<input type="text" name="title"><br>'+
+ '<input type="file" name="upload" multiple="multiple"><br>'+
+ '<input type="submit" value="Upload">'+
+ '</form>'
+ );
+ });
+});
+
+server.on('connection', function(socket) {
+ connections++;
+
+ socket.id = connections;
+ socket.filename = 'connection-' + socket.id + '.http';
+ socket.file = fs.createWriteStream(socket.filename);
+ socket.pipe(socket.file);
+
+ console.log('--> %s', socket.filename);
+ socket.on('close', function() {
+ console.log('<-- %s', socket.filename);
+ });
+});
+
+var port = process.env.PORT || 8080;
+server.listen(port, function() {
+ console.log('Recording connections on port %s', port);
+});
diff --git a/node_modules/express/node_modules/connect/package.json b/node_modules/express/node_modules/connect/package.json
new file mode 100644
index 0000000..268592d
--- /dev/null
+++ b/node_modules/express/node_modules/connect/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "connect",
+ "version": "1.8.6",
+ "description": "High performance middleware framework",
+ "keywords": [
+ "framework",
+ "web",
+ "middleware",
+ "connect",
+ "rack"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/senchalabs/connect.git"
+ },
+ "author": {
+ "name": "TJ Holowaychuk",
+ "email": "tj@vision-media.ca",
+ "url": "http://tjholowaychuk.com"
+ },
+ "dependencies": {
+ "qs": ">= 0.4.0",
+ "mime": ">= 0.0.1",
+ "formidable": "1.0.x"
+ },
+ "devDependencies": {
+ "expresso": "0.9.2",
+ "koala": "0.1.2",
+ "less": "1.1.1",
+ "sass": "0.5.0",
+ "markdown": "0.2.1",
+ "ejs": "0.4.3",
+ "should": "0.3.2"
+ },
+ "main": "index",
+ "engines": {
+ "node": ">= 0.4.1 < 0.7.0"
+ },
+ "_id": "connect@1.8.6",
+ "optionalDependencies": {},
+ "_engineSupported": true,
+ "_npmVersion": "1.1.12",
+ "_nodeVersion": "v0.6.14",
+ "_defaultsLoaded": true,
+ "dist": {
+ "shasum": "0c455688d8df01c210eb2e53591436a50e0c506c"
+ },
+ "_from": "connect@1.x"
+}
diff --git a/node_modules/express/node_modules/mime/LICENSE b/node_modules/express/node_modules/mime/LICENSE
new file mode 100644
index 0000000..451fc45
--- /dev/null
+++ b/node_modules/express/node_modules/mime/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/express/node_modules/mime/README.md b/node_modules/express/node_modules/mime/README.md
new file mode 100644
index 0000000..a157de1
--- /dev/null
+++ b/node_modules/express/node_modules/mime/README.md
@@ -0,0 +1,50 @@
+# mime
+
+Support for mapping between file extensions and MIME types. This module uses the latest version of the Apache "mime.types" file (maps over 620 types to 800+ extensions). It is also trivially easy to add your own types and extensions, should you need to do that.
+
+## Install
+
+Install with [npm](http://github.com/isaacs/npm):
+
+ npm install mime
+
+## API - Queries
+
+### mime.lookup(path)
+Get the mime type associated with a file. This is method is case-insensitive. Everything in path up to and including the last '/' or '.' is ignored, so you can pass it paths, filenames, or extensions, like so:
+
+ var mime = require('mime');
+
+ mime.lookup('/path/to/file.txt'); // => 'text/plain'
+ mime.lookup('file.txt'); // => 'text/plain'
+ mime.lookup('.txt'); // => 'text/plain'
+ mime.lookup('htm'); // => 'text/html'
+
+### mime.extension(type) - lookup the default extension for type
+
+ mime.extension('text/html'); // => 'html'
+ mime.extension('application/octet-stream'); // => 'bin'
+
+### mime.charsets.lookup() - map mime-type to charset
+
+ mime.charsets.lookup('text/plain'); // => 'UTF-8'
+
+(The logic for charset lookups is pretty rudimentary. Feel free to suggest improvements.)
+
+## API - Customizing
+
+The following APIs allow you to add your own type mappings within your project. If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types).
+### mime.define() - Add custom mime/extension mappings
+
+ mime.define({
+ 'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
+ 'application/x-my-type': ['x-mt', 'x-mtt'],
+ // etc ...
+ });
+
+ mime.lookup('x-sft'); // => 'text/x-some-format'
+ mime.extension('text/x-some-format'); // => 'x-sf'
+
+### mime.load(filepath) - Load mappings from an Apache ".types" format file
+
+ mime.load('./my_project.types');
diff --git a/node_modules/express/node_modules/mime/mime.js b/node_modules/express/node_modules/mime/mime.js
new file mode 100644
index 0000000..5fac753
--- /dev/null
+++ b/node_modules/express/node_modules/mime/mime.js
@@ -0,0 +1,92 @@
+var path = require('path'),
+ fs = require('fs');
+
+var mime = module.exports = {
+ /** Map of extension to mime type */
+ types: {},
+
+ /** Map of mime type to extension */
+ extensions :{},
+
+ /**
+ * Define mimetype -> extension mappings. Each key is a mime-type that maps
+ * to an array of extensions associated with the type. The first extension is
+ * used as the default extension for the type.
+ *
+ * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']});
+ *
+ * @param map (Object) type definitions
+ */
+ define: function(map) {
+ for (var type in map) {
+ var exts = map[type];
+
+ for (var i = 0; i < exts.length; i++) {
+ mime.types[exts[i]] = type;
+ }
+
+ // Default extension is the first one we encounter
+ if (!mime.extensions[type]) {
+ mime.extensions[type] = exts[0];
+ }
+ }
+ },
+
+ /**
+ * Load an Apache2-style ".types" file
+ *
+ * This may be called multiple times (it's expected). Where files declare
+ * overlapping types/extensions, the last file wins.
+ *
+ * @param file (String) path of file to load.
+ */
+ load: function(file) {
+ // Read file and split into lines
+ var map = {},
+ content = fs.readFileSync(file, 'ascii'),
+ lines = content.split(/[\r\n]+/);
+
+ lines.forEach(function(line, lineno) {
+ // Clean up whitespace/comments, and split into fields
+ var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
+ map[fields.shift()] = fields;
+ });
+
+ mime.define(map);
+ },
+
+ /**
+ * Lookup a mime type based on extension
+ */
+ lookup: function(path, fallback) {
+ var ext = path.replace(/.*[\.\/]/, '').toLowerCase();
+ return mime.types[ext] || fallback || mime.default_type;
+ },
+
+ /**
+ * Return file extension associated with a mime type
+ */
+ extension: function(mimeType) {
+ return mime.extensions[mimeType];
+ },
+
+ /**
+ * Lookup a charset based on mime type.
+ */
+ charsets: {
+ lookup: function (mimeType, fallback) {
+ // Assume text types are utf8. Modify mime logic as needed.
+ return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
+ }
+ }
+};
+
+// Load our local copy of
+// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
+mime.load(path.join(__dirname, 'types/mime.types'));
+
+// Overlay enhancements submitted by the node.js community
+mime.load(path.join(__dirname, 'types/node.types'));
+
+// Set the default type
+mime.default_type = mime.types.bin;
diff --git a/node_modules/express/node_modules/mime/package.json b/node_modules/express/node_modules/mime/package.json
new file mode 100644
index 0000000..a26fd79
--- /dev/null
+++ b/node_modules/express/node_modules/mime/package.json
@@ -0,0 +1,40 @@
+{
+ "author": {
+ "name": "Robert Kieffer",
+ "email": "robert@broofa.com",
+ "url": "http://github.com/broofa"
+ },
+ "contributors": [
+ {
+ "name": "Benjamin Thomas",
+ "email": "benjamin@benjaminthomas.org",
+ "url": "http://github.com/bentomas"
+ }
+ ],
+ "dependencies": {},
+ "description": "A comprehensive library for mime-type mapping",
+ "devDependencies": {
+ "async_testing": ""
+ },
+ "keywords": [
+ "util",
+ "mime"
+ ],
+ "main": "mime.js",
+ "name": "mime",
+ "repository": {
+ "url": "git://github.com/bentomas/node-mime.git",
+ "type": "git"
+ },
+ "version": "1.2.4",
+ "_id": "mime@1.2.4",
+ "optionalDependencies": {},
+ "engines": {
+ "node": "*"
+ },
+ "_engineSupported": true,
+ "_npmVersion": "1.1.12",
+ "_nodeVersion": "v0.6.14",
+ "_defaultsLoaded": true,
+ "_from": "mime@1.2.4"
+}
diff --git a/node_modules/express/node_modules/mime/test.js b/node_modules/express/node_modules/mime/test.js
new file mode 100644
index 0000000..b904895
--- /dev/null
+++ b/node_modules/express/node_modules/mime/test.js
@@ -0,0 +1,79 @@
+/**
+ * Requires the async_testing module
+ *
+ * Usage: node test.js
+ */
+var mime = require('./mime');
+exports["test mime lookup"] = function(test) {
+ // easy
+ test.equal('text/plain', mime.lookup('text.txt'));
+
+ // hidden file or multiple periods
+ test.equal('text/plain', mime.lookup('.text.txt'));
+
+ // just an extension
+ test.equal('text/plain', mime.lookup('.txt'));
+
+ // just an extension without a dot
+ test.equal('text/plain', mime.lookup('txt'));
+
+ // default
+ test.equal('application/octet-stream', mime.lookup('text.nope'));
+
+ // fallback
+ test.equal('fallback', mime.lookup('text.fallback', 'fallback'));
+
+ test.finish();
+};
+
+exports["test extension lookup"] = function(test) {
+ // easy
+ test.equal('txt', mime.extension(mime.types.text));
+ test.equal('html', mime.extension(mime.types.htm));
+ test.equal('bin', mime.extension('application/octet-stream'));
+
+ test.finish();
+};
+
+exports["test mime lookup uppercase"] = function(test) {
+ // easy
+ test.equal('text/plain', mime.lookup('TEXT.TXT'));
+
+ // just an extension
+ test.equal('text/plain', mime.lookup('.TXT'));
+
+ // just an extension without a dot
+ test.equal('text/plain', mime.lookup('TXT'));
+
+ // default
+ test.equal('application/octet-stream', mime.lookup('TEXT.NOPE'));
+
+ // fallback
+ test.equal('fallback', mime.lookup('TEXT.FALLBACK', 'fallback'));
+
+ test.finish();
+};
+
+exports["test custom types"] = function(test) {
+ test.equal('application/octet-stream', mime.lookup('file.buffer'));
+ test.equal('audio/mp4', mime.lookup('file.m4a'));
+
+ test.finish();
+};
+
+exports["test charset lookup"] = function(test) {
+ // easy
+ test.equal('UTF-8', mime.charsets.lookup('text/plain'));
+
+ // none
+ test.ok(typeof mime.charsets.lookup(mime.types.js) == 'undefined');
+
+ // fallback
+ test.equal('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
+
+ test.finish();
+};
+
+if (module == require.main) {
+ require('async_testing').run(__filename, process.ARGV);
+}
diff --git a/node_modules/express/node_modules/mime/types/mime.types b/node_modules/express/node_modules/mime/types/mime.types
new file mode 100644
index 0000000..6a90929
--- /dev/null
+++ b/node_modules/express/node_modules/mime/types/mime.types
@@ -0,0 +1,1479 @@
+# This file maps Internet media types to unique file extension(s).
+# Although created for httpd, this file is used by many software systems
+# and has been placed in the public domain for unlimited redisribution.
+#
+# The table below contains both registered and (common) unregistered types.
+# A type that has no unique extension can be ignored -- they are listed
+# here to guide configurations toward known types and to make it easier to
+# identify "new" types. File extensions are also commonly used to indicate
+# content languages and encodings, so choose them carefully.
+#
+# Internet media types should be registered as described in RFC 4288.
+# The registry is at <http://www.iana.org/assignments/media-types/>.
+#
+# MIME type (lowercased) Extensions
+# ============================================ ==========
+# application/1d-interleaved-parityfec
+# application/3gpp-ims+xml
+# application/activemessage
+application/andrew-inset ez
+# application/applefile
+application/applixware aw
+application/atom+xml atom
+application/atomcat+xml atomcat
+# application/atomicmail
+application/atomsvc+xml atomsvc
+# application/auth-policy+xml
+# application/batch-smtp
+# application/beep+xml
+# application/cals-1840
+application/ccxml+xml ccxml
+application/cdmi-capability cdmia
+application/cdmi-container cdmic
+application/cdmi-domain cdmid
+application/cdmi-object cdmio
+application/cdmi-queue cdmiq
+# application/cea-2018+xml
+# application/cellml+xml
+# application/cfw
+# application/cnrp+xml
+# application/commonground
+# application/conference-info+xml
+# application/cpl+xml
+# application/csta+xml
+# application/cstadata+xml
+application/cu-seeme cu
+# application/cybercash
+application/davmount+xml davmount
+# application/dca-rft
+# application/dec-dx
+# application/dialog-info+xml
+# application/dicom
+# application/dns
+# application/dskpp+xml
+application/dssc+der dssc
+application/dssc+xml xdssc
+# application/dvcs
+application/ecmascript ecma
+# application/edi-consent
+# application/edi-x12
+# application/edifact
+application/emma+xml emma
+# application/epp+xml
+application/epub+zip epub
+# application/eshop
+# application/example
+application/exi exi
+# application/fastinfoset
+# application/fastsoap
+# application/fits
+application/font-tdpfr pfr
+# application/framework-attributes+xml
+# application/h224
+# application/held+xml
+# application/http
+application/hyperstudio stk
+# application/ibe-key-request+xml
+# application/ibe-pkg-reply+xml
+# application/ibe-pp-data
+# application/iges
+# application/im-iscomposing+xml
+# application/index
+# application/index.cmd
+# application/index.obj
+# application/index.response
+# application/index.vnd
+# application/iotp
+application/ipfix ipfix
+# application/ipp
+# application/isup
+application/java-archive jar
+application/java-serialized-object ser
+application/java-vm class
+application/javascript js
+application/json json
+# application/kpml-request+xml
+# application/kpml-response+xml
+application/lost+xml lostxml
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+# application/macwriteii
+application/mads+xml mads
+application/marc mrc
+application/marcxml+xml mrcx
+application/mathematica ma nb mb
+# application/mathml-content+xml
+# application/mathml-presentation+xml
+application/mathml+xml mathml
+# application/mbms-associated-procedure-description+xml
+# application/mbms-deregister+xml
+# application/mbms-envelope+xml
+# application/mbms-msk+xml
+# application/mbms-msk-response+xml
+# application/mbms-protection-description+xml
+# application/mbms-reception-report+xml
+# application/mbms-register+xml
+# application/mbms-register-response+xml
+# application/mbms-user-service-description+xml
+application/mbox mbox
+# application/media_control+xml
+application/mediaservercontrol+xml mscml
+application/metalink4+xml meta4
+application/mets+xml mets
+# application/mikey
+application/mods+xml mods
+# application/moss-keys
+# application/moss-signature
+# application/mosskey-data
+# application/mosskey-request
+application/mp21 m21 mp21
+application/mp4 mp4s
+# application/mpeg4-generic
+# application/mpeg4-iod
+# application/mpeg4-iod-xmt
+# application/msc-ivr+xml
+# application/msc-mixer+xml
+application/msword doc dot
+application/mxf mxf
+# application/nasdata
+# application/news-checkgroups
+# application/news-groupinfo
+# application/news-transmission
+# application/nss
+# application/ocsp-request
+# application/ocsp-response
+application/octet-stream bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy
+application/oda oda
+application/oebps-package+xml opf
+application/ogg ogx
+application/onenote onetoc onetoc2 onetmp onepkg
+# application/parityfec
+application/patch-ops-error+xml xer
+application/pdf pdf
+application/pgp-encrypted pgp
+# application/pgp-keys
+application/pgp-signature asc sig
+application/pics-rules prf
+# application/pidf+xml
+# application/pidf-diff+xml
+application/pkcs10 p10
+application/pkcs7-mime p7m p7c
+application/pkcs7-signature p7s
+application/pkcs8 p8
+application/pkix-attr-cert ac
+application/pkix-cert cer
+application/pkix-crl crl
+application/pkix-pkipath pkipath
+application/pkixcmp pki
+application/pls+xml pls
+# application/poc-settings+xml
+application/postscript ai eps ps
+# application/prs.alvestrand.titrax-sheet
+application/prs.cww cww
+# application/prs.nprend
+# application/prs.plucker
+# application/prs.rdf-xml-crypt
+# application/prs.xsf+xml
+application/pskc+xml pskcxml
+# application/qsig
+application/rdf+xml rdf
+application/reginfo+xml rif
+application/relax-ng-compact-syntax rnc
+# application/remote-printing
+application/resource-lists+xml rl
+application/resource-lists-diff+xml rld
+# application/riscos
+# application/rlmi+xml
+application/rls-services+xml rs
+application/rsd+xml rsd
+application/rss+xml rss
+application/rtf rtf
+# application/rtx
+# application/samlassertion+xml
+# application/samlmetadata+xml
+application/sbml+xml sbml
+application/scvp-cv-request scq
+application/scvp-cv-response scs
+application/scvp-vp-request spq
+application/scvp-vp-response spp
+application/sdp sdp
+# application/set-payment
+application/set-payment-initiation setpay
+# application/set-registration
+application/set-registration-initiation setreg
+# application/sgml
+# application/sgml-open-catalog
+application/shf+xml shf
+# application/sieve
+# application/simple-filter+xml
+# application/simple-message-summary
+# application/simplesymbolcontainer
+# application/slate
+# application/smil
+application/smil+xml smi smil
+# application/soap+fastinfoset
+# application/soap+xml
+application/sparql-query rq
+application/sparql-results+xml srx
+# application/spirits-event+xml
+application/srgs gram
+application/srgs+xml grxml
+application/sru+xml sru
+application/ssml+xml ssml
+# application/tamp-apex-update
+# application/tamp-apex-update-confirm
+# application/tamp-community-update
+# application/tamp-community-update-confirm
+# application/tamp-error
+# application/tamp-sequence-adjust
+# application/tamp-sequence-adjust-confirm
+# application/tamp-status-query
+# application/tamp-status-response
+# application/tamp-update
+# application/tamp-update-confirm
+application/tei+xml tei teicorpus
+application/thraud+xml tfi
+# application/timestamp-query
+# application/timestamp-reply
+application/timestamped-data tsd
+# application/tve-trigger
+# application/ulpfec
+# application/vemmi
+# application/vividence.scriptfile
+# application/vnd.3gpp.bsf+xml
+application/vnd.3gpp.pic-bw-large plb
+application/vnd.3gpp.pic-bw-small psb
+application/vnd.3gpp.pic-bw-var pvb
+# application/vnd.3gpp.sms
+# application/vnd.3gpp2.bcmcsinfo+xml
+# application/vnd.3gpp2.sms
+application/vnd.3gpp2.tcap tcap
+application/vnd.3m.post-it-notes pwn
+application/vnd.accpac.simply.aso aso
+application/vnd.accpac.simply.imp imp
+application/vnd.acucobol acu
+application/vnd.acucorp atc acutc
+application/vnd.adobe.air-application-installer-package+zip air
+application/vnd.adobe.fxp fxp fxpl
+# application/vnd.adobe.partial-upload
+application/vnd.adobe.xdp+xml xdp
+application/vnd.adobe.xfdf xfdf
+# application/vnd.aether.imp
+# application/vnd.ah-barcode
+application/vnd.ahead.space ahead
+application/vnd.airzip.filesecure.azf azf
+application/vnd.airzip.filesecure.azs azs
+application/vnd.amazon.ebook azw
+application/vnd.americandynamics.acc acc
+application/vnd.amiga.ami ami
+# application/vnd.amundsen.maze+xml
+application/vnd.android.package-archive apk
+application/vnd.anser-web-certificate-issue-initiation cii
+application/vnd.anser-web-funds-transfer-initiation fti
+application/vnd.antix.game-component atx
+application/vnd.apple.installer+xml mpkg
+application/vnd.apple.mpegurl m3u8
+# application/vnd.arastra.swi
+application/vnd.aristanetworks.swi swi
+application/vnd.audiograph aep
+# application/vnd.autopackage
+# application/vnd.avistar+xml
+application/vnd.blueice.multipass mpm
+# application/vnd.bluetooth.ep.oob
+application/vnd.bmi bmi
+application/vnd.businessobjects rep
+# application/vnd.cab-jscript
+# application/vnd.canon-cpdl
+# application/vnd.canon-lips
+# application/vnd.cendio.thinlinc.clientconf
+application/vnd.chemdraw+xml cdxml
+application/vnd.chipnuts.karaoke-mmd mmd
+application/vnd.cinderella cdy
+# application/vnd.cirpack.isdn-ext
+application/vnd.claymore cla
+application/vnd.cloanto.rp9 rp9
+application/vnd.clonk.c4group c4g c4d c4f c4p c4u
+application/vnd.cluetrust.cartomobile-config c11amc
+application/vnd.cluetrust.cartomobile-config-pkg c11amz
+# application/vnd.commerce-battelle
+application/vnd.commonspace csp
+application/vnd.contact.cmsg cdbcmsg
+application/vnd.cosmocaller cmc
+application/vnd.crick.clicker clkx
+application/vnd.crick.clicker.keyboard clkk
+application/vnd.crick.clicker.palette clkp
+application/vnd.crick.clicker.template clkt
+application/vnd.crick.clicker.wordbank clkw
+application/vnd.criticaltools.wbs+xml wbs
+application/vnd.ctc-posml pml
+# application/vnd.ctct.ws+xml
+# application/vnd.cups-pdf
+# application/vnd.cups-postscript
+application/vnd.cups-ppd ppd
+# application/vnd.cups-raster
+# application/vnd.cups-raw
+application/vnd.curl.car car
+application/vnd.curl.pcurl pcurl
+# application/vnd.cybank
+application/vnd.data-vision.rdz rdz
+application/vnd.dece.data uvf uvvf uvd uvvd
+application/vnd.dece.ttml+xml uvt uvvt
+application/vnd.dece.unspecified uvx uvvx
+application/vnd.denovo.fcselayout-link fe_launch
+# application/vnd.dir-bi.plate-dl-nosuffix
+application/vnd.dna dna
+application/vnd.dolby.mlp mlp
+# application/vnd.dolby.mobile.1
+# application/vnd.dolby.mobile.2
+application/vnd.dpgraph dpg
+application/vnd.dreamfactory dfac
+application/vnd.dvb.ait ait
+# application/vnd.dvb.dvbj
+# application/vnd.dvb.esgcontainer
+# application/vnd.dvb.ipdcdftnotifaccess
+# application/vnd.dvb.ipdcesgaccess
+# application/vnd.dvb.ipdcesgaccess2
+# application/vnd.dvb.ipdcesgpdd
+# application/vnd.dvb.ipdcroaming
+# application/vnd.dvb.iptv.alfec-base
+# application/vnd.dvb.iptv.alfec-enhancement
+# application/vnd.dvb.notif-aggregate-root+xml
+# application/vnd.dvb.notif-container+xml
+# application/vnd.dvb.notif-generic+xml
+# application/vnd.dvb.notif-ia-msglist+xml
+# application/vnd.dvb.notif-ia-registration-request+xml
+# application/vnd.dvb.notif-ia-registration-response+xml
+# application/vnd.dvb.notif-init+xml
+# application/vnd.dvb.pfr
+application/vnd.dvb.service svc
+# application/vnd.dxr
+application/vnd.dynageo geo
+# application/vnd.easykaraoke.cdgdownload
+# application/vnd.ecdis-update
+application/vnd.ecowin.chart mag
+# application/vnd.ecowin.filerequest
+# application/vnd.ecowin.fileupdate
+# application/vnd.ecowin.series
+# application/vnd.ecowin.seriesrequest
+# application/vnd.ecowin.seriesupdate
+# application/vnd.emclient.accessrequest+xml
+application/vnd.enliven nml
+application/vnd.epson.esf esf
+application/vnd.epson.msf msf
+application/vnd.epson.quickanime qam
+application/vnd.epson.salt slt
+application/vnd.epson.ssf ssf
+# application/vnd.ericsson.quickcall
+application/vnd.eszigno3+xml es3 et3
+# application/vnd.etsi.aoc+xml
+# application/vnd.etsi.cug+xml
+# application/vnd.etsi.iptvcommand+xml
+# application/vnd.etsi.iptvdiscovery+xml
+# application/vnd.etsi.iptvprofile+xml
+# application/vnd.etsi.iptvsad-bc+xml
+# application/vnd.etsi.iptvsad-cod+xml
+# application/vnd.etsi.iptvsad-npvr+xml
+# application/vnd.etsi.iptvservice+xml
+# application/vnd.etsi.iptvsync+xml
+# application/vnd.etsi.iptvueprofile+xml
+# application/vnd.etsi.mcid+xml
+# application/vnd.etsi.overload-control-policy-dataset+xml
+# application/vnd.etsi.sci+xml
+# application/vnd.etsi.simservs+xml
+# application/vnd.etsi.tsl+xml
+# application/vnd.etsi.tsl.der
+# application/vnd.eudora.data
+application/vnd.ezpix-album ez2
+application/vnd.ezpix-package ez3
+# application/vnd.f-secure.mobile
+application/vnd.fdf fdf
+application/vnd.fdsn.mseed mseed
+application/vnd.fdsn.seed seed dataless
+# application/vnd.ffsns
+# application/vnd.fints
+application/vnd.flographit gph
+application/vnd.fluxtime.clip ftc
+# application/vnd.font-fontforge-sfd
+application/vnd.framemaker fm frame maker book
+application/vnd.frogans.fnc fnc
+application/vnd.frogans.ltf ltf
+application/vnd.fsc.weblaunch fsc
+application/vnd.fujitsu.oasys oas
+application/vnd.fujitsu.oasys2 oa2
+application/vnd.fujitsu.oasys3 oa3
+application/vnd.fujitsu.oasysgp fg5
+application/vnd.fujitsu.oasysprs bh2
+# application/vnd.fujixerox.art-ex
+# application/vnd.fujixerox.art4
+# application/vnd.fujixerox.hbpl
+application/vnd.fujixerox.ddd ddd
+application/vnd.fujixerox.docuworks xdw
+application/vnd.fujixerox.docuworks.binder xbd
+# application/vnd.fut-misnet
+application/vnd.fuzzysheet fzs
+application/vnd.genomatix.tuxedo txd
+# application/vnd.geocube+xml
+application/vnd.geogebra.file ggb
+application/vnd.geogebra.tool ggt
+application/vnd.geometry-explorer gex gre
+application/vnd.geonext gxt
+application/vnd.geoplan g2w
+application/vnd.geospace g3w
+# application/vnd.globalplatform.card-content-mgt
+# application/vnd.globalplatform.card-content-mgt-response
+application/vnd.gmx gmx
+application/vnd.google-earth.kml+xml kml
+application/vnd.google-earth.kmz kmz
+application/vnd.grafeq gqf gqs
+# application/vnd.gridmp
+application/vnd.groove-account gac
+application/vnd.groove-help ghf
+application/vnd.groove-identity-message gim
+application/vnd.groove-injector grv
+application/vnd.groove-tool-message gtm
+application/vnd.groove-tool-template tpl
+application/vnd.groove-vcard vcg
+application/vnd.hal+xml hal
+application/vnd.handheld-entertainment+xml zmm
+application/vnd.hbci hbci
+# application/vnd.hcl-bireports
+application/vnd.hhe.lesson-player les
+application/vnd.hp-hpgl hpgl
+application/vnd.hp-hpid hpid
+application/vnd.hp-hps hps
+application/vnd.hp-jlyt jlt
+application/vnd.hp-pcl pcl
+application/vnd.hp-pclxl pclxl
+# application/vnd.httphone
+application/vnd.hydrostatix.sof-data sfd-hdstx
+application/vnd.hzn-3d-crossword x3d
+# application/vnd.ibm.afplinedata
+# application/vnd.ibm.electronic-media
+application/vnd.ibm.minipay mpy
+application/vnd.ibm.modcap afp listafp list3820
+application/vnd.ibm.rights-management irm
+application/vnd.ibm.secure-container sc
+application/vnd.iccprofile icc icm
+application/vnd.igloader igl
+application/vnd.immervision-ivp ivp
+application/vnd.immervision-ivu ivu
+# application/vnd.informedcontrol.rms+xml
+# application/vnd.informix-visionary
+# application/vnd.infotech.project
+# application/vnd.infotech.project+xml
+application/vnd.insors.igm igm
+application/vnd.intercon.formnet xpw xpx
+application/vnd.intergeo i2g
+# application/vnd.intertrust.digibox
+# application/vnd.intertrust.nncp
+application/vnd.intu.qbo qbo
+application/vnd.intu.qfx qfx
+# application/vnd.iptc.g2.conceptitem+xml
+# application/vnd.iptc.g2.knowledgeitem+xml
+# application/vnd.iptc.g2.newsitem+xml
+# application/vnd.iptc.g2.packageitem+xml
+application/vnd.ipunplugged.rcprofile rcprofile
+application/vnd.irepository.package+xml irp
+application/vnd.is-xpr xpr
+application/vnd.isac.fcs fcs
+application/vnd.jam jam
+# application/vnd.japannet-directory-service
+# application/vnd.japannet-jpnstore-wakeup
+# application/vnd.japannet-payment-wakeup
+# application/vnd.japannet-registration
+# application/vnd.japannet-registration-wakeup
+# application/vnd.japannet-setstore-wakeup
+# application/vnd.japannet-verification
+# application/vnd.japannet-verification-wakeup
+application/vnd.jcp.javame.midlet-rms rms
+application/vnd.jisp jisp
+application/vnd.joost.joda-archive joda
+application/vnd.kahootz ktz ktr
+application/vnd.kde.karbon karbon
+application/vnd.kde.kchart chrt
+application/vnd.kde.kformula kfo
+application/vnd.kde.kivio flw
+application/vnd.kde.kontour kon
+application/vnd.kde.kpresenter kpr kpt
+application/vnd.kde.kspread ksp
+application/vnd.kde.kword kwd kwt
+application/vnd.kenameaapp htke
+application/vnd.kidspiration kia
+application/vnd.kinar kne knp
+application/vnd.koan skp skd skt skm
+application/vnd.kodak-descriptor sse
+application/vnd.las.las+xml lasxml
+# application/vnd.liberty-request+xml
+application/vnd.llamagraphics.life-balance.desktop lbd
+application/vnd.llamagraphics.life-balance.exchange+xml lbe
+application/vnd.lotus-1-2-3 123
+application/vnd.lotus-approach apr
+application/vnd.lotus-freelance pre
+application/vnd.lotus-notes nsf
+application/vnd.lotus-organizer org
+application/vnd.lotus-screencam scm
+application/vnd.lotus-wordpro lwp
+application/vnd.macports.portpkg portpkg
+# application/vnd.marlin.drm.actiontoken+xml
+# application/vnd.marlin.drm.conftoken+xml
+# application/vnd.marlin.drm.license+xml
+# application/vnd.marlin.drm.mdcf
+application/vnd.mcd mcd
+application/vnd.medcalcdata mc1
+application/vnd.mediastation.cdkey cdkey
+# application/vnd.meridian-slingshot
+application/vnd.mfer mwf
+application/vnd.mfmp mfm
+application/vnd.micrografx.flo flo
+application/vnd.micrografx.igx igx
+application/vnd.mif mif
+# application/vnd.minisoft-hp3000-save
+# application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf daf
+application/vnd.mobius.dis dis
+application/vnd.mobius.mbk mbk
+application/vnd.mobius.mqy mqy
+application/vnd.mobius.msl msl
+application/vnd.mobius.plc plc
+application/vnd.mobius.txf txf
+application/vnd.mophun.application mpn
+application/vnd.mophun.certificate mpc
+# application/vnd.motorola.flexsuite
+# application/vnd.motorola.flexsuite.adsi
+# application/vnd.motorola.flexsuite.fis
+# application/vnd.motorola.flexsuite.gotap
+# application/vnd.motorola.flexsuite.kmr
+# application/vnd.motorola.flexsuite.ttc
+# application/vnd.motorola.flexsuite.wem
+# application/vnd.motorola.iprm
+application/vnd.mozilla.xul+xml xul
+application/vnd.ms-artgalry cil
+# application/vnd.ms-asf
+application/vnd.ms-cab-compressed cab
+application/vnd.ms-excel xls xlm xla xlc xlt xlw
+application/vnd.ms-excel.addin.macroenabled.12 xlam
+application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
+application/vnd.ms-excel.sheet.macroenabled.12 xlsm
+application/vnd.ms-excel.template.macroenabled.12 xltm
+application/vnd.ms-fontobject eot
+application/vnd.ms-htmlhelp chm
+application/vnd.ms-ims ims
+application/vnd.ms-lrm lrm
+# application/vnd.ms-office.activex+xml
+application/vnd.ms-officetheme thmx
+application/vnd.ms-pki.seccat cat
+application/vnd.ms-pki.stl stl
+# application/vnd.ms-playready.initiator+xml
+application/vnd.ms-powerpoint ppt pps pot
+application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
+application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
+application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
+application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
+application/vnd.ms-powerpoint.template.macroenabled.12 potm
+application/vnd.ms-project mpp mpt
+# application/vnd.ms-tnef
+# application/vnd.ms-wmdrm.lic-chlg-req
+# application/vnd.ms-wmdrm.lic-resp
+# application/vnd.ms-wmdrm.meter-chlg-req
+# application/vnd.ms-wmdrm.meter-resp
+application/vnd.ms-word.document.macroenabled.12 docm
+application/vnd.ms-word.template.macroenabled.12 dotm
+application/vnd.ms-works wps wks wcm wdb
+application/vnd.ms-wpl wpl
+application/vnd.ms-xpsdocument xps
+application/vnd.mseq mseq
+# application/vnd.msign
+# application/vnd.multiad.creator
+# application/vnd.multiad.creator.cif
+# application/vnd.music-niff
+application/vnd.musician mus
+application/vnd.muvee.style msty
+# application/vnd.ncd.control
+# application/vnd.ncd.reference
+# application/vnd.nervana
+# application/vnd.netfpx
+application/vnd.neurolanguage.nlu nlu
+application/vnd.noblenet-directory nnd
+application/vnd.noblenet-sealer nns
+application/vnd.noblenet-web nnw
+# application/vnd.nokia.catalogs
+# application/vnd.nokia.conml+wbxml
+# application/vnd.nokia.conml+xml
+# application/vnd.nokia.isds-radio-presets
+# application/vnd.nokia.iptv.config+xml
+# application/vnd.nokia.landmark+wbxml
+# application/vnd.nokia.landmark+xml
+# application/vnd.nokia.landmarkcollection+xml
+# application/vnd.nokia.n-gage.ac+xml
+application/vnd.nokia.n-gage.data ngdat
+application/vnd.nokia.n-gage.symbian.install n-gage
+# application/vnd.nokia.ncd
+# application/vnd.nokia.pcd+wbxml
+# application/vnd.nokia.pcd+xml
+application/vnd.nokia.radio-preset rpst
+application/vnd.nokia.radio-presets rpss
+application/vnd.novadigm.edm edm
+application/vnd.novadigm.edx edx
+application/vnd.novadigm.ext ext
+# application/vnd.ntt-local.file-transfer
+# application/vnd.ntt-local.sip-ta_remote
+# application/vnd.ntt-local.sip-ta_tcp_stream
+application/vnd.oasis.opendocument.chart odc
+application/vnd.oasis.opendocument.chart-template otc
+application/vnd.oasis.opendocument.database odb
+application/vnd.oasis.opendocument.formula odf
+application/vnd.oasis.opendocument.formula-template odft
+application/vnd.oasis.opendocument.graphics odg
+application/vnd.oasis.opendocument.graphics-template otg
+application/vnd.oasis.opendocument.image odi
+application/vnd.oasis.opendocument.image-template oti
+application/vnd.oasis.opendocument.presentation odp
+application/vnd.oasis.opendocument.presentation-template otp
+application/vnd.oasis.opendocument.spreadsheet ods
+application/vnd.oasis.opendocument.spreadsheet-template ots
+application/vnd.oasis.opendocument.text odt
+application/vnd.oasis.opendocument.text-master odm
+application/vnd.oasis.opendocument.text-template ott
+application/vnd.oasis.opendocument.text-web oth
+# application/vnd.obn
+# application/vnd.oipf.contentaccessdownload+xml
+# application/vnd.oipf.contentaccessstreaming+xml
+# application/vnd.oipf.cspg-hexbinary
+# application/vnd.oipf.dae.svg+xml
+# application/vnd.oipf.dae.xhtml+xml
+# application/vnd.oipf.mippvcontrolmessage+xml
+# application/vnd.oipf.pae.gem
+# application/vnd.oipf.spdiscovery+xml
+# application/vnd.oipf.spdlist+xml
+# application/vnd.oipf.ueprofile+xml
+# application/vnd.oipf.userprofile+xml
+application/vnd.olpc-sugar xo
+# application/vnd.oma-scws-config
+# application/vnd.oma-scws-http-request
+# application/vnd.oma-scws-http-response
+# application/vnd.oma.bcast.associated-procedure-parameter+xml
+# application/vnd.oma.bcast.drm-trigger+xml
+# application/vnd.oma.bcast.imd+xml
+# application/vnd.oma.bcast.ltkm
+# application/vnd.oma.bcast.notification+xml
+# application/vnd.oma.bcast.provisioningtrigger
+# application/vnd.oma.bcast.sgboot
+# application/vnd.oma.bcast.sgdd+xml
+# application/vnd.oma.bcast.sgdu
+# application/vnd.oma.bcast.simple-symbol-container
+# application/vnd.oma.bcast.smartcard-trigger+xml
+# application/vnd.oma.bcast.sprov+xml
+# application/vnd.oma.bcast.stkm
+# application/vnd.oma.cab-address-book+xml
+# application/vnd.oma.cab-pcc+xml
+# application/vnd.oma.dcd
+# application/vnd.oma.dcdc
+application/vnd.oma.dd2+xml dd2
+# application/vnd.oma.drm.risd+xml
+# application/vnd.oma.group-usage-list+xml
+# application/vnd.oma.poc.detailed-progress-report+xml
+# application/vnd.oma.poc.final-report+xml
+# application/vnd.oma.poc.groups+xml
+# application/vnd.oma.poc.invocation-descriptor+xml
+# application/vnd.oma.poc.optimized-progress-report+xml
+# application/vnd.oma.push
+# application/vnd.oma.scidm.messages+xml
+# application/vnd.oma.xcap-directory+xml
+# application/vnd.omads-email+xml
+# application/vnd.omads-file+xml
+# application/vnd.omads-folder+xml
+# application/vnd.omaloc-supl-init
+application/vnd.openofficeorg.extension oxt
+# application/vnd.openxmlformats-officedocument.custom-properties+xml
+# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
+# application/vnd.openxmlformats-officedocument.drawing+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
+# application/vnd.openxmlformats-officedocument.extended-properties+xml
+# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
+# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
+# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
+application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
+# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
+application/vnd.openxmlformats-officedocument.presentationml.slide sldx
+# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
+application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
+# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
+application/vnd.openxmlformats-officedocument.presentationml.template potx
+# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
+# application/vnd.openxmlformats-officedocument.theme+xml
+# application/vnd.openxmlformats-officedocument.themeoverride+xml
+# application/vnd.openxmlformats-officedocument.vmldrawing
+# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
+# application/vnd.openxmlformats-package.core-properties+xml
+# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
+# application/vnd.openxmlformats-package.relationships+xml
+# application/vnd.quobject-quoxdocument
+# application/vnd.osa.netdeploy
+application/vnd.osgeo.mapguide.package mgp
+# application/vnd.osgi.bundle
+application/vnd.osgi.dp dp
+# application/vnd.otps.ct-kip+xml
+application/vnd.palm pdb pqa oprc
+# application/vnd.paos.xml
+application/vnd.pawaafile paw
+application/vnd.pg.format str
+application/vnd.pg.osasli ei6
+# application/vnd.piaccess.application-licence
+application/vnd.picsel efif
+application/vnd.pmi.widget wg
+# application/vnd.poc.group-advertisement+xml
+application/vnd.pocketlearn plf
+application/vnd.powerbuilder6 pbd
+# application/vnd.powerbuilder6-s
+# application/vnd.powerbuilder7
+# application/vnd.powerbuilder7-s
+# application/vnd.powerbuilder75
+# application/vnd.powerbuilder75-s
+# application/vnd.preminet
+application/vnd.previewsystems.box box
+application/vnd.proteus.magazine mgz
+application/vnd.publishare-delta-tree qps
+application/vnd.pvi.ptid1 ptid
+# application/vnd.pwg-multiplexed
+# application/vnd.pwg-xhtml-print+xml
+# application/vnd.qualcomm.brew-app-res
+application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb
+# application/vnd.radisys.moml+xml
+# application/vnd.radisys.msml+xml
+# application/vnd.radisys.msml-audit+xml
+# application/vnd.radisys.msml-audit-conf+xml
+# application/vnd.radisys.msml-audit-conn+xml
+# application/vnd.radisys.msml-audit-dialog+xml
+# application/vnd.radisys.msml-audit-stream+xml
+# application/vnd.radisys.msml-conf+xml
+# application/vnd.radisys.msml-dialog+xml
+# application/vnd.radisys.msml-dialog-base+xml
+# application/vnd.radisys.msml-dialog-fax-detect+xml
+# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
+# application/vnd.radisys.msml-dialog-group+xml
+# application/vnd.radisys.msml-dialog-speech+xml
+# application/vnd.radisys.msml-dialog-transform+xml
+# application/vnd.rainstor.data
+# application/vnd.rapid
+application/vnd.realvnc.bed bed
+application/vnd.recordare.musicxml mxl
+application/vnd.recordare.musicxml+xml musicxml
+# application/vnd.renlearn.rlprint
+application/vnd.rig.cryptonote cryptonote
+application/vnd.rim.cod cod
+application/vnd.rn-realmedia rm
+application/vnd.route66.link66+xml link66
+# application/vnd.ruckus.download
+# application/vnd.s3sms
+application/vnd.sailingtracker.track st
+# application/vnd.sbm.cid
+# application/vnd.sbm.mid2
+# application/vnd.scribus
+# application/vnd.sealed.3df
+# application/vnd.sealed.csf
+# application/vnd.sealed.doc
+# application/vnd.sealed.eml
+# application/vnd.sealed.mht
+# application/vnd.sealed.net
+# application/vnd.sealed.ppt
+# application/vnd.sealed.tiff
+# application/vnd.sealed.xls
+# application/vnd.sealedmedia.softseal.html
+# application/vnd.sealedmedia.softseal.pdf
+application/vnd.seemail see
+application/vnd.sema sema
+application/vnd.semd semd
+application/vnd.semf semf
+application/vnd.shana.informed.formdata ifm
+application/vnd.shana.informed.formtemplate itp
+application/vnd.shana.informed.interchange iif
+application/vnd.shana.informed.package ipk
+application/vnd.simtech-mindmapper twd twds
+application/vnd.smaf mmf
+# application/vnd.smart.notebook
+application/vnd.smart.teacher teacher
+# application/vnd.software602.filler.form+xml
+# application/vnd.software602.filler.form-xml-zip
+application/vnd.solent.sdkm+xml sdkm sdkd
+application/vnd.spotfire.dxp dxp
+application/vnd.spotfire.sfs sfs
+# application/vnd.sss-cod
+# application/vnd.sss-dtf
+# application/vnd.sss-ntf
+application/vnd.stardivision.calc sdc
+application/vnd.stardivision.draw sda
+application/vnd.stardivision.impress sdd
+application/vnd.stardivision.math smf
+application/vnd.stardivision.writer sdw vor
+application/vnd.stardivision.writer-global sgl
+application/vnd.stepmania.stepchart sm
+# application/vnd.street-stream
+application/vnd.sun.xml.calc sxc
+application/vnd.sun.xml.calc.template stc
+application/vnd.sun.xml.draw sxd
+application/vnd.sun.xml.draw.template std
+application/vnd.sun.xml.impress sxi
+application/vnd.sun.xml.impress.template sti
+application/vnd.sun.xml.math sxm
+application/vnd.sun.xml.writer sxw
+application/vnd.sun.xml.writer.global sxg
+application/vnd.sun.xml.writer.template stw
+# application/vnd.sun.wadl+xml
+application/vnd.sus-calendar sus susp
+application/vnd.svd svd
+# application/vnd.swiftview-ics
+application/vnd.symbian.install sis sisx
+application/vnd.syncml+xml xsm
+application/vnd.syncml.dm+wbxml bdm
+application/vnd.syncml.dm+xml xdm
+# application/vnd.syncml.dm.notification
+# application/vnd.syncml.ds.notification
+application/vnd.tao.intent-module-archive tao
+application/vnd.tmobile-livetv tmo
+application/vnd.trid.tpt tpt
+application/vnd.triscape.mxs mxs
+application/vnd.trueapp tra
+# application/vnd.truedoc
+# application/vnd.ubisoft.webplayer
+application/vnd.ufdl ufd ufdl
+application/vnd.uiq.theme utz
+application/vnd.umajin umj
+application/vnd.unity unityweb
+application/vnd.uoml+xml uoml
+# application/vnd.uplanet.alert
+# application/vnd.uplanet.alert-wbxml
+# application/vnd.uplanet.bearer-choice
+# application/vnd.uplanet.bearer-choice-wbxml
+# application/vnd.uplanet.cacheop
+# application/vnd.uplanet.cacheop-wbxml
+# application/vnd.uplanet.channel
+# application/vnd.uplanet.channel-wbxml
+# application/vnd.uplanet.list
+# application/vnd.uplanet.list-wbxml
+# application/vnd.uplanet.listcmd
+# application/vnd.uplanet.listcmd-wbxml
+# application/vnd.uplanet.signal
+application/vnd.vcx vcx
+# application/vnd.vd-study
+# application/vnd.vectorworks
+# application/vnd.verimatrix.vcas
+# application/vnd.vidsoft.vidconference
+application/vnd.visio vsd vst vss vsw
+application/vnd.visionary vis
+# application/vnd.vividence.scriptfile
+application/vnd.vsf vsf
+# application/vnd.wap.sic
+# application/vnd.wap.slc
+application/vnd.wap.wbxml wbxml
+application/vnd.wap.wmlc wmlc
+application/vnd.wap.wmlscriptc wmlsc
+application/vnd.webturbo wtb
+# application/vnd.wfa.wsc
+# application/vnd.wmc
+# application/vnd.wmf.bootstrap
+# application/vnd.wolfram.mathematica
+# application/vnd.wolfram.mathematica.package
+application/vnd.wolfram.player nbp
+application/vnd.wordperfect wpd
+application/vnd.wqd wqd
+# application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf stf
+# application/vnd.wv.csp+wbxml
+# application/vnd.wv.csp+xml
+# application/vnd.wv.ssp+xml
+application/vnd.xara xar
+application/vnd.xfdl xfdl
+# application/vnd.xfdl.webform
+# application/vnd.xmi+xml
+# application/vnd.xmpie.cpkg
+# application/vnd.xmpie.dpkg
+# application/vnd.xmpie.plan
+# application/vnd.xmpie.ppkg
+# application/vnd.xmpie.xlim
+application/vnd.yamaha.hv-dic hvd
+application/vnd.yamaha.hv-script hvs
+application/vnd.yamaha.hv-voice hvp
+application/vnd.yamaha.openscoreformat osf
+application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
+# application/vnd.yamaha.remote-setup
+application/vnd.yamaha.smaf-audio saf
+application/vnd.yamaha.smaf-phrase spf
+# application/vnd.yamaha.tunnel-udpencap
+application/vnd.yellowriver-custom-menu cmp
+application/vnd.zul zir zirz
+application/vnd.zzazz.deck+xml zaz
+application/voicexml+xml vxml
+# application/vq-rtcpxr
+# application/watcherinfo+xml
+# application/whoispp-query
+# application/whoispp-response
+application/widget wgt
+application/winhlp hlp
+# application/wita
+# application/wordperfect5.1
+application/wsdl+xml wsdl
+application/wspolicy+xml wspolicy
+application/x-7z-compressed 7z
+application/x-abiword abw
+application/x-ace-compressed ace
+application/x-authorware-bin aab x32 u32 vox
+application/x-authorware-map aam
+application/x-authorware-seg aas
+application/x-bcpio bcpio
+application/x-bittorrent torrent
+application/x-bzip bz
+application/x-bzip2 bz2 boz
+application/x-cdlink vcd
+application/x-chat chat
+application/x-chess-pgn pgn
+# application/x-compress
+application/x-cpio cpio
+application/x-csh csh
+application/x-debian-package deb udeb
+application/x-director dir dcr dxr cst cct cxt w3d fgd swa
+application/x-doom wad
+application/x-dtbncx+xml ncx
+application/x-dtbook+xml dtb
+application/x-dtbresource+xml res
+application/x-dvi dvi
+application/x-font-bdf bdf
+# application/x-font-dos
+# application/x-font-framemaker
+application/x-font-ghostscript gsf
+# application/x-font-libgrx
+application/x-font-linux-psf psf
+application/x-font-otf otf
+application/x-font-pcf pcf
+application/x-font-snf snf
+# application/x-font-speedo
+# application/x-font-sunos-news
+application/x-font-ttf ttf ttc
+application/x-font-type1 pfa pfb pfm afm
+application/x-font-woff woff
+# application/x-font-vfont
+application/x-futuresplash spl
+application/x-gnumeric gnumeric
+application/x-gtar gtar
+# application/x-gzip
+application/x-hdf hdf
+application/x-java-jnlp-file jnlp
+application/x-latex latex
+application/x-mobipocket-ebook prc mobi
+application/x-ms-application application
+application/x-ms-wmd wmd
+application/x-ms-wmz wmz
+application/x-ms-xbap xbap
+application/x-msaccess mdb
+application/x-msbinder obd
+application/x-mscardfile crd
+application/x-msclip clp
+application/x-msdownload exe dll com bat msi
+application/x-msmediaview mvb m13 m14
+application/x-msmetafile wmf
+application/x-msmoney mny
+application/x-mspublisher pub
+application/x-msschedule scd
+application/x-msterminal trm
+application/x-mswrite wri
+application/x-netcdf nc cdf
+application/x-pkcs12 p12 pfx
+application/x-pkcs7-certificates p7b spc
+application/x-pkcs7-certreqresp p7r
+application/x-rar-compressed rar
+application/x-sh sh
+application/x-shar shar
+application/x-shockwave-flash swf
+application/x-silverlight-app xap
+application/x-stuffit sit
+application/x-stuffitx sitx
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-tar tar
+application/x-tcl tcl
+application/x-tex tex
+application/x-tex-tfm tfm
+application/x-texinfo texinfo texi
+application/x-ustar ustar
+application/x-wais-source src
+application/x-x509-ca-cert der crt
+application/x-xfig fig
+application/x-xpinstall xpi
+# application/x400-bp
+# application/xcap-att+xml
+# application/xcap-caps+xml
+application/xcap-diff+xml xdf
+# application/xcap-el+xml
+# application/xcap-error+xml
+# application/xcap-ns+xml
+# application/xcon-conference-info-diff+xml
+# application/xcon-conference-info+xml
+application/xenc+xml xenc
+application/xhtml+xml xhtml xht
+# application/xhtml-voice+xml
+application/xml xml xsl
+application/xml-dtd dtd
+# application/xml-external-parsed-entity
+# application/xmpp+xml
+application/xop+xml xop
+application/xslt+xml xslt
+application/xspf+xml xspf
+application/xv+xml mxml xhvml xvml xvm
+application/yang yang
+application/yin+xml yin
+application/zip zip
+# audio/1d-interleaved-parityfec
+# audio/32kadpcm
+# audio/3gpp
+# audio/3gpp2
+# audio/ac3
+audio/adpcm adp
+# audio/amr
+# audio/amr-wb
+# audio/amr-wb+
+# audio/asc
+# audio/atrac-advanced-lossless
+# audio/atrac-x
+# audio/atrac3
+audio/basic au snd
+# audio/bv16
+# audio/bv32
+# audio/clearmode
+# audio/cn
+# audio/dat12
+# audio/dls
+# audio/dsr-es201108
+# audio/dsr-es202050
+# audio/dsr-es202211
+# audio/dsr-es202212
+# audio/dvi4
+# audio/eac3
+# audio/evrc
+# audio/evrc-qcp
+# audio/evrc0
+# audio/evrc1
+# audio/evrcb
+# audio/evrcb0
+# audio/evrcb1
+# audio/evrcwb
+# audio/evrcwb0
+# audio/evrcwb1
+# audio/example
+# audio/g719
+# audio/g722
+# audio/g7221
+# audio/g723
+# audio/g726-16
+# audio/g726-24
+# audio/g726-32
+# audio/g726-40
+# audio/g728
+# audio/g729
+# audio/g7291
+# audio/g729d
+# audio/g729e
+# audio/gsm
+# audio/gsm-efr
+# audio/gsm-hr-08
+# audio/ilbc
+# audio/l16
+# audio/l20
+# audio/l24
+# audio/l8
+# audio/lpc
+audio/midi mid midi kar rmi
+# audio/mobile-xmf
+audio/mp4 mp4a
+# audio/mp4a-latm
+# audio/mpa
+# audio/mpa-robust
+audio/mpeg mpga mp2 mp2a mp3 m2a m3a
+# audio/mpeg4-generic
+audio/ogg oga ogg spx
+# audio/parityfec
+# audio/pcma
+# audio/pcma-wb
+# audio/pcmu-wb
+# audio/pcmu
+# audio/prs.sid
+# audio/qcelp
+# audio/red
+# audio/rtp-enc-aescm128
+# audio/rtp-midi
+# audio/rtx
+# audio/smv
+# audio/smv0
+# audio/smv-qcp
+# audio/sp-midi
+# audio/speex
+# audio/t140c
+# audio/t38
+# audio/telephone-event
+# audio/tone
+# audio/uemclip
+# audio/ulpfec
+# audio/vdvi
+# audio/vmr-wb
+# audio/vnd.3gpp.iufp
+# audio/vnd.4sb
+# audio/vnd.audiokoz
+# audio/vnd.celp
+# audio/vnd.cisco.nse
+# audio/vnd.cmles.radio-events
+# audio/vnd.cns.anp1
+# audio/vnd.cns.inf1
+audio/vnd.dece.audio uva uvva
+audio/vnd.digital-winds eol
+# audio/vnd.dlna.adts
+# audio/vnd.dolby.heaac.1
+# audio/vnd.dolby.heaac.2
+# audio/vnd.dolby.mlp
+# audio/vnd.dolby.mps
+# audio/vnd.dolby.pl2
+# audio/vnd.dolby.pl2x
+# audio/vnd.dolby.pl2z
+# audio/vnd.dolby.pulse.1
+audio/vnd.dra dra
+audio/vnd.dts dts
+audio/vnd.dts.hd dtshd
+# audio/vnd.everad.plj
+# audio/vnd.hns.audio
+audio/vnd.lucent.voice lvp
+audio/vnd.ms-playready.media.pya pya
+# audio/vnd.nokia.mobile-xmf
+# audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800 ecelp4800
+audio/vnd.nuera.ecelp7470 ecelp7470
+audio/vnd.nuera.ecelp9600 ecelp9600
+# audio/vnd.octel.sbc
+# audio/vnd.qcelp
+# audio/vnd.rhetorex.32kadpcm
+audio/vnd.rip rip
+# audio/vnd.sealedmedia.softseal.mpeg
+# audio/vnd.vmx.cvsd
+# audio/vorbis
+# audio/vorbis-config
+audio/webm weba
+audio/x-aac aac
+audio/x-aiff aif aiff aifc
+audio/x-mpegurl m3u
+audio/x-ms-wax wax
+audio/x-ms-wma wma
+audio/x-pn-realaudio ram ra
+audio/x-pn-realaudio-plugin rmp
+audio/x-wav wav
+chemical/x-cdx cdx
+chemical/x-cif cif
+chemical/x-cmdf cmdf
+chemical/x-cml cml
+chemical/x-csml csml
+# chemical/x-pdb
+chemical/x-xyz xyz
+image/bmp bmp
+image/cgm cgm
+# image/example
+# image/fits
+image/g3fax g3
+image/gif gif
+image/ief ief
+# image/jp2
+image/jpeg jpeg jpg jpe
+# image/jpm
+# image/jpx
+image/ktx ktx
+# image/naplps
+image/png png
+image/prs.btif btif
+# image/prs.pti
+image/svg+xml svg svgz
+# image/t38
+image/tiff tiff tif
+# image/tiff-fx
+image/vnd.adobe.photoshop psd
+# image/vnd.cns.inf2
+image/vnd.dece.graphic uvi uvvi uvg uvvg
+image/vnd.dvb.subtitle sub
+image/vnd.djvu djvu djv
+image/vnd.dwg dwg
+image/vnd.dxf dxf
+image/vnd.fastbidsheet fbs
+image/vnd.fpx fpx
+image/vnd.fst fst
+image/vnd.fujixerox.edmics-mmr mmr
+image/vnd.fujixerox.edmics-rlc rlc
+# image/vnd.globalgraphics.pgb
+# image/vnd.microsoft.icon
+# image/vnd.mix
+image/vnd.ms-modi mdi
+image/vnd.net-fpx npx
+# image/vnd.radiance
+# image/vnd.sealed.png
+# image/vnd.sealedmedia.softseal.gif
+# image/vnd.sealedmedia.softseal.jpg
+# image/vnd.svf
+image/vnd.wap.wbmp wbmp
+image/vnd.xiff xif
+image/webp webp
+image/x-cmu-raster ras
+image/x-cmx cmx
+image/x-freehand fh fhc fh4 fh5 fh7
+image/x-icon ico
+image/x-pcx pcx
+image/x-pict pic pct
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+# message/cpim
+# message/delivery-status
+# message/disposition-notification
+# message/example
+# message/external-body
+# message/feedback-report
+# message/global
+# message/global-delivery-status
+# message/global-disposition-notification
+# message/global-headers
+# message/http
+# message/imdn+xml
+# message/news
+# message/partial
+message/rfc822 eml mime
+# message/s-http
+# message/sip
+# message/sipfrag
+# message/tracking-status
+# message/vnd.si.simp
+# model/example
+model/iges igs iges
+model/mesh msh mesh silo
+model/vnd.collada+xml dae
+model/vnd.dwf dwf
+# model/vnd.flatland.3dml
+model/vnd.gdl gdl
+# model/vnd.gs-gdl
+# model/vnd.gs.gdl
+model/vnd.gtw gtw
+# model/vnd.moml+xml
+model/vnd.mts mts
+# model/vnd.parasolid.transmit.binary
+# model/vnd.parasolid.transmit.text
+model/vnd.vtu vtu
+model/vrml wrl vrml
+# multipart/alternative
+# multipart/appledouble
+# multipart/byteranges
+# multipart/digest
+# multipart/encrypted
+# multipart/example
+# multipart/form-data
+# multipart/header-set
+# multipart/mixed
+# multipart/parallel
+# multipart/related
+# multipart/report
+# multipart/signed
+# multipart/voice-message
+# text/1d-interleaved-parityfec
+text/calendar ics ifb
+text/css css
+text/csv csv
+# text/directory
+# text/dns
+# text/ecmascript
+# text/enriched
+# text/example
+text/html html htm
+# text/javascript
+text/n3 n3
+# text/parityfec
+text/plain txt text conf def list log in
+# text/prs.fallenstein.rst
+text/prs.lines.tag dsc
+# text/vnd.radisys.msml-basic-layout
+# text/red
+# text/rfc822-headers
+text/richtext rtx
+# text/rtf
+# text/rtp-enc-aescm128
+# text/rtx
+text/sgml sgml sgm
+# text/t140
+text/tab-separated-values tsv
+text/troff t tr roff man me ms
+text/turtle ttl
+# text/ulpfec
+text/uri-list uri uris urls
+# text/vnd.abc
+text/vnd.curl curl
+text/vnd.curl.dcurl dcurl
+text/vnd.curl.scurl scurl
+text/vnd.curl.mcurl mcurl
+# text/vnd.dmclientscript
+# text/vnd.esmertec.theme-descriptor
+text/vnd.fly fly
+text/vnd.fmi.flexstor flx
+text/vnd.graphviz gv
+text/vnd.in3d.3dml 3dml
+text/vnd.in3d.spot spot
+# text/vnd.iptc.newsml
+# text/vnd.iptc.nitf
+# text/vnd.latex-z
+# text/vnd.motorola.reflex
+# text/vnd.ms-mediapackage
+# text/vnd.net2phone.commcenter.command
+# text/vnd.si.uricatalogue
+text/vnd.sun.j2me.app-descriptor jad
+# text/vnd.trolltech.linguist
+# text/vnd.wap.si
+# text/vnd.wap.sl
+text/vnd.wap.wml wml
+text/vnd.wap.wmlscript wmls
+text/x-asm s asm
+text/x-c c cc cxx cpp h hh dic
+text/x-fortran f for f77 f90
+text/x-pascal p pas
+text/x-java-source java
+text/x-setext etx
+text/x-uuencode uu
+text/x-vcalendar vcs
+text/x-vcard vcf
+# text/xml
+# text/xml-external-parsed-entity
+# video/1d-interleaved-parityfec
+video/3gpp 3gp
+# video/3gpp-tt
+video/3gpp2 3g2
+# video/bmpeg
+# video/bt656
+# video/celb
+# video/dv
+# video/example
+video/h261 h261
+video/h263 h263
+# video/h263-1998
+# video/h263-2000
+video/h264 h264
+# video/h264-rcdo
+# video/h264-svc
+video/jpeg jpgv
+# video/jpeg2000
+video/jpm jpm jpgm
+video/mj2 mj2 mjp2
+# video/mp1s
+# video/mp2p
+# video/mp2t
+video/mp4 mp4 mp4v mpg4
+# video/mp4v-es
+video/mpeg mpeg mpg mpe m1v m2v
+# video/mpeg4-generic
+# video/mpv
+# video/nv
+video/ogg ogv
+# video/parityfec
+# video/pointer
+video/quicktime qt mov
+# video/raw
+# video/rtp-enc-aescm128
+# video/rtx
+# video/smpte292m
+# video/ulpfec
+# video/vc1
+# video/vnd.cctv
+video/vnd.dece.hd uvh uvvh
+video/vnd.dece.mobile uvm uvvm
+# video/vnd.dece.mp4
+video/vnd.dece.pd uvp uvvp
+video/vnd.dece.sd uvs uvvs
+video/vnd.dece.video uvv uvvv
+# video/vnd.directv.mpeg
+# video/vnd.directv.mpeg-tts
+# video/vnd.dlna.mpeg-tts
+video/vnd.fvt fvt
+# video/vnd.hns.video
+# video/vnd.iptvforum.1dparityfec-1010
+# video/vnd.iptvforum.1dparityfec-2005
+# video/vnd.iptvforum.2dparityfec-1010
+# video/vnd.iptvforum.2dparityfec-2005
+# video/vnd.iptvforum.ttsavc
+# video/vnd.iptvforum.ttsmpeg2
+# video/vnd.motorola.video
+# video/vnd.motorola.videop
+video/vnd.mpegurl mxu m4u
+video/vnd.ms-playready.media.pyv pyv
+# video/vnd.nokia.interleaved-multimedia
+# video/vnd.nokia.videovoip
+# video/vnd.objectvideo
+# video/vnd.sealed.mpeg1
+# video/vnd.sealed.mpeg4
+# video/vnd.sealed.swf
+# video/vnd.sealedmedia.softseal.mov
+video/vnd.uvvu.mp4 uvu uvvu
+video/vnd.vivo viv
+video/webm webm
+video/x-f4v f4v
+video/x-fli fli
+video/x-flv flv
+video/x-m4v m4v
+video/x-ms-asf asf asx
+video/x-ms-wm wm
+video/x-ms-wmv wmv
+video/x-ms-wmx wmx
+video/x-ms-wvx wvx
+video/x-msvideo avi
+video/x-sgi-movie movie
+x-conference/x-cooltalk ice
diff --git a/node_modules/express/node_modules/mime/types/node.types b/node_modules/express/node_modules/mime/types/node.types
new file mode 100644
index 0000000..fdabaa4
--- /dev/null
+++ b/node_modules/express/node_modules/mime/types/node.types
@@ -0,0 +1,43 @@
+# What: Google Chrome Extension
+# Why: To allow apps to (work) be served with the right content type header.
+# http://codereview.chromium.org/2830017
+# Added by: niftylettuce
+application/x-chrome-extension crx
+
+# What: OTF Message Silencer
+# Why: To silence the "Resource interpreted as font but transferred with MIME
+# type font/otf" message that occurs in Google Chrome
+# Added by: niftylettuce
+font/opentype otf
+
+# What: HTC support
+# Why: To properly render .htc files such as CSS3PIE
+# Added by: niftylettuce
+text/x-component htc
+
+# What: HTML5 application cache manifest
+# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
+# per https://developer.mozilla.org/en/offline_resources_in_firefox
+# Added by: louisremi
+text/cache-manifest appcache manifest
+
+# What: node binary buffer format
+# Why: semi-standard extension w/in the node community
+# Added by: tootallnate
+application/octet-stream buffer
+
+# What: The "protected" MP-4 formats used by iTunes.
+# Why: Required for streaming music to browsers (?)
+# Added by: broofa
+application/mp4 m4p
+audio/mp4 m4a
+
+# What: Music playlist format (http://en.wikipedia.org/wiki/M3U)
+# Why: See https://github.com/bentomas/node-mime/pull/6
+# Added by: mjrusso
+application/x-mpegURL m3u8
+
+# What: Video format, Part of RFC1890
+# Why: See https://github.com/bentomas/node-mime/pull/6
+# Added by: mjrusso
+video/MP2T ts
diff --git a/node_modules/express/node_modules/mkdirp/.gitignore.orig b/node_modules/express/node_modules/mkdirp/.gitignore.orig
new file mode 100644
index 0000000..9303c34
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/.gitignore.orig
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log \ No newline at end of file
diff --git a/node_modules/express/node_modules/mkdirp/.gitignore.rej b/node_modules/express/node_modules/mkdirp/.gitignore.rej
new file mode 100644
index 0000000..69244ff
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/.gitignore.rej
@@ -0,0 +1,5 @@
+--- /dev/null
++++ .gitignore
+@@ -0,0 +1,2 @@
++node_modules/
++npm-debug.log \ No newline at end of file
diff --git a/node_modules/express/node_modules/mkdirp/.npmignore b/node_modules/express/node_modules/mkdirp/.npmignore
new file mode 100644
index 0000000..9303c34
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/.npmignore
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log \ No newline at end of file
diff --git a/node_modules/express/node_modules/mkdirp/LICENSE b/node_modules/express/node_modules/mkdirp/LICENSE
new file mode 100644
index 0000000..432d1ae
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/LICENSE
@@ -0,0 +1,21 @@
+Copyright 2010 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT/X11 license:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/express/node_modules/mkdirp/README.markdown b/node_modules/express/node_modules/mkdirp/README.markdown
new file mode 100644
index 0000000..b4dd75f
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/README.markdown
@@ -0,0 +1,54 @@
+mkdirp
+======
+
+Like `mkdir -p`, but in node.js!
+
+example
+=======
+
+pow.js
+------
+ var mkdirp = require('mkdirp');
+
+ mkdirp('/tmp/foo/bar/baz', function (err) {
+ if (err) console.error(err)
+ else console.log('pow!')
+ });
+
+Output
+ pow!
+
+And now /tmp/foo/bar/baz exists, huzzah!
+
+methods
+=======
+
+var mkdirp = require('mkdirp');
+
+mkdirp(dir, mode, cb)
+---------------------
+
+Create a new directory and any necessary subdirectories at `dir` with octal
+permission string `mode`.
+
+If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
+
+mkdirp.sync(dir, mode)
+----------------------
+
+Synchronously create a new directory and any necessary subdirectories at `dir`
+with octal permission string `mode`.
+
+If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
+
+install
+=======
+
+With [npm](http://npmjs.org) do:
+
+ npm install mkdirp
+
+license
+=======
+
+MIT/X11
diff --git a/node_modules/express/node_modules/mkdirp/examples/pow.js b/node_modules/express/node_modules/mkdirp/examples/pow.js
new file mode 100644
index 0000000..e692421
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/examples/pow.js
@@ -0,0 +1,6 @@
+var mkdirp = require('mkdirp');
+
+mkdirp('/tmp/foo/bar/baz', function (err) {
+ if (err) console.error(err)
+ else console.log('pow!')
+});
diff --git a/node_modules/express/node_modules/mkdirp/examples/pow.js.orig b/node_modules/express/node_modules/mkdirp/examples/pow.js.orig
new file mode 100644
index 0000000..7741462
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/examples/pow.js.orig
@@ -0,0 +1,6 @@
+var mkdirp = require('mkdirp');
+
+mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
+ if (err) console.error(err)
+ else console.log('pow!')
+});
diff --git a/node_modules/express/node_modules/mkdirp/examples/pow.js.rej b/node_modules/express/node_modules/mkdirp/examples/pow.js.rej
new file mode 100644
index 0000000..81e7f43
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/examples/pow.js.rej
@@ -0,0 +1,19 @@
+--- examples/pow.js
++++ examples/pow.js
+@@ -1,6 +1,15 @@
+-var mkdirp = require('mkdirp').mkdirp;
++var mkdirp = require('../').mkdirp,
++ mkdirpSync = require('../').mkdirpSync;
+
+ mkdirp('/tmp/foo/bar/baz', 0755, function (err) {
+ if (err) console.error(err)
+ else console.log('pow!')
+ });
++
++try {
++ mkdirpSync('/tmp/bar/foo/baz', 0755);
++ console.log('double pow!');
++}
++catch (ex) {
++ console.log(ex);
++} \ No newline at end of file
diff --git a/node_modules/express/node_modules/mkdirp/index.js b/node_modules/express/node_modules/mkdirp/index.js
new file mode 100644
index 0000000..25f43ad
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/index.js
@@ -0,0 +1,79 @@
+var path = require('path');
+var fs = require('fs');
+
+module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
+
+function mkdirP (p, mode, f) {
+ if (typeof mode === 'function' || mode === undefined) {
+ f = mode;
+ mode = 0777 & (~process.umask());
+ }
+
+ var cb = f || function () {};
+ if (typeof mode === 'string') mode = parseInt(mode, 8);
+ p = path.resolve(p);
+
+ fs.mkdir(p, mode, function (er) {
+ if (!er) return cb();
+ switch (er.code) {
+ case 'ENOENT':
+ mkdirP(path.dirname(p), mode, function (er) {
+ if (er) cb(er);
+ else mkdirP(p, mode, cb);
+ });
+ break;
+
+ case 'EEXIST':
+ fs.stat(p, function (er2, stat) {
+ // if the stat fails, then that's super weird.
+ // let the original EEXIST be the failure reason.
+ if (er2 || !stat.isDirectory()) cb(er)
+ else cb();
+ });
+ break;
+
+ default:
+ cb(er);
+ break;
+ }
+ });
+}
+
+mkdirP.sync = function sync (p, mode) {
+ if (mode === undefined) {
+ mode = 0777 & (~process.umask());
+ }
+
+ if (typeof mode === 'string') mode = parseInt(mode, 8);
+ p = path.resolve(p);
+
+ try {
+ fs.mkdirSync(p, mode)
+ }
+ catch (err0) {
+ switch (err0.code) {
+ case 'ENOENT' :
+ var err1 = sync(path.dirname(p), mode)
+ if (err1) throw err1;
+ else return sync(p, mode);
+ break;
+
+ case 'EEXIST' :
+ var stat;
+ try {
+ stat = fs.statSync(p);
+ }
+ catch (err1) {
+ throw err0
+ }
+ if (!stat.isDirectory()) throw err0;
+ else return null;
+ break;
+ default :
+ throw err0
+ break;
+ }
+ }
+
+ return null;
+};
diff --git a/node_modules/express/node_modules/mkdirp/package.json b/node_modules/express/node_modules/mkdirp/package.json
new file mode 100644
index 0000000..2c6fc93
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "mkdirp",
+ "description": "Recursively mkdir, like `mkdir -p`",
+ "version": "0.3.0",
+ "author": {
+ "name": "James Halliday",
+ "email": "mail@substack.net",
+ "url": "http://substack.net"
+ },
+ "main": "./index",
+ "keywords": [
+ "mkdir",
+ "directory"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/substack/node-mkdirp.git"
+ },
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "devDependencies": {
+ "tap": "0.0.x"
+ },
+ "license": "MIT/X11",
+ "engines": {
+ "node": "*"
+ },
+ "_id": "mkdirp@0.3.0",
+ "dependencies": {},
+ "optionalDependencies": {},
+ "_engineSupported": true,
+ "_npmVersion": "1.1.12",
+ "_nodeVersion": "v0.6.14",
+ "_defaultsLoaded": true,
+ "dist": {
+ "shasum": "b3f5fb223a8091bc45c59beba087473cf1db44b2"
+ },
+ "_from": "mkdirp@0.3.0"
+}
diff --git a/node_modules/express/node_modules/mkdirp/test/chmod.js b/node_modules/express/node_modules/mkdirp/test/chmod.js
new file mode 100644
index 0000000..520dcb8
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/chmod.js
@@ -0,0 +1,38 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+var ps = [ '', 'tmp' ];
+
+for (var i = 0; i < 25; i++) {
+ var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ ps.push(dir);
+}
+
+var file = ps.join('/');
+
+test('chmod-pre', function (t) {
+ var mode = 0744
+ mkdirp(file, mode, function (er) {
+ t.ifError(er, 'should not error');
+ fs.stat(file, function (er, stat) {
+ t.ifError(er, 'should exist');
+ t.ok(stat && stat.isDirectory(), 'should be directory');
+ t.equal(stat && stat.mode & 0777, mode, 'should be 0744');
+ t.end();
+ });
+ });
+});
+
+test('chmod', function (t) {
+ var mode = 0755
+ mkdirp(file, mode, function (er) {
+ t.ifError(er, 'should not error');
+ fs.stat(file, function (er, stat) {
+ t.ifError(er, 'should exist');
+ t.ok(stat && stat.isDirectory(), 'should be directory');
+ t.end();
+ });
+ });
+});
diff --git a/node_modules/express/node_modules/mkdirp/test/clobber.js b/node_modules/express/node_modules/mkdirp/test/clobber.js
new file mode 100644
index 0000000..0eb7099
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/clobber.js
@@ -0,0 +1,37 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+var ps = [ '', 'tmp' ];
+
+for (var i = 0; i < 25; i++) {
+ var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ ps.push(dir);
+}
+
+var file = ps.join('/');
+
+// a file in the way
+var itw = ps.slice(0, 3).join('/');
+
+
+test('clobber-pre', function (t) {
+ console.error("about to write to "+itw)
+ fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
+
+ fs.stat(itw, function (er, stat) {
+ t.ifError(er)
+ t.ok(stat && stat.isFile(), 'should be file')
+ t.end()
+ })
+})
+
+test('clobber', function (t) {
+ t.plan(2);
+ mkdirp(file, 0755, function (err) {
+ t.ok(err);
+ t.equal(err.code, 'ENOTDIR');
+ t.end();
+ });
+});
diff --git a/node_modules/express/node_modules/mkdirp/test/mkdirp.js b/node_modules/express/node_modules/mkdirp/test/mkdirp.js
new file mode 100644
index 0000000..b07cd70
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/mkdirp.js
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('woo', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
diff --git a/node_modules/express/node_modules/mkdirp/test/perm.js b/node_modules/express/node_modules/mkdirp/test/perm.js
new file mode 100644
index 0000000..23a7abb
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/perm.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('async perm', function (t) {
+ t.plan(2);
+ var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
+
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
+
+test('async root perm', function (t) {
+ mkdirp('/tmp', 0755, function (err) {
+ if (err) t.fail(err);
+ t.end();
+ });
+ t.end();
+});
diff --git a/node_modules/express/node_modules/mkdirp/test/perm_sync.js b/node_modules/express/node_modules/mkdirp/test/perm_sync.js
new file mode 100644
index 0000000..f685f60
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/perm_sync.js
@@ -0,0 +1,39 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('sync perm', function (t) {
+ t.plan(2);
+ var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
+
+ mkdirp.sync(file, 0755);
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ });
+});
+
+test('sync root perm', function (t) {
+ t.plan(1);
+
+ var file = '/tmp';
+ mkdirp.sync(file, 0755);
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ });
+});
diff --git a/node_modules/express/node_modules/mkdirp/test/race.js b/node_modules/express/node_modules/mkdirp/test/race.js
new file mode 100644
index 0000000..96a0447
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/race.js
@@ -0,0 +1,41 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('race', function (t) {
+ t.plan(4);
+ var ps = [ '', 'tmp' ];
+
+ for (var i = 0; i < 25; i++) {
+ var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ ps.push(dir);
+ }
+ var file = ps.join('/');
+
+ var res = 2;
+ mk(file, function () {
+ if (--res === 0) t.end();
+ });
+
+ mk(file, function () {
+ if (--res === 0) t.end();
+ });
+
+ function mk (file, cb) {
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ if (cb) cb();
+ }
+ })
+ })
+ });
+ }
+});
diff --git a/node_modules/express/node_modules/mkdirp/test/rel.js b/node_modules/express/node_modules/mkdirp/test/rel.js
new file mode 100644
index 0000000..7985824
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/rel.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('rel', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var cwd = process.cwd();
+ process.chdir('/tmp');
+
+ var file = [x,y,z].join('/');
+
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ process.chdir(cwd);
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
diff --git a/node_modules/express/node_modules/mkdirp/test/sync.js b/node_modules/express/node_modules/mkdirp/test/sync.js
new file mode 100644
index 0000000..e0e389d
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/sync.js
@@ -0,0 +1,27 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('sync', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ var err = mkdirp.sync(file, 0755);
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+});
diff --git a/node_modules/express/node_modules/mkdirp/test/umask.js b/node_modules/express/node_modules/mkdirp/test/umask.js
new file mode 100644
index 0000000..64ccafe
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/umask.js
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('implicit mode from umask', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ mkdirp(file, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0777 & (~process.umask()));
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
diff --git a/node_modules/express/node_modules/mkdirp/test/umask_sync.js b/node_modules/express/node_modules/mkdirp/test/umask_sync.js
new file mode 100644
index 0000000..83cba56
--- /dev/null
+++ b/node_modules/express/node_modules/mkdirp/test/umask_sync.js
@@ -0,0 +1,27 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('umask sync modes', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ var err = mkdirp.sync(file);
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, (0777 & (~process.umask())));
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+});
diff --git a/node_modules/express/node_modules/qs/.gitmodules b/node_modules/express/node_modules/qs/.gitmodules
new file mode 100644
index 0000000..49e31da
--- /dev/null
+++ b/node_modules/express/node_modules/qs/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "support/expresso"]
+ path = support/expresso
+ url = git://github.com/visionmedia/expresso.git
+[submodule "support/should"]
+ path = support/should
+ url = git://github.com/visionmedia/should.js.git
diff --git a/node_modules/express/node_modules/qs/.npmignore b/node_modules/express/node_modules/qs/.npmignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/node_modules/express/node_modules/qs/.npmignore
@@ -0,0 +1 @@
+node_modules
diff --git a/node_modules/express/node_modules/qs/.travis.yml b/node_modules/express/node_modules/qs/.travis.yml
new file mode 100644
index 0000000..2c0a8f6
--- /dev/null
+++ b/node_modules/express/node_modules/qs/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.4 \ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/History.md b/node_modules/express/node_modules/qs/History.md
new file mode 100644
index 0000000..3eaf7df
--- /dev/null
+++ b/node_modules/express/node_modules/qs/History.md
@@ -0,0 +1,73 @@
+
+0.4.2 / 2012-02-08
+==================
+
+ * Fixed: ensure objects are created when appropriate not arrays [aheckmann]
+
+0.4.1 / 2012-01-26
+==================
+
+ * Fixed stringify()ing numbers. Closes #23
+
+0.4.0 / 2011-11-21
+==================
+
+ * Allow parsing of an existing object (for `bodyParser()`) [jackyz]
+ * Replaced expresso with mocha
+
+0.3.2 / 2011-11-08
+==================
+
+ * Fixed global variable leak
+
+0.3.1 / 2011-08-17
+==================
+
+ * Added `try/catch` around malformed uri components
+ * Add test coverage for Array native method bleed-though
+
+0.3.0 / 2011-07-19
+==================
+
+ * Allow `array[index]` and `object[property]` syntaxes [Aria Stewart]
+
+0.2.0 / 2011-06-29
+==================
+
+ * Added `qs.stringify()` [Cory Forsyth]
+
+0.1.0 / 2011-04-13
+==================
+
+ * Added jQuery-ish array support
+
+0.0.7 / 2011-03-13
+==================
+
+ * Fixed; handle empty string and `== null` in `qs.parse()` [dmit]
+ allows for convenient `qs.parse(url.parse(str).query)`
+
+0.0.6 / 2011-02-14
+==================
+
+ * Fixed; support for implicit arrays
+
+0.0.4 / 2011-02-09
+==================
+
+ * Fixed `+` as a space
+
+0.0.3 / 2011-02-08
+==================
+
+ * Fixed case when right-hand value contains "]"
+
+0.0.2 / 2011-02-07
+==================
+
+ * Fixed "=" presence in key
+
+0.0.1 / 2011-02-07
+==================
+
+ * Initial release \ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/Makefile b/node_modules/express/node_modules/qs/Makefile
new file mode 100644
index 0000000..e4df837
--- /dev/null
+++ b/node_modules/express/node_modules/qs/Makefile
@@ -0,0 +1,5 @@
+
+test:
+ @./node_modules/.bin/mocha
+
+.PHONY: test \ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/Readme.md b/node_modules/express/node_modules/qs/Readme.md
new file mode 100644
index 0000000..db0d145
--- /dev/null
+++ b/node_modules/express/node_modules/qs/Readme.md
@@ -0,0 +1,54 @@
+# node-querystring
+
+ query string parser for node supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.
+
+## Installation
+
+ $ npm install qs
+
+## Examples
+
+```js
+var qs = require('qs');
+
+qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');
+// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }
+
+qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})
+// => user[name]=Tobi&user[email]=tobi%40learnboost.com
+```
+
+## Testing
+
+Install dev dependencies:
+
+ $ npm install -d
+
+and execute:
+
+ $ make test
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/benchmark.js b/node_modules/express/node_modules/qs/benchmark.js
new file mode 100644
index 0000000..97e2c93
--- /dev/null
+++ b/node_modules/express/node_modules/qs/benchmark.js
@@ -0,0 +1,17 @@
+
+var qs = require('./');
+
+var times = 100000
+ , start = new Date
+ , n = times;
+
+console.log('times: %d', times);
+
+while (n--) qs.parse('foo=bar');
+console.log('simple: %dms', new Date - start);
+
+var start = new Date
+ , n = times;
+
+while (n--) qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
+console.log('nested: %dms', new Date - start); \ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/examples.js b/node_modules/express/node_modules/qs/examples.js
new file mode 100644
index 0000000..27617b7
--- /dev/null
+++ b/node_modules/express/node_modules/qs/examples.js
@@ -0,0 +1,51 @@
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('./');
+
+var obj = qs.parse('foo');
+console.log(obj)
+
+var obj = qs.parse('foo=bar=baz');
+console.log(obj)
+
+var obj = qs.parse('users[]');
+console.log(obj)
+
+var obj = qs.parse('name=tj&email=tj@vision-media.ca');
+console.log(obj)
+
+var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane');
+console.log(obj)
+
+var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
+console.log(obj)
+
+var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk');
+console.log(obj)
+
+var obj = qs.parse('a=a&a=b&a=c');
+console.log(obj)
+
+var obj = qs.parse('user[tj]=tj&user[tj]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[names]=tj&user[names]=TJ&user[names]=Tyler');
+console.log(obj)
+
+var obj = qs.parse('user[name][first]=tj&user[name][first]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[0]=tj&user[1]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[0]=tj&user[]=TJ');
+console.log(obj)
+
+var obj = qs.parse('user[0]=tj&user[foo]=TJ');
+console.log(obj)
+
+var str = qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }});
+console.log(str); \ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/index.js b/node_modules/express/node_modules/qs/index.js
new file mode 100644
index 0000000..d177d20
--- /dev/null
+++ b/node_modules/express/node_modules/qs/index.js
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/querystring'); \ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/lib/querystring.js b/node_modules/express/node_modules/qs/lib/querystring.js
new file mode 100644
index 0000000..6c72712
--- /dev/null
+++ b/node_modules/express/node_modules/qs/lib/querystring.js
@@ -0,0 +1,264 @@
+
+/*!
+ * querystring
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Library version.
+ */
+
+exports.version = '0.4.2';
+
+/**
+ * Object#toString() ref for stringify().
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Cache non-integer test regexp.
+ */
+
+var isint = /^[0-9]+$/;
+
+function promote(parent, key) {
+ if (parent[key].length == 0) return parent[key] = {};
+ var t = {};
+ for (var i in parent[key]) t[i] = parent[key][i];
+ parent[key] = t;
+ return t;
+}
+
+function parse(parts, parent, key, val) {
+ var part = parts.shift();
+ // end
+ if (!part) {
+ if (Array.isArray(parent[key])) {
+ parent[key].push(val);
+ } else if ('object' == typeof parent[key]) {
+ parent[key] = val;
+ } else if ('undefined' == typeof parent[key]) {
+ parent[key] = val;
+ } else {
+ parent[key] = [parent[key], val];
+ }
+ // array
+ } else {
+ var obj = parent[key] = parent[key] || [];
+ if (']' == part) {
+ if (Array.isArray(obj)) {
+ if ('' != val) obj.push(val);
+ } else if ('object' == typeof obj) {
+ obj[Object.keys(obj).length] = val;
+ } else {
+ obj = parent[key] = [parent[key], val];
+ }
+ // prop
+ } else if (~part.indexOf(']')) {
+ part = part.substr(0, part.length - 1);
+ if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+ parse(parts, obj, part, val);
+ // key
+ } else {
+ if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
+ parse(parts, obj, part, val);
+ }
+ }
+}
+
+/**
+ * Merge parent key/val pair.
+ */
+
+function merge(parent, key, val){
+ if (~key.indexOf(']')) {
+ var parts = key.split('[')
+ , len = parts.length
+ , last = len - 1;
+ parse(parts, parent, 'base', val);
+ // optimize
+ } else {
+ if (!isint.test(key) && Array.isArray(parent.base)) {
+ var t = {};
+ for (var k in parent.base) t[k] = parent.base[k];
+ parent.base = t;
+ }
+ set(parent.base, key, val);
+ }
+
+ return parent;
+}
+
+/**
+ * Parse the given obj.
+ */
+
+function parseObject(obj){
+ var ret = { base: {} };
+ Object.keys(obj).forEach(function(name){
+ merge(ret, name, obj[name]);
+ });
+ return ret.base;
+}
+
+/**
+ * Parse the given str.
+ */
+
+function parseString(str){
+ return String(str)
+ .split('&')
+ .reduce(function(ret, pair){
+ try{
+ pair = decodeURIComponent(pair.replace(/\+/g, ' '));
+ } catch(e) {
+ // ignore
+ }
+
+ var eql = pair.indexOf('=')
+ , brace = lastBraceInKey(pair)
+ , key = pair.substr(0, brace || eql)
+ , val = pair.substr(brace || eql, pair.length)
+ , val = val.substr(val.indexOf('=') + 1, val.length);
+
+ // ?foo
+ if ('' == key) key = pair, val = '';
+
+ return merge(ret, key, val);
+ }, { base: {} }).base;
+}
+
+/**
+ * Parse the given query `str` or `obj`, returning an object.
+ *
+ * @param {String} str | {Object} obj
+ * @return {Object}
+ * @api public
+ */
+
+exports.parse = function(str){
+ if (null == str || '' == str) return {};
+ return 'object' == typeof str
+ ? parseObject(str)
+ : parseString(str);
+};
+
+/**
+ * Turn the given `obj` into a query string
+ *
+ * @param {Object} obj
+ * @return {String}
+ * @api public
+ */
+
+var stringify = exports.stringify = function(obj, prefix) {
+ if (Array.isArray(obj)) {
+ return stringifyArray(obj, prefix);
+ } else if ('[object Object]' == toString.call(obj)) {
+ return stringifyObject(obj, prefix);
+ } else if ('string' == typeof obj) {
+ return stringifyString(obj, prefix);
+ } else {
+ return prefix + '=' + obj;
+ }
+};
+
+/**
+ * Stringify the given `str`.
+ *
+ * @param {String} str
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyString(str, prefix) {
+ if (!prefix) throw new TypeError('stringify expects an object');
+ return prefix + '=' + encodeURIComponent(str);
+}
+
+/**
+ * Stringify the given `arr`.
+ *
+ * @param {Array} arr
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyArray(arr, prefix) {
+ var ret = [];
+ if (!prefix) throw new TypeError('stringify expects an object');
+ for (var i = 0; i < arr.length; i++) {
+ ret.push(stringify(arr[i], prefix + '[]'));
+ }
+ return ret.join('&');
+}
+
+/**
+ * Stringify the given `obj`.
+ *
+ * @param {Object} obj
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyObject(obj, prefix) {
+ var ret = []
+ , keys = Object.keys(obj)
+ , key;
+
+ for (var i = 0, len = keys.length; i < len; ++i) {
+ key = keys[i];
+ ret.push(stringify(obj[key], prefix
+ ? prefix + '[' + encodeURIComponent(key) + ']'
+ : encodeURIComponent(key)));
+ }
+
+ return ret.join('&');
+}
+
+/**
+ * Set `obj`'s `key` to `val` respecting
+ * the weird and wonderful syntax of a qs,
+ * where "foo=bar&foo=baz" becomes an array.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @param {String} val
+ * @api private
+ */
+
+function set(obj, key, val) {
+ var v = obj[key];
+ if (undefined === v) {
+ obj[key] = val;
+ } else if (Array.isArray(v)) {
+ v.push(val);
+ } else {
+ obj[key] = [v, val];
+ }
+}
+
+/**
+ * Locate last brace in `str` within the key.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function lastBraceInKey(str) {
+ var len = str.length
+ , brace
+ , c;
+ for (var i = 0; i < len; ++i) {
+ c = str[i];
+ if (']' == c) brace = false;
+ if ('[' == c) brace = true;
+ if ('=' == c && !brace) return i;
+ }
+}
diff --git a/node_modules/express/node_modules/qs/package.json b/node_modules/express/node_modules/qs/package.json
new file mode 100644
index 0000000..20672e8
--- /dev/null
+++ b/node_modules/express/node_modules/qs/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "qs",
+ "description": "querystring parser",
+ "version": "0.4.2",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/visionmedia/node-querystring.git"
+ },
+ "devDependencies": {
+ "mocha": "*",
+ "should": "*"
+ },
+ "author": {
+ "name": "TJ Holowaychuk",
+ "email": "tj@vision-media.ca",
+ "url": "http://tjholowaychuk.com"
+ },
+ "main": "index",
+ "engines": {
+ "node": "*"
+ },
+ "_id": "qs@0.4.2",
+ "dependencies": {},
+ "optionalDependencies": {},
+ "_engineSupported": true,
+ "_npmVersion": "1.1.12",
+ "_nodeVersion": "v0.6.14",
+ "_defaultsLoaded": true,
+ "dist": {
+ "shasum": "7d6f7309dd7f451c98d8a8565bb025ed1965ccbb"
+ },
+ "_from": "qs@0.4.x"
+}
diff --git a/node_modules/express/node_modules/qs/test/mocha.opts b/node_modules/express/node_modules/qs/test/mocha.opts
new file mode 100644
index 0000000..521cbb2
--- /dev/null
+++ b/node_modules/express/node_modules/qs/test/mocha.opts
@@ -0,0 +1,2 @@
+--require should
+--ui exports
diff --git a/node_modules/express/node_modules/qs/test/parse.js b/node_modules/express/node_modules/qs/test/parse.js
new file mode 100644
index 0000000..f219e27
--- /dev/null
+++ b/node_modules/express/node_modules/qs/test/parse.js
@@ -0,0 +1,167 @@
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('../');
+
+module.exports = {
+ 'test basics': function(){
+ qs.parse('0=foo').should.eql({ '0': 'foo' });
+
+ qs.parse('foo=c++')
+ .should.eql({ foo: 'c ' });
+
+ qs.parse('a[>=]=23')
+ .should.eql({ a: { '>=': '23' }});
+
+ qs.parse('a[<=>]==23')
+ .should.eql({ a: { '<=>': '=23' }});
+
+ qs.parse('a[==]=23')
+ .should.eql({ a: { '==': '23' }});
+
+ qs.parse('foo')
+ .should.eql({ foo: '' });
+
+ qs.parse('foo=bar')
+ .should.eql({ foo: 'bar' });
+
+ qs.parse('foo%3Dbar=baz')
+ .should.eql({ foo: 'bar=baz' });
+
+ qs.parse(' foo = bar = baz ')
+ .should.eql({ ' foo ': ' bar = baz ' });
+
+ qs.parse('foo=bar=baz')
+ .should.eql({ foo: 'bar=baz' });
+
+ qs.parse('foo=bar&bar=baz')
+ .should.eql({ foo: 'bar', bar: 'baz' });
+
+ qs.parse('foo=bar&baz')
+ .should.eql({ foo: 'bar', baz: '' });
+
+ qs.parse('cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World')
+ .should.eql({
+ cht: 'p3'
+ , chd: 't:60,40'
+ , chs: '250x100'
+ , chl: 'Hello|World'
+ });
+ },
+
+ 'test nesting': function(){
+ qs.parse('ops[>=]=25')
+ .should.eql({ ops: { '>=': '25' }});
+
+ qs.parse('user[name]=tj')
+ .should.eql({ user: { name: 'tj' }});
+
+ qs.parse('user[name][first]=tj&user[name][last]=holowaychuk')
+ .should.eql({ user: { name: { first: 'tj', last: 'holowaychuk' }}});
+ },
+
+ 'test escaping': function(){
+ qs.parse('foo=foo%20bar')
+ .should.eql({ foo: 'foo bar' });
+ },
+
+ 'test arrays': function(){
+ qs.parse('images[]')
+ .should.eql({ images: [] });
+
+ qs.parse('user[]=tj')
+ .should.eql({ user: ['tj'] });
+
+ qs.parse('user[]=tj&user[]=tobi&user[]=jane')
+ .should.eql({ user: ['tj', 'tobi', 'jane'] });
+
+ qs.parse('user[names][]=tj&user[names][]=tyler')
+ .should.eql({ user: { names: ['tj', 'tyler'] }});
+
+ qs.parse('user[names][]=tj&user[names][]=tyler&user[email]=tj@vision-media.ca')
+ .should.eql({ user: { names: ['tj', 'tyler'], email: 'tj@vision-media.ca' }});
+
+ qs.parse('items=a&items=b')
+ .should.eql({ items: ['a', 'b'] });
+
+ qs.parse('user[names]=tj&user[names]=holowaychuk&user[names]=TJ')
+ .should.eql({ user: { names: ['tj', 'holowaychuk', 'TJ'] }});
+
+ qs.parse('user[name][first]=tj&user[name][first]=TJ')
+ .should.eql({ user: { name: { first: ['tj', 'TJ'] }}});
+
+ var o = qs.parse('existing[fcbaebfecc][name][last]=tj')
+ o.should.eql({ existing: { 'fcbaebfecc': { name: { last: 'tj' }}}})
+ Array.isArray(o.existing).should.be.false;
+ },
+
+ 'test right-hand brackets': function(){
+ qs.parse('pets=["tobi"]')
+ .should.eql({ pets: '["tobi"]' });
+
+ qs.parse('operators=[">=", "<="]')
+ .should.eql({ operators: '[">=", "<="]' });
+
+ qs.parse('op[>=]=[1,2,3]')
+ .should.eql({ op: { '>=': '[1,2,3]' }});
+
+ qs.parse('op[>=]=[1,2,3]&op[=]=[[[[1]]]]')
+ .should.eql({ op: { '>=': '[1,2,3]', '=': '[[[[1]]]]' }});
+ },
+
+ 'test duplicates': function(){
+ qs.parse('items=bar&items=baz&items=raz')
+ .should.eql({ items: ['bar', 'baz', 'raz'] });
+ },
+
+ 'test empty': function(){
+ qs.parse('').should.eql({});
+ qs.parse(undefined).should.eql({});
+ qs.parse(null).should.eql({});
+ },
+
+ 'test arrays with indexes': function(){
+ qs.parse('foo[0]=bar&foo[1]=baz').should.eql({ foo: ['bar', 'baz'] });
+ qs.parse('foo[1]=bar&foo[0]=baz').should.eql({ foo: ['baz', 'bar'] });
+ qs.parse('foo[base64]=RAWR').should.eql({ foo: { base64: 'RAWR' }});
+ qs.parse('foo[64base]=RAWR').should.eql({ foo: { '64base': 'RAWR' }});
+ },
+
+ 'test arrays becoming objects': function(){
+ qs.parse('foo[0]=bar&foo[bad]=baz').should.eql({ foo: { 0: "bar", bad: "baz" }});
+ qs.parse('foo[bad]=baz&foo[0]=bar').should.eql({ foo: { 0: "bar", bad: "baz" }});
+ },
+
+ 'test bleed-through of Array native properties/methods': function(){
+ Array.prototype.protoProperty = true;
+ Array.prototype.protoFunction = function () {};
+ qs.parse('foo=bar').should.eql({ foo: 'bar' });
+ },
+
+ 'test malformed uri': function(){
+ qs.parse('{%:%}').should.eql({ '{%:%}': '' });
+ qs.parse('foo=%:%}').should.eql({ 'foo': '%:%}' });
+ },
+
+ 'test semi-parsed': function(){
+ qs.parse({ 'user[name]': 'tobi' })
+ .should.eql({ user: { name: 'tobi' }});
+
+ qs.parse({ 'user[name]': 'tobi', 'user[email][main]': 'tobi@lb.com' })
+ .should.eql({ user: { name: 'tobi', email: { main: 'tobi@lb.com' } }});
+ }
+
+ // 'test complex': function(){
+ // qs.parse('users[][name][first]=tj&users[foo]=bar')
+ // .should.eql({
+ // users: [ { name: 'tj' }, { name: 'tobi' }, { foo: 'bar' }]
+ // });
+ //
+ // qs.parse('users[][name][first]=tj&users[][name][first]=tobi')
+ // .should.eql({
+ // users: [ { name: 'tj' }, { name: 'tobi' }]
+ // });
+ // }
+};
diff --git a/node_modules/express/node_modules/qs/test/stringify.js b/node_modules/express/node_modules/qs/test/stringify.js
new file mode 100644
index 0000000..c2195cb
--- /dev/null
+++ b/node_modules/express/node_modules/qs/test/stringify.js
@@ -0,0 +1,103 @@
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('../')
+ , should = require('should')
+ , str_identities = {
+ 'basics': [
+ { str: 'foo=bar', obj: {'foo' : 'bar'}},
+ { str: 'foo=%22bar%22', obj: {'foo' : '\"bar\"'}},
+ { str: 'foo=', obj: {'foo': ''}},
+ { str: 'foo=1&bar=2', obj: {'foo' : '1', 'bar' : '2'}},
+ { str: 'my%20weird%20field=q1!2%22\'w%245%267%2Fz8)%3F', obj: {'my weird field': "q1!2\"'w$5&7/z8)?"}},
+ { str: 'foo%3Dbaz=bar', obj: {'foo=baz': 'bar'}},
+ { str: 'foo=bar&bar=baz', obj: {foo: 'bar', bar: 'baz'}}
+ ],
+ 'escaping': [
+ { str: 'foo=foo%20bar', obj: {foo: 'foo bar'}},
+ { str: 'cht=p3&chd=t%3A60%2C40&chs=250x100&chl=Hello%7CWorld', obj: {
+ cht: 'p3'
+ , chd: 't:60,40'
+ , chs: '250x100'
+ , chl: 'Hello|World'
+ }}
+ ],
+ 'nested': [
+ { str: 'foo[]=bar&foo[]=quux', obj: {'foo' : ['bar', 'quux']}},
+ { str: 'foo[]=bar', obj: {foo: ['bar']}},
+ { str: 'foo[]=1&foo[]=2', obj: {'foo' : ['1', '2']}},
+ { str: 'foo=bar&baz[]=1&baz[]=2&baz[]=3', obj: {'foo' : 'bar', 'baz' : ['1', '2', '3']}},
+ { str: 'foo[]=bar&baz[]=1&baz[]=2&baz[]=3', obj: {'foo' : ['bar'], 'baz' : ['1', '2', '3']}},
+ { str: 'x[y][z]=1', obj: {'x' : {'y' : {'z' : '1'}}}},
+ { str: 'x[y][z][]=1', obj: {'x' : {'y' : {'z' : ['1']}}}},
+ { str: 'x[y][z]=2', obj: {'x' : {'y' : {'z' : '2'}}}},
+ { str: 'x[y][z][]=1&x[y][z][]=2', obj: {'x' : {'y' : {'z' : ['1', '2']}}}},
+ { str: 'x[y][][z]=1', obj: {'x' : {'y' : [{'z' : '1'}]}}},
+ { str: 'x[y][][z][]=1', obj: {'x' : {'y' : [{'z' : ['1']}]}}},
+ { str: 'x[y][][z]=1&x[y][][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'w' : '2'}]}}},
+ { str: 'x[y][][v][w]=1', obj: {'x' : {'y' : [{'v' : {'w' : '1'}}]}}},
+ { str: 'x[y][][z]=1&x[y][][v][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'v' : {'w' : '2'}}]}}},
+ { str: 'x[y][][z]=1&x[y][][z]=2', obj: {'x' : {'y' : [{'z' : '1'}, {'z' : '2'}]}}},
+ { str: 'x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3', obj: {'x' : {'y' : [{'z' : '1', 'w' : 'a'}, {'z' : '2', 'w' : '3'}]}}},
+ { str: 'user[name][first]=tj&user[name][last]=holowaychuk', obj: { user: { name: { first: 'tj', last: 'holowaychuk' }}}}
+ ],
+ 'errors': [
+ { obj: 'foo=bar', message: 'stringify expects an object' },
+ { obj: ['foo', 'bar'], message: 'stringify expects an object' }
+ ],
+ 'numbers': [
+ { str: 'limit[]=1&limit[]=2&limit[]=3', obj: { limit: [1, 2, '3'] }},
+ { str: 'limit=1', obj: { limit: 1 }}
+ ]
+ };
+
+
+// Assert error
+function err(fn, msg){
+ var err;
+ try {
+ fn();
+ } catch (e) {
+ should.equal(e.message, msg);
+ return;
+ }
+ throw new Error('no exception thrown, expected "' + msg + '"');
+}
+
+function test(type) {
+ var str, obj;
+ for (var i = 0; i < str_identities[type].length; i++) {
+ str = str_identities[type][i].str;
+ obj = str_identities[type][i].obj;
+ qs.stringify(obj).should.eql(str);
+ }
+}
+
+module.exports = {
+ 'test basics': function() {
+ test('basics');
+ },
+
+ 'test escaping': function() {
+ test('escaping');
+ },
+
+ 'test nested': function() {
+ test('nested');
+ },
+
+ 'test numbers': function(){
+ test('numbers');
+ },
+
+ 'test errors': function() {
+ var obj, message;
+ for (var i = 0; i < str_identities['errors'].length; i++) {
+ message = str_identities['errors'][i].message;
+ obj = str_identities['errors'][i].obj;
+ err(function(){ qs.stringify(obj) }, message);
+ }
+ }
+}; \ No newline at end of file
diff --git a/node_modules/express/package.json b/node_modules/express/package.json
new file mode 100644
index 0000000..6729dce
--- /dev/null
+++ b/node_modules/express/package.json
@@ -0,0 +1,74 @@
+{
+ "name": "express",
+ "description": "Sinatra inspired web development framework",
+ "version": "2.5.8",
+ "author": {
+ "name": "TJ Holowaychuk",
+ "email": "tj@vision-media.ca"
+ },
+ "contributors": [
+ {
+ "name": "TJ Holowaychuk",
+ "email": "tj@vision-media.ca"
+ },
+ {
+ "name": "Aaron Heckmann",
+ "email": "aaron.heckmann+github@gmail.com"
+ },
+ {
+ "name": "Ciaran Jessup",
+ "email": "ciaranj@gmail.com"
+ },
+ {
+ "name": "Guillermo Rauch",
+ "email": "rauchg@gmail.com"
+ }
+ ],
+ "dependencies": {
+ "connect": "1.x",
+ "mime": "1.2.4",
+ "qs": "0.4.x",
+ "mkdirp": "0.3.0"
+ },
+ "devDependencies": {
+ "connect-form": "0.2.1",
+ "ejs": "0.4.2",
+ "expresso": "0.9.2",
+ "hamljs": "0.6.x",
+ "jade": "0.16.2",
+ "stylus": "0.13.0",
+ "should": "0.3.2",
+ "express-messages": "0.0.2",
+ "node-markdown": ">= 0.0.1",
+ "connect-redis": ">= 0.0.1"
+ },
+ "keywords": [
+ "framework",
+ "sinatra",
+ "web",
+ "rest",
+ "restful"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/visionmedia/express.git"
+ },
+ "main": "index",
+ "bin": {
+ "express": "./bin/express"
+ },
+ "scripts": {
+ "test": "make test",
+ "prepublish": "npm prune"
+ },
+ "engines": {
+ "node": ">= 0.4.1 < 0.7.0"
+ },
+ "_id": "express@2.5.8",
+ "optionalDependencies": {},
+ "_engineSupported": true,
+ "_npmVersion": "1.1.12",
+ "_nodeVersion": "v0.6.14",
+ "_defaultsLoaded": true,
+ "_from": "express@2.5.8"
+}
diff --git a/node_modules/express/testing/foo/app.js b/node_modules/express/testing/foo/app.js
new file mode 100644
index 0000000..7574676
--- /dev/null
+++ b/node_modules/express/testing/foo/app.js
@@ -0,0 +1,35 @@
+
+/**
+ * Module dependencies.
+ */
+
+var express = require('express')
+ , routes = require('./routes')
+
+var app = module.exports = express.createServer();
+
+// Configuration
+
+app.configure(function(){
+ app.set('views', __dirname + '/views');
+ app.set('view engine', 'jade');
+ app.use(express.bodyParser());
+ app.use(express.methodOverride());
+ app.use(app.router);
+ app.use(express.static(__dirname + '/public'));
+});
+
+app.configure('development', function(){
+ app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
+});
+
+app.configure('production', function(){
+ app.use(express.errorHandler());
+});
+
+// Routes
+
+app.get('/', routes.index);
+
+app.listen(3000);
+console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
diff --git a/node_modules/express/testing/foo/package.json b/node_modules/express/testing/foo/package.json
new file mode 100644
index 0000000..dd54123
--- /dev/null
+++ b/node_modules/express/testing/foo/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "application-name"
+ , "version": "0.0.1"
+ , "private": true
+ , "dependencies": {
+ "express": "2.5.0"
+ , "jade": ">= 0.0.1"
+ }
+} \ No newline at end of file
diff --git a/node_modules/express/testing/foo/public/stylesheets/style.css b/node_modules/express/testing/foo/public/stylesheets/style.css
new file mode 100644
index 0000000..30e047d
--- /dev/null
+++ b/node_modules/express/testing/foo/public/stylesheets/style.css
@@ -0,0 +1,8 @@
+body {
+ padding: 50px;
+ font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
+}
+
+a {
+ color: #00B7FF;
+} \ No newline at end of file
diff --git a/node_modules/express/testing/foo/routes/index.js b/node_modules/express/testing/foo/routes/index.js
new file mode 100644
index 0000000..0b2205c
--- /dev/null
+++ b/node_modules/express/testing/foo/routes/index.js
@@ -0,0 +1,10 @@
+
+/*
+ * GET home page.
+ */
+
+exports.index = function(req, res){
+ res.writeHead(200);
+ req.doesnotexist();
+ // res.render('index', { title: 'Express' })
+}; \ No newline at end of file
diff --git a/node_modules/express/testing/foo/views/index.jade b/node_modules/express/testing/foo/views/index.jade
new file mode 100644
index 0000000..c9c35fa
--- /dev/null
+++ b/node_modules/express/testing/foo/views/index.jade
@@ -0,0 +1,2 @@
+h1= title
+p Welcome to #{title} \ No newline at end of file
diff --git a/node_modules/express/testing/foo/views/layout.jade b/node_modules/express/testing/foo/views/layout.jade
new file mode 100644
index 0000000..1a36941
--- /dev/null
+++ b/node_modules/express/testing/foo/views/layout.jade
@@ -0,0 +1,6 @@
+!!!
+html
+ head
+ title= title
+ link(rel='stylesheet', href='/stylesheets/style.css')
+ body!= body \ No newline at end of file
diff --git a/node_modules/express/testing/index.js b/node_modules/express/testing/index.js
new file mode 100644
index 0000000..3c5185d
--- /dev/null
+++ b/node_modules/express/testing/index.js
@@ -0,0 +1,43 @@
+
+/**
+ * Module dependencies.
+ */
+
+var express = require('../')
+ , http = require('http')
+ , connect = require('connect');
+
+var app = express.createServer();
+
+app.get('/', function(req, res){
+ req.foo();
+ res.send('test');
+});
+
+// app.set('views', __dirname + '/views');
+// app.set('view engine', 'jade');
+//
+// app.configure(function(){
+// app.use(function(req, res, next){
+// debugger
+// res.write('first');
+// console.error('first');
+// next();
+// });
+//
+// app.use(app.router);
+//
+// app.use(function(req, res, next){
+// console.error('last');
+// res.end('last');
+// });
+// });
+//
+// app.get('/', function(req, res, next){
+// console.error('middle');
+// res.write(' route ');
+// next();
+// });
+
+app.listen(3000);
+console.log('listening on port 3000'); \ No newline at end of file
diff --git a/node_modules/express/testing/public/test.txt b/node_modules/express/testing/public/test.txt
new file mode 100644
index 0000000..cb9a165
--- /dev/null
+++ b/node_modules/express/testing/public/test.txt
@@ -0,0 +1,2971 @@
+foo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+bazfoo
+bar
+baz \ No newline at end of file
diff --git a/node_modules/express/testing/views/page.html b/node_modules/express/testing/views/page.html
new file mode 100644
index 0000000..4ff9827
--- /dev/null
+++ b/node_modules/express/testing/views/page.html
@@ -0,0 +1 @@
+p register test \ No newline at end of file
diff --git a/node_modules/express/testing/views/page.jade b/node_modules/express/testing/views/page.jade
new file mode 100644
index 0000000..9c3f888
--- /dev/null
+++ b/node_modules/express/testing/views/page.jade
@@ -0,0 +1,3 @@
+html
+ body
+ h1 test \ No newline at end of file
diff --git a/node_modules/express/testing/views/test.md b/node_modules/express/testing/views/test.md
new file mode 100644
index 0000000..9139ff4
--- /dev/null
+++ b/node_modules/express/testing/views/test.md
@@ -0,0 +1 @@
+testing _some_ markdown \ No newline at end of file
diff --git a/node_modules/express/testing/views/user/index.jade b/node_modules/express/testing/views/user/index.jade
new file mode 100644
index 0000000..1b66a4f
--- /dev/null
+++ b/node_modules/express/testing/views/user/index.jade
@@ -0,0 +1 @@
+p user page \ No newline at end of file
diff --git a/node_modules/express/testing/views/user/list.jade b/node_modules/express/testing/views/user/list.jade
new file mode 100644
index 0000000..ed2b471
--- /dev/null
+++ b/node_modules/express/testing/views/user/list.jade
@@ -0,0 +1 @@
+p user list page \ No newline at end of file