Install the "express" node module via npm master
authorCarl Worth <cworth@cworth.org>
Fri, 6 May 2011 20:12:24 +0000 (13:12 -0700)
committerCarl Worth <cworth@cworth.org>
Fri, 6 May 2011 20:12:24 +0000 (13:12 -0700)
This was done with the simple command:

npm install express

Which pulled in the following versions under node_modules/express:

mime@1.2.1
connect@1.4.0
qs@0.1.0
express@2.3.3

102 files changed:
node_modules/.bin/express [new symlink]
node_modules/express/.npmignore [new file with mode: 0644]
node_modules/express/History.md [new file with mode: 0644]
node_modules/express/LICENSE [new file with mode: 0644]
node_modules/express/Makefile [new file with mode: 0644]
node_modules/express/Readme.md [new file with mode: 0644]
node_modules/express/bin/express [new file with mode: 0755]
node_modules/express/index.js [new file with mode: 0644]
node_modules/express/lib/express.js [new file with mode: 0644]
node_modules/express/lib/http.js [new file with mode: 0644]
node_modules/express/lib/https.js [new file with mode: 0644]
node_modules/express/lib/request.js [new file with mode: 0644]
node_modules/express/lib/response.js [new file with mode: 0644]
node_modules/express/lib/router/index.js [new file with mode: 0644]
node_modules/express/lib/router/methods.js [new file with mode: 0644]
node_modules/express/lib/router/route.js [new file with mode: 0644]
node_modules/express/lib/utils.js [new file with mode: 0644]
node_modules/express/lib/view.js [new file with mode: 0644]
node_modules/express/lib/view/partial.js [new file with mode: 0644]
node_modules/express/lib/view/view.js [new file with mode: 0644]
node_modules/express/node_modules/connect/.npmignore [new file with mode: 0644]
node_modules/express/node_modules/connect/LICENSE [new file with mode: 0644]
node_modules/express/node_modules/connect/index.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/connect.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/http.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/https.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/index.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/basicAuth.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/bodyParser.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/compiler.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/cookieParser.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/errorHandler.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/favicon.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/limit.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/logger.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/methodOverride.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/profiler.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/responseTime.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/router.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/session.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/session/cookie.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/session/memory.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/session/session.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/session/store.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/static.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/middleware/vhost.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/patch.js [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/public/error.html [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/public/favicon.ico [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/public/style.css [new file with mode: 0644]
node_modules/express/node_modules/connect/lib/utils.js [new file with mode: 0644]
node_modules/express/node_modules/connect/package.json [new file with mode: 0644]
node_modules/express/node_modules/connect/test.js [new file with mode: 0644]
node_modules/express/node_modules/mime/README.md [new file with mode: 0644]
node_modules/express/node_modules/mime/index.js [new file with mode: 0644]
node_modules/express/node_modules/mime/mime.js [new file with mode: 0644]
node_modules/express/node_modules/mime/mime.types [new file with mode: 0644]
node_modules/express/node_modules/mime/node.types [new file with mode: 0644]
node_modules/express/node_modules/mime/package.json [new file with mode: 0644]
node_modules/express/node_modules/mime/test.js [new file with mode: 0644]
node_modules/express/node_modules/qs/.gitmodules [new file with mode: 0644]
node_modules/express/node_modules/qs/History.md [new file with mode: 0644]
node_modules/express/node_modules/qs/Makefile [new file with mode: 0644]
node_modules/express/node_modules/qs/Readme.md [new file with mode: 0644]
node_modules/express/node_modules/qs/benchmark.js [new file with mode: 0644]
node_modules/express/node_modules/qs/examples.js [new file with mode: 0644]
node_modules/express/node_modules/qs/index.js [new file with mode: 0644]
node_modules/express/node_modules/qs/lib/querystring.js [new file with mode: 0644]
node_modules/express/node_modules/qs/package.json [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/.gitignore [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/.gitmodules [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/History.md [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/Makefile [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/Readme.md [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/bin/expresso [new file with mode: 0755]
node_modules/express/node_modules/qs/support/expresso/docs/api.html [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/docs/index.html [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/docs/index.md [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/docs/layout/foot.html [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/docs/layout/head.html [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/lib/bar.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/lib/foo.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/package.json [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/test/assert.test.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/test/async.test.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/test/bar.test.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/test/foo.test.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/test/http.test.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/test/serial/async.test.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/expresso/test/serial/http.test.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/.gitmodules [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/History.md [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/Makefile [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/Readme.md [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/examples/runner.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/index.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/lib/eql.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/lib/should.js [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/package.json [new file with mode: 0644]
node_modules/express/node_modules/qs/support/should/test/should.test.js [new file with mode: 0644]
node_modules/express/node_modules/qs/test/querystring.test.js [new file with mode: 0644]
node_modules/express/package.json [new file with mode: 0644]

diff --git a/node_modules/.bin/express b/node_modules/.bin/express
new file mode 120000 (symlink)
index 0000000..b741d99
--- /dev/null
@@ -0,0 +1 @@
+../express/bin/express
\ No newline at end of file
diff --git a/node_modules/express/.npmignore b/node_modules/express/.npmignore
new file mode 100644 (file)
index 0000000..74bd365
--- /dev/null
@@ -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 (file)
index 0000000..7441913
--- /dev/null
@@ -0,0 +1,624 @@
+
+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 (file)
index 0000000..36075a3
--- /dev/null
@@ -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 (file)
index 0000000..83a6210
--- /dev/null
@@ -0,0 +1,39 @@
+
+DOCS = $(shell find docs/*.md)
+HTMLDOCS =$(DOCS:.md=.html)
+
+test:
+       @NODE_ENV=test ./support/expresso/bin/expresso \
+               -I lib \
+               -I support \
+               -I support/connect/lib \
+               -I support/haml/lib \
+               -I support/jade/lib \
+               -I support/ejs/lib \
+               $(TESTFLAGS) \
+               test/*.test.js
+
+test-cov:
+       @TESTFLAGS=--cov $(MAKE) test
+
+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 test-cov 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 (file)
index 0000000..9ea3409
--- /dev/null
@@ -0,0 +1,102 @@
+
+# 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
+
+## 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-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
+  * 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)
+  * 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 and connect 1.x
+
+## 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 (executable)
index 0000000..05dc2eb
--- /dev/null
@@ -0,0 +1,451 @@
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , exec = require('child_process').exec;
+
+/**
+ * Framework version.
+ */
+
+var version = '2.3.3';
+
+/**
+ * Add session support.
+ */
+
+var sessions = false;
+
+/**
+ * CSS engine to utilize.
+ */
+
+var cssEngine;
+
+/**
+ * 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 (less|sass|stylus). default=plain css\n'
+  + '    -v, --version            output framework version\n'
+  + '    -h, --help               output help information\n'
+  ;
+
+/**
+ * Jade layout template.
+ */
+
+var jadeLayout = [
+    '!!!'
+  , 'html'
+  , '  head'
+  , '    title= title'
+  , '    link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')'
+  , '  body!= body'
+].join('\n');
+
+/**
+ * Jade index template.
+ */
+
+var jadeIndex = [
+    'h1= title'
+  , 'p Welcome to #{title}'
+].join('\n');
+
+/**
+ * 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('\n');
+
+/**
+ * EJS index template.
+ */
+
+var ejsIndex = [
+    '<h1><%= title %></h1>'
+  , '<p>Welcome to <%= title %></p>'
+  ].join('\n');
+
+/**
+ * Default css template.
+ */
+
+var css = [
+    'body {'
+  , '  padding: 50px;'
+  , '  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
+  , '}'
+  , ''
+  , 'a {'
+  , '  color: #00B7FF;'
+  , '}'
+].join('\n');
+
+/**
+ * Default less template.
+ */
+
+var less = [
+    'body {'
+  , '  padding: 50px;'
+  , '  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
+  , '}'
+  , ''
+  , 'a {'
+  , '  color: #00B7FF;'
+  , '}'
+].join('\n');
+
+/**
+ * Default sass template.
+ */
+
+var sass = [
+    'body'
+  , '  :padding 50px'
+  , '  :font 14px "Lucida Grande", Helvetica, Arial, sans-serif'
+  , 'a'
+  , '  :color #00B7FF'
+].join('\n');
+
+/**
+ * Default stylus template.
+ */
+
+var stylus = [
+    'body'
+  , '  padding 50px'
+  , '  font 14px "Lucida Grande", Helvetica, Arial, sans-serif'
+  , 'a'
+  , '  color #00B7FF'
+].join('\n');
+
+/**
+ * App test template.
+ */
+
+var appTest = [
+    ""
+  , "// Run $ expresso"
+  , ""
+  , "/**"
+  , " * Module dependencies."
+  , " */"
+  , ""
+  , "var app = require('../app')"
+  , "  , assert = require('assert');"
+  , "",
+  , "module.exports = {"
+  , "  'GET /': function(){"
+  , "    assert.response(app,"
+  , "      { url: '/' },"
+  , "      { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' }},"
+  , "      function(res){"
+  , "        assert.includes(res.body, '<title>Express</title>');"
+  , "      });"
+  , "  }"
+  , "};"
+].join('\n');
+
+/**
+ * App template.
+ */
+
+var app = [
+    ''
+  , '/**'
+  , ' * Module dependencies.'
+  , ' */'
+  , ''
+  , 'var express = require(\'express\');'
+  , ''
+  , '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(\'/\', function(req, res){'
+  , '  res.render(\'index\', {'
+  , '    title: \'Express\''
+  , '  });'
+  , '});'
+  , ''
+  , '// Only listen on $ node app.js'
+  , ''
+  , 'if (!module.parent) {'
+  , '  app.listen(3000);'
+  , '  console.log("Express server listening on port %d", app.address().port);'
+  , '}'
+  , ''
+].join('\n');
+
+// 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) {
+  mkdir(path, function(){
+    mkdir(path + '/pids');
+    mkdir(path + '/logs');
+    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;
+        case 'less':
+          write(path + '/public/stylesheets/style.less', less);
+          break;
+        case 'sass':
+          write(path + '/public/stylesheets/style.sass', sass);
+          break;
+        default:
+          write(path + '/public/stylesheets/style.css', css);
+      }
+    });
+    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;
+      }
+    });
+    mkdir(path + '/test', function(){
+      write(path + '/test/app.test.js', appTest);
+    });
+
+    // CSS Engine support
+    switch (cssEngine) {
+      case 'sass':
+      case 'less':
+        app = app.replace('{css}', '\n  app.use(express.compiler({ src: __dirname + \'/public\', enable: [\'' + cssEngine + '\'] }));');
+        break;
+      case 'stylus':
+        app = app.replace('{css}', '\n  app.use(require(\'stylus\').middleware({ src: __dirname + \'/public\' }));');
+        break;
+      default:
+        app = app.replace('{css}', '');
+    }
+
+    // Session support
+    app = app.replace('{sess}', sessions
+      ? '\n  app.use(express.cookieParser());\n  app.use(express.session({ secret: \'your secret here\' }));'
+      : '');
+
+    // Template support
+    app = app.replace(':TEMPLATE', templateEngine);
+
+    write(path + '/app.js', app);
+
+    // Suggestions
+    process.on('exit', function(){
+      if (cssEngine) {
+        console.log('   - make sure you have installed %s: \x1b[33m$ npm install %s\x1b[0m'
+          , cssEngine
+          , cssEngine);
+      }
+      console.log('   - make sure you have installed %s: \x1b[33m$ npm install %s\x1b[0m'
+        , templateEngine
+        , templateEngine);
+    });
+  });
+}
+
+/**
+ * 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) {
+  exec('mkdir -p ' + path, function(err){
+    if (err) throw err;
+    console.log('   \x1b[36mcreate\x1b[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 (file)
index 0000000..8d81ea7
--- /dev/null
@@ -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 (file)
index 0000000..9ef0578
--- /dev/null
@@ -0,0 +1,78 @@
+
+/*!
+ * 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.3.3';
+
+/**
+ * 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.
+ */
+
+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 (file)
index 0000000..b80ef4b
--- /dev/null
@@ -0,0 +1,503 @@
+
+/*!
+ * 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')
+  , methods = router.methods.concat(['del', 'all'])
+  , view = require('./view')
+  , 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('home', '/');
+  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));
+
+  // use router, expose as app.get(), etc
+  var fn = router(function(app){ self.routes = app; }, this);
+  this.__defineGetter__('router', function(){
+    this.__usedRouter = true;
+    return fn;
+  });
+
+  // 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 lookup methods
+  this.remove = function(url){
+    return self.remove.all(url);
+  };
+
+  this.match = function(url){
+    return self.match.all(url);
+  };
+
+  this.lookup = function(url){
+    return self.lookup.all(url);
+  };
+
+  methods.forEach(function(method){
+    self.match[method] = function(url){
+      return self.router.match(url, 'all' == method
+        ? null
+        : method);
+    };
+
+    self.remove[method] = function(url){
+      return self.router.remove(url, 'all' == method
+        ? null
+        : method);
+    };
+
+    self.lookup[method] = function(path){
+      return self.router.lookup(path, 'all' == method
+        ? null
+        : method);
+    };
+  });
+};
+
+/**
+ * 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, home, 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) {
+    home = app.set('home');
+    if ('/' == home) home = '';
+    app.set('home', app.route + home);
+    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 `fn`.
+ *
+ * Param mapping is used to provide pre-conditions to routes
+ * which us normalized placeholders. For example ":user_id" may
+ * attempt to load the user from the database, where as ":num" may
+ * pass the value through `parseInt(num, 10)`.
+ *
+ * When the callback function accepts only a single argument, the
+ * value of placeholder is passed:
+ *
+ *    app.param('page', function(n){ return parseInt(n, 10); });
+ *
+ * After which "/users/:page" would automatically provide us with
+ * an integer for `req.params.page`. If desired we could use the callback
+ * signature shown below, and immediately `next(new Error('invalid page'))`
+ * when `parseInt` fails.
+ *
+ * Alternatively the callback may accept the request, response, next, and
+ * the value, acting like middlware:
+ *
+ *     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'));
+ *         }
+ *       });
+ *     });
+ *
+ * Now every time ":userId" is present, the associated user object
+ * will be loaded and assigned before the route handler is invoked.
+ *
+ * @param {String|Array} name
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.param = function(name, fn){
+  if (Array.isArray(name)) {
+    name.forEach(function(name){
+      this.param(name, fn);
+    }, this);
+  } else {
+    if (':' == name[0]) name = name.substr(1);
+    this.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 the given `env`.
+ *
+ * @param {String} env
+ * @param {Function} fn
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.configure = function(env, fn){
+  if ('function' == typeof env) {
+    fn = env, env = 'all';
+  }
+  if ('all' == env || env == this.settings.env) {
+    fn.call(this);
+  }
+  return this;
+};
+
+// Generate routing methods
+
+function generateMethod(method){
+  app[method] = function(path){
+    var self = this;
+
+    // Lookup
+    if (1 == arguments.length) {
+      return this.router.lookup(path, 'all' == method
+        ? null
+        : method);
+    }
+
+    // Ensure router is mounted
+    if (!this.__usedRouter) this.use(this.router);
+
+    // Generate the route
+    this.routes[method].apply(this, arguments);
+    return this;
+  };
+  return arguments.callee;
+}
+
+methods.forEach(generateMethod);
+
+// Alias delete as "del"
+
+app.del = app.delete;
diff --git a/node_modules/express/lib/https.js b/node_modules/express/lib/https.js
new file mode 100644 (file)
index 0000000..8a8c008
--- /dev/null
@@ -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 (file)
index 0000000..f22690d
--- /dev/null
@@ -0,0 +1,289 @@
+
+/*!
+ * 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')
+  , 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;
+  }
+};
+
+/**
+ * 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('/') < 0) {
+      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) >= 0;
+  } 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(utils.escape(msg));
+    msg = msg.replace(/%([a-zA-Z])/g, function(_, format){
+      var formatter = formatters[format];
+      if (formatter) return formatter(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 contentType = this.headers['content-type'];
+  if (!contentType) return;
+  if (!~type.indexOf('/')) type = mime.lookup(type);
+  if (~type.indexOf('*')) {
+    type = type.split('/')
+    contentType = contentType.split('/');
+    if ('*' == type[0] && type[1] == contentType[1]) return true;
+    if ('*' == type[1] && type[0] == contentType[0]) return true;
+  }
+  return ~contentType.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 (file)
index 0000000..2c3ac64
--- /dev/null
@@ -0,0 +1,423 @@
+
+/*!
+ * 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
+  , join = require('path').join
+  , mime = require('mime');
+
+/**
+ * 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) 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 {
+        if (!this.header('Content-Type')) {
+          this.charset = this.charset || 'utf-8';
+          this.contentType('.json');
+        }
+        body = JSON.stringify(body);
+        if (this.req.query.callback && this.app.set('jsonp callback')) {
+          this.charset = this.charset || 'utf-8';
+          this.header('Content-Type', 'text/javascript');
+          body = this.req.query.callback.replace(/[^\w$.]/g, '') + '(' + body + ');';
+        }
+      }
+      break;
+  }
+
+  // populate Content-Length
+  if (!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) {
+    this.removeHeader('Content-Type');
+    this.removeHeader('Content-Length');
+  }
+
+  // respond
+  this.statusCode = status;
+  this.end('HEAD' == this.req.method ? undefined : body);
+};
+
+/**
+ * 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 = 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="' + path.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 headers have 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 {String}
+ * @api public
+ */
+
+res.header = function(name, val){
+  if (val === undefined) {
+    return this.getHeader(name);
+  } else {
+    this.setHeader(name, val);
+    return val;
+  }
+};
+
+/**
+ * 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`
+ *
+ * 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);
+  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
+ * "home" setting. Express also supports "home" out of the box,
+ * which can be set via `app.set('home', '/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('home') || '/'
+    , status = status || 302
+    , 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 (app.route) {
+      url = join(app.route, 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(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/index.js b/node_modules/express/lib/router/index.js
new file mode 100644 (file)
index 0000000..5a80b5c
--- /dev/null
@@ -0,0 +1,329 @@
+
+/*!
+ * Express - router
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , parse = require('url').parse
+  , _methods = require('./methods')
+  , Route = require('./route');
+
+/**
+ * Expose router.
+ */
+
+exports = module.exports = router;
+
+/**
+ * Expose methods.
+ */
+
+exports.methods = _methods;
+
+/**
+ * Provides Sinatra-like routing capabilities.
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @api private
+ */
+
+function router(fn, app){
+  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);
+      }
+
+      if (!path) throw new Error(name + ' route requires a path');
+      if (!fn) throw new Error(name + ' route ' + path + ' requires a callback');
+
+      var options = { sensitive: app.enabled('case sensitive routes') };
+      var route = new Route(name, path, fn, options);
+      route.middleware = middleware;
+      localRoutes.push(route);
+      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.callback.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, ret){
+    var ret = ret || []
+      , route;
+
+    // method specific remove
+    if (method) {
+      method = method.toUpperCase();
+      if (routes[method]) {
+        for (var i = 0; i < routes[method].length; ++i) {
+          route = routes[method][i];
+          if (path == route.path) {
+            route.index = i;
+            routes[method].splice(i, 1);
+            ret.push(route);
+            --i;
+          }
+        }
+      }
+    // global remove
+    } else {
+      _methods.forEach(function(method){
+        router.remove(path, method, ret);
+      });
+    }
+
+    return ret;
+  };
+
+  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.path) {
+            route.index = i;
+            ret.push(route);
+          }
+        });
+      }
+    // 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
+      , route
+      , req;
+
+    // method specific matches
+    if (method) {
+      method = method.toUpperCase();
+      req = { url: url, method: method };
+      while (route = match(req, routes, i)) {
+        i = req._route_index + 1;
+        route.index = i;
+        ret.push(route);
+      } 
+    // 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.send(body, { Allow: 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].regexp.test(path)) return true;
+    }
+  }).map(function(method){
+    return method.toUpperCase();
+  });
+}
+
+/**
+ * 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;
+
+  // pass HEAD to GET routes
+  if ('HEAD' == method) method = 'GET';
+
+  // routes for this method
+  if (routes = routes[method]) {
+    var url = parse(req.url)
+      , pathname = url.pathname;
+
+    // matching routes
+    for (var len = routes.length; i < len; ++i) {
+      var route = routes[i]
+        , fn = route.callback
+        , path = route.regexp
+        , keys = route.keys;
+
+      // match
+      if (captures = path.exec(pathname)) {
+        route.params = [];
+        for (var j = 1, l = captures.length; j < l; ++j) {
+          var key = keys[j-1],
+            val = 'string' == typeof captures[j]
+              ? decodeURIComponent(captures[j])
+              : captures[j];
+          if (key) {
+            route.params[key] = val;
+          } else {
+            route.params.push(val);
+          }
+        }
+        req._route_index = i;
+        return route;
+      }
+    }
+  }
+}
diff --git a/node_modules/express/lib/router/methods.js b/node_modules/express/lib/router/methods.js
new file mode 100644 (file)
index 0000000..e19787b
--- /dev/null
@@ -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 (file)
index 0000000..6b747a1
--- /dev/null
@@ -0,0 +1,71 @@
+
+/*!
+ * 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 callback `fn` and `options`.
+ *
+ * Options:
+ *
+ *   - `sensitive`   enable case-sensitive routes
+ *
+ * @param {String} method
+ * @param {String} path
+ * @param {Function} fn
+ * @param {Object} options.
+ * @api private
+ */
+
+function Route(method, path, fn, options) {
+  options = options || {};
+  this.callback = fn;
+  this.path = path;
+  this.regexp = normalize(path, this.keys = [], options.sensitive);
+  this.method = method;
+}
+
+/**
+ * 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
+ * @return {RegExp}
+ * @api private
+ */
+
+function normalize(path, keys, sensitive) {
+  if (path instanceof RegExp) return path; 
+  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 + '$', sensitive ? '' : 'i');
+}
\ No newline at end of file
diff --git a/node_modules/express/lib/utils.js b/node_modules/express/lib/utils.js
new file mode 100644 (file)
index 0000000..a620bc6
--- /dev/null
@@ -0,0 +1,122 @@
+
+/*!
+ * Express - Utils
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * 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;
+};
diff --git a/node_modules/express/lib/view.js b/node_modules/express/lib/view.js
new file mode 100644 (file)
index 0000000..89317b8
--- /dev/null
@@ -0,0 +1,413 @@
+
+/*!
+ * 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;
+
+/**
+ * Partial render helper.
+ *
+ * @api private
+ */
+
+function renderPartial(res, view, options, parentLocals, parent){
+  var collection, object, locals;
+
+  // Inherit parent view extension when not present
+  if (parent && !~view.indexOf('.')) {
+    view += parent.extension;
+  }
+
+  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.renderPartial = 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);
+      } else {
+        options.scope = 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 || {}
+    , 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 (app.set('view engine')) {
+    parent.extension = '.' + app.set('view engine');
+  }
+
+  // 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
+    // several next(err) calls
+    } 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')
+    , cacheViews = app.enabled('view cache')
+    , root = app.set('views') || process.cwd() + '/views';
+
+  // cache id
+  var cid = view + (parent ? ':' + parent.path : '');
+
+  // 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.renderPartial
+    , 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);
+  };
+
+  // cached view
+  if (app.cache[cid]) {
+    view = app.cache[cid];
+    options.filename = view.path;
+  // resolve view
+  } else {
+    var orig = view = new View(view, options);
+
+    // Try _ prefix ex: ./views/_<name>.jade
+    if (partial) {
+      view = new View(orig.prefixPath, options);
+      if (!view.exists) view = orig;
+    }
+  
+    // Try index ex: ./views/user/index.jade
+    if (!view.exists) view = new View(orig.indexPath, options);
+
+    // Try ../<name>/index ex: ../user/index.jade
+    // when calling partial('user') within the same dir
+    if (!view.exists && !options.isLayout) 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);
+
+    // Does not exist
+    if (!view.exists) {
+      if (app.enabled('hints')) hintAtViewPaths(orig, options);
+      var err = new Error('failed to locate view "' + orig.view + '"');
+      err.view = orig;
+      throw err;
+    }    
+
+    options.filename = view.path;
+    var engine = view.templateEngine;
+    view.fn = engine.compile(view.contents, options)
+    if (cacheViews) app.cache[cid] = view;
+  }
+
+  // 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();
+}
\ No newline at end of file
diff --git a/node_modules/express/lib/view/partial.js b/node_modules/express/lib/view/partial.js
new file mode 100644 (file)
index 0000000..7d2f69b
--- /dev/null
@@ -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 (file)
index 0000000..f7c68db
--- /dev/null
@@ -0,0 +1,206 @@
+
+/*!
+ * 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
+  , 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) 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 ('/' == path[0]) 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 (file)
index 0000000..b04a224
--- /dev/null
@@ -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 (file)
index 0000000..0c5d22d
--- /dev/null
@@ -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 (file)
index 0000000..7477048
--- /dev/null
@@ -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/connect.js b/node_modules/express/node_modules/connect/lib/connect.js
new file mode 100644 (file)
index 0000000..6e37577
--- /dev/null
@@ -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.4.0';
+
+/**
+ * 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 (file)
index 0000000..6ffc5cc
--- /dev/null
@@ -0,0 +1,218 @@
+
+/*!
+ * 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 = '/';
+  }
+
+  // multiples
+  if (arguments.length > 2) {
+    return Array.prototype.slice.call(arguments, 1).forEach(function(fn){
+      this.use(route, fn);
+    }, this);
+  }
+
+  // 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) {
+    req.url = removed + req.url;
+    req.originalUrl = req.originalUrl || req.url;
+    removed = '';
+
+    var layer = stack[index++];
+
+    // all done
+    if (!layer) {
+      // but wait! we have a parent
+      if (out) return out(err);
+
+      // otherwise send a proper error message to the browser.
+      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());
+
+        res.statusCode = 500;
+        res.setHeader('Content-Type', 'text/plain');
+        res.end(msg);
+      } else {
+        res.statusCode = 404;
+        res.setHeader('Content-Type', 'text/plain');
+        res.end('Cannot ' + req.method + ' ' + req.url);
+      }
+      return;
+    }
+
+    try {
+      var pathname = parse(req.url).pathname;
+      if (undefined == pathname) pathname = '/';
+
+      // skip this layer if the route doesn't match.
+      if (0 != pathname.indexOf(layer.route)) return next(err);
+
+      var nextChar = pathname[layer.route.length];
+      if (nextChar && '/' != nextChar && '.' != nextChar) 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 (file)
index 0000000..9b09fa4
--- /dev/null
@@ -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 (file)
index 0000000..eaaa489
--- /dev/null
@@ -0,0 +1,41 @@
+
+/**
+ * # 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
+ *  - [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
+ *  - [static](middleware-static.html) streaming static file server supporting `Range` and more
+ *  - [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
+ *
+ * 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 (file)
index 0000000..3ff472b
--- /dev/null
@@ -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 (file)
index 0000000..6de74db
--- /dev/null
@@ -0,0 +1,91 @@
+
+/*!
+ * Connect - bodyParser
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('qs');
+
+/**
+ * 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_ and _application/x-www-form-urlencoded_
+ * are supported, however you may map `connect.bodyParser.parse[contentType]`
+ * to a function of your choice to replace existing parsers, or implement
+ * one for other content-types.
+ *
+ * Examples:
+ *
+ *      connect.createServer(
+ *          connect.bodyParser()
+ *        , function(req, res) {
+ *          res.end('viewing user ' + req.body.user.name);
+ *        }
+ *      );
+ *
+ * Since both _json_ and _x-www-form-urlencoded_ are supported by
+ * default, either of the following requests would result in the response
+ * of "viewing user tj".
+ *
+ *      $ curl -d 'user[name]=tj' http://localhost/
+ *      $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://localhost/
+ *
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function bodyParser(){
+  return function bodyParser(req, res, next) {
+    var parser = exports.parse[mime(req)];
+    if (parser && !req.body) {
+      var data = '';
+      req.setEncoding('utf8');
+      req.on('data', function(chunk) { data += chunk; });
+      req.on('end', function(){
+        req.rawBody = data;
+        try {
+          req.body = data
+            ? parser(data)
+            : {};
+        } catch (err) {
+          return next(err);
+        }
+        next();
+      });
+    } else {
+      next();
+    }
+  }
+};
+
+/**
+ * Supported decoders.
+ *
+ *  - application/x-www-form-urlencoded
+ *  - application/json
+ */
+
+exports.parse = {
+    'application/x-www-form-urlencoded': qs.parse
+  , 'application/json': JSON.parse
+};
\ 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 (file)
index 0000000..798b268
--- /dev/null
@@ -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 cass 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 (file)
index 0000000..d6b69de
--- /dev/null
@@ -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/errorHandler.js b/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js
new file mode 100644 (file)
index 0000000..3bea222
--- /dev/null
@@ -0,0 +1,101 @@
+
+/*!
+ * 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 (file)
index 0000000..8eeafba
--- /dev/null
@@ -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 (file)
index 0000000..3bff0cc
--- /dev/null
@@ -0,0 +1,78 @@
+
+/*!
+ * 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);
+ *
+ * TODO: pause EV_READ
+ *
+ * @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) deny();
+
+    // 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 (file)
index 0000000..f7ff0a1
--- /dev/null
@@ -0,0 +1,169 @@
+
+/*!
+ * 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_
+ *
+ * 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`
+ *
+ * @param {String|Function|Object} format or options
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function logger(options) {
+  if ('object' == typeof options) {
+    options = options || {};
+  } else if (options) {
+    options = { format: options };
+  } else {
+    options = {};
+  }
+
+  var fmt = options.format
+    , 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) {
+    var start = +new Date
+      , statusCode
+      , writeHead = res.writeHead
+      , end = res.end
+      , url = req.originalUrl;
+
+    // mount safety
+    if (req._logging) return next();
+
+    // flag as logging
+    req._logging = true;
+
+    // proxy for statusCode.
+    res.writeHead = function(code, headers){
+      res.writeHead = writeHead;
+      res.writeHead(code, headers);
+      res.__statusCode = statusCode = code;
+      res.__headers = headers || {};
+    };
+
+    // proxy end to output a line to the provided logger.
+    if (fmt) {
+      res.end = function(chunk, encoding) {
+        res.end = end;
+        res.end(chunk, encoding);
+        res.responseTime = +new Date - start;
+        if ('function' == typeof fmt) {
+          var line = fmt(req, res, function(str){ return format(str, req, res); });
+          if (line) stream.write(line + '\n', 'ascii');
+        } else {
+          stream.write(format(fmt, req, res) + '\n', 'ascii');
+        }
+      };
+    } else {
+      res.end = function(chunk, encoding) {
+        var contentLength = (res._headers && res._headers['content-length'])
+          || (res.__headers && res.__headers['Content-Length'])
+          || '-';
+
+        res.end = end;
+        res.end(chunk, encoding);
+
+        stream.write((req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)))
+           + ' - - [' + (new Date).toUTCString() + ']'
+           + ' "' + req.method + ' ' + url
+           + ' HTTP/' + req.httpVersionMajor + '.' + req.httpVersionMinor + '" '
+           + (statusCode || res.statusCode) + ' ' + contentLength
+           + ' "' + (req.headers['referer'] || req.headers['referrer'] || '')
+           + '" "' + (req.headers['user-agent'] || '') + '"\n', 'ascii');
+      };
+    }
+
+    next();
+  };
+};
+
+/**
+ * Return formatted log line.
+ *
+ * @param  {String} str
+ * @param  {IncomingMessage} req
+ * @param  {ServerResponse} res
+ * @return {String}
+ * @api private
+ */
+function format(str, req, res) {
+  return str
+    .replace(':url', req.originalUrl)
+    .replace(':method', req.method)
+    .replace(':status', res.__statusCode || res.statusCode)
+    .replace(':response-time', res.responseTime)
+    .replace(':date', new Date().toUTCString())
+    .replace(':referrer', req.headers['referer'] || req.headers['referrer'] || '')
+    .replace(':http-version', req.httpVersionMajor + '.' + req.httpVersionMinor)
+    .replace(':remote-addr', req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)))
+    .replace(':user-agent', req.headers['user-agent'] || '')
+    .replace(/:req\[([^\]]+)\]/g, function(_, field){ return req.headers[field.toLowerCase()]; })
+    .replace(/:res\[([^\]]+)\]/g, function(_, field){
+      return res._headers
+        ? (res._headers[field.toLowerCase()] || res.__headers[field])
+        : (res.__headers && res.__headers[field]);
+    });
+}
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 (file)
index 0000000..db4e9f3
--- /dev/null
@@ -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 (file)
index 0000000..b0b5bac
--- /dev/null
@@ -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/responseTime.js b/node_modules/express/node_modules/connect/lib/middleware/responseTime.js
new file mode 100644 (file)
index 0000000..2b2133a
--- /dev/null
@@ -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 (file)
index 0000000..a07452e
--- /dev/null
@@ -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 (file)
index 0000000..95715e9
--- /dev/null
@@ -0,0 +1,329 @@
+
+/*!
+ * 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 req.headers['user-agent'] || '';
+};
+
+/**
+ * Paths to ignore, defaulting to `/favicon.ico`.
+ */
+
+exports.ignore = ['/favicon.ico'];
+
+/**
+ * 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#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 (file)
index 0000000..793c2e9
--- /dev/null
@@ -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 (file)
index 0000000..ec569f5
--- /dev/null
@@ -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 (file)
index 0000000..4e7e1a6
--- /dev/null
@@ -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 (file)
index 0000000..a71eeca
--- /dev/null
@@ -0,0 +1,59 @@
+
+/*!
+ * Connect - session - Store
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Session = require('./session')
+  , Cookie = require('./cookie')
+  , utils = require('../../utils');
+
+/**
+ * Initialize abstract `Store`.
+ *
+ * @api private
+ */
+
+var Store = module.exports = function Store(options){};
+
+/**
+ * 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);
+  });
+};
+
+/**
+ * Create session from JSON `sess` data.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} sess
+ * @return {Session}
+ * @api private
+ */
+
+Store.prototype.createSession = function(req, sess){
+  var expires = sess.cookie.expires
+    , orig = sess.cookie.originalMaxAge;
+  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);
+  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 (file)
index 0000000..89645f4
--- /dev/null
@@ -0,0 +1,203 @@
+
+/*!
+ * Connect - staticProvider
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , join = require('path').join
+  , 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
+ *
+ * @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;
+    send(req, res, next, options);
+  };
+};
+
+/**
+ * Respond with 403 "Forbidden".
+ *
+ * @param {ServerResponse} res
+ * @api private
+ */
+
+function forbidden(res) {
+  var body = 'Forbidden';
+  res.setHeader('Content-Type', 'text/plain');
+  res.setHeader('Content-Length', body.length);
+  res.statusCode = 403;
+  res.end(body);
+}
+
+/**
+ * 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
+    , root = options.root
+    , fn = options.callback;
+
+  // replace next() with callback when available
+  if (fn) next = fn;
+
+  // ignore non-GET requests
+  if ('GET' != req.method && !head) return next();
+
+  // parse url
+  var url = parse(options.path)
+    , path = decodeURIComponent(url.pathname)
+    , type;
+
+  // potentially malicious path
+  if (~path.indexOf('..')) return fn
+    ? fn(new Error('Forbidden'))
+    : forbidden(res);
+
+  // join from optional root dir
+  path = join(options.root, path);
+
+  // index.html support
+  if ('/' == path[path.length - 1]) path += 'index.html';
+
+  // mime type
+  type = mime.lookup(path);
+
+  fs.stat(path, function(err, stat){
+    // ignore ENOENT
+    if (err) {
+      if (fn) return fn(err);
+      return 'ENOENT' == err.code
+        ? next()
+        : next(err);
+    // ignore directories
+    } else if (stat.isDirectory()) {
+      return fn
+        ? fn(new Error('Cannot Transfer Directory'))
+        : next();
+    }
+
+    // we have a Range request
+    if (ranges) {
+      ranges = utils.parseRange(stat.size, ranges);
+      // valid
+      if (ranges) {
+        // TODO: stream options
+        // TODO: multiple support
+        var stream = fs.createReadStream(path, ranges[0])
+          , start = ranges[0].start
+          , end = ranges[0].end;
+        res.statusCode = 206;
+        res.setHeader('Content-Range', 'bytes '
+          + start
+          + '-'
+          + end
+          + '/'
+          + stat.size);
+      // invalid
+      } else {
+        return fn
+          ? fn(new Error('Requested Range Not Satisfiable'))
+          : invalidRange(res);
+      }
+    // stream the entire file
+    } else {
+      res.setHeader('Content-Length', stat.size);
+      res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000));
+      res.setHeader('Last-Modified', stat.mtime.toUTCString());
+      res.setHeader('ETag', utils.etag(stat));
+
+      // conditional GET support
+      if (utils.conditionalGET(req)) {
+        if (!utils.modified(req, res)) {
+          return utils.notModified(res);
+        }
+      }
+
+      // read stream
+      var stream = fs.createReadStream(path);
+    }
+
+    // transfer
+    if (!res.getHeader('content-type')) {
+      var charset = mime.charsets.lookup(type);
+      res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
+    }
+    res.setHeader('Accept-Ranges', 'bytes');
+
+    if (head) return res.end();
+    stream.pipe(res);
+    if (fn) {
+      res.connection.on('error', fn);
+      stream.on('end', fn);
+    }
+  });
+};
\ 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 (file)
index 0000000..50be925
--- /dev/null
@@ -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, next);
+    } 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 (file)
index 0000000..e8620fe
--- /dev/null
@@ -0,0 +1,45 @@
+
+/*!
+ * Connect
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , res = http.OutgoingMessage.prototype;
+
+// original setHeader()
+
+var setHeader = res.setHeader;
+
+/**
+ * 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);
+};
\ 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 (file)
index 0000000..34e0df5
--- /dev/null
@@ -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 (file)
index 0000000..895fc96
Binary files /dev/null and b/node_modules/express/node_modules/connect/lib/public/favicon.ico 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 (file)
index 0000000..d4eb14f
--- /dev/null
@@ -0,0 +1,61 @@
+body {
+  margin: 0;
+  padding: 80px 100px;
+  font: 13px "Helvetica Neue", "Lucida Grande", "Arial";
+  background: #F8F8F8;
+  background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9));
+  background: -moz-linear-gradient(top, #fff, #ECE9E9);
+  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;
+}
+#stacktrace {
+       margin-top: 15px;
+}
\ No newline at end of file
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 (file)
index 0000000..1a9e905
--- /dev/null
@@ -0,0 +1,405 @@
+
+/*!
+ * 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 (obj[key] === undefined) {
+      obj[key] = decodeURIComponent(val.replace(/\+/g, ' '));
+    }
+  }
+  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 412 "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;
+};
+
+/**
+ * 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/package.json b/node_modules/express/node_modules/connect/package.json
new file mode 100644 (file)
index 0000000..37d7d9d
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "name": "connect",
+  "version": "1.4.0",
+  "description": "High performance middleware framework",
+  "keywords": ["framework", "web", "middleware", "connect", "rack"],
+  "repository": "git://github.com/senchalabs/connect.git",
+  "author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
+  "repository": "git://github.com/senchalabs/connect",
+  "dependencies": {
+    "qs": ">= 0.0.6",
+    "mime": ">= 0.0.1"
+  },
+  "main": "index",
+  "engines": { "node": ">= 0.4.1 < 0.5.0" }
+}
\ No newline at end of file
diff --git a/node_modules/express/node_modules/connect/test.js b/node_modules/express/node_modules/connect/test.js
new file mode 100644 (file)
index 0000000..4e4ae48
--- /dev/null
@@ -0,0 +1,26 @@
+
+/**
+ * Module dependencies.
+ */
+
+var connect = require('./');
+
+var router = connect.router(function(app){
+  function one(req, res, next) {
+    console.log('one');
+    next();
+  }
+  
+  function two(req, res, next) {
+    console.log('two');
+    next();
+  }
+
+  app.param('user', one, two);
+
+  app.get('/user/:user', one, two, function(req, res){
+    res.end('yay');
+  });
+});
+
+connect(router).listen(3000);
\ No newline at end of file
diff --git a/node_modules/express/node_modules/mime/README.md b/node_modules/express/node_modules/mime/README.md
new file mode 100644 (file)
index 0000000..5aa6a28
--- /dev/null
@@ -0,0 +1,54 @@
+# 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
+
+### mime.lookup(path) - lookup the type for a file or extension
+
+    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.)
+
+## "Can you add support for [some type/extension]?"
+
+Start by adding support for the type in your project using the mime.define() or mime.load() methods (documented below).
+
+If there's a type that is shared across node.js modules, by different people, create an issue here and we'll add it if it makes sense.
+
+If the type in question applies to projects outside the node.js community (e.g. if [IANA](http://www.iana.org/assignments/media-types/) approves a new type) file a [bug with Apache](http://httpd.apache.org/bug_report.html) and create an issue here that links to it.
+
+### 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/index.js b/node_modules/express/node_modules/mime/index.js
new file mode 100644 (file)
index 0000000..4a58dae
--- /dev/null
@@ -0,0 +1 @@
+module.exports = require('./mime');
diff --git a/node_modules/express/node_modules/mime/mime.js b/node_modules/express/node_modules/mime/mime.js
new file mode 100644 (file)
index 0000000..62bff98
--- /dev/null
@@ -0,0 +1,89 @@
+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;
+      }
+
+      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, 'mime.types'));
+
+// Overlay enhancements we've had requests for (and that seem to make sense)
+mime.load(path.join(__dirname, 'node.types'));
+
+// Set the default type
+mime.default_type = mime.types.bin;
diff --git a/node_modules/express/node_modules/mime/mime.types b/node_modules/express/node_modules/mime/mime.types
new file mode 100644 (file)
index 0000000..1ae0097
--- /dev/null
@@ -0,0 +1,1351 @@
+# 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                                    Extensions
+# 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/cea-2018+xml
+# application/cellml+xml
+# 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/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/fastinfoset
+# application/fastsoap
+# application/fits
+application/font-tdpfr                         pfr
+# 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/marc                               mrc
+application/mathematica                                ma nb mb
+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/mikey
+# application/moss-keys
+# application/moss-signature
+# application/mosskey-data
+# application/mosskey-request
+application/mp4                                        mp4s
+# application/mpeg4-generic
+# application/mpeg4-iod
+# application/mpeg4-iod-xmt
+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/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/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/ssml+xml                           ssml
+# application/timestamp-query
+# application/timestamp-reply
+# 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.partial-upload
+application/vnd.adobe.xdp+xml                  xdp
+application/vnd.adobe.xfdf                     xfdf
+# application/vnd.aether.imp
+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.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.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.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.esgcontainer
+# application/vnd.dvb.ipdcdftnotifaccess
+# application/vnd.dvb.ipdcesgaccess
+# 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.dxr
+application/vnd.dynageo                                geo
+# 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.iptvueprofile+xml
+# application/vnd.etsi.mcid+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.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.intercon.formnet               xpw xpx
+# 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.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.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-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.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         otm
+application/vnd.oasis.opendocument.text-template       ott
+application/vnd.oasis.opendocument.text-web            oth
+# application/vnd.obn
+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.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.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.osa.netdeploy
+# 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.rapid
+application/vnd.realvnc.bed                    bed
+application/vnd.recordare.musicxml             mxl
+application/vnd.recordare.musicxml+xml         musicxml
+# application/vnd.renlearn.rlprint
+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
+application/vnd.stardivision.writer            vor
+application/vnd.stardivision.writer-global     sgl
+# 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.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.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.smaf-audio              saf
+application/vnd.yamaha.smaf-phrase             spf
+application/vnd.yellowriver-custom-menu                cmp
+application/vnd.zul                            zir zirz
+application/vnd.zzazz.deck+xml                 zaz
+application/voicexml+xml                       vxml
+# application/watcherinfo+xml
+# application/whoispp-query
+# application/whoispp-response
+application/winhlp                             hlp
+# application/wita
+# application/wordperfect5.1
+application/wsdl+xml                           wsdl
+application/wspolicy+xml                       wspolicy
+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-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-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/zip                                        zip
+# 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/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.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.sealedmedia.softseal.mpeg
+# audio/vnd.vmx.cvsd
+# audio/vorbis
+# audio/vorbis-config
+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/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.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/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/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.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/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/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/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/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/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.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.vivo                                 viv
+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/node.types b/node_modules/express/node_modules/mime/node.types
new file mode 100644 (file)
index 0000000..84a7dfc
--- /dev/null
@@ -0,0 +1,3 @@
+application/mp4        m4p
+application/octet-stream       bin buffer
+audio/mp4      m4a
diff --git a/node_modules/express/node_modules/mime/package.json b/node_modules/express/node_modules/mime/package.json
new file mode 100644 (file)
index 0000000..34ff5fc
--- /dev/null
@@ -0,0 +1,11 @@
+{ "name"          : "mime"
+, "description"   : "A comprehensive library for mime-type mapping"
+, "url"           : "http://github.com/bentomas/node-mime"
+, "keywords"      : ["util", "mime"]
+, "author"        : "Benjamin Thomas <benjamin@benjaminthomas.org>"
+, "contributors"  : []
+, "dependencies"  : []
+, "lib"           : "."
+, "main"          : "mime.js"
+, "version"       : "1.2.1"
+}
diff --git a/node_modules/express/node_modules/mime/test.js b/node_modules/express/node_modules/mime/test.js
new file mode 100644 (file)
index 0000000..44ce43f
--- /dev/null
@@ -0,0 +1,74 @@
+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/qs/.gitmodules b/node_modules/express/node_modules/qs/.gitmodules
new file mode 100644 (file)
index 0000000..49e31da
--- /dev/null
@@ -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/History.md b/node_modules/express/node_modules/qs/History.md
new file mode 100644 (file)
index 0000000..c2a9796
--- /dev/null
@@ -0,0 +1,36 @@
+
+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 (file)
index 0000000..4bbe969
--- /dev/null
@@ -0,0 +1,7 @@
+
+test:
+       @./support/expresso/bin/expresso \
+               -I support \
+               -I lib
+
+.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 (file)
index 0000000..78cbe24
--- /dev/null
@@ -0,0 +1,38 @@
+
+# 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
+
+    require('querystring').parse('user[name][first]=tj&user[email]=tj');
+    // => { user: { name: { first: 'tj' }}}
+
+## 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 (file)
index 0000000..165095e
--- /dev/null
@@ -0,0 +1,32 @@
+
+var old = require('querystring')
+  , qs = require('./')
+  , times = 100000;
+
+var start = new Date
+  , n = times;
+
+while (n--) old.parse('foo=bar');
+console.log('old simple: %dms', new Date - start);
+
+var start = new Date
+  , n = times;
+
+while (n--) old.parse('user[name][first]=tj&user[name][last]=holowaychuk');
+console.log('old nested: %dms', new Date - start);
+
+
+console.log();
+
+
+var start = new Date
+  , n = times;
+
+while (n--) qs.parse('foo=bar');
+console.log('new 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('new 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 (file)
index 0000000..6fe9f47
--- /dev/null
@@ -0,0 +1,39 @@
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('./');
+
+var obj = qs.parse('foo');
+require('inspect')(obj)
+
+var obj = qs.parse('foo=bar=baz');
+require('inspect')(obj)
+
+var obj = qs.parse('users[]');
+require('inspect')(obj)
+
+var obj = qs.parse('name=tj&email=tj@vision-media.ca');
+require('inspect')(obj)
+
+var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane');
+require('inspect')(obj)
+
+var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
+require('inspect')(obj)
+
+var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk');
+require('inspect')(obj)
+
+var obj = qs.parse('a=a&a=b&a=c');
+require('inspect')(obj)
+
+var obj = qs.parse('user[tj]=tj&user[tj]=TJ');
+require('inspect')(obj)
+
+var obj = qs.parse('user[names]=tj&user[names]=TJ&user[names]=Tyler');
+require('inspect')(obj)
+
+var obj = qs.parse('user[name][first]=tj&user[name][first]=TJ');
+require('inspect')(obj)
\ 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 (file)
index 0000000..d177d20
--- /dev/null
@@ -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 (file)
index 0000000..5fb3441
--- /dev/null
@@ -0,0 +1,123 @@
+
+/*!
+ * querystring
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Library version.
+ */
+
+exports.version = '0.1.0';
+
+/**
+ * Parse the given query `str`, returning an object.
+ *
+ * @param {String} str
+ * @return {Object}
+ * @api public
+ */
+
+exports.parse = function(str) {
+  if (str == undefined || str == '') return {};
+
+  return String(str)
+    .split('&')
+    .reduce(function(ret, pair){
+      var pair = decodeURIComponent(pair.replace(/\+/g, ' '))
+        , 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)
+        , obj = ret;
+
+      // ?foo
+      if ('' == key) key = pair, val = '';
+
+      // nested
+      if (~key.indexOf(']')) {
+        var parts = key.split('[')
+          , len = parts.length
+          , last = len - 1;
+
+        function parse(obj, parts, parent, key) {
+          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 {
+              parent[key] = [parent[key], val];
+            }
+          // array
+          } else if (']' == part) {
+            obj = parent[key] = Array.isArray(parent[key])
+              ? parent[key]
+              : [];
+            if ('' != val) obj.push(val);
+          // prop
+          } else if (~part.indexOf(']')) {
+            part = part.substr(0, part.length - 1);
+            parse(obj[part] = obj[part] || {}, parts, obj, part);
+          // key
+          } else {
+            parse(obj[part] = obj[part] || {}, parts, obj, part);
+          }
+        }
+
+        parse(obj, parts);
+      // optimize
+      } else {
+        set(obj, key, val);
+      }
+
+      return ret;
+    }, {});
+};
+
+/**
+ * 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 (file)
index 0000000..a28a899
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "name": "qs",
+  "description": "querystring parser",
+  "version": "0.1.0",
+  "repository": {},
+  "author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
+  "main": "index",
+  "engines": { "node": "*" }
+}
\ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/support/expresso/.gitignore b/node_modules/express/node_modules/qs/support/expresso/.gitignore
new file mode 100644 (file)
index 0000000..432563f
--- /dev/null
@@ -0,0 +1,3 @@
+.DS_Store
+lib-cov
+*.seed
\ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/support/expresso/.gitmodules b/node_modules/express/node_modules/qs/support/expresso/.gitmodules
new file mode 100644 (file)
index 0000000..191ddeb
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "deps/jscoverage"]
+       path = deps/jscoverage
+       url = git://github.com/visionmedia/node-jscoverage.git
diff --git a/node_modules/express/node_modules/qs/support/expresso/History.md b/node_modules/express/node_modules/qs/support/expresso/History.md
new file mode 100644 (file)
index 0000000..cb16fa9
--- /dev/null
@@ -0,0 +1,128 @@
+
+0.7.2 / 2010-12-29 
+==================
+
+  * Fixed problem with `listen()` sometimes firing on the same tick [guillermo]
+
+0.7.1 / 2010-12-28 
+==================
+
+  * Fixed `assert.request()` client logic into an issue() function, fired upon the `listen()` callback if the server doesn't have an assigned fd. [guillermo]
+  * Removed `--watch`
+
+0.7.0 / 2010-11-19 
+==================
+
+  * Removed `assert` from test function signature
+    Just use `require('assert')` :) this will make integration
+    with libraries like [should](http://github.com/visionmedia/should) cleaner.
+
+0.6.4 / 2010-11-02 
+==================
+
+  * Added regexp support to `assert.response()` headers
+  * Removed `waitForExit` code, causing issues
+
+0.6.3 / 2010-11-02 
+==================
+
+  * Added `assert.response()` body RegExp support
+  * Fixed issue with _--serial_ not executing files sequentially. Closes #42
+  * Fixed hang when modules use `setInterval` - monitor running tests & force the process to quit after all have completed + timeout [Steve Mason]
+
+0.6.2 / 2010-09-17 
+==================
+
+  * Added _node-jsocoverage_ to package.json (aka will respect npm's binroot)
+  * Added _-t, --timeout_ MS option, defaulting to 2000 ms
+  * Added _-s, --serial_
+  * __PREFIX__ clobberable
+  * Fixed `assert.response()` for latest node
+  * Fixed cov reporting from exploding on empty files
+
+0.6.2 / 2010-08-03
+==================
+
+  * Added `assert.type()`
+  * Renamed `assert.isNotUndefined()` to `assert.isDefined()`
+  * Fixed `assert.includes()` param ordering
+
+0.6.0 / 2010-07-31
+==================
+
+  * Added _docs/api.html_
+  * Added -w, --watch
+  * Added `Array` support to `assert.includes()`
+  * Added; outputting exceptions immediately. Closes #19
+  * Fixed `assert.includes()` param ordering
+  * Fixed `assert.length()` param ordering
+  * Fixed jscoverage links
+
+0.5.0 / 2010-07-16
+==================
+
+  * Added support for async exports
+  * Added timeout support to `assert.response()`. Closes #3
+  * Added 4th arg callback support to `assert.response()`
+  * Added `assert.length()`
+  * Added `assert.match()`
+  * Added `assert.isUndefined()`
+  * Added `assert.isNull()`
+  * Added `assert.includes()`
+  * Added growlnotify support via -g, --growl
+  * Added -o, --only TESTS. Ex: --only "test foo()" --only "test foo(), test bar()"
+  * Removed profanity
+
+0.4.0 / 2010-07-09
+==================
+
+  * Added reporting source coverage (respects --boring for color haters)
+  * Added callback to assert.response(). Closes #12
+  * Fixed; putting exceptions to stderr. Closes #13
+
+0.3.1 / 2010-06-28
+==================
+
+  * Faster assert.response()
+
+0.3.0 / 2010-06-28
+==================
+
+  * Added -p, --port NUM flags
+  * Added assert.response(). Closes #11
+
+0.2.1 / 2010-06-25
+==================
+
+  * Fixed issue with reporting object assertions
+
+0.2.0 / 2010-06-21
+==================
+
+  * Added `make uninstall`
+  * Added better readdir() failure message
+  * Fixed `make install` for kiwi
+
+0.1.0 / 2010-06-15
+==================
+
+  * Added better usage docs via --help
+  * Added better conditional color support
+  * Added pre exit assertion support
+
+0.0.3 / 2010-06-02
+==================
+
+  * Added more room for filenames in test coverage
+  * Added boring output support via --boring (suppress colored output)
+  * Fixed async failure exit status
+
+0.0.2 / 2010-05-30
+==================
+
+  * Fixed exit status for CI support
+
+0.0.1 / 2010-05-30
+==================
+
+  * Initial release
\ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/support/expresso/Makefile b/node_modules/express/node_modules/qs/support/expresso/Makefile
new file mode 100644 (file)
index 0000000..8acfe56
--- /dev/null
@@ -0,0 +1,53 @@
+
+PREFIX ?= /usr/local
+BIN = bin/expresso
+JSCOV = deps/jscoverage/node-jscoverage
+DOCS = docs/index.md
+HTMLDOCS = $(DOCS:.md=.html)
+
+test: $(BIN)
+       @./$(BIN) -I lib --growl $(TEST_FLAGS) test/*.test.js
+
+test-cov:
+       @./$(BIN) -I lib --cov $(TEST_FLAGS) test/*.test.js
+
+test-serial:
+       @./$(BIN) --serial -I lib $(TEST_FLAGS) test/serial/*.test.js
+
+install: install-jscov install-expresso
+
+uninstall:
+       rm -f $(PREFIX)/bin/expresso
+       rm -f $(PREFIX)/bin/node-jscoverage
+
+install-jscov: $(JSCOV)
+       install $(JSCOV) $(PREFIX)/bin
+
+install-expresso:
+       install $(BIN) $(PREFIX)/bin
+
+$(JSCOV):
+       cd deps/jscoverage && ./configure && make && mv jscoverage node-jscoverage
+
+clean:
+       @cd deps/jscoverage && git clean -fd
+
+docs: docs/api.html $(HTMLDOCS)
+
+%.html: %.md
+       @echo "... $< > $@"
+       @ronn -5 --pipe --fragment $< \
+               | cat docs/layout/head.html - docs/layout/foot.html \
+               > $@
+
+docs/api.html: bin/expresso
+       dox \
+               --title "Expresso" \
+               --ribbon "http://github.com/visionmedia/expresso" \
+               --desc "Insanely fast TDD framework for [node](http://nodejs.org) featuring code coverage reporting." \
+               $< > $@
+
+docclean:
+       rm -f docs/*.html
+
+.PHONY: test test-cov install uninstall install-expresso install-jscov clean docs docclean
\ No newline at end of file
diff --git a/node_modules/express/node_modules/qs/support/expresso/Readme.md b/node_modules/express/node_modules/qs/support/expresso/Readme.md
new file mode 100644 (file)
index 0000000..05c972e
--- /dev/null
@@ -0,0 +1,61 @@
+
+# Expresso
+
+  TDD framework for [nodejs](http://nodejs.org).
+  
+## Features
+
+  - light-weight
+  - intuitive async support
+  - intuitive test runner executable
+  - test coverage support and reporting
+  - uses the _assert_ module
+  - `assert.eql()` alias of `assert.deepEqual()`
+  - `assert.response()` http response utility
+  - `assert.includes()`
+  - `assert.type()`
+  - `assert.isNull()`
+  - `assert.isUndefined()`
+  - `assert.isNotNull()`
+  - `assert.isDefined()`
+  - `assert.match()`
+  - `assert.length()`
+
+## Installation
+
+To install both expresso _and_ node-jscoverage run:
+
+    $ make install
+
+To install expresso alone (no build required) run:
+
+    $ make install-expresso
+
+Install via npm:
+
+       $ npm install expresso
+
+## 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.
diff --git a/node_modules/express/node_modules/qs/support/expresso/bin/expresso b/node_modules/express/node_modules/qs/support/expresso/bin/expresso
new file mode 100755 (executable)
index 0000000..ec1edc8
--- /dev/null
@@ -0,0 +1,856 @@
+#!/usr/bin/env node
+
+/*
+ * Expresso
+ * Copyright(c) TJ Holowaychuk <tj@vision-media.ca>
+ * (MIT Licensed)
+ */
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert'),
+    childProcess = require('child_process'),
+    http = require('http'),
+    path = require('path'),
+    sys = require('sys'),
+    cwd = process.cwd(),
+    fs = require('fs'),
+    defer;
+
+/**
+ * Expresso version.
+ */
+
+var version = '0.7.2';
+
+/**
+ * Failure count.
+ */
+
+var failures = 0;
+
+
+/**
+ * Number of tests executed.
+ */
+
+var testcount = 0;
+
+/**
+ * Whitelist of tests to run.
+ */
+var only = [];
+
+/**
+ * Boring output.
+ */
+var boring = false;
+
+/**
+ * Growl notifications.
+ */
+
+var growl = false;
+
+/**
+ * Server port.
+ */
+
+var port = 5555;
+
+/**
+ * Execute serially.
+ */
+
+var serial = false;
+
+/**
+ * Default timeout.
+ */
+
+var timeout = 2000;
+
+/**
+ * Quiet output.
+ */
+
+var quiet = false;
+
+/**
+ * Usage documentation.
+ */
+
+var usage = ''
+    + '[bold]{Usage}: expresso [options] <file ...>'
+    + '\n'
+    + '\n[bold]{Options}:'
+    + '\n  -g, --growl          Enable growl notifications'
+    + '\n  -c, --coverage       Generate and report test coverage'
+    + '\n  -q, --quiet          Suppress coverage report if 100%'
+    + '\n  -t, --timeout MS     Timeout in milliseconds, defaults to 2000'
+    + '\n  -r, --require PATH   Require the given module path'
+    + '\n  -o, --only TESTS     Execute only the comma sperated TESTS (can be set several times)'
+    + '\n  -I, --include PATH   Unshift the given path to require.paths'
+    + '\n  -p, --port NUM       Port number for test servers, starts at 5555'
+    + '\n  -s, --serial         Execute tests serially'
+    + '\n  -b, --boring         Suppress ansi-escape colors'
+    + '\n  -v, --version        Output version number'
+    + '\n  -h, --help           Display help information'
+    + '\n';
+
+// Parse arguments
+
+var files = [],
+    args = process.argv.slice(2);
+
+while (args.length) {
+    var arg = args.shift();
+    switch (arg) {
+        case '-h':
+        case '--help':
+            print(usage + '\n');
+            process.exit(1);
+            break;
+        case '-v':
+        case '--version':
+            sys.puts(version);
+            process.exit(1);
+            break;
+        case '-i':
+        case '-I':
+        case '--include':
+            if (arg = args.shift()) {
+                require.paths.unshift(arg);
+            } else {
+                throw new Error('--include requires a path');
+            }
+            break;
+        case '-o':
+        case '--only':
+            if (arg = args.shift()) {
+                only = only.concat(arg.split(/ *, */));
+            } else {
+                throw new Error('--only requires comma-separated test names');
+            }
+            break;
+        case '-p':
+        case '--port':
+            if (arg = args.shift()) {
+                port = parseInt(arg, 10);
+            } else {
+                throw new Error('--port requires a number');
+            }
+            break;
+        case '-r':
+        case '--require':
+            if (arg = args.shift()) {
+                require(arg);
+            } else {
+                throw new Error('--require requires a path');
+            }
+            break;
+        case '-t':
+        case '--timeout':
+          if (arg = args.shift()) {
+            timeout = parseInt(arg, 10);
+          } else {
+            throw new Error('--timeout requires an argument');
+          }
+          break;
+        case '-c':
+        case '--cov':
+        case '--coverage':
+            defer = true;
+            childProcess.exec('rm -fr lib-cov && node-jscoverage lib lib-cov', function(err){
+                if (err) throw err;
+                require.paths.unshift('lib-cov');
+                run(files);
+            })
+            break;
+        case '-q':
+        case '--quiet':
+            quiet = true;
+            break;
+        case '-b':
+        case '--boring':
+               boring = true;
+               break;
+        case '-g':
+        case '--growl':
+            growl = true;
+            break;
+        case '-s':
+        case '--serial':
+            serial = true;
+            break;
+        default:
+            if (/\.js$/.test(arg)) {
+                files.push(arg);
+            }
+            break;
+    }
+}
+
+/**
+ * Colorized sys.error().
+ *
+ * @param {String} str
+ */
+
+function print(str){
+    sys.error(colorize(str));
+}
+
+/**
+ * Colorize the given string using ansi-escape sequences.
+ * Disabled when --boring is set.
+ *
+ * @param {String} str
+ * @return {String}
+ */
+
+function colorize(str){
+    var colors = { bold: 1, red: 31, green: 32, yellow: 33 };
+    return str.replace(/\[(\w+)\]\{([^]*?)\}/g, function(_, color, str){
+        return boring
+            ? str
+            : '\x1B[' + colors[color] + 'm' + str + '\x1B[0m';
+    });
+}
+
+// Alias deepEqual as eql for complex equality
+
+assert.eql = assert.deepEqual;
+
+/**
+ * Assert that `val` is null.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isNull = function(val, msg) {
+    assert.strictEqual(null, val, msg);
+};
+
+/**
+ * Assert that `val` is not null.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isNotNull = function(val, msg) {
+    assert.notStrictEqual(null, val, msg);
+};
+
+/**
+ * Assert that `val` is undefined.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isUndefined = function(val, msg) {
+    assert.strictEqual(undefined, val, msg);
+};
+
+/**
+ * Assert that `val` is not undefined.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isDefined = function(val, msg) {
+    assert.notStrictEqual(undefined, val, msg);
+};
+
+/**
+ * Assert that `obj` is `type`.
+ *
+ * @param {Mixed} obj
+ * @param {String} type
+ * @api public
+ */
+
+assert.type = function(obj, type, msg){
+    var real = typeof obj;
+    msg = msg || 'typeof ' + sys.inspect(obj) + ' is ' + real + ', expected ' + type;
+    assert.ok(type === real, msg);
+};
+
+/**
+ * Assert that `str` matches `regexp`.
+ *
+ * @param {String} str
+ * @param {RegExp} regexp
+ * @param {String} msg
+ */
+
+assert.match = function(str, regexp, msg) {
+    msg = msg || sys.inspect(str) + ' does not match ' + sys.inspect(regexp);
+    assert.ok(regexp.test(str), msg);
+};
+
+/**
+ * Assert that `val` is within `obj`.
+ *
+ * Examples:
+ *
+ *    assert.includes('foobar', 'bar');
+ *    assert.includes(['foo', 'bar'], 'foo');
+ *
+ * @param {String|Array} obj
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.includes = function(obj, val, msg) {
+    msg = msg || sys.inspect(obj) + ' does not include ' + sys.inspect(val);
+    assert.ok(obj.indexOf(val) >= 0, msg);
+};
+
+/**
+ * Assert length of `val` is `n`.
+ *
+ * @param {Mixed} val
+ * @param {Number} n
+ * @param {String} msg
+ */
+
+assert.length = function(val, n, msg) {
+    msg = msg || sys.inspect(val) + ' has length of ' + val.length + ', expected ' + n;
+    assert.equal(n, val.length, msg);
+};
+
+/**
+ * Assert response from `server` with
+ * the given `req` object and `res` assertions object.
+ *
+ * @param {Server} server
+ * @param {Object} req
+ * @param {Object|Function} res
+ * @param {String} msg
+ */
+
+assert.response = function(server, req, res, msg){
+    // Check that the server is ready or defer
+    if (!server.fd) {
+        if (!('__deferred' in server)) {
+            server.__deferred = [];
+        }
+        server.__deferred.push(arguments);
+        if (!server.__started) {
+            server.listen(server.__port = port++, '127.0.0.1', function(){
+                if (server.__deferred) {
+                    process.nextTick(function(){
+                        server.__deferred.forEach(function(args){
+                          assert.response.apply(assert, args);
+                        });
+                    });
+                }
+            });
+            server.__started = true;
+        }
+        return;
+    }
+
+    // Callback as third or fourth arg
+    var callback = typeof res === 'function'
+        ? res
+        : typeof msg === 'function'
+            ? msg
+            : function(){};
+
+    // Default messate to test title
+    if (typeof msg === 'function') msg = null;
+    msg = msg || assert.testTitle;
+    msg += '. ';
+
+    // Pending responses
+    server.__pending = server.__pending || 0;
+    server.__pending++;
+
+    // Create client
+    if (!server.fd) {
+        server.listen(server.__port = port++, '127.0.0.1', issue);
+    } else {
+        issue();
+    }
+
+    function issue(){
+        if (!server.client)
+            server.client = http.createClient(server.__port);
+
+        // Issue request
+        var timer,
+            client = server.client,
+            method = req.method || 'GET',
+            status = res.status || res.statusCode,
+            data = req.data || req.body,
+            requestTimeout = req.timeout || 0;
+
+        var request = client.request(method, req.url, req.headers);
+
+        // Timeout
+        if (requestTimeout) {
+            timer = setTimeout(function(){
+                --server.__pending || server.close();
+                delete req.timeout;
+                assert.fail(msg + 'Request timed out after ' + requestTimeout + 'ms.');
+            }, requestTimeout);
+        }
+
+        if (data) request.write(data);
+        request.on('response', function(response){
+            response.body = '';
+            response.setEncoding('utf8');
+            response.on('data', function(chunk){ response.body += chunk; });
+            response.on('end', function(){
+                --server.__pending || server.close();
+                if (timer) clearTimeout(timer);
+
+                // Assert response body
+                if (res.body !== undefined) {
+                    var eql = res.body instanceof RegExp
+                      ? res.body.test(response.body)
+                      : res.body === response.body;
+                    assert.ok(
+                        eql,
+                        msg + 'Invalid response body.\n'
+                            + '    Expected: ' + sys.inspect(res.body) + '\n'
+                            + '    Got: ' + sys.inspect(response.body)
+                    );
+                }
+
+                // Assert response status
+                if (typeof status === 'number') {
+                    assert.equal(
+                        response.statusCode,
+                        status,
+                        msg + colorize('Invalid response status code.\n'
+                            + '    Expected: [green]{' + status + '}\n'
+                            + '    Got: [red]{' + response.statusCode + '}')
+                    );
+                }
+
+                // Assert response headers
+                if (res.headers) {
+                    var keys = Object.keys(res.headers);
+                    for (var i = 0, len = keys.length; i < len; ++i) {
+                        var name = keys[i],
+                            actual = response.headers[name.toLowerCase()],
+                            expected = res.headers[name],
+                            eql = expected instanceof RegExp
+                              ? expected.test(actual)
+                              : expected == actual;
+                        assert.ok(
+                            eql,
+                            msg + colorize('Invalid response header [bold]{' + name + '}.\n'
+                                + '    Expected: [green]{' + expected + '}\n'
+                                + '    Got: [red]{' + actual + '}')
+                        );
+                    }
+                }
+
+                // Callback
+                callback(response);
+            });
+        });
+        request.end();
+      }
+};
+
+/**
+ * Pad the given string to the maximum width provided.
+ *
+ * @param  {String} str
+ * @param  {Number} width
+ * @return {String}
+ */
+
+function lpad(str, width) {
+    str = String(str);
+    var n = width - str.length;
+    if (n < 1) return str;
+    while (n--) str = ' ' + str;
+    return str;
+}
+
+/**
+ * Pad the given string to the maximum width provided.
+ *
+ * @param  {String} str
+ * @param  {Number} width
+ * @return {String}
+ */
+
+function rpad(str, width) {
+    str = String(str);
+    var n = width - str.length;
+    if (n < 1) return str;
+    while (n--) str = str + ' ';
+    return str;
+}
+
+/**
+ * Report test coverage.
+ *
+ * @param  {Object} cov
+ */
+
+function reportCoverage(cov) {
+    // Stats
+    print('\n   [bold]{Test Coverage}\n');
+    var sep = '   +------------------------------------------+----------+------+------+--------+',
+        lastSep = '                                              +----------+------+------+--------+';
+    sys.puts(sep);
+    sys.puts('   | filename                                 | coverage | LOC  | SLOC | missed |');
+    sys.puts(sep);
+    for (var name in cov) {
+        var file = cov[name];
+        if (Array.isArray(file)) {
+            sys.print('   | ' + rpad(name, 40));
+            sys.print(' | ' + lpad(file.coverage.toFixed(2), 8));
+            sys.print(' | ' + lpad(file.LOC, 4));
+            sys.print(' | ' + lpad(file.SLOC, 4));
+            sys.print(' | ' + lpad(file.totalMisses, 6));
+            sys.print(' |\n');
+        }
+    }
+    sys.puts(sep);
+    sys.print('     ' + rpad('', 40));
+    sys.print(' | ' + lpad(cov.coverage.toFixed(2), 8));
+    sys.print(' | ' + lpad(cov.LOC, 4));
+    sys.print(' | ' + lpad(cov.SLOC, 4));
+    sys.print(' | ' + lpad(cov.totalMisses, 6));
+    sys.print(' |\n');
+    sys.puts(lastSep