Index: Dev/trunk/src/node_modules/.bin/csv-reshuffle
===================================================================
--- Dev/trunk/src/node_modules/.bin/csv-reshuffle	(revision 484)
+++ Dev/trunk/src/node_modules/.bin/csv-reshuffle	(revision 484)
@@ -0,0 +1,1 @@
+link ../ya-csv/bin/reshuffle.js
Index: Dev/trunk/src/node_modules/.bin/express
===================================================================
--- Dev/trunk/src/node_modules/.bin/express	(revision 484)
+++ Dev/trunk/src/node_modules/.bin/express	(revision 484)
@@ -0,0 +1,1 @@
+link ../express/bin/express
Index: Dev/trunk/src/node_modules/express/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/.npmignore	(revision 484)
@@ -0,0 +1,9 @@
+.git*
+docs/
+examples/
+support/
+test/
+testing.js
+.DS_Store
+coverage.html
+lib-cov
Index: Dev/trunk/src/node_modules/express/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/express/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/express/.travis.yml	(revision 484)
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - "0.8"
+  - "0.10"
Index: Dev/trunk/src/node_modules/express/History.md
===================================================================
--- Dev/trunk/src/node_modules/express/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/History.md	(revision 484)
@@ -0,0 +1,1152 @@
+
+3.2.6 / 2013-06-02 
+==================
+
+ * update connect
+
+3.2.5 / 2013-05-21 
+==================
+
+ * update connect
+ * update node-cookie
+ * add: throw a meaningful error when there is no default engine
+ * change generation of ETags with res.send() to GET requests only. Closes #1619
+
+3.2.4 / 2013-05-09 
+==================
+  
+  * fix `req.subdomains` when no Host is present
+  * fix `req.host` when no Host is present, return undefined
+
+3.2.3 / 2013-05-07 
+==================
+
+  * update connect / qs
+
+3.2.2 / 2013-05-03 
+==================
+
+  * update qs
+
+3.2.1 / 2013-04-29 
+==================
+
+  * add app.VERB() paths array deprecation warning
+  * update connect
+  * update qs and remove all ~ semver crap
+  * fix: accept number as value of Signed Cookie
+
+3.2.0 / 2013-04-15 
+==================
+
+  * add "view" constructor setting to override view behaviour
+  * add req.acceptsEncoding(name)
+  * add req.acceptedEncodings
+  * revert cookie signature change causing session race conditions
+  * fix sorting of Accept values of the same quality  
+
+3.1.2 / 2013-04-12 
+==================
+
+  * add support for custom Accept parameters
+  * update cookie-signature
+
+3.1.1 / 2013-04-01 
+==================
+
+  * add X-Forwarded-Host support to `req.host`
+  * fix relative redirects  
+  * update mkdirp 
+  * update buffer-crc32
+  * remove legacy app.configure() method from app template.
+
+3.1.0 / 2013-01-25
+==================
+
+  * add support for leading "." in "view engine" setting
+  * add array support to `res.set()`
+  * add node 0.8.x to travis.yml
+  * add "subdomain offset" setting for tweaking `req.subdomains`
+  * add `res.location(url)` implementing `res.redirect()`-like setting of Location
+  * use app.get() for x-powered-by setting for inheritance
+  * fix colons in passwords for `req.auth`
+
+3.0.6 / 2013-01-04
+==================
+
+  * add http verb methods to Router
+  * update connect
+  * fix mangling of the `res.cookie()` options object
+  * fix jsonp whitespace escape. Closes #1132
+
+3.0.5 / 2012-12-19
+==================
+
+  * add throwing when a non-function is passed to a route
+  * fix: explicitly remove Transfer-Encoding header from 204 and 304 responses
+  * revert "add 'etag' option"
+
+3.0.4 / 2012-12-05
+==================
+
+  * add 'etag' option to disable `res.send()` Etags
+  * add escaping of urls in text/plain in `res.redirect()`
+    for old browsers interpreting as html
+  * change crc32 module for a more liberal license
+  * update connect
+
+3.0.3 / 2012-11-13
+==================
+
+  * update connect
+  * update cookie module
+  * fix cookie max-age
+
+3.0.2 / 2012-11-08
+==================
+
+  * add OPTIONS to cors example. Closes #1398
+  * fix route chaining regression. Closes #1397
+
+3.0.1 / 2012-11-01
+==================
+
+  * update connect
+
+3.0.0 / 2012-10-23
+==================
+
+  * add `make clean`
+  * add "Basic" check to req.auth
+  * add `req.auth` test coverage
+  * add cb && cb(payload) to `res.jsonp()`. Closes #1374
+  * add backwards compat for `res.redirect()` status. Closes #1336
+  * add support for `res.json()` to retain previously defined Content-Types. Closes #1349
+  * update connect
+  * change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382
+  * remove non-primitive string support for `res.send()`
+  * fix view-locals example. Closes #1370
+  * fix route-separation example
+
+3.0.0rc5 / 2012-09-18
+==================
+
+  * update connect
+  * add redis search example
+  * add static-files example
+  * add "x-powered-by" setting (`app.disable('x-powered-by')`)
+  * add "application/octet-stream" redirect Accept test case. Closes #1317
+
+3.0.0rc4 / 2012-08-30
+==================
+
+  * add `res.jsonp()`. Closes #1307
+  * add "verbose errors" option to error-pages example
+  * add another route example to express(1) so people are not so confused
+  * add redis online user activity tracking example
+  * update connect dep
+  * fix etag quoting. Closes #1310
+  * fix error-pages 404 status
+  * fix jsonp callback char restrictions
+  * remove old OPTIONS default response
+
+3.0.0rc3 / 2012-08-13
+==================
+
+  * update connect dep
+  * fix signed cookies to work with `connect.cookieParser()` ("s:" prefix was missing) [tnydwrds]
+  * fix `res.render()` clobbering of "locals"
+
+3.0.0rc2 / 2012-08-03
+==================
+
+  * add CORS example
+  * update connect dep
+  * deprecate `.createServer()` & remove old stale examples
+  * fix: escape `res.redirect()` link
+  * fix vhost example
+
+3.0.0rc1 / 2012-07-24
+==================
+
+  * add more examples to view-locals
+  * add scheme-relative redirects (`res.redirect("//foo.com")`) support
+  * update cookie dep
+  * update connect dep
+  * update send dep
+  * fix `express(1)` -h flag, use -H for hogan. Closes #1245
+  * fix `res.sendfile()` socket error handling regression
+
+3.0.0beta7 / 2012-07-16
+==================
+
+  * update connect dep for `send()` root normalization regression
+
+3.0.0beta6 / 2012-07-13
+==================
+
+  * add `err.view` property for view errors. Closes #1226
+  * add "jsonp callback name" setting
+  * add support for "/foo/:bar*" non-greedy matches
+  * change `res.sendfile()` to use `send()` module
+  * change `res.send` to use "response-send" module
+  * remove `app.locals.use` and `res.locals.use`, use regular middleware
+
+3.0.0beta5 / 2012-07-03
+==================
+
+  * add "make check" support
+  * add route-map example
+  * add `res.json(obj, status)` support back for BC
+  * add "methods" dep, remove internal methods module
+  * update connect dep
+  * update auth example to utilize cores pbkdf2
+  * updated tests to use "supertest"
+
+3.0.0beta4 / 2012-06-25
+==================
+
+  * Added `req.auth`
+  * Added `req.range(size)`
+  * Added `res.links(obj)`
+  * Added `res.send(body, status)` support back for backwards compat
+  * Added `.default()` support to `res.format()`
+  * Added 2xx / 304 check to `req.fresh`
+  * Revert "Added + support to the router"
+  * Fixed `res.send()` freshness check, respect res.statusCode
+
+3.0.0beta3 / 2012-06-15
+==================
+
+  * Added hogan `--hjs` to express(1) [nullfirm]
+  * Added another example to content-negotiation
+  * Added `fresh` dep
+  * Changed: `res.send()` always checks freshness
+  * Fixed: expose connects mime module. Cloases #1165
+
+3.0.0beta2 / 2012-06-06
+==================
+
+  * Added `+` support to the router
+  * Added `req.host`
+  * Changed `req.param()` to check route first
+  * Update connect dep
+
+3.0.0beta1 / 2012-06-01
+==================
+
+  * Added `res.format()` callback to override default 406 behaviour
+  * Fixed `res.redirect()` 406. Closes #1154
+
+3.0.0alpha5 / 2012-05-30
+==================
+
+  * Added `req.ip`
+  * Added `{ signed: true }` option to `res.cookie()`
+  * Removed `res.signedCookie()`
+  * Changed: dont reverse `req.ips`
+  * Fixed "trust proxy" setting check for `req.ips`
+
+3.0.0alpha4 / 2012-05-09
+==================
+
+  * Added: allow `[]` in jsonp callback. Closes #1128
+  * Added `PORT` env var support in generated template. Closes #1118 [benatkin]
+  * Updated: connect 2.2.2
+
+3.0.0alpha3 / 2012-05-04
+==================
+
+  * Added public `app.routes`. Closes #887
+  * Added _view-locals_ example
+  * Added _mvc_ example
+  * Added `res.locals.use()`. Closes #1120
+  * Added conditional-GET support to `res.send()`
+  * Added: coerce `res.set()` values to strings
+  * Changed: moved `static()` in generated apps below router
+  * Changed: `res.send()` only set ETag when not previously set
+  * Changed connect 2.2.1 dep
+  * Changed: `make test` now runs unit / acceptance tests
+  * Fixed req/res proto inheritance
+
+3.0.0alpha2 / 2012-04-26
+==================
+
+  * Added `make benchmark` back
+  * Added `res.send()` support for `String` objects
+  * Added client-side data exposing example
+  * Added `res.header()` and `req.header()` aliases for BC
+  * Added `express.createServer()` for BC
+  * Perf: memoize parsed urls
+  * Perf: connect 2.2.0 dep
+  * Changed: make `expressInit()` middleware self-aware
+  * Fixed: use app.get() for all core settings
+  * Fixed redis session example
+  * Fixed session example. Closes #1105
+  * Fixed generated express dep. Closes #1078
+
+3.0.0alpha1 / 2012-04-15
+==================
+
+  * Added `app.locals.use(callback)`
+  * Added `app.locals` object
+  * Added `app.locals(obj)`
+  * Added `res.locals` object
+  * Added `res.locals(obj)`
+  * Added `res.format()` for content-negotiation
+  * Added `app.engine()`
+  * Added `res.cookie()` JSON cookie support
+  * Added "trust proxy" setting
+  * Added `req.subdomains`
+  * Added `req.protocol`
+  * Added `req.secure`
+  * Added `req.path`
+  * Added `req.ips`
+  * Added `req.fresh`
+  * Added `req.stale`
+  * Added comma-delmited / array support for `req.accepts()`
+  * Added debug instrumentation
+  * Added `res.set(obj)`
+  * Added `res.set(field, value)`
+  * Added `res.get(field)`
+  * Added `app.get(setting)`. Closes #842
+  * Added `req.acceptsLanguage()`
+  * Added `req.acceptsCharset()`
+  * Added `req.accepted`
+  * Added `req.acceptedLanguages`
+  * Added `req.acceptedCharsets`
+  * Added "json replacer" setting
+  * Added "json spaces" setting
+  * Added X-Forwarded-Proto support to `res.redirect()`. Closes #92
+  * Added `--less` support to express(1)
+  * Added `express.response` prototype
+  * Added `express.request` prototype
+  * Added `express.application` prototype
+  * Added `app.path()`
+  * Added `app.render()`
+  * Added `res.type()` to replace `res.contentType()`
+  * Changed: `res.redirect()` to add relative support
+  * Changed: enable "jsonp callback" by default
+  * Changed: renamed "case sensitive routes" to "case sensitive routing"
+  * Rewrite of all tests with mocha
+  * Removed "root" setting
+  * Removed `res.redirect('home')` support
+  * Removed `req.notify()`
+  * Removed `app.register()`
+  * Removed `app.redirect()`
+  * Removed `app.is()`
+  * Removed `app.helpers()`
+  * Removed `app.dynamicHelpers()`
+  * Fixed `res.sendfile()` with non-GET. Closes #723
+  * Fixed express(1) public dir for windows. Closes #866
+
+2.5.9/ 2012-04-02
+==================
+
+  * Added support for PURGE request method [pbuyle]
+  * Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki]
+
+2.5.8 / 2012-02-08
+==================
+
+  * Update mkdirp dep. Closes #991
+
+2.5.7 / 2012-02-06
+==================
+
+  * Fixed `app.all` duplicate DELETE requests [mscdex]
+
+2.5.6 / 2012-01-13
+==================
+
+  * Updated hamljs dev dep. Closes #953
+
+2.5.5 / 2012-01-08
+==================
+
+  * Fixed: set `filename` on cached templates [matthewleon]
+
+2.5.4 / 2012-01-02
+==================
+
+  * Fixed `express(1)` eol on 0.4.x. Closes #947
+
+2.5.3 / 2011-12-30
+==================
+
+  * Fixed `req.is()` when a charset is present
+
+2.5.2 / 2011-12-10
+==================
+
+  * Fixed: express(1) LF -> CRLF for windows
+
+2.5.1 / 2011-11-17
+==================
+
+  * Changed: updated connect to 1.8.x
+  * Removed sass.js support from express(1)
+
+2.5.0 / 2011-10-24
+==================
+
+  * Added ./routes dir for generated app by default
+  * Added npm install reminder to express(1) app gen
+  * Added 0.5.x support
+  * Removed `make test-cov` since it wont work with node 0.5.x
+  * Fixed express(1) public dir for windows. Closes #866
+
+2.4.7 / 2011-10-05
+==================
+
+  * Added mkdirp to express(1). Closes #795
+  * Added simple _json-config_ example
+  * Added  shorthand for the parsed request's pathname via `req.path`
+  * Changed connect dep to 1.7.x to fix npm issue...
+  * Fixed `res.redirect()` __HEAD__ support. [reported by xerox]
+  * Fixed `req.flash()`, only escape args
+  * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie]
+
+2.4.6 / 2011-08-22
+==================
+
+  * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode]
+
+2.4.5 / 2011-08-19
+==================
+
+  * Added support for routes to handle errors. Closes #809
+  * Added `app.routes.all()`. Closes #803
+  * Added "basepath" setting to work in conjunction with reverse proxies etc.
+  * Refactored `Route` to use a single array of callbacks
+  * Added support for multiple callbacks for `app.param()`. Closes #801
+Closes #805
+  * Changed: removed .call(self) for route callbacks
+  * Dependency: `qs >= 0.3.1`
+  * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808
+
+2.4.4 / 2011-08-05
+==================
+
+  * Fixed `res.header()` intention of a set, even when `undefined`
+  * Fixed `*`, value no longer required
+  * Fixed `res.send(204)` support. Closes #771
+
+2.4.3 / 2011-07-14
+==================
+
+  * Added docs for `status` option special-case. Closes #739
+  * Fixed `options.filename`, exposing the view path to template engines
+
+2.4.2. / 2011-07-06
+==================
+
+  * Revert "removed jsonp stripping" for XSS
+
+2.4.1 / 2011-07-06
+==================
+
+  * Added `res.json()` JSONP support. Closes #737
+  * Added _extending-templates_ example. Closes #730
+  * Added "strict routing" setting for trailing slashes
+  * Added support for multiple envs in `app.configure()` calls. Closes #735
+  * Changed: `res.send()` using `res.json()`
+  * Changed: when cookie `path === null` don't default it
+  * Changed; default cookie path to "home" setting. Closes #731
+  * Removed _pids/logs_ creation from express(1)
+
+2.4.0 / 2011-06-28
+==================
+
+  * Added chainable `res.status(code)`
+  * Added `res.json()`, an explicit version of `res.send(obj)`
+  * Added simple web-service example
+
+2.3.12 / 2011-06-22
+==================
+
+  * \#express is now on freenode! come join!
+  * Added `req.get(field, param)`
+  * Added links to Japanese documentation, thanks @hideyukisaito!
+  * Added; the `express(1)` generated app outputs the env
+  * Added `content-negotiation` example
+  * Dependency: connect >= 1.5.1 < 2.0.0
+  * Fixed view layout bug. Closes #720
+  * Fixed; ignore body on 304. Closes #701
+
+2.3.11 / 2011-06-04
+==================
+
+  * Added `npm test`
+  * Removed generation of dummy test file from `express(1)`
+  * Fixed; `express(1)` adds express as a dep
+  * Fixed; prune on `prepublish`
+
+2.3.10 / 2011-05-27
+==================
+
+  * Added `req.route`, exposing the current route
+  * Added _package.json_ generation support to `express(1)`
+  * Fixed call to `app.param()` function for optional params. Closes #682
+
+2.3.9 / 2011-05-25
+==================
+
+  * Fixed bug-ish with `../' in `res.partial()` calls
+
+2.3.8 / 2011-05-24
+==================
+
+  * Fixed `app.options()`
+
+2.3.7 / 2011-05-23
+==================
+
+  * Added route `Collection`, ex: `app.get('/user/:id').remove();`
+  * Added support for `app.param(fn)` to define param logic
+  * Removed `app.param()` support for callback with return value
+  * Removed module.parent check from express(1) generated app. Closes #670
+  * Refactored router. Closes #639
+
+2.3.6 / 2011-05-20
+==================
+
+  * Changed; using devDependencies instead of git submodules
+  * Fixed redis session example
+  * Fixed markdown example
+  * Fixed view caching, should not be enabled in development
+
+2.3.5 / 2011-05-20
+==================
+
+  * Added export `.view` as alias for `.View`
+
+2.3.4 / 2011-05-08
+==================
+
+  * Added `./examples/say`
+  * Fixed `res.sendfile()` bug preventing the transfer of files with spaces
+
+2.3.3 / 2011-05-03
+==================
+
+  * Added "case sensitive routes" option.
+  * Changed; split methods supported per rfc [slaskis]
+  * Fixed route-specific middleware when using the same callback function several times
+
+2.3.2 / 2011-04-27
+==================
+
+  * Fixed view hints
+
+2.3.1 / 2011-04-26
+==================
+
+  * Added `app.match()` as `app.match.all()`
+  * Added `app.lookup()` as `app.lookup.all()`
+  * Added `app.remove()` for `app.remove.all()`
+  * Added `app.remove.VERB()`
+  * Fixed template caching collision issue. Closes #644
+  * Moved router over from connect and started refactor
+
+2.3.0 / 2011-04-25
+==================
+
+  * Added options support to `res.clearCookie()`
+  * Added `res.helpers()` as alias of `res.locals()`
+  * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel   * Dependency `connect >= 1.4.0`
+  * Changed; auto set Content-Type in res.attachement [Aaron Heckmann]
+  * Renamed "cache views" to "view cache". Closes #628
+  * Fixed caching of views when using several apps. Closes #637
+  * Fixed gotcha invoking `app.param()` callbacks once per route middleware.
+Closes #638
+  * Fixed partial lookup precedence. Closes #631
+Shaw]
+
+2.2.2 / 2011-04-12
+==================
+
+  * Added second callback support for `res.download()` connection errors
+  * Fixed `filename` option passing to template engine
+
+2.2.1 / 2011-04-04
+==================
+
+  * Added `layout(path)` helper to change the layout within a view. Closes #610
+  * Fixed `partial()` collection object support.
+    Previously only anything with `.length` would work.
+    When `.length` is present one must still be aware of holes,
+    however now `{ collection: {foo: 'bar'}}` is valid, exposes
+    `keyInCollection` and `keysInCollection`.
+
+  * Performance improved with better view caching
+  * Removed `request` and `response` locals
+  * Changed; errorHandler page title is now `Express` instead of `Connect`
+
+2.2.0 / 2011-03-30
+==================
+
+  * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606
+  * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606
+  * Added `app.VERB(path)` as alias of `app.lookup.VERB()`.
+  * Dependency `connect >= 1.2.0`
+
+2.1.1 / 2011-03-29
+==================
+
+  * Added; expose `err.view` object when failing to locate a view
+  * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann]
+  * Fixed; `res.send(undefined)` responds with 204 [aheckmann]
+
+2.1.0 / 2011-03-24
+==================
+
+  * Added `<root>/_?<name>` partial lookup support. Closes #447
+  * Added `request`, `response`, and `app` local variables
+  * Added `settings` local variable, containing the app's settings
+  * Added `req.flash()` exception if `req.session` is not available
+  * Added `res.send(bool)` support (json response)
+  * Fixed stylus example for latest version
+  * Fixed; wrap try/catch around `res.render()`
+
+2.0.0 / 2011-03-17
+==================
+
+  * Fixed up index view path alternative.
+  * Changed; `res.locals()` without object returns the locals
+
+2.0.0rc3 / 2011-03-17
+==================
+
+  * Added `res.locals(obj)` to compliment `res.local(key, val)`
+  * Added `res.partial()` callback support
+  * Fixed recursive error reporting issue in `res.render()`
+
+2.0.0rc2 / 2011-03-17
+==================
+
+  * Changed; `partial()` "locals" are now optional
+  * Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01]
+  * Fixed .filename view engine option [reported by drudge]
+  * Fixed blog example
+  * Fixed `{req,res}.app` reference when mounting [Ben Weaver]
+
+2.0.0rc / 2011-03-14
+==================
+
+  * Fixed; expose `HTTPSServer` constructor
+  * Fixed express(1) default test charset. Closes #579 [reported by secoif]
+  * Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP]
+
+2.0.0beta3 / 2011-03-09
+==================
+
+  * Added support for `res.contentType()` literal
+    The original `res.contentType('.json')`,
+    `res.contentType('application/json')`, and `res.contentType('json')`
+    will work now.
+  * Added `res.render()` status option support back
+  * Added charset option for `res.render()`
+  * Added `.charset` support (via connect 1.0.4)
+  * Added view resolution hints when in development and a lookup fails
+  * Added layout lookup support relative to the page view.
+    For example while rendering `./views/user/index.jade` if you create
+    `./views/user/layout.jade` it will be used in favour of the root layout.
+  * Fixed `res.redirect()`. RFC states absolute url [reported by unlink]
+  * Fixed; default `res.send()` string charset to utf8
+  * Removed `Partial` constructor (not currently used)
+
+2.0.0beta2 / 2011-03-07
+==================
+
+  * Added res.render() `.locals` support back to aid in migration process
+  * Fixed flash example
+
+2.0.0beta / 2011-03-03
+==================
+
+  * Added HTTPS support
+  * Added `res.cookie()` maxAge support
+  * Added `req.header()` _Referrer_ / _Referer_ special-case, either works
+  * Added mount support for `res.redirect()`, now respects the mount-point
+  * Added `union()` util, taking place of `merge(clone())` combo
+  * Added stylus support to express(1) generated app
+  * Added secret to session middleware used in examples and generated app
+  * Added `res.local(name, val)` for progressive view locals
+  * Added default param support to `req.param(name, default)`
+  * Added `app.disabled()` and `app.enabled()`
+  * Added `app.register()` support for omitting leading ".", either works
+  * Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539
+  * Added `app.param()` to map route params to async/sync logic
+  * Added; aliased `app.helpers()` as `app.locals()`. Closes #481
+  * Added extname with no leading "." support to `res.contentType()`
+  * Added `cache views` setting, defaulting to enabled in "production" env
+  * Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_.
+  * Added `req.accepts()` support for extensions
+  * Changed; `res.download()` and `res.sendfile()` now utilize Connect's
+    static file server `connect.static.send()`.
+  * Changed; replaced `connect.utils.mime()` with npm _mime_ module
+  * Changed; allow `req.query` to be pre-defined (via middleware or other parent
+  * Changed view partial resolution, now relative to parent view
+  * Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`.
+  * Fixed `req.param()` bug returning Array.prototype methods. Closes #552
+  * Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()`
+  * Fixed; using _qs_ module instead of _querystring_
+  * Fixed; strip unsafe chars from jsonp callbacks
+  * Removed "stream threshold" setting
+
+1.0.8 / 2011-03-01
+==================
+
+  * Allow `req.query` to be pre-defined (via middleware or other parent app)
+  * "connect": ">= 0.5.0 < 1.0.0". Closes #547
+  * Removed the long deprecated __EXPRESS_ENV__ support
+
+1.0.7 / 2011-02-07
+==================
+
+  * Fixed `render()` setting inheritance.
+    Mounted apps would not inherit "view engine"
+
+1.0.6 / 2011-02-07
+==================
+
+  * Fixed `view engine` setting bug when period is in dirname
+
+1.0.5 / 2011-02-05
+==================
+
+  * Added secret to generated app `session()` call
+
+1.0.4 / 2011-02-05
+==================
+
+  * Added `qs` dependency to _package.json_
+  * Fixed namespaced `require()`s for latest connect support
+
+1.0.3 / 2011-01-13
+==================
+
+  * Remove unsafe characters from JSONP callback names [Ryan Grove]
+
+1.0.2 / 2011-01-10
+==================
+
+  * Removed nested require, using `connect.router`
+
+1.0.1 / 2010-12-29
+==================
+
+  * Fixed for middleware stacked via `createServer()`
+    previously the `foo` middleware passed to `createServer(foo)`
+    would not have access to Express methods such as `res.send()`
+    or props like `req.query` etc.
+
+1.0.0 / 2010-11-16
+==================
+
+  * Added; deduce partial object names from the last segment.
+    For example by default `partial('forum/post', postObject)` will
+    give you the _post_ object, providing a meaningful default.
+  * Added http status code string representation to `res.redirect()` body
+  * Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__.
+  * Added `req.is()` to aid in content negotiation
+  * Added partial local inheritance [suggested by masylum]. Closes #102
+    providing access to parent template locals.
+  * Added _-s, --session[s]_ flag to express(1) to add session related middleware
+  * Added _--template_ flag to express(1) to specify the
+    template engine to use.
+  * Added _--css_ flag to express(1) to specify the
+    stylesheet engine to use (or just plain css by default).
+  * Added `app.all()` support [thanks aheckmann]
+  * Added partial direct object support.
+    You may now `partial('user', user)` providing the "user" local,
+    vs previously `partial('user', { object: user })`.
+  * Added _route-separation_ example since many people question ways
+    to do this with CommonJS modules. Also view the _blog_ example for
+    an alternative.
+  * Performance; caching view path derived partial object names
+  * Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454
+  * Fixed jsonp support; _text/javascript_ as per mailinglist discussion
+
+1.0.0rc4 / 2010-10-14
+==================
+
+  * Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0
+  * Added route-middleware support (very helpful, see the [docs](http://expressjs.com/guide.html#Route-Middleware))
+  * Added _jsonp callback_ setting to enable/disable jsonp autowrapping [Dav Glass]
+  * Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass]
+  * Added `partial()` support for array-like collections. Closes #434
+  * Added support for swappable querystring parsers
+  * Added session usage docs. Closes #443
+  * Added dynamic helper caching. Closes #439 [suggested by maritz]
+  * Added authentication example
+  * Added basic Range support to `res.sendfile()` (and `res.download()` etc)
+  * Changed; `express(1)` generated app using 2 spaces instead of 4
+  * Default env to "development" again [aheckmann]
+  * Removed _context_ option is no more, use "scope"
+  * Fixed; exposing _./support_ libs to examples so they can run without installs
+  * Fixed mvc example
+
+1.0.0rc3 / 2010-09-20
+==================
+
+  * Added confirmation for `express(1)` app generation. Closes #391
+  * Added extending of flash formatters via `app.flashFormatters`
+  * Added flash formatter support. Closes #411
+  * Added streaming support to `res.sendfile()` using `sys.pump()` when >= "stream threshold"
+  * Added _stream threshold_ setting for `res.sendfile()`
+  * Added `res.send()` __HEAD__ support
+  * Added `res.clearCookie()`
+  * Added `res.cookie()`
+  * Added `res.render()` headers option
+  * Added `res.redirect()` response bodies
+  * Added `res.render()` status option support. Closes #425 [thanks aheckmann]
+  * Fixed `res.sendfile()` responding with 403 on malicious path
+  * Fixed `res.download()` bug; when an error occurs remove _Content-Disposition_
+  * Fixed; mounted apps settings now inherit from parent app [aheckmann]
+  * Fixed; stripping Content-Length / Content-Type when 204
+  * Fixed `res.send()` 204. Closes #419
+  * Fixed multiple _Set-Cookie_ headers via `res.header()`. Closes #402
+  * Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo]
+
+
+1.0.0rc2 / 2010-08-17
+==================
+
+  * Added `app.register()` for template engine mapping. Closes #390
+  * Added `res.render()` callback support as second argument (no options)
+  * Added callback support to `res.download()`
+  * Added callback support for `res.sendfile()`
+  * Added support for middleware access via `express.middlewareName()` vs `connect.middlewareName()`
+  * Added "partials" setting to docs
+  * Added default expresso tests to `express(1)` generated app. Closes #384
+  * Fixed `res.sendfile()` error handling, defer via `next()`
+  * Fixed `res.render()` callback when a layout is used [thanks guillermo]
+  * Fixed; `make install` creating ~/.node_libraries when not present
+  * Fixed issue preventing error handlers from being defined anywhere. Closes #387
+
+1.0.0rc / 2010-07-28
+==================
+
+  * Added mounted hook. Closes #369
+  * Added connect dependency to _package.json_
+
+  * Removed "reload views" setting and support code
+    development env never caches, production always caches.
+
+  * Removed _param_ in route callbacks, signature is now
+    simply (req, res, next), previously (req, res, params, next).
+    Use _req.params_ for path captures, _req.query_ for GET params.
+
+  * Fixed "home" setting
+  * Fixed middleware/router precedence issue. Closes #366
+  * Fixed; _configure()_ callbacks called immediately. Closes #368
+
+1.0.0beta2 / 2010-07-23
+==================
+
+  * Added more examples
+  * Added; exporting `Server` constructor
+  * Added `Server#helpers()` for view locals
+  * Added `Server#dynamicHelpers()` for dynamic view locals. Closes #349
+  * Added support for absolute view paths
+  * Added; _home_ setting defaults to `Server#route` for mounted apps. Closes #363
+  * Added Guillermo Rauch to the contributor list
+  * Added support for "as" for non-collection partials. Closes #341
+  * Fixed _install.sh_, ensuring _~/.node_libraries_ exists. Closes #362 [thanks jf]
+  * Fixed `res.render()` exceptions, now passed to `next()` when no callback is given [thanks guillermo]
+  * Fixed instanceof `Array` checks, now `Array.isArray()`
+  * Fixed express(1) expansion of public dirs. Closes #348
+  * Fixed middleware precedence. Closes #345
+  * Fixed view watcher, now async [thanks aheckmann]
+
+1.0.0beta / 2010-07-15
+==================
+
+  * Re-write
+    - much faster
+    - much lighter
+    - Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs
+
+0.14.0 / 2010-06-15
+==================
+
+  * Utilize relative requires
+  * Added Static bufferSize option [aheckmann]
+  * Fixed caching of view and partial subdirectories [aheckmann]
+  * Fixed mime.type() comments now that ".ext" is not supported
+  * Updated haml submodule
+  * Updated class submodule
+  * Removed bin/express
+
+0.13.0 / 2010-06-01
+==================
+
+  * Added node v0.1.97 compatibility
+  * Added support for deleting cookies via Request#cookie('key', null)
+  * Updated haml submodule
+  * Fixed not-found page, now using using charset utf-8
+  * Fixed show-exceptions page, now using using charset utf-8
+  * Fixed view support due to fs.readFile Buffers
+  * Changed; mime.type() no longer accepts ".type" due to node extname() changes
+
+0.12.0 / 2010-05-22
+==================
+
+  * Added node v0.1.96 compatibility
+  * Added view `helpers` export which act as additional local variables
+  * Updated haml submodule
+  * Changed ETag; removed inode, modified time only
+  * Fixed LF to CRLF for setting multiple cookies
+  * Fixed cookie complation; values are now urlencoded
+  * Fixed cookies parsing; accepts quoted values and url escaped cookies
+
+0.11.0 / 2010-05-06
+==================
+
+  * Added support for layouts using different engines
+    - this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' })
+    - this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml'
+    - this.render('page.html.haml', { layout: false }) // no layout
+  * Updated ext submodule
+  * Updated haml submodule
+  * Fixed EJS partial support by passing along the context. Issue #307
+
+0.10.1 / 2010-05-03
+==================
+
+  * Fixed binary uploads.
+
+0.10.0 / 2010-04-30
+==================
+
+  * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s
+    encoding is set to 'utf8' or 'utf-8'.
+  * Added "encoding" option to Request#render(). Closes #299
+  * Added "dump exceptions" setting, which is enabled by default.
+  * Added simple ejs template engine support
+  * Added error reponse support for text/plain, application/json. Closes #297
+  * Added callback function param to Request#error()
+  * Added Request#sendHead()
+  * Added Request#stream()
+  * Added support for Request#respond(304, null) for empty response bodies
+  * Added ETag support to Request#sendfile()
+  * Added options to Request#sendfile(), passed to fs.createReadStream()
+  * Added filename arg to Request#download()
+  * Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request
+  * Performance enhanced by preventing several calls to toLowerCase() in Router#match()
+  * Changed; Request#sendfile() now streams
+  * Changed; Renamed Request#halt() to Request#respond(). Closes #289
+  * Changed; Using sys.inspect() instead of JSON.encode() for error output
+  * Changed; run() returns the http.Server instance. Closes #298
+  * Changed; Defaulting Server#host to null (INADDR_ANY)
+  * Changed; Logger "common" format scale of 0.4f
+  * Removed Logger "request" format
+  * Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found
+  * Fixed several issues with http client
+  * Fixed Logger Content-Length output
+  * Fixed bug preventing Opera from retaining the generated session id. Closes #292
+
+0.9.0 / 2010-04-14
+==================
+
+  * Added DSL level error() route support
+  * Added DSL level notFound() route support
+  * Added Request#error()
+  * Added Request#notFound()
+  * Added Request#render() callback function. Closes #258
+  * Added "max upload size" setting
+  * Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254
+  * Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js
+  * Added callback function support to Request#halt() as 3rd/4th arg
+  * Added preprocessing of route param wildcards using param(). Closes #251
+  * Added view partial support (with collections etc)
+  * Fixed bug preventing falsey params (such as ?page=0). Closes #286
+  * Fixed setting of multiple cookies. Closes #199
+  * Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml)
+  * Changed; session cookie is now httpOnly
+  * Changed; Request is no longer global
+  * Changed; Event is no longer global
+  * Changed; "sys" module is no longer global
+  * Changed; moved Request#download to Static plugin where it belongs
+  * Changed; Request instance created before body parsing. Closes #262
+  * Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253
+  * Changed; Pre-caching view partials in memory when "cache view partials" is enabled
+  * Updated support to node --version 0.1.90
+  * Updated dependencies
+  * Removed set("session cookie") in favour of use(Session, { cookie: { ... }})
+  * Removed utils.mixin(); use Object#mergeDeep()
+
+0.8.0 / 2010-03-19
+==================
+
+  * Added coffeescript example app. Closes #242
+  * Changed; cache api now async friendly. Closes #240
+  * Removed deprecated 'express/static' support. Use 'express/plugins/static'
+
+0.7.6 / 2010-03-19
+==================
+
+  * Added Request#isXHR. Closes #229
+  * Added `make install` (for the executable)
+  * Added `express` executable for setting up simple app templates
+  * Added "GET /public/*" to Static plugin, defaulting to <root>/public
+  * Added Static plugin
+  * Fixed; Request#render() only calls cache.get() once
+  * Fixed; Namespacing View caches with "view:"
+  * Fixed; Namespacing Static caches with "static:"
+  * Fixed; Both example apps now use the Static plugin
+  * Fixed set("views"). Closes #239
+  * Fixed missing space for combined log format
+  * Deprecated Request#sendfile() and 'express/static'
+  * Removed Server#running
+
+0.7.5 / 2010-03-16
+==================
+
+  * Added Request#flash() support without args, now returns all flashes
+  * Updated ext submodule
+
+0.7.4 / 2010-03-16
+==================
+
+  * Fixed session reaper
+  * Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft)
+
+0.7.3 / 2010-03-16
+==================
+
+  * Added package.json
+  * Fixed requiring of haml / sass due to kiwi removal
+
+0.7.2 / 2010-03-16
+==================
+
+  * Fixed GIT submodules (HAH!)
+
+0.7.1 / 2010-03-16
+==================
+
+  * Changed; Express now using submodules again until a PM is adopted
+  * Changed; chat example using millisecond conversions from ext
+
+0.7.0 / 2010-03-15
+==================
+
+  * Added Request#pass() support (finds the next matching route, or the given path)
+  * Added Logger plugin (default "common" format replaces CommonLogger)
+  * Removed Profiler plugin
+  * Removed CommonLogger plugin
+
+0.6.0 / 2010-03-11
+==================
+
+  * Added seed.yml for kiwi package management support
+  * Added HTTP client query string support when method is GET. Closes #205
+
+  * Added support for arbitrary view engines.
+    For example "foo.engine.html" will now require('engine'),
+    the exports from this module are cached after the first require().
+
+  * Added async plugin support
+
+  * Removed usage of RESTful route funcs as http client
+    get() etc, use http.get() and friends
+
+  * Removed custom exceptions
+
+0.5.0 / 2010-03-10
+==================
+
+  * Added ext dependency (library of js extensions)
+  * Removed extname() / basename() utils. Use path module
+  * Removed toArray() util. Use arguments.values
+  * Removed escapeRegexp() util. Use RegExp.escape()
+  * Removed process.mixin() dependency. Use utils.mixin()
+  * Removed Collection
+  * Removed ElementCollection
+  * Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com)  ;)
+
+0.4.0 / 2010-02-11
+==================
+
+  * Added flash() example to sample upload app
+  * Added high level restful http client module (express/http)
+  * Changed; RESTful route functions double as HTTP clients. Closes #69
+  * Changed; throwing error when routes are added at runtime
+  * Changed; defaulting render() context to the current Request. Closes #197
+  * Updated haml submodule
+
+0.3.0 / 2010-02-11
+==================
+
+  * Updated haml / sass submodules. Closes #200
+  * Added flash message support. Closes #64
+  * Added accepts() now allows multiple args. fixes #117
+  * Added support for plugins to halt. Closes #189
+  * Added alternate layout support. Closes #119
+  * Removed Route#run(). Closes #188
+  * Fixed broken specs due to use(Cookie) missing
+
+0.2.1 / 2010-02-05
+==================
+
+  * Added "plot" format option for Profiler (for gnuplot processing)
+  * Added request number to Profiler plugin
+  * Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8
+  * Fixed issue with routes not firing when not files are present. Closes #184
+  * Fixed process.Promise -> events.Promise
+
+0.2.0 / 2010-02-03
+==================
+
+  * Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180
+  * Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174
+  * Added expiration support to cache api with reaper. Closes #133
+  * Added cache Store.Memory#reap()
+  * Added Cache; cache api now uses first class Cache instances
+  * Added abstract session Store. Closes #172
+  * Changed; cache Memory.Store#get() utilizing Collection
+  * Renamed MemoryStore -> Store.Memory
+  * Fixed use() of the same plugin several time will always use latest options. Closes #176
+
+0.1.0 / 2010-02-03
+==================
+
+  * Changed; Hooks (before / after) pass request as arg as well as evaluated in their context
+  * Updated node support to 0.1.27 Closes #169
+  * Updated dirname(__filename) -> __dirname
+  * Updated libxmljs support to v0.2.0
+  * Added session support with memory store / reaping
+  * Added quick uid() helper
+  * Added multi-part upload support
+  * Added Sass.js support / submodule
+  * Added production env caching view contents and static files
+  * Added static file caching. Closes #136
+  * Added cache plugin with memory stores
+  * Added support to StaticFile so that it works with non-textual files.
+  * Removed dirname() helper
+  * Removed several globals (now their modules must be required)
+
+0.0.2 / 2010-01-10
+==================
+
+  * Added view benchmarks; currently haml vs ejs
+  * Added Request#attachment() specs. Closes #116
+  * Added use of node's parseQuery() util. Closes #123
+  * Added `make init` for submodules
+  * Updated Haml
+  * Updated sample chat app to show messages on load
+  * Updated libxmljs parseString -> parseHtmlString
+  * Fixed `make init` to work with older versions of git
+  * Fixed specs can now run independant specs for those who cant build deps. Closes #127
+  * Fixed issues introduced by the node url module changes. Closes 126.
+  * Fixed two assertions failing due to Collection#keys() returning strings
+  * Fixed faulty Collection#toArray() spec due to keys() returning strings
+  * Fixed `make test` now builds libxmljs.node before testing
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
Index: Dev/trunk/src/node_modules/express/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/express/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/express/LICENSE	(revision 484)
@@ -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.
Index: Dev/trunk/src/node_modules/express/Makefile
===================================================================
--- Dev/trunk/src/node_modules/express/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/express/Makefile	(revision 484)
@@ -0,0 +1,33 @@
+
+MOCHA_OPTS= --check-leaks
+REPORTER = dot
+
+check: test
+
+test: test-unit test-acceptance
+
+test-unit:
+	@NODE_ENV=test ./node_modules/.bin/mocha \
+		--reporter $(REPORTER) \
+		$(MOCHA_OPTS)
+
+test-acceptance:
+	@NODE_ENV=test ./node_modules/.bin/mocha \
+		--reporter $(REPORTER) \
+		--bail \
+		test/acceptance/*.js
+
+test-cov: lib-cov
+	@EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html
+
+lib-cov:
+	@jscoverage lib lib-cov
+
+benchmark:
+	@./support/bench
+
+clean:
+	rm -f coverage.html
+	rm -fr lib-cov
+
+.PHONY: test test-unit test-acceptance benchmark clean
Index: Dev/trunk/src/node_modules/express/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/Readme.md	(revision 484)
@@ -0,0 +1,179 @@
+![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png)
+
+  Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express) [![Dependency Status](https://gemnasium.com/visionmedia/express.png)](https://gemnasium.com/visionmedia/express)
+
+```js
+var express = require('express');
+var app = express();
+
+app.get('/', function(req, res){
+  res.send('Hello World');
+});
+
+app.listen(3000);
+```
+
+## Installation
+
+    $ npm install -g express
+
+## Quick Start
+
+ The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:
+
+ Create the app:
+
+    $ npm install -g express
+    $ express /tmp/foo && cd /tmp/foo
+
+ Install dependencies:
+
+    $ npm install
+
+ Start the server:
+
+    $ node app
+
+## Features
+
+  * Built on [Connect](http://github.com/senchalabs/connect)
+  * Robust routing
+  * HTTP helpers (redirection, caching, etc)
+  * View system supporting 14+ template engines
+  * Content negotiation
+  * Focus on high performance
+  * Environment based configuration
+  * Executable for generating applications quickly
+  * High test coverage
+
+## Philosophy
+
+  The Express philosophy is to provide small, robust tooling for HTTP servers. Making
+  it a great solution for single page applications, web sites, hybrids, or public
+  HTTP APIs.
+
+  Built on Connect you can use _only_ what you need, and nothing more, applications
+  can be as big or as small as you like, even a single file. Express does
+  not force you to use any specific ORM or template engine. With support for over
+  14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js)
+  you can quickly craft your perfect framework.
+
+## More Information
+
+  * Join #express on freenode
+  * [Google Group](http://groups.google.com/group/express-js) for discussion
+  * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
+  * Visit the [Wiki](http://github.com/visionmedia/express/wiki)
+  * [Ð ÑÑÑÐºÐŸÑÐ·ÑÑÐœÐ°Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÑ](http://jsman.ru/express/)
+  * Run express examples [online](https://runnable.com/express)
+
+## Viewing Examples
+
+Clone the Express repo, then install the dev dependencies to install all the example / test suite deps:
+
+    $ git clone git://github.com/visionmedia/express.git --depth 1
+    $ cd express
+    $ npm install
+
+then run whichever tests you want:
+
+    $ node examples/content-negotiation
+
+## Running Tests
+
+To run the test suite first invoke the following command within the repo, installing the development dependencies:
+
+    $ npm install
+
+then run the tests:
+
+    $ make test
+
+## Contributors
+
+```
+project: express
+commits: 3559
+active : 468 days
+files  : 237
+authors:
+ 1891	Tj Holowaychuk          53.1%
+ 1285	visionmedia             36.1%
+  182	TJ Holowaychuk          5.1%
+   54	Aaron Heckmann          1.5%
+   34	csausdev                1.0%
+   26	ciaranj                 0.7%
+   21	Robert SkÃ¶ld            0.6%
+    6	Guillermo Rauch         0.2%
+    3	Dav Glass               0.1%
+    3	Nick Poulden            0.1%
+    2	Randy Merrill           0.1%
+    2	Benny Wong              0.1%
+    2	Hunter Loftis           0.1%
+    2	Jake Gordon             0.1%
+    2	Brian McKinney          0.1%
+    2	Roman Shtylman          0.1%
+    2	Ben Weaver              0.1%
+    2	Dave Hoover             0.1%
+    2	Eivind Fjeldstad        0.1%
+    2	Daniel Shaw             0.1%
+    1	Matt Colyer             0.0%
+    1	Pau Ramon               0.0%
+    1	Pero Pejovic            0.0%
+    1	Peter Rekdal Sunde      0.0%
+    1	Raynos                  0.0%
+    1	Teng Siong Ong          0.0%
+    1	Viktor Kelemen          0.0%
+    1	ctide                   0.0%
+    1	8bitDesigner            0.0%
+    1	isaacs                  0.0%
+    1	mgutz                   0.0%
+    1	pikeas                  0.0%
+    1	shuwatto                0.0%
+    1	tstrimple               0.0%
+    1	ewoudj                  0.0%
+    1	Adam Sanderson          0.0%
+    1	Andrii Kostenko         0.0%
+    1	Andy Hiew               0.0%
+    1	Arpad Borsos            0.0%
+    1	Ashwin Purohit          0.0%
+    1	Benjen                  0.0%
+    1	Darren Torpey           0.0%
+    1	Greg Ritter             0.0%
+    1	Gregory Ritter          0.0%
+    1	James Herdman           0.0%
+    1	Jim Snodgrass           0.0%
+    1	Joe McCann              0.0%
+    1	Jonathan Dumaine        0.0%
+    1	Jonathan Palardy        0.0%
+    1	Jonathan Zacsh          0.0%
+    1	Justin Lilly            0.0%
+    1	Ken Sato                0.0%
+    1	Maciej MaÅecki          0.0%
+    1	Masahiro Hayashi        0.0%
+```
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2009-2012 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.
Index: Dev/trunk/src/node_modules/express/bin/express
===================================================================
--- Dev/trunk/src/node_modules/express/bin/express	(revision 484)
+++ Dev/trunk/src/node_modules/express/bin/express	(revision 484)
@@ -0,0 +1,422 @@
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var exec = require('child_process').exec
+  , program = require('commander')
+  , mkdirp = require('mkdirp')
+  , pkg = require('../package.json')
+  , version = pkg.version
+  , os = require('os')
+  , fs = require('fs');
+
+// CLI
+
+program
+  .version(version)
+  .option('-s, --sessions', 'add session support')
+  .option('-e, --ejs', 'add ejs engine support (defaults to jade)')
+  .option('-J, --jshtml', 'add jshtml engine support (defaults to jade)')
+  .option('-H, --hogan', 'add hogan.js engine support')
+  .option('-c, --css <engine>', 'add stylesheet <engine> support (less|stylus) (defaults to plain css)')
+  .option('-f, --force', 'force on non-empty directory')
+  .parse(process.argv);
+
+// Path
+
+var path = program.args.shift() || '.';
+
+// end-of-line code
+
+var eol = os.EOL
+
+// Template engine
+
+program.template = 'jade';
+if (program.ejs) program.template = 'ejs';
+if (program.jshtml) program.template = 'jshtml';
+if (program.hogan) program.template = 'hjs';
+
+/**
+ * Routes index template.
+ */
+
+var index = [
+    ''
+  , '/*'
+  , ' * GET home page.'
+  , ' */'
+  , ''
+  , 'exports.index = function(req, res){'
+  , '  res.render(\'index\', { title: \'Express\' });'
+  , '};'
+].join(eol);
+
+/**
+ * Routes users template.
+ */
+
+var users = [
+    ''
+  , '/*'
+  , ' * GET users listing.'
+  , ' */'
+  , ''
+  , 'exports.list = function(req, res){'
+  , '  res.send("respond with a resource");'
+  , '};'
+].join(eol);
+
+/**
+ * Jade layout template.
+ */
+
+var jadeLayout = [
+    'doctype 5'
+  , 'html'
+  , '  head'
+  , '    title= title'
+  , '    link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')'
+  , '  body'
+  , '    block content'
+].join(eol);
+
+/**
+ * Jade index template.
+ */
+
+var jadeIndex = [
+    'extends layout'
+  , ''
+  , 'block content'
+  , '  h1= title'
+  , '  p Welcome to #{title}'
+].join(eol);
+
+/**
+ * EJS index template.
+ */
+
+var ejsIndex = [
+    '<!DOCTYPE html>'
+  , '<html>'
+  , '  <head>'
+  , '    <title><%= title %></title>'
+  , '    <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
+  , '  </head>'
+  , '  <body>'
+  , '    <h1><%= title %></h1>'
+  , '    <p>Welcome to <%= title %></p>'
+  , '  </body>'
+  , '</html>'
+].join(eol);
+
+/**
+ * JSHTML layout template.
+ */
+
+var jshtmlLayout = [
+    '<!DOCTYPE html>'
+  , '<html>'
+  , '  <head>'
+  , '    <title> @write(title) </title>'
+  , '    <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
+  , '  </head>'
+  , '  <body>'
+  , '    @write(body)'
+  , '  </body>'
+  , '</html>'
+].join(eol);
+
+/**
+ * JSHTML index template.
+ */
+
+var jshtmlIndex = [
+    '<h1>@write(title)</h1>'
+  , '<p>Welcome to @write(title)</p>'
+].join(eol);
+
+/**
+ * Hogan.js index template.
+ */
+var hoganIndex = [
+    '<!DOCTYPE html>'
+  , '<html>'
+  , '  <head>'
+  , '    <title>{{ title }}</title>'
+  , '    <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
+  , '  </head>'
+  , '  <body>'
+  , '    <h1>{{ title }}</h1>'
+  , '    <p>Welcome to {{ title }}</p>'
+  , '  </body>'
+  , '</html>'
+].join(eol);
+
+/**
+ * Default css template.
+ */
+
+var css = [
+    'body {'
+  , '  padding: 50px;'
+  , '  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
+  , '}'
+  , ''
+  , 'a {'
+  , '  color: #00B7FF;'
+  , '}'
+].join(eol);
+
+/**
+ * Default less template.
+ */
+
+var less = [
+    'body {'
+  , '  padding: 50px;'
+  , '  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
+  , '}'
+  , ''
+  , 'a {'
+  , '  color: #00B7FF;'
+  , '}'
+].join(eol);
+
+/**
+ * Default stylus template.
+ */
+
+var stylus = [
+    'body'
+  , '  padding: 50px'
+  , '  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif'
+  , 'a'
+  , '  color: #00B7FF'
+].join(eol);
+
+/**
+ * App template.
+ */
+
+var app = [
+    ''
+  , '/**'
+  , ' * Module dependencies.'
+  , ' */'
+  , ''
+  , 'var express = require(\'express\')'
+  , '  , routes = require(\'./routes\')'
+  , '  , user = require(\'./routes/user\')'
+  , '  , http = require(\'http\')'
+  , '  , path = require(\'path\');'
+  , ''
+  , 'var app = express();'
+  , ''
+  , '// all environments'
+  , 'app.set(\'port\', process.env.PORT || 3000);'
+  , 'app.set(\'views\', __dirname + \'/views\');'
+  , 'app.set(\'view engine\', \':TEMPLATE\');'
+  , 'app.use(express.favicon());'
+  , 'app.use(express.logger(\'dev\'));'
+  , 'app.use(express.bodyParser());'
+  , 'app.use(express.methodOverride());{sess}'
+  , 'app.use(app.router);{css}'
+  , 'app.use(express.static(path.join(__dirname, \'public\')));'
+  , ''
+  , '// development only'
+  , 'if (\'development\' == app.get(\'env\')) {'
+  , '  app.use(express.errorHandler());'
+  , '}'
+  , ''
+  , 'app.get(\'/\', routes.index);'
+  , 'app.get(\'/users\', user.list);'
+  , ''
+  , 'http.createServer(app).listen(app.get(\'port\'), function(){'
+  , '  console.log(\'Express server listening on port \' + app.get(\'port\'));'
+  , '});'
+  , ''
+].join(eol);
+
+// Generate application
+
+(function createApplication(path) {
+  emptyDirectory(path, function(empty){
+    if (empty || program.force) {
+      createApplicationAt(path);
+    } else {
+      program.confirm('destination is not empty, continue? ', function(ok){
+        if (ok) {
+          process.stdin.destroy();
+          createApplicationAt(path);
+        } else {
+          abort('aborting');
+        }
+      });
+    }
+  });
+})(path);
+
+/**
+ * Create application at the given directory `path`.
+ *
+ * @param {String} path
+ */
+
+function createApplicationAt(path) {
+  console.log();
+  process.on('exit', function(){
+    console.log();
+    console.log('   install dependencies:');
+    console.log('     $ cd %s && npm install', path);
+    console.log();
+    console.log('   run the app:');
+    console.log('     $ node app');
+    console.log();
+  });
+
+  mkdir(path, function(){
+    mkdir(path + '/public');
+    mkdir(path + '/public/javascripts');
+    mkdir(path + '/public/images');
+    mkdir(path + '/public/stylesheets', function(){
+      switch (program.css) {
+        case 'less':
+          write(path + '/public/stylesheets/style.less', less);
+          break;
+        case 'stylus':
+          write(path + '/public/stylesheets/style.styl', stylus);
+          break;
+        default:
+          write(path + '/public/stylesheets/style.css', css);
+      }
+    });
+
+    mkdir(path + '/routes', function(){
+      write(path + '/routes/index.js', index);
+      write(path + '/routes/user.js', users);
+    });
+
+    mkdir(path + '/views', function(){
+      switch (program.template) {
+        case 'ejs':
+          write(path + '/views/index.ejs', ejsIndex);
+          break;
+        case 'jade':
+          write(path + '/views/layout.jade', jadeLayout);
+          write(path + '/views/index.jade', jadeIndex);
+          break;
+        case 'jshtml':
+          write(path + '/views/layout.jshtml', jshtmlLayout);
+          write(path + '/views/index.jshtml', jshtmlIndex);
+          break;
+        case 'hjs':
+          write(path + '/views/index.hjs', hoganIndex);
+          break;
+
+      }
+    });
+
+    // CSS Engine support
+    switch (program.css) {
+      case 'less':
+        app = app.replace('{css}', eol + 'app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));');
+        break;
+      case 'stylus':
+        app = app.replace('{css}', eol + 'app.use(require(\'stylus\').middleware(__dirname + \'/public\'));');
+        break;
+      default:
+        app = app.replace('{css}', '');
+    }
+
+    // Session support
+    app = app.replace('{sess}', program.sessions
+      ? eol + 'app.use(express.cookieParser(\'your secret here\'));' + eol + 'app.use(express.session());'
+      : '');
+
+    // Template support
+    app = app.replace(':TEMPLATE', program.template);
+
+    // package.json
+    var pkg = {
+        name: 'application-name'
+      , version: '0.0.1'
+      , private: true
+      , scripts: { start: 'node app.js' }
+      , dependencies: {
+        express: version
+      }
+    }
+
+    if (program.template) pkg.dependencies[program.template] = '*';
+
+    // CSS Engine support
+    switch (program.css) {
+      case 'less':
+        pkg.dependencies['less-middleware'] = '*';
+        break;
+      default:
+        if (program.css) {
+          pkg.dependencies[program.css] = '*';
+        }
+    }
+
+    write(path + '/package.json', JSON.stringify(pkg, null, 2));
+    write(path + '/app.js', app);
+  });
+}
+
+/**
+ * Check if the given directory `path` is empty.
+ *
+ * @param {String} path
+ * @param {Function} fn
+ */
+
+function emptyDirectory(path, fn) {
+  fs.readdir(path, function(err, files){
+    if (err && 'ENOENT' != err.code) throw err;
+    fn(!files || !files.length);
+  });
+}
+
+/**
+ * echo str > path.
+ *
+ * @param {String} path
+ * @param {String} str
+ */
+
+function write(path, str) {
+  fs.writeFile(path, str);
+  console.log('   \x1b[36mcreate\x1b[0m : ' + path);
+}
+
+/**
+ * Mkdir -p.
+ *
+ * @param {String} path
+ * @param {Function} fn
+ */
+
+function mkdir(path, fn) {
+  mkdirp(path, 0755, function(err){
+    if (err) throw err;
+    console.log('   \033[36mcreate\033[0m : ' + path);
+    fn && fn();
+  });
+}
+
+/**
+ * Exit with the given `str`.
+ *
+ * @param {String} str
+ */
+
+function abort(str) {
+  console.error(str);
+  process.exit(1);
+}
Index: Dev/trunk/src/node_modules/express/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/index.js	(revision 484)
@@ -0,0 +1,4 @@
+
+module.exports = process.env.EXPRESS_COV
+  ? require('./lib-cov/express')
+  : require('./lib/express');
Index: Dev/trunk/src/node_modules/express/lib/application.js
===================================================================
--- Dev/trunk/src/node_modules/express/lib/application.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/lib/application.js	(revision 484)
@@ -0,0 +1,536 @@
+/**
+ * Module dependencies.
+ */
+
+var connect = require('connect')
+  , Router = require('./router')
+  , methods = require('methods')
+  , middleware = require('./middleware')
+  , debug = require('debug')('express:application')
+  , locals = require('./utils').locals
+  , View = require('./view')
+  , utils = connect.utils
+  , path = require('path')
+  , http = require('http')
+  , join = path.join;
+
+/**
+ * Application prototype.
+ */
+
+var app = exports = module.exports = {};
+
+/**
+ * Initialize the server.
+ *
+ *   - setup default configuration
+ *   - setup default middleware
+ *   - setup route reflection methods
+ *
+ * @api private
+ */
+
+app.init = function(){
+  this.cache = {};
+  this.settings = {};
+  this.engines = {};
+  this.defaultConfiguration();
+};
+
+/**
+ * Initialize application configuration.
+ *
+ * @api private
+ */
+
+app.defaultConfiguration = function(){
+  // default settings
+  this.enable('x-powered-by');
+  this.set('env', process.env.NODE_ENV || 'development');
+  this.set('subdomain offset', 2);
+  debug('booting in %s mode', this.get('env'));
+
+  // implicit middleware
+  this.use(connect.query());
+  this.use(middleware.init(this));
+
+  // inherit protos
+  this.on('mount', function(parent){
+    this.request.__proto__ = parent.request;
+    this.response.__proto__ = parent.response;
+    this.engines.__proto__ = parent.engines;
+    this.settings.__proto__ = parent.settings;
+  });
+
+  // router
+  this._router = new Router(this);
+  this.routes = this._router.map;
+  this.__defineGetter__('router', function(){
+    this._usedRouter = true;
+    this._router.caseSensitive = this.enabled('case sensitive routing');
+    this._router.strict = this.enabled('strict routing');
+    return this._router.middleware;
+  });
+
+  // setup locals
+  this.locals = locals(this);
+
+  // default locals
+  this.locals.settings = this.settings;
+
+  // default configuration
+  this.set('view', View);
+  this.set('views', process.cwd() + '/views');
+  this.set('jsonp callback name', 'callback');
+
+  this.configure('development', function(){
+    this.set('json spaces', 2);
+  });
+
+  this.configure('production', function(){
+    this.enable('view cache');
+  });
+};
+
+/**
+ * Proxy `connect#use()` to apply settings to
+ * mounted applications.
+ *
+ * @param {String|Function|Server} route
+ * @param {Function|Server} fn
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.use = function(route, fn){
+  var app;
+
+  // default route to '/'
+  if ('string' != typeof route) fn = route, route = '/';
+
+  // express app
+  if (fn.handle && fn.set) app = fn;
+
+  // restore .app property on req and res
+  if (app) {
+    app.route = route;
+    fn = function(req, res, next) {
+      var orig = req.app;
+      app.handle(req, res, function(err){
+        req.app = res.app = orig;
+        req.__proto__ = orig.request;
+        res.__proto__ = orig.response;
+        next(err);
+      });
+    };
+  }
+
+  connect.proto.use.call(this, route, fn);
+
+  // mounted an app
+  if (app) {
+    app.parent = this;
+    app.emit('mount', this);
+  }
+
+  return this;
+};
+
+/**
+ * Register the given template engine callback `fn`
+ * as `ext`.
+ *
+ * By default will `require()` the engine based on the
+ * file extension. For example if you try to render
+ * a "foo.jade" file Express will invoke the following internally:
+ *
+ *     app.engine('jade', require('jade').__express);
+ *
+ * For engines that do not provide `.__express` out of the box,
+ * or if you wish to "map" a different extension to the template engine
+ * you may use this method. For example mapping the EJS template engine to
+ * ".html" files:
+ *
+ *     app.engine('html', require('ejs').renderFile);
+ *
+ * In this case EJS provides a `.renderFile()` method with
+ * the same signature that Express expects: `(path, options, callback)`,
+ * though note that it aliases this method as `ejs.__express` internally
+ * so if you're using ".ejs" extensions you dont need to do anything.
+ *
+ * Some template engines do not follow this convention, the
+ * [Consolidate.js](https://github.com/visionmedia/consolidate.js)
+ * library was created to map all of node's popular template
+ * engines to follow this convention, thus allowing them to
+ * work seamlessly within Express.
+ *
+ * @param {String} ext
+ * @param {Function} fn
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.engine = function(ext, fn){
+  if ('function' != typeof fn) throw new Error('callback function required');
+  if ('.' != ext[0]) ext = '.' + ext;
+  this.engines[ext] = fn;
+  return this;
+};
+
+/**
+ * Map the given param placeholder `name`(s) to the given callback(s).
+ *
+ * Parameter mapping is used to provide pre-conditions to routes
+ * which use normalized placeholders. For example a _:user_id_ parameter
+ * could automatically load a user's information from the database without
+ * any additional code,
+ *
+ * The callback uses the samesignature as middleware, the only differencing
+ * being that the value of the placeholder is passed, in this case the _id_
+ * of the user. Once the `next()` function is invoked, just like middleware
+ * it will continue on to execute the route, or subsequent parameter functions.
+ *
+ *      app.param('user_id', 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'));
+ *          }
+ *        });
+ *      });
+ *
+ * @param {String|Array} name
+ * @param {Function} fn
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.param = function(name, fn){
+  var self = this
+    , fns = [].slice.call(arguments, 1);
+
+  // array
+  if (Array.isArray(name)) {
+    name.forEach(function(name){
+      fns.forEach(function(fn){
+        self.param(name, fn);
+      });
+    });
+  // param logic
+  } else if ('function' == typeof name) {
+    this._router.param(name);
+  // single
+  } else {
+    if (':' == name[0]) name = name.substr(1);
+    fns.forEach(function(fn){
+      self._router.param(name, fn);
+    });
+  }
+
+  return this;
+};
+
+/**
+ * Assign `setting` to `val`, or return `setting`'s value.
+ *
+ *    app.set('foo', 'bar');
+ *    app.get('foo');
+ *    // => "bar"
+ *
+ * Mounted servers inherit their parent server's settings.
+ *
+ * @param {String} setting
+ * @param {String} val
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.set = function(setting, val){
+  if (1 == arguments.length) {
+    return this.settings[setting];
+  } else {
+    this.settings[setting] = val;
+    return this;
+  }
+};
+
+/**
+ * Return the app's absolute pathname
+ * based on the parent(s) that have
+ * mounted it.
+ *
+ * For example if the application was
+ * mounted as "/admin", which itself
+ * was mounted as "/blog" then the
+ * return value would be "/blog/admin".
+ *
+ * @return {String}
+ * @api private
+ */
+
+app.path = function(){
+  return this.parent
+    ? this.parent.path() + this.route
+    : '';
+};
+
+/**
+ * Check if `setting` is enabled (truthy).
+ *
+ *    app.enabled('foo')
+ *    // => false
+ *
+ *    app.enable('foo')
+ *    app.enabled('foo')
+ *    // => true
+ *
+ * @param {String} setting
+ * @return {Boolean}
+ * @api public
+ */
+
+app.enabled = function(setting){
+  return !!this.set(setting);
+};
+
+/**
+ * Check if `setting` is disabled.
+ *
+ *    app.disabled('foo')
+ *    // => true
+ *
+ *    app.enable('foo')
+ *    app.disabled('foo')
+ *    // => false
+ *
+ * @param {String} setting
+ * @return {Boolean}
+ * @api public
+ */
+
+app.disabled = function(setting){
+  return !this.set(setting);
+};
+
+/**
+ * Enable `setting`.
+ *
+ * @param {String} setting
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.enable = function(setting){
+  return this.set(setting, true);
+};
+
+/**
+ * Disable `setting`.
+ *
+ * @param {String} setting
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.disable = function(setting){
+  return this.set(setting, false);
+};
+
+/**
+ * Configure callback for zero or more envs,
+ * when no `env` is specified that callback will
+ * be invoked for all environments. Any combination
+ * can be used multiple times, in any order desired.
+ *
+ * Examples:
+ *
+ *    app.configure(function(){
+ *      // executed for all envs
+ *    });
+ *
+ *    app.configure('stage', function(){
+ *      // executed staging env
+ *    });
+ *
+ *    app.configure('stage', 'production', function(){
+ *      // executed for stage and production
+ *    });
+ *
+ * Note:
+ *
+ *  These callbacks are invoked immediately, and
+ *  are effectively sugar for the following:
+ *
+ *     var env = process.env.NODE_ENV || 'development';
+ *
+ *      switch (env) {
+ *        case 'development':
+ *          ...
+ *          break;
+ *        case 'stage':
+ *          ...
+ *          break;
+ *        case 'production':
+ *          ...
+ *          break;
+ *      }
+ *
+ * @param {String} env...
+ * @param {Function} fn
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.configure = function(env, fn){
+  var envs = 'all'
+    , args = [].slice.call(arguments);
+  fn = args.pop();
+  if (args.length) envs = args;
+  if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this);
+  return this;
+};
+
+/**
+ * Delegate `.VERB(...)` calls to `router.VERB(...)`.
+ */
+
+methods.forEach(function(method){
+  app[method] = function(path){
+    if ('get' == method && 1 == arguments.length) return this.set(path);
+
+    // deprecated
+    if (Array.isArray(path)) {
+      console.trace('passing an array to app.VERB() is deprecated and will be removed in 4.0');
+    }
+
+    // if no router attached yet, attach the router
+    if (!this._usedRouter) this.use(this.router);
+
+    // setup route
+    this._router[method].apply(this._router, arguments);
+    return this;
+  };
+});
+
+/**
+ * Special-cased "all" method, applying the given route `path`,
+ * middleware, and callback to _every_ HTTP method.
+ *
+ * @param {String} path
+ * @param {Function} ...
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.all = function(path){
+  var args = arguments;
+  methods.forEach(function(method){
+    app[method].apply(this, args);
+  }, this);
+  return this;
+};
+
+// del -> delete alias
+
+app.del = app.delete;
+
+/**
+ * Render the given view `name` name with `options`
+ * and a callback accepting an error and the
+ * rendered template string.
+ *
+ * Example:
+ *
+ *    app.render('email', { name: 'Tobi' }, function(err, html){
+ *      // ...
+ *    })
+ *
+ * @param {String} name
+ * @param {String|Function} options or fn
+ * @param {Function} fn
+ * @api public
+ */
+
+app.render = function(name, options, fn){
+  var opts = {}
+    , cache = this.cache
+    , engines = this.engines
+    , view;
+
+  // support callback function as second arg
+  if ('function' == typeof options) {
+    fn = options, options = {};
+  }
+
+  // merge app.locals
+  utils.merge(opts, this.locals);
+
+  // merge options._locals
+  if (options._locals) utils.merge(opts, options._locals);
+
+  // merge options
+  utils.merge(opts, options);
+
+  // set .cache unless explicitly provided
+  opts.cache = null == opts.cache
+    ? this.enabled('view cache')
+    : opts.cache;
+
+  // primed cache
+  if (opts.cache) view = cache[name];
+
+  // view
+  if (!view) {
+    view = new (this.get('view'))(name, {
+      defaultEngine: this.get('view engine'),
+      root: this.get('views'),
+      engines: engines
+    });
+
+    if (!view.path) {
+      var err = new Error('Failed to lookup view "' + name + '"');
+      err.view = view;
+      return fn(err);
+    }
+
+    // prime the cache
+    if (opts.cache) cache[name] = view;
+  }
+
+  // render
+  try {
+    view.render(opts, fn);
+  } catch (err) {
+    fn(err);
+  }
+};
+
+/**
+ * Listen for connections.
+ *
+ * A node `http.Server` is returned, with this
+ * application (which is a `Function`) as its
+ * callback. If you wish to create both an HTTP
+ * and HTTPS server you may do so with the "http"
+ * and "https" modules as shown here:
+ *
+ *    var http = require('http')
+ *      , https = require('https')
+ *      , express = require('express')
+ *      , app = express();
+ *
+ *    http.createServer(app).listen(80);
+ *    https.createServer({ ... }, app).listen(443);
+ *
+ * @return {http.Server}
+ * @api public
+ */
+
+app.listen = function(){
+  var server = http.createServer(this);
+  return server.listen.apply(server, arguments);
+};
Index: Dev/trunk/src/node_modules/express/lib/express.js
===================================================================
--- Dev/trunk/src/node_modules/express/lib/express.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/lib/express.js	(revision 484)
@@ -0,0 +1,92 @@
+/**
+ * Module dependencies.
+ */
+
+var connect = require('connect')
+  , proto = require('./application')
+  , Route = require('./router/route')
+  , Router = require('./router')
+  , req = require('./request')
+  , res = require('./response')
+  , utils = connect.utils;
+
+/**
+ * Expose `createApplication()`.
+ */
+
+exports = module.exports = createApplication;
+
+/**
+ * Framework version.
+ */
+
+exports.version = '3.2.5';
+
+/**
+ * Expose mime.
+ */
+
+exports.mime = connect.mime;
+
+/**
+ * Create an express application.
+ *
+ * @return {Function}
+ * @api public
+ */
+
+function createApplication() {
+  var app = connect();
+  utils.merge(app, proto);
+  app.request = { __proto__: req };
+  app.response = { __proto__: res };
+  app.init();
+  return app;
+}
+
+/**
+ * Expose connect.middleware as express.*
+ * for example `express.logger` etc.
+ */
+
+for (var key in connect.middleware) {
+  Object.defineProperty(
+      exports
+    , key
+    , Object.getOwnPropertyDescriptor(connect.middleware, key));
+}
+
+/**
+ * Error on createServer().
+ */
+
+exports.createServer = function(){
+  console.warn('Warning: express.createServer() is deprecated, express');
+  console.warn('applications no longer inherit from http.Server,');
+  console.warn('please use:');
+  console.warn('');
+  console.warn('  var express = require("express");');
+  console.warn('  var app = express();');
+  console.warn('');
+  return createApplication();
+};
+
+/**
+ * Expose the prototypes.
+ */
+
+exports.application = proto;
+exports.request = req;
+exports.response = res;
+
+/**
+ * Expose constructors.
+ */
+
+exports.Route = Route;
+exports.Router = Router;
+
+// Error handler title
+
+exports.errorHandler.title = 'Express';
+
Index: Dev/trunk/src/node_modules/express/lib/middleware.js
===================================================================
--- Dev/trunk/src/node_modules/express/lib/middleware.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/lib/middleware.js	(revision 484)
@@ -0,0 +1,33 @@
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('./utils');
+
+/**
+ * Initialization middleware, exposing the
+ * request and response to eachother, as well
+ * as defaulting the X-Powered-By header field.
+ *
+ * @param {Function} app
+ * @return {Function}
+ * @api private
+ */
+
+exports.init = function(app){
+  return function expressInit(req, res, next){
+    req.app = res.app = app;
+    if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express');
+    req.res = res;
+    res.req = req;
+    req.next = next;
+
+    req.__proto__ = app.request;
+    res.__proto__ = app.response;
+
+    res.locals = res.locals || utils.locals(res);
+
+    next();
+  }
+};
Index: Dev/trunk/src/node_modules/express/lib/request.js
===================================================================
--- Dev/trunk/src/node_modules/express/lib/request.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/lib/request.js	(revision 484)
@@ -0,0 +1,527 @@
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , utils = require('./utils')
+  , connect = require('connect')
+  , fresh = require('fresh')
+  , parseRange = require('range-parser')
+  , parse = connect.utils.parseUrl
+  , mime = connect.mime;
+
+/**
+ * Request prototype.
+ */
+
+var req = exports = module.exports = {
+  __proto__: http.IncomingMessage.prototype
+};
+
+/**
+ * Return request header.
+ *
+ * The `Referrer` header field is special-cased,
+ * both `Referrer` and `Referer` are interchangeable.
+ *
+ * Examples:
+ *
+ *     req.get('Content-Type');
+ *     // => "text/plain"
+ *
+ *     req.get('content-type');
+ *     // => "text/plain"
+ *
+ *     req.get('Something');
+ *     // => undefined
+ *
+ * Aliased as `req.header()`.
+ *
+ * @param {String} name
+ * @return {String}
+ * @api public
+ */
+
+req.get =
+req.header = function(name){
+  switch (name = name.toLowerCase()) {
+    case 'referer':
+    case 'referrer':
+      return this.headers.referrer
+        || this.headers.referer;
+    default:
+      return this.headers[name];
+  }
+};
+
+/**
+ * Check if the given `type(s)` is acceptable, returning
+ * the best match when true, otherwise `undefined`, in which
+ * case you should respond with 406 "Not Acceptable".
+ *
+ * The `type` value may be a single mime type string
+ * such as "application/json", the extension name
+ * such as "json", a comma-delimted list such as "json, html, text/plain",
+ * or an array `["json", "html", "text/plain"]`. When a list
+ * or array is given the _best_ match, if any is returned.
+ *
+ * Examples:
+ *
+ *     // Accept: text/html
+ *     req.accepts('html');
+ *     // => "html"
+ *
+ *     // Accept: text/*, application/json
+ *     req.accepts('html');
+ *     // => "html"
+ *     req.accepts('text/html');
+ *     // => "text/html"
+ *     req.accepts('json, text');
+ *     // => "json"
+ *     req.accepts('application/json');
+ *     // => "application/json"
+ *
+ *     // Accept: text/*, application/json
+ *     req.accepts('image/png');
+ *     req.accepts('png');
+ *     // => undefined
+ *
+ *     // Accept: text/*;q=.5, application/json
+ *     req.accepts(['html', 'json']);
+ *     req.accepts('html, json');
+ *     // => "json"
+ *
+ * @param {String|Array} type(s)
+ * @return {String}
+ * @api public
+ */
+
+req.accepts = function(type){
+  return utils.accepts(type, this.get('Accept'));
+};
+
+/**
+ * Check if the given `encoding` is accepted.
+ *
+ * @param {String} encoding
+ * @return {Boolean}
+ * @api public
+ */
+
+req.acceptsEncoding = function(encoding){
+  return ~this.acceptedEncodings.indexOf(encoding);
+};
+
+/**
+ * Check if the given `charset` is acceptable,
+ * otherwise you should respond with 406 "Not Acceptable".
+ *
+ * @param {String} charset
+ * @return {Boolean}
+ * @api public
+ */
+
+req.acceptsCharset = function(charset){
+  var accepted = this.acceptedCharsets;
+  return accepted.length
+    ? ~accepted.indexOf(charset)
+    : true;
+};
+
+/**
+ * Check if the given `lang` is acceptable,
+ * otherwise you should respond with 406 "Not Acceptable".
+ *
+ * @param {String} lang
+ * @return {Boolean}
+ * @api public
+ */
+
+req.acceptsLanguage = function(lang){
+  var accepted = this.acceptedLanguages;
+  return accepted.length
+    ? ~accepted.indexOf(lang)
+    : true;
+};
+
+/**
+ * Parse Range header field,
+ * capping to the given `size`.
+ *
+ * Unspecified ranges such as "0-" require
+ * knowledge of your resource length. In
+ * the case of a byte range this is of course
+ * the total number of bytes. If the Range
+ * header field is not given `null` is returned,
+ * `-1` when unsatisfiable, `-2` when syntactically invalid.
+ *
+ * NOTE: remember that ranges are inclusive, so
+ * for example "Range: users=0-3" should respond
+ * with 4 users when available, not 3.
+ *
+ * @param {Number} size
+ * @return {Array}
+ * @api public
+ */
+
+req.range = function(size){
+  var range = this.get('Range');
+  if (!range) return;
+  return parseRange(size, range);
+};
+
+/**
+ * Return an array of encodings.
+ *
+ * Examples:
+ *
+ *     ['gzip', 'deflate']
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('acceptedEncodings', function(){
+  var accept = this.get('Accept-Encoding');
+  return accept
+    ? accept.trim().split(/ *, */)
+    : [];
+});
+
+/**
+ * Return an array of Accepted media types
+ * ordered from highest quality to lowest.
+ *
+ * Examples:
+ *
+ *     [ { value: 'application/json',
+ *         quality: 1,
+ *         type: 'application',
+ *         subtype: 'json' },
+ *       { value: 'text/html',
+ *         quality: 0.5,
+ *         type: 'text',
+ *         subtype: 'html' } ]
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('accepted', function(){
+  var accept = this.get('Accept');
+  return accept
+    ? utils.parseAccept(accept)
+    : [];
+});
+
+/**
+ * Return an array of Accepted languages
+ * ordered from highest quality to lowest.
+ *
+ * Examples:
+ *
+ *     Accept-Language: en;q=.5, en-us
+ *     ['en-us', 'en']
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('acceptedLanguages', function(){
+  var accept = this.get('Accept-Language');
+  return accept
+    ? utils
+      .parseParams(accept)
+      .map(function(obj){
+        return obj.value;
+      })
+    : [];
+});
+
+/**
+ * Return an array of Accepted charsets
+ * ordered from highest quality to lowest.
+ *
+ * Examples:
+ *
+ *     Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8
+ *     ['unicode-1-1', 'iso-8859-5']
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('acceptedCharsets', function(){
+  var accept = this.get('Accept-Charset');
+  return accept
+    ? utils
+      .parseParams(accept)
+      .map(function(obj){
+        return obj.value;
+      })
+    : [];
+});
+
+/**
+ * Return the value of param `name` when present or `defaultValue`.
+ *
+ *  - Checks route placeholders, ex: _/user/:id_
+ *  - Checks body params, ex: id=12, {"id":12}
+ *  - Checks query string params, ex: ?id=12
+ *
+ * To utilize 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){
+  var params = this.params || {};
+  var body = this.body || {};
+  var query = this.query || {};
+  if (null != params[name] && params.hasOwnProperty(name)) return params[name];
+  if (null != body[name]) return body[name];
+  if (null != query[name]) return query[name];
+  return defaultValue;
+};
+
+/**
+ * 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');
+ *      req.is('text/*');
+ *      // => true
+ *
+ *      // When Content-Type is application/json
+ *      req.is('json');
+ *      req.is('application/json');
+ *      req.is('application/*');
+ *      // => true
+ *
+ *      req.is('html');
+ *      // => false
+ *
+ * @param {String} type
+ * @return {Boolean}
+ * @api public
+ */
+
+req.is = function(type){
+  var ct = this.get('Content-Type');
+  if (!ct) return false;
+  ct = ct.split(';')[0];
+  if (!~type.indexOf('/')) type = mime.lookup(type);
+  if (~type.indexOf('*')) {
+    type = type.split('/');
+    ct = ct.split('/');
+    if ('*' == type[0] && type[1] == ct[1]) return true;
+    if ('*' == type[1] && type[0] == ct[0]) return true;
+    return false;
+  }
+  return !! ~ct.indexOf(type);
+};
+
+/**
+ * Return the protocol string "http" or "https"
+ * when requested with TLS. When the "trust proxy"
+ * setting is enabled the "X-Forwarded-Proto" header
+ * field will be trusted. If you're running behind
+ * a reverse proxy that supplies https for you this
+ * may be enabled.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('protocol', function(){
+  var trustProxy = this.app.get('trust proxy');
+  return this.connection.encrypted
+    ? 'https'
+    : trustProxy
+      ? (this.get('X-Forwarded-Proto') || 'http')
+      : 'http';
+});
+
+/**
+ * Short-hand for:
+ *
+ *    req.protocol == 'https'
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('secure', function(){
+  return 'https' == this.protocol;
+});
+
+/**
+ * Return the remote address, or when
+ * "trust proxy" is `true` return
+ * the upstream addr.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('ip', function(){
+  return this.ips[0] || this.connection.remoteAddress;
+});
+
+/**
+ * When "trust proxy" is `true`, parse
+ * the "X-Forwarded-For" ip address list.
+ *
+ * For example if the value were "client, proxy1, proxy2"
+ * you would receive the array `["client", "proxy1", "proxy2"]`
+ * where "proxy2" is the furthest down-stream.
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('ips', function(){
+  var trustProxy = this.app.get('trust proxy');
+  var val = this.get('X-Forwarded-For');
+  return trustProxy && val
+    ? val.split(/ *, */)
+    : [];
+});
+
+/**
+ * Return basic auth credentials.
+ *
+ * Examples:
+ *
+ *    // http://tobi:hello@example.com
+ *    req.auth
+ *    // => { username: 'tobi', password: 'hello' }
+ *
+ * @return {Object} or undefined
+ * @api public
+ */
+
+req.__defineGetter__('auth', function(){
+  // missing
+  var auth = this.get('Authorization');
+  if (!auth) return;
+
+  // malformed
+  var parts = auth.split(' ');
+  if ('basic' != parts[0].toLowerCase()) return;
+  if (!parts[1]) return;
+  auth = parts[1];
+
+  // credentials
+  auth = new Buffer(auth, 'base64').toString().match(/^([^:]*):(.*)$/);
+  if (!auth) return;
+  return { username: auth[1], password: auth[2] };
+});
+
+/**
+ * Return subdomains as an array.
+ *
+ * Subdomains are the dot-separated parts of the host before the main domain of
+ * the app. By default, the domain of the app is assumed to be the last two
+ * parts of the host. This can be changed by setting "subdomain offset".
+ *
+ * For example, if the domain is "tobi.ferrets.example.com":
+ * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`.
+ * If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('subdomains', function(){
+  var offset = this.app.get('subdomain offset');
+  return (this.host || '')
+    .split('.')
+    .reverse()
+    .slice(offset);
+});
+
+/**
+ * Short-hand for `url.parse(req.url).pathname`.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('path', function(){
+  return parse(this).pathname;
+});
+
+/**
+ * Parse the "Host" header field hostname.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('host', function(){
+  var trustProxy = this.app.get('trust proxy');
+  var host = trustProxy && this.get('X-Forwarded-Host');
+  host = host || this.get('Host');
+  if (!host) return;
+  return host.split(':')[0];
+});
+
+/**
+ * Check if the request is fresh, aka
+ * Last-Modified and/or the ETag
+ * still match.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('fresh', function(){
+  var method = this.method;
+  var s = this.res.statusCode;
+
+  // GET or HEAD for weak freshness validation only
+  if ('GET' != method && 'HEAD' != method) return false;
+
+  // 2xx or 304 as per rfc2616 14.26
+  if ((s >= 200 && s < 300) || 304 == s) {
+    return fresh(this.headers, this.res._headers);
+  }
+
+  return false;
+});
+
+/**
+ * Check if the request is stale, aka
+ * "Last-Modified" and / or the "ETag" for the
+ * resource has changed.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('stale', function(){
+  return !this.fresh;
+});
+
+/**
+ * Check if the request was an _XMLHttpRequest_.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('xhr', function(){
+  var val = this.get('X-Requested-With') || '';
+  return 'xmlhttprequest' == val.toLowerCase();
+});
Index: Dev/trunk/src/node_modules/express/lib/response.js
===================================================================
--- Dev/trunk/src/node_modules/express/lib/response.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/lib/response.js	(revision 484)
@@ -0,0 +1,757 @@
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , path = require('path')
+  , connect = require('connect')
+  , utils = connect.utils
+  , sign = require('cookie-signature').sign
+  , normalizeType = require('./utils').normalizeType
+  , normalizeTypes = require('./utils').normalizeTypes
+  , etag = require('./utils').etag
+  , statusCodes = http.STATUS_CODES
+  , cookie = require('cookie')
+  , send = require('send')
+  , mime = connect.mime
+  , basename = path.basename
+  , extname = path.extname
+  , join = path.join;
+
+/**
+ * Response prototype.
+ */
+
+var res = module.exports = {
+  __proto__: http.ServerResponse.prototype
+};
+
+/**
+ * Set status `code`.
+ *
+ * @param {Number} code
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.status = function(code){
+  this.statusCode = code;
+  return this;
+};
+
+/**
+ * Set Link header field with the given `links`.
+ *
+ * Examples:
+ *
+ *    res.links({
+ *      next: 'http://api.example.com/users?page=2',
+ *      last: 'http://api.example.com/users?page=5'
+ *    });
+ *
+ * @param {Object} links
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.links = function(links){
+  return this.set('Link', Object.keys(links).map(function(rel){
+    return '<' + links[rel] + '>; rel="' + rel + '"';
+  }).join(', '));
+};
+
+/**
+ * Send a response.
+ *
+ * Examples:
+ *
+ *     res.send(new Buffer('wahoo'));
+ *     res.send({ some: 'json' });
+ *     res.send('<p>some html</p>');
+ *     res.send(404, 'Sorry, cant find that');
+ *     res.send(404);
+ *
+ * @param {Mixed} body or status
+ * @param {Mixed} body
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.send = function(body){
+  var req = this.req;
+  var head = 'HEAD' == req.method;
+  var len;
+
+  // allow status / body
+  if (2 == arguments.length) {
+    // res.send(body, status) backwards compat
+    if ('number' != typeof body && 'number' == typeof arguments[1]) {
+      this.statusCode = arguments[1];
+    } else {
+      this.statusCode = body;
+      body = arguments[1];
+    }
+  }
+
+  switch (typeof body) {
+    // response status
+    case 'number':
+      this.get('Content-Type') || this.type('txt');
+      this.statusCode = body;
+      body = http.STATUS_CODES[body];
+      break;
+    // string defaulting to html
+    case 'string':
+      if (!this.get('Content-Type')) {
+        this.charset = this.charset || 'utf-8';
+        this.type('html');
+      }
+      break;
+    case 'boolean':
+    case 'object':
+      if (null == body) {
+        body = '';
+      } else if (Buffer.isBuffer(body)) {
+        this.get('Content-Type') || this.type('bin');
+      } else {
+        return this.json(body);
+      }
+      break;
+  }
+
+  // populate Content-Length
+  if (undefined !== body && !this.get('Content-Length')) {
+    this.set('Content-Length', len = Buffer.isBuffer(body)
+      ? body.length
+      : Buffer.byteLength(body));
+  }
+
+  // ETag support
+  // TODO: W/ support
+  if (len > 1024 && 'GET' == req.method) {
+    if (!this.get('ETag')) {
+      this.set('ETag', etag(body));
+    }
+  }
+
+  // freshness
+  if (req.fresh) this.statusCode = 304;
+
+  // strip irrelevant headers
+  if (204 == this.statusCode || 304 == this.statusCode) {
+    this.removeHeader('Content-Type');
+    this.removeHeader('Content-Length');
+    this.removeHeader('Transfer-Encoding');
+    body = '';
+  }
+
+  // respond
+  this.end(head ? null : body);
+  return this;
+};
+
+/**
+ * Send JSON response.
+ *
+ * Examples:
+ *
+ *     res.json(null);
+ *     res.json({ user: 'tj' });
+ *     res.json(500, 'oh noes!');
+ *     res.json(404, 'I dont have that');
+ *
+ * @param {Mixed} obj or status
+ * @param {Mixed} obj
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.json = function(obj){
+  // allow status / body
+  if (2 == arguments.length) {
+    // res.json(body, status) backwards compat
+    if ('number' == typeof arguments[1]) {
+      this.statusCode = arguments[1];
+    } else {
+      this.statusCode = obj;
+      obj = arguments[1];
+    }
+  }
+
+  // settings
+  var app = this.app;
+  var replacer = app.get('json replacer');
+  var spaces = app.get('json spaces');
+  var body = JSON.stringify(obj, replacer, spaces);
+
+  // content-type
+  this.charset = this.charset || 'utf-8';
+  this.get('Content-Type') || this.set('Content-Type', 'application/json');
+
+  return this.send(body);
+};
+
+/**
+ * Send JSON response with JSONP callback support.
+ *
+ * Examples:
+ *
+ *     res.jsonp(null);
+ *     res.jsonp({ user: 'tj' });
+ *     res.jsonp(500, 'oh noes!');
+ *     res.jsonp(404, 'I dont have that');
+ *
+ * @param {Mixed} obj or status
+ * @param {Mixed} obj
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.jsonp = function(obj){
+  // allow status / body
+  if (2 == arguments.length) {
+    // res.json(body, status) backwards compat
+    if ('number' == typeof arguments[1]) {
+      this.statusCode = arguments[1];
+    } else {
+      this.statusCode = obj;
+      obj = arguments[1];
+    }
+  }
+
+  // settings
+  var app = this.app;
+  var replacer = app.get('json replacer');
+  var spaces = app.get('json spaces');
+  var body = JSON.stringify(obj, replacer, spaces)
+    .replace(/\u2028/g, '\\u2028')
+    .replace(/\u2029/g, '\\u2029');
+  var callback = this.req.query[app.get('jsonp callback name')];
+
+  // content-type
+  this.charset = this.charset || 'utf-8';
+  this.set('Content-Type', 'application/json');
+
+  // jsonp
+  if (callback) {
+    this.set('Content-Type', 'text/javascript');
+    var cb = callback.replace(/[^\[\]\w$.]/g, '');
+    body = cb + ' && ' + cb + '(' + body + ');';
+  }
+
+  return this.send(body);
+};
+
+/**
+ * Transfer the file at the given `path`.
+ *
+ * Automatically sets the _Content-Type_ response header field.
+ * The callback `fn(err)` is invoked when the transfer is complete
+ * or when an error occurs. Be sure to check `res.sentHeader`
+ * if you wish to attempt responding, as the header and some data
+ * may have already been transferred.
+ *
+ * Options:
+ *
+ *   - `maxAge` defaulting to 0
+ *   - `root`   root directory for relative filenames
+ *
+ * Examples:
+ *
+ *  The following example illustrates how `res.sendfile()` may
+ *  be used as an alternative for the `static()` middleware for
+ *  dynamic situations. The code backing `res.sendfile()` is actually
+ *  the same code, so HTTP cache support etc is identical.
+ *
+ *     app.get('/user/:uid/photos/:file', function(req, res){
+ *       var uid = req.params.uid
+ *         , file = req.params.file;
+ *
+ *       req.user.mayViewFilesFrom(uid, function(yes){
+ *         if (yes) {
+ *           res.sendfile('/uploads/' + uid + '/' + file);
+ *         } else {
+ *           res.send(403, 'Sorry! you cant see that.');
+ *         }
+ *       });
+ *     });
+ *
+ * @param {String} path
+ * @param {Object|Function} options or fn
+ * @param {Function} fn
+ * @api public
+ */
+
+res.sendfile = function(path, options, fn){
+  var self = this
+    , req = self.req
+    , next = this.req.next
+    , options = options || {}
+    , done;
+
+  // support function as second arg
+  if ('function' == typeof options) {
+    fn = options;
+    options = {};
+  }
+
+  // socket errors
+  req.socket.on('error', error);
+
+  // errors
+  function error(err) {
+    if (done) return;
+    done = true;
+
+    // clean up
+    cleanup();
+    if (!self.headerSent) self.removeHeader('Content-Disposition');
+
+    // callback available
+    if (fn) return fn(err);
+
+    // list in limbo if there's no callback
+    if (self.headerSent) return;
+
+    // delegate
+    next(err);
+  }
+
+  // streaming
+  function stream() {
+    if (done) return;
+    cleanup();
+    if (fn) self.on('finish', fn);
+  }
+
+  // cleanup
+  function cleanup() {
+    req.socket.removeListener('error', error);
+  }
+
+  // transfer
+  var file = send(req, path);
+  if (options.root) file.root(options.root);
+  file.maxage(options.maxAge || 0);
+  file.on('error', error);
+  file.on('directory', next);
+  file.on('stream', stream);
+  file.pipe(this);
+  this.on('finish', cleanup);
+};
+
+/**
+ * Transfer the file at the given `path` as an attachment.
+ *
+ * Optionally providing an alternate attachment `filename`,
+ * and optional callback `fn(err)`. The callback is invoked
+ * when the data transfer is complete, or when an error has
+ * ocurred. Be sure to check `res.headerSent` if you plan to respond.
+ *
+ * This method uses `res.sendfile()`.
+ *
+ * @param {String} path
+ * @param {String|Function} filename or fn
+ * @param {Function} fn
+ * @api public
+ */
+
+res.download = function(path, filename, fn){
+  // support function as second arg
+  if ('function' == typeof filename) {
+    fn = filename;
+    filename = null;
+  }
+
+  filename = filename || path;
+  this.set('Content-Disposition', 'attachment; filename="' + basename(filename) + '"');
+  return this.sendfile(path, fn);
+};
+
+/**
+ * Set _Content-Type_ response header with `type` through `mime.lookup()`
+ * when it does not contain "/", or set the Content-Type to `type` otherwise.
+ *
+ * Examples:
+ *
+ *     res.type('.html');
+ *     res.type('html');
+ *     res.type('json');
+ *     res.type('application/json');
+ *     res.type('png');
+ *
+ * @param {String} type
+ * @return {ServerResponse} for chaining
+ * @api public
+ */
+
+res.contentType =
+res.type = function(type){
+  return this.set('Content-Type', ~type.indexOf('/')
+    ? type
+    : mime.lookup(type));
+};
+
+/**
+ * Respond to the Acceptable formats using an `obj`
+ * of mime-type callbacks.
+ *
+ * This method uses `req.accepted`, an array of
+ * acceptable types ordered by their quality values.
+ * When "Accept" is not present the _first_ callback
+ * is invoked, otherwise the first match is used. When
+ * no match is performed the server responds with
+ * 406 "Not Acceptable".
+ *
+ * Content-Type is set for you, however if you choose
+ * you may alter this within the callback using `res.type()`
+ * or `res.set('Content-Type', ...)`.
+ *
+ *    res.format({
+ *      'text/plain': function(){
+ *        res.send('hey');
+ *      },
+ *
+ *      'text/html': function(){
+ *        res.send('<p>hey</p>');
+ *      },
+ *
+ *      'appliation/json': function(){
+ *        res.send({ message: 'hey' });
+ *      }
+ *    });
+ *
+ * In addition to canonicalized MIME types you may
+ * also use extnames mapped to these types:
+ *
+ *    res.format({
+ *      text: function(){
+ *        res.send('hey');
+ *      },
+ *
+ *      html: function(){
+ *        res.send('<p>hey</p>');
+ *      },
+ *
+ *      json: function(){
+ *        res.send({ message: 'hey' });
+ *      }
+ *    });
+ *
+ * By default Express passes an `Error`
+ * with a `.status` of 406 to `next(err)`
+ * if a match is not made. If you provide
+ * a `.default` callback it will be invoked
+ * instead.
+ *
+ * @param {Object} obj
+ * @return {ServerResponse} for chaining
+ * @api public
+ */
+
+res.format = function(obj){
+  var req = this.req
+    , next = req.next;
+
+  var fn = obj.default;
+  if (fn) delete obj.default;
+  var keys = Object.keys(obj);
+
+  var key = req.accepts(keys);
+
+  this.set('Vary', 'Accept');
+
+  if (key) {
+    this.set('Content-Type', normalizeType(key).value);
+    obj[key](req, this, next);
+  } else if (fn) {
+    fn();
+  } else {
+    var err = new Error('Not Acceptable');
+    err.status = 406;
+    err.types = normalizeTypes(keys).map(function(o){ return o.value });
+    next(err);
+  }
+
+  return this;
+};
+
+/**
+ * Set _Content-Disposition_ header to _attachment_ with optional `filename`.
+ *
+ * @param {String} filename
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.attachment = function(filename){
+  if (filename) this.type(extname(filename));
+  this.set('Content-Disposition', filename
+    ? 'attachment; filename="' + basename(filename) + '"'
+    : 'attachment');
+  return this;
+};
+
+/**
+ * Set header `field` to `val`, or pass
+ * an object of header fields.
+ *
+ * Examples:
+ *
+ *    res.set('Foo', ['bar', 'baz']);
+ *    res.set('Accept', 'application/json');
+ *    res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
+ *
+ * Aliased as `res.header()`.
+ *
+ * @param {String|Object|Array} field
+ * @param {String} val
+ * @return {ServerResponse} for chaining
+ * @api public
+ */
+
+res.set =
+res.header = function(field, val){
+  if (2 == arguments.length) {
+    if (Array.isArray(val)) val = val.map(String);
+    else val = String(val);
+    this.setHeader(field, val);
+  } else {
+    for (var key in field) {
+      this.set(key, field[key]);
+    }
+  }
+  return this;
+};
+
+/**
+ * Get value for header `field`.
+ *
+ * @param {String} field
+ * @return {String}
+ * @api public
+ */
+
+res.get = function(field){
+  return this.getHeader(field);
+};
+
+/**
+ * Clear cookie `name`.
+ *
+ * @param {String} name
+ * @param {Object} options
+ * @param {ServerResponse} for chaining
+ * @api public
+ */
+
+res.clearCookie = function(name, options){
+  var opts = { expires: new Date(1), path: '/' };
+  return this.cookie(name, '', options
+    ? utils.merge(opts, options)
+    : opts);
+};
+
+/**
+ * Set cookie `name` to `val`, with the given `options`.
+ *
+ * Options:
+ *
+ *    - `maxAge`   max-age in milliseconds, converted to `expires`
+ *    - `signed`   sign the cookie
+ *    - `path`     defaults to "/"
+ *
+ * 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|Object} val
+ * @param {Options} options
+ * @api public
+ */
+
+res.cookie = function(name, val, options){
+  options = utils.merge({}, options);
+  var secret = this.req.secret;
+  var signed = options.signed;
+  if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies');
+  if ('number' == typeof val) val = val.toString();
+  if ('object' == typeof val) val = 'j:' + JSON.stringify(val);
+  if (signed) val = 's:' + sign(val, secret);
+  if ('maxAge' in options) {
+    options.expires = new Date(Date.now() + options.maxAge);
+    options.maxAge /= 1000;
+  }
+  if (null == options.path) options.path = '/';
+  this.set('Set-Cookie', cookie.serialize(name, String(val), options));
+  return this;
+};
+
+
+/**
+ * Set the location header to `url`.
+ *
+ * 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 "/".
+ *
+ * Examples:
+ *
+ *    res.location('/foo/bar').;
+ *    res.location('http://example.com');
+ *    res.location('../login'); // /blog/post/1 -> /blog/login
+ *
+ * Mounting:
+ *
+ *   When an application is mounted and `res.location()`
+ *   is given a path that does _not_ lead with "/" it becomes
+ *   relative to the mount-point. For example if the application
+ *   is mounted at "/blog", the following would become "/blog/login".
+ *
+ *      res.location('login');
+ *
+ *   While the leading slash would result in a location of "/login":
+ *
+ *      res.location('/login');
+ *
+ * @param {String} url
+ * @api public
+ */
+
+res.location = function(url){
+  var app = this.app
+    , req = this.req;
+
+  // setup redirect map
+  var map = { back: req.get('Referrer') || '/' };
+
+  // perform redirect
+  url = map[url] || url;
+
+  // relative
+  if (!~url.indexOf('://') && 0 != url.indexOf('//')) {
+    var path
+
+    // relative to path
+    if ('.' == url[0]) {
+      path = req.originalUrl.split('?')[0]
+      url =  path + ('/' == path[path.length - 1] ? '' : '/') + url;
+      // relative to mount-point
+    } else if ('/' != url[0]) {
+      path = app.path();
+      url = path + '/' + url;
+    }
+  }
+
+  // Respond
+  this.set('Location', url);
+  return this;
+};
+
+/**
+ * Redirect to the given `url` with optional response `status`
+ * defaulting to 302.
+ *
+ * The resulting `url` is determined by `res.location()`, so
+ * it will play nicely with mounted apps, relative paths,
+ * `"back"` etc.
+ *
+ * Examples:
+ *
+ *    res.redirect('/foo/bar');
+ *    res.redirect('http://example.com');
+ *    res.redirect(301, 'http://example.com');
+ *    res.redirect('http://example.com', 301);
+ *    res.redirect('../login'); // /blog/post/1 -> /blog/login
+ *
+ * @param {String} url
+ * @param {Number} code
+ * @api public
+ */
+
+res.redirect = function(url){
+  var app = this.app
+    , head = 'HEAD' == this.req.method
+    , status = 302
+    , body;
+
+  // allow status / url
+  if (2 == arguments.length) {
+    if ('number' == typeof url) {
+      status = url;
+      url = arguments[1];
+    } else {
+      status = arguments[1];
+    }
+  }
+
+  // Set location header
+  this.location(url);
+  url = this.get('Location');
+
+  // Support text/{plain,html} by default
+  this.format({
+    text: function(){
+      body = statusCodes[status] + '. Redirecting to ' + encodeURI(url);
+    },
+
+    html: function(){
+      var u = utils.escape(url);
+      body = '<p>' + statusCodes[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>';
+    },
+
+    default: function(){
+      body = '';
+    }
+  });
+
+  // Respond
+  this.statusCode = status;
+  this.set('Content-Length', Buffer.byteLength(body));
+  this.end(head ? null : body);
+};
+
+/**
+ * Render `view` with the given `options` and optional callback `fn`.
+ * When a callback function is given a response will _not_ be made
+ * automatically, otherwise a response of _200_ and _text/html_ is given.
+ *
+ * Options:
+ *
+ *  - `cache`     boolean hinting to the engine it should cache
+ *  - `filename`  filename of the view being rendered
+ *
+ * @param  {String} view
+ * @param  {Object|Function} options or callback function
+ * @param  {Function} fn
+ * @api public
+ */
+
+res.render = function(view, options, fn){
+  var self = this
+    , options = options || {}
+    , req = this.req
+    , app = req.app;
+
+  // support callback function as second arg
+  if ('function' == typeof options) {
+    fn = options, options = {};
+  }
+
+  // merge res.locals
+  options._locals = self.locals;
+
+  // default callback to respond
+  fn = fn || function(err, str){
+    if (err) return req.next(err);
+    self.send(str);
+  };
+
+  // render
+  app.render(view, options, fn);
+};
Index: Dev/trunk/src/node_modules/express/lib/router/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/lib/router/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/lib/router/index.js	(revision 484)
@@ -0,0 +1,273 @@
+/**
+ * Module dependencies.
+ */
+
+var Route = require('./route')
+  , utils = require('../utils')
+  , methods = require('methods')
+  , debug = require('debug')('express:router')
+  , parse = require('connect').utils.parseUrl;
+
+/**
+ * Expose `Router` constructor.
+ */
+
+exports = module.exports = Router;
+
+/**
+ * Initialize a new `Router` with the given `options`.
+ *
+ * @param {Object} options
+ * @api private
+ */
+
+function Router(options) {
+  options = options || {};
+  var self = this;
+  this.map = {};
+  this.params = {};
+  this._params = [];
+  this.caseSensitive = options.caseSensitive;
+  this.strict = options.strict;
+  this.middleware = function router(req, res, next){
+    self._dispatch(req, res, next);
+  };
+}
+
+/**
+ * Register a param callback `fn` for the given `name`.
+ *
+ * @param {String|Function} name
+ * @param {Function} fn
+ * @return {Router} for chaining
+ * @api public
+ */
+
+Router.prototype.param = function(name, fn){
+  // param logic
+  if ('function' == typeof name) {
+    this._params.push(name);
+    return;
+  }
+
+  // apply param functions
+  var params = this._params
+    , len = params.length
+    , ret;
+
+  for (var i = 0; i < len; ++i) {
+    if (ret = params[i](name, fn)) {
+      fn = ret;
+    }
+  }
+
+  // ensure we end up with a
+  // middleware function
+  if ('function' != typeof fn) {
+    throw new Error('invalid param() call for ' + name + ', got ' + fn);
+  }
+
+  (this.params[name] = this.params[name] || []).push(fn);
+  return this;
+};
+
+/**
+ * Route dispatcher aka the route "middleware".
+ *
+ * @param {IncomingMessage} req
+ * @param {ServerResponse} res
+ * @param {Function} next
+ * @api private
+ */
+
+Router.prototype._dispatch = function(req, res, next){
+  var params = this.params
+    , self = this;
+
+  debug('dispatching %s %s (%s)', req.method, req.url, req.originalUrl);
+
+  // route dispatch
+  (function pass(i, err){
+    var paramCallbacks
+      , paramIndex = 0
+      , paramVal
+      , route
+      , keys
+      , key;
+
+    // match next route
+    function nextRoute(err) {
+      pass(req._route_index + 1, err);
+    }
+
+    // match route
+    req.route = route = self.matchRequest(req, i);
+
+    // no route
+    if (!route) return next(err);
+    debug('matched %s %s', route.method, route.path);
+
+    // we have a route
+    // start at param 0
+    req.params = route.params;
+    keys = route.keys;
+    i = 0;
+
+    // param callbacks
+    function param(err) {
+      paramIndex = 0;
+      key = keys[i++];
+      paramVal = key && req.params[key.name];
+      paramCallbacks = key && params[key.name];
+
+      try {
+        if ('route' == err) {
+          nextRoute();
+        } else if (err) {
+          i = 0;
+          callbacks(err);
+        } else if (paramCallbacks && undefined !== paramVal) {
+          paramCallback();
+        } else if (key) {
+          param();
+        } else {
+          i = 0;
+          callbacks();
+        }
+      } catch (err) {
+        param(err);
+      }
+    };
+
+    param(err);
+
+    // single param callbacks
+    function paramCallback(err) {
+      var fn = paramCallbacks[paramIndex++];
+      if (err || !fn) return param(err);
+      fn(req, res, paramCallback, paramVal, key.name);
+    }
+
+    // invoke route callbacks
+    function callbacks(err) {
+      var fn = route.callbacks[i++];
+      try {
+        if ('route' == err) {
+          nextRoute();
+        } else if (err && fn) {
+          if (fn.length < 4) return callbacks(err);
+          fn(err, req, res, callbacks);
+        } else if (fn) {
+          if (fn.length < 4) return fn(req, res, callbacks);
+          callbacks();
+        } else {
+          nextRoute(err);
+        }
+      } catch (err) {
+        callbacks(err);
+      }
+    }
+  })(0);
+};
+
+/**
+ * Attempt to match a route for `req`
+ * with optional starting index of `i`
+ * defaulting to 0.
+ *
+ * @param {IncomingMessage} req
+ * @param {Number} i
+ * @return {Route}
+ * @api private
+ */
+
+Router.prototype.matchRequest = function(req, i, head){
+  var method = req.method.toLowerCase()
+    , url = parse(req)
+    , path = url.pathname
+    , routes = this.map
+    , i = i || 0
+    , route;
+
+  // HEAD support
+  if (!head && 'head' == method) {
+    route = this.matchRequest(req, i, true);
+    if (route) return route;
+     method = 'get';
+  }
+
+  // routes for this method
+  if (routes = routes[method]) {
+
+    // matching routes
+    for (var len = routes.length; i < len; ++i) {
+      route = routes[i];
+      if (route.match(path)) {
+        req._route_index = i;
+        return route;
+      }
+    }
+  }
+};
+
+/**
+ * Attempt to match a route for `method`
+ * and `url` with optional starting
+ * index of `i` defaulting to 0.
+ *
+ * @param {String} method
+ * @param {String} url
+ * @param {Number} i
+ * @return {Route}
+ * @api private
+ */
+
+Router.prototype.match = function(method, url, i, head){
+  var req = { method: method, url: url };
+  return  this.matchRequest(req, i, head);
+};
+
+/**
+ * Route `method`, `path`, and one or more callbacks.
+ *
+ * @param {String} method
+ * @param {String} path
+ * @param {Function} callback...
+ * @return {Router} for chaining
+ * @api private
+ */
+
+Router.prototype.route = function(method, path, callbacks){
+  var method = method.toLowerCase()
+    , callbacks = utils.flatten([].slice.call(arguments, 2));
+
+  // ensure path was given
+  if (!path) throw new Error('Router#' + method + '() requires a path');
+
+  // ensure all callbacks are functions
+  callbacks.forEach(function(fn, i){
+    if ('function' == typeof fn) return;
+    var type = {}.toString.call(fn);
+    var msg = '.' + method + '() requires callback functions but got a ' + type;
+    throw new Error(msg);
+  });
+
+  // create the route
+  debug('defined %s %s', method, path);
+  var route = new Route(method, path, callbacks, {
+    sensitive: this.caseSensitive,
+    strict: this.strict
+  });
+
+  // add it
+  (this.map[method] = this.map[method] || []).push(route);
+  return this;
+};
+
+methods.forEach(function(method){
+  Router.prototype[method] = function(path){
+    var args = [method].concat([].slice.call(arguments));
+    this.route.apply(this, args);
+    return this;
+  };
+});
Index: Dev/trunk/src/node_modules/express/lib/router/route.js
===================================================================
--- Dev/trunk/src/node_modules/express/lib/router/route.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/lib/router/route.js	(revision 484)
@@ -0,0 +1,72 @@
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils');
+
+/**
+ * Expose `Route`.
+ */
+
+module.exports = Route;
+
+/**
+ * Initialize `Route` with the given HTTP `method`, `path`,
+ * and an array of `callbacks` and `options`.
+ *
+ * Options:
+ *
+ *   - `sensitive`    enable case-sensitive routes
+ *   - `strict`       enable strict matching for trailing slashes
+ *
+ * @param {String} method
+ * @param {String} path
+ * @param {Array} callbacks
+ * @param {Object} options.
+ * @api private
+ */
+
+function Route(method, path, callbacks, options) {
+  options = options || {};
+  this.path = path;
+  this.method = method;
+  this.callbacks = callbacks;
+  this.regexp = utils.pathRegexp(path
+    , this.keys = []
+    , options.sensitive
+    , options.strict);
+}
+
+/**
+ * Check if this route matches `path`, if so
+ * populate `.params`.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api private
+ */
+
+Route.prototype.match = function(path){
+  var keys = this.keys
+    , params = this.params = []
+    , m = this.regexp.exec(path);
+
+  if (!m) return false;
+
+  for (var i = 1, len = m.length; i < len; ++i) {
+    var key = keys[i - 1];
+
+    var val = 'string' == typeof m[i]
+      ? decodeURIComponent(m[i])
+      : m[i];
+
+    if (key) {
+      params[key.name] = val;
+    } else {
+      params.push(val);
+    }
+  }
+
+  return true;
+};
Index: Dev/trunk/src/node_modules/express/lib/utils.js
===================================================================
--- Dev/trunk/src/node_modules/express/lib/utils.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/lib/utils.js	(revision 484)
@@ -0,0 +1,313 @@
+
+/**
+ * Module dependencies.
+ */
+
+var mime = require('connect').mime
+  , crc32 = require('buffer-crc32');
+
+/**
+ * toString ref.
+ */
+
+var toString = {}.toString;
+
+/**
+ * Return ETag for `body`.
+ *
+ * @param {String|Buffer} body
+ * @return {String}
+ * @api private
+ */
+
+exports.etag = function(body){
+  return '"' + crc32.signed(body) + '"';
+};
+
+/**
+ * Make `locals()` bound to the given `obj`.
+ *
+ * This is used for `app.locals` and `res.locals`.
+ *
+ * @param {Object} obj
+ * @return {Function}
+ * @api private
+ */
+
+exports.locals = function(obj){
+  function locals(obj){
+    for (var key in obj) locals[key] = obj[key];
+    return obj;
+  };
+
+  return locals;
+};
+
+/**
+ * Check if `path` looks absolute.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.isAbsolute = function(path){
+  if ('/' == path[0]) return true;
+  if (':' == path[1] && '\\' == path[2]) return true;
+};
+
+/**
+ * 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;
+};
+
+/**
+ * Normalize the given `type`, for example "html" becomes "text/html".
+ *
+ * @param {String} type
+ * @return {Object}
+ * @api private
+ */
+
+exports.normalizeType = function(type){
+  return ~type.indexOf('/')
+    ? acceptParams(type)
+    : { value: mime.lookup(type), params: {} };
+};
+
+/**
+ * Normalize `types`, for example "html" becomes "text/html".
+ *
+ * @param {Array} types
+ * @return {Array}
+ * @api private
+ */
+
+exports.normalizeTypes = function(types){
+  var ret = [];
+
+  for (var i = 0; i < types.length; ++i) {
+    ret.push(exports.normalizeType(types[i]));
+  }
+
+  return ret;
+};
+
+/**
+ * Return the acceptable type in `types`, if any.
+ *
+ * @param {Array} types
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.acceptsArray = function(types, str){
+  // accept anything when Accept is not present
+  if (!str) return types[0];
+
+  // parse
+  var accepted = exports.parseAccept(str)
+    , normalized = exports.normalizeTypes(types)
+    , len = accepted.length;
+
+  for (var i = 0; i < len; ++i) {
+    for (var j = 0, jlen = types.length; j < jlen; ++j) {
+      if (exports.accept(normalized[j], accepted[i])) {
+        return types[j];
+      }
+    }
+  }
+};
+
+/**
+ * Check if `type(s)` are acceptable based on
+ * the given `str`.
+ *
+ * @param {String|Array} type(s)
+ * @param {String} str
+ * @return {Boolean|String}
+ * @api private
+ */
+
+exports.accepts = function(type, str){
+  if ('string' == typeof type) type = type.split(/ *, */);
+  return exports.acceptsArray(type, str);
+};
+
+/**
+ * Check if `type` array is acceptable for `other`.
+ *
+ * @param {Object} type
+ * @param {Object} other
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.accept = function(type, other){
+  var t = type.value.split('/');
+  return (t[0] == other.type || '*' == other.type)
+    && (t[1] == other.subtype || '*' == other.subtype)
+    && paramsEqual(type.params, other.params);
+};
+
+/**
+ * Check if accept params are equal.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Boolean}
+ * @api private
+ */
+
+function paramsEqual(a, b){
+  return !Object.keys(a).some(function(k) {
+    return a[k] != b[k];
+  });
+}
+
+/**
+ * Parse accept `str`, returning
+ * an array objects containing
+ * `.type` and `.subtype` along
+ * with the values provided by
+ * `parseQuality()`.
+ *
+ * @param {Type} name
+ * @return {Type}
+ * @api private
+ */
+
+exports.parseAccept = function(str){
+  return exports
+    .parseParams(str)
+    .map(function(obj){
+      var parts = obj.value.split('/');
+      obj.type = parts[0];
+      obj.subtype = parts[1];
+      return obj;
+    });
+};
+
+/**
+ * Parse quality `str`, returning an
+ * array of objects with `.value`,
+ * `.quality` and optional `.params`
+ *
+ * @param {String} str
+ * @return {Array}
+ * @api private
+ */
+
+exports.parseParams = function(str){
+  return str
+    .split(/ *, */)
+    .map(acceptParams)
+    .filter(function(obj){
+      return obj.quality;
+    })
+    .sort(function(a, b){
+      if (a.quality === b.quality) {
+        return a.originalIndex - b.originalIndex;
+      } else {
+        return b.quality - a.quality;
+      }
+    });
+};
+
+/**
+ * Parse accept params `str` returning an
+ * object with `.value`, `.quality` and `.params`.
+ * also includes `.originalIndex` for stable sorting
+ *
+ * @param {String} str
+ * @return {Object}
+ * @api private
+ */
+
+function acceptParams(str, index) {
+  var parts = str.split(/ *; */);
+  var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
+
+  for (var i = 1; i < parts.length; ++i) {
+    var pms = parts[i].split(/ *= */);
+    if ('q' == pms[0]) {
+      ret.quality = parseFloat(pms[1]);
+    } else {
+      ret.params[pms[0]] = pms[1];
+    }
+  }
+
+  return ret;
+}
+
+/**
+ * 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;');
+};
+
+/**
+ * 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|Array} path
+ * @param  {Array} keys
+ * @param  {Boolean} sensitive
+ * @param  {Boolean} strict
+ * @return {RegExp}
+ * @api private
+ */
+
+exports.pathRegexp = function(path, keys, sensitive, strict) {
+  if (toString.call(path) == '[object RegExp]') return path;
+  if (Array.isArray(path)) path = '(' + path.join('|') + ')';
+  path = path
+    .concat(strict ? '' : '/?')
+    .replace(/\/\(/g, '(?:/')
+    .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){
+      keys.push({ name: key, optional: !! optional });
+      slash = slash || '';
+      return ''
+        + (optional ? '' : slash)
+        + '(?:'
+        + (optional ? slash : '')
+        + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')'
+        + (optional || '')
+        + (star ? '(/*)?' : '');
+    })
+    .replace(/([\/.])/g, '\\$1')
+    .replace(/\*/g, '(.*)');
+  return new RegExp('^' + path + '$', sensitive ? '' : 'i');
+}
Index: Dev/trunk/src/node_modules/express/lib/view.js
===================================================================
--- Dev/trunk/src/node_modules/express/lib/view.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/lib/view.js	(revision 484)
@@ -0,0 +1,77 @@
+/**
+ * Module dependencies.
+ */
+
+var path = require('path')
+  , fs = require('fs')
+  , utils = require('./utils')
+  , dirname = path.dirname
+  , basename = path.basename
+  , extname = path.extname
+  , exists = fs.existsSync || path.existsSync
+  , join = path.join;
+
+/**
+ * Expose `View`.
+ */
+
+module.exports = View;
+
+/**
+ * Initialize a new `View` with the given `name`.
+ *
+ * Options:
+ *
+ *   - `defaultEngine` the default template engine name
+ *   - `engines` template engine require() cache
+ *   - `root` root path for view lookup
+ *
+ * @param {String} name
+ * @param {Object} options
+ * @api private
+ */
+
+function View(name, options) {
+  options = options || {};
+  this.name = name;
+  this.root = options.root;
+  var engines = options.engines;
+  this.defaultEngine = options.defaultEngine;
+  var ext = this.ext = extname(name);
+  if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.');
+  if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine);
+  this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express);
+  this.path = this.lookup(name);
+}
+
+/**
+ * Lookup view by the given `path`
+ *
+ * @param {String} path
+ * @return {String}
+ * @api private
+ */
+
+View.prototype.lookup = function(path){
+  var ext = this.ext;
+
+  // <path>.<engine>
+  if (!utils.isAbsolute(path)) path = join(this.root, path);
+  if (exists(path)) return path;
+
+  // <path>/index.<engine>
+  path = join(dirname(path), basename(path, ext), 'index' + ext);
+  if (exists(path)) return path;
+};
+
+/**
+ * Render with the given `options` and callback `fn(err, str)`.
+ *
+ * @param {Object} options
+ * @param {Function} fn
+ * @api private
+ */
+
+View.prototype.render = function(options, fn){
+  this.engine(this.path, options, fn);
+};
Index: Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/.npmignore	(revision 484)
@@ -0,0 +1,1 @@
+node_modules
Index: Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/.travis.yml	(revision 484)
@@ -0,0 +1,8 @@
+language: node_js
+node_js:
+  - 0.6
+  - 0.8
+notifications:
+  email:
+    recipients:
+      - brianloveswords@gmail.com
Index: Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/README.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/README.md	(revision 484)
@@ -0,0 +1,47 @@
+# buffer-crc32
+
+[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32)
+
+crc32 that works with binary data and fancy character sets, outputs
+buffer, signed or unsigned data and has tests.
+
+Derived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix
+
+# install
+```
+npm install buffer-crc32
+```
+
+# example
+```js
+var crc32 = require('buffer-crc32');
+// works with buffers
+var buf = Buffer([0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00])
+crc32(buf) // -> <Buffer 94 5a ab 4a>
+
+// has convenience methods for getting signed or unsigned ints
+crc32.signed(buf) // -> -1805997238
+crc32.unsigned(buf) // -> 2488970058
+
+// will cast to buffer if given a string, so you can
+// directly use foreign characters safely
+crc32('èªåè²©å£²æ©') // -> <Buffer cb 03 1a c5>
+
+// and works in append mode too
+var partialCrc = crc32('hey');
+var partialCrc = crc32(' ', partialCrc);
+var partialCrc = crc32('sup', partialCrc);
+var partialCrc = crc32(' ', partialCrc);
+var finalCrc = crc32('bros', partialCrc); // -> <Buffer 47 fa 55 70>
+```
+
+# tests
+This was tested against the output of zlib's crc32 method. You can run
+the tests with`npm test` (requires tap)
+
+# see also
+https://github.com/alexgorbatchev/node-crc, `crc.buffer.crc32` also
+supports buffer inputs and return unsigned ints (thanks @tjholowaychuk).
+
+# license
+MIT/X11
Index: Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/index.js	(revision 484)
@@ -0,0 +1,88 @@
+var Buffer = require('buffer').Buffer;
+
+var CRC_TABLE = [
+  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+  0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+  0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+  0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+  0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+  0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+  0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+  0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+  0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+  0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+  0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+  0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+  0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+  0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+  0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+  0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+  0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+  0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+  0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+  0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+  0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+  0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+  0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+  0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+  0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+  0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+  0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+  0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+  0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+  0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+  0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+  0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+  0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+  0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+  0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+  0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+  0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+  0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+  0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+  0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+  0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+  0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+  0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+  0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+  0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+  0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+  0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+  0x2d02ef8d
+];
+
+function bufferizeInt(num) {
+  var tmp = Buffer(4);
+  tmp.writeInt32BE(num, 0);
+  return tmp;
+}
+
+function _crc32(buf, previous) {
+  if (!Buffer.isBuffer(buf)) {
+    buf = Buffer(buf);
+  }
+  if (Buffer.isBuffer(previous)) {
+    previous = previous.readUInt32BE(0);
+  }
+  var crc = ~~previous ^ -1;
+  for (var n = 0; n < buf.length; n++) {
+    crc = CRC_TABLE[(crc ^ buf[n]) & 0xff] ^ (crc >>> 8);
+  }
+  return (crc ^ -1);
+}
+
+function crc32() {
+  return bufferizeInt(_crc32.apply(null, arguments));
+}
+crc32.signed = function () {
+  return _crc32.apply(null, arguments);
+};
+crc32.unsigned = function () {
+  return _crc32.apply(null, arguments) >>> 0;
+};
+
+module.exports = crc32;
Index: Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/package.json	(revision 484)
@@ -0,0 +1,39 @@
+{
+  "author": {
+    "name": "Brian J. Brennan",
+    "email": "brianloveswords@gmail.com",
+    "url": "http://bjb.io"
+  },
+  "name": "buffer-crc32",
+  "description": "A pure javascript CRC32 algorithm that plays nice with binary data",
+  "version": "0.2.1",
+  "contributors": [
+    {
+      "name": "Vladimir Kuznetsov"
+    }
+  ],
+  "homepage": "https://github.com/brianloveswords/buffer-crc32",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/brianloveswords/buffer-crc32.git"
+  },
+  "main": "index.js",
+  "scripts": {
+    "test": "./node_modules/.bin/tap tests/*.test.js"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "tap": "~0.2.5"
+  },
+  "optionalDependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "readme": "# buffer-crc32\n\n[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32)\n\ncrc32 that works with binary data and fancy character sets, outputs\nbuffer, signed or unsigned data and has tests.\n\nDerived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix\n\n# install\n```\nnpm install buffer-crc32\n```\n\n# example\n```js\nvar crc32 = require('buffer-crc32');\n// works with buffers\nvar buf = Buffer([0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00])\ncrc32(buf) // -> <Buffer 94 5a ab 4a>\n\n// has convenience methods for getting signed or unsigned ints\ncrc32.signed(buf) // -> -1805997238\ncrc32.unsigned(buf) // -> 2488970058\n\n// will cast to buffer if given a string, so you can\n// directly use foreign characters safely\ncrc32('èªåè²©å£²æ©') // -> <Buffer cb 03 1a c5>\n\n// and works in append mode too\nvar partialCrc = crc32('hey');\nvar partialCrc = crc32(' ', partialCrc);\nvar partialCrc = crc32('sup', partialCrc);\nvar partialCrc = crc32(' ', partialCrc);\nvar finalCrc = crc32('bros', partialCrc); // -> <Buffer 47 fa 55 70>\n```\n\n# tests\nThis was tested against the output of zlib's crc32 method. You can run\nthe tests with`npm test` (requires tap)\n\n# see also\nhttps://github.com/alexgorbatchev/node-crc, `crc.buffer.crc32` also\nsupports buffer inputs and return unsigned ints (thanks @tjholowaychuk).\n\n# license\nMIT/X11\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/brianloveswords/buffer-crc32/issues"
+  },
+  "_id": "buffer-crc32@0.2.1",
+  "_from": "buffer-crc32@0.2.1"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/tests/crc.test.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/tests/crc.test.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/buffer-crc32/tests/crc.test.js	(revision 484)
@@ -0,0 +1,89 @@
+var crc32 = require('..');
+var test = require('tap').test;
+
+test('simple crc32 is no problem', function (t) {
+  var input = Buffer('hey sup bros');
+  var expected = Buffer([0x47, 0xfa, 0x55, 0x70]);
+  t.same(crc32(input), expected);
+  t.end();
+});
+
+test('another simple one', function (t) {
+  var input = Buffer('IEND');
+  var expected = Buffer([0xae, 0x42, 0x60, 0x82]);
+  t.same(crc32(input), expected);
+  t.end();
+});
+
+test('slightly more complex', function (t) {
+  var input = Buffer([0x00, 0x00, 0x00]);
+  var expected = Buffer([0xff, 0x41, 0xd9, 0x12]);
+  t.same(crc32(input), expected);
+  t.end();
+});
+
+test('complex crc32 gets calculated like a champ', function (t) {
+  var input = Buffer('à€¶à¥à€°à¥à€·à€');
+  var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]);
+  t.same(crc32(input), expected);
+  t.end();
+});
+
+test('casts to buffer if necessary', function (t) {
+  var input = 'à€¶à¥à€°à¥à€·à€';
+  var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]);
+  t.same(crc32(input), expected);
+  t.end();
+});
+
+test('can do signed', function (t) {
+  var input = 'ham sandwich';
+  var expected = -1891873021;
+  t.same(crc32.signed(input), expected);
+  t.end();
+});
+
+test('can do unsigned', function (t) {
+  var input = 'bear sandwich';
+  var expected = 3711466352;
+  t.same(crc32.unsigned(input), expected);
+  t.end();
+});
+
+
+test('simple crc32 in append mode', function (t) {
+  var input = [Buffer('hey'), Buffer(' '), Buffer('sup'), Buffer(' '), Buffer('bros')];
+  var expected = Buffer([0x47, 0xfa, 0x55, 0x70]);
+  for (var crc = 0, i = 0; i < input.length; i++) {
+    crc = crc32(input[i], crc);
+  }
+  t.same(crc, expected);
+  t.end();
+});
+
+
+test('can do signed in append mode', function (t) {
+  var input1 = 'ham';
+  var input2 = ' ';
+  var input3 = 'sandwich';
+  var expected = -1891873021;
+
+  var crc = crc32.signed(input1);
+  crc = crc32.signed(input2, crc);
+  crc = crc32.signed(input3, crc);
+
+  t.same(crc, expected);
+  t.end();
+});
+
+test('can do unsigned in append mode', function (t) {
+  var input1 = 'bear san';
+  var input2 = 'dwich';
+  var expected = 3711466352;
+
+  var crc = crc32.unsigned(input1);
+  crc = crc32.unsigned(input2, crc);
+  t.same(crc, expected);
+  t.end();
+});
+
Index: Dev/trunk/src/node_modules/express/node_modules/commander/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/commander/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/commander/.npmignore	(revision 484)
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
Index: Dev/trunk/src/node_modules/express/node_modules/commander/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/commander/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/commander/.travis.yml	(revision 484)
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.4
+  - 0.6
Index: Dev/trunk/src/node_modules/express/node_modules/commander/History.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/commander/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/commander/History.md	(revision 484)
@@ -0,0 +1,107 @@
+
+0.6.1 / 2012-06-01 
+==================
+
+  * Added: append (yes or no) on confirmation
+  * Added: allow node.js v0.7.x
+
+0.6.0 / 2012-04-10 
+==================
+
+  * Added `.prompt(obj, callback)` support. Closes #49
+  * Added default support to .choose(). Closes #41
+  * Fixed the choice example
+
+0.5.1 / 2011-12-20 
+==================
+
+  * Fixed `password()` for recent nodes. Closes #36
+
+0.5.0 / 2011-12-04 
+==================
+
+  * Added sub-command option support [itay]
+
+0.4.3 / 2011-12-04 
+==================
+
+  * Fixed custom help ordering. Closes #32
+
+0.4.2 / 2011-11-24 
+==================
+
+  * Added travis support
+  * Fixed: line-buffered input automatically trimmed. Closes #31
+
+0.4.1 / 2011-11-18 
+==================
+
+  * Removed listening for "close" on --help
+
+0.4.0 / 2011-11-15 
+==================
+
+  * Added support for `--`. Closes #24
+
+0.3.3 / 2011-11-14 
+==================
+
+  * Fixed: wait for close event when writing help info [Jerry Hamlet]
+
+0.3.2 / 2011-11-01 
+==================
+
+  * Fixed long flag definitions with values [felixge]
+
+0.3.1 / 2011-10-31 
+==================
+
+  * Changed `--version` short flag to `-V` from `-v`
+  * Changed `.version()` so it's configurable [felixge]
+
+0.3.0 / 2011-10-31 
+==================
+
+  * Added support for long flags only. Closes #18
+
+0.2.1 / 2011-10-24 
+==================
+
+  * "node": ">= 0.4.x < 0.7.0". Closes #20
+
+0.2.0 / 2011-09-26 
+==================
+
+  * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs]
+
+0.1.0 / 2011-08-24 
+==================
+
+  * Added support for custom `--help` output
+
+0.0.5 / 2011-08-18 
+==================
+
+  * Changed: when the user enters nothing prompt for password again
+  * Fixed issue with passwords beginning with numbers [NuckChorris]
+
+0.0.4 / 2011-08-15 
+==================
+
+  * Fixed `Commander#args`
+
+0.0.3 / 2011-08-15 
+==================
+
+  * Added default option value support
+
+0.0.2 / 2011-08-15 
+==================
+
+  * Added mask support to `Command#password(str[, mask], fn)`
+  * Added `Command#password(str, fn)`
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
Index: Dev/trunk/src/node_modules/express/node_modules/commander/Makefile
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/commander/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/commander/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+
+TESTS = $(shell find test/test.*.js)
+
+test:
+	@./test/run $(TESTS)
+
+.PHONY: test
Index: Dev/trunk/src/node_modules/express/node_modules/commander/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/commander/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/commander/Readme.md	(revision 484)
@@ -0,0 +1,262 @@
+# Commander.js
+
+  The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).
+
+ [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)
+
+## Installation
+
+    $ npm install commander
+
+## Option parsing
+
+ Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.
+
+```js
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var program = require('commander');
+
+program
+  .version('0.0.1')
+  .option('-p, --peppers', 'Add peppers')
+  .option('-P, --pineapple', 'Add pineapple')
+  .option('-b, --bbq', 'Add bbq sauce')
+  .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')
+  .parse(process.argv);
+
+console.log('you ordered a pizza with:');
+if (program.peppers) console.log('  - peppers');
+if (program.pineapple) console.log('  - pineappe');
+if (program.bbq) console.log('  - bbq');
+console.log('  - %s cheese', program.cheese);
+```
+
+ Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc.
+
+## Automated --help
+
+ The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:
+
+```  
+ $ ./examples/pizza --help
+
+   Usage: pizza [options]
+
+   Options:
+
+     -V, --version        output the version number
+     -p, --peppers        Add peppers
+     -P, --pineapple      Add pineappe
+     -b, --bbq            Add bbq sauce
+     -c, --cheese <type>  Add the specified type of cheese [marble]
+     -h, --help           output usage information
+
+```
+
+## Coercion
+
+```js
+function range(val) {
+  return val.split('..').map(Number);
+}
+
+function list(val) {
+  return val.split(',');
+}
+
+program
+  .version('0.0.1')
+  .usage('[options] <file ...>')
+  .option('-i, --integer <n>', 'An integer argument', parseInt)
+  .option('-f, --float <n>', 'A float argument', parseFloat)
+  .option('-r, --range <a>..<b>', 'A range', range)
+  .option('-l, --list <items>', 'A list', list)
+  .option('-o, --optional [value]', 'An optional value')
+  .parse(process.argv);
+
+console.log(' int: %j', program.integer);
+console.log(' float: %j', program.float);
+console.log(' optional: %j', program.optional);
+program.range = program.range || [];
+console.log(' range: %j..%j', program.range[0], program.range[1]);
+console.log(' list: %j', program.list);
+console.log(' args: %j', program.args);
+```
+
+## Custom help
+
+ You can display arbitrary `-h, --help` information
+ by listening for "--help". Commander will automatically
+ exit once you are done so that the remainder of your program
+ does not execute causing undesired behaviours, for example
+ in the following executable "stuff" will not output when
+ `--help` is used.
+
+```js
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var program = require('../');
+
+function list(val) {
+  return val.split(',').map(Number);
+}
+
+program
+  .version('0.0.1')
+  .option('-f, --foo', 'enable some foo')
+  .option('-b, --bar', 'enable some bar')
+  .option('-B, --baz', 'enable some baz');
+
+// must be before .parse() since
+// node's emit() is immediate
+
+program.on('--help', function(){
+  console.log('  Examples:');
+  console.log('');
+  console.log('    $ custom-help --help');
+  console.log('    $ custom-help -h');
+  console.log('');
+});
+
+program.parse(process.argv);
+
+console.log('stuff');
+```
+
+yielding the following help output:
+
+```
+
+Usage: custom-help [options]
+
+Options:
+
+  -h, --help     output usage information
+  -V, --version  output the version number
+  -f, --foo      enable some foo
+  -b, --bar      enable some bar
+  -B, --baz      enable some baz
+
+Examples:
+
+  $ custom-help --help
+  $ custom-help -h
+
+```
+
+## .prompt(msg, fn)
+
+ Single-line prompt:
+
+```js
+program.prompt('name: ', function(name){
+  console.log('hi %s', name);
+});
+```
+
+ Multi-line prompt:
+
+```js
+program.prompt('description:', function(name){
+  console.log('hi %s', name);
+});
+```
+
+ Coercion:
+
+```js
+program.prompt('Age: ', Number, function(age){
+  console.log('age: %j', age);
+});
+```
+
+```js
+program.prompt('Birthdate: ', Date, function(date){
+  console.log('date: %s', date);
+});
+```
+
+## .password(msg[, mask], fn)
+
+Prompt for password without echoing:
+
+```js
+program.password('Password: ', function(pass){
+  console.log('got "%s"', pass);
+  process.stdin.destroy();
+});
+```
+
+Prompt for password with mask char "*":
+
+```js
+program.password('Password: ', '*', function(pass){
+  console.log('got "%s"', pass);
+  process.stdin.destroy();
+});
+```
+
+## .confirm(msg, fn)
+
+ Confirm with the given `msg`:
+
+```js
+program.confirm('continue? ', function(ok){
+  console.log(' got %j', ok);
+});
+```
+
+## .choose(list, fn)
+
+ Let the user choose from a `list`:
+
+```js
+var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];
+
+console.log('Choose the coolest pet:');
+program.choose(list, function(i){
+  console.log('you chose %d "%s"', i, list[i]);
+});
+```
+
+## Links
+
+ - [API documentation](http://visionmedia.github.com/commander.js/)
+ - [ascii tables](https://github.com/LearnBoost/cli-table)
+ - [progress bars](https://github.com/visionmedia/node-progress)
+ - [more progress bars](https://github.com/substack/node-multimeter)
+ - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 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.
Index: Dev/trunk/src/node_modules/express/node_modules/commander/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/commander/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/commander/index.js	(revision 484)
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/commander');
Index: Dev/trunk/src/node_modules/express/node_modules/commander/lib/commander.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/commander/lib/commander.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/commander/lib/commander.js	(revision 484)
@@ -0,0 +1,1026 @@
+
+/*!
+ * commander
+ * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter
+  , path = require('path')
+  , tty = require('tty')
+  , basename = path.basename;
+
+/**
+ * Expose the root command.
+ */
+
+exports = module.exports = new Command;
+
+/**
+ * Expose `Command`.
+ */
+
+exports.Command = Command;
+
+/**
+ * Expose `Option`.
+ */
+
+exports.Option = Option;
+
+/**
+ * Initialize a new `Option` with the given `flags` and `description`.
+ *
+ * @param {String} flags
+ * @param {String} description
+ * @api public
+ */
+
+function Option(flags, description) {
+  this.flags = flags;
+  this.required = ~flags.indexOf('<');
+  this.optional = ~flags.indexOf('[');
+  this.bool = !~flags.indexOf('-no-');
+  flags = flags.split(/[ ,|]+/);
+  if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift();
+  this.long = flags.shift();
+  this.description = description;
+}
+
+/**
+ * Return option name.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Option.prototype.name = function(){
+  return this.long
+    .replace('--', '')
+    .replace('no-', '');
+};
+
+/**
+ * Check if `arg` matches the short or long flag.
+ *
+ * @param {String} arg
+ * @return {Boolean}
+ * @api private
+ */
+
+Option.prototype.is = function(arg){
+  return arg == this.short
+    || arg == this.long;
+};
+
+/**
+ * Initialize a new `Command`.
+ *
+ * @param {String} name
+ * @api public
+ */
+
+function Command(name) {
+  this.commands = [];
+  this.options = [];
+  this.args = [];
+  this.name = name;
+}
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+Command.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Add command `name`.
+ *
+ * The `.action()` callback is invoked when the
+ * command `name` is specified via __ARGV__,
+ * and the remaining arguments are applied to the
+ * function for access.
+ *
+ * When the `name` is "*" an un-matched command
+ * will be passed as the first arg, followed by
+ * the rest of __ARGV__ remaining.
+ *
+ * Examples:
+ *
+ *      program
+ *        .version('0.0.1')
+ *        .option('-C, --chdir <path>', 'change the working directory')
+ *        .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
+ *        .option('-T, --no-tests', 'ignore test hook')
+ *     
+ *      program
+ *        .command('setup')
+ *        .description('run remote setup commands')
+ *        .action(function(){
+ *          console.log('setup');
+ *        });
+ *     
+ *      program
+ *        .command('exec <cmd>')
+ *        .description('run the given remote command')
+ *        .action(function(cmd){
+ *          console.log('exec "%s"', cmd);
+ *        });
+ *     
+ *      program
+ *        .command('*')
+ *        .description('deploy the given env')
+ *        .action(function(env){
+ *          console.log('deploying "%s"', env);
+ *        });
+ *     
+ *      program.parse(process.argv);
+  *
+ * @param {String} name
+ * @return {Command} the new command
+ * @api public
+ */
+
+Command.prototype.command = function(name){
+  var args = name.split(/ +/);
+  var cmd = new Command(args.shift());
+  this.commands.push(cmd);
+  cmd.parseExpectedArgs(args);
+  cmd.parent = this;
+  return cmd;
+};
+
+/**
+ * Parse expected `args`.
+ *
+ * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`.
+ *
+ * @param {Array} args
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.parseExpectedArgs = function(args){
+  if (!args.length) return;
+  var self = this;
+  args.forEach(function(arg){
+    switch (arg[0]) {
+      case '<':
+        self.args.push({ required: true, name: arg.slice(1, -1) });
+        break;
+      case '[':
+        self.args.push({ required: false, name: arg.slice(1, -1) });
+        break;
+    }
+  });
+  return this;
+};
+
+/**
+ * Register callback `fn` for the command.
+ *
+ * Examples:
+ *
+ *      program
+ *        .command('help')
+ *        .description('display verbose help')
+ *        .action(function(){
+ *           // output help here
+ *        });
+ *
+ * @param {Function} fn
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.action = function(fn){
+  var self = this;
+  this.parent.on(this.name, function(args, unknown){    
+    // Parse any so-far unknown options
+    unknown = unknown || [];
+    var parsed = self.parseOptions(unknown);
+    
+    // Output help if necessary
+    outputHelpIfNecessary(self, parsed.unknown);
+    
+    // If there are still any unknown options, then we simply 
+    // die, unless someone asked for help, in which case we give it
+    // to them, and then we die.
+    if (parsed.unknown.length > 0) {      
+      self.unknownOption(parsed.unknown[0]);
+    }
+    
+    self.args.forEach(function(arg, i){
+      if (arg.required && null == args[i]) {
+        self.missingArgument(arg.name);
+      }
+    });
+    
+    // Always append ourselves to the end of the arguments,
+    // to make sure we match the number of arguments the user
+    // expects
+    if (self.args.length) {
+      args[self.args.length] = self;
+    } else {
+      args.push(self);
+    }
+    
+    fn.apply(this, args);
+  });
+  return this;
+};
+
+/**
+ * Define option with `flags`, `description` and optional
+ * coercion `fn`. 
+ *
+ * The `flags` string should contain both the short and long flags,
+ * separated by comma, a pipe or space. The following are all valid
+ * all will output this way when `--help` is used.
+ *
+ *    "-p, --pepper"
+ *    "-p|--pepper"
+ *    "-p --pepper"
+ *
+ * Examples:
+ *
+ *     // simple boolean defaulting to false
+ *     program.option('-p, --pepper', 'add pepper');
+ *
+ *     --pepper
+ *     program.pepper
+ *     // => Boolean
+ *
+ *     // simple boolean defaulting to false
+ *     program.option('-C, --no-cheese', 'remove cheese');
+ *
+ *     program.cheese
+ *     // => true
+ *
+ *     --no-cheese
+ *     program.cheese
+ *     // => true
+ *
+ *     // required argument
+ *     program.option('-C, --chdir <path>', 'change the working directory');
+ *
+ *     --chdir /tmp
+ *     program.chdir
+ *     // => "/tmp"
+ *
+ *     // optional argument
+ *     program.option('-c, --cheese [type]', 'add cheese [marble]');
+ *
+ * @param {String} flags
+ * @param {String} description
+ * @param {Function|Mixed} fn or default
+ * @param {Mixed} defaultValue
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.option = function(flags, description, fn, defaultValue){
+  var self = this
+    , option = new Option(flags, description)
+    , oname = option.name()
+    , name = camelcase(oname);
+
+  // default as 3rd arg
+  if ('function' != typeof fn) defaultValue = fn, fn = null;
+
+  // preassign default value only for --no-*, [optional], or <required>
+  if (false == option.bool || option.optional || option.required) {
+    // when --no-* we make sure default is true
+    if (false == option.bool) defaultValue = true;
+    // preassign only if we have a default
+    if (undefined !== defaultValue) self[name] = defaultValue;
+  }
+
+  // register the option
+  this.options.push(option);
+
+  // when it's passed assign the value
+  // and conditionally invoke the callback
+  this.on(oname, function(val){
+    // coercion
+    if (null != val && fn) val = fn(val);
+
+    // unassigned or bool
+    if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) {
+      // if no value, bool true, and we have a default, then use it!
+      if (null == val) {
+        self[name] = option.bool
+          ? defaultValue || true
+          : false;
+      } else {
+        self[name] = val;
+      }
+    } else if (null !== val) {
+      // reassign
+      self[name] = val;
+    }
+  });
+
+  return this;
+};
+
+/**
+ * Parse `argv`, settings options and invoking commands when defined.
+ *
+ * @param {Array} argv
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.parse = function(argv){
+  // store raw args
+  this.rawArgs = argv;
+
+  // guess name
+  if (!this.name) this.name = basename(argv[1]);
+
+  // process argv
+  var parsed = this.parseOptions(this.normalize(argv.slice(2)));
+  this.args = parsed.args;
+  return this.parseArgs(this.args, parsed.unknown);
+};
+
+/**
+ * Normalize `args`, splitting joined short flags. For example
+ * the arg "-abc" is equivalent to "-a -b -c".
+ *
+ * @param {Array} args
+ * @return {Array}
+ * @api private
+ */
+
+Command.prototype.normalize = function(args){
+  var ret = []
+    , arg;
+
+  for (var i = 0, len = args.length; i < len; ++i) {
+    arg = args[i];
+    if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) {
+      arg.slice(1).split('').forEach(function(c){
+        ret.push('-' + c);
+      });
+    } else {
+      ret.push(arg);
+    }
+  }
+
+  return ret;
+};
+
+/**
+ * Parse command `args`.
+ *
+ * When listener(s) are available those
+ * callbacks are invoked, otherwise the "*"
+ * event is emitted and those actions are invoked.
+ *
+ * @param {Array} args
+ * @return {Command} for chaining
+ * @api private
+ */
+
+Command.prototype.parseArgs = function(args, unknown){
+  var cmds = this.commands
+    , len = cmds.length
+    , name;
+
+  if (args.length) {
+    name = args[0];
+    if (this.listeners(name).length) {
+      this.emit(args.shift(), args, unknown);
+    } else {
+      this.emit('*', args);
+    }
+  } else {
+    outputHelpIfNecessary(this, unknown);
+    
+    // If there were no args and we have unknown options,
+    // then they are extraneous and we need to error.
+    if (unknown.length > 0) {      
+      this.unknownOption(unknown[0]);
+    }
+  }
+
+  return this;
+};
+
+/**
+ * Return an option matching `arg` if any.
+ *
+ * @param {String} arg
+ * @return {Option}
+ * @api private
+ */
+
+Command.prototype.optionFor = function(arg){
+  for (var i = 0, len = this.options.length; i < len; ++i) {
+    if (this.options[i].is(arg)) {
+      return this.options[i];
+    }
+  }
+};
+
+/**
+ * Parse options from `argv` returning `argv`
+ * void of these options.
+ *
+ * @param {Array} argv
+ * @return {Array}
+ * @api public
+ */
+
+Command.prototype.parseOptions = function(argv){
+  var args = []
+    , len = argv.length
+    , literal
+    , option
+    , arg;
+
+  var unknownOptions = [];
+
+  // parse options
+  for (var i = 0; i < len; ++i) {
+    arg = argv[i];
+
+    // literal args after --
+    if ('--' == arg) {
+      literal = true;
+      continue;
+    }
+
+    if (literal) {
+      args.push(arg);
+      continue;
+    }
+
+    // find matching Option
+    option = this.optionFor(arg);
+
+    // option is defined
+    if (option) {
+      // requires arg
+      if (option.required) {
+        arg = argv[++i];
+        if (null == arg) return this.optionMissingArgument(option);
+        if ('-' == arg[0]) return this.optionMissingArgument(option, arg);
+        this.emit(option.name(), arg);
+      // optional arg
+      } else if (option.optional) {
+        arg = argv[i+1];
+        if (null == arg || '-' == arg[0]) {
+          arg = null;
+        } else {
+          ++i;
+        }
+        this.emit(option.name(), arg);
+      // bool
+      } else {
+        this.emit(option.name());
+      }
+      continue;
+    }
+    
+    // looks like an option
+    if (arg.length > 1 && '-' == arg[0]) {
+      unknownOptions.push(arg);
+      
+      // If the next argument looks like it might be
+      // an argument for this option, we pass it on.
+      // If it isn't, then it'll simply be ignored
+      if (argv[i+1] && '-' != argv[i+1][0]) {
+        unknownOptions.push(argv[++i]);
+      }
+      continue;
+    }
+    
+    // arg
+    args.push(arg);
+  }
+  
+  return { args: args, unknown: unknownOptions };
+};
+
+/**
+ * Argument `name` is missing.
+ *
+ * @param {String} name
+ * @api private
+ */
+
+Command.prototype.missingArgument = function(name){
+  console.error();
+  console.error("  error: missing required argument `%s'", name);
+  console.error();
+  process.exit(1);
+};
+
+/**
+ * `Option` is missing an argument, but received `flag` or nothing.
+ *
+ * @param {String} option
+ * @param {String} flag
+ * @api private
+ */
+
+Command.prototype.optionMissingArgument = function(option, flag){
+  console.error();
+  if (flag) {
+    console.error("  error: option `%s' argument missing, got `%s'", option.flags, flag);
+  } else {
+    console.error("  error: option `%s' argument missing", option.flags);
+  }
+  console.error();
+  process.exit(1);
+};
+
+/**
+ * Unknown option `flag`.
+ *
+ * @param {String} flag
+ * @api private
+ */
+
+Command.prototype.unknownOption = function(flag){
+  console.error();
+  console.error("  error: unknown option `%s'", flag);
+  console.error();
+  process.exit(1);
+};
+
+/**
+ * Set the program version to `str`.
+ *
+ * This method auto-registers the "-V, --version" flag
+ * which will print the version number when passed.
+ *
+ * @param {String} str
+ * @param {String} flags
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.version = function(str, flags){
+  if (0 == arguments.length) return this._version;
+  this._version = str;
+  flags = flags || '-V, --version';
+  this.option(flags, 'output the version number');
+  this.on('version', function(){
+    console.log(str);
+    process.exit(0);
+  });
+  return this;
+};
+
+/**
+ * Set the description `str`.
+ *
+ * @param {String} str
+ * @return {String|Command}
+ * @api public
+ */
+
+Command.prototype.description = function(str){
+  if (0 == arguments.length) return this._description;
+  this._description = str;
+  return this;
+};
+
+/**
+ * Set / get the command usage `str`.
+ *
+ * @param {String} str
+ * @return {String|Command}
+ * @api public
+ */
+
+Command.prototype.usage = function(str){
+  var args = this.args.map(function(arg){
+    return arg.required
+      ? '<' + arg.name + '>'
+      : '[' + arg.name + ']';
+  });
+
+  var usage = '[options'
+    + (this.commands.length ? '] [command' : '')
+    + ']'
+    + (this.args.length ? ' ' + args : '');
+  if (0 == arguments.length) return this._usage || usage;
+  this._usage = str;
+
+  return this;
+};
+
+/**
+ * Return the largest option length.
+ *
+ * @return {Number}
+ * @api private
+ */
+
+Command.prototype.largestOptionLength = function(){
+  return this.options.reduce(function(max, option){
+    return Math.max(max, option.flags.length);
+  }, 0);
+};
+
+/**
+ * Return help for options.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Command.prototype.optionHelp = function(){
+  var width = this.largestOptionLength();
+  
+  // Prepend the help information
+  return [pad('-h, --help', width) + '  ' + 'output usage information']
+    .concat(this.options.map(function(option){
+      return pad(option.flags, width)
+        + '  ' + option.description;
+      }))
+    .join('\n');
+};
+
+/**
+ * Return command help documentation.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Command.prototype.commandHelp = function(){
+  if (!this.commands.length) return '';
+  return [
+      ''
+    , '  Commands:'
+    , ''
+    , this.commands.map(function(cmd){
+      var args = cmd.args.map(function(arg){
+        return arg.required
+          ? '<' + arg.name + '>'
+          : '[' + arg.name + ']';
+      }).join(' ');
+
+      return cmd.name 
+        + (cmd.options.length 
+          ? ' [options]'
+          : '') + ' ' + args
+        + (cmd.description()
+          ? '\n' + cmd.description()
+          : '');
+    }).join('\n\n').replace(/^/gm, '    ')
+    , ''
+  ].join('\n');
+};
+
+/**
+ * Return program help documentation.
+ *
+ * @return {String}
+ * @api private
+ */
+
+Command.prototype.helpInformation = function(){
+  return [
+      ''
+    , '  Usage: ' + this.name + ' ' + this.usage()
+    , '' + this.commandHelp()
+    , '  Options:'
+    , ''
+    , '' + this.optionHelp().replace(/^/gm, '    ')
+    , ''
+    , ''
+  ].join('\n');
+};
+
+/**
+ * Prompt for a `Number`.
+ *
+ * @param {String} str
+ * @param {Function} fn
+ * @api private
+ */
+
+Command.prototype.promptForNumber = function(str, fn){
+  var self = this;
+  this.promptSingleLine(str, function parseNumber(val){
+    val = Number(val);
+    if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber);
+    fn(val);
+  });
+};
+
+/**
+ * Prompt for a `Date`.
+ *
+ * @param {String} str
+ * @param {Function} fn
+ * @api private
+ */
+
+Command.prototype.promptForDate = function(str, fn){
+  var self = this;
+  this.promptSingleLine(str, function parseDate(val){
+    val = new Date(val);
+    if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate);
+    fn(val);
+  });
+};
+
+/**
+ * Single-line prompt.
+ *
+ * @param {String} str
+ * @param {Function} fn
+ * @api private
+ */
+
+Command.prototype.promptSingleLine = function(str, fn){
+  if ('function' == typeof arguments[2]) {
+    return this['promptFor' + (fn.name || fn)](str, arguments[2]);
+  }
+
+  process.stdout.write(str);
+  process.stdin.setEncoding('utf8');
+  process.stdin.once('data', function(val){
+    fn(val.trim());
+  }).resume();
+};
+
+/**
+ * Multi-line prompt.
+ *
+ * @param {String} str
+ * @param {Function} fn
+ * @api private
+ */
+
+Command.prototype.promptMultiLine = function(str, fn){
+  var buf = [];
+  console.log(str);
+  process.stdin.setEncoding('utf8');
+  process.stdin.on('data', function(val){
+    if ('\n' == val || '\r\n' == val) {
+      process.stdin.removeAllListeners('data');
+      fn(buf.join('\n'));
+    } else {
+      buf.push(val.trimRight());
+    }
+  }).resume();
+};
+
+/**
+ * Prompt `str` and callback `fn(val)`
+ *
+ * Commander supports single-line and multi-line prompts.
+ * To issue a single-line prompt simply add white-space
+ * to the end of `str`, something like "name: ", whereas
+ * for a multi-line prompt omit this "description:".
+ *
+ *
+ * Examples:
+ *
+ *     program.prompt('Username: ', function(name){
+ *       console.log('hi %s', name);
+ *     });
+ *     
+ *     program.prompt('Description:', function(desc){
+ *       console.log('description was "%s"', desc.trim());
+ *     });
+ *
+ * @param {String|Object} str
+ * @param {Function} fn
+ * @api public
+ */
+
+Command.prototype.prompt = function(str, fn){
+  var self = this;
+
+  if ('string' == typeof str) {
+    if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments);
+    this.promptMultiLine(str, fn);
+  } else {
+    var keys = Object.keys(str)
+      , obj = {};
+
+    function next() {
+      var key = keys.shift()
+        , label = str[key];
+
+      if (!key) return fn(obj);
+      self.prompt(label, function(val){
+        obj[key] = val;
+        next();
+      });
+    }
+
+    next();
+  }
+};
+
+/**
+ * Prompt for password with `str`, `mask` char and callback `fn(val)`.
+ *
+ * The mask string defaults to '', aka no output is
+ * written while typing, you may want to use "*" etc.
+ *
+ * Examples:
+ *
+ *     program.password('Password: ', function(pass){
+ *       console.log('got "%s"', pass);
+ *       process.stdin.destroy();
+ *     });
+ *
+ *     program.password('Password: ', '*', function(pass){
+ *       console.log('got "%s"', pass);
+ *       process.stdin.destroy();
+ *     });
+ *
+ * @param {String} str
+ * @param {String} mask
+ * @param {Function} fn
+ * @api public
+ */
+
+Command.prototype.password = function(str, mask, fn){
+  var self = this
+    , buf = '';
+
+  // default mask
+  if ('function' == typeof mask) {
+    fn = mask;
+    mask = '';
+  }
+
+  process.stdin.resume();
+  tty.setRawMode(true);
+  process.stdout.write(str);
+
+  // keypress
+  process.stdin.on('keypress', function(c, key){
+    if (key && 'enter' == key.name) {
+      console.log();
+      process.stdin.removeAllListeners('keypress');
+      tty.setRawMode(false);
+      if (!buf.trim().length) return self.password(str, mask, fn);
+      fn(buf);
+      return;
+    }
+
+    if (key && key.ctrl && 'c' == key.name) {
+      console.log('%s', buf);
+      process.exit();
+    }
+
+    process.stdout.write(mask);
+    buf += c;
+  }).resume();
+};
+
+/**
+ * Confirmation prompt with `str` and callback `fn(bool)`
+ *
+ * Examples:
+ *
+ *      program.confirm('continue? ', function(ok){
+ *        console.log(' got %j', ok);
+ *        process.stdin.destroy();
+ *      });
+ *
+ * @param {String} str
+ * @param {Function} fn
+ * @api public
+ */
+
+
+Command.prototype.confirm = function(str, fn, verbose){
+  var self = this;
+  this.prompt(str, function(ok){
+    if (!ok.trim()) {
+      if (!verbose) str += '(yes or no) ';
+      return self.confirm(str, fn, true);
+    }
+    fn(parseBool(ok));
+  });
+};
+
+/**
+ * Choice prompt with `list` of items and callback `fn(index, item)`
+ *
+ * Examples:
+ *
+ *      var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];
+ *      
+ *      console.log('Choose the coolest pet:');
+ *      program.choose(list, function(i){
+ *        console.log('you chose %d "%s"', i, list[i]);
+ *        process.stdin.destroy();
+ *      });
+ *
+ * @param {Array} list
+ * @param {Number|Function} index or fn
+ * @param {Function} fn
+ * @api public
+ */
+
+Command.prototype.choose = function(list, index, fn){
+  var self = this
+    , hasDefault = 'number' == typeof index;
+
+  if (!hasDefault) {
+    fn = index;
+    index = null;
+  }
+
+  list.forEach(function(item, i){
+    if (hasDefault && i == index) {
+      console.log('* %d) %s', i + 1, item);
+    } else {
+      console.log('  %d) %s', i + 1, item);
+    }
+  });
+
+  function again() {
+    self.prompt('  : ', function(val){
+      val = parseInt(val, 10) - 1;
+      if (hasDefault && isNaN(val)) val = index;
+
+      if (null == list[val]) {
+        again();
+      } else {
+        fn(val, list[val]);
+      }
+    });
+  }
+
+  again();
+};
+
+/**
+ * Camel-case the given `flag`
+ *
+ * @param {String} flag
+ * @return {String}
+ * @api private
+ */
+
+function camelcase(flag) {
+  return flag.split('-').reduce(function(str, word){
+    return str + word[0].toUpperCase() + word.slice(1);
+  });
+}
+
+/**
+ * Parse a boolean `str`.
+ *
+ * @param {String} str
+ * @return {Boolean}
+ * @api private
+ */
+
+function parseBool(str) {
+  return /^y|yes|ok|true$/i.test(str);
+}
+
+/**
+ * Pad `str` to `width`.
+ *
+ * @param {String} str
+ * @param {Number} width
+ * @return {String}
+ * @api private
+ */
+
+function pad(str, width) {
+  var len = Math.max(0, width - str.length);
+  return str + Array(len + 1).join(' ');
+}
+
+/**
+ * Output help information if necessary
+ *
+ * @param {Command} command to output help for
+ * @param {Array} array of options to search for -h or --help
+ * @api private
+ */
+
+function outputHelpIfNecessary(cmd, options) {
+  options = options || [];
+  for (var i = 0; i < options.length; i++) {
+    if (options[i] == '--help' || options[i] == '-h') {
+      process.stdout.write(cmd.helpInformation());
+      cmd.emit('--help');
+      process.exit(0);
+    }
+  }
+}
Index: Dev/trunk/src/node_modules/express/node_modules/commander/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/commander/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/commander/package.json	(revision 484)
@@ -0,0 +1,38 @@
+{
+  "name": "commander",
+  "version": "0.6.1",
+  "description": "the complete solution for node.js command-line programs",
+  "keywords": [
+    "command",
+    "option",
+    "parser",
+    "prompt",
+    "stdin"
+  ],
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/visionmedia/commander.js.git"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "should": ">= 0.0.1"
+  },
+  "scripts": {
+    "test": "make test"
+  },
+  "main": "index",
+  "engines": {
+    "node": ">= 0.4.x"
+  },
+  "readme": "# Commander.js\n\n  The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).\n\n [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)\n\n## Installation\n\n    $ npm install commander\n\n## Option parsing\n\n Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('commander');\n\nprogram\n  .version('0.0.1')\n  .option('-p, --peppers', 'Add peppers')\n  .option('-P, --pineapple', 'Add pineapple')\n  .option('-b, --bbq', 'Add bbq sauce')\n  .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')\n  .parse(process.argv);\n\nconsole.log('you ordered a pizza with:');\nif (program.peppers) console.log('  - peppers');\nif (program.pineapple) console.log('  - pineappe');\nif (program.bbq) console.log('  - bbq');\nconsole.log('  - %s cheese', program.cheese);\n```\n\n Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as \"--template-engine\" are camel-cased, becoming `program.templateEngine` etc.\n\n## Automated --help\n\n The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:\n\n```  \n $ ./examples/pizza --help\n\n   Usage: pizza [options]\n\n   Options:\n\n     -V, --version        output the version number\n     -p, --peppers        Add peppers\n     -P, --pineapple      Add pineappe\n     -b, --bbq            Add bbq sauce\n     -c, --cheese <type>  Add the specified type of cheese [marble]\n     -h, --help           output usage information\n\n```\n\n## Coercion\n\n```js\nfunction range(val) {\n  return val.split('..').map(Number);\n}\n\nfunction list(val) {\n  return val.split(',');\n}\n\nprogram\n  .version('0.0.1')\n  .usage('[options] <file ...>')\n  .option('-i, --integer <n>', 'An integer argument', parseInt)\n  .option('-f, --float <n>', 'A float argument', parseFloat)\n  .option('-r, --range <a>..<b>', 'A range', range)\n  .option('-l, --list <items>', 'A list', list)\n  .option('-o, --optional [value]', 'An optional value')\n  .parse(process.argv);\n\nconsole.log(' int: %j', program.integer);\nconsole.log(' float: %j', program.float);\nconsole.log(' optional: %j', program.optional);\nprogram.range = program.range || [];\nconsole.log(' range: %j..%j', program.range[0], program.range[1]);\nconsole.log(' list: %j', program.list);\nconsole.log(' args: %j', program.args);\n```\n\n## Custom help\n\n You can display arbitrary `-h, --help` information\n by listening for \"--help\". Commander will automatically\n exit once you are done so that the remainder of your program\n does not execute causing undesired behaviours, for example\n in the following executable \"stuff\" will not output when\n `--help` is used.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('../');\n\nfunction list(val) {\n  return val.split(',').map(Number);\n}\n\nprogram\n  .version('0.0.1')\n  .option('-f, --foo', 'enable some foo')\n  .option('-b, --bar', 'enable some bar')\n  .option('-B, --baz', 'enable some baz');\n\n// must be before .parse() since\n// node's emit() is immediate\n\nprogram.on('--help', function(){\n  console.log('  Examples:');\n  console.log('');\n  console.log('    $ custom-help --help');\n  console.log('    $ custom-help -h');\n  console.log('');\n});\n\nprogram.parse(process.argv);\n\nconsole.log('stuff');\n```\n\nyielding the following help output:\n\n```\n\nUsage: custom-help [options]\n\nOptions:\n\n  -h, --help     output usage information\n  -V, --version  output the version number\n  -f, --foo      enable some foo\n  -b, --bar      enable some bar\n  -B, --baz      enable some baz\n\nExamples:\n\n  $ custom-help --help\n  $ custom-help -h\n\n```\n\n## .prompt(msg, fn)\n\n Single-line prompt:\n\n```js\nprogram.prompt('name: ', function(name){\n  console.log('hi %s', name);\n});\n```\n\n Multi-line prompt:\n\n```js\nprogram.prompt('description:', function(name){\n  console.log('hi %s', name);\n});\n```\n\n Coercion:\n\n```js\nprogram.prompt('Age: ', Number, function(age){\n  console.log('age: %j', age);\n});\n```\n\n```js\nprogram.prompt('Birthdate: ', Date, function(date){\n  console.log('date: %s', date);\n});\n```\n\n## .password(msg[, mask], fn)\n\nPrompt for password without echoing:\n\n```js\nprogram.password('Password: ', function(pass){\n  console.log('got \"%s\"', pass);\n  process.stdin.destroy();\n});\n```\n\nPrompt for password with mask char \"*\":\n\n```js\nprogram.password('Password: ', '*', function(pass){\n  console.log('got \"%s\"', pass);\n  process.stdin.destroy();\n});\n```\n\n## .confirm(msg, fn)\n\n Confirm with the given `msg`:\n\n```js\nprogram.confirm('continue? ', function(ok){\n  console.log(' got %j', ok);\n});\n```\n\n## .choose(list, fn)\n\n Let the user choose from a `list`:\n\n```js\nvar list = ['tobi', 'loki', 'jane', 'manny', 'luna'];\n\nconsole.log('Choose the coolest pet:');\nprogram.choose(list, function(i){\n  console.log('you chose %d \"%s\"', i, list[i]);\n});\n```\n\n## Links\n\n - [API documentation](http://visionmedia.github.com/commander.js/)\n - [ascii tables](https://github.com/LearnBoost/cli-table)\n - [progress bars](https://github.com/visionmedia/node-progress)\n - [more progress bars](https://github.com/substack/node-multimeter)\n - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/visionmedia/commander.js/issues"
+  },
+  "_id": "commander@0.6.1",
+  "_from": "commander@0.6.1"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/.npmignore	(revision 484)
@@ -0,0 +1,12 @@
+*.markdown
+*.md
+.git*
+Makefile
+benchmarks/
+docs/
+examples/
+install.sh
+support/
+test/
+.DS_Store
+coverage.html
Index: Dev/trunk/src/node_modules/express/node_modules/connect/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/.travis.yml	(revision 484)
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - "0.8"
+  - "0.10"
Index: Dev/trunk/src/node_modules/express/node_modules/connect/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/LICENSE	(revision 484)
@@ -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.
Index: Dev/trunk/src/node_modules/express/node_modules/connect/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/Readme.md	(revision 484)
@@ -0,0 +1,133 @@
+[![build status](https://secure.travis-ci.org/senchalabs/connect.png)](http://travis-ci.org/senchalabs/connect)
+# Connect
+
+  Connect is an extensible HTTP server framework for [node](http://nodejs.org), providing high performance "plugins" known as _middleware_.
+
+ Connect is bundled with over _20_ commonly used middleware, including
+ a logger, session support, cookie parser, and [more](http://senchalabs.github.com/connect). Be sure to view the 2.x [documentation](http://senchalabs.github.com/connect/).
+
+```js
+var connect = require('connect')
+  , http = require('http');
+
+var app = connect()
+  .use(connect.favicon())
+  .use(connect.logger('dev'))
+  .use(connect.static('public'))
+  .use(connect.directory('public'))
+  .use(connect.cookieParser())
+  .use(connect.session({ secret: 'my secret here' }))
+  .use(function(req, res){
+    res.end('Hello from Connect!\n');
+  });
+
+http.createServer(app).listen(3000);
+```
+
+## Middleware
+
+  - [csrf](http://www.senchalabs.org/connect/csrf.html)
+  - [basicAuth](http://www.senchalabs.org/connect/basicAuth.html)
+  - [bodyParser](http://www.senchalabs.org/connect/bodyParser.html)
+  - [json](http://www.senchalabs.org/connect/json.html)
+  - [multipart](http://www.senchalabs.org/connect/multipart.html)
+  - [urlencoded](http://www.senchalabs.org/connect/urlencoded.html)
+  - [cookieParser](http://www.senchalabs.org/connect/cookieParser.html)
+  - [directory](http://www.senchalabs.org/connect/directory.html)
+  - [compress](http://www.senchalabs.org/connect/compress.html)
+  - [errorHandler](http://www.senchalabs.org/connect/errorHandler.html)
+  - [favicon](http://www.senchalabs.org/connect/favicon.html)
+  - [limit](http://www.senchalabs.org/connect/limit.html)
+  - [logger](http://www.senchalabs.org/connect/logger.html)
+  - [methodOverride](http://www.senchalabs.org/connect/methodOverride.html)
+  - [query](http://www.senchalabs.org/connect/query.html)
+  - [responseTime](http://www.senchalabs.org/connect/responseTime.html)
+  - [session](http://www.senchalabs.org/connect/session.html)
+  - [static](http://www.senchalabs.org/connect/static.html)
+  - [staticCache](http://www.senchalabs.org/connect/staticCache.html)
+  - [vhost](http://www.senchalabs.org/connect/vhost.html)
+  - [subdomains](http://www.senchalabs.org/connect/subdomains.html)
+  - [cookieSession](http://www.senchalabs.org/connect/cookieSession.html)
+
+## Running Tests
+
+first:
+
+    $ npm install -d
+
+then:
+
+    $ make test
+
+## Authors
+
+ Below is the output from [git-summary](http://github.com/visionmedia/git-extras).
+
+
+     project: connect
+     commits: 2033
+     active : 301 days
+     files  : 171
+     authors: 
+      1414	Tj Holowaychuk          69.6%
+       298	visionmedia             14.7%
+       191	Tim Caswell             9.4%
+        51	TJ Holowaychuk          2.5%
+        10	Ryan Olds               0.5%
+         8	Astro                   0.4%
+         5	Nathan Rajlich          0.2%
+         5	Jakub NeÅ¡etÅil          0.2%
+         3	Daniel Dickison         0.1%
+         3	David Rio Deiros        0.1%
+         3	Alexander Simmerl       0.1%
+         3	Andreas Lind Petersen   0.1%
+         2	Aaron Heckmann          0.1%
+         2	Jacques Crocker         0.1%
+         2	Fabian Jakobs           0.1%
+         2	Brian J Brennan         0.1%
+         2	Adam Malcontenti-Wilson 0.1%
+         2	Glen Mailer             0.1%
+         2	James Campos            0.1%
+         1	Trent Mick              0.0%
+         1	Troy Kruthoff           0.0%
+         1	Wei Zhu                 0.0%
+         1	comerc                  0.0%
+         1	darobin                 0.0%
+         1	nateps                  0.0%
+         1	Marco Sanson            0.0%
+         1	Arthur Taylor           0.0%
+         1	Aseem Kishore           0.0%
+         1	Bart Teeuwisse          0.0%
+         1	Cameron Howey           0.0%
+         1	Chad Weider             0.0%
+         1	Craig Barnes            0.0%
+         1	Eran Hammer-Lahav       0.0%
+         1	Gregory McWhirter       0.0%
+         1	Guillermo Rauch         0.0%
+         1	Jae Kwon                0.0%
+         1	Jakub Nesetril          0.0%
+         1	Joshua Peek             0.0%
+         1	Jxck                    0.0%
+         1	AJ ONeal                0.0%
+         1	Michael Hemesath        0.0%
+         1	Morten Siebuhr          0.0%
+         1	Samori Gorse            0.0%
+         1	Tom Jensen              0.0%
+
+## Node Compatibility
+
+  Connect `< 1.x` is compatible with node 0.2.x
+
+
+  Connect `1.x` is compatible with node 0.4.x
+
+
+  Connect (_master_) `2.x` is compatible with node 0.6.x
+
+## CLA
+
+ [http://sencha.com/cla](http://sencha.com/cla)
+
+## License
+
+View the [LICENSE](https://github.com/senchalabs/connect/blob/master/LICENSE) file. The [Silk](http://www.famfamfam.com/lab/icons/silk/) icons used by the `directory` middleware created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/).
Index: Dev/trunk/src/node_modules/express/node_modules/connect/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/index.js	(revision 484)
@@ -0,0 +1,4 @@
+
+module.exports = process.env.CONNECT_COV
+  ? require('./lib-cov/connect')
+  : require('./lib/connect');
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/cache.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/cache.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/cache.js	(revision 484)
@@ -0,0 +1,81 @@
+
+/*!
+ * Connect - Cache
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Expose `Cache`.
+ */
+
+module.exports = Cache;
+
+/**
+ * LRU cache store.
+ *
+ * @param {Number} limit
+ * @api private
+ */
+
+function Cache(limit) {
+  this.store = {};
+  this.keys = [];
+  this.limit = limit;
+}
+
+/**
+ * Touch `key`, promoting the object.
+ *
+ * @param {String} key
+ * @param {Number} i
+ * @api private
+ */
+
+Cache.prototype.touch = function(key, i){
+  this.keys.splice(i,1);
+  this.keys.push(key);
+};
+
+/**
+ * Remove `key`.
+ *
+ * @param {String} key
+ * @api private
+ */
+
+Cache.prototype.remove = function(key){
+  delete this.store[key];
+};
+
+/**
+ * Get the object stored for `key`.
+ *
+ * @param {String} key
+ * @return {Array}
+ * @api private
+ */
+
+Cache.prototype.get = function(key){
+  return this.store[key];
+};
+
+/**
+ * Add a cache `key`.
+ *
+ * @param {String} key
+ * @return {Array}
+ * @api private
+ */
+
+Cache.prototype.add = function(key){
+  // initialize store
+  var len = this.keys.push(key);
+
+  // limit reached, invalidate LRU
+  if (len > this.limit) this.remove(this.keys.shift());
+
+  var arr = this.store[key] = [];
+  arr.createdAt = new Date;
+  return arr;
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/connect.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/connect.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/connect.js	(revision 484)
@@ -0,0 +1,92 @@
+/*!
+ * Connect
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter
+  , proto = require('./proto')
+  , utils = require('./utils')
+  , path = require('path')
+  , basename = path.basename
+  , fs = require('fs');
+
+// node patches
+
+require('./patch');
+
+// expose createServer() as the module
+
+exports = module.exports = createServer;
+
+/**
+ * Framework version.
+ */
+
+exports.version = '2.7.11';
+
+/**
+ * Expose mime module.
+ */
+
+exports.mime = require('./middleware/static').mime;
+
+/**
+ * Expose the prototype.
+ */
+
+exports.proto = proto;
+
+/**
+ * Auto-load middleware getters.
+ */
+
+exports.middleware = {};
+
+/**
+ * Expose utilities.
+ */
+
+exports.utils = utils;
+
+/**
+ * Create a new connect server.
+ *
+ * @return {Function}
+ * @api public
+ */
+
+function createServer() {
+  function app(req, res, next){ app.handle(req, res, next); }
+  utils.merge(app, proto);
+  utils.merge(app, EventEmitter.prototype);
+  app.route = '/';
+  app.stack = [];
+  for (var i = 0; i < arguments.length; ++i) {
+    app.use(arguments[i]);
+  }
+  return app;
+};
+
+/**
+ * Support old `.createServer()` method.
+ */
+
+createServer.createServer = createServer;
+
+/**
+ * Auto-load bundled middleware with getters.
+ */
+
+fs.readdirSync(__dirname + '/middleware').forEach(function(filename){
+  if (!/\.js$/.test(filename)) return;
+  var name = basename(filename, '.js');
+  function load(){ return require('./middleware/' + name); }
+  exports.middleware.__defineGetter__(name, load);
+  exports.__defineGetter__(name, load);
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/index.js	(revision 484)
@@ -0,0 +1,50 @@
+
+/**
+ * Connect is a middleware framework for node,
+ * shipping with over 18 bundled middleware and a rich selection of
+ * 3rd-party middleware.
+ *
+ *     var app = connect()
+ *       .use(connect.logger('dev'))
+ *       .use(connect.static('public'))
+ *       .use(function(req, res){
+ *         res.end('hello world\n');
+ *       })
+ *      .listen(3000);
+ *     
+ * Installation:
+ * 
+ *     $ npm install connect
+ *
+ * Middleware:
+ *
+ *  - [logger](logger.html) request logger with custom format support
+ *  - [csrf](csrf.html) Cross-site request forgery protection
+ *  - [compress](compress.html) Gzip compression middleware
+ *  - [basicAuth](basicAuth.html) basic http authentication
+ *  - [bodyParser](bodyParser.html) extensible request body parser
+ *  - [json](json.html) application/json parser
+ *  - [urlencoded](urlencoded.html) application/x-www-form-urlencoded parser
+ *  - [multipart](multipart.html) multipart/form-data parser
+ *  - [timeout](timeout.html) request timeouts
+ *  - [cookieParser](cookieParser.html) cookie parser
+ *  - [session](session.html) session management support with bundled MemoryStore
+ *  - [cookieSession](cookieSession.html) cookie-based session support
+ *  - [methodOverride](methodOverride.html) faux HTTP method support
+ *  - [responseTime](responseTime.html) calculates response-time and exposes via X-Response-Time
+ *  - [staticCache](staticCache.html) memory cache layer for the static() middleware
+ *  - [static](static.html) streaming static file server supporting `Range` and more
+ *  - [directory](directory.html) directory listing middleware
+ *  - [vhost](vhost.html) virtual host sub-domain mapping middleware
+ *  - [favicon](favicon.html) efficient favicon server (with default icon)
+ *  - [limit](limit.html) limit the bytesize of request bodies
+ *  - [query](query.html) automatic querystring parser, populating `req.query`
+ *  - [errorHandler](errorHandler.html) flexible error handler
+ *
+ * Links:
+ * 
+ *   - list of [3rd-party](https://github.com/senchalabs/connect/wiki) middleware
+ *   - GitHub [repository](http://github.com/senchalabs/connect)
+ *   - [test documentation](https://github.com/senchalabs/connect/blob/gh-pages/tests.md)
+ * 
+ */
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/basicAuth.js	(revision 484)
@@ -0,0 +1,103 @@
+
+/*!
+ * Connect - basicAuth
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , unauthorized = utils.unauthorized;
+
+/**
+ * Basic Auth:
+ *
+ * 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.user`. The final alternative is simply passing username / password
+ * strings.
+ *
+ *  Simple username and password
+ *
+ *     connect(connect.basicAuth('username', 'password'));
+ *
+ *  Callback verification
+ *
+ *     connect()
+ *       .use(connect.basicAuth(function(user, pass){
+ *         return 'tj' == user & 'wahoo' == pass;
+ *       }))
+ *
+ *  Async callback verification, accepting `fn(err, user)`.
+ *
+ *     connect()
+ *       .use(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.user) return next();
+    if (!authorization) return unauthorized(res, realm);
+
+    var parts = authorization.split(' ');
+
+    if (parts.length !== 2) return next(utils.error(400));
+
+    var scheme = parts[0]
+      , credentials = new Buffer(parts[1], 'base64').toString()
+      , index = credentials.indexOf(':');
+
+    if ('Basic' != scheme || index < 0) return next(utils.error(400));
+    
+    var user = credentials.slice(0, index)
+      , pass = credentials.slice(index + 1);
+
+    // async
+    if (callback.length >= 3) {
+      var pause = utils.pause(req);
+      callback(user, pass, function(err, user){
+        if (err || !user)  return unauthorized(res, realm);
+        req.user = req.remoteUser = user;
+        next();
+        pause.resume();
+      });
+    // sync
+    } else {
+      if (callback(user, pass)) {
+        req.user = req.remoteUser = user;
+        next();
+      } else {
+        unauthorized(res, realm);
+      }
+    }
+  }
+};
+
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js	(revision 484)
@@ -0,0 +1,61 @@
+
+/*!
+ * Connect - bodyParser
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var multipart = require('./multipart')
+  , urlencoded = require('./urlencoded')
+  , json = require('./json');
+
+/**
+ * Body parser:
+ * 
+ *   Parse request bodies, supports _application/json_,
+ *   _application/x-www-form-urlencoded_, and _multipart/form-data_.
+ *
+ *   This is equivalent to: 
+ *
+ *     app.use(connect.json());
+ *     app.use(connect.urlencoded());
+ *     app.use(connect.multipart());
+ *
+ * Examples:
+ *
+ *      connect()
+ *        .use(connect.bodyParser())
+ *        .use(function(req, res) {
+ *          res.end('viewing user ' + req.body.user.name);
+ *        });
+ *
+ *      $ curl -d 'user[name]=tj' http://local/
+ *      $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://local/
+ *
+ *  View [json](json.html), [urlencoded](urlencoded.html), and [multipart](multipart.html) for more info.
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function bodyParser(options){
+  var _urlencoded = urlencoded(options)
+    , _multipart = multipart(options)
+    , _json = json(options);
+
+  return function bodyParser(req, res, next) {
+    _json(req, res, function(err){
+      if (err) return next(err);
+      _urlencoded(req, res, function(err){
+        if (err) return next(err);
+        _multipart(req, res, next);
+      });
+    });
+  }
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/compress.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/compress.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/compress.js	(revision 484)
@@ -0,0 +1,157 @@
+/*!
+ * Connect - compress
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var zlib = require('zlib');
+
+/**
+ * Supported content-encoding methods.
+ */
+
+exports.methods = {
+    gzip: zlib.createGzip
+  , deflate: zlib.createDeflate
+};
+
+/**
+ * Default filter function.
+ */
+
+exports.filter = function(req, res){
+  return /json|text|javascript/.test(res.getHeader('Content-Type'));
+};
+
+/**
+ * Compress:
+ *
+ * Compress response data with gzip/deflate.
+ *
+ * Filter:
+ *
+ *  A `filter` callback function may be passed to
+ *  replace the default logic of:
+ *
+ *     exports.filter = function(req, res){
+ *       return /json|text|javascript/.test(res.getHeader('Content-Type'));
+ *     };
+ *
+ * Options:
+ *
+ *  All remaining options are passed to the gzip/deflate
+ *  creation functions. Consult node's docs for additional details.
+ *
+ *   - `chunkSize` (default: 16*1024)
+ *   - `windowBits`
+ *   - `level`: 0-9 where 0 is no compression, and 9 is slow but best compression
+ *   - `memLevel`: 1-9 low is slower but uses less memory, high is fast but uses more
+ *   - `strategy`: compression strategy
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function compress(options) {
+  options = options || {};
+  var names = Object.keys(exports.methods)
+    , filter = options.filter || exports.filter;
+
+  return function compress(req, res, next){
+    var accept = req.headers['accept-encoding']
+      , vary = res.getHeader('Vary')
+      , write = res.write
+      , end = res.end
+      , stream
+      , method;
+
+    // vary
+    if (!vary) {
+      res.setHeader('Vary', 'Accept-Encoding');
+    } else if (!~vary.indexOf('Accept-Encoding')) {
+      res.setHeader('Vary', vary + ', Accept-Encoding');
+    }
+
+    // see #724
+    req.on('close', function(){
+      res.write = res.end = function(){};
+    });
+
+    // proxy
+
+    res.write = function(chunk, encoding){
+      if (!this.headerSent) this._implicitHeader();
+      return stream
+        ? stream.write(new Buffer(chunk, encoding))
+        : write.call(res, chunk, encoding);
+    };
+
+    res.end = function(chunk, encoding){
+      if (chunk) this.write(chunk, encoding);
+      return stream
+        ? stream.end()
+        : end.call(res);
+    };
+
+    res.on('header', function(){
+      var encoding = res.getHeader('Content-Encoding') || 'identity';
+
+      // already encoded
+      if ('identity' != encoding) return;
+
+      // default request filter
+      if (!filter(req, res)) return;
+
+      // SHOULD use identity
+      if (!accept) return;
+
+      // head
+      if ('HEAD' == req.method) return;
+
+      // default to gzip
+      if ('*' == accept.trim()) method = 'gzip';
+
+      // compression method
+      if (!method) {
+        for (var i = 0, len = names.length; i < len; ++i) {
+          if (~accept.indexOf(names[i])) {
+            method = names[i];
+            break;
+          }
+        }
+      }
+
+      // compression method
+      if (!method) return;
+
+      // compression stream
+      stream = exports.methods[method](options);
+
+      // header fields
+      res.setHeader('Content-Encoding', method);
+      res.removeHeader('Content-Length');
+
+      // compression
+
+      stream.on('data', function(chunk){
+        write.call(res, chunk);
+      });
+
+      stream.on('end', function(){
+        end.call(res);
+      });
+
+      stream.on('drain', function() {
+        res.emit('drain');
+      });
+    });
+
+    next();
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js	(revision 484)
@@ -0,0 +1,62 @@
+
+/*!
+ * Connect - cookieParser
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('./../utils')
+  , cookie = require('cookie');
+
+/**
+ * Cookie parser:
+ *
+ * Parse _Cookie_ header and populate `req.cookies`
+ * with an object keyed by the cookie names. Optionally
+ * you may enabled signed cookie support by passing
+ * a `secret` string, which assigns `req.secret` so
+ * it may be used by other middleware.
+ *
+ * Examples:
+ *
+ *     connect()
+ *       .use(connect.cookieParser('optional secret string'))
+ *       .use(function(req, res, next){
+ *         res.end(JSON.stringify(req.cookies));
+ *       })
+ *
+ * @param {String} secret
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function cookieParser(secret){
+  return function cookieParser(req, res, next) {
+    if (req.cookies) return next();
+    var cookies = req.headers.cookie;
+
+    req.secret = secret;
+    req.cookies = {};
+    req.signedCookies = {};
+
+    if (cookies) {
+      try {
+        req.cookies = cookie.parse(cookies);
+        if (secret) {
+          req.signedCookies = utils.parseSignedCookies(req.cookies, secret);
+          req.signedCookies = utils.parseJSONCookies(req.signedCookies);
+        }
+        req.cookies = utils.parseJSONCookies(req.cookies);
+      } catch (err) {
+        err.status = 400;
+        return next(err);
+      }
+    }
+    next();
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js	(revision 484)
@@ -0,0 +1,117 @@
+
+/*!
+ * Connect - cookieSession
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('./../utils')
+  , Cookie = require('./session/cookie')
+  , debug = require('debug')('connect:cookieSession')
+  , signature = require('cookie-signature')
+  , crc32 = require('buffer-crc32');
+
+/**
+ * Cookie Session:
+ *
+ *   Cookie session middleware.
+ *
+ *      var app = connect();
+ *      app.use(connect.cookieParser());
+ *      app.use(connect.cookieSession({ secret: 'tobo!', cookie: { maxAge: 60 * 60 * 1000 }}));
+ *
+ * Options:
+ *
+ *   - `key` cookie name defaulting to `connect.sess`
+ *   - `secret` prevents cookie tampering
+ *   - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }`
+ *   - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto")
+ *
+ * Clearing sessions:
+ *
+ *  To clear the session simply set its value to `null`,
+ *  `cookieSession()` will then respond with a 1970 Set-Cookie.
+ *
+ *     req.session = null;
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function cookieSession(options){
+  // TODO: utilize Session/Cookie to unify API
+  options = options || {};
+  var key = options.key || 'connect.sess'
+    , trustProxy = options.proxy;
+
+  return function cookieSession(req, res, next) {
+
+    // req.secret is for backwards compatibility
+    var secret = options.secret || req.secret;
+    if (!secret) throw new Error('`secret` option required for cookie sessions');
+
+    // default session
+    req.session = {};
+    var cookie = req.session.cookie = new Cookie(options.cookie);
+
+    // pathname mismatch
+    if (0 != req.originalUrl.indexOf(cookie.path)) return next();
+
+    // cookieParser secret
+    if (!options.secret && req.secret) {
+      req.session = req.signedCookies[key] || {};
+      req.session.cookie = cookie;
+    } else {
+      // TODO: refactor
+      var rawCookie = req.cookies[key];
+      if (rawCookie) {
+        var unsigned = utils.parseSignedCookie(rawCookie, secret);
+        if (unsigned) {
+          var originalHash = crc32.signed(unsigned);
+          req.session = utils.parseJSONCookie(unsigned) || {};
+          req.session.cookie = cookie;
+        }
+      }
+    }
+
+    res.on('header', function(){
+      // removed
+      if (!req.session) {
+        debug('clear session');
+        cookie.expires = new Date(0);
+        res.setHeader('Set-Cookie', cookie.serialize(key, ''));
+        return;
+      }
+
+      delete req.session.cookie;
+
+      // check security
+      var proto = (req.headers['x-forwarded-proto'] || '').toLowerCase()
+        , tls = req.connection.encrypted || (trustProxy && 'https' == proto)
+        , secured = cookie.secure && tls;
+
+      // only send secure cookies via https
+      if (cookie.secure && !secured) return debug('not secured');
+
+      // serialize
+      debug('serializing %j', req.session);
+      var val = 'j:' + JSON.stringify(req.session);
+
+      // compare hashes, no need to set-cookie if unchanged
+      if (originalHash == crc32.signed(val)) return debug('unmodified session');
+
+      // set-cookie
+      val = 's:' + signature.sign(val, secret);
+      val = cookie.serialize(key, val);
+      debug('set-cookie %j', cookie);
+      res.setHeader('Set-Cookie', val);
+    });
+
+    next();
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/csrf.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/csrf.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/csrf.js	(revision 484)
@@ -0,0 +1,73 @@
+/*!
+ * Connect - csrf
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils');
+
+/**
+ * Anti CSRF:
+ *
+ * CRSF protection middleware.
+ *
+ * By default this middleware generates a token named "_csrf"
+ * which should be added to requests which mutate
+ * state, within a hidden form field, query-string etc. This
+ * token is validated against the visitor's `req.session._csrf`
+ * property.
+ *
+ * The default `value` function checks `req.body` generated
+ * by the `bodyParser()` middleware, `req.query` generated
+ * by `query()`, and the "X-CSRF-Token" header field.
+ *
+ * This middleware requires session support, thus should be added
+ * somewhere _below_ `session()` and `cookieParser()`.
+ *
+ * Options:
+ *
+ *    - `value` a function accepting the request, returning the token 
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+module.exports = function csrf(options) {
+  options = options || {};
+  var value = options.value || defaultValue;
+
+  return function(req, res, next){
+    // generate CSRF token
+    var token = req.session._csrf || (req.session._csrf = utils.uid(24));
+
+    // ignore these methods
+    if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next();
+
+    // determine value
+    var val = value(req);
+
+    // check
+    if (val != token) return next(utils.error(403));
+    
+    next();
+  }
+};
+
+/**
+ * Default value function, checking the `req.body`
+ * and `req.query` for the CSRF token.
+ *
+ * @param {IncomingMessage} req
+ * @return {String}
+ * @api private
+ */
+
+function defaultValue(req) {
+  return (req.body && req.body._csrf)
+    || (req.query && req.query._csrf)
+    || (req.headers['x-csrf-token']);
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/directory.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/directory.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/directory.js	(revision 484)
@@ -0,0 +1,229 @@
+
+/*!
+ * Connect - directory
+ * Copyright(c) 2011 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+// TODO: icon / style for directories
+// TODO: arrow key navigation
+// TODO: make icons extensible
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , parse = require('url').parse
+  , utils = require('../utils')
+  , path = require('path')
+  , normalize = path.normalize
+  , extname = path.extname
+  , join = path.join;
+
+/*!
+ * Icon cache.
+ */
+
+var cache = {};
+
+/**
+ * Directory:
+ *
+ * Serve directory listings with the given `root` path.
+ *
+ * Options:
+ *
+ *  - `hidden` display hidden (dot) files. Defaults to false.
+ *  - `icons`  display icons. Defaults to false.
+ *  - `filter` Apply this filter function to files. Defaults to false.
+ *
+ * @param {String} root
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function directory(root, options){
+  options = options || {};
+
+  // root required
+  if (!root) throw new Error('directory() root path required');
+  var hidden = options.hidden
+    , icons = options.icons
+    , filter = options.filter
+    , root = normalize(root);
+
+  return function directory(req, res, next) {
+    if ('GET' != req.method && 'HEAD' != req.method) return next();
+
+    var accept = req.headers.accept || 'text/plain'
+      , url = parse(req.url)
+      , dir = decodeURIComponent(url.pathname)
+      , path = normalize(join(root, dir))
+      , originalUrl = parse(req.originalUrl)
+      , originalDir = decodeURIComponent(originalUrl.pathname)
+      , showUp = path != root && path != root + '/';
+
+    // null byte(s), bad request
+    if (~path.indexOf('\0')) return next(utils.error(400));
+
+    // malicious path, forbidden
+    if (0 != path.indexOf(root)) return next(utils.error(403));
+
+    // check if we have a directory
+    fs.stat(path, function(err, stat){
+      if (err) return 'ENOENT' == err.code
+        ? next()
+        : next(err);
+
+      if (!stat.isDirectory()) return next();
+
+      // fetch files
+      fs.readdir(path, function(err, files){
+        if (err) return next(err);
+        if (!hidden) files = removeHidden(files);
+        if (filter) files = files.filter(filter);
+        files.sort();
+
+        // content-negotiation
+        for (var key in exports) {
+          if (~accept.indexOf(key) || ~accept.indexOf('*/*')) {
+            exports[key](req, res, files, next, originalDir, showUp, icons);
+            return;
+          }
+        }
+
+        // not acceptable
+        next(utils.error(406));
+      });
+    });
+  };
+};
+
+/**
+ * Respond with text/html.
+ */
+
+exports.html = function(req, res, files, next, dir, showUp, icons){
+  fs.readFile(__dirname + '/../public/directory.html', 'utf8', function(err, str){
+    if (err) return next(err);
+    fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){
+      if (err) return next(err);
+      if (showUp) files.unshift('..');
+      str = str
+        .replace('{style}', style)
+        .replace('{files}', html(files, dir, icons))
+        .replace('{directory}', dir)
+        .replace('{linked-path}', htmlPath(dir));
+      res.setHeader('Content-Type', 'text/html');
+      res.setHeader('Content-Length', str.length);
+      res.end(str);
+    });
+  });
+};
+
+/**
+ * Respond with application/json.
+ */
+
+exports.json = function(req, res, files){
+  files = JSON.stringify(files);
+  res.setHeader('Content-Type', 'application/json');
+  res.setHeader('Content-Length', files.length);
+  res.end(files);
+};
+
+/**
+ * Respond with text/plain.
+ */
+
+exports.plain = function(req, res, files){
+  files = files.join('\n') + '\n';
+  res.setHeader('Content-Type', 'text/plain');
+  res.setHeader('Content-Length', files.length);
+  res.end(files);
+};
+
+/**
+ * Map html `dir`, returning a linked path.
+ */
+
+function htmlPath(dir) {
+  var curr = [];
+  return dir.split('/').map(function(part){
+    curr.push(part);
+    return '<a href="' + curr.join('/') + '">' + part + '</a>';
+  }).join(' / ');
+}
+
+/**
+ * Map html `files`, returning an html unordered list.
+ */
+
+function html(files, dir, useIcons) {
+  return '<ul id="files">' + files.map(function(file){
+    var icon = ''
+      , classes = [];
+
+    if (useIcons && '..' != file) {
+      icon = icons[extname(file)] || icons.default;
+      icon = '<img src="data:image/png;base64,' + load(icon) + '" />';
+      classes.push('icon');
+    }
+
+    return '<li><a href="'
+      + join(dir, file)
+      + '" class="'
+      + classes.join(' ') + '"'
+      + ' title="' + file + '">'
+      + icon + file + '</a></li>';
+
+  }).join('\n') + '</ul>';
+}
+
+/**
+ * Load and cache the given `icon`.
+ *
+ * @param {String} icon
+ * @return {String}
+ * @api private
+ */
+
+function load(icon) {
+  if (cache[icon]) return cache[icon];
+  return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64');
+}
+
+/**
+ * Filter "hidden" `files`, aka files
+ * beginning with a `.`.
+ *
+ * @param {Array} files
+ * @return {Array}
+ * @api private
+ */
+
+function removeHidden(files) {
+  return files.filter(function(file){
+    return '.' != file[0];
+  });
+}
+
+/**
+ * Icon map.
+ */
+
+var icons = {
+    '.js': 'page_white_code_red.png'
+  , '.c': 'page_white_c.png'
+  , '.h': 'page_white_h.png'
+  , '.cc': 'page_white_cplusplus.png'
+  , '.php': 'page_white_php.png'
+  , '.rb': 'page_white_ruby.png'
+  , '.cpp': 'page_white_cplusplus.png'
+  , '.swf': 'page_white_flash.png'
+  , '.pdf': 'page_white_acrobat.png'
+  , 'default': 'page_white.png'
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js	(revision 484)
@@ -0,0 +1,86 @@
+/*!
+ * Connect - errorHandler
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , fs = require('fs');
+
+// environment
+
+var env = process.env.NODE_ENV || 'development';
+
+/**
+ * Error handler:
+ *
+ * Development error handler, providing stack traces
+ * and error message responses for requests accepting text, html,
+ * or json.
+ *
+ * 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.
+ *
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function errorHandler(){
+  return function errorHandler(err, req, res, next){
+    if (err.status) res.statusCode = err.status;
+    if (res.statusCode < 400) res.statusCode = 500;
+    if ('test' != env) console.error(err.stack);
+    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('{statusCode}', res.statusCode)
+              .replace(/\{error\}/g, utils.escape(err.toString()));
+            res.setHeader('Content-Type', 'text/html; charset=utf-8');
+            res.end(html);
+        });
+      });
+    // json
+    } else if (~accept.indexOf('json')) {
+      var error = { message: err.message, stack: err.stack };
+      for (var prop in err) error[prop] = err[prop];
+      var json = JSON.stringify({ error: error });
+      res.setHeader('Content-Type', 'application/json');
+      res.end(json);
+    // plain text
+    } else {
+      res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' });
+      res.end(err.stack);
+    }
+  };
+};
+
+/**
+ * Template title, framework authors may override this value.
+ */
+
+exports.title = 'Connect';
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/favicon.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/favicon.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/favicon.js	(revision 484)
@@ -0,0 +1,80 @@
+/*!
+ * Connect - favicon
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , utils = require('../utils');
+
+/**
+ * Favicon:
+ *
+ * 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:
+ *
+ *   Serve default favicon:
+ *
+ *     connect()
+ *       .use(connect.favicon())
+ *
+ *   Serve favicon before logging for brevity:
+ *
+ *     connect()
+ *       .use(connect.favicon())
+ *       .use(connect.logger('dev'))
+ *
+ *   Serve custom favicon:
+ *
+ *     connect()
+ *       .use(connect.favicon('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
+    , icon; // favicon cache
+
+  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();
+    }
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/json.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/json.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/json.js	(revision 484)
@@ -0,0 +1,86 @@
+
+/*!
+ * Connect - json
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , _limit = require('./limit');
+
+/**
+ * noop middleware.
+ */
+
+function noop(req, res, next) {
+  next();
+}
+
+/**
+ * JSON:
+ *
+ * Parse JSON request bodies, providing the
+ * parsed object as `req.body`.
+ *
+ * Options:
+ *
+ *   - `strict`  when `false` anything `JSON.parse()` accepts will be parsed
+ *   - `reviver`  used as the second "reviver" argument for JSON.parse
+ *   - `limit`  byte limit disabled by default
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function(options){
+  var options = options || {}
+    , strict = options.strict !== false;
+
+  var limit = options.limit
+    ? _limit(options.limit)
+    : noop;
+
+  return function json(req, res, next) {
+    if (req._body) return next();
+    req.body = req.body || {};
+
+    if (!utils.hasBody(req)) return next();
+
+    // check Content-Type
+    if ('application/json' != utils.mime(req)) return next();
+
+    // flag as parsed
+    req._body = true;
+
+    // parse
+    limit(req, res, function(err){
+      if (err) return next(err);
+      var buf = '';
+      req.setEncoding('utf8');
+      req.on('data', function(chunk){ buf += chunk });
+      req.on('end', function(){
+        var first = buf.trim()[0];
+
+        if (0 == buf.length) {
+          return next(utils.error(400, 'invalid json, empty body'));
+        }
+        
+        if (strict && '{' != first && '[' != first) return next(utils.error(400, 'invalid json'));
+        try {
+          req.body = JSON.parse(buf, options.reviver);
+        } catch (err){
+          err.body = buf;
+          err.status = 400;
+          return next(err);
+        }
+        next();
+      });
+    });
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/limit.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/limit.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/limit.js	(revision 484)
@@ -0,0 +1,78 @@
+
+/*!
+ * Connect - limit
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils'),
+  brokenPause = utils.brokenPause;
+
+/**
+ * Limit:
+ *
+ *   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.
+ *
+ *     connect()
+ *       .use(connect.limit('5.5mb'))
+ *       .use(handleImageUpload)
+ *
+ * @param {Number|String} bytes
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function limit(bytes){
+  if ('string' == typeof bytes) bytes = utils.parseBytes(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;
+
+    // self-awareness
+    if (req._limit) return next();
+    req._limit = true;
+
+    // limit by content-length
+    if (len && len > bytes) return next(utils.error(413));
+
+    // limit
+    if (brokenPause) {
+      listen();
+    } else {
+      req.on('newListener', function handler(event) {
+        if (event !== 'data') return;
+
+        req.removeListener('newListener', handler);
+        // Start listening at the end of the current loop
+        // otherwise the request will be consumed too early.
+        // Sideaffect is `limit` will miss the first chunk,
+        // but that's not a big deal.
+        // Unfortunately, the tests don't have large enough
+        // request bodies to test this.
+        process.nextTick(listen);
+      });
+    };
+
+    next();
+
+    function listen() {
+      req.on('data', function(chunk) {
+        received += Buffer.isBuffer(chunk)
+          ? chunk.length :
+          Buffer.byteLength(chunk);
+
+        if (received > bytes) req.destroy();
+      });
+    };
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/logger.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/logger.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/logger.js	(revision 484)
@@ -0,0 +1,339 @@
+/*!
+ * Connect - logger
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var bytes = require('bytes');
+
+/*!
+ * Log buffer.
+ */
+
+var buf = [];
+
+/*!
+ * Default log buffer duration.
+ */
+
+var defaultBufferDuration = 1000;
+
+/**
+ * Logger:
+ *
+ * Log requests with the given `options` or a `format` string.
+ *
+ * Options:
+ *
+ *   - `format`  Format string, see below for tokens
+ *   - `stream`  Output stream, defaults to _stdout_
+ *   - `buffer`  Buffer duration, defaults to 1000ms when _true_
+ *   - `immediate`  Write log line on request instead of response (for response times)
+ *
+ * Tokens:
+ *
+ *   - `:req[header]` ex: `:req[Accept]`
+ *   - `:res[header]` ex: `:res[Content-Length]`
+ *   - `:http-version`
+ *   - `:response-time`
+ *   - `:remote-addr`
+ *   - `:date`
+ *   - `:method`
+ *   - `:url`
+ *   - `:referrer`
+ *   - `:user-agent`
+ *   - `:status`
+ *
+ * Formats:
+ *
+ *   Pre-defined formats that ship with connect:
+ *
+ *    - `default` ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"'
+ *    - `short` ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'
+ *    - `tiny`  ':method :url :status :res[content-length] - :response-time ms'
+ *    - `dev` concise output colored by response status for development use
+ *
+ * Examples:
+ *
+ *      connect.logger() // default
+ *      connect.logger('short')
+ *      connect.logger('tiny')
+ *      connect.logger({ immediate: true, format: 'dev' })
+ *      connect.logger(':method :url - :referrer')
+ *      connect.logger(':req[content-type] -> :res[content-type]')
+ *      connect.logger(function(tokens, req, res){ return 'some format string' })
+ *
+ * Defining Tokens:
+ *
+ *   To define a token, simply invoke `connect.logger.token()` with the
+ *   name and a callback function. The value returned is then available
+ *   as ":type" in this case.
+ *
+ *      connect.logger.token('type', function(req, res){ return req.headers['content-type']; })
+ *
+ * Defining Formats:
+ *
+ *   All default formats are defined this way, however it's public API as well:
+ *
+ *       connect.logger.format('name', 'string or function')
+ *
+ * @param {String|Function|Object} format or options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function logger(options) {
+  if ('object' == typeof options) {
+    options = options || {};
+  } else if (options) {
+    options = { format: options };
+  } else {
+    options = {};
+  }
+
+  // output on request instead of response
+  var immediate = options.immediate;
+
+  // format name
+  var fmt = exports[options.format] || options.format || exports.default;
+
+  // compile format
+  if ('function' != typeof fmt) fmt = compile(fmt);
+
+  // options
+  var stream = options.stream || process.stdout
+    , buffer = options.buffer;
+
+  // buffering support
+  if (buffer) {
+    var realStream = stream
+      , interval = 'number' == typeof buffer
+        ? buffer
+        : defaultBufferDuration;
+
+    // flush interval
+    setInterval(function(){
+      if (buf.length) {
+        realStream.write(buf.join(''));
+        buf.length = 0;
+      }
+    }, interval); 
+
+    // swap the stream
+    stream = {
+      write: function(str){
+        buf.push(str);
+      }
+    };
+  }
+
+  return function logger(req, res, next) {
+    req._startTime = new Date;
+
+    // immediate
+    if (immediate) {
+      var line = fmt(exports, req, res);
+      if (null == line) return;
+      stream.write(line + '\n');
+    // proxy end to output logging
+    } else {
+      var end = res.end;
+      res.end = function(chunk, encoding){
+        res.end = end;
+        res.end(chunk, encoding);
+        var line = fmt(exports, req, res);
+        if (null == line) return;
+        stream.write(line + '\n');
+      };
+    }
+
+
+    next();
+  };
+};
+
+/**
+ * Compile `fmt` into a function.
+ *
+ * @param {String} fmt
+ * @return {Function}
+ * @api private
+ */
+
+function compile(fmt) {
+  fmt = fmt.replace(/"/g, '\\"');
+  var js = '  return "' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function(_, name, arg){
+    return '"\n    + (tokens["' + name + '"](req, res, "' + arg + '") || "-") + "';
+  }) + '";'
+  return new Function('tokens, req, res', js);
+};
+
+/**
+ * Define a token function with the given `name`,
+ * and callback `fn(req, res)`.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @return {Object} exports for chaining
+ * @api public
+ */
+
+exports.token = function(name, fn) {
+  exports[name] = fn;
+  return this;
+};
+
+/**
+ * Define a `fmt` with the given `name`.
+ *
+ * @param {String} name
+ * @param {String|Function} fmt
+ * @return {Object} exports for chaining
+ * @api public
+ */
+
+exports.format = function(name, str){
+  exports[name] = str;
+  return this;
+};
+
+/**
+ * Default format.
+ */
+
+exports.format('default', ':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"');
+
+/**
+ * Short format.
+ */
+
+exports.format('short', ':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms');
+
+/**
+ * Tiny format.
+ */
+
+exports.format('tiny', ':method :url :status :res[content-length] - :response-time ms');
+
+/**
+ * dev (colored)
+ */
+
+exports.format('dev', function(tokens, req, res){
+  var status = res.statusCode
+    , len = parseInt(res.getHeader('Content-Length'), 10)
+    , color = 32;
+
+  if (status >= 500) color = 31
+  else if (status >= 400) color = 33
+  else if (status >= 300) color = 36;
+
+  len = isNaN(len)
+    ? ''
+    : len = ' - ' + bytes(len);
+
+  return '\033[90m' + req.method
+    + ' ' + req.originalUrl + ' '
+    + '\033[' + color + 'm' + res.statusCode
+    + ' \033[90m'
+    + (new Date - req._startTime)
+    + 'ms' + len
+    + '\033[0m';
+});
+
+/**
+ * request url
+ */
+
+exports.token('url', function(req){
+  return req.originalUrl || req.url;
+});
+
+/**
+ * request method
+ */
+
+exports.token('method', function(req){
+  return req.method;
+});
+
+/**
+ * response time in milliseconds
+ */
+
+exports.token('response-time', function(req){
+  return new Date - req._startTime;
+});
+
+/**
+ * UTC date
+ */
+
+exports.token('date', function(){
+  return new Date().toUTCString();
+});
+
+/**
+ * response status code
+ */
+
+exports.token('status', function(req, res){
+  return res.statusCode;
+});
+
+/**
+ * normalized referrer
+ */
+
+exports.token('referrer', function(req){
+  return req.headers['referer'] || req.headers['referrer'];
+});
+
+/**
+ * remote address
+ */
+
+exports.token('remote-addr', function(req){
+  if (req.ip) return req.ip;
+  var sock = req.socket;
+  if (sock.socket) return sock.socket.remoteAddress;
+  return sock.remoteAddress;
+});
+
+/**
+ * HTTP version
+ */
+
+exports.token('http-version', function(req){
+  return req.httpVersionMajor + '.' + req.httpVersionMinor;
+});
+
+/**
+ * UA string
+ */
+
+exports.token('user-agent', function(req){
+  return req.headers['user-agent'];
+});
+
+/**
+ * request header
+ */
+
+exports.token('req', function(req, res, field){
+  return req.headers[field.toLowerCase()];
+});
+
+/**
+ * response header
+ */
+
+exports.token('res', function(req, res, field){
+  return (res._headers || {})[field.toLowerCase()];
+});
+
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/methodOverride.js	(revision 484)
@@ -0,0 +1,40 @@
+
+/*!
+ * Connect - methodOverride
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Method Override:
+ * 
+ * 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();
+  };
+};
+
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/multipart.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/multipart.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/multipart.js	(revision 484)
@@ -0,0 +1,133 @@
+/*!
+ * Connect - multipart
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var formidable = require('formidable')
+  , _limit = require('./limit')
+  , utils = require('../utils')
+  , qs = require('qs');
+
+/**
+ * noop middleware.
+ */
+
+function noop(req, res, next) {
+  next();
+}
+
+/**
+ * Multipart:
+ * 
+ * Parse multipart/form-data request bodies,
+ * providing the parsed object as `req.body`
+ * and `req.files`.
+ *
+ * Configuration:
+ *
+ *  The options passed are merged with [formidable](https://github.com/felixge/node-formidable)'s
+ *  `IncomingForm` object, allowing you to configure the upload directory,
+ *  size limits, etc. For example if you wish to change the upload dir do the following.
+ *
+ *     app.use(connect.multipart({ uploadDir: path }));
+ *
+ * Options:
+ *
+ *   - `limit`  byte limit defaulting to none
+ *   - `defer`  defers processing and exposes the Formidable form object as `req.form`.
+ *              `next()` is called without waiting for the form's "end" event.
+ *              This option is useful if you need to bind to the "progress" event, for example.
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function(options){
+  options = options || {};
+
+  var limit = options.limit
+    ? _limit(options.limit)
+    : noop;
+
+  return function multipart(req, res, next) {
+    if (req._body) return next();
+    req.body = req.body || {};
+    req.files = req.files || {};
+
+    if (!utils.hasBody(req)) return next();
+
+    // ignore GET
+    if ('GET' == req.method || 'HEAD' == req.method) return next();
+
+    // check Content-Type
+    if ('multipart/form-data' != utils.mime(req)) return next();
+
+    // flag as parsed
+    req._body = true;
+
+    // parse
+    limit(req, res, function(err){
+      if (err) return next(err);
+
+      var form = new formidable.IncomingForm
+        , data = {}
+        , files = {}
+        , done;
+
+      Object.keys(options).forEach(function(key){
+        form[key] = options[key];
+      });
+
+      function ondata(name, val, data){
+        if (Array.isArray(data[name])) {
+          data[name].push(val);
+        } else if (data[name]) {
+          data[name] = [data[name], val];
+        } else {
+          data[name] = val;
+        }
+      }
+
+      form.on('field', function(name, val){
+        ondata(name, val, data);
+      });
+
+      form.on('file', function(name, val){
+        ondata(name, val, files);
+      });
+
+      form.on('error', function(err){
+        if (!options.defer) {
+          err.status = 400;
+          next(err);
+        }
+        done = true;
+      });
+
+      form.on('end', function(){
+        if (done) return;
+        try {
+          req.body = qs.parse(data);
+          req.files = qs.parse(files);
+          if (!options.defer) next();
+        } catch (err) {
+          form.emit('error', err);
+        }
+      });
+
+      form.parse(req);
+
+      if (options.defer) {
+        req.form = form;
+        next();
+      }
+    });
+  }
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/query.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/query.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/query.js	(revision 484)
@@ -0,0 +1,46 @@
+/*!
+ * Connect - query
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var qs = require('qs')
+  , parse = require('../utils').parseUrl;
+
+/**
+ * Query:
+ *
+ * Automatically parse the query-string when available,
+ * populating the `req.query` object.
+ *
+ * Examples:
+ *
+ *     connect()
+ *       .use(connect.query())
+ *       .use(function(req, res){
+ *         res.end(JSON.stringify(req.query));
+ *       });
+ *
+ *  The `options` passed are provided to qs.parse function.
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function query(options){
+  return function query(req, res, next){
+    if (!req.query) {
+      req.query = ~req.url.indexOf('?')
+        ? qs.parse(parse(req).query, options)
+        : {};
+    }
+
+    next();
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/responseTime.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/responseTime.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/responseTime.js	(revision 484)
@@ -0,0 +1,32 @@
+
+/*!
+ * Connect - responseTime
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Reponse time:
+ *
+ * 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 start = new Date;
+
+    if (res._responseTime) return next();
+    res._responseTime = true;
+
+    res.on('header', function(){
+      var duration = new Date - start;
+      res.setHeader('X-Response-Time', duration + 'ms');
+    });
+
+    next();
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session.js	(revision 484)
@@ -0,0 +1,356 @@
+
+/*!
+ * Connect - session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Session = require('./session/session')
+  , debug = require('debug')('connect:session')
+  , MemoryStore = require('./session/memory')
+  , signature = require('cookie-signature')
+  , Cookie = require('./session/cookie')
+  , Store = require('./session/store')
+  , utils = require('./../utils')
+  , parse = utils.parseUrl
+  , crc32 = require('buffer-crc32');
+
+// 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 will not scale past a single process.';
+
+/**
+ * Session:
+ *
+ *   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()](cookieParser.html)
+ *   middleware _before_ `session()`.
+ *
+ * Examples:
+ *
+ *     connect()
+ *       .use(connect.cookieParser())
+ *       .use(connect.session({ secret: 'keyboard cat', key: 'sid', cookie: { secure: true }}))
+ *
+ * Options:
+ *
+ *   - `key` cookie name defaulting to `connect.sid`
+ *   - `store` session store instance
+ *   - `secret` session cookie is signed with this secret to prevent tampering
+ *   - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }`
+ *   - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto")
+ *
+ * Cookie option:
+ *
+ *  By default `cookie.maxAge` is `null`, meaning no "expires" parameter is set
+ *  so the cookie becomes a browser-session cookie. When the user closes the
+ *  browser the cookie (and session) will be removed.
+ *
+ * ## 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()
+ *         .use(connect.favicon())
+ *         .use(connect.cookieParser())
+ *         .use(connect.session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
+ *         .use(function(req, res, next){
+ *           var sess = req.session;
+ *           if (sess.views) {
+ *             res.setHeader('Content-Type', 'text/html');
+ *             res.write('<p>views: ' + sess.views + '</p>');
+ *             res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>');
+ *             res.end();
+ *             sess.views++;
+ *           } else {
+ *             sess.views = 1;
+ *             res.end('welcome to the session demo. refresh!');
+ *           }
+ *         }
+ *       )).listen(3000);
+ *
+ * ## Session#regenerate()
+ *
+ *  To regenerate the session simply invoke the method, once complete
+ *  a new SID and `Session` instance will be initialized at `req.session`.
+ *
+ *      req.session.regenerate(function(err){
+ *        // will have a new session here
+ *      });
+ *
+ * ## Session#destroy()
+ *
+ *  Destroys the session, removing `req.session`, will be re-generated next request.
+ *
+ *      req.session.destroy(function(err){
+ *        // cannot access session here
+ *      });
+ *
+ * ## Session#reload()
+ *
+ *  Reloads the session data.
+ *
+ *      req.session.reload(function(err){
+ *        // session updated
+ *      });
+ *
+ * ## Session#save()
+ *
+ *  Save the session.
+ *
+ *      req.session.save(function(err){
+ *        // session saved
+ *      });
+ *
+ * ## Session#touch()
+ *
+ *   Updates the `.maxAge` property. 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 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'
+    , store = options.store || new MemoryStore
+    , cookie = options.cookie || {}
+    , trustProxy = options.proxy
+    , storeReady = true;
+
+  // notify user that this store is not
+  // meant for a production environment
+  if ('production' == env && store instanceof MemoryStore) {
+    console.warn(warning);
+  }
+
+  // generates the new session
+  store.generate = function(req){
+    req.sessionID = utils.uid(24);
+    req.session = new Session(req);
+    req.session.cookie = new Cookie(cookie);
+  };
+
+  store.on('disconnect', function(){ storeReady = false; });
+  store.on('connect', function(){ storeReady = true; });
+
+  return function session(req, res, next) {
+    // self-awareness
+    if (req.session) return next();
+
+    // Handle connection as if there is no session if
+    // the store has temporarily disconnected etc
+    if (!storeReady) return debug('store is disconnected'), next();
+
+    // pathname mismatch
+    if (0 != req.originalUrl.indexOf(cookie.path || '/')) return next();
+
+    // backwards compatibility for signed cookies
+    // req.secret is passed from the cookie parser middleware
+    var secret = options.secret || req.secret;
+
+    // ensure secret is available or bail
+    if (!secret) throw new Error('`secret` option required for sessions');
+
+    // parse url
+    var originalHash
+      , originalId;
+
+    // expose store
+    req.sessionStore = store;
+
+    // grab the session cookie value and check the signature
+    var rawCookie = req.cookies[key];
+
+    // get signedCookies for backwards compat with signed cookies
+    var unsignedCookie = req.signedCookies[key];
+
+    if (!unsignedCookie && rawCookie) {
+      unsignedCookie = utils.parseSignedCookie(rawCookie, secret);
+    }
+
+    // set-cookie
+    res.on('header', function(){
+      if (!req.session) return;
+      var cookie = req.session.cookie
+        , proto = (req.headers['x-forwarded-proto'] || '').split(',')[0].toLowerCase().trim()
+        , tls = req.connection.encrypted || (trustProxy && 'https' == proto)
+        , secured = cookie.secure && tls
+        , isNew = unsignedCookie != req.sessionID;
+
+      // only send secure cookies via https
+      if (cookie.secure && !secured) return debug('not secured');
+
+      // long expires, handle expiry server-side
+      if (!isNew && cookie.hasLongExpires) return debug('already set cookie');
+
+      // browser-session length cookie
+      if (null == cookie.expires) {
+        if (!isNew) return debug('already set browser-session cookie');
+      // compare hashes and ids
+      } else if (originalHash == hash(req.session) && originalId == req.session.id) {
+        return debug('unmodified session');
+      }
+
+      var val = 's:' + signature.sign(req.sessionID, secret);
+      val = cookie.serialize(key, val);
+      debug('set-cookie %s', val);
+      res.setHeader('Set-Cookie', val);
+    });
+
+    // proxy end() to commit the session
+    var end = res.end;
+    res.end = function(data, encoding){
+      res.end = end;
+      if (!req.session) return res.end(data, encoding);
+      debug('saving');
+      req.session.resetMaxAge();
+      req.session.save(function(err){
+        if (err) console.error(err.stack);
+        debug('saved');
+        res.end(data, encoding);
+      });
+    };
+
+    // generate the session
+    function generate() {
+      store.generate(req);
+    }
+
+    // get the sessionID from the cookie
+    req.sessionID = unsignedCookie;
+
+    // generate a session if the browser doesn't send a sessionID
+    if (!req.sessionID) {
+      debug('no SID sent, generating session');
+      generate();
+      next();
+      return;
+    }
+
+    // generate the session object
+    var pause = utils.pause(req);
+    debug('fetching %s', req.sessionID);
+    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) {
+        debug('error %j', err);
+        if ('ENOENT' == err.code) {
+          generate();
+          next();
+        } else {
+          next(err);
+        }
+      // no session
+      } else if (!sess) {
+        debug('no session found');
+        generate();
+        next();
+      // populate req.session
+      } else {
+        debug('session found');
+        store.createSession(req, sess);
+        originalId = req.sessionID;
+        originalHash = hash(sess);
+        next();
+      }
+    });
+  };
+};
+
+/**
+ * Hash the given `sess` object omitting changes
+ * to `.cookie`.
+ *
+ * @param {Object} sess
+ * @return {String}
+ * @api private
+ */
+
+function hash(sess) {
+  return crc32.signed(JSON.stringify(sess, function(key, val){
+    if ('cookie' != key) return val;
+  }));
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/cookie.js	(revision 484)
@@ -0,0 +1,140 @@
+
+/*!
+ * Connect - session - Cookie
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../../utils')
+  , cookie = require('cookie');
+
+/**
+ * Initialize a new `Cookie` with the given `options`.
+ *
+ * @param {IncomingMessage} req
+ * @param {Object} options
+ * @api private
+ */
+
+var Cookie = module.exports = function Cookie(options) {
+  this.path = '/';
+  this.maxAge = null;
+  this.httpOnly = true;
+  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
+    }
+  },
+
+  /**
+   * Check if the cookie has a reasonably large max-age.
+   *
+   * @return {Boolean}
+   * @api private
+   */
+
+  get hasLongExpires() {
+    var week = 604800000;
+    return this.maxAge > (4 * week);
+  },
+
+  /**
+   * Return a serialized cookie string.
+   *
+   * @return {String}
+   * @api public
+   */
+
+  serialize: function(name, val){
+    return cookie.serialize(name, val, this.data);
+  },
+
+  /**
+   * Return JSON representation of this cookie.
+   *
+   * @return {Object}
+   * @api private
+   */
+
+  toJSON: function(){
+    return this.data;
+  }
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/memory.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/memory.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/memory.js	(revision 484)
@@ -0,0 +1,129 @@
+
+/*!
+ * Connect - session - MemoryStore
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Store = require('./store');
+
+/**
+ * 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);
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/session.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/session.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/session.js	(revision 484)
@@ -0,0 +1,116 @@
+
+/*!
+ * Connect - session - Session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../../utils');
+
+/**
+ * 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);
+};
+
+/**
+ * Update 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.resetMaxAge();
+};
+
+/**
+ * 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 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;
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/store.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/store.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/session/store.js	(revision 484)
@@ -0,0 +1,84 @@
+
+/*!
+ * Connect - session - Store
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter
+  , Session = require('./session')
+  , Cookie = require('./cookie');
+
+/**
+ * Initialize abstract `Store`.
+ *
+ * @api private
+ */
+
+var Store = module.exports = function Store(options){};
+
+/**
+ * Inherit from `EventEmitter.prototype`.
+ */
+
+Store.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Re-generate the given requests's session.
+ *
+ * @param {IncomingRequest} req
+ * @return {Function} fn
+ * @api public
+ */
+
+Store.prototype.regenerate = function(req, fn){
+  var self = this;
+  this.destroy(req.sessionID, function(err){
+    self.generate(req);
+    fn(err);
+  });
+};
+
+/**
+ * Load a `Session` instance via the given `sid`
+ * and invoke the callback `fn(err, sess)`.
+ *
+ * @param {String} sid
+ * @param {Function} fn
+ * @api public
+ */
+
+Store.prototype.load = function(sid, fn){
+  var self = this;
+  this.get(sid, function(err, sess){
+    if (err) return fn(err);
+    if (!sess) return fn();
+    var req = { sessionID: sid, sessionStore: self };
+    sess = self.createSession(req, sess);
+    fn(null, sess);
+  });
+};
+
+/**
+ * Create session from JSON `sess` data.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} sess
+ * @return {Session}
+ * @api private
+ */
+
+Store.prototype.createSession = function(req, sess){
+  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);
+  return req.session;
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/static.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/static.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/static.js	(revision 484)
@@ -0,0 +1,95 @@
+/*!
+ * Connect - static
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var send = require('send')
+  , utils = require('../utils')
+  , parse = utils.parseUrl
+  , url = require('url');
+
+/**
+ * Static:
+ *
+ *   Static file server with the given `root` path.
+ *
+ * Examples:
+ *
+ *     var oneDay = 86400000;
+ *
+ *     connect()
+ *       .use(connect.static(__dirname + '/public'))
+ *
+ *     connect()
+ *       .use(connect.static(__dirname + '/public', { maxAge: oneDay }))
+ *
+ * Options:
+ *
+ *    - `maxAge`     Browser cache maxAge in milliseconds. defaults to 0
+ *    - `hidden`     Allow transfer of hidden files. defaults to false
+ *    - `redirect`   Redirect to trailing "/" when the pathname is a dir. defaults to true
+ *    - `index`      Default file name, defaults to 'index.html'
+ *
+ * @param {String} root
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function(root, options){
+  options = options || {};
+
+  // root required
+  if (!root) throw new Error('static() root path required');
+
+  // default redirect
+  var redirect = false !== options.redirect;
+
+  return function static(req, res, next) {
+    if ('GET' != req.method && 'HEAD' != req.method) return next();
+    var path = parse(req).pathname;
+    var pause = utils.pause(req);
+
+    function resume() {
+      next();
+      pause.resume();
+    }
+
+    function directory() {
+      if (!redirect) return resume();
+      var pathname = url.parse(req.originalUrl).pathname;
+      res.statusCode = 301;
+      res.setHeader('Location', pathname + '/');
+      res.end('Redirecting to ' + utils.escape(pathname) + '/');
+    }
+
+    function error(err) {
+      if (404 == err.status) return resume();
+      next(err);
+    }
+
+    send(req, path)
+      .maxage(options.maxAge || 0)
+      .root(root)
+      .index(options.index || 'index.html')
+      .hidden(options.hidden)
+      .on('error', error)
+      .on('directory', directory)
+      .pipe(res);
+  };
+};
+
+/**
+ * Expose mime module.
+ *
+ * If you wish to extend the mime table use this
+ * reference to the "mime" module in the npm registry.
+ */
+
+exports.mime = send.mime;
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/staticCache.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/staticCache.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/staticCache.js	(revision 484)
@@ -0,0 +1,231 @@
+
+/*!
+ * Connect - staticCache
+ * Copyright(c) 2011 Sencha Inc.
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , Cache = require('../cache')
+  , fresh = require('fresh');
+
+/**
+ * Static cache:
+ *
+ * Enables a memory cache layer on top of
+ * the `static()` middleware, serving popular
+ * static files.
+ *
+ * By default a maximum of 128 objects are
+ * held in cache, with a max of 256k each,
+ * totalling ~32mb.
+ *
+ * A Least-Recently-Used (LRU) cache algo
+ * is implemented through the `Cache` object,
+ * simply rotating cache objects as they are
+ * hit. This means that increasingly popular
+ * objects maintain their positions while
+ * others get shoved out of the stack and
+ * garbage collected.
+ *
+ * Benchmarks:
+ *
+ *     static(): 2700 rps
+ *     node-static: 5300 rps
+ *     static() + staticCache(): 7500 rps
+ *
+ * Options:
+ *
+ *   - `maxObjects`  max cache objects [128]
+ *   - `maxLength`  max cache object length 256kb
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function staticCache(options){
+  var options = options || {}
+    , cache = new Cache(options.maxObjects || 128)
+    , maxlen = options.maxLength || 1024 * 256;
+
+  console.warn('connect.staticCache() is deprecated and will be removed in 3.0');
+  console.warn('use varnish or similar reverse proxy caches.');
+
+  return function staticCache(req, res, next){
+    var key = cacheKey(req)
+      , ranges = req.headers.range
+      , hasCookies = req.headers.cookie
+      , hit = cache.get(key);
+
+    // cache static
+    // TODO: change from staticCache() -> cache()
+    // and make this work for any request
+    req.on('static', function(stream){
+      var headers = res._headers
+        , cc = utils.parseCacheControl(headers['cache-control'] || '')
+        , contentLength = headers['content-length']
+        , hit;
+
+      // dont cache set-cookie responses
+      if (headers['set-cookie']) return hasCookies = true;
+
+      // dont cache when cookies are present
+      if (hasCookies) return;
+
+      // ignore larger files
+      if (!contentLength || contentLength > maxlen) return;
+
+      // don't cache partial files
+      if (headers['content-range']) return;
+
+      // dont cache items we shouldn't be
+      // TODO: real support for must-revalidate / no-cache
+      if ( cc['no-cache']
+        || cc['no-store']
+        || cc['private']
+        || cc['must-revalidate']) return;
+
+      // if already in cache then validate
+      if (hit = cache.get(key)){
+        if (headers.etag == hit[0].etag) {
+          hit[0].date = new Date;
+          return;
+        } else {
+          cache.remove(key);
+        }
+      }
+
+      // validation notifiactions don't contain a steam
+      if (null == stream) return;
+
+      // add the cache object
+      var arr = [];
+
+      // store the chunks
+      stream.on('data', function(chunk){
+        arr.push(chunk);
+      });
+
+      // flag it as complete
+      stream.on('end', function(){
+        var cacheEntry = cache.add(key);
+        delete headers['x-cache']; // Clean up (TODO: others)
+        cacheEntry.push(200);
+        cacheEntry.push(headers);
+        cacheEntry.push.apply(cacheEntry, arr);
+      });
+    });
+
+    if (req.method == 'GET' || req.method == 'HEAD') {
+      if (ranges) {
+        next();
+      } else if (!hasCookies && hit && !mustRevalidate(req, hit)) {
+        res.setHeader('X-Cache', 'HIT');
+        respondFromCache(req, res, hit);
+      } else {
+        res.setHeader('X-Cache', 'MISS');
+        next();
+      }
+    } else {
+      next();
+    }
+  }
+};
+
+/**
+ * Respond with the provided cached value.
+ * TODO: Assume 200 code, that's iffy.
+ *
+ * @param {Object} req
+ * @param {Object} res
+ * @param {Object} cacheEntry
+ * @return {String}
+ * @api private
+ */
+
+function respondFromCache(req, res, cacheEntry) {
+  var status = cacheEntry[0]
+    , headers = utils.merge({}, cacheEntry[1])
+    , content = cacheEntry.slice(2);
+
+  headers.age = (new Date - new Date(headers.date)) / 1000 || 0;
+
+  switch (req.method) {
+    case 'HEAD':
+      res.writeHead(status, headers);
+      res.end();
+      break;
+    case 'GET':
+      if (utils.conditionalGET(req) && fresh(req.headers, headers)) {
+        headers['content-length'] = 0;
+        res.writeHead(304, headers);
+        res.end();
+      } else {
+        res.writeHead(status, headers);
+
+        function write() {
+          while (content.length) {
+            if (false === res.write(content.shift())) {
+              res.once('drain', write);
+              return;
+            }
+          }
+          res.end();
+        }
+
+        write();
+      }
+      break;
+    default:
+      // This should never happen.
+      res.writeHead(500, '');
+      res.end();
+  }
+}
+
+/**
+ * Determine whether or not a cached value must be revalidated.
+ *
+ * @param {Object} req
+ * @param {Object} cacheEntry
+ * @return {String}
+ * @api private
+ */
+
+function mustRevalidate(req, cacheEntry) {
+  var cacheHeaders = cacheEntry[1]
+    , reqCC = utils.parseCacheControl(req.headers['cache-control'] || '')
+    , cacheCC = utils.parseCacheControl(cacheHeaders['cache-control'] || '')
+    , cacheAge = (new Date - new Date(cacheHeaders.date)) / 1000 || 0;
+
+  if ( cacheCC['no-cache']
+    || cacheCC['must-revalidate']
+    || cacheCC['proxy-revalidate']) return true;
+
+  if (reqCC['no-cache']) return true;
+
+  if (null != reqCC['max-age']) return reqCC['max-age'] < cacheAge;
+
+  if (null != cacheCC['max-age']) return cacheCC['max-age'] < cacheAge;
+
+  return false;
+}
+
+/**
+ * The key to use in the cache. For now, this is the URL path and query.
+ *
+ * 'http://example.com?key=value' -> '/?key=value'
+ *
+ * @param {Object} req
+ * @return {String}
+ * @api private
+ */
+
+function cacheKey(req) {
+  return utils.parseUrl(req).path;
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/timeout.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/timeout.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/timeout.js	(revision 484)
@@ -0,0 +1,55 @@
+/*!
+ * Connect - timeout
+ * Ported from https://github.com/LearnBoost/connect-timeout
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var debug = require('debug')('connect:timeout');
+
+/**
+ * Timeout:
+ *
+ * Times out the request in `ms`, defaulting to `5000`. The
+ * method `req.clearTimeout()` is added to revert this behaviour
+ * programmatically within your application's middleware, routes, etc.
+ *
+ * The timeout error is passed to `next()` so that you may customize
+ * the response behaviour. This error has the `.timeout` property as
+ * well as `.status == 408`.
+ *
+ * @param {Number} ms
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function timeout(ms) {
+  ms = ms || 5000;
+
+  return function(req, res, next) {
+    var id = setTimeout(function(){
+      req.emit('timeout', ms);
+    }, ms);
+
+    req.on('timeout', function(){
+      if (res.headerSent) return debug('response started, cannot timeout');
+      var err = new Error('Response timeout');
+      err.timeout = ms;
+      err.status = 503;
+      next(err);
+    });
+
+    req.clearTimeout = function(){
+      clearTimeout(id);
+    };
+
+    res.on('header', function(){
+      clearTimeout(id);
+    });
+
+    next();
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/urlencoded.js	(revision 484)
@@ -0,0 +1,78 @@
+
+/*!
+ * Connect - urlencoded
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+  , _limit = require('./limit')
+  , qs = require('qs');
+
+/**
+ * noop middleware.
+ */
+
+function noop(req, res, next) {
+  next();
+}
+
+/**
+ * Urlencoded:
+ * 
+ *  Parse x-ww-form-urlencoded request bodies,
+ *  providing the parsed object as `req.body`.
+ *
+ * Options:
+ *
+ *    - `limit`  byte limit disabled by default
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function(options){
+  options = options || {};
+
+  var limit = options.limit
+    ? _limit(options.limit)
+    : noop;
+
+  return function urlencoded(req, res, next) {
+    if (req._body) return next();
+    req.body = req.body || {};
+
+    if (!utils.hasBody(req)) return next();
+
+    // check Content-Type
+    if ('application/x-www-form-urlencoded' != utils.mime(req)) return next();
+
+    // flag as parsed
+    req._body = true;
+
+    // parse
+    limit(req, res, function(err){
+      if (err) return next(err);
+      var buf = '';
+      req.setEncoding('utf8');
+      req.on('data', function(chunk){ buf += chunk });
+      req.on('end', function(){
+        try {
+          req.body = buf.length
+            ? qs.parse(buf, options)
+            : {};
+          next();
+        } catch (err){
+          err.body = buf;
+          next(err);
+        }
+      });
+    });
+  }
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/vhost.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/vhost.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/middleware/vhost.js	(revision 484)
@@ -0,0 +1,40 @@
+
+/*!
+ * Connect - vhost
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Vhost:
+ *
+ *   Setup vhost for the given `hostname` and `server`.
+ *
+ *     connect()
+ *       .use(connect.vhost('foo.com', fooApp))
+ *       .use(connect.vhost('bar.com', barApp))
+ *       .use(connect.vhost('*.com', mainApp))
+ *
+ *  The `server` may be a Connect server or
+ *  a regular Node `http.Server`.
+ *
+ * @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(/[^*\w]/g, '\\$&').replace(/[*]/g, '(?:.*?)')  + '$', 'i');
+  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 (!regexp.test(host)) return next();
+    if ('function' == typeof server) return server(req, res, next);
+    server.emit('request', req, res);
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/patch.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/patch.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/patch.js	(revision 484)
@@ -0,0 +1,79 @@
+
+/*!
+ * Connect
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , res = http.ServerResponse.prototype
+  , setHeader = res.setHeader
+  , _renderHeaders = res._renderHeaders
+  , writeHead = res.writeHead;
+
+// apply only once
+
+if (!res._hasConnectPatch) {
+
+  /**
+   * Provide a public "header sent" flag
+   * until node does.
+   *
+   * @return {Boolean}
+   * @api public
+   */
+
+  res.__defineGetter__('headerSent', function(){
+    return this._header;
+  });
+
+  /**
+   * Set header `field` to `val`, special-casing
+   * the `Set-Cookie` field for multiple support.
+   *
+   * @param {String} field
+   * @param {String} val
+   * @api public
+   */
+
+  res.setHeader = function(field, val){
+    var key = field.toLowerCase()
+      , prev;
+
+    // special-case Set-Cookie
+    if (this._headers && 'set-cookie' == key) {
+      if (prev = this.getHeader(field)) {
+        val = Array.isArray(prev)
+          ? prev.concat(val)
+          : [prev, val];
+      }
+    // charset
+    } else if ('content-type' == key && this.charset) {
+      val += '; charset=' + this.charset;
+    }
+
+    return setHeader.call(this, field, val);
+  };
+
+  /**
+   * Proxy to emit "header" event.
+   */
+
+  res._renderHeaders = function(){
+    if (!this._emittedHeader) this.emit('header');
+    this._emittedHeader = true;
+    return _renderHeaders.call(this);
+  };
+
+  res.writeHead = function(){
+    if (!this._emittedHeader) this.emit('header');
+    this._emittedHeader = true;
+    return writeHead.apply(this, arguments);
+  };
+
+  res._hasConnectPatch = true;
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/proto.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/proto.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/proto.js	(revision 484)
@@ -0,0 +1,230 @@
+
+/*!
+ * Connect - HTTPServer
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , utils = require('./utils')
+  , debug = require('debug')('connect:dispatcher');
+
+// prototype
+
+var app = module.exports = {};
+
+// environment
+
+var env = process.env.NODE_ENV || 'development';
+
+/**
+ * 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_.
+ *
+ * Examples:
+ *
+ *      var app = connect();
+ *      app.use(connect.favicon());
+ *      app.use(connect.logger());
+ *      app.use(connect.static(__dirname + '/public'));
+ *
+ * If we wanted to prefix static files with _/public_, we could
+ * "mount" the `static()` middleware:
+ *
+ *      app.use('/public', connect.static(__dirname + '/public'));
+ *
+ * This api is chainable, so the following is valid:
+ *
+ *      connect()
+ *        .use(connect.favicon())
+ *        .use(connect.logger())
+ *        .use(connect.static(__dirname + '/public'))
+ *        .listen(3000);
+ *
+ * @param {String|Function|Server} route, callback or server
+ * @param {Function|Server} callback or server
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.use = function(route, fn){
+  // default route to '/'
+  if ('string' != typeof route) {
+    fn = route;
+    route = '/';
+  }
+
+  // wrap sub-apps
+  if ('function' == typeof fn.handle) {
+    var server = fn;
+    fn.route = route;
+    fn = function(req, res, next){
+      server.handle(req, res, next);
+    };
+  }
+
+  // wrap vanilla http.Servers
+  if (fn instanceof http.Server) {
+    fn = fn.listeners('request')[0];
+  }
+
+  // strip trailing slash
+  if ('/' == route[route.length - 1]) {
+    route = route.slice(0, -1);
+  }
+
+  // add the middleware
+  debug('use %s %s', route || '/', fn.name || 'anonymous');
+  this.stack.push({ route: route, handle: fn });
+
+  return this;
+};
+
+/**
+ * Handle server requests, punting them down
+ * the middleware stack.
+ *
+ * @api private
+ */
+
+app.handle = function(req, res, out) {
+  var stack = this.stack
+    , fqdn = ~req.url.indexOf('://')
+    , removed = ''
+    , slashAdded = false
+    , index = 0;
+
+  function next(err) {
+    var layer, path, status, c;
+
+    if (slashAdded) {
+      req.url = req.url.substr(1);
+      slashAdded = false;
+    }
+
+    req.url = removed + req.url;
+    req.originalUrl = req.originalUrl || req.url;
+    removed = '';
+
+    // next callback
+    layer = stack[index++];
+
+    // all done
+    if (!layer || res.headerSent) {
+      // delegate to parent
+      if (out) return out(err);
+
+      // unhandled error
+      if (err) {
+        // default to 500
+        if (res.statusCode < 400) res.statusCode = 500;
+        debug('default %s', res.statusCode);
+
+        // respect err.status
+        if (err.status) res.statusCode = err.status;
+
+        // production gets a basic error message
+        var msg = 'production' == env
+          ? http.STATUS_CODES[res.statusCode]
+          : err.stack || err.toString();
+
+        // log to stderr in a non-test env
+        if ('test' != env) console.error(err.stack || err.toString());
+        if (res.headerSent) return req.socket.destroy();
+        res.setHeader('Content-Type', 'text/plain');
+        res.setHeader('Content-Length', Buffer.byteLength(msg));
+        if ('HEAD' == req.method) return res.end();
+        res.end(msg);
+      } else {
+        debug('default 404');
+        res.statusCode = 404;
+        res.setHeader('Content-Type', 'text/plain');
+        if ('HEAD' == req.method) return res.end();
+        res.end('Cannot ' + req.method + ' ' + utils.escape(req.originalUrl));
+      }
+      return;
+    }
+
+    try {
+      path = utils.parseUrl(req).pathname;
+      if (undefined == path) path = '/';
+
+      // skip this layer if the route doesn't match.
+      if (0 != path.toLowerCase().indexOf(layer.route.toLowerCase())) return next(err);
+
+      c = path[layer.route.length];
+      if (c && '/' != c && '.' != c) return next(err);
+
+      // Call the layer handler
+      // Trim off the part of the url that matches the route
+      removed = layer.route;
+      req.url = req.url.substr(removed.length);
+
+      // Ensure leading slash
+      if (!fqdn && '/' != req.url[0]) {
+        req.url = '/' + req.url;
+        slashAdded = true;
+      }
+
+      debug('%s', layer.handle.name || 'anonymous');
+      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) {
+      next(e);
+    }
+  }
+  next();
+};
+
+/**
+ * Listen for connections.
+ *
+ * This method takes the same arguments
+ * as node's `http.Server#listen()`.  
+ *
+ * HTTP and HTTPS:
+ *
+ * If you run your application both as HTTP
+ * and HTTPS you may wrap them individually,
+ * since your Connect "server" is really just
+ * a JavaScript `Function`.
+ *
+ *      var connect = require('connect')
+ *        , http = require('http')
+ *        , https = require('https');
+ *      
+ *      var app = connect();
+ *      
+ *      http.createServer(app).listen(80);
+ *      https.createServer(options, app).listen(443);
+ *
+ * @return {http.Server}
+ * @api public
+ */
+
+app.listen = function(){
+  var server = http.createServer(this);
+  return server.listen.apply(server, arguments);
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/public/directory.html
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/public/directory.html	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/public/directory.html	(revision 484)
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset='utf-8'> 
+    <title>listing directory {directory}</title>
+    <style>{style}</style>
+    <script>
+      function $(id){
+        var el = 'string' == typeof id
+          ? document.getElementById(id)
+          : id;
+
+        el.on = function(event, fn){
+          if ('content loaded' == event) {
+            event = window.attachEvent ? "load" : "DOMContentLoaded";
+          }
+          el.addEventListener
+            ? el.addEventListener(event, fn, false)
+            : el.attachEvent("on" + event, fn);
+        };
+
+        el.all = function(selector){
+          return $(el.querySelectorAll(selector));
+        };
+
+        el.each = function(fn){
+          for (var i = 0, len = el.length; i < len; ++i) {
+            fn($(el[i]), i);
+          }
+        };
+
+        el.getClasses = function(){
+          return this.getAttribute('class').split(/\s+/);
+        };
+
+        el.addClass = function(name){
+          var classes = this.getAttribute('class');
+          el.setAttribute('class', classes
+            ? classes + ' ' + name
+            : name);
+        };
+
+        el.removeClass = function(name){
+          var classes = this.getClasses().filter(function(curr){
+            return curr != name;
+          });
+          this.setAttribute('class', classes);
+        };
+
+        return el;
+      }
+
+      function search() {
+        var str = $('search').value
+          , links = $('files').all('a');
+
+        links.each(function(link){
+          var text = link.textContent;
+
+          if ('..' == text) return;
+          if (str.length && ~text.indexOf(str)) {
+            link.addClass('highlight');
+          } else {
+            link.removeClass('highlight');
+          }
+        });
+      }
+
+      $(window).on('content loaded', function(){
+        $('search').on('keyup', search);
+      });
+    </script>
+  </head>
+  <body class="directory">
+    <input id="search" type="text" placeholder="Search" autocomplete="off" />
+    <div id="wrapper">
+      <h1>{linked-path}</h1>
+      {files}
+    </div>
+  </body>
+</html>
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/public/error.html
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/public/error.html	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/public/error.html	(revision 484)
@@ -0,0 +1,14 @@
+<html>
+  <head>
+    <meta charset='utf-8'> 
+    <title>{error}</title>
+    <style>{style}</style>
+  </head>
+  <body>
+    <div id="wrapper">
+      <h1>{title}</h1>
+      <h2><em>{statusCode}</em> {error}</h2>
+      <ul id="stacktrace">{stack}</ul>
+    </div>
+  </body>
+</html>
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/public/style.css
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/public/style.css	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/public/style.css	(revision 484)
@@ -0,0 +1,141 @@
+body {
+  margin: 0;
+  padding: 80px 100px;
+  font: 13px "Helvetica Neue", "Lucida Grande", "Arial";
+  background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9));
+  background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9);
+  background-repeat: no-repeat;
+  color: #555;
+  -webkit-font-smoothing: antialiased;
+}
+h1, h2, h3 {
+  margin: 0;
+  font-size: 22px;
+  color: #343434;
+}
+h1 em, h2 em {
+  padding: 0 5px;
+  font-weight: normal;
+}
+h1 {
+  font-size: 60px;
+}
+h2 {
+	margin-top: 10px;
+}
+h3 {
+  margin: 5px 0 10px 0;
+  padding-bottom: 5px;
+  border-bottom: 1px solid #eee;
+  font-size: 18px;
+}
+ul {
+  margin: 0;
+  padding: 0;
+}
+ul li {
+  margin: 5px 0;
+  padding: 3px 8px;
+  list-style: none;
+}
+ul li:hover {
+  cursor: pointer;
+  color: #2e2e2e;
+}
+ul li .path {
+  padding-left: 5px;
+  font-weight: bold;
+}
+ul li .line {
+  padding-right: 5px;
+  font-style: italic;
+}
+ul li:first-child .path {
+  padding-left: 0;
+}
+p {
+  line-height: 1.5;
+}
+a {
+  color: #555;
+  text-decoration: none;
+}
+a:hover {
+  color: #303030;
+}
+#stacktrace {
+	margin-top: 15px;
+}
+.directory h1 {
+  margin-bottom: 15px;
+  font-size: 18px;
+}
+ul#files {
+  width: 100%;
+  height: 500px;
+}
+ul#files li {
+  padding: 0;
+}
+ul#files li img {
+  position: absolute;
+  top: 5px;
+  left: 5px;
+}
+ul#files li a {
+   position: relative;
+  display: block;
+  margin: 1px;
+  width: 30%;
+  height: 25px;
+  line-height: 25px;
+  text-indent: 8px;
+  float: left;
+  border: 1px solid transparent;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+ul#files li a.icon {
+  text-indent: 25px;
+}
+ul#files li a:focus,
+ul#files li a:hover {
+  outline: none;
+  background: rgba(255,255,255,0.65);
+  border: 1px solid #ececec;
+}
+ul#files li a.highlight {
+  -webkit-transition: background .4s ease-in-out;
+  background: #ffff4f;
+  border-color: #E9DC51;
+}
+#search {
+  display: block;
+  position: fixed;
+  top: 20px;
+  right: 20px;
+  width: 90px;
+  -webkit-transition: width ease 0.2s, opacity ease 0.4s;
+  -moz-transition: width ease 0.2s, opacity ease 0.4s;
+  -webkit-border-radius: 32px;
+  -moz-border-radius: 32px;
+  -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03);
+  -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03);
+  -webkit-font-smoothing: antialiased;
+  text-align: left;
+  font: 13px "Helvetica Neue", Arial, sans-serif;
+  padding: 4px 10px;
+  border: none;
+  background: transparent;
+  margin-bottom: 0;
+  outline: none;
+  opacity: 0.7;
+  color: #888;
+}
+#search:focus {
+  width: 120px;
+  opacity: 1.0; 
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/lib/utils.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/lib/utils.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/lib/utils.js	(revision 484)
@@ -0,0 +1,404 @@
+
+/*!
+ * Connect - utils
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+  , crypto = require('crypto')
+  , parse = require('url').parse
+  , signature = require('cookie-signature')
+  , nodeVersion = process.versions.node.split('.');
+
+// pause is broken in node < 0.10
+exports.brokenPause = parseInt(nodeVersion[0], 10) === 0
+  && parseInt(nodeVersion[1], 10) < 10;
+
+/**
+ * Return `true` if the request has a body, otherwise return `false`.
+ *
+ * @param  {IncomingMessage} req
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.hasBody = function(req) {
+  return 'transfer-encoding' in req.headers || 'content-length' in req.headers;
+};
+
+/**
+ * Extract the mime type from the given request's
+ * _Content-Type_ header.
+ *
+ * @param  {IncomingMessage} req
+ * @return {String}
+ * @api private
+ */
+
+exports.mime = function(req) {
+  var str = req.headers['content-type'] || '';
+  return str.split(';')[0];
+};
+
+/**
+ * Generate an `Error` from the given status `code`
+ * and optional `msg`.
+ *
+ * @param {Number} code
+ * @param {String} msg
+ * @return {Error}
+ * @api private
+ */
+
+exports.error = function(code, msg){
+  var err = new Error(msg || http.STATUS_CODES[code]);
+  err.status = code;
+  return err;
+};
+
+/**
+ * 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 private
+ */
+
+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 private
+ */
+
+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 private
+ */
+
+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 private
+ */
+
+exports.uid = function(len) {
+  return crypto.randomBytes(Math.ceil(len * 3 / 4))
+    .toString('base64')
+    .slice(0, len)
+    .replace(/\//g, '-')
+    .replace(/\+/g, '_');
+};
+
+/**
+ * Sign the given `val` with `secret`.
+ *
+ * @param {String} val
+ * @param {String} secret
+ * @return {String}
+ * @api private
+ */
+
+exports.sign = function(val, secret){
+  console.warn('do not use utils.sign(), use https://github.com/visionmedia/node-cookie-signature')
+  return val + '.' + crypto
+    .createHmac('sha256', secret)
+    .update(val)
+    .digest('base64')
+    .replace(/=+$/, '');
+};
+
+/**
+ * Unsign and decode the given `val` with `secret`,
+ * returning `false` if the signature is invalid.
+ *
+ * @param {String} val
+ * @param {String} secret
+ * @return {String|Boolean}
+ * @api private
+ */
+
+exports.unsign = function(val, secret){
+  console.warn('do not use utils.unsign(), use https://github.com/visionmedia/node-cookie-signature')
+  var str = val.slice(0, val.lastIndexOf('.'));
+  return exports.sign(str, secret) == val
+    ? str
+    : false;
+};
+
+/**
+ * Parse signed cookies, returning an object
+ * containing the decoded key/value pairs,
+ * while removing the signed key from `obj`.
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api private
+ */
+
+exports.parseSignedCookies = function(obj, secret){
+  var ret = {};
+  Object.keys(obj).forEach(function(key){
+    var val = obj[key];
+    if (0 == val.indexOf('s:')) {
+      val = signature.unsign(val.slice(2), secret);
+      if (val) {
+        ret[key] = val;
+        delete obj[key];
+      }
+    }
+  });
+  return ret;
+};
+
+/**
+ * Parse a signed cookie string, return the decoded value
+ *
+ * @param {String} str signed cookie string
+ * @param {String} secret
+ * @return {String} decoded value
+ * @api private
+ */
+
+exports.parseSignedCookie = function(str, secret){
+  return 0 == str.indexOf('s:')
+    ? signature.unsign(str.slice(2), secret)
+    : str;
+};
+
+/**
+ * Parse JSON cookies.
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api private
+ */
+
+exports.parseJSONCookies = function(obj){
+  Object.keys(obj).forEach(function(key){
+    var val = obj[key];
+    var res = exports.parseJSONCookie(val);
+    if (res) obj[key] = res;
+  });
+  return obj;
+};
+
+/**
+ * Parse JSON cookie string
+ *
+ * @param {String} str
+ * @return {Object} Parsed object or null if not json cookie
+ * @api private
+ */
+
+exports.parseJSONCookie = function(str) {
+  if (0 == str.indexOf('j:')) {
+    try {
+      return JSON.parse(str.slice(2));
+    } catch (err) {
+      // no op
+    }
+  }
+};
+
+/**
+ * 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. Pause is only required for
+ * node versions less than 10, and is replaced with
+ * noop's otherwise.
+ *
+ *      var pause = utils.pause(req);
+ *      fs.readFile(path, function(){
+ *         next();
+ *         pause.resume();
+ *      });
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api private
+ */
+
+exports.pause = exports.brokenPause
+  ? require('pause')
+  : function () {
+    return {
+      end: noop,
+      resume: noop
+    }
+  }
+
+/**
+ * Strip `Content-*` headers from `res`.
+ *
+ * @param {ServerResponse} res
+ * @api private
+ */
+
+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 private
+ */
+
+exports.conditionalGET = function(req) {
+  return req.headers['if-modified-since']
+    || req.headers['if-none-match'];
+};
+
+/**
+ * Respond with 401 "Unauthorized".
+ *
+ * @param {ServerResponse} res
+ * @param {String} realm
+ * @api private
+ */
+
+exports.unauthorized = function(res, realm) {
+  res.statusCode = 401;
+  res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"');
+  res.end('Unauthorized');
+};
+
+/**
+ * Respond with 304 "Not Modified".
+ *
+ * @param {ServerResponse} res
+ * @param {Object} headers
+ * @api private
+ */
+
+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 private
+ */
+
+exports.etag = function(stat) {
+  return '"' + stat.size + '-' + Number(stat.mtime) + '"';
+};
+
+/**
+ * Parse the given Cache-Control `str`.
+ *
+ * @param {String} str
+ * @return {Object}
+ * @api private
+ */
+
+exports.parseCacheControl = function(str){
+  var directives = str.split(',')
+    , obj = {};
+
+  for(var i = 0, len = directives.length; i < len; i++) {
+    var parts = directives[i].split('=')
+      , key = parts.shift().trim()
+      , val = parseInt(parts.shift(), 10);
+
+    obj[key] = isNaN(val) ? true : val;
+  }
+
+  return obj;
+};
+
+/**
+ * Parse the `req` url with memoization.
+ *
+ * @param {ServerRequest} req
+ * @return {Object}
+ * @api private
+ */
+
+exports.parseUrl = function(req){
+  var parsed = req._parsedUrl;
+  if (parsed && parsed.href == req.url) {
+    return parsed;
+  } else {
+    return req._parsedUrl = parse(req.url);
+  }
+};
+
+/**
+ * Parse byte `size` string.
+ *
+ * @param {String} size
+ * @return {Number}
+ * @api private
+ */
+
+exports.parseBytes = require('bytes');
+
+function noop() {}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/.npmignore	(revision 484)
@@ -0,0 +1,1 @@
+test
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/History.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/History.md	(revision 484)
@@ -0,0 +1,10 @@
+
+0.2.0 / 2012-10-28 
+==================
+
+  * bytes(200).should.eql('200b')
+
+0.1.0 / 2012-07-04 
+==================
+
+  * add bytes to string conversion [yields]
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/Makefile
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--reporter spec \
+		--require should
+
+.PHONY: test
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/Readme.md	(revision 484)
@@ -0,0 +1,51 @@
+# node-bytes
+
+  Byte string parser / formatter.
+
+## Example:
+
+```js
+bytes('1kb')
+// => 1024
+
+bytes('2mb')
+// => 2097152
+
+bytes('1gb')
+// => 1073741824
+
+bytes(1073741824)
+// => 1gb
+```
+
+## Installation
+
+```
+$ npm install bytes
+$ component install visionmedia/bytes.js
+```
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2012 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.
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/component.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/component.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/component.json	(revision 484)
@@ -0,0 +1,7 @@
+{
+  "name": "bytes",
+  "description": "byte size string parser / serializer",
+  "keywords": ["bytes", "utility"],
+  "version": "0.1.0",
+  "scripts": ["index.js"]
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/index.js	(revision 484)
@@ -0,0 +1,39 @@
+
+/**
+ * Parse byte `size` string.
+ *
+ * @param {String} size
+ * @return {Number}
+ * @api public
+ */
+
+module.exports = function(size) {
+  if ('number' == typeof size) return convert(size);
+  var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb)$/)
+    , n = parseFloat(parts[1])
+    , type = parts[2];
+
+  var map = {
+      kb: 1 << 10
+    , mb: 1 << 20
+    , gb: 1 << 30
+  };
+
+  return map[type] * n;
+};
+
+/**
+ * convert bytes into string.
+ *
+ * @param {Number} b - bytes to convert
+ * @return {String}
+ * @api public
+ */
+
+function convert (b) {
+  var gb = 1 << 30, mb = 1 << 20, kb = 1 << 10;
+  if (b >= gb) return (Math.round(b / gb * 100) / 100) + 'gb';
+  if (b >= mb) return (Math.round(b / mb * 100) / 100) + 'mb';
+  if (b >= kb) return (Math.round(b / kb * 100) / 100) + 'kb';
+  return b + 'b';
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/bytes/package.json	(revision 484)
@@ -0,0 +1,20 @@
+{
+  "name": "bytes",
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca",
+    "url": "http://tjholowaychuk.com"
+  },
+  "description": "byte size string parser / serializer",
+  "version": "0.2.0",
+  "main": "index.js",
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "readme": "# node-bytes\n\n  Byte string parser / formatter.\n\n## Example:\n\n```js\nbytes('1kb')\n// => 1024\n\nbytes('2mb')\n// => 2097152\n\nbytes('1gb')\n// => 1073741824\n\nbytes(1073741824)\n// => 1gb\n```\n\n## Installation\n\n```\n$ npm install bytes\n$ component install visionmedia/bytes.js\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
+  "readmeFilename": "Readme.md",
+  "_id": "bytes@0.2.0",
+  "_from": "bytes@0.2.0"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/.npmignore	(revision 484)
@@ -0,0 +1,1 @@
+node_modules
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/.travis.yml	(revision 484)
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+    - 0.6
+    - 0.8
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/README.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/README.md	(revision 484)
@@ -0,0 +1,44 @@
+# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) #
+
+cookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers.
+
+See [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies.
+
+## how?
+
+```
+npm install cookie
+```
+
+```javascript
+var cookie = require('cookie');
+
+var hdr = cookie.serialize('foo', 'bar');
+// hdr = 'foo=bar';
+
+var cookies = cookie.parse('foo=bar; cat=meow; dog=ruff');
+// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' };
+```
+
+## more
+
+The serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values.
+
+### path
+> cookie path
+
+### expires
+> absolute expiration date for the cookie (Date object)
+
+### maxAge
+> relative max age of the cookie from when the client receives it (seconds)
+
+### domain
+> domain for the cookie
+
+### secure
+> true or false
+
+### httpOnly
+> true or false
+
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/index.js	(revision 484)
@@ -0,0 +1,61 @@
+
+/// Serialize the a name value pair into a cookie string suitable for
+/// http headers. An optional options object specified cookie parameters
+///
+/// serialize('foo', 'bar', { httpOnly: true })
+///   => "foo=bar; httpOnly"
+///
+/// @param {String} name
+/// @param {String} val
+/// @param {Object} options
+/// @return {String}
+var serialize = function(name, val, opt){
+    var pairs = [name + '=' + encode(val)];
+    opt = opt || {};
+
+    if (opt.maxAge) pairs.push('Max-Age=' + opt.maxAge);
+    if (opt.domain) pairs.push('Domain=' + opt.domain);
+    if (opt.path) pairs.push('Path=' + opt.path);
+    if (opt.expires) pairs.push('Expires=' + opt.expires.toUTCString());
+    if (opt.httpOnly) pairs.push('HttpOnly');
+    if (opt.secure) pairs.push('Secure');
+
+    return pairs.join('; ');
+};
+
+/// Parse the given cookie header string into an object
+/// The object has the various cookies as keys(names) => values
+/// @param {String} str
+/// @return {Object}
+var parse = function(str) {
+    var obj = {}
+    var pairs = str.split(/[;,] */);
+
+    pairs.forEach(function(pair) {
+        var eq_idx = pair.indexOf('=')
+        var key = pair.substr(0, eq_idx).trim()
+        var val = pair.substr(++eq_idx, pair.length).trim();
+
+        // quoted values
+        if ('"' == val[0]) {
+            val = val.slice(1, -1);
+        }
+
+        // only assign once
+        if (undefined == obj[key]) {
+            try {
+                obj[key] = decode(val);
+            } catch (e) {
+                obj[key] = val;
+            }
+        }
+    });
+
+    return obj;
+};
+
+var encode = encodeURIComponent;
+var decode = decodeURIComponent;
+
+module.exports.serialize = serialize;
+module.exports.parse = parse;
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/package.json	(revision 484)
@@ -0,0 +1,36 @@
+{
+  "author": {
+    "name": "Roman Shtylman",
+    "email": "shtylman@gmail.com"
+  },
+  "name": "cookie",
+  "description": "cookie parsing and serialization",
+  "version": "0.0.5",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/shtylman/node-cookie.git"
+  },
+  "keywords": [
+    "cookie",
+    "cookies"
+  ],
+  "main": "index.js",
+  "scripts": {
+    "test": "mocha"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "1.x.x"
+  },
+  "optionalDependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "readme": "# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) #\n\ncookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers.\n\nSee [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies.\n\n## how?\n\n```\nnpm install cookie\n```\n\n```javascript\nvar cookie = require('cookie');\n\nvar hdr = cookie.serialize('foo', 'bar');\n// hdr = 'foo=bar';\n\nvar cookies = cookie.parse('foo=bar; cat=meow; dog=ruff');\n// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' };\n```\n\n## more\n\nThe serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values.\n\n### path\n> cookie path\n\n### expires\n> absolute expiration date for the cookie (Date object)\n\n### maxAge\n> relative max age of the cookie from when the client receives it (seconds)\n\n### domain\n> domain for the cookie\n\n### secure\n> true or false\n\n### httpOnly\n> true or false\n\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/shtylman/node-cookie/issues"
+  },
+  "_id": "cookie@0.0.5",
+  "_from": "cookie@0.0.5"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/test/mocha.opts
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/test/mocha.opts	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/test/mocha.opts	(revision 484)
@@ -0,0 +1,1 @@
+--ui qunit
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/test/parse.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/test/parse.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/test/parse.js	(revision 484)
@@ -0,0 +1,28 @@
+
+var assert = require('assert');
+
+var cookie = require('..');
+
+suite('parse');
+
+test('basic', function() {
+    assert.deepEqual({ foo: 'bar' }, cookie.parse('foo=bar'));
+    assert.deepEqual({ foo: '123' }, cookie.parse('foo=123'));
+});
+
+test('ignore spaces', function() {
+    assert.deepEqual({ FOO: 'bar', baz: 'raz' },
+            cookie.parse('FOO    = bar;   baz  =   raz'));
+});
+
+test('escaping', function() {
+    assert.deepEqual({ foo: 'bar=123456789&name=Magic+Mouse' },
+            cookie.parse('foo="bar=123456789&name=Magic+Mouse"'));
+
+    assert.deepEqual({ email: ' ",;/' },
+            cookie.parse('email=%20%22%2c%3b%2f'));
+});
+
+test('ignore escaping error and return original value', function() {
+    assert.deepEqual({ foo: '%1', bar: 'bar' }, cookie.parse('foo=%1;bar=bar'));
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/test/serialize.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/test/serialize.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/cookie/test/serialize.js	(revision 484)
@@ -0,0 +1,59 @@
+// builtin
+var assert = require('assert');
+
+var cookie = require('..');
+
+suite('serialize');
+
+test('basic', function() {
+    assert.equal('foo=bar', cookie.serialize('foo', 'bar'));
+    assert.equal('foo=bar%20baz', cookie.serialize('foo', 'bar baz'));
+});
+
+test('path', function() {
+    assert.equal('foo=bar; Path=/', cookie.serialize('foo', 'bar', {
+        path: '/'
+    }));
+});
+
+test('secure', function() {
+    assert.equal('foo=bar; Secure', cookie.serialize('foo', 'bar', {
+        secure: true
+    }));
+
+    assert.equal('foo=bar', cookie.serialize('foo', 'bar', {
+        secure: false
+    }));
+});
+
+test('domain', function() {
+    assert.equal('foo=bar; Domain=example.com', cookie.serialize('foo', 'bar', {
+        domain: 'example.com'
+    }));
+});
+
+test('httpOnly', function() {
+    assert.equal('foo=bar; HttpOnly', cookie.serialize('foo', 'bar', {
+        httpOnly: true
+    }));
+});
+
+test('maxAge', function() {
+    assert.equal('foo=bar; Max-Age=1000', cookie.serialize('foo', 'bar', {
+        maxAge: 1000
+    }));
+});
+
+test('escaping', function() {
+    assert.deepEqual('cat=%2B%20', cookie.serialize('cat', '+ '));
+});
+
+test('parse->serialize', function() {
+
+    assert.deepEqual({ cat: 'foo=123&name=baz five' }, cookie.parse(
+      cookie.serialize('cat', 'foo=123&name=baz five')));
+
+    assert.deepEqual({ cat: ' ";/' }, cookie.parse(
+      cookie.serialize('cat', ' ";/')));
+});
+
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/.npmignore	(revision 484)
@@ -0,0 +1,4 @@
+/test/tmp/
+*.upload
+*.un~
+*.http
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+  - 0.8
+  - 0.9
+  - "0.10"
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/LICENSE	(revision 484)
@@ -0,0 +1,7 @@
+Copyright (C) 2011 Felix GeisendÃ¶rfer
+
+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.
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md	(revision 484)
@@ -0,0 +1,419 @@
+# Formidable
+
+[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)
+
+## Purpose
+
+A node.js module for parsing form data, especially file uploads.
+
+## Current status
+
+This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading
+and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from
+a large variety of clients and is considered production-ready.
+
+## Features
+
+* Fast (~500mb/sec), non-buffering multipart parser
+* Automatically writing file uploads to disk
+* Low memory footprint
+* Graceful error handling
+* Very high test coverage
+
+## Installation
+
+Via [npm](http://github.com/isaacs/npm):
+```
+npm install formidable@latest
+```
+Manually:
+```
+git clone git://github.com/felixge/node-formidable.git formidable
+vim my.js
+# var formidable = require('./formidable');
+```
+
+Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.
+
+## Example
+
+Parse an incoming file upload.
+```javascript
+var formidable = require('formidable'),
+    http = require('http'),
+    util = require('util');
+
+http.createServer(function(req, res) {
+  if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
+    // parse a file upload
+    var form = new formidable.IncomingForm();
+
+    form.parse(req, function(err, fields, files) {
+      res.writeHead(200, {'content-type': 'text/plain'});
+      res.write('received upload:\n\n');
+      res.end(util.inspect({fields: fields, files: files}));
+    });
+
+    return;
+  }
+
+  // show a file upload form
+  res.writeHead(200, {'content-type': 'text/html'});
+  res.end(
+    '<form action="/upload" enctype="multipart/form-data" method="post">'+
+    '<input type="text" name="title"><br>'+
+    '<input type="file" name="upload" multiple="multiple"><br>'+
+    '<input type="submit" value="Upload">'+
+    '</form>'
+  );
+}).listen(8080);
+```
+## API
+
+### Formidable.IncomingForm
+```javascript
+var form = new formidable.IncomingForm()
+```
+Creates a new incoming form.
+
+```javascript
+form.encoding = 'utf-8';
+```
+Sets encoding for incoming form fields.
+
+```javascript
+form.uploadDir = process.env.TMP || process.env.TMPDIR || process.env.TEMP || '/tmp' || process.cwd();
+```
+The directory for placing file uploads in. You can move them later on using
+`fs.rename()`. The default directory is picked at module load time depending on
+the first existing directory from those listed above.
+
+```javascript
+form.keepExtensions = false;
+```
+If you want the files written to `form.uploadDir` to include the extensions of the original files, set this property to `true`.
+
+```javascript
+form.type
+```
+Either 'multipart' or 'urlencoded' depending on the incoming request.
+
+```javascript
+form.maxFieldsSize = 2 * 1024 * 1024;
+```
+Limits the amount of memory a field (not file) can allocate in bytes.
+If this value is exceeded, an `'error'` event is emitted. The default
+size is 2MB.
+
+```javascript
+form.maxFields = 0;
+```
+Limits the number of fields that the querystring parser will decode. Defaults
+to 0 (unlimited).
+
+```javascript
+form.hash = false;
+```
+If you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`.
+
+```javascript
+form.bytesReceived
+```
+The amount of bytes received for this form so far.
+
+```javascript
+form.bytesExpected
+```
+The expected number of bytes in this form.
+
+```javascript
+form.parse(request, [cb]);
+```
+Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback:
+
+
+```javascript
+form.parse(req, function(err, fields, files) {
+  // ...
+});
+
+form.onPart(part);
+```
+You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events  processing which would occur otherwise, making you fully responsible for handling the processing.
+
+```javascript
+form.onPart = function(part) {
+  part.addListener('data', function() {
+    // ...
+  });
+}
+```
+If you want to use formidable to only handle certain parts for you, you can do so:
+```javascript
+form.onPart = function(part) {
+  if (!part.filename) {
+    // let formidable handle all non-file parts
+    form.handlePart(part);
+  }
+}
+```
+Check the code in this method for further inspiration.
+
+
+### Formidable.File
+```javascript
+file.size = 0
+```
+The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.
+```javascript
+file.path = null
+```
+The path this file is being written to. You can modify this in the `'fileBegin'` event in
+case you are unhappy with the way formidable generates a temporary path for your files.
+```javascript
+file.name = null
+```
+The name this file had according to the uploading client.
+```javascript
+file.type = null
+```
+The mime type of this file, according to the uploading client.
+```javascript
+file.lastModifiedDate = null
+```
+A date object (or `null`) containing the time this file was last written to. Mostly
+here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
+```javascript
+file.hash = null
+```
+If hash calculation was set, you can read the hex digest out of this var.
+
+#### Formidable.File#toJSON()
+
+  This method returns a JSON-representation of the file, allowing you to
+  `JSON.stringify()` the file which is useful for logging and responding
+  to requests.
+
+### Events
+
+
+#### 'progress'
+```javascript
+form.on('progress', function(bytesReceived, bytesExpected) {
+});
+```
+Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.
+
+
+
+#### 'field'
+```javascript
+form.on('field', function(name, value) {
+});
+```
+
+#### 'fileBegin'
+
+Emitted whenever a field / value pair has been received.
+```javascript
+form.on('fileBegin', function(name, file) {
+});
+```
+
+#### 'file'
+
+Emitted whenever a new file is detected in the upload stream. Use this even if
+you want to stream the file to somewhere else while buffering the upload on
+the file system.
+
+Emitted whenever a field / file pair has been received. `file` is an instance of `File`.
+```javascript
+form.on('file', function(name, file) {
+});
+```
+
+#### 'error'
+
+Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.
+```javascript
+form.on('error', function(err) {
+});
+```
+
+#### 'aborted'
+
+
+Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).
+```javascript
+form.on('aborted', function() {
+});
+```
+
+##### 'end'
+```javascript
+form.on('end', function() {
+});
+```
+Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.
+
+
+
+## Changelog
+
+### v1.0.14
+
+* Add failing hash tests. (Ben Trask)
+* Enable hash calculation again (Eugene Girshov)
+* Test for immediate data events (Tim Smart)
+* Re-arrange IncomingForm#parse (Tim Smart)
+
+### v1.0.13
+
+* Only update hash if update method exists (Sven Lito)
+* According to travis v0.10 needs to go quoted (Sven Lito)
+* Bumping build node versions (Sven Lito)
+* Additional fix for empty requests (Eugene Girshov)
+* Change the default to 1000, to match the new Node behaviour. (OrangeDog)
+* Add ability to control maxKeys in the querystring parser. (OrangeDog)
+* Adjust test case to work with node 0.9.x (Eugene Girshov)
+* Update package.json (Sven Lito)
+* Path adjustment according to eb4468b (Markus Ast)
+
+### v1.0.12
+
+* Emit error on aborted connections (Eugene Girshov)
+* Add support for empty requests (Eugene Girshov)
+* Fix name/filename handling in Content-Disposition (jesperp)
+* Tolerate malformed closing boundary in multipart (Eugene Girshov)
+* Ignore preamble in multipart messages (Eugene Girshov)
+* Add support for application/json (Mike Frey, Carlos Rodriguez)
+* Add support for Base64 encoding (Elmer Bulthuis)
+* Add File#toJSON (TJ Holowaychuk)
+* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley)
+* Documentation improvements (Sven Lito, Andre Azevedo)
+* Add support for application/octet-stream (Ion Lupascu, Chris Scribner)
+* Use os.tmpDir() to get tmp directory (Andrew Kelley)
+* Improve package.json (Andrew Kelley, Sven Lito)
+* Fix benchmark script (Andrew Kelley)
+* Fix scope issue in incoming_forms (Sven Lito)
+* Fix file handle leak on error (OrangeDog)
+
+### v1.0.11
+
+* Calculate checksums for incoming files (sreuter)
+* Add definition parameters to "IncomingForm" as an argument (Math-)
+
+### v1.0.10
+
+* Make parts to be proper Streams (Matt Robenolt)
+
+### v1.0.9
+
+* Emit progress when content length header parsed (Tim KoschÃŒtzki)
+* Fix Readme syntax due to GitHub changes (goob)
+* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara)
+
+### v1.0.8
+
+* Strip potentially unsafe characters when using `keepExtensions: true`.
+* Switch to utest / urun for testing
+* Add travis build
+
+### v1.0.7
+
+* Remove file from package that was causing problems when installing on windows. (#102)
+* Fix typos in Readme (Jason Davies).
+
+### v1.0.6
+
+* Do not default to the default to the field name for file uploads where
+  filename="".
+
+### v1.0.5
+
+* Support filename="" in multipart parts
+* Explain unexpected end() errors in parser better
+
+**Note:** Starting with this version, formidable emits 'file' events for empty
+file input fields. Previously those were incorrectly emitted as regular file
+input fields with value = "".
+
+### v1.0.4
+
+* Detect a good default tmp directory regardless of platform. (#88)
+
+### v1.0.3
+
+* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)
+* Small performance improvements
+* New test suite and fixture system
+
+### v1.0.2
+
+* Exclude node\_modules folder from git
+* Implement new `'aborted'` event
+* Fix files in example folder to work with recent node versions
+* Make gently a devDependency
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)
+
+### v1.0.1
+
+* Fix package.json to refer to proper main directory. (#68, Dean Landolt)
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)
+
+### v1.0.0
+
+* Add support for multipart boundaries that are quoted strings. (Jeff Craig)
+
+This marks the beginning of development on version 2.0 which will include
+several architectural improvements.
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)
+
+### v0.9.11
+
+* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim KoschÃŒtzki)
+* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class
+
+**Important:** The old property names of the File class will be removed in a
+future release.
+
+[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)
+
+### Older releases
+
+These releases were done before starting to maintain the above Changelog:
+
+* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)
+* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)
+* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)
+* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)
+* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)
+* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)
+* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)
+* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)
+* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)
+* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
+* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)
+
+## License
+
+Formidable is licensed under the MIT license.
+
+## Ports
+
+* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable
+
+## Credits
+
+* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js	(revision 484)
@@ -0,0 +1,71 @@
+var assert = require('assert');
+require('../test/common');
+var multipartParser = require('../lib/multipart_parser'),
+    MultipartParser = multipartParser.MultipartParser,
+    parser = new MultipartParser(),
+    Buffer = require('buffer').Buffer,
+    boundary = '-----------------------------168072824752491622650073',
+    mb = 100,
+    buffer = createMultipartBuffer(boundary, mb * 1024 * 1024),
+    callbacks =
+      { partBegin: -1,
+        partEnd: -1,
+        headerField: -1,
+        headerValue: -1,
+        partData: -1,
+        end: -1,
+      };
+
+
+parser.initWithBoundary(boundary);
+parser.onHeaderField = function() {
+  callbacks.headerField++;
+};
+
+parser.onHeaderValue = function() {
+  callbacks.headerValue++;
+};
+
+parser.onPartBegin = function() {
+  callbacks.partBegin++;
+};
+
+parser.onPartData = function() {
+  callbacks.partData++;
+};
+
+parser.onPartEnd = function() {
+  callbacks.partEnd++;
+};
+
+parser.onEnd = function() {
+  callbacks.end++;
+};
+
+var start = +new Date(),
+    nparsed = parser.write(buffer),
+    duration = +new Date - start,
+    mbPerSec = (mb / (duration / 1000)).toFixed(2);
+
+console.log(mbPerSec+' mb/sec');
+
+assert.equal(nparsed, buffer.length);
+
+function createMultipartBuffer(boundary, size) {
+  var head =
+        '--'+boundary+'\r\n'
+      + 'content-disposition: form-data; name="field1"\r\n'
+      + '\r\n'
+    , tail = '\r\n--'+boundary+'--\r\n'
+    , buffer = new Buffer(size);
+
+  buffer.write(head, 'ascii', 0);
+  buffer.write(tail, 'ascii', buffer.length - tail.length);
+  return buffer;
+}
+
+process.on('exit', function() {
+  for (var k in callbacks) {
+    assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]);
+  }
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/example/json.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/example/json.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/example/json.js	(revision 484)
@@ -0,0 +1,67 @@
+var common = require('../test/common'),
+    http = require('http'),
+    util = require('util'),
+    formidable = common.formidable,
+    Buffer = require('buffer').Buffer,
+    port = common.port,
+    server;
+
+server = http.createServer(function(req, res) {
+  if (req.method !== 'POST') {
+    res.writeHead(200, {'content-type': 'text/plain'})
+    res.end('Please POST a JSON payload to http://localhost:'+port+'/')
+    return;
+  }
+
+  var form = new formidable.IncomingForm(),
+      fields = {};
+
+  form
+    .on('error', function(err) {
+      res.writeHead(500, {'content-type': 'text/plain'});
+      res.end('error:\n\n'+util.inspect(err));
+      console.error(err);
+    })
+    .on('field', function(field, value) {
+      console.log(field, value);
+      fields[field] = value;
+    })
+    .on('end', function() {
+      console.log('-> post done');
+      res.writeHead(200, {'content-type': 'text/plain'});
+      res.end('received fields:\n\n '+util.inspect(fields));
+    });
+  form.parse(req);
+});
+server.listen(port);
+
+console.log('listening on http://localhost:'+port+'/');
+
+
+var request = http.request({
+  host: 'localhost',
+  path: '/',
+  port: port,
+  method: 'POST',
+  headers: { 'content-type':'application/json', 'content-length':48 }
+}, function(response) {
+  var data = '';
+  console.log('\nServer responded with:');
+  console.log('Status:', response.statusCode);
+  response.pipe(process.stdout);
+  response.on('end', function() {
+    console.log('\n')
+    process.exit();
+  });
+  // response.on('data', function(chunk) {
+  //   data += chunk.toString('utf8');
+  // });
+  // response.on('end', function() {
+  //   console.log('Response Data:')
+  //   console.log(data);
+  //   process.exit();
+  // });
+})
+
+request.write('{"numbers":[1,2,3,4,5],"nested":{"key":"value"}}');
+request.end();
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js	(revision 484)
@@ -0,0 +1,43 @@
+require('../test/common');
+var http = require('http'),
+    util = require('util'),
+    formidable = require('formidable'),
+    server;
+
+server = http.createServer(function(req, res) {
+  if (req.url == '/') {
+    res.writeHead(200, {'content-type': 'text/html'});
+    res.end(
+      '<form action="/post" method="post">'+
+      '<input type="text" name="title"><br>'+
+      '<input type="text" name="data[foo][]"><br>'+
+      '<input type="submit" value="Submit">'+
+      '</form>'
+    );
+  } else if (req.url == '/post') {
+    var form = new formidable.IncomingForm(),
+        fields = [];
+
+    form
+      .on('error', function(err) {
+        res.writeHead(200, {'content-type': 'text/plain'});
+        res.end('error:\n\n'+util.inspect(err));
+      })
+      .on('field', function(field, value) {
+        console.log(field, value);
+        fields.push([field, value]);
+      })
+      .on('end', function() {
+        console.log('-> post done');
+        res.writeHead(200, {'content-type': 'text/plain'});
+        res.end('received fields:\n\n '+util.inspect(fields));
+      });
+    form.parse(req);
+  } else {
+    res.writeHead(404, {'content-type': 'text/plain'});
+    res.end('404');
+  }
+});
+server.listen(TEST_PORT);
+
+console.log('listening on http://localhost:'+TEST_PORT+'/');
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js	(revision 484)
@@ -0,0 +1,48 @@
+require('../test/common');
+var http = require('http'),
+    util = require('util'),
+    formidable = require('formidable'),
+    server;
+
+server = http.createServer(function(req, res) {
+  if (req.url == '/') {
+    res.writeHead(200, {'content-type': 'text/html'});
+    res.end(
+      '<form action="/upload" enctype="multipart/form-data" method="post">'+
+      '<input type="text" name="title"><br>'+
+      '<input type="file" name="upload" multiple="multiple"><br>'+
+      '<input type="submit" value="Upload">'+
+      '</form>'
+    );
+  } else if (req.url == '/upload') {
+    var form = new formidable.IncomingForm(),
+        files = [],
+        fields = [];
+
+    form.uploadDir = TEST_TMP;
+
+    form
+      .on('field', function(field, value) {
+        console.log(field, value);
+        fields.push([field, value]);
+      })
+      .on('file', function(field, file) {
+        console.log(field, file);
+        files.push([field, file]);
+      })
+      .on('end', function() {
+        console.log('-> upload done');
+        res.writeHead(200, {'content-type': 'text/plain'});
+        res.write('received fields:\n\n '+util.inspect(fields));
+        res.write('\n\n');
+        res.end('received files:\n\n '+util.inspect(files));
+      });
+    form.parse(req);
+  } else {
+    res.writeHead(404, {'content-type': 'text/plain'});
+    res.end('404');
+  }
+});
+server.listen(TEST_PORT);
+
+console.log('listening on http://localhost:'+TEST_PORT+'/');
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/index.js	(revision 484)
@@ -0,0 +1,1 @@
+module.exports = require('./lib');
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js	(revision 484)
@@ -0,0 +1,72 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var util = require('util'),
+    WriteStream = require('fs').WriteStream,
+    EventEmitter = require('events').EventEmitter,
+    crypto = require('crypto');
+
+function File(properties) {
+  EventEmitter.call(this);
+
+  this.size = 0;
+  this.path = null;
+  this.name = null;
+  this.type = null;
+  this.hash = null;
+  this.lastModifiedDate = null;
+
+  this._writeStream = null;
+  
+  for (var key in properties) {
+    this[key] = properties[key];
+  }
+
+  if(typeof this.hash === 'string') {
+    this.hash = crypto.createHash(properties.hash);
+  } else {
+    this.hash = null;
+  }
+}
+module.exports = File;
+util.inherits(File, EventEmitter);
+
+File.prototype.open = function() {
+  this._writeStream = new WriteStream(this.path);
+};
+
+File.prototype.toJSON = function() {
+  return {
+    size: this.size,
+    path: this.path,
+    name: this.name,
+    type: this.type,
+    mtime: this.lastModifiedDate,
+    length: this.length,
+    filename: this.filename,
+    mime: this.mime
+  };
+};
+
+File.prototype.write = function(buffer, cb) {
+  var self = this;
+  if (self.hash) {
+    self.hash.update(buffer);
+  }
+  this._writeStream.write(buffer, function() {
+    self.lastModifiedDate = new Date();
+    self.size += buffer.length;
+    self.emit('progress', self.size);
+    cb();
+  });
+};
+
+File.prototype.end = function(cb) {
+  var self = this;
+  if (self.hash) {
+    self.hash = self.hash.digest('hex');
+  }
+  this._writeStream.end(function() {
+    self.emit('end');
+    cb();
+  });
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js	(revision 484)
@@ -0,0 +1,535 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var fs = require('fs');
+var util = require('util'),
+    path = require('path'),
+    File = require('./file'),
+    MultipartParser = require('./multipart_parser').MultipartParser,
+    QuerystringParser = require('./querystring_parser').QuerystringParser,
+    OctetParser       = require('./octet_parser').OctetParser,
+    JSONParser = require('./json_parser').JSONParser,
+    StringDecoder = require('string_decoder').StringDecoder,
+    EventEmitter = require('events').EventEmitter,
+    Stream = require('stream').Stream,
+    os = require('os');
+
+function IncomingForm(opts) {
+  if (!(this instanceof IncomingForm)) return new IncomingForm(opts);
+  EventEmitter.call(this);
+
+  opts=opts||{};
+
+  this.error = null;
+  this.ended = false;
+
+  this.maxFields = opts.maxFields || 1000;
+  this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024;
+  this.keepExtensions = opts.keepExtensions || false;
+  this.uploadDir = opts.uploadDir || os.tmpDir();
+  this.encoding = opts.encoding || 'utf-8';
+  this.headers = null;
+  this.type = null;
+  this.hash = false;
+
+  this.bytesReceived = null;
+  this.bytesExpected = null;
+
+  this._parser = null;
+  this._flushing = 0;
+  this._fieldsSize = 0;
+  this.openedFiles = [];
+
+  return this;
+};
+util.inherits(IncomingForm, EventEmitter);
+exports.IncomingForm = IncomingForm;
+
+IncomingForm.prototype.parse = function(req, cb) {
+  this.pause = function() {
+    try {
+      req.pause();
+    } catch (err) {
+      // the stream was destroyed
+      if (!this.ended) {
+        // before it was completed, crash & burn
+        this._error(err);
+      }
+      return false;
+    }
+    return true;
+  };
+
+  this.resume = function() {
+    try {
+      req.resume();
+    } catch (err) {
+      // the stream was destroyed
+      if (!this.ended) {
+        // before it was completed, crash & burn
+        this._error(err);
+      }
+      return false;
+    }
+
+    return true;
+  };
+
+  // Setup callback first, so we don't miss anything from data events emitted
+  // immediately.
+  if (cb) {
+    var fields = {}, files = {};
+    this
+      .on('field', function(name, value) {
+        fields[name] = value;
+      })
+      .on('file', function(name, file) {
+        files[name] = file;
+      })
+      .on('error', function(err) {
+        cb(err, fields, files);
+      })
+      .on('end', function() {
+        cb(null, fields, files);
+      });
+  }
+
+  // Parse headers and setup the parser, ready to start listening for data.
+  this.writeHeaders(req.headers);
+
+  // Start listening for data.
+  var self = this;
+  req
+    .on('error', function(err) {
+      self._error(err);
+    })
+    .on('aborted', function() {
+      self.emit('aborted');
+      self._error(new Error('Request aborted'));
+    })
+    .on('data', function(buffer) {
+      self.write(buffer);
+    })
+    .on('end', function() {
+      if (self.error) {
+        return;
+      }
+
+      var err = self._parser.end();
+      if (err) {
+        self._error(err);
+      }
+    });
+
+  return this;
+};
+
+IncomingForm.prototype.writeHeaders = function(headers) {
+  this.headers = headers;
+  this._parseContentLength();
+  this._parseContentType();
+};
+
+IncomingForm.prototype.write = function(buffer) {
+  if (!this._parser) {
+    this._error(new Error('unintialized parser'));
+    return;
+  }
+
+  this.bytesReceived += buffer.length;
+  this.emit('progress', this.bytesReceived, this.bytesExpected);
+
+  var bytesParsed = this._parser.write(buffer);
+  if (bytesParsed !== buffer.length) {
+    this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed'));
+  }
+
+  return bytesParsed;
+};
+
+IncomingForm.prototype.pause = function() {
+  // this does nothing, unless overwritten in IncomingForm.parse
+  return false;
+};
+
+IncomingForm.prototype.resume = function() {
+  // this does nothing, unless overwritten in IncomingForm.parse
+  return false;
+};
+
+IncomingForm.prototype.onPart = function(part) {
+  // this method can be overwritten by the user
+  this.handlePart(part);
+};
+
+IncomingForm.prototype.handlePart = function(part) {
+  var self = this;
+
+  if (part.filename === undefined) {
+    var value = ''
+      , decoder = new StringDecoder(this.encoding);
+
+    part.on('data', function(buffer) {
+      self._fieldsSize += buffer.length;
+      if (self._fieldsSize > self.maxFieldsSize) {
+        self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data'));
+        return;
+      }
+      value += decoder.write(buffer);
+    });
+
+    part.on('end', function() {
+      self.emit('field', part.name, value);
+    });
+    return;
+  }
+
+  this._flushing++;
+
+  var file = new File({
+    path: this._uploadPath(part.filename),
+    name: part.filename,
+    type: part.mime,
+    hash: self.hash
+  });
+
+  this.emit('fileBegin', part.name, file);
+
+  file.open();
+  this.openedFiles.push(file);
+
+  part.on('data', function(buffer) {
+    self.pause();
+    file.write(buffer, function() {
+      self.resume();
+    });
+  });
+
+  part.on('end', function() {
+    file.end(function() {
+      self._flushing--;
+      self.emit('file', part.name, file);
+      self._maybeEnd();
+    });
+  });
+};
+
+function dummyParser(self) {
+  return {
+    end: function () {
+      self.ended = true;
+      self._maybeEnd();
+      return null;
+    }
+  };
+}
+
+IncomingForm.prototype._parseContentType = function() {
+  if (this.bytesExpected === 0) {
+    this._parser = dummyParser(this);
+    return;
+  }
+
+  if (!this.headers['content-type']) {
+    this._error(new Error('bad content-type header, no content-type'));
+    return;
+  }
+
+  if (this.headers['content-type'].match(/octet-stream/i)) {
+    this._initOctetStream();
+    return;
+  }
+
+  if (this.headers['content-type'].match(/urlencoded/i)) {
+    this._initUrlencoded();
+    return;
+  }
+
+  if (this.headers['content-type'].match(/multipart/i)) {
+    var m;
+    if (m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i)) {
+      this._initMultipart(m[1] || m[2]);
+    } else {
+      this._error(new Error('bad content-type header, no multipart boundary'));
+    }
+    return;
+  }
+
+  if (this.headers['content-type'].match(/json/i)) {
+    this._initJSONencoded();
+    return;
+  }
+
+  this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type']));
+};
+
+IncomingForm.prototype._error = function(err) {
+  if (this.error || this.ended) {
+    return;
+  }
+
+  this.error = err;
+  this.pause();
+  this.emit('error', err);
+
+  if (Array.isArray(this.openedFiles)) {
+    this.openedFiles.forEach(function(file) {
+      file._writeStream.destroy();
+      setTimeout(fs.unlink, 0, file.path);
+    });
+  }
+};
+
+IncomingForm.prototype._parseContentLength = function() {
+  this.bytesReceived = 0;
+  if (this.headers['content-length']) {
+    this.bytesExpected = parseInt(this.headers['content-length'], 10);
+  } else if (this.headers['transfer-encoding'] === undefined) {
+    this.bytesExpected = 0;
+  }
+
+  if (this.bytesExpected !== null) {
+    this.emit('progress', this.bytesReceived, this.bytesExpected);
+  }
+};
+
+IncomingForm.prototype._newParser = function() {
+  return new MultipartParser();
+};
+
+IncomingForm.prototype._initMultipart = function(boundary) {
+  this.type = 'multipart';
+
+  var parser = new MultipartParser(),
+      self = this,
+      headerField,
+      headerValue,
+      part;
+
+  parser.initWithBoundary(boundary);
+
+  parser.onPartBegin = function() {
+    part = new Stream();
+    part.readable = true;
+    part.headers = {};
+    part.name = null;
+    part.filename = null;
+    part.mime = null;
+
+    part.transferEncoding = 'binary';
+    part.transferBuffer = '';
+
+    headerField = '';
+    headerValue = '';
+  };
+
+  parser.onHeaderField = function(b, start, end) {
+    headerField += b.toString(self.encoding, start, end);
+  };
+
+  parser.onHeaderValue = function(b, start, end) {
+    headerValue += b.toString(self.encoding, start, end);
+  };
+
+  parser.onHeaderEnd = function() {
+    headerField = headerField.toLowerCase();
+    part.headers[headerField] = headerValue;
+
+    var m;
+    if (headerField == 'content-disposition') {
+      if (m = headerValue.match(/\bname="([^"]+)"/i)) {
+        part.name = m[1];
+      }
+
+      part.filename = self._fileName(headerValue);
+    } else if (headerField == 'content-type') {
+      part.mime = headerValue;
+    } else if (headerField == 'content-transfer-encoding') {
+      part.transferEncoding = headerValue.toLowerCase();
+    }
+
+    headerField = '';
+    headerValue = '';
+  };
+
+  parser.onHeadersEnd = function() {
+    switch(part.transferEncoding){
+      case 'binary':
+      case '7bit':
+      case '8bit':
+      parser.onPartData = function(b, start, end) {
+        part.emit('data', b.slice(start, end));
+      };
+
+      parser.onPartEnd = function() {
+        part.emit('end');
+      };
+      break;
+
+      case 'base64':
+      parser.onPartData = function(b, start, end) {
+        part.transferBuffer += b.slice(start, end).toString('ascii');
+
+        /*
+        four bytes (chars) in base64 converts to three bytes in binary
+        encoding. So we should always work with a number of bytes that
+        can be divided by 4, it will result in a number of buytes that
+        can be divided vy 3.
+        */
+        var offset = parseInt(part.transferBuffer.length / 4) * 4;
+        part.emit('data', new Buffer(part.transferBuffer.substring(0, offset), 'base64'))
+        part.transferBuffer = part.transferBuffer.substring(offset);
+      };
+
+      parser.onPartEnd = function() {
+        part.emit('data', new Buffer(part.transferBuffer, 'base64'))
+        part.emit('end');
+      };
+      break;
+
+      default:
+      return self._error(new Error('unknown transfer-encoding'));
+    }
+
+    self.onPart(part);
+  };
+
+
+  parser.onEnd = function() {
+    self.ended = true;
+    self._maybeEnd();
+  };
+
+  this._parser = parser;
+};
+
+IncomingForm.prototype._fileName = function(headerValue) {
+  var m = headerValue.match(/\bfilename="(.*?)"($|; )/i);
+  if (!m) return;
+
+  var filename = m[1].substr(m[1].lastIndexOf('\\') + 1);
+  filename = filename.replace(/%22/g, '"');
+  filename = filename.replace(/&#([\d]{4});/g, function(m, code) {
+    return String.fromCharCode(code);
+  });
+  return filename;
+};
+
+IncomingForm.prototype._initUrlencoded = function() {
+  this.type = 'urlencoded';
+
+  var parser = new QuerystringParser(this.maxFields)
+    , self = this;
+
+  parser.onField = function(key, val) {
+    self.emit('field', key, val);
+  };
+
+  parser.onEnd = function() {
+    self.ended = true;
+    self._maybeEnd();
+  };
+
+  this._parser = parser;
+};
+
+IncomingForm.prototype._initOctetStream = function() {
+  this.type = 'octet-stream';
+  var filename = this.headers['x-file-name'];
+  var mime = this.headers['content-type'];
+
+  var file = new File({
+    path: this._uploadPath(filename),
+    name: filename,
+    type: mime
+  });
+
+  file.open();
+
+  this.emit('fileBegin', filename, file);
+
+  this._flushing++;
+
+  var self = this;
+
+  self._parser = new OctetParser();
+
+  //Keep track of writes that haven't finished so we don't emit the file before it's done being written
+  var outstandingWrites = 0;
+
+  self._parser.on('data', function(buffer){
+    self.pause();
+    outstandingWrites++;
+
+    file.write(buffer, function() {
+      outstandingWrites--;
+      self.resume();
+
+      if(self.ended){
+        self._parser.emit('doneWritingFile');
+      }
+    });
+  });
+
+  self._parser.on('end', function(){
+    self._flushing--;
+    self.ended = true;
+
+    var done = function(){
+      self.emit('file', 'file', file);
+      self._maybeEnd();
+    };
+
+    if(outstandingWrites === 0){
+      done();
+    } else {
+      self._parser.once('doneWritingFile', done);
+    }
+  });
+};
+
+IncomingForm.prototype._initJSONencoded = function() {
+  this.type = 'json';
+
+  var parser = new JSONParser()
+    , self = this;
+
+  if (this.bytesExpected) {
+    parser.initWithLength(this.bytesExpected);
+  }
+
+  parser.onField = function(key, val) {
+    self.emit('field', key, val);
+  }
+
+  parser.onEnd = function() {
+    self.ended = true;
+    self._maybeEnd();
+  };
+
+  this._parser = parser;
+};
+
+IncomingForm.prototype._uploadPath = function(filename) {
+  var name = '';
+  for (var i = 0; i < 32; i++) {
+    name += Math.floor(Math.random() * 16).toString(16);
+  }
+
+  if (this.keepExtensions) {
+    var ext = path.extname(filename);
+    ext     = ext.replace(/(\.[a-z0-9]+).*/, '$1');
+
+    name += ext;
+  }
+
+  return path.join(this.uploadDir, name);
+};
+
+IncomingForm.prototype._maybeEnd = function() {
+  if (!this.ended || this._flushing || this.error) {
+    return;
+  }
+
+  this.emit('end');
+};
+
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js	(revision 484)
@@ -0,0 +1,3 @@
+var IncomingForm = require('./incoming_form').IncomingForm;
+IncomingForm.IncomingForm = IncomingForm;
+module.exports = IncomingForm;
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/json_parser.js	(revision 484)
@@ -0,0 +1,35 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+var Buffer = require('buffer').Buffer
+
+function JSONParser() {
+  this.data = new Buffer('');
+  this.bytesWritten = 0;
+};
+exports.JSONParser = JSONParser;
+
+JSONParser.prototype.initWithLength = function(length) {
+  this.data = new Buffer(length);
+}
+
+JSONParser.prototype.write = function(buffer) {
+  if (this.data.length >= this.bytesWritten + buffer.length) {
+    buffer.copy(this.data, this.bytesWritten);
+  } else {
+    this.data = Buffer.concat([this.data, buffer]);
+  }
+  this.bytesWritten += buffer.length;
+  return buffer.length;
+}
+
+JSONParser.prototype.end = function() {
+  try {
+    var fields = JSON.parse(this.data.toString('utf8'))
+    for (var field in fields) {
+      this.onField(field, fields[field]);
+    }
+  } catch (e) {}
+  this.data = null;
+
+  this.onEnd();
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js	(revision 484)
@@ -0,0 +1,324 @@
+var Buffer = require('buffer').Buffer,
+    s = 0,
+    S =
+    { PARSER_UNINITIALIZED: s++,
+      START: s++,
+      START_BOUNDARY: s++,
+      HEADER_FIELD_START: s++,
+      HEADER_FIELD: s++,
+      HEADER_VALUE_START: s++,
+      HEADER_VALUE: s++,
+      HEADER_VALUE_ALMOST_DONE: s++,
+      HEADERS_ALMOST_DONE: s++,
+      PART_DATA_START: s++,
+      PART_DATA: s++,
+      PART_END: s++,
+      END: s++
+    },
+
+    f = 1,
+    F =
+    { PART_BOUNDARY: f,
+      LAST_BOUNDARY: f *= 2
+    },
+
+    LF = 10,
+    CR = 13,
+    SPACE = 32,
+    HYPHEN = 45,
+    COLON = 58,
+    A = 97,
+    Z = 122,
+
+    lower = function(c) {
+      return c | 0x20;
+    };
+
+for (s in S) {
+  exports[s] = S[s];
+}
+
+function MultipartParser() {
+  this.boundary = null;
+  this.boundaryChars = null;
+  this.lookbehind = null;
+  this.state = S.PARSER_UNINITIALIZED;
+
+  this.index = null;
+  this.flags = 0;
+};
+exports.MultipartParser = MultipartParser;
+
+MultipartParser.stateToString = function(stateNumber) {
+  for (var state in S) {
+    var number = S[state];
+    if (number === stateNumber) return state;
+  }
+};
+
+MultipartParser.prototype.initWithBoundary = function(str) {
+  this.boundary = new Buffer(str.length+4);
+  this.boundary.write('\r\n--', 'ascii', 0);
+  this.boundary.write(str, 'ascii', 4);
+  this.lookbehind = new Buffer(this.boundary.length+8);
+  this.state = S.START;
+
+  this.boundaryChars = {};
+  for (var i = 0; i < this.boundary.length; i++) {
+    this.boundaryChars[this.boundary[i]] = true;
+  }
+};
+
+MultipartParser.prototype.write = function(buffer) {
+  var self = this,
+      i = 0,
+      len = buffer.length,
+      prevIndex = this.index,
+      index = this.index,
+      state = this.state,
+      flags = this.flags,
+      lookbehind = this.lookbehind,
+      boundary = this.boundary,
+      boundaryChars = this.boundaryChars,
+      boundaryLength = this.boundary.length,
+      boundaryEnd = boundaryLength - 1,
+      bufferLength = buffer.length,
+      c,
+      cl,
+
+      mark = function(name) {
+        self[name+'Mark'] = i;
+      },
+      clear = function(name) {
+        delete self[name+'Mark'];
+      },
+      callback = function(name, buffer, start, end) {
+        if (start !== undefined && start === end) {
+          return;
+        }
+
+        var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
+        if (callbackSymbol in self) {
+          self[callbackSymbol](buffer, start, end);
+        }
+      },
+      dataCallback = function(name, clear) {
+        var markSymbol = name+'Mark';
+        if (!(markSymbol in self)) {
+          return;
+        }
+
+        if (!clear) {
+          callback(name, buffer, self[markSymbol], buffer.length);
+          self[markSymbol] = 0;
+        } else {
+          callback(name, buffer, self[markSymbol], i);
+          delete self[markSymbol];
+        }
+      };
+
+  for (i = 0; i < len; i++) {
+    c = buffer[i];
+    switch (state) {
+      case S.PARSER_UNINITIALIZED:
+        return i;
+      case S.START:
+        index = 0;
+        state = S.START_BOUNDARY;
+      case S.START_BOUNDARY:
+        if (index == boundary.length - 2) {
+          if (c != CR) {
+            return i;
+          }
+          index++;
+          break;
+        } else if (index - 1 == boundary.length - 2) {
+          if (c != LF) {
+            return i;
+          }
+          index = 0;
+          callback('partBegin');
+          state = S.HEADER_FIELD_START;
+          break;
+        }
+
+        if (c != boundary[index+2]) {
+          index = -2;
+        }
+        if (c == boundary[index+2]) {
+          index++;
+        }
+        break;
+      case S.HEADER_FIELD_START:
+        state = S.HEADER_FIELD;
+        mark('headerField');
+        index = 0;
+      case S.HEADER_FIELD:
+        if (c == CR) {
+          clear('headerField');
+          state = S.HEADERS_ALMOST_DONE;
+          break;
+        }
+
+        index++;
+        if (c == HYPHEN) {
+          break;
+        }
+
+        if (c == COLON) {
+          if (index == 1) {
+            // empty header field
+            return i;
+          }
+          dataCallback('headerField', true);
+          state = S.HEADER_VALUE_START;
+          break;
+        }
+
+        cl = lower(c);
+        if (cl < A || cl > Z) {
+          return i;
+        }
+        break;
+      case S.HEADER_VALUE_START:
+        if (c == SPACE) {
+          break;
+        }
+
+        mark('headerValue');
+        state = S.HEADER_VALUE;
+      case S.HEADER_VALUE:
+        if (c == CR) {
+          dataCallback('headerValue', true);
+          callback('headerEnd');
+          state = S.HEADER_VALUE_ALMOST_DONE;
+        }
+        break;
+      case S.HEADER_VALUE_ALMOST_DONE:
+        if (c != LF) {
+          return i;
+        }
+        state = S.HEADER_FIELD_START;
+        break;
+      case S.HEADERS_ALMOST_DONE:
+        if (c != LF) {
+          return i;
+        }
+
+        callback('headersEnd');
+        state = S.PART_DATA_START;
+        break;
+      case S.PART_DATA_START:
+        state = S.PART_DATA;
+        mark('partData');
+      case S.PART_DATA:
+        prevIndex = index;
+
+        if (index == 0) {
+          // boyer-moore derrived algorithm to safely skip non-boundary data
+          i += boundaryEnd;
+          while (i < bufferLength && !(buffer[i] in boundaryChars)) {
+            i += boundaryLength;
+          }
+          i -= boundaryEnd;
+          c = buffer[i];
+        }
+
+        if (index < boundary.length) {
+          if (boundary[index] == c) {
+            if (index == 0) {
+              dataCallback('partData', true);
+            }
+            index++;
+          } else {
+            index = 0;
+          }
+        } else if (index == boundary.length) {
+          index++;
+          if (c == CR) {
+            // CR = part boundary
+            flags |= F.PART_BOUNDARY;
+          } else if (c == HYPHEN) {
+            // HYPHEN = end boundary
+            flags |= F.LAST_BOUNDARY;
+          } else {
+            index = 0;
+          }
+        } else if (index - 1 == boundary.length)  {
+          if (flags & F.PART_BOUNDARY) {
+            index = 0;
+            if (c == LF) {
+              // unset the PART_BOUNDARY flag
+              flags &= ~F.PART_BOUNDARY;
+              callback('partEnd');
+              callback('partBegin');
+              state = S.HEADER_FIELD_START;
+              break;
+            }
+          } else if (flags & F.LAST_BOUNDARY) {
+            if (c == HYPHEN) {
+              callback('partEnd');
+              callback('end');
+              state = S.END;
+            } else {
+              index = 0;
+            }
+          } else {
+            index = 0;
+          }
+        }
+
+        if (index > 0) {
+          // when matching a possible boundary, keep a lookbehind reference
+          // in case it turns out to be a false lead
+          lookbehind[index-1] = c;
+        } else if (prevIndex > 0) {
+          // if our boundary turned out to be rubbish, the captured lookbehind
+          // belongs to partData
+          callback('partData', lookbehind, 0, prevIndex);
+          prevIndex = 0;
+          mark('partData');
+
+          // reconsider the current character even so it interrupted the sequence
+          // it could be the beginning of a new sequence
+          i--;
+        }
+
+        break;
+      case S.END:
+        break;
+      default:
+        return i;
+    }
+  }
+
+  dataCallback('headerField');
+  dataCallback('headerValue');
+  dataCallback('partData');
+
+  this.index = index;
+  this.state = state;
+  this.flags = flags;
+
+  return len;
+};
+
+MultipartParser.prototype.end = function() {
+  var callback = function(self, name) {
+    var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1);
+    if (callbackSymbol in self) {
+      self[callbackSymbol]();
+    }
+  };
+  if ((this.state == S.HEADER_FIELD_START && this.index == 0) ||
+      (this.state == S.PART_DATA && this.index == this.boundary.length)) {
+    callback(this, 'partEnd');
+    callback(this, 'end');
+  } else if (this.state != S.END) {
+    return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain());
+  }
+};
+
+MultipartParser.prototype.explain = function() {
+  return 'state = ' + MultipartParser.stateToString(this.state);
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/octet_parser.js	(revision 484)
@@ -0,0 +1,20 @@
+var EventEmitter = require('events').EventEmitter
+	, util = require('util');
+
+function OctetParser(options){
+	if(!(this instanceof OctetParser)) return new OctetParser(options);
+	EventEmitter.call(this);
+}
+
+util.inherits(OctetParser, EventEmitter);
+
+exports.OctetParser = OctetParser;
+
+OctetParser.prototype.write = function(buffer) {
+    this.emit('data', buffer);
+	return buffer.length;
+};
+
+OctetParser.prototype.end = function() {
+	this.emit('end');
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js	(revision 484)
@@ -0,0 +1,27 @@
+if (global.GENTLY) require = GENTLY.hijack(require);
+
+// This is a buffering parser, not quite as nice as the multipart one.
+// If I find time I'll rewrite this to be fully streaming as well
+var querystring = require('querystring');
+
+function QuerystringParser(maxKeys) {
+  this.maxKeys = maxKeys;
+  this.buffer = '';
+};
+exports.QuerystringParser = QuerystringParser;
+
+QuerystringParser.prototype.write = function(buffer) {
+  this.buffer += buffer.toString('ascii');
+  return buffer.length;
+};
+
+QuerystringParser.prototype.end = function() {
+  var fields = querystring.parse(this.buffer, '&', '=', { maxKeys: this.maxKeys });
+  for (var field in fields) {
+    this.onField(field, fields[field]);
+  }
+  this.buffer = '';
+
+  this.onEnd();
+};
+
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/package.json	(revision 484)
@@ -0,0 +1,38 @@
+{
+  "name": "formidable",
+  "description": "A node.js module for parsing form data, especially file uploads.",
+  "homepage": "https://github.com/felixge/node-formidable",
+  "version": "1.0.14",
+  "devDependencies": {
+    "gently": "0.8.0",
+    "findit": "0.1.1",
+    "hashish": "0.0.4",
+    "urun": "~0.0.6",
+    "utest": "0.0.3",
+    "request": "~2.11.4"
+  },
+  "directories": {
+    "lib": "./lib"
+  },
+  "main": "./lib/index",
+  "scripts": {
+    "test": "node test/run.js",
+    "clean": "rm test/tmp/*"
+  },
+  "engines": {
+    "node": ">=0.8.0"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/felixge/node-formidable.git"
+  },
+  "bugs": {
+    "url": "http://github.com/felixge/node-formidable/issues"
+  },
+  "optionalDependencies": {},
+  "readme": "# Formidable\n\n[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png?branch=master)](http://travis-ci.org/felixge/node-formidable)\n\n## Purpose\n\nA node.js module for parsing form data, especially file uploads.\n\n## Current status\n\nThis module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading\nand encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from\na large variety of clients and is considered production-ready.\n\n## Features\n\n* Fast (~500mb/sec), non-buffering multipart parser\n* Automatically writing file uploads to disk\n* Low memory footprint\n* Graceful error handling\n* Very high test coverage\n\n## Installation\n\nVia [npm](http://github.com/isaacs/npm):\n```\nnpm install formidable@latest\n```\nManually:\n```\ngit clone git://github.com/felixge/node-formidable.git formidable\nvim my.js\n# var formidable = require('./formidable');\n```\n\nNote: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.\n\n## Example\n\nParse an incoming file upload.\n```javascript\nvar formidable = require('formidable'),\n    http = require('http'),\n    util = require('util');\n\nhttp.createServer(function(req, res) {\n  if (req.url == '/upload' && req.method.toLowerCase() == 'post') {\n    // parse a file upload\n    var form = new formidable.IncomingForm();\n\n    form.parse(req, function(err, fields, files) {\n      res.writeHead(200, {'content-type': 'text/plain'});\n      res.write('received upload:\\n\\n');\n      res.end(util.inspect({fields: fields, files: files}));\n    });\n\n    return;\n  }\n\n  // show a file upload form\n  res.writeHead(200, {'content-type': 'text/html'});\n  res.end(\n    '<form action=\"/upload\" enctype=\"multipart/form-data\" method=\"post\">'+\n    '<input type=\"text\" name=\"title\"><br>'+\n    '<input type=\"file\" name=\"upload\" multiple=\"multiple\"><br>'+\n    '<input type=\"submit\" value=\"Upload\">'+\n    '</form>'\n  );\n}).listen(8080);\n```\n## API\n\n### Formidable.IncomingForm\n```javascript\nvar form = new formidable.IncomingForm()\n```\nCreates a new incoming form.\n\n```javascript\nform.encoding = 'utf-8';\n```\nSets encoding for incoming form fields.\n\n```javascript\nform.uploadDir = process.env.TMP || process.env.TMPDIR || process.env.TEMP || '/tmp' || process.cwd();\n```\nThe directory for placing file uploads in. You can move them later on using\n`fs.rename()`. The default directory is picked at module load time depending on\nthe first existing directory from those listed above.\n\n```javascript\nform.keepExtensions = false;\n```\nIf you want the files written to `form.uploadDir` to include the extensions of the original files, set this property to `true`.\n\n```javascript\nform.type\n```\nEither 'multipart' or 'urlencoded' depending on the incoming request.\n\n```javascript\nform.maxFieldsSize = 2 * 1024 * 1024;\n```\nLimits the amount of memory a field (not file) can allocate in bytes.\nIf this value is exceeded, an `'error'` event is emitted. The default\nsize is 2MB.\n\n```javascript\nform.maxFields = 0;\n```\nLimits the number of fields that the querystring parser will decode. Defaults\nto 0 (unlimited).\n\n```javascript\nform.hash = false;\n```\nIf you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`.\n\n```javascript\nform.bytesReceived\n```\nThe amount of bytes received for this form so far.\n\n```javascript\nform.bytesExpected\n```\nThe expected number of bytes in this form.\n\n```javascript\nform.parse(request, [cb]);\n```\nParses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback:\n\n\n```javascript\nform.parse(req, function(err, fields, files) {\n  // ...\n});\n\nform.onPart(part);\n```\nYou may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events  processing which would occur otherwise, making you fully responsible for handling the processing.\n\n```javascript\nform.onPart = function(part) {\n  part.addListener('data', function() {\n    // ...\n  });\n}\n```\nIf you want to use formidable to only handle certain parts for you, you can do so:\n```javascript\nform.onPart = function(part) {\n  if (!part.filename) {\n    // let formidable handle all non-file parts\n    form.handlePart(part);\n  }\n}\n```\nCheck the code in this method for further inspiration.\n\n\n### Formidable.File\n```javascript\nfile.size = 0\n```\nThe size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.\n```javascript\nfile.path = null\n```\nThe path this file is being written to. You can modify this in the `'fileBegin'` event in\ncase you are unhappy with the way formidable generates a temporary path for your files.\n```javascript\nfile.name = null\n```\nThe name this file had according to the uploading client.\n```javascript\nfile.type = null\n```\nThe mime type of this file, according to the uploading client.\n```javascript\nfile.lastModifiedDate = null\n```\nA date object (or `null`) containing the time this file was last written to. Mostly\nhere for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).\n```javascript\nfile.hash = null\n```\nIf hash calculation was set, you can read the hex digest out of this var.\n\n#### Formidable.File#toJSON()\n\n  This method returns a JSON-representation of the file, allowing you to\n  `JSON.stringify()` the file which is useful for logging and responding\n  to requests.\n\n### Events\n\n\n#### 'progress'\n```javascript\nform.on('progress', function(bytesReceived, bytesExpected) {\n});\n```\nEmitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.\n\n\n\n#### 'field'\n```javascript\nform.on('field', function(name, value) {\n});\n```\n\n#### 'fileBegin'\n\nEmitted whenever a field / value pair has been received.\n```javascript\nform.on('fileBegin', function(name, file) {\n});\n```\n\n#### 'file'\n\nEmitted whenever a new file is detected in the upload stream. Use this even if\nyou want to stream the file to somewhere else while buffering the upload on\nthe file system.\n\nEmitted whenever a field / file pair has been received. `file` is an instance of `File`.\n```javascript\nform.on('file', function(name, file) {\n});\n```\n\n#### 'error'\n\nEmitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.\n```javascript\nform.on('error', function(err) {\n});\n```\n\n#### 'aborted'\n\n\nEmitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).\n```javascript\nform.on('aborted', function() {\n});\n```\n\n##### 'end'\n```javascript\nform.on('end', function() {\n});\n```\nEmitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.\n\n\n\n## Changelog\n\n### v1.0.14\n\n* Add failing hash tests. (Ben Trask)\n* Enable hash calculation again (Eugene Girshov)\n* Test for immediate data events (Tim Smart)\n* Re-arrange IncomingForm#parse (Tim Smart)\n\n### v1.0.13\n\n* Only update hash if update method exists (Sven Lito)\n* According to travis v0.10 needs to go quoted (Sven Lito)\n* Bumping build node versions (Sven Lito)\n* Additional fix for empty requests (Eugene Girshov)\n* Change the default to 1000, to match the new Node behaviour. (OrangeDog)\n* Add ability to control maxKeys in the querystring parser. (OrangeDog)\n* Adjust test case to work with node 0.9.x (Eugene Girshov)\n* Update package.json (Sven Lito)\n* Path adjustment according to eb4468b (Markus Ast)\n\n### v1.0.12\n\n* Emit error on aborted connections (Eugene Girshov)\n* Add support for empty requests (Eugene Girshov)\n* Fix name/filename handling in Content-Disposition (jesperp)\n* Tolerate malformed closing boundary in multipart (Eugene Girshov)\n* Ignore preamble in multipart messages (Eugene Girshov)\n* Add support for application/json (Mike Frey, Carlos Rodriguez)\n* Add support for Base64 encoding (Elmer Bulthuis)\n* Add File#toJSON (TJ Holowaychuk)\n* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley)\n* Documentation improvements (Sven Lito, Andre Azevedo)\n* Add support for application/octet-stream (Ion Lupascu, Chris Scribner)\n* Use os.tmpDir() to get tmp directory (Andrew Kelley)\n* Improve package.json (Andrew Kelley, Sven Lito)\n* Fix benchmark script (Andrew Kelley)\n* Fix scope issue in incoming_forms (Sven Lito)\n* Fix file handle leak on error (OrangeDog)\n\n### v1.0.11\n\n* Calculate checksums for incoming files (sreuter)\n* Add definition parameters to \"IncomingForm\" as an argument (Math-)\n\n### v1.0.10\n\n* Make parts to be proper Streams (Matt Robenolt)\n\n### v1.0.9\n\n* Emit progress when content length header parsed (Tim KoschÃŒtzki)\n* Fix Readme syntax due to GitHub changes (goob)\n* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara)\n\n### v1.0.8\n\n* Strip potentially unsafe characters when using `keepExtensions: true`.\n* Switch to utest / urun for testing\n* Add travis build\n\n### v1.0.7\n\n* Remove file from package that was causing problems when installing on windows. (#102)\n* Fix typos in Readme (Jason Davies).\n\n### v1.0.6\n\n* Do not default to the default to the field name for file uploads where\n  filename=\"\".\n\n### v1.0.5\n\n* Support filename=\"\" in multipart parts\n* Explain unexpected end() errors in parser better\n\n**Note:** Starting with this version, formidable emits 'file' events for empty\nfile input fields. Previously those were incorrectly emitted as regular file\ninput fields with value = \"\".\n\n### v1.0.4\n\n* Detect a good default tmp directory regardless of platform. (#88)\n\n### v1.0.3\n\n* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)\n* Small performance improvements\n* New test suite and fixture system\n\n### v1.0.2\n\n* Exclude node\\_modules folder from git\n* Implement new `'aborted'` event\n* Fix files in example folder to work with recent node versions\n* Make gently a devDependency\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)\n\n### v1.0.1\n\n* Fix package.json to refer to proper main directory. (#68, Dean Landolt)\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)\n\n### v1.0.0\n\n* Add support for multipart boundaries that are quoted strings. (Jeff Craig)\n\nThis marks the beginning of development on version 2.0 which will include\nseveral architectural improvements.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)\n\n### v0.9.11\n\n* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim KoschÃŒtzki)\n* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class\n\n**Important:** The old property names of the File class will be removed in a\nfuture release.\n\n[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)\n\n### Older releases\n\nThese releases were done before starting to maintain the above Changelog:\n\n* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)\n* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)\n* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)\n* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)\n* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)\n* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)\n* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)\n* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)\n* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)\n* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)\n* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)\n\n## License\n\nFormidable is licensed under the MIT license.\n\n## Ports\n\n* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable\n\n## Credits\n\n* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js\n",
+  "readmeFilename": "Readme.md",
+  "dependencies": {},
+  "_id": "formidable@1.0.14",
+  "_from": "formidable@1.0.14"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js	(revision 484)
@@ -0,0 +1,18 @@
+var path = require('path');
+
+var root = path.join(__dirname, '../');
+exports.dir = {
+  root    : root,
+  lib     : root + '/lib',
+  fixture : root + '/test/fixture',
+  tmp     : root + '/test/tmp',
+};
+
+exports.port = 13532;
+
+exports.formidable = require('..');
+exports.assert     = require('assert');
+
+exports.require = function(lib) {
+  return require(exports.dir.lib + '/' + lib);
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt	(revision 484)
@@ -0,0 +1,1 @@
+I am a text file with a funky name!
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt	(revision 484)
@@ -0,0 +1,1 @@
+I am a plain text file
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md	(revision 484)
@@ -0,0 +1,3 @@
+* Opera does not allow submitting this file, it shows a warning to the
+  user that the file could not be found instead. Tested in 9.8, 11.51 on OSX.
+  Reported to Opera on 08.09.2011 (tracking email DSK-346009@bugs.opera.com).
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/encoding.js	(revision 484)
@@ -0,0 +1,24 @@
+module.exports['menu_seperator.png.http'] = [
+  {type: 'file', name: 'image', filename: 'menu_separator.png', fixture: 'menu_separator.png',
+  sha1: 'c845ca3ea794be298f2a1b79769b71939eaf4e54'}
+];
+
+module.exports['beta-sticker-1.png.http'] = [
+  {type: 'file', name: 'sticker', filename: 'beta-sticker-1.png', fixture: 'beta-sticker-1.png',
+  sha1: '6abbcffd12b4ada5a6a084fe9e4584f846331bc4'}
+];
+
+module.exports['blank.gif.http'] = [
+  {type: 'file', name: 'file', filename: 'blank.gif', fixture: 'blank.gif',
+  sha1: 'a1fdee122b95748d81cee426d717c05b5174fe96'}
+];
+
+module.exports['binaryfile.tar.gz.http'] = [
+  {type: 'file', name: 'file', filename: 'binaryfile.tar.gz', fixture: 'binaryfile.tar.gz',
+  sha1: 'cfabe13b348e5e69287d677860880c52a69d2155'}
+];
+
+module.exports['plain.txt.http'] = [
+  {type: 'file', name: 'file', filename: 'plain.txt', fixture: 'plain.txt',
+  sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}
+];
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/misc.js	(revision 484)
@@ -0,0 +1,6 @@
+module.exports = {
+  'empty.http': [],
+  'empty-urlencoded.http': [],
+  'empty-multipart.http': [],
+  'minimal.http': [],
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js	(revision 484)
@@ -0,0 +1,9 @@
+module.exports['generic.http'] = [
+  {type: 'file', name: 'upload', filename: '', fixture: 'plain.txt',
+  sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
+];
+
+module.exports['filename-name.http'] = [
+  {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt',
+  sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
+];
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/preamble.js	(revision 484)
@@ -0,0 +1,9 @@
+module.exports['crlf.http'] = [
+  {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt',
+  sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
+];
+
+module.exports['preamble.http'] = [
+  {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt',
+  sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
+];
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js	(revision 484)
@@ -0,0 +1,21 @@
+var properFilename = 'funkyfilename.txt';
+
+function expect(filename) {
+  return [
+    {type: 'field', name: 'title', value: 'Weird filename'},
+    {type: 'file', name: 'upload', filename: filename, fixture: properFilename},
+  ];
+};
+
+var webkit = " ? % * | \" < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt";
+var ffOrIe = " ? % * | \" < > . â ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt";
+
+module.exports = {
+  'osx-chrome-13.http'   : expect(webkit),
+  'osx-firefox-3.6.http' : expect(ffOrIe),
+  'osx-safari-5.http'    : expect(webkit),
+  'xp-chrome-12.http'    : expect(webkit),
+  'xp-ie-7.http'         : expect(ffOrIe),
+  'xp-ie-8.http'         : expect(ffOrIe),
+  'xp-safari-5.http'     : expect(webkit),
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/workarounds.js	(revision 484)
@@ -0,0 +1,8 @@
+module.exports['missing-hyphens1.http'] = [
+  {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt',
+  sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
+];
+module.exports['missing-hyphens2.http'] = [
+  {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt',
+  sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
+];
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js	(revision 484)
@@ -0,0 +1,72 @@
+exports['rfc1867'] =
+  { boundary: 'AaB03x',
+    raw:
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="field1"\r\n'+
+      '\r\n'+
+      'Joe Blow\r\nalmost tricked you!\r\n'+
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
+      'Content-Type: text/plain\r\n'+
+      '\r\n'+
+      '... contents of file1.txt ...\r\r\n'+
+      '--AaB03x--\r\n',
+    parts:
+    [ { headers: {
+          'content-disposition': 'form-data; name="field1"',
+        },
+        data: 'Joe Blow\r\nalmost tricked you!',
+      },
+      { headers: {
+          'content-disposition': 'form-data; name="pics"; filename="file1.txt"',
+          'Content-Type': 'text/plain',
+        },
+        data: '... contents of file1.txt ...\r',
+      }
+    ]
+  };
+
+exports['noTrailing\r\n'] =
+  { boundary: 'AaB03x',
+    raw:
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="field1"\r\n'+
+      '\r\n'+
+      'Joe Blow\r\nalmost tricked you!\r\n'+
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
+      'Content-Type: text/plain\r\n'+
+      '\r\n'+
+      '... contents of file1.txt ...\r\r\n'+
+      '--AaB03x--',
+    parts:
+    [ { headers: {
+          'content-disposition': 'form-data; name="field1"',
+        },
+        data: 'Joe Blow\r\nalmost tricked you!',
+      },
+      { headers: {
+          'content-disposition': 'form-data; name="pics"; filename="file1.txt"',
+          'Content-Type': 'text/plain',
+        },
+        data: '... contents of file1.txt ...\r',
+      }
+    ]
+  };
+
+exports['emptyHeader'] =
+  { boundary: 'AaB03x',
+    raw:
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="field1"\r\n'+
+      ': foo\r\n'+
+      '\r\n'+
+      'Joe Blow\r\nalmost tricked you!\r\n'+
+      '--AaB03x\r\n'+
+      'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+
+      'Content-Type: text/plain\r\n'+
+      '\r\n'+
+      '... contents of file1.txt ...\r\r\n'+
+      '--AaB03x--\r\n',
+    expectError: true,
+  };
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js	(revision 484)
@@ -0,0 +1,96 @@
+var hashish = require('hashish');
+var fs = require('fs');
+var findit = require('findit');
+var path = require('path');
+var http = require('http');
+var net = require('net');
+var assert = require('assert');
+
+var common = require('../common');
+var formidable = common.formidable;
+
+var server = http.createServer();
+server.listen(common.port, findFixtures);
+
+function findFixtures() {
+  var fixtures = [];
+  findit
+    .sync(common.dir.fixture + '/js')
+    .forEach(function(jsPath) {
+      if (!/\.js$/.test(jsPath)) return;
+
+      var group = path.basename(jsPath, '.js');
+      hashish.forEach(require(jsPath), function(fixture, name) {
+        fixtures.push({
+          name    : group + '/' + name,
+          fixture : fixture,
+        });
+      });
+    });
+
+  testNext(fixtures);
+}
+
+function testNext(fixtures) {
+  var fixture = fixtures.shift();
+  if (!fixture) return server.close();
+
+  var name    = fixture.name;
+  var fixture = fixture.fixture;
+
+  uploadFixture(name, function(err, parts) {
+    if (err) throw err;
+
+    fixture.forEach(function(expectedPart, i) {
+      var parsedPart = parts[i];
+      assert.equal(parsedPart.type, expectedPart.type);
+      assert.equal(parsedPart.name, expectedPart.name);
+
+      if (parsedPart.type === 'file') {
+        var file = parsedPart.value;
+        assert.equal(file.name, expectedPart.filename);
+        if(expectedPart.sha1) assert.equal(file.hash, expectedPart.sha1);
+      }
+    });
+
+    testNext(fixtures);
+  });
+};
+
+function uploadFixture(name, cb) {
+  server.once('request', function(req, res) {
+    var form = new formidable.IncomingForm();
+    form.uploadDir = common.dir.tmp;
+    form.hash = "sha1";
+    form.parse(req);
+
+    function callback() {
+      var realCallback = cb;
+      cb = function() {};
+      realCallback.apply(null, arguments);
+    }
+
+    var parts = [];
+    form
+      .on('error', callback)
+      .on('fileBegin', function(name, value) {
+        parts.push({type: 'file', name: name, value: value});
+      })
+      .on('field', function(name, value) {
+        parts.push({type: 'field', name: name, value: value});
+      })
+      .on('end', function() {
+        res.end('OK');
+        callback(null, parts);
+      });
+  });
+
+  var socket = net.createConnection(common.port);
+  var file = fs.createReadStream(common.dir.fixture + '/http/' + name);
+
+  file.pipe(socket, {end: false});
+  socket.on('data', function () {
+    socket.end();
+  });
+
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-json.js	(revision 484)
@@ -0,0 +1,38 @@
+var common = require('../common');
+var formidable = common.formidable;
+var http = require('http');
+var assert = require('assert');
+
+var testData = {
+  numbers: [1, 2, 3, 4, 5],
+  nested: { key: 'value' }
+};
+
+var server = http.createServer(function(req, res) {
+    var form = new formidable.IncomingForm();
+
+    form.parse(req, function(err, fields, files) {
+        assert.deepEqual(fields, testData);
+
+        res.end();
+        server.close();
+    });
+});
+
+var port = common.port;
+
+server.listen(port, function(err){
+    assert.equal(err, null);
+
+    var request = http.request({
+        port: port,
+        method: 'POST',
+        headers: {
+            'Content-Type': 'application/json'
+        }
+    });
+
+    request.write(JSON.stringify(testData));
+    request.end();
+});
+
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-octet-stream.js	(revision 484)
@@ -0,0 +1,45 @@
+var common = require('../common');
+var formidable = common.formidable;
+var http = require('http');
+var fs = require('fs');
+var path = require('path');
+var hashish = require('hashish');
+var assert = require('assert');
+
+var testFilePath = path.join(__dirname, '../fixture/file/binaryfile.tar.gz');
+
+var server = http.createServer(function(req, res) {
+    var form = new formidable.IncomingForm();
+
+    form.parse(req, function(err, fields, files) {
+        assert.equal(hashish(files).length, 1);
+        var file = files.file;
+
+        assert.equal(file.size, 301);
+
+        var uploaded = fs.readFileSync(file.path);
+        var original = fs.readFileSync(testFilePath);
+
+        assert.deepEqual(uploaded, original);
+
+        res.end();
+        server.close();
+    });
+});
+
+var port = common.port;
+
+server.listen(port, function(err){
+    assert.equal(err, null);
+
+    var request = http.request({
+        port: port,
+        method: 'POST',
+        headers: {
+            'Content-Type': 'application/octet-stream'
+        }
+    });
+
+    fs.createReadStream(testFilePath).pipe(request);
+});
+
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js	(revision 484)
@@ -0,0 +1,24 @@
+var path = require('path'),
+    fs = require('fs');
+
+try {
+  global.Gently = require('gently');
+} catch (e) {
+  throw new Error('this test suite requires node-gently');
+}
+
+exports.lib = path.join(__dirname, '../../lib');
+
+global.GENTLY = new Gently();
+
+global.assert = require('assert');
+global.TEST_PORT = 13532;
+global.TEST_FIXTURES = path.join(__dirname, '../fixture');
+global.TEST_TMP = path.join(__dirname, '../tmp');
+
+// Stupid new feature in node that complains about gently attaching too many
+// listeners to process 'exit'. This is a workaround until I can think of a
+// better way to deal with this.
+if (process.setMaxListeners) {
+  process.setMaxListeners(10000);
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js	(revision 484)
@@ -0,0 +1,80 @@
+var common = require('../common');
+var CHUNK_LENGTH = 10,
+    multipartParser = require(common.lib + '/multipart_parser'),
+    MultipartParser = multipartParser.MultipartParser,
+    parser = new MultipartParser(),
+    fixtures = require(TEST_FIXTURES + '/multipart'),
+    Buffer = require('buffer').Buffer;
+
+Object.keys(fixtures).forEach(function(name) {
+  var fixture = fixtures[name],
+      buffer = new Buffer(Buffer.byteLength(fixture.raw, 'binary')),
+      offset = 0,
+      chunk,
+      nparsed,
+
+      parts = [],
+      part = null,
+      headerField,
+      headerValue,
+      endCalled = '';
+
+  parser.initWithBoundary(fixture.boundary);
+  parser.onPartBegin = function() {
+    part = {headers: {}, data: ''};
+    parts.push(part);
+    headerField = '';
+    headerValue = '';
+  };
+
+  parser.onHeaderField = function(b, start, end) {
+    headerField += b.toString('ascii', start, end);
+  };
+
+  parser.onHeaderValue = function(b, start, end) {
+    headerValue += b.toString('ascii', start, end);
+  }
+
+  parser.onHeaderEnd = function() {
+    part.headers[headerField] = headerValue;
+    headerField = '';
+    headerValue = '';
+  };
+
+  parser.onPartData = function(b, start, end) {
+    var str = b.toString('ascii', start, end);
+    part.data += b.slice(start, end);
+  }
+
+  parser.onEnd = function() {
+    endCalled = true;
+  }
+
+  buffer.write(fixture.raw, 'binary', 0);
+
+  while (offset < buffer.length) {
+    if (offset + CHUNK_LENGTH < buffer.length) {
+      chunk = buffer.slice(offset, offset+CHUNK_LENGTH);
+    } else {
+      chunk = buffer.slice(offset, buffer.length);
+    }
+    offset = offset + CHUNK_LENGTH;
+
+    nparsed = parser.write(chunk);
+    if (nparsed != chunk.length) {
+      if (fixture.expectError) {
+        return;
+      }
+      puts('-- ERROR --');
+      p(chunk.toString('ascii'));
+      throw new Error(chunk.length+' bytes written, but only '+nparsed+' bytes parsed!');
+    }
+  }
+
+  if (fixture.expectError) {
+    throw new Error('expected parse error did not happen');
+  }
+
+  assert.ok(endCalled);
+  assert.deepEqual(parts, fixture.parts);
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js	(revision 484)
@@ -0,0 +1,104 @@
+var common = require('../common');
+var WriteStreamStub = GENTLY.stub('fs', 'WriteStream');
+
+var File = require(common.lib + '/file'),
+    EventEmitter = require('events').EventEmitter,
+    file,
+    gently;
+
+function test(test) {
+  gently = new Gently();
+  file = new File();
+  test();
+  gently.verify(test.name);
+}
+
+test(function constructor() {
+  assert.ok(file instanceof EventEmitter);
+  assert.strictEqual(file.size, 0);
+  assert.strictEqual(file.path, null);
+  assert.strictEqual(file.name, null);
+  assert.strictEqual(file.type, null);
+  assert.strictEqual(file.lastModifiedDate, null);
+
+  assert.strictEqual(file._writeStream, null);
+
+  (function testSetProperties() {
+    var file2 = new File({foo: 'bar'});
+    assert.equal(file2.foo, 'bar');
+  })();
+});
+
+test(function open() {
+  var WRITE_STREAM;
+  file.path = '/foo';
+
+  gently.expect(WriteStreamStub, 'new', function (path) {
+    WRITE_STREAM = this;
+    assert.strictEqual(path, file.path);
+  });
+
+  file.open();
+  assert.strictEqual(file._writeStream, WRITE_STREAM);
+});
+
+test(function write() {
+  var BUFFER = {length: 10},
+      CB_STUB,
+      CB = function() {
+        CB_STUB.apply(this, arguments);
+      };
+
+  file._writeStream = {};
+
+  gently.expect(file._writeStream, 'write', function (buffer, cb) {
+    assert.strictEqual(buffer, BUFFER);
+
+    gently.expect(file, 'emit', function (event, bytesWritten) {
+      assert.ok(file.lastModifiedDate instanceof Date);
+      assert.equal(event, 'progress');
+      assert.equal(bytesWritten, file.size);
+    });
+
+    CB_STUB = gently.expect(function writeCb() {
+      assert.equal(file.size, 10);
+    });
+
+    cb();
+
+    gently.expect(file, 'emit', function (event, bytesWritten) {
+      assert.equal(event, 'progress');
+      assert.equal(bytesWritten, file.size);
+    });
+
+    CB_STUB = gently.expect(function writeCb() {
+      assert.equal(file.size, 20);
+    });
+
+    cb();
+  });
+
+  file.write(BUFFER, CB);
+});
+
+test(function end() {
+  var CB_STUB,
+      CB = function() {
+        CB_STUB.apply(this, arguments);
+      };
+
+  file._writeStream = {};
+
+  gently.expect(file._writeStream, 'end', function (cb) {
+    gently.expect(file, 'emit', function (event) {
+      assert.equal(event, 'end');
+    });
+
+    CB_STUB = gently.expect(function endCb() {
+    });
+
+    cb();
+  });
+
+  file.end(CB);
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js	(revision 484)
@@ -0,0 +1,756 @@
+var common = require('../common');
+var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'),
+    QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'),
+    EventEmitterStub = GENTLY.stub('events', 'EventEmitter'),
+    StreamStub = GENTLY.stub('stream', 'Stream'),
+    FileStub = GENTLY.stub('./file');
+
+var formidable = require(common.lib + '/index'),
+    IncomingForm = formidable.IncomingForm,
+    events = require('events'),
+    fs = require('fs'),
+    path = require('path'),
+    Buffer = require('buffer').Buffer,
+    fixtures = require(TEST_FIXTURES + '/multipart'),
+    form,
+    gently;
+
+function test(test) {
+  gently = new Gently();
+  gently.expect(EventEmitterStub, 'call');
+  form = new IncomingForm();
+  test();
+  gently.verify(test.name);
+}
+
+test(function constructor() {
+  assert.strictEqual(form.error, null);
+  assert.strictEqual(form.ended, false);
+  assert.strictEqual(form.type, null);
+  assert.strictEqual(form.headers, null);
+  assert.strictEqual(form.keepExtensions, false);
+  // Can't assume dir === '/tmp' for portability
+  // assert.strictEqual(form.uploadDir, '/tmp');
+  // Make sure it is a directory instead
+  assert.doesNotThrow(function () {
+    assert(fs.statSync(form.uploadDir).isDirectory());
+  });
+  assert.strictEqual(form.encoding, 'utf-8');
+  assert.strictEqual(form.bytesReceived, null);
+  assert.strictEqual(form.bytesExpected, null);
+  assert.strictEqual(form.maxFieldsSize, 2 * 1024 * 1024);
+  assert.strictEqual(form._parser, null);
+  assert.strictEqual(form._flushing, 0);
+  assert.strictEqual(form._fieldsSize, 0);
+  assert.ok(form instanceof EventEmitterStub);
+  assert.equal(form.constructor.name, 'IncomingForm');
+
+  (function testSimpleConstructor() {
+    gently.expect(EventEmitterStub, 'call');
+    var form = IncomingForm();
+    assert.ok(form instanceof IncomingForm);
+  })();
+
+  (function testSimpleConstructorShortcut() {
+    gently.expect(EventEmitterStub, 'call');
+    var form = formidable();
+    assert.ok(form instanceof IncomingForm);
+  })();
+});
+
+test(function parse() {
+  var REQ = {headers: {}}
+    , emit = {};
+
+  gently.expect(form, 'writeHeaders', function(headers) {
+    assert.strictEqual(headers, REQ.headers);
+  });
+
+  var EVENTS = ['error', 'aborted', 'data', 'end'];
+  gently.expect(REQ, 'on', EVENTS.length, function(event, fn) {
+    assert.equal(event, EVENTS.shift());
+    emit[event] = fn;
+    return this;
+  });
+
+  form.parse(REQ);
+
+  (function testPause() {
+    gently.expect(REQ, 'pause');
+    assert.strictEqual(form.pause(), true);
+  })();
+
+  (function testPauseCriticalException() {
+    form.ended = false;
+
+    var ERR = new Error('dasdsa');
+    gently.expect(REQ, 'pause', function() {
+      throw ERR;
+    });
+
+    gently.expect(form, '_error', function(err) {
+      assert.strictEqual(err, ERR);
+    });
+
+    assert.strictEqual(form.pause(), false);
+  })();
+
+  (function testPauseHarmlessException() {
+    form.ended = true;
+
+    var ERR = new Error('dasdsa');
+    gently.expect(REQ, 'pause', function() {
+      throw ERR;
+    });
+
+    assert.strictEqual(form.pause(), false);
+  })();
+
+  (function testResume() {
+    gently.expect(REQ, 'resume');
+    assert.strictEqual(form.resume(), true);
+  })();
+
+  (function testResumeCriticalException() {
+    form.ended = false;
+
+    var ERR = new Error('dasdsa');
+    gently.expect(REQ, 'resume', function() {
+      throw ERR;
+    });
+
+    gently.expect(form, '_error', function(err) {
+      assert.strictEqual(err, ERR);
+    });
+
+    assert.strictEqual(form.resume(), false);
+  })();
+
+  (function testResumeHarmlessException() {
+    form.ended = true;
+
+    var ERR = new Error('dasdsa');
+    gently.expect(REQ, 'resume', function() {
+      throw ERR;
+    });
+
+    assert.strictEqual(form.resume(), false);
+  })();
+
+  (function testEmitError() {
+    var ERR = new Error('something bad happened');
+    gently.expect(form, '_error',function(err) {
+      assert.strictEqual(err, ERR);
+    });
+    emit.error(ERR);
+  })();
+
+  (function testEmitAborted() {
+    gently.expect(form, 'emit',function(event) {
+      assert.equal(event, 'aborted');
+    });
+    gently.expect(form, '_error');
+
+    emit.aborted();
+  })();
+
+
+  (function testEmitData() {
+    var BUFFER = [1, 2, 3];
+    gently.expect(form, 'write', function(buffer) {
+      assert.strictEqual(buffer, BUFFER);
+    });
+    emit.data(BUFFER);
+  })();
+
+  (function testEmitEnd() {
+    form._parser = {};
+
+    (function testWithError() {
+      var ERR = new Error('haha');
+      gently.expect(form._parser, 'end', function() {
+        return ERR;
+      });
+
+      gently.expect(form, '_error', function(err) {
+        assert.strictEqual(err, ERR);
+      });
+
+      emit.end();
+    })();
+
+    (function testWithoutError() {
+      gently.expect(form._parser, 'end');
+      emit.end();
+    })();
+
+    (function testAfterError() {
+      form.error = true;
+      emit.end();
+    })();
+  })();
+
+  (function testWithCallback() {
+    gently.expect(EventEmitterStub, 'call');
+    var form = new IncomingForm(),
+        REQ = {headers: {}},
+        parseCalled = 0;
+
+    gently.expect(form, 'on', 4, function(event, fn) {
+      if (event == 'field') {
+        fn('field1', 'foo');
+        fn('field1', 'bar');
+        fn('field2', 'nice');
+      }
+
+      if (event == 'file') {
+        fn('file1', '1');
+        fn('file1', '2');
+        fn('file2', '3');
+      }
+
+      if (event == 'end') {
+        fn();
+      }
+      return this;
+    });
+
+    gently.expect(form, 'writeHeaders');
+
+    gently.expect(REQ, 'on', 4, function() {
+      return this;
+    });
+
+    var parseCbOk = function (err, fields, files) {
+      assert.deepEqual(fields, {field1: 'bar', field2: 'nice'});
+      assert.deepEqual(files, {file1: '2', file2: '3'});
+    };
+    form.parse(REQ, parseCbOk);
+
+    var ERR = new Error('test');
+    gently.expect(form, 'on', 3, function(event, fn) {
+      if (event == 'field') {
+        fn('foo', 'bar');
+      }
+
+      if (event == 'error') {
+        fn(ERR);
+        gently.expect(form, 'on');
+        gently.expect(form, 'writeHeaders');
+        gently.expect(REQ, 'on', 4, function() {
+          return this;
+        });
+      }
+      return this;
+    });
+
+    form.parse(REQ, function parseCbErr(err, fields, files) {
+      assert.strictEqual(err, ERR);
+      assert.deepEqual(fields, {foo: 'bar'});
+    });
+  })();
+
+  (function testWriteOrder() {
+    gently.expect(EventEmitterStub, 'call');
+    var form    = new IncomingForm();
+    var REQ     = new events.EventEmitter();
+    var BUF     = {};
+    var DATACB  = null;
+
+    REQ.on('newListener', function(event, fn) {
+      if ('data' === event) fn(BUF);
+    });
+
+    gently.expect(form, 'writeHeaders');
+    gently.expect(form, 'write', function(buf) {
+      assert.strictEqual(buf, BUF);
+    });
+
+    form.parse(REQ);
+  })();
+});
+
+test(function pause() {
+  assert.strictEqual(form.pause(), false);
+});
+
+test(function resume() {
+  assert.strictEqual(form.resume(), false);
+});
+
+
+test(function writeHeaders() {
+  var HEADERS = {};
+  gently.expect(form, '_parseContentLength');
+  gently.expect(form, '_parseContentType');
+
+  form.writeHeaders(HEADERS);
+  assert.strictEqual(form.headers, HEADERS);
+});
+
+test(function write() {
+  var parser = {},
+      BUFFER = [1, 2, 3];
+
+  form._parser = parser;
+  form.bytesExpected = 523423;
+
+  (function testBasic() {
+    gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
+      assert.equal(event, 'progress');
+      assert.equal(bytesReceived, BUFFER.length);
+      assert.equal(bytesExpected, form.bytesExpected);
+    });
+
+    gently.expect(parser, 'write', function(buffer) {
+      assert.strictEqual(buffer, BUFFER);
+      return buffer.length;
+    });
+
+    assert.equal(form.write(BUFFER), BUFFER.length);
+    assert.equal(form.bytesReceived, BUFFER.length);
+  })();
+
+  (function testParserError() {
+    gently.expect(form, 'emit');
+
+    gently.expect(parser, 'write', function(buffer) {
+      assert.strictEqual(buffer, BUFFER);
+      return buffer.length - 1;
+    });
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/parser error/i));
+    });
+
+    assert.equal(form.write(BUFFER), BUFFER.length - 1);
+    assert.equal(form.bytesReceived, BUFFER.length + BUFFER.length);
+  })();
+
+  (function testUninitialized() {
+    delete form._parser;
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/unintialized parser/i));
+    });
+    form.write(BUFFER);
+  })();
+});
+
+test(function parseContentType() {
+  var HEADERS = {};
+
+  form.headers = {'content-type': 'application/x-www-form-urlencoded'};
+  gently.expect(form, '_initUrlencoded');
+  form._parseContentType();
+
+  // accept anything that has 'urlencoded' in it
+  form.headers = {'content-type': 'broken-client/urlencoded-stupid'};
+  gently.expect(form, '_initUrlencoded');
+  form._parseContentType();
+
+  var BOUNDARY = '---------------------------57814261102167618332366269';
+  form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY};
+
+  gently.expect(form, '_initMultipart', function(boundary) {
+    assert.equal(boundary, BOUNDARY);
+  });
+  form._parseContentType();
+
+  (function testQuotedBoundary() {
+    form.headers = {'content-type': 'multipart/form-data; boundary="' + BOUNDARY + '"'};
+
+    gently.expect(form, '_initMultipart', function(boundary) {
+      assert.equal(boundary, BOUNDARY);
+    });
+    form._parseContentType();
+  })();
+
+  (function testNoBoundary() {
+    form.headers = {'content-type': 'multipart/form-data'};
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/no multipart boundary/i));
+    });
+    form._parseContentType();
+  })();
+
+  (function testNoContentType() {
+    form.headers = {};
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/no content-type/i));
+    });
+    form._parseContentType();
+  })();
+
+  (function testUnknownContentType() {
+    form.headers = {'content-type': 'invalid'};
+
+    gently.expect(form, '_error', function(err) {
+      assert.ok(err.message.match(/unknown content-type/i));
+    });
+    form._parseContentType();
+  })();
+});
+
+test(function parseContentLength() {
+  var HEADERS = {};
+
+  form.headers = {};
+  gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
+    assert.equal(event, 'progress');
+    assert.equal(bytesReceived, 0);
+    assert.equal(bytesExpected, 0);
+  });
+  form._parseContentLength();
+
+  form.headers['content-length'] = '8';
+  gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
+    assert.equal(event, 'progress');
+    assert.equal(bytesReceived, 0);
+    assert.equal(bytesExpected, 8);
+  });
+  form._parseContentLength();
+  assert.strictEqual(form.bytesReceived, 0);
+  assert.strictEqual(form.bytesExpected, 8);
+
+  // JS can be evil, lets make sure we are not
+  form.headers['content-length'] = '08';
+  gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) {
+    assert.equal(event, 'progress');
+    assert.equal(bytesReceived, 0);
+    assert.equal(bytesExpected, 8);
+  });
+  form._parseContentLength();
+  assert.strictEqual(form.bytesExpected, 8);
+});
+
+test(function _initMultipart() {
+  var BOUNDARY = '123',
+      PARSER;
+
+  gently.expect(MultipartParserStub, 'new', function() {
+    PARSER = this;
+  });
+
+  gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) {
+    assert.equal(boundary, BOUNDARY);
+  });
+
+  form._initMultipart(BOUNDARY);
+  assert.equal(form.type, 'multipart');
+  assert.strictEqual(form._parser, PARSER);
+
+  (function testRegularField() {
+    var PART;
+    gently.expect(StreamStub, 'new', function() {
+      PART = this;
+    });
+
+    gently.expect(form, 'onPart', function(part) {
+      assert.strictEqual(part, PART);
+      assert.deepEqual
+        ( part.headers
+        , { 'content-disposition': 'form-data; name="field1"'
+          , 'foo': 'bar'
+          }
+        );
+      assert.equal(part.name, 'field1');
+
+      var strings = ['hello', ' world'];
+      gently.expect(part, 'emit', 2, function(event, b) {
+          assert.equal(event, 'data');
+          assert.equal(b.toString(), strings.shift());
+      });
+
+      gently.expect(part, 'emit', function(event, b) {
+          assert.equal(event, 'end');
+      });
+    });
+
+    PARSER.onPartBegin();
+    PARSER.onHeaderField(new Buffer('content-disposition'), 0, 10);
+    PARSER.onHeaderField(new Buffer('content-disposition'), 10, 19);
+    PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 0, 14);
+    PARSER.onHeaderValue(new Buffer('form-data; name="field1"'), 14, 24);
+    PARSER.onHeaderEnd();
+    PARSER.onHeaderField(new Buffer('foo'), 0, 3);
+    PARSER.onHeaderValue(new Buffer('bar'), 0, 3);
+    PARSER.onHeaderEnd();
+    PARSER.onHeadersEnd();
+    PARSER.onPartData(new Buffer('hello world'), 0, 5);
+    PARSER.onPartData(new Buffer('hello world'), 5, 11);
+    PARSER.onPartEnd();
+  })();
+
+  (function testFileField() {
+    var PART;
+    gently.expect(StreamStub, 'new', function() {
+      PART = this;
+    });
+
+    gently.expect(form, 'onPart', function(part) {
+      assert.deepEqual
+        ( part.headers
+        , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'
+          , 'content-type': 'text/plain'
+          }
+        );
+      assert.equal(part.name, 'field2');
+      assert.equal(part.filename, 'Sun"et.jpg');
+      assert.equal(part.mime, 'text/plain');
+
+      gently.expect(part, 'emit', function(event, b) {
+        assert.equal(event, 'data');
+        assert.equal(b.toString(), '... contents of file1.txt ...');
+      });
+
+      gently.expect(part, 'emit', function(event, b) {
+          assert.equal(event, 'end');
+      });
+    });
+
+    PARSER.onPartBegin();
+    PARSER.onHeaderField(new Buffer('content-disposition'), 0, 19);
+    PARSER.onHeaderValue(new Buffer('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'), 0, 85);
+    PARSER.onHeaderEnd();
+    PARSER.onHeaderField(new Buffer('Content-Type'), 0, 12);
+    PARSER.onHeaderValue(new Buffer('text/plain'), 0, 10);
+    PARSER.onHeaderEnd();
+    PARSER.onHeadersEnd();
+    PARSER.onPartData(new Buffer('... contents of file1.txt ...'), 0, 29);
+    PARSER.onPartEnd();
+  })();
+
+  (function testEnd() {
+    gently.expect(form, '_maybeEnd');
+    PARSER.onEnd();
+    assert.ok(form.ended);
+  })();
+});
+
+test(function _fileName() {
+  // TODO
+  return;
+});
+
+test(function _initUrlencoded() {
+  var PARSER;
+
+  gently.expect(QuerystringParserStub, 'new', function() {
+    PARSER = this;
+  });
+
+  form._initUrlencoded();
+  assert.equal(form.type, 'urlencoded');
+  assert.strictEqual(form._parser, PARSER);
+
+  (function testOnField() {
+    var KEY = 'KEY', VAL = 'VAL';
+    gently.expect(form, 'emit', function(field, key, val) {
+      assert.equal(field, 'field');
+      assert.equal(key, KEY);
+      assert.equal(val, VAL);
+    });
+
+    PARSER.onField(KEY, VAL);
+  })();
+
+  (function testOnEnd() {
+    gently.expect(form, '_maybeEnd');
+
+    PARSER.onEnd();
+    assert.equal(form.ended, true);
+  })();
+});
+
+test(function _error() {
+  var ERR = new Error('bla');
+
+  gently.expect(form, 'pause');
+  gently.expect(form, 'emit', function(event, err) {
+    assert.equal(event, 'error');
+    assert.strictEqual(err, ERR);
+  });
+
+  form._error(ERR);
+  assert.strictEqual(form.error, ERR);
+
+  // make sure _error only does its thing once
+  form._error(ERR);
+});
+
+test(function onPart() {
+  var PART = {};
+  gently.expect(form, 'handlePart', function(part) {
+    assert.strictEqual(part, PART);
+  });
+
+  form.onPart(PART);
+});
+
+test(function handlePart() {
+  (function testUtf8Field() {
+    var PART = new events.EventEmitter();
+    PART.name = 'my_field';
+
+    gently.expect(form, 'emit', function(event, field, value) {
+      assert.equal(event, 'field');
+      assert.equal(field, 'my_field');
+      assert.equal(value, 'hello world: â¬');
+    });
+
+    form.handlePart(PART);
+    PART.emit('data', new Buffer('hello'));
+    PART.emit('data', new Buffer(' world: '));
+    PART.emit('data', new Buffer([0xE2]));
+    PART.emit('data', new Buffer([0x82, 0xAC]));
+    PART.emit('end');
+  })();
+
+  (function testBinaryField() {
+    var PART = new events.EventEmitter();
+    PART.name = 'my_field2';
+
+    gently.expect(form, 'emit', function(event, field, value) {
+      assert.equal(event, 'field');
+      assert.equal(field, 'my_field2');
+      assert.equal(value, 'hello world: '+new Buffer([0xE2, 0x82, 0xAC]).toString('binary'));
+    });
+
+    form.encoding = 'binary';
+    form.handlePart(PART);
+    PART.emit('data', new Buffer('hello'));
+    PART.emit('data', new Buffer(' world: '));
+    PART.emit('data', new Buffer([0xE2]));
+    PART.emit('data', new Buffer([0x82, 0xAC]));
+    PART.emit('end');
+  })();
+
+  (function testFieldSize() {
+    form.maxFieldsSize = 8;
+    var PART = new events.EventEmitter();
+    PART.name = 'my_field';
+
+    gently.expect(form, '_error', function(err) {
+      assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data');
+    });
+
+    form.handlePart(PART);
+    form._fieldsSize = 1;
+    PART.emit('data', new Buffer(7));
+    PART.emit('data', new Buffer(1));
+  })();
+
+  (function testFilePart() {
+    var PART = new events.EventEmitter(),
+        FILE = new events.EventEmitter(),
+        PATH = '/foo/bar';
+
+    PART.name = 'my_file';
+    PART.filename = 'sweet.txt';
+    PART.mime = 'sweet.txt';
+
+    gently.expect(form, '_uploadPath', function(filename) {
+      assert.equal(filename, PART.filename);
+      return PATH;
+    });
+
+    gently.expect(FileStub, 'new', function(properties) {
+      assert.equal(properties.path, PATH);
+      assert.equal(properties.name, PART.filename);
+      assert.equal(properties.type, PART.mime);
+      FILE = this;
+
+      gently.expect(form, 'emit', function (event, field, file) {
+        assert.equal(event, 'fileBegin');
+        assert.strictEqual(field, PART.name);
+        assert.strictEqual(file, FILE);
+      });
+
+      gently.expect(FILE, 'open');
+    });
+
+    form.handlePart(PART);
+    assert.equal(form._flushing, 1);
+
+    var BUFFER;
+    gently.expect(form, 'pause');
+    gently.expect(FILE, 'write', function(buffer, cb) {
+      assert.strictEqual(buffer, BUFFER);
+      gently.expect(form, 'resume');
+      // @todo handle cb(new Err)
+      cb();
+    });
+
+    PART.emit('data', BUFFER = new Buffer('test'));
+
+    gently.expect(FILE, 'end', function(cb) {
+      gently.expect(form, 'emit', function(event, field, file) {
+        assert.equal(event, 'file');
+        assert.strictEqual(file, FILE);
+      });
+
+      gently.expect(form, '_maybeEnd');
+
+      cb();
+      assert.equal(form._flushing, 0);
+    });
+
+    PART.emit('end');
+  })();
+});
+
+test(function _uploadPath() {
+  (function testUniqueId() {
+    var UUID_A, UUID_B;
+    gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) {
+      assert.equal(uploadDir, form.uploadDir);
+      UUID_A = uuid;
+    });
+    form._uploadPath();
+
+    gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) {
+      UUID_B = uuid;
+    });
+    form._uploadPath();
+
+    assert.notEqual(UUID_A, UUID_B);
+  })();
+
+  (function testFileExtension() {
+    form.keepExtensions = true;
+    var FILENAME = 'foo.jpg',
+        EXT = '.bar';
+
+    gently.expect(GENTLY.hijacked.path, 'extname', function(filename) {
+      assert.equal(filename, FILENAME);
+      gently.restore(path, 'extname');
+
+      return EXT;
+    });
+
+    gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, name) {
+      assert.equal(path.extname(name), EXT);
+    });
+    form._uploadPath(FILENAME);
+  })();
+});
+
+test(function _maybeEnd() {
+  gently.expect(form, 'emit', 0);
+  form._maybeEnd();
+
+  form.ended = true;
+  form._flushing = 1;
+  form._maybeEnd();
+
+  gently.expect(form, 'emit', function(event) {
+    assert.equal(event, 'end');
+  });
+
+  form.ended = true;
+  form._flushing = 0;
+  form._maybeEnd();
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js	(revision 484)
@@ -0,0 +1,50 @@
+var common = require('../common');
+var multipartParser = require(common.lib + '/multipart_parser'),
+    MultipartParser = multipartParser.MultipartParser,
+    events = require('events'),
+    Buffer = require('buffer').Buffer,
+    parser;
+
+function test(test) {
+  parser = new MultipartParser();
+  test();
+}
+
+test(function constructor() {
+  assert.equal(parser.boundary, null);
+  assert.equal(parser.state, 0);
+  assert.equal(parser.flags, 0);
+  assert.equal(parser.boundaryChars, null);
+  assert.equal(parser.index, null);
+  assert.equal(parser.lookbehind, null);
+  assert.equal(parser.constructor.name, 'MultipartParser');
+});
+
+test(function initWithBoundary() {
+  var boundary = 'abc';
+  parser.initWithBoundary(boundary);
+  assert.deepEqual(Array.prototype.slice.call(parser.boundary), [13, 10, 45, 45, 97, 98, 99]);
+  assert.equal(parser.state, multipartParser.START);
+
+  assert.deepEqual(parser.boundaryChars, {10: true, 13: true, 45: true, 97: true, 98: true, 99: true});
+});
+
+test(function parserError() {
+  var boundary = 'abc',
+      buffer = new Buffer(5);
+
+  parser.initWithBoundary(boundary);
+  buffer.write('--ad', 'ascii', 0);
+  assert.equal(parser.write(buffer), 5);
+});
+
+test(function end() {
+  (function testError() {
+    assert.equal(parser.end().message, 'MultipartParser.end(): stream ended unexpectedly: ' + parser.explain());
+  })();
+
+  (function testRegular() {
+    parser.state = multipartParser.END;
+    assert.strictEqual(parser.end(), undefined);
+  })();
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js	(revision 484)
@@ -0,0 +1,45 @@
+var common = require('../common');
+var QuerystringParser = require(common.lib + '/querystring_parser').QuerystringParser,
+    Buffer = require('buffer').Buffer,
+    gently,
+    parser;
+
+function test(test) {
+  gently = new Gently();
+  parser = new QuerystringParser();
+  test();
+  gently.verify(test.name);
+}
+
+test(function constructor() {
+  assert.equal(parser.buffer, '');
+  assert.equal(parser.constructor.name, 'QuerystringParser');
+});
+
+test(function write() {
+  var a = new Buffer('a=1');
+  assert.equal(parser.write(a), a.length);
+
+  var b = new Buffer('&b=2');
+  parser.write(b);
+  assert.equal(parser.buffer, a + b);
+});
+
+test(function end() {
+  var FIELDS = {a: ['b', {c: 'd'}], e: 'f'};
+
+  gently.expect(GENTLY.hijacked.querystring, 'parse', function(str) {
+    assert.equal(str, parser.buffer);
+    return FIELDS;
+  });
+
+  gently.expect(parser, 'onField', Object.keys(FIELDS).length, function(key, val) {
+    assert.deepEqual(FIELDS[key], val);
+  });
+
+  gently.expect(parser, 'onEnd');
+
+  parser.buffer = 'my buffer';
+  parser.end();
+  assert.equal(parser.buffer, '');
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js	(revision 484)
@@ -0,0 +1,71 @@
+var common = require('../common');
+var BOUNDARY = '---------------------------10102754414578508781458777923',
+    FIXTURE = TEST_FIXTURES+'/multi_video.upload',
+    fs = require('fs'),
+    http = require('http'),
+    formidable = require(common.lib + '/index'),
+    server = http.createServer();
+
+server.on('request', function(req, res) {
+  var form = new formidable.IncomingForm(),
+      uploads = {};
+
+  form.uploadDir = TEST_TMP;
+  form.hash = 'sha1';
+  form.parse(req);
+
+  form
+    .on('fileBegin', function(field, file) {
+      assert.equal(field, 'upload');
+
+      var tracker = {file: file, progress: [], ended: false};
+      uploads[file.name] = tracker;
+      file
+        .on('progress', function(bytesReceived) {
+          tracker.progress.push(bytesReceived);
+          assert.equal(bytesReceived, file.size);
+        })
+        .on('end', function() {
+          tracker.ended = true;
+        });
+    })
+    .on('field', function(field, value) {
+      assert.equal(field, 'title');
+      assert.equal(value, '');
+    })
+    .on('file', function(field, file) {
+      assert.equal(field, 'upload');
+      assert.strictEqual(uploads[file.name].file, file);
+    })
+    .on('end', function() {
+      assert.ok(uploads['shortest_video.flv']);
+      assert.ok(uploads['shortest_video.flv'].ended);
+      assert.ok(uploads['shortest_video.flv'].progress.length > 3);
+      assert.equal(uploads['shortest_video.flv'].file.hash, 'd6a17616c7143d1b1438ceeef6836d1a09186b3a');
+      assert.equal(uploads['shortest_video.flv'].progress.slice(-1), uploads['shortest_video.flv'].file.size);
+      assert.ok(uploads['shortest_video.mp4']);
+      assert.ok(uploads['shortest_video.mp4'].ended);
+      assert.ok(uploads['shortest_video.mp4'].progress.length > 3);
+      assert.equal(uploads['shortest_video.mp4'].file.hash, '937dfd4db263f4887ceae19341dcc8d63bcd557f');
+
+      server.close();
+      res.writeHead(200);
+      res.end('good');
+    });
+});
+
+server.listen(TEST_PORT, function() {
+  var stat, headers, request, fixture;
+
+  stat = fs.statSync(FIXTURE);
+  request = http.request({
+    port: TEST_PORT,
+    path: '/',
+    method: 'POST',
+    headers: {
+      'content-type': 'multipart/form-data; boundary='+BOUNDARY,
+      'content-length': stat.size,
+    },
+  });
+  fs.createReadStream(FIXTURE).pipe(request);
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js	(revision 484)
@@ -0,0 +1,1 @@
+require('urun')(__dirname)
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-connection-aborted.js	(revision 484)
@@ -0,0 +1,27 @@
+var assert = require('assert');
+var http = require('http');
+var net = require('net');
+var formidable = require('../../lib/index');
+
+var server = http.createServer(function (req, res) {
+  var form = new formidable.IncomingForm();
+  var aborted_received = false;
+  form.on('aborted', function () {
+    aborted_received = true;
+  });
+  form.on('error', function () {
+    assert(aborted_received, 'Error event should follow aborted');
+    server.close();
+  });
+  form.on('end', function () {
+    throw new Error('Unexpected "end" event');
+  });
+  form.parse(req);
+}).listen(0, 'localhost', function () {
+  var client = net.connect(server.address().port);
+  client.write(
+    "POST / HTTP/1.1\r\n" +
+    "Content-Length: 70\r\n" +
+    "Content-Type: multipart/form-data; boundary=foo\r\n\r\n");
+  client.end();
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-content-transfer-encoding.js	(revision 484)
@@ -0,0 +1,48 @@
+var assert = require('assert');
+var common = require('../common');
+var formidable = require('../../lib/index');
+var http = require('http');
+
+var server = http.createServer(function(req, res) {
+  var form = new formidable.IncomingForm();
+  form.uploadDir = common.dir.tmp;
+  form.on('end', function () {
+    throw new Error('Unexpected "end" event');
+  });
+  form.on('error', function (e) {
+    res.writeHead(500);
+    res.end(e.message);
+  });
+  form.parse(req);
+});
+
+server.listen(0, function() {
+  var body =
+    '--foo\r\n' +
+    'Content-Disposition: form-data; name="file1"; filename="file1"\r\n' +
+    'Content-Type: application/octet-stream\r\n' +
+    '\r\nThis is the first file\r\n' +
+    '--foo\r\n' +
+    'Content-Type: application/octet-stream\r\n' +
+    'Content-Disposition: form-data; name="file2"; filename="file2"\r\n' +
+    'Content-Transfer-Encoding: unknown\r\n' +
+    '\r\nThis is the second file\r\n' +
+    '--foo--\r\n';
+
+  var req = http.request({
+    method: 'POST',
+    port: server.address().port,
+    headers: {
+      'Content-Length': body.length,
+      'Content-Type': 'multipart/form-data; boundary=foo'
+    }
+  });
+  req.on('response', function (res) {
+    assert.equal(res.statusCode, 500);
+    res.on('data', function () {});
+    res.on('end', function () {
+      server.close();
+    });
+  });
+  req.end(body);
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/standalone/test-issue-46.js	(revision 484)
@@ -0,0 +1,49 @@
+var http       = require('http'),
+    formidable = require('../../lib/index'),
+    request    = require('request'),
+    assert     = require('assert');
+
+var host = 'localhost';
+
+var index = [
+  '<form action="/" method="post" enctype="multipart/form-data">',
+  '  <input type="text" name="foo" />',
+  '  <input type="submit" />',
+  '</form>'
+].join("\n");
+
+var server = http.createServer(function(req, res) {
+
+  // Show a form for testing purposes.
+  if (req.method == 'GET') {
+    res.writeHead(200, {'content-type': 'text/html'});
+    res.end(index);
+    return;
+  }
+
+  // Parse form and write results to response.
+  var form = new formidable.IncomingForm();
+  form.parse(req, function(err, fields, files) {
+    res.writeHead(200, {'content-type': 'text/plain'}); 
+    res.write(JSON.stringify({err: err, fields: fields, files: files}));
+    res.end();
+  });
+
+}).listen(0, host, function() {
+
+  console.log("Server up and running...");
+
+  var server = this,
+      url    = 'http://' + host + ':' + server.address().port;
+
+  var parts  = [
+    {'Content-Disposition': 'form-data; name="foo"', 'body': 'bar'}
+  ]
+
+  var req = request({method: 'POST', url: url, multipart: parts}, function(e, res, body) {
+    var obj = JSON.parse(body);
+    assert.equal("bar", obj.fields.foo);
+    server.close();
+  });
+
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/tools/base64.html	(revision 484)
@@ -0,0 +1,67 @@
+<html>
+<head>
+	<title>Convert a file to a base64 request</title>
+
+<script type="text/javascript">
+
+function form_submit(e){
+	console.log(e)
+
+	var resultOutput = document.getElementById('resultOutput');
+	var fileInput = document.getElementById('fileInput');
+	var fieldInput = document.getElementById('fieldInput');
+
+	makeRequestBase64(fileInput.files[0], fieldInput.value, function(err, result){
+		resultOutput.value = result;
+	});
+
+	return false;
+}
+
+function makeRequestBase64(file, fieldName, cb){
+	var boundary = '\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/';
+	var crlf = "\r\n";
+
+	var reader = new FileReader();
+	reader.onload = function(e){
+		var body = '';
+
+		body += '--' + boundary + crlf;
+		body += 'Content-Disposition: form-data; name="' + fieldName + '"; filename="' + escape(file.name)+ '"' + crlf;
+		body += 'Content-Type: ' + file.type + '' + crlf;
+		body += 'Content-Transfer-Encoding: base64' + crlf
+		body += crlf;
+		body += e.target.result.substring(e.target.result.indexOf(',') + 1) + crlf;
+
+		body += '--' + boundary + '--';
+
+		var head = '';
+		head += 'POST /upload HTTP/1.1' + crlf;
+		head += 'Host: localhost:8080' + crlf;
+		head += 'Content-Type: multipart/form-data; boundary=' + boundary + '' + crlf;
+		head += 'Content-Length: ' + body.length + '' + crlf;
+
+		cb(null, head + crlf + body);
+	};
+
+	reader.readAsDataURL(file);
+}
+
+</script>
+
+</head>
+
+<body>
+
+<form action="" onsubmit="return form_submit();">
+	<label>File: <input id="fileInput" type="file" /></label><br />
+	<label>Field: <input id="fieldInput" type="text" value="file" /></label><br />
+	<button type="submit">Ok!</button><br />
+	<label>Request: <textarea id="resultOutput" readonly="readonly" rows="20" cols="80"></textarea></label><br />
+</form>
+<p>
+Don't forget to save the output with windows (CRLF) line endings!
+</p>
+
+</body>
+</html>
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-file.js	(revision 484)
@@ -0,0 +1,33 @@
+var common       = require('../common');
+var test         = require('utest');
+var assert       = common.assert;
+var File = common.require('file');
+
+var file;
+var now = new Date;
+test('IncomingForm', {
+  before: function() {
+    file = new File({
+      size: 1024,
+      path: '/tmp/cat.png',
+      name: 'cat.png',
+      type: 'image/png',
+      lastModifiedDate: now,
+      filename: 'cat.png',
+      mime: 'image/png'
+    })
+  },
+
+  '#toJSON()': function() {
+    var obj = file.toJSON();
+    var len = Object.keys(obj).length;
+    assert.equal(1024, obj.size);
+    assert.equal('/tmp/cat.png', obj.path);
+    assert.equal('cat.png', obj.name);
+    assert.equal('image/png', obj.type);
+    assert.equal('image/png', obj.mime);
+    assert.equal('cat.png', obj.filename);
+    assert.equal(now, obj.mtime);
+    assert.equal(len, 8);
+  }
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js	(revision 484)
@@ -0,0 +1,63 @@
+var common       = require('../common');
+var test         = require('utest');
+var assert       = common.assert;
+var IncomingForm = common.require('incoming_form').IncomingForm;
+var path         = require('path');
+
+var form;
+test('IncomingForm', {
+  before: function() {
+    form = new IncomingForm();
+  },
+
+  '#_fileName with regular characters': function() {
+    var filename = 'foo.txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'foo.txt');
+  },
+
+  '#_fileName with unescaped quote': function() {
+    var filename = 'my".txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
+  },
+
+  '#_fileName with escaped quote': function() {
+    var filename = 'my%22.txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'my".txt');
+  },
+
+  '#_fileName with bad quote and additional sub-header': function() {
+    var filename = 'my".txt';
+    var header = makeHeader(filename) + '; foo="bar"';
+    assert.equal(form._fileName(header), filename);
+  },
+
+  '#_fileName with semicolon': function() {
+    var filename = 'my;.txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'my;.txt');
+  },
+
+  '#_fileName with utf8 character': function() {
+    var filename = 'my&#9731;.txt';
+    assert.equal(form._fileName(makeHeader(filename)), 'myâ.txt');
+  },
+
+  '#_uploadPath strips harmful characters from extension when keepExtensions': function() {
+    form.keepExtensions = true;
+
+    var ext = path.extname(form._uploadPath('fine.jpg?foo=bar'));
+    assert.equal(ext, '.jpg');
+
+    var ext = path.extname(form._uploadPath('fine?foo=bar'));
+    assert.equal(ext, '');
+
+    var ext = path.extname(form._uploadPath('super.cr2+dsad'));
+    assert.equal(ext, '.cr2');
+
+    var ext = path.extname(form._uploadPath('super.bar'));
+    assert.equal(ext, '.bar');
+  },
+});
+
+function makeHeader(filename) {
+  return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"';
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js	(revision 484)
@@ -0,0 +1,47 @@
+var http = require('http');
+var fs = require('fs');
+var connections = 0;
+
+var server = http.createServer(function(req, res) {
+  var socket = req.socket;
+  console.log('Request: %s %s -> %s', req.method, req.url, socket.filename);
+
+  req.on('end', function() {
+    if (req.url !== '/') {
+      res.end(JSON.stringify({
+        method: req.method,
+        url: req.url,
+        filename: socket.filename,
+      }));
+      return;
+    }
+
+    res.writeHead(200, {'content-type': 'text/html'});
+    res.end(
+      '<form action="/upload" enctype="multipart/form-data" method="post">'+
+      '<input type="text" name="title"><br>'+
+      '<input type="file" name="upload" multiple="multiple"><br>'+
+      '<input type="submit" value="Upload">'+
+      '</form>'
+    );
+  });
+});
+
+server.on('connection', function(socket) {
+  connections++;
+
+  socket.id = connections;
+  socket.filename = 'connection-' + socket.id + '.http';
+  socket.file = fs.createWriteStream(socket.filename);
+  socket.pipe(socket.file);
+
+  console.log('--> %s', socket.filename);
+  socket.on('close', function() {
+    console.log('<-- %s', socket.filename);
+  });
+});
+
+var port = process.env.PORT || 8080;
+server.listen(port, function() {
+  console.log('Recording connections on port %s', port);
+});
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/.npmignore	(revision 484)
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/History.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/History.md	(revision 484)
@@ -0,0 +1,5 @@
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/Makefile
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--require should \
+		--reporter spec
+
+.PHONY: test
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/Readme.md	(revision 484)
@@ -0,0 +1,29 @@
+
+# pause
+
+  Pause streams...
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2012 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.
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/index.js	(revision 484)
@@ -0,0 +1,29 @@
+
+module.exports = 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]);
+      }
+    }
+  };
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/pause/package.json	(revision 484)
@@ -0,0 +1,20 @@
+{
+  "name": "pause",
+  "version": "0.0.1",
+  "description": "Pause streams...",
+  "keywords": [],
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "main": "index",
+  "readme": "\n# pause\n\n  Pause streams...\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
+  "readmeFilename": "Readme.md",
+  "_id": "pause@0.0.1",
+  "_from": "pause@0.0.1"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/.gitmodules	(revision 484)
@@ -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
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/.npmignore	(revision 484)
@@ -0,0 +1,7 @@
+test
+.travis.yml
+benchmark.js
+component.json
+examples.js
+History.md
+Makefile
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/Readme.md	(revision 484)
@@ -0,0 +1,58 @@
+# node-querystring
+
+  query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.
+
+## Installation
+
+    $ npm install qs
+
+## Examples
+
+```js
+var qs = require('qs');
+
+qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');
+// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }
+
+qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})
+// => user[name]=Tobi&user[email]=tobi%40learnboost.com
+```
+
+## Testing
+
+Install dev dependencies:
+
+    $ npm install -d
+
+and execute:
+
+    $ make test
+
+browser:
+
+    $ open test/browser/index.html
+
+## 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.
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/index.js	(revision 484)
@@ -0,0 +1,387 @@
+/**
+ * Object#toString() ref for stringify().
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Object#hasOwnProperty ref
+ */
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+/**
+ * Array#indexOf shim.
+ */
+
+var indexOf = typeof Array.prototype.indexOf === 'function'
+  ? function(arr, el) { return arr.indexOf(el); }
+  : function(arr, el) {
+      for (var i = 0; i < arr.length; i++) {
+        if (arr[i] === el) return i;
+      }
+      return -1;
+    };
+
+/**
+ * Array.isArray shim.
+ */
+
+var isArray = Array.isArray || function(arr) {
+  return toString.call(arr) == '[object Array]';
+};
+
+/**
+ * Object.keys shim.
+ */
+
+var objectKeys = Object.keys || function(obj) {
+  var ret = [];
+  for (var key in obj) ret.push(key);
+  return ret;
+};
+
+/**
+ * Array#forEach shim.
+ */
+
+var forEach = typeof Array.prototype.forEach === 'function'
+  ? function(arr, fn) { return arr.forEach(fn); }
+  : function(arr, fn) {
+      for (var i = 0; i < arr.length; i++) fn(arr[i]);
+    };
+
+/**
+ * Array#reduce shim.
+ */
+
+var reduce = function(arr, fn, initial) {
+  if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
+  var res = initial;
+  for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
+  return res;
+};
+
+/**
+ * Create a nullary object if possible
+ */
+
+function createObject() {
+  return Object.create
+    ? Object.create(null)
+    : {};
+}
+
+/**
+ * Cache non-integer test regexp.
+ */
+
+var isint = /^[0-9]+$/;
+
+function promote(parent, key) {
+  if (parent[key].length == 0) return parent[key] = createObject();
+  var t = createObject();
+  for (var i in parent[key]) {
+    if (hasOwnProperty.call(parent[key], i)) {
+      t[i] = parent[key][i];
+    }
+  }
+  parent[key] = t;
+  return t;
+}
+
+function parse(parts, parent, key, val) {
+  var part = parts.shift();
+  // end
+  if (!part) {
+    if (isArray(parent[key])) {
+      parent[key].push(val);
+    } else if ('object' == typeof parent[key]) {
+      parent[key] = val;
+    } else if ('undefined' == typeof parent[key]) {
+      parent[key] = val;
+    } else {
+      parent[key] = [parent[key], val];
+    }
+    // array
+  } else {
+    var obj = parent[key] = parent[key] || [];
+    if (']' == part) {
+      if (isArray(obj)) {
+        if ('' != val) obj.push(val);
+      } else if ('object' == typeof obj) {
+        obj[objectKeys(obj).length] = val;
+      } else {
+        obj = parent[key] = [parent[key], val];
+      }
+      // prop
+    } else if (~indexOf(part, ']')) {
+      part = part.substr(0, part.length - 1);
+      if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+      // key
+    } else {
+      if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+    }
+  }
+}
+
+/**
+ * Merge parent key/val pair.
+ */
+
+function merge(parent, key, val){
+  if (~indexOf(key, ']')) {
+    var parts = key.split('[')
+      , len = parts.length
+      , last = len - 1;
+    parse(parts, parent, 'base', val);
+    // optimize
+  } else {
+    if (!isint.test(key) && isArray(parent.base)) {
+      var t = createObject();
+      for (var k in parent.base) t[k] = parent.base[k];
+      parent.base = t;
+    }
+    set(parent.base, key, val);
+  }
+
+  return parent;
+}
+
+/**
+ * Compact sparse arrays.
+ */
+
+function compact(obj) {
+  if ('object' != typeof obj) return obj;
+
+  if (isArray(obj)) {
+    var ret = [];
+
+    for (var i in obj) {
+      if (hasOwnProperty.call(obj, i)) {
+        ret.push(obj[i]);
+      }
+    }
+
+    return ret;
+  }
+
+  for (var key in obj) {
+    obj[key] = compact(obj[key]);
+  }
+
+  return obj;
+}
+
+/**
+ * Restore Object.prototype.
+ * see pull-request #58
+ */
+
+function restoreProto(obj) {
+  if (!Object.create) return obj;
+  if (isArray(obj)) return obj;
+  if (obj && 'object' != typeof obj) return obj;
+
+  for (var key in obj) {
+    if (hasOwnProperty.call(obj, key)) {
+      obj[key] = restoreProto(obj[key]);
+    }
+  }
+
+  obj.__proto__ = Object.prototype;
+  return obj;
+}
+
+/**
+ * Parse the given obj.
+ */
+
+function parseObject(obj){
+  var ret = { base: {} };
+
+  forEach(objectKeys(obj), function(name){
+    merge(ret, name, obj[name]);
+  });
+
+  return compact(ret.base);
+}
+
+/**
+ * Parse the given str.
+ */
+
+function parseString(str){
+  var ret = reduce(String(str).split('&'), function(ret, pair){
+    var eql = indexOf(pair, '=')
+      , brace = lastBraceInKey(pair)
+      , key = pair.substr(0, brace || eql)
+      , val = pair.substr(brace || eql, pair.length)
+      , val = val.substr(indexOf(val, '=') + 1, val.length);
+
+    // ?foo
+    if ('' == key) key = pair, val = '';
+    if ('' == key) return ret;
+
+    return merge(ret, decode(key), decode(val));
+  }, { base: createObject() }).base;
+
+  return restoreProto(compact(ret));
+}
+
+/**
+ * Parse the given query `str` or `obj`, returning an object.
+ *
+ * @param {String} str | {Object} obj
+ * @return {Object}
+ * @api public
+ */
+
+exports.parse = function(str){
+  if (null == str || '' == str) return {};
+  return 'object' == typeof str
+    ? parseObject(str)
+    : parseString(str);
+};
+
+/**
+ * Turn the given `obj` into a query string
+ *
+ * @param {Object} obj
+ * @return {String}
+ * @api public
+ */
+
+var stringify = exports.stringify = function(obj, prefix) {
+  if (isArray(obj)) {
+    return stringifyArray(obj, prefix);
+  } else if ('[object Object]' == toString.call(obj)) {
+    return stringifyObject(obj, prefix);
+  } else if ('string' == typeof obj) {
+    return stringifyString(obj, prefix);
+  } else {
+    return prefix + '=' + encodeURIComponent(String(obj));
+  }
+};
+
+/**
+ * Stringify the given `str`.
+ *
+ * @param {String} str
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyString(str, prefix) {
+  if (!prefix) throw new TypeError('stringify expects an object');
+  return prefix + '=' + encodeURIComponent(str);
+}
+
+/**
+ * Stringify the given `arr`.
+ *
+ * @param {Array} arr
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyArray(arr, prefix) {
+  var ret = [];
+  if (!prefix) throw new TypeError('stringify expects an object');
+  for (var i = 0; i < arr.length; i++) {
+    ret.push(stringify(arr[i], prefix + '[' + i + ']'));
+  }
+  return ret.join('&');
+}
+
+/**
+ * Stringify the given `obj`.
+ *
+ * @param {Object} obj
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyObject(obj, prefix) {
+  var ret = []
+    , keys = objectKeys(obj)
+    , key;
+
+  for (var i = 0, len = keys.length; i < len; ++i) {
+    key = keys[i];
+    if ('' == key) continue;
+    if (null == obj[key]) {
+      ret.push(encodeURIComponent(key) + '=');
+    } else {
+      ret.push(stringify(obj[key], prefix
+        ? prefix + '[' + encodeURIComponent(key) + ']'
+        : encodeURIComponent(key)));
+    }
+  }
+
+  return ret.join('&');
+}
+
+/**
+ * Set `obj`'s `key` to `val` respecting
+ * the weird and wonderful syntax of a qs,
+ * where "foo=bar&foo=baz" becomes an array.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @param {String} val
+ * @api private
+ */
+
+function set(obj, key, val) {
+  var v = obj[key];
+  if (undefined === v) {
+    obj[key] = val;
+  } else if (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;
+  }
+}
+
+/**
+ * Decode `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+function decode(str) {
+  try {
+    return decodeURIComponent(str.replace(/\+/g, ' '));
+  } catch (err) {
+    return str;
+  }
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/qs/package.json	(revision 484)
@@ -0,0 +1,37 @@
+{
+  "name": "qs",
+  "description": "querystring parser",
+  "version": "0.6.5",
+  "keywords": [
+    "query string",
+    "parser",
+    "component"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/node-querystring.git"
+  },
+  "devDependencies": {
+    "mocha": "*",
+    "expect.js": "*"
+  },
+  "scripts": {
+    "test": "make test"
+  },
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca",
+    "url": "http://tjholowaychuk.com"
+  },
+  "main": "index",
+  "engines": {
+    "node": "*"
+  },
+  "readme": "# node-querystring\n\n  query string parser for node and the browser 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.\n\n## Installation\n\n    $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n    $ npm install -d\n\nand execute:\n\n    $ make test\n\nbrowser:\n\n    $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/visionmedia/node-querystring/issues"
+  },
+  "_id": "qs@0.6.5",
+  "_from": "qs@0.6.5"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/.npmignore	(revision 484)
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/History.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/History.md	(revision 484)
@@ -0,0 +1,25 @@
+
+0.1.0 / 2012-08-25 
+==================
+
+  * add options parameter to send() that is passed to fs.createReadStream() [kanongil]
+
+0.0.4 / 2012-08-16 
+==================
+
+  * allow custom "Accept-Ranges" definition
+
+0.0.3 / 2012-07-16 
+==================
+
+  * fix normalization of the root directory. Closes #3
+
+0.0.2 / 2012-07-09 
+==================
+
+  * add passing of req explicitly for now (YUCK)
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/Makefile
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/Makefile	(revision 484)
@@ -0,0 +1,8 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--require should \
+		--reporter spec \
+		--bail
+
+.PHONY: test
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/Readme.md	(revision 484)
@@ -0,0 +1,128 @@
+# send
+
+  Send is Connect's `static()` extracted for generalized use, a streaming static file
+  server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.
+
+## Installation
+
+    $ npm install send
+
+## Examples
+
+  Small:
+
+```js
+var http = require('http');
+var send = require('send');
+
+var app = http.createServer(function(req, res){
+  send(req, req.url).pipe(res);
+}).listen(3000);
+```
+
+  Serving from a root directory with custom error-handling:
+
+```js
+var http = require('http');
+var send = require('send');
+var url = require('url');
+
+var app = http.createServer(function(req, res){
+  // your custom error-handling logic:
+  function error(err) {
+    res.statusCode = err.status || 500;
+    res.end(err.message);
+  }
+
+  // your custom directory handling logic:
+  function redirect() {
+    res.statusCode = 301;
+    res.setHeader('Location', req.url + '/');
+    res.end('Redirecting to ' + req.url + '/');
+  }
+
+  // transfer arbitrary files from within
+  // /www/example.com/public/*
+  send(req, url.parse(req.url).pathname)
+  .root('/www/example.com/public')
+  .on('error', error)
+  .on('directory', redirect)
+  .pipe(res);
+}).listen(3000);
+```
+
+## API
+
+### Events
+
+  - `error` an error occurred `(err)`
+  - `directory` a directory was requested
+  - `file` a file was requested `(path, stat)`
+  - `stream` file streaming has started `(stream)`
+  - `end` streaming has completed
+
+### .root(dir)
+
+  Serve files relative to `path`. Aliased as `.from(dir)`.
+
+### .index(path)
+
+  By default send supports "index.html" files, to disable this
+  invoke `.index(false)` or to supply a new index pass a string.
+
+### .maxage(ms)
+
+  Provide a max-age in milliseconds for http caching, defaults to 0.
+
+### .hidden(bool)
+
+  Enable or disable transfer of hidden files, defaults to false.
+
+## Error-handling
+
+  By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.
+
+## Caching
+
+  It does _not_ perform internal caching, you should use a reverse proxy cache such
+  as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).
+
+## Debugging
+
+ To enable `debug()` instrumentation output export __DEBUG__:
+
+```
+$ DEBUG=send node app
+```
+
+## Running tests
+
+```
+$ npm install
+$ make test
+```
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2012 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.
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/index.js	(revision 484)
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/send');
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/lib/send.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/lib/send.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/lib/send.js	(revision 484)
@@ -0,0 +1,474 @@
+
+/**
+ * Module dependencies.
+ */
+
+var debug = require('debug')('send')
+  , parseRange = require('range-parser')
+  , Stream = require('stream')
+  , mime = require('mime')
+  , fresh = require('fresh')
+  , path = require('path')
+  , http = require('http')
+  , fs = require('fs')
+  , basename = path.basename
+  , normalize = path.normalize
+  , join = path.join
+  , utils = require('./utils');
+
+/**
+ * Expose `send`.
+ */
+
+exports = module.exports = send;
+
+/**
+ * Expose mime module.
+ */
+
+exports.mime = mime;
+
+/**
+ * Return a `SendStream` for `req` and `path`.
+ *
+ * @param {Request} req
+ * @param {String} path
+ * @param {Object} options
+ * @return {SendStream}
+ * @api public
+ */
+
+function send(req, path, options) {
+  return new SendStream(req, path, options);
+}
+
+/**
+ * Initialize a `SendStream` with the given `path`.
+ *
+ * Events:
+ *
+ *  - `error` an error occurred
+ *  - `stream` file streaming has started
+ *  - `end` streaming has completed
+ *  - `directory` a directory was requested
+ *
+ * @param {Request} req
+ * @param {String} path
+ * @param {Object} options
+ * @api private
+ */
+
+function SendStream(req, path, options) {
+  var self = this;
+  this.req = req;
+  this.path = path;
+  this.options = options || {};
+  this.maxage(0);
+  this.hidden(false);
+  this.index('index.html');
+}
+
+/**
+ * Inherits from `Stream.prototype`.
+ */
+
+SendStream.prototype.__proto__ = Stream.prototype;
+
+/**
+ * Enable or disable "hidden" (dot) files.
+ *
+ * @param {Boolean} path
+ * @return {SendStream}
+ * @api public
+ */
+
+SendStream.prototype.hidden = function(val){
+  debug('hidden %s', val);
+  this._hidden = val;
+  return this;
+};
+
+/**
+ * Set index `path`, set to a falsy
+ * value to disable index support.
+ *
+ * @param {String|Boolean} path
+ * @return {SendStream}
+ * @api public
+ */
+
+SendStream.prototype.index = function(path){
+  debug('index %s', path);
+  this._index = path;
+  return this;
+};
+
+/**
+ * Set root `path`.
+ *
+ * @param {String} path
+ * @return {SendStream}
+ * @api public
+ */
+
+SendStream.prototype.root = 
+SendStream.prototype.from = function(path){
+  this._root = normalize(path);
+  return this;
+};
+
+/**
+ * Set max-age to `ms`.
+ *
+ * @param {Number} ms
+ * @return {SendStream}
+ * @api public
+ */
+
+SendStream.prototype.maxage = function(ms){
+  if (Infinity == ms) ms = 60 * 60 * 24 * 365 * 1000;
+  debug('max-age %d', ms);
+  this._maxage = ms;
+  return this;
+};
+
+/**
+ * Emit error with `status`.
+ *
+ * @param {Number} status
+ * @api private
+ */
+
+SendStream.prototype.error = function(status, err){
+  var res = this.res;
+  var msg = http.STATUS_CODES[status];
+  err = err || new Error(msg);
+  err.status = status;
+  if (this.listeners('error').length) return this.emit('error', err);
+  res.statusCode = err.status;
+  res.end(msg);
+};
+
+/**
+ * Check if the pathname is potentially malicious.
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.isMalicious = function(){
+  return !this._root && ~this.path.indexOf('..');
+};
+
+/**
+ * Check if the pathname ends with "/".
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.hasTrailingSlash = function(){
+  return '/' == this.path[this.path.length - 1];
+};
+
+/**
+ * Check if the basename leads with ".".
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.hasLeadingDot = function(){
+  return '.' == basename(this.path)[0];
+};
+
+/**
+ * Check if this is a conditional GET request.
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.isConditionalGET = function(){
+  return this.req.headers['if-none-match']
+    || this.req.headers['if-modified-since'];
+};
+
+/**
+ * Strip content-* header fields.
+ *
+ * @api private
+ */
+
+SendStream.prototype.removeContentHeaderFields = function(){
+  var res = this.res;
+  Object.keys(res._headers).forEach(function(field){
+    if (0 == field.indexOf('content')) {
+      res.removeHeader(field);
+    }
+  });
+};
+
+/**
+ * Respond with 304 not modified.
+ *
+ * @api private
+ */
+
+SendStream.prototype.notModified = function(){
+  var res = this.res;
+  debug('not modified');
+  this.removeContentHeaderFields();
+  res.statusCode = 304;
+  res.end();
+};
+
+/**
+ * Check if the request is cacheable, aka
+ * responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}).
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.isCachable = function(){
+  var res = this.res;
+  return (res.statusCode >= 200 && res.statusCode < 300) || 304 == res.statusCode;
+};
+
+/**
+ * Handle stat() error.
+ *
+ * @param {Error} err
+ * @api private
+ */
+
+SendStream.prototype.onStatError = function(err){
+  var notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'];
+  if (~notfound.indexOf(err.code)) return this.error(404, err);
+  this.error(500, err);
+};
+
+/**
+ * Check if the cache is fresh.
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.isFresh = function(){
+  return fresh(this.req.headers, this.res._headers);
+};
+
+/**
+ * Redirect to `path`.
+ *
+ * @param {String} path
+ * @api private
+ */
+
+SendStream.prototype.redirect = function(path){
+  if (this.listeners('directory').length) return this.emit('directory');
+  var res = this.res;
+  path += '/';
+  res.statusCode = 301;
+  res.setHeader('Location', path);
+  res.end('Redirecting to ' + utils.escape(path));
+};
+
+/**
+ * Pipe to `res.
+ *
+ * @param {Stream} res
+ * @return {Stream} res
+ * @api public
+ */
+
+SendStream.prototype.pipe = function(res){
+  var self = this
+    , args = arguments
+    , path = this.path
+    , root = this._root;
+
+  // references
+  this.res = res;
+
+  // invalid request uri
+  path = utils.decode(path);
+  if (-1 == path) return this.error(400);
+
+  // null byte(s)
+  if (~path.indexOf('\0')) return this.error(400);
+
+  // join / normalize from optional root dir
+  if (root) path = normalize(join(this._root, path));
+
+  // ".." is malicious without "root"
+  if (this.isMalicious()) return this.error(403);
+
+  // malicious path
+  if (root && 0 != path.indexOf(root)) return this.error(403);
+
+  // hidden file support
+  if (!this._hidden && this.hasLeadingDot()) return this.error(404);
+
+  // index file support
+  if (this._index && this.hasTrailingSlash()) path += this._index;
+
+  debug('stat "%s"', path);
+  fs.stat(path, function(err, stat){
+    if (err) return self.onStatError(err);
+    if (stat.isDirectory()) return self.redirect(self.path);
+    self.emit('file', path, stat);
+    self.send(path, stat);
+  });
+
+  return res;
+};
+
+/**
+ * Transfer `path`.
+ *
+ * @param {String} path
+ * @api public
+ */
+
+SendStream.prototype.send = function(path, stat){
+  var options = this.options;
+  var len = stat.size;
+  var res = this.res;
+  var req = this.req;
+  var ranges = req.headers.range;
+  var offset = options.start || 0;
+
+  // set header fields
+  this.setHeader(stat);
+
+  // set content-type
+  this.type(path);
+
+  // conditional GET support
+  if (this.isConditionalGET()
+    && this.isCachable()
+    && this.isFresh()) {
+    return this.notModified();
+  }
+
+  // adjust len to start/end options
+  len = Math.max(0, len - offset);
+  if (options.end !== undefined) {
+    var bytes = options.end - offset + 1;
+    if (len > bytes) len = bytes;
+  }
+
+  // Range support
+  if (ranges) {
+    ranges = parseRange(len, ranges);
+
+    // unsatisfiable
+    if (-1 == ranges) {
+      res.setHeader('Content-Range', 'bytes */' + stat.size);
+      return this.error(416);
+    }
+
+    // valid (syntactically invalid ranges are treated as a regular response)
+    if (-2 != ranges) {
+      options.start = offset + ranges[0].start;
+      options.end = offset + ranges[0].end;
+
+      // Content-Range
+      res.statusCode = 206;
+      res.setHeader('Content-Range', 'bytes '
+        + ranges[0].start
+        + '-'
+        + ranges[0].end
+        + '/'
+        + len);
+      len = options.end - options.start + 1;
+    }
+  }
+
+  // content-length
+  res.setHeader('Content-Length', len);
+
+  // HEAD support
+  if ('HEAD' == req.method) return res.end();
+
+  this.stream(path, options);
+};
+
+/**
+ * Stream `path` to the response.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @api private
+ */
+
+SendStream.prototype.stream = function(path, options){
+  // TODO: this is all lame, refactor meeee
+  var self = this;
+  var res = this.res;
+  var req = this.req;
+
+  // pipe
+  var stream = fs.createReadStream(path, options);
+  this.emit('stream', stream);
+  stream.pipe(res);
+
+  // socket closed, done with the fd
+  req.on('close', stream.destroy.bind(stream));
+
+  // error handling code-smell
+  stream.on('error', function(err){
+    // no hope in responding
+    if (res._header) {
+      console.error(err.stack);
+      req.destroy();
+      return;
+    }
+
+    // 500
+    err.status = 500;
+    self.emit('error', err);
+  });
+
+  // end
+  stream.on('end', function(){
+    self.emit('end');
+  });
+};
+
+/**
+ * Set content-type based on `path`
+ * if it hasn't been explicitly set.
+ *
+ * @param {String} path
+ * @api private
+ */
+
+SendStream.prototype.type = function(path){
+  var res = this.res;
+  if (res.getHeader('Content-Type')) return;
+  var type = mime.lookup(path);
+  var charset = mime.charsets.lookup(type);
+  debug('content-type %s', type);
+  res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
+};
+
+/**
+ * Set reaponse header fields, most
+ * fields may be pre-defined.
+ *
+ * @param {Object} stat
+ * @api private
+ */
+
+SendStream.prototype.setHeader = function(stat){
+  var res = this.res;
+  if (!res.getHeader('Accept-Ranges')) res.setHeader('Accept-Ranges', 'bytes');
+  if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat));
+  if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString());
+  if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (this._maxage / 1000));
+  if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/lib/utils.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/lib/utils.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/lib/utils.js	(revision 484)
@@ -0,0 +1,47 @@
+
+/**
+ * Return an ETag in the form of `"<size>-<mtime>"`
+ * from the given `stat`.
+ *
+ * @param {Object} stat
+ * @return {String}
+ * @api private
+ */
+
+exports.etag = function(stat) {
+  return '"' + stat.size + '-' + Number(stat.mtime) + '"';
+};
+
+/**
+ * decodeURIComponent.
+ *
+ * Allows V8 to only deoptimize this fn instead of all
+ * of send().
+ *
+ * @param {String} path
+ * @api private
+ */
+
+exports.decode = function(path){
+  try {
+    return decodeURIComponent(path);
+  } catch (err) {
+    return -1;
+  }
+};
+
+/**
+ * Escape the given string of `html`.
+ *
+ * @param {String} html
+ * @return {String}
+ * @api private
+ */
+
+exports.escape = function(html){
+  return String(html)
+    .replace(/&(?!\w+;)/g, '&amp;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;')
+    .replace(/"/g, '&quot;');
+};
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/LICENSE	(revision 484)
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/README.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/README.md	(revision 484)
@@ -0,0 +1,63 @@
+# mime
+
+Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.
+
+## Install
+
+Install with [npm](http://github.com/isaacs/npm):
+
+    npm install mime
+
+## API - Queries
+
+### mime.lookup(path)
+Get the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.').  E.g.
+
+    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)
+Get the default extension for `type`
+
+    mime.extension('text/html');                 // => 'html'
+    mime.extension('application/octet-stream');  // => 'bin'
+
+### mime.charsets.lookup()
+
+Map mime-type to charset
+
+    mime.charsets.lookup('text/plain');        // => 'UTF-8'
+
+(The logic for charset lookups is pretty rudimentary.  Feel free to suggest improvements.)
+
+## API - Defining Custom Types
+
+The following APIs allow you to add your own type mappings within your project.  If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).
+
+### mime.define()
+
+Add custom mime/extension mappings
+
+    mime.define({
+        'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
+        'application/x-my-type': ['x-mt', 'x-mtt'],
+        // etc ...
+    });
+
+    mime.lookup('x-sft');                 // => 'text/x-some-format'
+
+The first entry in the extensions array is returned by `mime.extension()`. E.g.
+
+    mime.extension('text/x-some-format'); // => 'x-sf'
+
+### mime.load(filepath)
+
+Load mappings from an Apache ".types" format file
+
+    mime.load('./my_project.types');
+
+The .types file format is simple -  See the `types` dir for examples.
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/mime.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/mime.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/mime.js	(revision 484)
@@ -0,0 +1,113 @@
+var path = require('path');
+var fs = require('fs');
+
+function Mime() {
+  // Map of extension -> mime type
+  this.types = Object.create(null);
+
+  // Map of mime type -> extension
+  this.extensions = Object.create(null);
+}
+
+/**
+ * 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
+ */
+Mime.prototype.define = function (map) {
+  for (var type in map) {
+    var exts = map[type];
+
+    for (var i = 0; i < exts.length; i++) {
+      if (process.env.DEBUG_MIME && this.types[exts]) {
+        console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' +
+          this.types[exts] + ' to ' + type);
+      }
+
+      this.types[exts[i]] = type;
+    }
+
+    // Default extension is the first one we encounter
+    if (!this.extensions[type]) {
+      this.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.
+ */
+Mime.prototype.load = function(file) {
+
+  this._loading = file;
+  // Read file and split into lines
+  var map = {},
+      content = fs.readFileSync(file, 'ascii'),
+      lines = content.split(/[\r\n]+/);
+
+  lines.forEach(function(line) {
+    // Clean up whitespace/comments, and split into fields
+    var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
+    map[fields.shift()] = fields;
+  });
+
+  this.define(map);
+
+  this._loading = null;
+};
+
+/**
+ * Lookup a mime type based on extension
+ */
+Mime.prototype.lookup = function(path, fallback) {
+  var ext = path.replace(/.*[\.\/]/, '').toLowerCase();
+
+  return this.types[ext] || fallback || this.default_type;
+};
+
+/**
+ * Return file extension associated with a mime type
+ */
+Mime.prototype.extension = function(mimeType) {
+  return this.extensions[mimeType];
+};
+
+// Default instance
+var mime = new Mime();
+
+// Load local copy of
+// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
+mime.load(path.join(__dirname, 'types/mime.types'));
+
+// Load additional types from node.js community
+mime.load(path.join(__dirname, 'types/node.types'));
+
+// Default type
+mime.default_type = mime.lookup('bin');
+
+//
+// Additional API specific to the default instance
+//
+
+mime.Mime = Mime;
+
+/**
+ * Lookup a charset based on mime type.
+ */
+mime.charsets = {
+  lookup: function(mimeType, fallback) {
+    // Assume text types are utf8
+    return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
+  }
+};
+
+module.exports = mime;
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/package.json	(revision 484)
@@ -0,0 +1,35 @@
+{
+  "author": {
+    "name": "Robert Kieffer",
+    "email": "robert@broofa.com",
+    "url": "http://github.com/broofa"
+  },
+  "contributors": [
+    {
+      "name": "Benjamin Thomas",
+      "email": "benjamin@benjaminthomas.org",
+      "url": "http://github.com/bentomas"
+    }
+  ],
+  "dependencies": {},
+  "description": "A comprehensive library for mime-type mapping",
+  "devDependencies": {},
+  "keywords": [
+    "util",
+    "mime"
+  ],
+  "main": "mime.js",
+  "name": "mime",
+  "repository": {
+    "url": "https://github.com/broofa/node-mime",
+    "type": "git"
+  },
+  "version": "1.2.9",
+  "readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n    npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.').  E.g.\n\n    var mime = require('mime');\n\n    mime.lookup('/path/to/file.txt');         // => 'text/plain'\n    mime.lookup('file.txt');                  // => 'text/plain'\n    mime.lookup('.TXT');                      // => 'text/plain'\n    mime.lookup('htm');                       // => 'text/html'\n\n### mime.extension(type)\nGet the default extension for `type`\n\n    mime.extension('text/html');                 // => 'html'\n    mime.extension('application/octet-stream');  // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n    mime.charsets.lookup('text/plain');        // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary.  Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project.  If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n    mime.define({\n        'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n        'application/x-my-type': ['x-mt', 'x-mtt'],\n        // etc ...\n    });\n\n    mime.lookup('x-sft');                 // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n    mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n    mime.load('./my_project.types');\n\nThe .types file format is simple -  See the `types` dir for examples.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/broofa/node-mime/issues"
+  },
+  "_id": "mime@1.2.9",
+  "_from": "mime@~1.2.9"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/test.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/test.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/test.js	(revision 484)
@@ -0,0 +1,55 @@
+/**
+ * Usage: node test.js
+ */
+
+var mime = require('./mime');
+var assert = require('assert');
+
+function eq(a, b) {
+  console.log('Test: ' + a + ' === ' + b);
+  assert.strictEqual.apply(null, arguments);
+}
+
+console.log(Object.keys(mime.extensions).length + ' types');
+console.log(Object.keys(mime.types).length + ' extensions\n');
+
+//
+// Test mime lookups
+//
+
+eq('text/plain', mime.lookup('text.txt'));
+eq('text/plain', mime.lookup('.text.txt'));
+eq('text/plain', mime.lookup('.txt'));
+eq('text/plain', mime.lookup('txt'));
+eq('application/octet-stream', mime.lookup('text.nope'));
+eq('fallback', mime.lookup('text.fallback', 'fallback'));
+eq('application/octet-stream', mime.lookup('constructor'));
+eq('text/plain', mime.lookup('TEXT.TXT'));
+eq('text/event-stream', mime.lookup('text/event-stream'));
+eq('application/x-web-app-manifest+json', mime.lookup('text.webapp'));
+
+//
+// Test extensions
+//
+
+eq('txt', mime.extension(mime.types.text));
+eq('html', mime.extension(mime.types.htm));
+eq('bin', mime.extension('application/octet-stream'));
+eq(undefined, mime.extension('constructor'));
+
+//
+// Test node types
+//
+
+eq('application/octet-stream', mime.lookup('file.buffer'));
+eq('audio/mp4', mime.lookup('file.m4a'));
+
+//
+// Test charsets
+//
+
+eq('UTF-8', mime.charsets.lookup('text/plain'));
+eq(undefined, mime.charsets.lookup(mime.types.js));
+eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
+
+console.log('\nOK');
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/types/mime.types
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/types/mime.types	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/types/mime.types	(revision 484)
@@ -0,0 +1,1588 @@
+# This file maps Internet media types to unique file extension(s).
+# Although created for httpd, this file is used by many software systems
+# and has been placed in the public domain for unlimited redisribution.
+#
+# The table below contains both registered and (common) unregistered types.
+# A type that has no unique extension can be ignored -- they are listed
+# here to guide configurations toward known types and to make it easier to
+# identify "new" types.  File extensions are also commonly used to indicate
+# content languages and encodings, so choose them carefully.
+#
+# Internet media types should be registered as described in RFC 4288.
+# The registry is at <http://www.iana.org/assignments/media-types/>.
+#
+# MIME type (lowercased)			Extensions
+# ============================================	==========
+# application/1d-interleaved-parityfec
+# application/3gpp-ims+xml
+# application/activemessage
+application/andrew-inset			ez
+# application/applefile
+application/applixware				aw
+application/atom+xml				atom
+application/atomcat+xml				atomcat
+# application/atomicmail
+application/atomsvc+xml				atomsvc
+# application/auth-policy+xml
+# application/batch-smtp
+# application/beep+xml
+# application/calendar+xml
+# application/cals-1840
+# application/ccmp+xml
+application/ccxml+xml				ccxml
+application/cdmi-capability			cdmia
+application/cdmi-container			cdmic
+application/cdmi-domain				cdmid
+application/cdmi-object				cdmio
+application/cdmi-queue				cdmiq
+# application/cea-2018+xml
+# application/cellml+xml
+# application/cfw
+# application/cnrp+xml
+# application/commonground
+# application/conference-info+xml
+# application/cpl+xml
+# application/csta+xml
+# application/cstadata+xml
+application/cu-seeme				cu
+# application/cybercash
+application/davmount+xml			davmount
+# application/dca-rft
+# application/dec-dx
+# application/dialog-info+xml
+# application/dicom
+# application/dns
+application/docbook+xml				dbk
+# application/dskpp+xml
+application/dssc+der				dssc
+application/dssc+xml				xdssc
+# application/dvcs
+application/ecmascript				ecma
+# application/edi-consent
+# application/edi-x12
+# application/edifact
+application/emma+xml				emma
+# application/epp+xml
+application/epub+zip				epub
+# application/eshop
+# application/example
+application/exi					exi
+# application/fastinfoset
+# application/fastsoap
+# application/fits
+application/font-tdpfr				pfr
+# application/framework-attributes+xml
+application/gml+xml				gml
+application/gpx+xml				gpx
+application/gxf					gxf
+# 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/inkml+xml				ink inkml
+# 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/jsonml+json				jsonml
+# application/kpml-request+xml
+# application/kpml-response+xml
+application/lost+xml				lostxml
+application/mac-binhex40			hqx
+application/mac-compactpro			cpt
+# application/macwriteii
+application/mads+xml				mads
+application/marc				mrc
+application/marcxml+xml				mrcx
+application/mathematica				ma nb mb
+# application/mathml-content+xml
+# application/mathml-presentation+xml
+application/mathml+xml				mathml
+# application/mbms-associated-procedure-description+xml
+# application/mbms-deregister+xml
+# application/mbms-envelope+xml
+# application/mbms-msk+xml
+# application/mbms-msk-response+xml
+# application/mbms-protection-description+xml
+# application/mbms-reception-report+xml
+# application/mbms-register+xml
+# application/mbms-register-response+xml
+# application/mbms-user-service-description+xml
+application/mbox				mbox
+# application/media_control+xml
+application/mediaservercontrol+xml		mscml
+application/metalink+xml			metalink
+application/metalink4+xml			meta4
+application/mets+xml				mets
+# application/mikey
+application/mods+xml				mods
+# application/moss-keys
+# application/moss-signature
+# application/mosskey-data
+# application/mosskey-request
+application/mp21				m21 mp21
+application/mp4					mp4s
+# application/mpeg4-generic
+# application/mpeg4-iod
+# application/mpeg4-iod-xmt
+# application/msc-ivr+xml
+# application/msc-mixer+xml
+application/msword				doc dot
+application/mxf					mxf
+# application/nasdata
+# application/news-checkgroups
+# application/news-groupinfo
+# application/news-transmission
+# application/nss
+# application/ocsp-request
+# application/ocsp-response
+application/octet-stream	bin dms lrf mar so dist distz pkg bpk dump elc deploy
+application/oda					oda
+application/oebps-package+xml			opf
+application/ogg					ogx
+application/omdoc+xml				omdoc
+application/onenote				onetoc onetoc2 onetmp onepkg
+application/oxps				oxps
+# application/parityfec
+application/patch-ops-error+xml			xer
+application/pdf					pdf
+application/pgp-encrypted			pgp
+# application/pgp-keys
+application/pgp-signature			asc sig
+application/pics-rules				prf
+# application/pidf+xml
+# application/pidf-diff+xml
+application/pkcs10				p10
+application/pkcs7-mime				p7m p7c
+application/pkcs7-signature			p7s
+application/pkcs8				p8
+application/pkix-attr-cert			ac
+application/pkix-cert				cer
+application/pkix-crl				crl
+application/pkix-pkipath			pkipath
+application/pkixcmp				pki
+application/pls+xml				pls
+# application/poc-settings+xml
+application/postscript				ai eps ps
+# application/prs.alvestrand.titrax-sheet
+application/prs.cww				cww
+# application/prs.nprend
+# application/prs.plucker
+# application/prs.rdf-xml-crypt
+# application/prs.xsf+xml
+application/pskc+xml				pskcxml
+# application/qsig
+application/rdf+xml				rdf
+application/reginfo+xml				rif
+application/relax-ng-compact-syntax		rnc
+# application/remote-printing
+application/resource-lists+xml			rl
+application/resource-lists-diff+xml		rld
+# application/riscos
+# application/rlmi+xml
+application/rls-services+xml			rs
+application/rpki-ghostbusters			gbr
+application/rpki-manifest			mft
+application/rpki-roa				roa
+# application/rpki-updown
+application/rsd+xml				rsd
+application/rss+xml				rss
+application/rtf					rtf
+# application/rtx
+# application/samlassertion+xml
+# application/samlmetadata+xml
+application/sbml+xml				sbml
+application/scvp-cv-request			scq
+application/scvp-cv-response			scs
+application/scvp-vp-request			spq
+application/scvp-vp-response			spp
+application/sdp					sdp
+# application/set-payment
+application/set-payment-initiation		setpay
+# application/set-registration
+application/set-registration-initiation		setreg
+# application/sgml
+# application/sgml-open-catalog
+application/shf+xml				shf
+# application/sieve
+# application/simple-filter+xml
+# application/simple-message-summary
+# application/simplesymbolcontainer
+# application/slate
+# application/smil
+application/smil+xml				smi smil
+# application/soap+fastinfoset
+# application/soap+xml
+application/sparql-query			rq
+application/sparql-results+xml			srx
+# application/spirits-event+xml
+application/srgs				gram
+application/srgs+xml				grxml
+application/sru+xml				sru
+application/ssdl+xml				ssdl
+application/ssml+xml				ssml
+# application/tamp-apex-update
+# application/tamp-apex-update-confirm
+# application/tamp-community-update
+# application/tamp-community-update-confirm
+# application/tamp-error
+# application/tamp-sequence-adjust
+# application/tamp-sequence-adjust-confirm
+# application/tamp-status-query
+# application/tamp-status-response
+# application/tamp-update
+# application/tamp-update-confirm
+application/tei+xml				tei teicorpus
+application/thraud+xml				tfi
+# application/timestamp-query
+# application/timestamp-reply
+application/timestamped-data			tsd
+# application/tve-trigger
+# application/ulpfec
+# application/vcard+xml
+# 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.formscentral.fcdt		fcdt
+application/vnd.adobe.fxp			fxp fxpl
+# application/vnd.adobe.partial-upload
+application/vnd.adobe.xdp+xml			xdp
+application/vnd.adobe.xfdf			xfdf
+# application/vnd.aether.imp
+# application/vnd.ah-barcode
+application/vnd.ahead.space			ahead
+application/vnd.airzip.filesecure.azf		azf
+application/vnd.airzip.filesecure.azs		azs
+application/vnd.amazon.ebook			azw
+application/vnd.americandynamics.acc		acc
+application/vnd.amiga.ami			ami
+# application/vnd.amundsen.maze+xml
+application/vnd.android.package-archive		apk
+application/vnd.anser-web-certificate-issue-initiation	cii
+application/vnd.anser-web-funds-transfer-initiation	fti
+application/vnd.antix.game-component		atx
+application/vnd.apple.installer+xml		mpkg
+application/vnd.apple.mpegurl			m3u8
+# application/vnd.arastra.swi
+application/vnd.aristanetworks.swi		swi
+application/vnd.astraea-software.iota		iota
+application/vnd.audiograph			aep
+# application/vnd.autopackage
+# application/vnd.avistar+xml
+application/vnd.blueice.multipass		mpm
+# application/vnd.bluetooth.ep.oob
+application/vnd.bmi				bmi
+application/vnd.businessobjects			rep
+# application/vnd.cab-jscript
+# application/vnd.canon-cpdl
+# application/vnd.canon-lips
+# application/vnd.cendio.thinlinc.clientconf
+application/vnd.chemdraw+xml			cdxml
+application/vnd.chipnuts.karaoke-mmd		mmd
+application/vnd.cinderella			cdy
+# application/vnd.cirpack.isdn-ext
+application/vnd.claymore			cla
+application/vnd.cloanto.rp9			rp9
+application/vnd.clonk.c4group			c4g c4d c4f c4p c4u
+application/vnd.cluetrust.cartomobile-config		c11amc
+application/vnd.cluetrust.cartomobile-config-pkg	c11amz
+# application/vnd.collection+json
+# 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
+application/vnd.curl.car			car
+application/vnd.curl.pcurl			pcurl
+# application/vnd.cybank
+application/vnd.dart				dart
+application/vnd.data-vision.rdz			rdz
+application/vnd.dece.data			uvf uvvf uvd uvvd
+application/vnd.dece.ttml+xml			uvt uvvt
+application/vnd.dece.unspecified		uvx uvvx
+application/vnd.dece.zip			uvz uvvz
+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.ds-keypoint			kpxx
+application/vnd.dvb.ait				ait
+# application/vnd.dvb.dvbj
+# application/vnd.dvb.esgcontainer
+# application/vnd.dvb.ipdcdftnotifaccess
+# application/vnd.dvb.ipdcesgaccess
+# application/vnd.dvb.ipdcesgaccess2
+# application/vnd.dvb.ipdcesgpdd
+# application/vnd.dvb.ipdcroaming
+# application/vnd.dvb.iptv.alfec-base
+# application/vnd.dvb.iptv.alfec-enhancement
+# application/vnd.dvb.notif-aggregate-root+xml
+# application/vnd.dvb.notif-container+xml
+# application/vnd.dvb.notif-generic+xml
+# application/vnd.dvb.notif-ia-msglist+xml
+# application/vnd.dvb.notif-ia-registration-request+xml
+# application/vnd.dvb.notif-ia-registration-response+xml
+# application/vnd.dvb.notif-init+xml
+# application/vnd.dvb.pfr
+application/vnd.dvb.service			svc
+# application/vnd.dxr
+application/vnd.dynageo				geo
+# application/vnd.easykaraoke.cdgdownload
+# application/vnd.ecdis-update
+application/vnd.ecowin.chart			mag
+# application/vnd.ecowin.filerequest
+# application/vnd.ecowin.fileupdate
+# application/vnd.ecowin.series
+# application/vnd.ecowin.seriesrequest
+# application/vnd.ecowin.seriesupdate
+# application/vnd.emclient.accessrequest+xml
+application/vnd.enliven				nml
+# application/vnd.eprints.data+xml
+application/vnd.epson.esf			esf
+application/vnd.epson.msf			msf
+application/vnd.epson.quickanime		qam
+application/vnd.epson.salt			slt
+application/vnd.epson.ssf			ssf
+# application/vnd.ericsson.quickcall
+application/vnd.eszigno3+xml			es3 et3
+# application/vnd.etsi.aoc+xml
+# application/vnd.etsi.cug+xml
+# application/vnd.etsi.iptvcommand+xml
+# application/vnd.etsi.iptvdiscovery+xml
+# application/vnd.etsi.iptvprofile+xml
+# application/vnd.etsi.iptvsad-bc+xml
+# application/vnd.etsi.iptvsad-cod+xml
+# application/vnd.etsi.iptvsad-npvr+xml
+# application/vnd.etsi.iptvservice+xml
+# application/vnd.etsi.iptvsync+xml
+# application/vnd.etsi.iptvueprofile+xml
+# application/vnd.etsi.mcid+xml
+# application/vnd.etsi.overload-control-policy-dataset+xml
+# application/vnd.etsi.sci+xml
+# application/vnd.etsi.simservs+xml
+# application/vnd.etsi.tsl+xml
+# application/vnd.etsi.tsl.der
+# application/vnd.eudora.data
+application/vnd.ezpix-album			ez2
+application/vnd.ezpix-package			ez3
+# application/vnd.f-secure.mobile
+application/vnd.fdf				fdf
+application/vnd.fdsn.mseed			mseed
+application/vnd.fdsn.seed			seed dataless
+# application/vnd.ffsns
+# application/vnd.fints
+application/vnd.flographit			gph
+application/vnd.fluxtime.clip			ftc
+# application/vnd.font-fontforge-sfd
+application/vnd.framemaker			fm frame maker book
+application/vnd.frogans.fnc			fnc
+application/vnd.frogans.ltf			ltf
+application/vnd.fsc.weblaunch			fsc
+application/vnd.fujitsu.oasys			oas
+application/vnd.fujitsu.oasys2			oa2
+application/vnd.fujitsu.oasys3			oa3
+application/vnd.fujitsu.oasysgp			fg5
+application/vnd.fujitsu.oasysprs		bh2
+# application/vnd.fujixerox.art-ex
+# application/vnd.fujixerox.art4
+# application/vnd.fujixerox.hbpl
+application/vnd.fujixerox.ddd			ddd
+application/vnd.fujixerox.docuworks		xdw
+application/vnd.fujixerox.docuworks.binder	xbd
+# application/vnd.fut-misnet
+application/vnd.fuzzysheet			fzs
+application/vnd.genomatix.tuxedo		txd
+# application/vnd.geocube+xml
+application/vnd.geogebra.file			ggb
+application/vnd.geogebra.tool			ggt
+application/vnd.geometry-explorer		gex gre
+application/vnd.geonext				gxt
+application/vnd.geoplan				g2w
+application/vnd.geospace			g3w
+# application/vnd.globalplatform.card-content-mgt
+# application/vnd.globalplatform.card-content-mgt-response
+application/vnd.gmx				gmx
+application/vnd.google-earth.kml+xml		kml
+application/vnd.google-earth.kmz		kmz
+application/vnd.grafeq				gqf gqs
+# application/vnd.gridmp
+application/vnd.groove-account			gac
+application/vnd.groove-help			ghf
+application/vnd.groove-identity-message		gim
+application/vnd.groove-injector			grv
+application/vnd.groove-tool-message		gtm
+application/vnd.groove-tool-template		tpl
+application/vnd.groove-vcard			vcg
+# application/vnd.hal+json
+application/vnd.hal+xml				hal
+application/vnd.handheld-entertainment+xml	zmm
+application/vnd.hbci				hbci
+# application/vnd.hcl-bireports
+application/vnd.hhe.lesson-player		les
+application/vnd.hp-hpgl				hpgl
+application/vnd.hp-hpid				hpid
+application/vnd.hp-hps				hps
+application/vnd.hp-jlyt				jlt
+application/vnd.hp-pcl				pcl
+application/vnd.hp-pclxl			pclxl
+# application/vnd.httphone
+application/vnd.hydrostatix.sof-data		sfd-hdstx
+# application/vnd.hzn-3d-crossword
+# application/vnd.ibm.afplinedata
+# application/vnd.ibm.electronic-media
+application/vnd.ibm.minipay			mpy
+application/vnd.ibm.modcap			afp listafp list3820
+application/vnd.ibm.rights-management		irm
+application/vnd.ibm.secure-container		sc
+application/vnd.iccprofile			icc icm
+application/vnd.igloader			igl
+application/vnd.immervision-ivp			ivp
+application/vnd.immervision-ivu			ivu
+# application/vnd.informedcontrol.rms+xml
+# application/vnd.informix-visionary
+# application/vnd.infotech.project
+# application/vnd.infotech.project+xml
+# application/vnd.innopath.wamp.notification
+application/vnd.insors.igm			igm
+application/vnd.intercon.formnet		xpw xpx
+application/vnd.intergeo			i2g
+# application/vnd.intertrust.digibox
+# application/vnd.intertrust.nncp
+application/vnd.intu.qbo			qbo
+application/vnd.intu.qfx			qfx
+# application/vnd.iptc.g2.conceptitem+xml
+# application/vnd.iptc.g2.knowledgeitem+xml
+# application/vnd.iptc.g2.newsitem+xml
+# application/vnd.iptc.g2.newsmessage+xml
+# application/vnd.iptc.g2.packageitem+xml
+# application/vnd.iptc.g2.planningitem+xml
+application/vnd.ipunplugged.rcprofile		rcprofile
+application/vnd.irepository.package+xml		irp
+application/vnd.is-xpr				xpr
+application/vnd.isac.fcs			fcs
+application/vnd.jam				jam
+# application/vnd.japannet-directory-service
+# application/vnd.japannet-jpnstore-wakeup
+# application/vnd.japannet-payment-wakeup
+# application/vnd.japannet-registration
+# application/vnd.japannet-registration-wakeup
+# application/vnd.japannet-setstore-wakeup
+# application/vnd.japannet-verification
+# application/vnd.japannet-verification-wakeup
+application/vnd.jcp.javame.midlet-rms		rms
+application/vnd.jisp				jisp
+application/vnd.joost.joda-archive		joda
+application/vnd.kahootz				ktz ktr
+application/vnd.kde.karbon			karbon
+application/vnd.kde.kchart			chrt
+application/vnd.kde.kformula			kfo
+application/vnd.kde.kivio			flw
+application/vnd.kde.kontour			kon
+application/vnd.kde.kpresenter			kpr kpt
+application/vnd.kde.kspread			ksp
+application/vnd.kde.kword			kwd kwt
+application/vnd.kenameaapp			htke
+application/vnd.kidspiration			kia
+application/vnd.kinar				kne knp
+application/vnd.koan				skp skd skt skm
+application/vnd.kodak-descriptor		sse
+application/vnd.las.las+xml			lasxml
+# application/vnd.liberty-request+xml
+application/vnd.llamagraphics.life-balance.desktop	lbd
+application/vnd.llamagraphics.life-balance.exchange+xml	lbe
+application/vnd.lotus-1-2-3			123
+application/vnd.lotus-approach			apr
+application/vnd.lotus-freelance			pre
+application/vnd.lotus-notes			nsf
+application/vnd.lotus-organizer			org
+application/vnd.lotus-screencam			scm
+application/vnd.lotus-wordpro			lwp
+application/vnd.macports.portpkg		portpkg
+# application/vnd.marlin.drm.actiontoken+xml
+# application/vnd.marlin.drm.conftoken+xml
+# application/vnd.marlin.drm.license+xml
+# application/vnd.marlin.drm.mdcf
+application/vnd.mcd				mcd
+application/vnd.medcalcdata			mc1
+application/vnd.mediastation.cdkey		cdkey
+# application/vnd.meridian-slingshot
+application/vnd.mfer				mwf
+application/vnd.mfmp				mfm
+application/vnd.micrografx.flo			flo
+application/vnd.micrografx.igx			igx
+application/vnd.mif				mif
+# application/vnd.minisoft-hp3000-save
+# application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf			daf
+application/vnd.mobius.dis			dis
+application/vnd.mobius.mbk			mbk
+application/vnd.mobius.mqy			mqy
+application/vnd.mobius.msl			msl
+application/vnd.mobius.plc			plc
+application/vnd.mobius.txf			txf
+application/vnd.mophun.application		mpn
+application/vnd.mophun.certificate		mpc
+# application/vnd.motorola.flexsuite
+# application/vnd.motorola.flexsuite.adsi
+# application/vnd.motorola.flexsuite.fis
+# application/vnd.motorola.flexsuite.gotap
+# application/vnd.motorola.flexsuite.kmr
+# application/vnd.motorola.flexsuite.ttc
+# application/vnd.motorola.flexsuite.wem
+# application/vnd.motorola.iprm
+application/vnd.mozilla.xul+xml			xul
+application/vnd.ms-artgalry			cil
+# application/vnd.ms-asf
+application/vnd.ms-cab-compressed		cab
+# application/vnd.ms-color.iccprofile
+application/vnd.ms-excel			xls xlm xla xlc xlt xlw
+application/vnd.ms-excel.addin.macroenabled.12		xlam
+application/vnd.ms-excel.sheet.binary.macroenabled.12	xlsb
+application/vnd.ms-excel.sheet.macroenabled.12		xlsm
+application/vnd.ms-excel.template.macroenabled.12	xltm
+application/vnd.ms-fontobject			eot
+application/vnd.ms-htmlhelp			chm
+application/vnd.ms-ims				ims
+application/vnd.ms-lrm				lrm
+# application/vnd.ms-office.activex+xml
+application/vnd.ms-officetheme			thmx
+# application/vnd.ms-opentype
+# application/vnd.ms-package.obfuscated-opentype
+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-printing.printticket+xml
+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.mynfc				taglet
+# application/vnd.ncd.control
+# application/vnd.ncd.reference
+# application/vnd.nervana
+# application/vnd.netfpx
+application/vnd.neurolanguage.nlu		nlu
+application/vnd.nitf				ntf nitf
+application/vnd.noblenet-directory		nnd
+application/vnd.noblenet-sealer			nns
+application/vnd.noblenet-web			nnw
+# application/vnd.nokia.catalogs
+# application/vnd.nokia.conml+wbxml
+# application/vnd.nokia.conml+xml
+# application/vnd.nokia.isds-radio-presets
+# application/vnd.nokia.iptv.config+xml
+# application/vnd.nokia.landmark+wbxml
+# application/vnd.nokia.landmark+xml
+# application/vnd.nokia.landmarkcollection+xml
+# application/vnd.nokia.n-gage.ac+xml
+application/vnd.nokia.n-gage.data		ngdat
+application/vnd.nokia.n-gage.symbian.install	n-gage
+# application/vnd.nokia.ncd
+# application/vnd.nokia.pcd+wbxml
+# application/vnd.nokia.pcd+xml
+application/vnd.nokia.radio-preset		rpst
+application/vnd.nokia.radio-presets		rpss
+application/vnd.novadigm.edm			edm
+application/vnd.novadigm.edx			edx
+application/vnd.novadigm.ext			ext
+# application/vnd.ntt-local.file-transfer
+# application/vnd.ntt-local.sip-ta_remote
+# application/vnd.ntt-local.sip-ta_tcp_stream
+application/vnd.oasis.opendocument.chart		odc
+application/vnd.oasis.opendocument.chart-template	otc
+application/vnd.oasis.opendocument.database		odb
+application/vnd.oasis.opendocument.formula		odf
+application/vnd.oasis.opendocument.formula-template	odft
+application/vnd.oasis.opendocument.graphics		odg
+application/vnd.oasis.opendocument.graphics-template	otg
+application/vnd.oasis.opendocument.image		odi
+application/vnd.oasis.opendocument.image-template	oti
+application/vnd.oasis.opendocument.presentation		odp
+application/vnd.oasis.opendocument.presentation-template	otp
+application/vnd.oasis.opendocument.spreadsheet		ods
+application/vnd.oasis.opendocument.spreadsheet-template	ots
+application/vnd.oasis.opendocument.text			odt
+application/vnd.oasis.opendocument.text-master		odm
+application/vnd.oasis.opendocument.text-template	ott
+application/vnd.oasis.opendocument.text-web		oth
+# application/vnd.obn
+# application/vnd.oftn.l10n+json
+# application/vnd.oipf.contentaccessdownload+xml
+# application/vnd.oipf.contentaccessstreaming+xml
+# application/vnd.oipf.cspg-hexbinary
+# application/vnd.oipf.dae.svg+xml
+# application/vnd.oipf.dae.xhtml+xml
+# application/vnd.oipf.mippvcontrolmessage+xml
+# application/vnd.oipf.pae.gem
+# application/vnd.oipf.spdiscovery+xml
+# application/vnd.oipf.spdlist+xml
+# application/vnd.oipf.ueprofile+xml
+# application/vnd.oipf.userprofile+xml
+application/vnd.olpc-sugar			xo
+# application/vnd.oma-scws-config
+# application/vnd.oma-scws-http-request
+# application/vnd.oma-scws-http-response
+# application/vnd.oma.bcast.associated-procedure-parameter+xml
+# application/vnd.oma.bcast.drm-trigger+xml
+# application/vnd.oma.bcast.imd+xml
+# application/vnd.oma.bcast.ltkm
+# application/vnd.oma.bcast.notification+xml
+# application/vnd.oma.bcast.provisioningtrigger
+# application/vnd.oma.bcast.sgboot
+# application/vnd.oma.bcast.sgdd+xml
+# application/vnd.oma.bcast.sgdu
+# application/vnd.oma.bcast.simple-symbol-container
+# application/vnd.oma.bcast.smartcard-trigger+xml
+# application/vnd.oma.bcast.sprov+xml
+# application/vnd.oma.bcast.stkm
+# application/vnd.oma.cab-address-book+xml
+# application/vnd.oma.cab-feature-handler+xml
+# application/vnd.oma.cab-pcc+xml
+# application/vnd.oma.cab-user-prefs+xml
+# application/vnd.oma.dcd
+# application/vnd.oma.dcdc
+application/vnd.oma.dd2+xml			dd2
+# application/vnd.oma.drm.risd+xml
+# application/vnd.oma.group-usage-list+xml
+# application/vnd.oma.pal+xml
+# application/vnd.oma.poc.detailed-progress-report+xml
+# application/vnd.oma.poc.final-report+xml
+# application/vnd.oma.poc.groups+xml
+# application/vnd.oma.poc.invocation-descriptor+xml
+# application/vnd.oma.poc.optimized-progress-report+xml
+# application/vnd.oma.push
+# application/vnd.oma.scidm.messages+xml
+# application/vnd.oma.xcap-directory+xml
+# application/vnd.omads-email+xml
+# application/vnd.omads-file+xml
+# application/vnd.omads-folder+xml
+# application/vnd.omaloc-supl-init
+application/vnd.openofficeorg.extension		oxt
+# application/vnd.openxmlformats-officedocument.custom-properties+xml
+# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
+# application/vnd.openxmlformats-officedocument.drawing+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
+# application/vnd.openxmlformats-officedocument.extended-properties+xml
+# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
+# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
+# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
+application/vnd.openxmlformats-officedocument.presentationml.presentation	pptx
+# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
+application/vnd.openxmlformats-officedocument.presentationml.slide	sldx
+# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
+application/vnd.openxmlformats-officedocument.presentationml.slideshow	ppsx
+# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
+application/vnd.openxmlformats-officedocument.presentationml.template	potx
+# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet	xlsx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.template	xltx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
+# application/vnd.openxmlformats-officedocument.theme+xml
+# application/vnd.openxmlformats-officedocument.themeoverride+xml
+# application/vnd.openxmlformats-officedocument.vmldrawing
+# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.document	docx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.template	dotx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
+# application/vnd.openxmlformats-package.core-properties+xml
+# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
+# application/vnd.openxmlformats-package.relationships+xml
+# application/vnd.quobject-quoxdocument
+# application/vnd.osa.netdeploy
+application/vnd.osgeo.mapguide.package		mgp
+# application/vnd.osgi.bundle
+application/vnd.osgi.dp				dp
+application/vnd.osgi.subsystem			esa
+# application/vnd.otps.ct-kip+xml
+application/vnd.palm				pdb pqa oprc
+# application/vnd.paos.xml
+application/vnd.pawaafile			paw
+application/vnd.pg.format			str
+application/vnd.pg.osasli			ei6
+# application/vnd.piaccess.application-licence
+application/vnd.picsel				efif
+application/vnd.pmi.widget			wg
+# application/vnd.poc.group-advertisement+xml
+application/vnd.pocketlearn			plf
+application/vnd.powerbuilder6			pbd
+# application/vnd.powerbuilder6-s
+# application/vnd.powerbuilder7
+# application/vnd.powerbuilder7-s
+# application/vnd.powerbuilder75
+# application/vnd.powerbuilder75-s
+# application/vnd.preminet
+application/vnd.previewsystems.box		box
+application/vnd.proteus.magazine		mgz
+application/vnd.publishare-delta-tree		qps
+application/vnd.pvi.ptid1			ptid
+# application/vnd.pwg-multiplexed
+# application/vnd.pwg-xhtml-print+xml
+# application/vnd.qualcomm.brew-app-res
+application/vnd.quark.quarkxpress		qxd qxt qwd qwt qxl qxb
+# application/vnd.radisys.moml+xml
+# application/vnd.radisys.msml+xml
+# application/vnd.radisys.msml-audit+xml
+# application/vnd.radisys.msml-audit-conf+xml
+# application/vnd.radisys.msml-audit-conn+xml
+# application/vnd.radisys.msml-audit-dialog+xml
+# application/vnd.radisys.msml-audit-stream+xml
+# application/vnd.radisys.msml-conf+xml
+# application/vnd.radisys.msml-dialog+xml
+# application/vnd.radisys.msml-dialog-base+xml
+# application/vnd.radisys.msml-dialog-fax-detect+xml
+# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
+# application/vnd.radisys.msml-dialog-group+xml
+# application/vnd.radisys.msml-dialog-speech+xml
+# application/vnd.radisys.msml-dialog-transform+xml
+# application/vnd.rainstor.data
+# application/vnd.rapid
+application/vnd.realvnc.bed			bed
+application/vnd.recordare.musicxml		mxl
+application/vnd.recordare.musicxml+xml		musicxml
+# application/vnd.renlearn.rlprint
+application/vnd.rig.cryptonote			cryptonote
+application/vnd.rim.cod				cod
+application/vnd.rn-realmedia			rm
+application/vnd.rn-realmedia-vbr		rmvb
+application/vnd.route66.link66+xml		link66
+# application/vnd.rs-274x
+# application/vnd.ruckus.download
+# application/vnd.s3sms
+application/vnd.sailingtracker.track		st
+# application/vnd.sbm.cid
+# application/vnd.sbm.mid2
+# application/vnd.scribus
+# application/vnd.sealed.3df
+# application/vnd.sealed.csf
+# application/vnd.sealed.doc
+# application/vnd.sealed.eml
+# application/vnd.sealed.mht
+# application/vnd.sealed.net
+# application/vnd.sealed.ppt
+# application/vnd.sealed.tiff
+# application/vnd.sealed.xls
+# application/vnd.sealedmedia.softseal.html
+# application/vnd.sealedmedia.softseal.pdf
+application/vnd.seemail				see
+application/vnd.sema				sema
+application/vnd.semd				semd
+application/vnd.semf				semf
+application/vnd.shana.informed.formdata		ifm
+application/vnd.shana.informed.formtemplate	itp
+application/vnd.shana.informed.interchange	iif
+application/vnd.shana.informed.package		ipk
+application/vnd.simtech-mindmapper		twd twds
+application/vnd.smaf				mmf
+# application/vnd.smart.notebook
+application/vnd.smart.teacher			teacher
+# application/vnd.software602.filler.form+xml
+# application/vnd.software602.filler.form-xml-zip
+application/vnd.solent.sdkm+xml			sdkm sdkd
+application/vnd.spotfire.dxp			dxp
+application/vnd.spotfire.sfs			sfs
+# application/vnd.sss-cod
+# application/vnd.sss-dtf
+# application/vnd.sss-ntf
+application/vnd.stardivision.calc		sdc
+application/vnd.stardivision.draw		sda
+application/vnd.stardivision.impress		sdd
+application/vnd.stardivision.math		smf
+application/vnd.stardivision.writer		sdw vor
+application/vnd.stardivision.writer-global	sgl
+application/vnd.stepmania.package		smzip
+application/vnd.stepmania.stepchart		sm
+# application/vnd.street-stream
+application/vnd.sun.xml.calc			sxc
+application/vnd.sun.xml.calc.template		stc
+application/vnd.sun.xml.draw			sxd
+application/vnd.sun.xml.draw.template		std
+application/vnd.sun.xml.impress			sxi
+application/vnd.sun.xml.impress.template	sti
+application/vnd.sun.xml.math			sxm
+application/vnd.sun.xml.writer			sxw
+application/vnd.sun.xml.writer.global		sxg
+application/vnd.sun.xml.writer.template		stw
+# application/vnd.sun.wadl+xml
+application/vnd.sus-calendar			sus susp
+application/vnd.svd				svd
+# application/vnd.swiftview-ics
+application/vnd.symbian.install			sis sisx
+application/vnd.syncml+xml			xsm
+application/vnd.syncml.dm+wbxml			bdm
+application/vnd.syncml.dm+xml			xdm
+# application/vnd.syncml.dm.notification
+# application/vnd.syncml.ds.notification
+application/vnd.tao.intent-module-archive	tao
+application/vnd.tcpdump.pcap			pcap cap dmp
+application/vnd.tmobile-livetv			tmo
+application/vnd.trid.tpt			tpt
+application/vnd.triscape.mxs			mxs
+application/vnd.trueapp				tra
+# application/vnd.truedoc
+# application/vnd.ubisoft.webplayer
+application/vnd.ufdl				ufd ufdl
+application/vnd.uiq.theme			utz
+application/vnd.umajin				umj
+application/vnd.unity				unityweb
+application/vnd.uoml+xml			uoml
+# application/vnd.uplanet.alert
+# application/vnd.uplanet.alert-wbxml
+# application/vnd.uplanet.bearer-choice
+# application/vnd.uplanet.bearer-choice-wbxml
+# application/vnd.uplanet.cacheop
+# application/vnd.uplanet.cacheop-wbxml
+# application/vnd.uplanet.channel
+# application/vnd.uplanet.channel-wbxml
+# application/vnd.uplanet.list
+# application/vnd.uplanet.list-wbxml
+# application/vnd.uplanet.listcmd
+# application/vnd.uplanet.listcmd-wbxml
+# application/vnd.uplanet.signal
+application/vnd.vcx				vcx
+# application/vnd.vd-study
+# application/vnd.vectorworks
+# application/vnd.verimatrix.vcas
+# application/vnd.vidsoft.vidconference
+application/vnd.visio				vsd vst vss vsw
+application/vnd.visionary			vis
+# application/vnd.vividence.scriptfile
+application/vnd.vsf				vsf
+# application/vnd.wap.sic
+# application/vnd.wap.slc
+application/vnd.wap.wbxml			wbxml
+application/vnd.wap.wmlc			wmlc
+application/vnd.wap.wmlscriptc			wmlsc
+application/vnd.webturbo			wtb
+# application/vnd.wfa.wsc
+# application/vnd.wmc
+# application/vnd.wmf.bootstrap
+# application/vnd.wolfram.mathematica
+# application/vnd.wolfram.mathematica.package
+application/vnd.wolfram.player			nbp
+application/vnd.wordperfect			wpd
+application/vnd.wqd				wqd
+# application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf				stf
+# application/vnd.wv.csp+wbxml
+# application/vnd.wv.csp+xml
+# application/vnd.wv.ssp+xml
+application/vnd.xara				xar
+application/vnd.xfdl				xfdl
+# application/vnd.xfdl.webform
+# application/vnd.xmi+xml
+# application/vnd.xmpie.cpkg
+# application/vnd.xmpie.dpkg
+# application/vnd.xmpie.plan
+# application/vnd.xmpie.ppkg
+# application/vnd.xmpie.xlim
+application/vnd.yamaha.hv-dic			hvd
+application/vnd.yamaha.hv-script		hvs
+application/vnd.yamaha.hv-voice			hvp
+application/vnd.yamaha.openscoreformat			osf
+application/vnd.yamaha.openscoreformat.osfpvg+xml	osfpvg
+# application/vnd.yamaha.remote-setup
+application/vnd.yamaha.smaf-audio		saf
+application/vnd.yamaha.smaf-phrase		spf
+# application/vnd.yamaha.through-ngn
+# application/vnd.yamaha.tunnel-udpencap
+application/vnd.yellowriver-custom-menu		cmp
+application/vnd.zul				zir zirz
+application/vnd.zzazz.deck+xml			zaz
+application/voicexml+xml			vxml
+# application/vq-rtcpxr
+# application/watcherinfo+xml
+# application/whoispp-query
+# application/whoispp-response
+application/widget				wgt
+application/winhlp				hlp
+# application/wita
+# application/wordperfect5.1
+application/wsdl+xml				wsdl
+application/wspolicy+xml			wspolicy
+application/x-7z-compressed			7z
+application/x-abiword				abw
+application/x-ace-compressed			ace
+# application/x-amf
+application/x-apple-diskimage			dmg
+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-blorb				blb blorb
+application/x-bzip				bz
+application/x-bzip2				bz2 boz
+application/x-cbr				cbr cba cbt cbz cb7
+application/x-cdlink				vcd
+application/x-cfs-compressed			cfs
+application/x-chat				chat
+application/x-chess-pgn				pgn
+application/x-conference			nsc
+# application/x-compress
+application/x-cpio				cpio
+application/x-csh				csh
+application/x-debian-package			deb udeb
+application/x-dgc-compressed			dgc
+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-envoy				evy
+application/x-eva				eva
+application/x-font-bdf				bdf
+# application/x-font-dos
+# application/x-font-framemaker
+application/x-font-ghostscript			gsf
+# application/x-font-libgrx
+application/x-font-linux-psf			psf
+application/x-font-otf				otf
+application/x-font-pcf				pcf
+application/x-font-snf				snf
+# application/x-font-speedo
+# application/x-font-sunos-news
+application/x-font-ttf				ttf ttc
+application/x-font-type1			pfa pfb pfm afm
+application/x-font-woff				woff
+# application/x-font-vfont
+application/x-freearc				arc
+application/x-futuresplash			spl
+application/x-gca-compressed			gca
+application/x-glulx				ulx
+application/x-gnumeric				gnumeric
+application/x-gramps-xml			gramps
+application/x-gtar				gtar
+# application/x-gzip
+application/x-hdf				hdf
+application/x-install-instructions		install
+application/x-iso9660-image			iso
+application/x-java-jnlp-file			jnlp
+application/x-latex				latex
+application/x-lzh-compressed			lzh lha
+application/x-mie				mie
+application/x-mobipocket-ebook			prc mobi
+application/x-ms-application			application
+application/x-ms-shortcut			lnk
+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 wmz emf emz
+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-nzb				nzb
+application/x-pkcs12				p12 pfx
+application/x-pkcs7-certificates		p7b spc
+application/x-pkcs7-certreqresp			p7r
+application/x-rar-compressed			rar
+application/x-research-info-systems		ris
+application/x-sh				sh
+application/x-shar				shar
+application/x-shockwave-flash			swf
+application/x-silverlight-app			xap
+application/x-sql				sql
+application/x-stuffit				sit
+application/x-stuffitx				sitx
+application/x-subrip				srt
+application/x-sv4cpio				sv4cpio
+application/x-sv4crc				sv4crc
+application/x-t3vm-image			t3
+application/x-tads				gam
+application/x-tar				tar
+application/x-tcl				tcl
+application/x-tex				tex
+application/x-tex-tfm				tfm
+application/x-texinfo				texinfo texi
+application/x-tgif				obj
+application/x-ustar				ustar
+application/x-wais-source			src
+application/x-x509-ca-cert			der crt
+application/x-xfig				fig
+application/x-xliff+xml				xlf
+application/x-xpinstall				xpi
+application/x-xz				xz
+application/x-zmachine				z1 z2 z3 z4 z5 z6 z7 z8
+# application/x400-bp
+application/xaml+xml				xaml
+# application/xcap-att+xml
+# application/xcap-caps+xml
+application/xcap-diff+xml			xdf
+# application/xcap-el+xml
+# application/xcap-error+xml
+# application/xcap-ns+xml
+# application/xcon-conference-info-diff+xml
+# application/xcon-conference-info+xml
+application/xenc+xml				xenc
+application/xhtml+xml				xhtml xht
+# application/xhtml-voice+xml
+application/xml					xml xsl
+application/xml-dtd				dtd
+# application/xml-external-parsed-entity
+# application/xmpp+xml
+application/xop+xml				xop
+application/xproc+xml				xpl
+application/xslt+xml				xslt
+application/xspf+xml				xspf
+application/xv+xml				mxml xhvml xvml xvm
+application/yang				yang
+application/yin+xml				yin
+application/zip					zip
+# audio/1d-interleaved-parityfec
+# audio/32kadpcm
+# audio/3gpp
+# audio/3gpp2
+# audio/ac3
+audio/adpcm					adp
+# audio/amr
+# audio/amr-wb
+# audio/amr-wb+
+# audio/asc
+# audio/atrac-advanced-lossless
+# audio/atrac-x
+# audio/atrac3
+audio/basic					au snd
+# audio/bv16
+# audio/bv32
+# audio/clearmode
+# audio/cn
+# audio/dat12
+# audio/dls
+# audio/dsr-es201108
+# audio/dsr-es202050
+# audio/dsr-es202211
+# audio/dsr-es202212
+# audio/dv
+# 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/fwdred
+# audio/g719
+# audio/g722
+# audio/g7221
+# audio/g723
+# audio/g726-16
+# audio/g726-24
+# audio/g726-32
+# audio/g726-40
+# audio/g728
+# audio/g729
+# audio/g7291
+# audio/g729d
+# audio/g729e
+# audio/gsm
+# audio/gsm-efr
+# audio/gsm-hr-08
+# audio/ilbc
+# audio/ip-mr_v2.5
+# audio/isac
+# 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/musepack
+audio/ogg					oga ogg spx
+# audio/opus
+# 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/s3m					s3m
+audio/silk					sil
+# audio/smv
+# audio/smv0
+# audio/smv-qcp
+# audio/sp-midi
+# audio/speex
+# audio/t140c
+# audio/t38
+# audio/telephone-event
+# audio/tone
+# audio/uemclip
+# audio/ulpfec
+# audio/vdvi
+# audio/vmr-wb
+# audio/vnd.3gpp.iufp
+# audio/vnd.4sb
+# audio/vnd.audiokoz
+# audio/vnd.celp
+# audio/vnd.cisco.nse
+# audio/vnd.cmles.radio-events
+# audio/vnd.cns.anp1
+# audio/vnd.cns.inf1
+audio/vnd.dece.audio				uva uvva
+audio/vnd.digital-winds				eol
+# audio/vnd.dlna.adts
+# audio/vnd.dolby.heaac.1
+# audio/vnd.dolby.heaac.2
+# audio/vnd.dolby.mlp
+# audio/vnd.dolby.mps
+# audio/vnd.dolby.pl2
+# audio/vnd.dolby.pl2x
+# audio/vnd.dolby.pl2z
+# audio/vnd.dolby.pulse.1
+audio/vnd.dra					dra
+audio/vnd.dts					dts
+audio/vnd.dts.hd				dtshd
+# audio/vnd.dvb.file
+# audio/vnd.everad.plj
+# audio/vnd.hns.audio
+audio/vnd.lucent.voice				lvp
+audio/vnd.ms-playready.media.pya		pya
+# audio/vnd.nokia.mobile-xmf
+# audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800			ecelp4800
+audio/vnd.nuera.ecelp7470			ecelp7470
+audio/vnd.nuera.ecelp9600			ecelp9600
+# audio/vnd.octel.sbc
+# audio/vnd.qcelp
+# audio/vnd.rhetorex.32kadpcm
+audio/vnd.rip					rip
+# audio/vnd.sealedmedia.softseal.mpeg
+# audio/vnd.vmx.cvsd
+# audio/vorbis
+# audio/vorbis-config
+audio/webm					weba
+audio/x-aac					aac
+audio/x-aiff					aif aiff aifc
+audio/x-caf					caf
+audio/x-flac					flac
+audio/x-matroska				mka
+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-tta
+audio/x-wav					wav
+audio/xm					xm
+chemical/x-cdx					cdx
+chemical/x-cif					cif
+chemical/x-cmdf					cmdf
+chemical/x-cml					cml
+chemical/x-csml					csml
+# chemical/x-pdb
+chemical/x-xyz					xyz
+image/bmp					bmp
+image/cgm					cgm
+# image/example
+# image/fits
+image/g3fax					g3
+image/gif					gif
+image/ief					ief
+# image/jp2
+image/jpeg					jpeg jpg jpe
+# image/jpm
+# image/jpx
+image/ktx					ktx
+# image/naplps
+image/png					png
+image/prs.btif					btif
+# image/prs.pti
+image/sgi					sgi
+image/svg+xml					svg svgz
+# image/t38
+image/tiff					tiff tif
+# image/tiff-fx
+image/vnd.adobe.photoshop			psd
+# image/vnd.cns.inf2
+image/vnd.dece.graphic				uvi uvvi uvg uvvg
+image/vnd.dvb.subtitle				sub
+image/vnd.djvu					djvu djv
+image/vnd.dwg					dwg
+image/vnd.dxf					dxf
+image/vnd.fastbidsheet				fbs
+image/vnd.fpx					fpx
+image/vnd.fst					fst
+image/vnd.fujixerox.edmics-mmr			mmr
+image/vnd.fujixerox.edmics-rlc			rlc
+# image/vnd.globalgraphics.pgb
+# image/vnd.microsoft.icon
+# image/vnd.mix
+image/vnd.ms-modi				mdi
+image/vnd.ms-photo				wdp
+image/vnd.net-fpx				npx
+# image/vnd.radiance
+# image/vnd.sealed.png
+# image/vnd.sealedmedia.softseal.gif
+# image/vnd.sealedmedia.softseal.jpg
+# image/vnd.svf
+image/vnd.wap.wbmp				wbmp
+image/vnd.xiff					xif
+image/webp					webp
+image/x-3ds					3ds
+image/x-cmu-raster				ras
+image/x-cmx					cmx
+image/x-freehand				fh fhc fh4 fh5 fh7
+image/x-icon					ico
+image/x-mrsid-image				sid
+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-tga					tga
+image/x-xbitmap					xbm
+image/x-xpixmap					xpm
+image/x-xwindowdump				xwd
+# message/cpim
+# message/delivery-status
+# message/disposition-notification
+# message/example
+# message/external-body
+# message/feedback-report
+# message/global
+# message/global-delivery-status
+# message/global-disposition-notification
+# message/global-headers
+# message/http
+# message/imdn+xml
+# message/news
+# message/partial
+message/rfc822					eml mime
+# message/s-http
+# message/sip
+# message/sipfrag
+# message/tracking-status
+# message/vnd.si.simp
+# model/example
+model/iges					igs iges
+model/mesh					msh mesh silo
+model/vnd.collada+xml				dae
+model/vnd.dwf					dwf
+# model/vnd.flatland.3dml
+model/vnd.gdl					gdl
+# model/vnd.gs-gdl
+# model/vnd.gs.gdl
+model/vnd.gtw					gtw
+# model/vnd.moml+xml
+model/vnd.mts					mts
+# model/vnd.parasolid.transmit.binary
+# model/vnd.parasolid.transmit.text
+model/vnd.vtu					vtu
+model/vrml					wrl vrml
+model/x3d+binary				x3db x3dbz
+model/x3d+vrml					x3dv x3dvz
+model/x3d+xml					x3d x3dz
+# multipart/alternative
+# multipart/appledouble
+# multipart/byteranges
+# multipart/digest
+# multipart/encrypted
+# multipart/example
+# multipart/form-data
+# multipart/header-set
+# multipart/mixed
+# multipart/parallel
+# multipart/related
+# multipart/report
+# multipart/signed
+# multipart/voice-message
+# text/1d-interleaved-parityfec
+text/cache-manifest				appcache
+text/calendar					ics ifb
+text/css					css
+text/csv					csv
+# text/directory
+# text/dns
+# text/ecmascript
+# text/enriched
+# text/example
+# text/fwdred
+text/html					html htm
+# text/javascript
+text/n3						n3
+# text/parityfec
+text/plain					txt text conf def list log in
+# text/prs.fallenstein.rst
+text/prs.lines.tag				dsc
+# text/vnd.radisys.msml-basic-layout
+# text/red
+# text/rfc822-headers
+text/richtext					rtx
+# text/rtf
+# text/rtp-enc-aescm128
+# text/rtx
+text/sgml					sgml sgm
+# text/t140
+text/tab-separated-values			tsv
+text/troff					t tr roff man me ms
+text/turtle					ttl
+# text/ulpfec
+text/uri-list					uri uris urls
+text/vcard					vcard
+# 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.dvb.subtitle				sub
+# 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-java-source				java
+text/x-opml					opml
+text/x-pascal					p pas
+text/x-nfo					nfo
+text/x-setext					etx
+text/x-sfv					sfv
+text/x-uuencode					uu
+text/x-vcalendar				vcs
+text/x-vcard					vcf
+# text/xml
+# text/xml-external-parsed-entity
+# video/1d-interleaved-parityfec
+video/3gpp					3gp
+# video/3gpp-tt
+video/3gpp2					3g2
+# video/bmpeg
+# video/bt656
+# video/celb
+# video/dv
+# video/example
+video/h261					h261
+video/h263					h263
+# video/h263-1998
+# video/h263-2000
+video/h264					h264
+# video/h264-rcdo
+# video/h264-svc
+video/jpeg					jpgv
+# video/jpeg2000
+video/jpm					jpm jpgm
+video/mj2					mj2 mjp2
+# video/mp1s
+# video/mp2p
+# video/mp2t
+video/mp4					mp4 mp4v mpg4
+# video/mp4v-es
+video/mpeg					mpeg mpg mpe m1v m2v
+# video/mpeg4-generic
+# video/mpv
+# video/nv
+video/ogg					ogv
+# video/parityfec
+# video/pointer
+video/quicktime					qt mov
+# video/raw
+# video/rtp-enc-aescm128
+# video/rtx
+# video/smpte292m
+# video/ulpfec
+# video/vc1
+# video/vnd.cctv
+video/vnd.dece.hd				uvh uvvh
+video/vnd.dece.mobile				uvm uvvm
+# video/vnd.dece.mp4
+video/vnd.dece.pd				uvp uvvp
+video/vnd.dece.sd				uvs uvvs
+video/vnd.dece.video				uvv uvvv
+# video/vnd.directv.mpeg
+# video/vnd.directv.mpeg-tts
+# video/vnd.dlna.mpeg-tts
+video/vnd.dvb.file				dvb
+video/vnd.fvt					fvt
+# video/vnd.hns.video
+# video/vnd.iptvforum.1dparityfec-1010
+# video/vnd.iptvforum.1dparityfec-2005
+# video/vnd.iptvforum.2dparityfec-1010
+# video/vnd.iptvforum.2dparityfec-2005
+# video/vnd.iptvforum.ttsavc
+# video/vnd.iptvforum.ttsmpeg2
+# video/vnd.motorola.video
+# video/vnd.motorola.videop
+video/vnd.mpegurl				mxu m4u
+video/vnd.ms-playready.media.pyv		pyv
+# video/vnd.nokia.interleaved-multimedia
+# video/vnd.nokia.videovoip
+# video/vnd.objectvideo
+# video/vnd.sealed.mpeg1
+# video/vnd.sealed.mpeg4
+# video/vnd.sealed.swf
+# video/vnd.sealedmedia.softseal.mov
+video/vnd.uvvu.mp4				uvu uvvu
+video/vnd.vivo					viv
+video/webm					webm
+video/x-f4v					f4v
+video/x-fli					fli
+video/x-flv					flv
+video/x-m4v					m4v
+video/x-matroska				mkv mk3d mks
+video/x-mng					mng
+video/x-ms-asf					asf asx
+video/x-ms-vob					vob
+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
+video/x-smv					smv
+x-conference/x-cooltalk				ice
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/types/node.types
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/types/node.types	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/node_modules/mime/types/node.types	(revision 484)
@@ -0,0 +1,60 @@
+# What: WebVTT
+# Why: To allow formats intended for marking up external text track resources.
+# http://dev.w3.org/html5/webvtt/
+# Added by: niftylettuce
+text/vtt  vtt
+
+# What: Google Chrome Extension
+# Why: To allow apps to (work) be served with the right content type header.
+# http://codereview.chromium.org/2830017
+# Added by: niftylettuce
+application/x-chrome-extension  crx
+
+# What: HTC support
+# Why: To properly render .htc files such as CSS3PIE
+# Added by: niftylettuce
+text/x-component  htc
+
+# What: HTML5 application cache manifest
+# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
+# per https://developer.mozilla.org/en/offline_resources_in_firefox
+# Added by: louisremi
+text/cache-manifest  appcache manifest
+
+# What: node binary buffer format
+# Why: semi-standard extension w/in the node community
+# Added by: tootallnate
+application/octet-stream  buffer
+
+# What: The "protected" MP-4 formats used by iTunes.
+# Why: Required for streaming music to browsers (?)
+# Added by: broofa
+application/mp4  m4p
+audio/mp4  m4a
+
+# What: Video format, Part of RFC1890
+# Why: See https://github.com/bentomas/node-mime/pull/6
+# Added by: mjrusso
+video/MP2T  ts
+
+# What: EventSource mime type
+# Why: mime type of Server-Sent Events stream
+# http://www.w3.org/TR/eventsource/#text-event-stream
+# Added by: francois2metz
+text/event-stream  event-stream
+
+# What: Mozilla App manifest mime type
+# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests
+# Added by: ednapiranha
+application/x-web-app-manifest+json   webapp
+
+# What: Lua file types
+# Why: Googling around shows de-facto consensus on these
+# Added by: creationix (Issue #45)
+text/x-lua  lua
+application/x-lua-bytecode  luac
+
+# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax
+# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown
+# Added by: avoidwork
+text/x-markdown  markdown md mkd
Index: Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/node_modules/send/package.json	(revision 484)
@@ -0,0 +1,41 @@
+{
+  "name": "send",
+  "version": "0.1.1",
+  "description": "Better streaming static file server with Range and conditional-GET support",
+  "keywords": [
+    "static",
+    "file",
+    "server"
+  ],
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca"
+  },
+  "dependencies": {
+    "debug": "*",
+    "mime": "~1.2.9",
+    "fresh": "0.1.0",
+    "range-parser": "0.0.4"
+  },
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*",
+    "supertest": "0.0.1",
+    "connect": "2.x"
+  },
+  "scripts": {
+    "test": "make test"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/send.git"
+  },
+  "main": "index",
+  "readme": "# send\n\n  Send is Connect's `static()` extracted for generalized use, a streaming static file\n  server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.\n\n## Installation\n\n    $ npm install send\n\n## Examples\n\n  Small:\n\n```js\nvar http = require('http');\nvar send = require('send');\n\nvar app = http.createServer(function(req, res){\n  send(req, req.url).pipe(res);\n}).listen(3000);\n```\n\n  Serving from a root directory with custom error-handling:\n\n```js\nvar http = require('http');\nvar send = require('send');\nvar url = require('url');\n\nvar app = http.createServer(function(req, res){\n  // your custom error-handling logic:\n  function error(err) {\n    res.statusCode = err.status || 500;\n    res.end(err.message);\n  }\n\n  // your custom directory handling logic:\n  function redirect() {\n    res.statusCode = 301;\n    res.setHeader('Location', req.url + '/');\n    res.end('Redirecting to ' + req.url + '/');\n  }\n\n  // transfer arbitrary files from within\n  // /www/example.com/public/*\n  send(req, url.parse(req.url).pathname)\n  .root('/www/example.com/public')\n  .on('error', error)\n  .on('directory', redirect)\n  .pipe(res);\n}).listen(3000);\n```\n\n## API\n\n### Events\n\n  - `error` an error occurred `(err)`\n  - `directory` a directory was requested\n  - `file` a file was requested `(path, stat)`\n  - `stream` file streaming has started `(stream)`\n  - `end` streaming has completed\n\n### .root(dir)\n\n  Serve files relative to `path`. Aliased as `.from(dir)`.\n\n### .index(path)\n\n  By default send supports \"index.html\" files, to disable this\n  invoke `.index(false)` or to supply a new index pass a string.\n\n### .maxage(ms)\n\n  Provide a max-age in milliseconds for http caching, defaults to 0.\n\n### .hidden(bool)\n\n  Enable or disable transfer of hidden files, defaults to false.\n\n## Error-handling\n\n  By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.\n\n## Caching\n\n  It does _not_ perform internal caching, you should use a reverse proxy cache such\n  as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).\n\n## Debugging\n\n To enable `debug()` instrumentation output export __DEBUG__:\n\n```\n$ DEBUG=send node app\n```\n\n## Running tests\n\n```\n$ npm install\n$ make test\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/visionmedia/send/issues"
+  },
+  "_id": "send@0.1.1",
+  "_from": "send@0.1.1"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/package.json	(revision 484)
@@ -0,0 +1,53 @@
+{
+  "name": "connect",
+  "version": "2.7.11",
+  "description": "High performance middleware framework",
+  "keywords": [
+    "framework",
+    "web",
+    "middleware",
+    "connect",
+    "rack"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/senchalabs/connect.git"
+  },
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca",
+    "url": "http://tjholowaychuk.com"
+  },
+  "dependencies": {
+    "qs": "0.6.5",
+    "formidable": "1.0.14",
+    "cookie-signature": "1.0.1",
+    "buffer-crc32": "0.2.1",
+    "cookie": "0.0.5",
+    "send": "0.1.1",
+    "bytes": "0.2.0",
+    "fresh": "0.1.0",
+    "pause": "0.0.1",
+    "debug": "*"
+  },
+  "devDependencies": {
+    "should": "*",
+    "mocha": "*",
+    "jade": "*",
+    "dox": "*"
+  },
+  "main": "index",
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "test": "make"
+  },
+  "readme": "[![build status](https://secure.travis-ci.org/senchalabs/connect.png)](http://travis-ci.org/senchalabs/connect)\n# Connect\n\n  Connect is an extensible HTTP server framework for [node](http://nodejs.org), providing high performance \"plugins\" known as _middleware_.\n\n Connect is bundled with over _20_ commonly used middleware, including\n a logger, session support, cookie parser, and [more](http://senchalabs.github.com/connect). Be sure to view the 2.x [documentation](http://senchalabs.github.com/connect/).\n\n```js\nvar connect = require('connect')\n  , http = require('http');\n\nvar app = connect()\n  .use(connect.favicon())\n  .use(connect.logger('dev'))\n  .use(connect.static('public'))\n  .use(connect.directory('public'))\n  .use(connect.cookieParser())\n  .use(connect.session({ secret: 'my secret here' }))\n  .use(function(req, res){\n    res.end('Hello from Connect!\\n');\n  });\n\nhttp.createServer(app).listen(3000);\n```\n\n## Middleware\n\n  - [csrf](http://www.senchalabs.org/connect/csrf.html)\n  - [basicAuth](http://www.senchalabs.org/connect/basicAuth.html)\n  - [bodyParser](http://www.senchalabs.org/connect/bodyParser.html)\n  - [json](http://www.senchalabs.org/connect/json.html)\n  - [multipart](http://www.senchalabs.org/connect/multipart.html)\n  - [urlencoded](http://www.senchalabs.org/connect/urlencoded.html)\n  - [cookieParser](http://www.senchalabs.org/connect/cookieParser.html)\n  - [directory](http://www.senchalabs.org/connect/directory.html)\n  - [compress](http://www.senchalabs.org/connect/compress.html)\n  - [errorHandler](http://www.senchalabs.org/connect/errorHandler.html)\n  - [favicon](http://www.senchalabs.org/connect/favicon.html)\n  - [limit](http://www.senchalabs.org/connect/limit.html)\n  - [logger](http://www.senchalabs.org/connect/logger.html)\n  - [methodOverride](http://www.senchalabs.org/connect/methodOverride.html)\n  - [query](http://www.senchalabs.org/connect/query.html)\n  - [responseTime](http://www.senchalabs.org/connect/responseTime.html)\n  - [session](http://www.senchalabs.org/connect/session.html)\n  - [static](http://www.senchalabs.org/connect/static.html)\n  - [staticCache](http://www.senchalabs.org/connect/staticCache.html)\n  - [vhost](http://www.senchalabs.org/connect/vhost.html)\n  - [subdomains](http://www.senchalabs.org/connect/subdomains.html)\n  - [cookieSession](http://www.senchalabs.org/connect/cookieSession.html)\n\n## Running Tests\n\nfirst:\n\n    $ npm install -d\n\nthen:\n\n    $ make test\n\n## Authors\n\n Below is the output from [git-summary](http://github.com/visionmedia/git-extras).\n\n\n     project: connect\n     commits: 2033\n     active : 301 days\n     files  : 171\n     authors: \n      1414\tTj Holowaychuk          69.6%\n       298\tvisionmedia             14.7%\n       191\tTim Caswell             9.4%\n        51\tTJ Holowaychuk          2.5%\n        10\tRyan Olds               0.5%\n         8\tAstro                   0.4%\n         5\tNathan Rajlich          0.2%\n         5\tJakub NeÅ¡etÅil          0.2%\n         3\tDaniel Dickison         0.1%\n         3\tDavid Rio Deiros        0.1%\n         3\tAlexander Simmerl       0.1%\n         3\tAndreas Lind Petersen   0.1%\n         2\tAaron Heckmann          0.1%\n         2\tJacques Crocker         0.1%\n         2\tFabian Jakobs           0.1%\n         2\tBrian J Brennan         0.1%\n         2\tAdam Malcontenti-Wilson 0.1%\n         2\tGlen Mailer             0.1%\n         2\tJames Campos            0.1%\n         1\tTrent Mick              0.0%\n         1\tTroy Kruthoff           0.0%\n         1\tWei Zhu                 0.0%\n         1\tcomerc                  0.0%\n         1\tdarobin                 0.0%\n         1\tnateps                  0.0%\n         1\tMarco Sanson            0.0%\n         1\tArthur Taylor           0.0%\n         1\tAseem Kishore           0.0%\n         1\tBart Teeuwisse          0.0%\n         1\tCameron Howey           0.0%\n         1\tChad Weider             0.0%\n         1\tCraig Barnes            0.0%\n         1\tEran Hammer-Lahav       0.0%\n         1\tGregory McWhirter       0.0%\n         1\tGuillermo Rauch         0.0%\n         1\tJae Kwon                0.0%\n         1\tJakub Nesetril          0.0%\n         1\tJoshua Peek             0.0%\n         1\tJxck                    0.0%\n         1\tAJ ONeal                0.0%\n         1\tMichael Hemesath        0.0%\n         1\tMorten Siebuhr          0.0%\n         1\tSamori Gorse            0.0%\n         1\tTom Jensen              0.0%\n\n## Node Compatibility\n\n  Connect `< 1.x` is compatible with node 0.2.x\n\n\n  Connect `1.x` is compatible with node 0.4.x\n\n\n  Connect (_master_) `2.x` is compatible with node 0.6.x\n\n## CLA\n\n [http://sencha.com/cla](http://sencha.com/cla)\n\n## License\n\nView the [LICENSE](https://github.com/senchalabs/connect/blob/master/LICENSE) file. The [Silk](http://www.famfamfam.com/lab/icons/silk/) icons used by the `directory` middleware created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/).\n",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/senchalabs/connect/issues"
+  },
+  "_id": "connect@2.7.11",
+  "_from": "connect@2.7.11"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/connect/test.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/connect/test.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/connect/test.js	(revision 484)
@@ -0,0 +1,40 @@
+
+var connect = require('./');
+var app = connect();
+
+app.use(connect.logger('dev'));
+app.use(connect.bodyParser());
+
+app.use(function(req, res, next){
+  if (req.checkContinue) {
+    res.writeContinue();
+  }
+  res.end('hello');
+});
+
+var server = app.listen(3000);
+
+server.on('checkContinue', function(req, res){
+  req.checkContinue = true;
+  app(req, res);
+});
+
+
+// var http = require('http');
+
+// var app = http.createServer(function(req, res){
+//   console.log(req.headers);
+// });
+
+// app.on('checkContinue', function(req, res){
+//   if ('application/json' == req.headers['content-type']) {
+//     res.writeContinue();
+//     console.log('ok');
+//     res.end('thanks')
+//   } else {
+//     res.writeHead(400);
+//     res.end('bad request, json only');
+//   }
+// });
+
+// app.listen(3000);
Index: Dev/trunk/src/node_modules/express/node_modules/cookie-signature/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie-signature/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie-signature/.npmignore	(revision 484)
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
Index: Dev/trunk/src/node_modules/express/node_modules/cookie-signature/History.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie-signature/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie-signature/History.md	(revision 484)
@@ -0,0 +1,11 @@
+
+1.0.1 / 2013-04-15 
+==================
+
+  * Revert "Changed underlying HMAC algo. to sha512."
+  * Revert "Fix for timing attacks on MAC verification."
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
Index: Dev/trunk/src/node_modules/express/node_modules/cookie-signature/Makefile
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie-signature/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie-signature/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--require should \
+		--reporter spec
+
+.PHONY: test
Index: Dev/trunk/src/node_modules/express/node_modules/cookie-signature/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie-signature/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie-signature/Readme.md	(revision 484)
@@ -0,0 +1,42 @@
+
+# cookie-signature
+
+  Sign and unsign cookies.
+
+## Example
+
+```js
+var cookie = require('cookie-signature');
+
+var val = cookie.sign('hello', 'tobiiscool');
+val.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI');
+
+var val = cookie.sign('hello', 'tobiiscool');
+cookie.unsign(val, 'tobiiscool').should.equal('hello');
+cookie.unsign(val, 'luna').should.be.false;
+```
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2012 LearnBoost &lt;tj@learnboost.com&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.
Index: Dev/trunk/src/node_modules/express/node_modules/cookie-signature/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie-signature/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie-signature/index.js	(revision 484)
@@ -0,0 +1,42 @@
+
+/**
+ * Module dependencies.
+ */
+
+var crypto = require('crypto');
+
+/**
+ * Sign the given `val` with `secret`.
+ *
+ * @param {String} val
+ * @param {String} secret
+ * @return {String}
+ * @api private
+ */
+
+exports.sign = function(val, secret){
+  if ('string' != typeof val) throw new TypeError('cookie required');
+  if ('string' != typeof secret) throw new TypeError('secret required');
+  return val + '.' + crypto
+    .createHmac('sha256', secret)
+    .update(val)
+    .digest('base64')
+    .replace(/\=+$/, '');
+};
+
+/**
+ * Unsign and decode the given `val` with `secret`,
+ * returning `false` if the signature is invalid.
+ *
+ * @param {String} val
+ * @param {String} secret
+ * @return {String|Boolean}
+ * @api private
+ */
+
+exports.unsign = function(val, secret){
+  if ('string' != typeof val) throw new TypeError('cookie required');
+  if ('string' != typeof secret) throw new TypeError('secret required');
+  var str = val.slice(0, val.lastIndexOf('.'));
+  return exports.sign(str, secret) == val ? str : false;
+};
Index: Dev/trunk/src/node_modules/express/node_modules/cookie-signature/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie-signature/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie-signature/package.json	(revision 484)
@@ -0,0 +1,24 @@
+{
+  "name": "cookie-signature",
+  "version": "1.0.1",
+  "description": "Sign and unsign cookies",
+  "keywords": [
+    "cookie",
+    "sign",
+    "unsign"
+  ],
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@learnboost.com"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "main": "index",
+  "readme": "\n# cookie-signature\n\n  Sign and unsign cookies.\n\n## Example\n\n```js\nvar cookie = require('cookie-signature');\n\nvar val = cookie.sign('hello', 'tobiiscool');\nval.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI');\n\nvar val = cookie.sign('hello', 'tobiiscool');\ncookie.unsign(val, 'tobiiscool').should.equal('hello');\ncookie.unsign(val, 'luna').should.be.false;\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 LearnBoost &lt;tj@learnboost.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
+  "readmeFilename": "Readme.md",
+  "_id": "cookie-signature@1.0.1",
+  "_from": "cookie-signature@1.0.1"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/cookie/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie/.npmignore	(revision 484)
@@ -0,0 +1,1 @@
+node_modules
Index: Dev/trunk/src/node_modules/express/node_modules/cookie/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+    - "0.6"
+    - "0.8"
+    - "0.10"
Index: Dev/trunk/src/node_modules/express/node_modules/cookie/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie/LICENSE	(revision 484)
@@ -0,0 +1,9 @@
+// MIT License
+
+Copyright (C) Roman Shtylman <shtylman@gmail.com>
+
+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.
Index: Dev/trunk/src/node_modules/express/node_modules/cookie/README.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie/README.md	(revision 484)
@@ -0,0 +1,44 @@
+# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) #
+
+cookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers.
+
+See [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies.
+
+## how?
+
+```
+npm install cookie
+```
+
+```javascript
+var cookie = require('cookie');
+
+var hdr = cookie.serialize('foo', 'bar');
+// hdr = 'foo=bar';
+
+var cookies = cookie.parse('foo=bar; cat=meow; dog=ruff');
+// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' };
+```
+
+## more
+
+The serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values.
+
+### path
+> cookie path
+
+### expires
+> absolute expiration date for the cookie (Date object)
+
+### maxAge
+> relative max age of the cookie from when the client receives it (seconds)
+
+### domain
+> domain for the cookie
+
+### secure
+> true or false
+
+### httpOnly
+> true or false
+
Index: Dev/trunk/src/node_modules/express/node_modules/cookie/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie/index.js	(revision 484)
@@ -0,0 +1,70 @@
+
+/// Serialize the a name value pair into a cookie string suitable for
+/// http headers. An optional options object specified cookie parameters
+///
+/// serialize('foo', 'bar', { httpOnly: true })
+///   => "foo=bar; httpOnly"
+///
+/// @param {String} name
+/// @param {String} val
+/// @param {Object} options
+/// @return {String}
+var serialize = function(name, val, opt){
+    opt = opt || {};
+    var enc = opt.encode || encode;
+    var pairs = [name + '=' + enc(val)];
+
+    if (opt.maxAge) pairs.push('Max-Age=' + opt.maxAge);
+    if (opt.domain) pairs.push('Domain=' + opt.domain);
+    if (opt.path) pairs.push('Path=' + opt.path);
+    if (opt.expires) pairs.push('Expires=' + opt.expires.toUTCString());
+    if (opt.httpOnly) pairs.push('HttpOnly');
+    if (opt.secure) pairs.push('Secure');
+
+    return pairs.join('; ');
+};
+
+/// Parse the given cookie header string into an object
+/// The object has the various cookies as keys(names) => values
+/// @param {String} str
+/// @return {Object}
+var parse = function(str, opt) {
+    opt = opt || {};
+    var obj = {}
+    var pairs = str.split(/[;,] */);
+    var dec = opt.decode || decode;
+
+    pairs.forEach(function(pair) {
+        var eq_idx = pair.indexOf('=')
+
+        // skip things that don't look like key=value
+        if (eq_idx < 0) {
+            return;
+        }
+
+        var key = pair.substr(0, eq_idx).trim()
+        var val = pair.substr(++eq_idx, pair.length).trim();
+
+        // quoted values
+        if ('"' == val[0]) {
+            val = val.slice(1, -1);
+        }
+
+        // only assign once
+        if (undefined == obj[key]) {
+            try {
+                obj[key] = dec(val);
+            } catch (e) {
+                obj[key] = val;
+            }
+        }
+    });
+
+    return obj;
+};
+
+var encode = encodeURIComponent;
+var decode = decodeURIComponent;
+
+module.exports.serialize = serialize;
+module.exports.parse = parse;
Index: Dev/trunk/src/node_modules/express/node_modules/cookie/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie/package.json	(revision 484)
@@ -0,0 +1,36 @@
+{
+  "author": {
+    "name": "Roman Shtylman",
+    "email": "shtylman@gmail.com"
+  },
+  "name": "cookie",
+  "description": "cookie parsing and serialization",
+  "version": "0.1.0",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/shtylman/node-cookie.git"
+  },
+  "keywords": [
+    "cookie",
+    "cookies"
+  ],
+  "main": "index.js",
+  "scripts": {
+    "test": "mocha"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "1.x.x"
+  },
+  "optionalDependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "readme": "# cookie [![Build Status](https://secure.travis-ci.org/shtylman/node-cookie.png?branch=master)](http://travis-ci.org/shtylman/node-cookie) #\n\ncookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers.\n\nSee [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies.\n\n## how?\n\n```\nnpm install cookie\n```\n\n```javascript\nvar cookie = require('cookie');\n\nvar hdr = cookie.serialize('foo', 'bar');\n// hdr = 'foo=bar';\n\nvar cookies = cookie.parse('foo=bar; cat=meow; dog=ruff');\n// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' };\n```\n\n## more\n\nThe serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values.\n\n### path\n> cookie path\n\n### expires\n> absolute expiration date for the cookie (Date object)\n\n### maxAge\n> relative max age of the cookie from when the client receives it (seconds)\n\n### domain\n> domain for the cookie\n\n### secure\n> true or false\n\n### httpOnly\n> true or false\n\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/shtylman/node-cookie/issues"
+  },
+  "_id": "cookie@0.1.0",
+  "_from": "cookie@0.1.0"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/cookie/test/mocha.opts
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie/test/mocha.opts	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie/test/mocha.opts	(revision 484)
@@ -0,0 +1,1 @@
+--ui qunit
Index: Dev/trunk/src/node_modules/express/node_modules/cookie/test/parse.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie/test/parse.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie/test/parse.js	(revision 484)
@@ -0,0 +1,44 @@
+
+var assert = require('assert');
+
+var cookie = require('..');
+
+suite('parse');
+
+test('basic', function() {
+    assert.deepEqual({ foo: 'bar' }, cookie.parse('foo=bar'));
+    assert.deepEqual({ foo: '123' }, cookie.parse('foo=123'));
+});
+
+test('ignore spaces', function() {
+    assert.deepEqual({ FOO: 'bar', baz: 'raz' },
+            cookie.parse('FOO    = bar;   baz  =   raz'));
+});
+
+test('escaping', function() {
+    assert.deepEqual({ foo: 'bar=123456789&name=Magic+Mouse' },
+            cookie.parse('foo="bar=123456789&name=Magic+Mouse"'));
+
+    assert.deepEqual({ email: ' ",;/' },
+            cookie.parse('email=%20%22%2c%3b%2f'));
+});
+
+test('ignore escaping error and return original value', function() {
+    assert.deepEqual({ foo: '%1', bar: 'bar' }, cookie.parse('foo=%1;bar=bar'));
+});
+
+test('ignore non values', function() {
+    assert.deepEqual({ foo: '%1', bar: 'bar' }, cookie.parse('foo=%1;bar=bar;HttpOnly;Secure'));
+});
+
+test('unencoded', function() {
+    assert.deepEqual({ foo: 'bar=123456789&name=Magic+Mouse' },
+            cookie.parse('foo="bar=123456789&name=Magic+Mouse"',{
+                decode: function(value) { return value; }
+            }));
+
+    assert.deepEqual({ email: '%20%22%2c%3b%2f' },
+            cookie.parse('email=%20%22%2c%3b%2f',{
+                decode: function(value) { return value; }
+            }));
+})
Index: Dev/trunk/src/node_modules/express/node_modules/cookie/test/serialize.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/cookie/test/serialize.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/cookie/test/serialize.js	(revision 484)
@@ -0,0 +1,64 @@
+// builtin
+var assert = require('assert');
+
+var cookie = require('..');
+
+suite('serialize');
+
+test('basic', function() {
+    assert.equal('foo=bar', cookie.serialize('foo', 'bar'));
+    assert.equal('foo=bar%20baz', cookie.serialize('foo', 'bar baz'));
+});
+
+test('path', function() {
+    assert.equal('foo=bar; Path=/', cookie.serialize('foo', 'bar', {
+        path: '/'
+    }));
+});
+
+test('secure', function() {
+    assert.equal('foo=bar; Secure', cookie.serialize('foo', 'bar', {
+        secure: true
+    }));
+
+    assert.equal('foo=bar', cookie.serialize('foo', 'bar', {
+        secure: false
+    }));
+});
+
+test('domain', function() {
+    assert.equal('foo=bar; Domain=example.com', cookie.serialize('foo', 'bar', {
+        domain: 'example.com'
+    }));
+});
+
+test('httpOnly', function() {
+    assert.equal('foo=bar; HttpOnly', cookie.serialize('foo', 'bar', {
+        httpOnly: true
+    }));
+});
+
+test('maxAge', function() {
+    assert.equal('foo=bar; Max-Age=1000', cookie.serialize('foo', 'bar', {
+        maxAge: 1000
+    }));
+});
+
+test('escaping', function() {
+    assert.deepEqual('cat=%2B%20', cookie.serialize('cat', '+ '));
+});
+
+test('parse->serialize', function() {
+
+    assert.deepEqual({ cat: 'foo=123&name=baz five' }, cookie.parse(
+      cookie.serialize('cat', 'foo=123&name=baz five')));
+
+    assert.deepEqual({ cat: ' ";/' }, cookie.parse(
+      cookie.serialize('cat', ' ";/')));
+});
+
+test('unencoded', function() {
+    assert.deepEqual('cat=+ ', cookie.serialize('cat', '+ ', {
+        encode: function(value) { return value; }
+    }));
+})
Index: Dev/trunk/src/node_modules/express/node_modules/debug/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/.npmignore	(revision 484)
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
Index: Dev/trunk/src/node_modules/express/node_modules/debug/History.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/History.md	(revision 484)
@@ -0,0 +1,62 @@
+
+0.7.2 / 2013-02-06 
+==================
+
+  * fix package.json
+  * fix: Mobile Safari (private mode) is broken with debug
+  * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05 
+==================
+
+  * add repository URL to package.json
+  * add DEBUG_COLORED to force colored output
+  * add browserify support
+  * fix component. Closes #24
+
+0.7.0 / 2012-05-04 
+==================
+
+  * Added .component to package.json
+  * Added debug.component.js build
+
+0.6.0 / 2012-03-16 
+==================
+
+  * Added support for "-" prefix in DEBUG [Vinay Pulim]
+  * Added `.enabled` flag to the node version [TooTallNate] 
+
+0.5.0 / 2012-02-02 
+==================
+
+  * Added: humanize diffs. Closes #8
+  * Added `debug.disable()` to the CS variant
+  * Removed padding. Closes #10
+  * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01 
+==================
+
+  * Added browser variant support for older browsers [TooTallNate]
+  * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+  * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26 
+==================
+
+  * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22 
+==================
+
+  * Added wildcard support
+
+0.1.0 / 2011-12-02 
+==================
+
+  * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
Index: Dev/trunk/src/node_modules/express/node_modules/debug/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/Readme.md	(revision 484)
@@ -0,0 +1,115 @@
+
+# debug
+
+  tiny node.js debugging utility modelled after node core's debugging technique.
+
+## Installation
+
+```
+$ npm install debug
+```
+
+## Usage
+
+ With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.
+ 
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+  debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
+
+  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
+
+## Millisecond diff
+
+  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
+
+  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+  
+  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
+
+## Conventions
+
+ If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". 
+
+## Wildcards
+
+  The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+  You can also exclude specific debuggers by prefixing them with a "-" character.  For example, `DEBUG=* -connect:*` would include all debuggers except those starting with "connect:".
+
+## Browser support
+
+ Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. 
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+  a('doing some work');
+}, 1000);
+
+setInterval(function(){
+  a('doing some work');
+}, 1200);
+```
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 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.
Index: Dev/trunk/src/node_modules/express/node_modules/debug/component.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/component.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/component.json	(revision 484)
@@ -0,0 +1,9 @@
+{
+  "name": "debug",
+  "repo": "visionmedia/debug",
+  "description": "small debugging utility",
+  "version": "0.7.2",
+  "keywords": ["debug", "log", "debugger"],
+  "scripts": ["index.js", "debug.js"],
+  "dependencies": {}
+}
Index: Dev/trunk/src/node_modules/express/node_modules/debug/debug.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/debug.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/debug.js	(revision 484)
@@ -0,0 +1,124 @@
+
+/**
+ * Expose `debug()` as the module.
+ */
+
+module.exports = debug;
+
+/**
+ * Create a debugger with the given `name`.
+ *
+ * @param {String} name
+ * @return {Type}
+ * @api public
+ */
+
+function debug(name) {
+  if (!debug.enabled(name)) return function(){};
+
+  return function(fmt){
+    var curr = new Date;
+    var ms = curr - (debug[name] || curr);
+    debug[name] = curr;
+
+    fmt = name
+      + ' '
+      + fmt
+      + ' +' + debug.humanize(ms);
+
+    // This hackery is required for IE8
+    // where `console.log` doesn't have 'apply'
+    window.console
+      && console.log
+      && Function.prototype.apply.call(console.log, console, arguments);
+  }
+}
+
+/**
+ * The currently active debug mode names.
+ */
+
+debug.names = [];
+debug.skips = [];
+
+/**
+ * Enables a debug mode by name. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} name
+ * @api public
+ */
+
+debug.enable = function(name) {
+  try {
+    localStorage.debug = name;
+  } catch(e){}
+
+  var split = (name || '').split(/[\s,]+/)
+    , len = split.length;
+
+  for (var i = 0; i < len; i++) {
+    name = split[i].replace('*', '.*?');
+    if (name[0] === '-') {
+      debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
+    }
+    else {
+      debug.names.push(new RegExp('^' + name + '$'));
+    }
+  }
+};
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+debug.disable = function(){
+  debug.enable('');
+};
+
+/**
+ * Humanize the given `ms`.
+ *
+ * @param {Number} m
+ * @return {String}
+ * @api private
+ */
+
+debug.humanize = function(ms) {
+  var sec = 1000
+    , min = 60 * 1000
+    , hour = 60 * min;
+
+  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
+  if (ms >= min) return (ms / min).toFixed(1) + 'm';
+  if (ms >= sec) return (ms / sec | 0) + 's';
+  return ms + 'ms';
+};
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+debug.enabled = function(name) {
+  for (var i = 0, len = debug.skips.length; i < len; i++) {
+    if (debug.skips[i].test(name)) {
+      return false;
+    }
+  }
+  for (var i = 0, len = debug.names.length; i < len; i++) {
+    if (debug.names[i].test(name)) {
+      return true;
+    }
+  }
+  return false;
+};
+
+// persist
+
+if (window.localStorage) debug.enable(localStorage.debug);
Index: Dev/trunk/src/node_modules/express/node_modules/debug/example/app.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/example/app.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/example/app.js	(revision 484)
@@ -0,0 +1,19 @@
+
+var debug = require('../')('http')
+  , http = require('http')
+  , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+  debug(req.method + ' ' + req.url);
+  res.end('hello\n');
+}).listen(3000, function(){
+  debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
Index: Dev/trunk/src/node_modules/express/node_modules/debug/example/browser.html
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/example/browser.html	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/example/browser.html	(revision 484)
@@ -0,0 +1,24 @@
+<html>
+  <head>
+    <title>debug()</title>
+    <script src="../debug.js"></script>
+    <script>
+      // type debug.enable('*') in
+      // the console and refresh :)
+
+      a = debug('worker:a');
+      b = debug('worker:b');
+
+      setInterval(function(){
+        a('doing some work');
+      }, 1000);
+
+      setInterval(function(){
+        a('doing some work');
+      }, 1200);
+    </script>
+  </head>
+  <body>
+    
+  </body>
+</html>
Index: Dev/trunk/src/node_modules/express/node_modules/debug/example/wildcards.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/example/wildcards.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/example/wildcards.js	(revision 484)
@@ -0,0 +1,10 @@
+
+var debug = {
+  foo: require('../')('test:foo'),
+  bar: require('../')('test:bar'),
+  baz: require('../')('test:baz')
+};
+
+debug.foo('foo')
+debug.bar('bar')
+debug.baz('baz')
Index: Dev/trunk/src/node_modules/express/node_modules/debug/example/worker.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/example/worker.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/example/worker.js	(revision 484)
@@ -0,0 +1,22 @@
+
+// DEBUG=* node example/worker
+// DEBUG=worker:* node example/worker
+// DEBUG=worker:a node example/worker
+// DEBUG=worker:b node example/worker
+
+var a = require('../')('worker:a')
+  , b = require('../')('worker:b');
+
+function work() {
+  a('doing lots of uninteresting work');
+  setTimeout(work, Math.random() * 1000);
+}
+
+work();
+
+function workb() {
+  b('doing some work');
+  setTimeout(workb, Math.random() * 2000);
+}
+
+workb();
Index: Dev/trunk/src/node_modules/express/node_modules/debug/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/index.js	(revision 484)
@@ -0,0 +1,5 @@
+if ('undefined' == typeof window) {
+  module.exports = require('./lib/debug');
+} else {
+  module.exports = require('./debug');
+}
Index: Dev/trunk/src/node_modules/express/node_modules/debug/lib/debug.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/lib/debug.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/lib/debug.js	(revision 484)
@@ -0,0 +1,134 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+
+/**
+ * Expose `debug()` as the module.
+ */
+
+module.exports = debug;
+
+/**
+ * Enabled debuggers.
+ */
+
+var names = []
+  , skips = [];
+
+(process.env.DEBUG || '')
+  .split(/[\s,]+/)
+  .forEach(function(name){
+    name = name.replace('*', '.*?');
+    if (name[0] === '-') {
+      skips.push(new RegExp('^' + name.substr(1) + '$'));
+    } else {
+      names.push(new RegExp('^' + name + '$'));
+    }
+  });
+
+/**
+ * Colors.
+ */
+
+var colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Previous debug() call.
+ */
+
+var prev = {};
+
+/**
+ * Previously assigned color.
+ */
+
+var prevColor = 0;
+
+/**
+ * Is stdout a TTY? Colored output is disabled when `true`.
+ */
+
+var isatty = tty.isatty(2);
+
+/**
+ * Select a color.
+ *
+ * @return {Number}
+ * @api private
+ */
+
+function color() {
+  return colors[prevColor++ % colors.length];
+}
+
+/**
+ * Humanize the given `ms`.
+ *
+ * @param {Number} m
+ * @return {String}
+ * @api private
+ */
+
+function humanize(ms) {
+  var sec = 1000
+    , min = 60 * 1000
+    , hour = 60 * min;
+
+  if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
+  if (ms >= min) return (ms / min).toFixed(1) + 'm';
+  if (ms >= sec) return (ms / sec | 0) + 's';
+  return ms + 'ms';
+}
+
+/**
+ * Create a debugger with the given `name`.
+ *
+ * @param {String} name
+ * @return {Type}
+ * @api public
+ */
+
+function debug(name) {
+  function disabled(){}
+  disabled.enabled = false;
+
+  var match = skips.some(function(re){
+    return re.test(name);
+  });
+
+  if (match) return disabled;
+
+  match = names.some(function(re){
+    return re.test(name);
+  });
+
+  if (!match) return disabled;
+  var c = color();
+
+  function colored(fmt) {
+    var curr = new Date;
+    var ms = curr - (prev[name] || curr);
+    prev[name] = curr;
+
+    fmt = '  \u001b[9' + c + 'm' + name + ' '
+      + '\u001b[3' + c + 'm\u001b[90m'
+      + fmt + '\u001b[3' + c + 'm'
+      + ' +' + humanize(ms) + '\u001b[0m';
+
+    console.error.apply(this, arguments);
+  }
+
+  function plain(fmt) {
+    fmt = new Date().toUTCString()
+      + ' ' + name + ' ' + fmt;
+    console.error.apply(this, arguments);
+  }
+
+  colored.enabled = plain.enabled = true;
+
+  return isatty || process.env.DEBUG_COLORS
+    ? colored
+    : plain;
+}
Index: Dev/trunk/src/node_modules/express/node_modules/debug/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/debug/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/debug/package.json	(revision 484)
@@ -0,0 +1,41 @@
+{
+  "name": "debug",
+  "version": "0.7.2",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/debug.git"
+  },
+  "description": "small debugging utility",
+  "keywords": [
+    "debug",
+    "log",
+    "debugger"
+  ],
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "*"
+  },
+  "main": "lib/debug.js",
+  "browserify": "debug.js",
+  "engines": {
+    "node": "*"
+  },
+  "component": {
+    "scripts": {
+      "debug/index.js": "index.js",
+      "debug/debug.js": "debug.js"
+    }
+  },
+  "readme": "\n# debug\n\n  tiny node.js debugging utility modelled after node core's debugging technique.\n\n## Installation\n\n```\n$ npm install debug\n```\n\n## Usage\n\n With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.\n \nExample _app.js_:\n\n```js\nvar debug = require('debug')('http')\n  , http = require('http')\n  , name = 'My App';\n\n// fake app\n\ndebug('booting %s', name);\n\nhttp.createServer(function(req, res){\n  debug(req.method + ' ' + req.url);\n  res.end('hello\\n');\n}).listen(3000, function(){\n  debug('listening');\n});\n\n// fake worker of some kind\n\nrequire('./worker');\n```\n\nExample _worker.js_:\n\n```js\nvar debug = require('debug')('worker');\n\nsetInterval(function(){\n  debug('doing some work');\n}, 1000);\n```\n\n The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:\n\n  ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)\n\n  ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)\n\n## Millisecond diff\n\n  When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the \"+NNNms\" will show you how much time was spent between calls.\n\n  ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)\n\n  When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:\n  \n  ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)\n\n## Conventions\n\n If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use \":\" to separate features. For example \"bodyParser\" from Connect would then be \"connect:bodyParser\". \n\n## Wildcards\n\n  The \"*\" character may be used as a wildcard. Suppose for example your library has debuggers named \"connect:bodyParser\", \"connect:compress\", \"connect:session\", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.\n\n  You can also exclude specific debuggers by prefixing them with a \"-\" character.  For example, `DEBUG=* -connect:*` would include all debuggers except those starting with \"connect:\".\n\n## Browser support\n\n Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`. \n\n```js\na = debug('worker:a');\nb = debug('worker:b');\n\nsetInterval(function(){\n  a('doing some work');\n}, 1000);\n\nsetInterval(function(){\n  a('doing some work');\n}, 1200);\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/visionmedia/debug/issues"
+  },
+  "_id": "debug@0.7.2",
+  "_from": "debug@*",
+  "scripts": {}
+}
Index: Dev/trunk/src/node_modules/express/node_modules/fresh/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/fresh/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/fresh/.npmignore	(revision 484)
@@ -0,0 +1,1 @@
+test
Index: Dev/trunk/src/node_modules/express/node_modules/fresh/Makefile
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/fresh/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/fresh/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--reporter spec \
+		--require should
+
+.PHONY: test
Index: Dev/trunk/src/node_modules/express/node_modules/fresh/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/fresh/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/fresh/Readme.md	(revision 484)
@@ -0,0 +1,32 @@
+
+# node-fresh
+
+  HTTP response freshness testing
+
+## fresh(req, res)
+
+ Check freshness of `req` and `res` headers.
+
+ When the cache is "fresh" __true__ is returned,
+ otherwise __false__ is returned to indicate that
+ the cache is now stale.
+
+## Example:
+
+```js
+var req = { 'if-none-match': 'tobi' };
+var res = { 'etag': 'luna' };
+fresh(req, res);
+// => false
+
+var req = { 'if-none-match': 'tobi' };
+var res = { 'etag': 'tobi' };
+fresh(req, res);
+// => true
+```
+
+## Installation
+
+```
+$ npm install fresh
+```
Index: Dev/trunk/src/node_modules/express/node_modules/fresh/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/fresh/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/fresh/index.js	(revision 484)
@@ -0,0 +1,49 @@
+
+/**
+ * Expose `fresh()`.
+ */
+
+module.exports = fresh;
+
+/**
+ * Check freshness of `req` and `res` headers.
+ *
+ * When the cache is "fresh" __true__ is returned,
+ * otherwise __false__ is returned to indicate that
+ * the cache is now stale.
+ *
+ * @param {Object} req
+ * @param {Object} res
+ * @return {Boolean}
+ * @api public
+ */
+
+function fresh(req, res) {
+  // defaults
+  var etagMatches = true;
+  var notModified = true;
+
+  // fields
+  var modifiedSince = req['if-modified-since'];
+  var noneMatch = req['if-none-match'];
+  var lastModified = res['last-modified'];
+  var etag = res['etag'];
+
+  // unconditional request
+  if (!modifiedSince && !noneMatch) return false;
+
+  // parse if-none-match
+  if (noneMatch) noneMatch = noneMatch.split(/ *, */);
+
+  // if-none-match
+  if (noneMatch) etagMatches = ~noneMatch.indexOf(etag) || '*' == noneMatch[0];
+
+  // if-modified-since
+  if (modifiedSince) {
+    modifiedSince = new Date(modifiedSince);
+    lastModified = new Date(lastModified);
+    notModified = lastModified <= modifiedSince;
+  }
+
+  return !! (etagMatches && notModified);
+}
Index: Dev/trunk/src/node_modules/express/node_modules/fresh/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/fresh/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/fresh/package.json	(revision 484)
@@ -0,0 +1,20 @@
+{
+  "name": "fresh",
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca",
+    "url": "http://tjholowaychuk.com"
+  },
+  "description": "HTTP response freshness testing",
+  "version": "0.1.0",
+  "main": "index.js",
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "readme": "\n# node-fresh\n\n  HTTP response freshness testing\n\n## fresh(req, res)\n\n Check freshness of `req` and `res` headers.\n\n When the cache is \"fresh\" __true__ is returned,\n otherwise __false__ is returned to indicate that\n the cache is now stale.\n\n## Example:\n\n```js\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'luna' };\nfresh(req, res);\n// => false\n\nvar req = { 'if-none-match': 'tobi' };\nvar res = { 'etag': 'tobi' };\nfresh(req, res);\n// => true\n```\n\n## Installation\n\n```\n$ npm install fresh\n```",
+  "readmeFilename": "Readme.md",
+  "_id": "fresh@0.1.0",
+  "_from": "fresh@0.1.0"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/methods/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/methods/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/methods/index.js	(revision 484)
@@ -0,0 +1,26 @@
+
+module.exports = [
+    'get'
+  , 'post'
+  , 'put'
+  , 'head'
+  , 'delete'
+  , 'options'
+  , 'trace'
+  , 'copy'
+  , 'lock'
+  , 'mkcol'
+  , 'move'
+  , 'propfind'
+  , 'proppatch'
+  , 'unlock'
+  , 'report'
+  , 'mkactivity'
+  , 'checkout'
+  , 'merge'
+  , 'm-search'
+  , 'notify'
+  , 'subscribe'
+  , 'unsubscribe'
+  , 'patch'
+];
Index: Dev/trunk/src/node_modules/express/node_modules/methods/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/methods/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/methods/package.json	(revision 484)
@@ -0,0 +1,20 @@
+{
+  "name": "methods",
+  "version": "0.0.1",
+  "description": "HTTP methods that node supports",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "keywords": [
+    "http",
+    "methods"
+  ],
+  "author": {
+    "name": "TJ Holowaychuk"
+  },
+  "license": "MIT",
+  "readme": "ERROR: No README data found!",
+  "_id": "methods@0.0.1",
+  "_from": "methods@0.0.1"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/.npmignore	(revision 484)
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/.travis.yml	(revision 484)
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - 0.4
+  - 0.6
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/LICENSE	(revision 484)
@@ -0,0 +1,21 @@
+Copyright 2010 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT/X11 license:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/README.markdown
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/README.markdown	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/README.markdown	(revision 484)
@@ -0,0 +1,61 @@
+mkdirp
+======
+
+Like `mkdir -p`, but in node.js!
+
+[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
+
+example
+=======
+
+pow.js
+------
+    var mkdirp = require('mkdirp');
+    
+    mkdirp('/tmp/foo/bar/baz', function (err) {
+        if (err) console.error(err)
+        else console.log('pow!')
+    });
+
+Output
+    pow!
+
+And now /tmp/foo/bar/baz exists, huzzah!
+
+methods
+=======
+
+var mkdirp = require('mkdirp');
+
+mkdirp(dir, mode, cb)
+---------------------
+
+Create a new directory and any necessary subdirectories at `dir` with octal
+permission string `mode`.
+
+If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
+
+`cb(err, made)` fires with the error or the first directory `made`
+that had to be created, if any.
+
+mkdirp.sync(dir, mode)
+----------------------
+
+Synchronously create a new directory and any necessary subdirectories at `dir`
+with octal permission string `mode`.
+
+If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
+
+Returns the first directory that had to be created, if any.
+
+install
+=======
+
+With [npm](http://npmjs.org) do:
+
+    npm install mkdirp
+
+license
+=======
+
+MIT/X11
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/examples/pow.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/examples/pow.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/examples/pow.js	(revision 484)
@@ -0,0 +1,6 @@
+var mkdirp = require('mkdirp');
+
+mkdirp('/tmp/foo/bar/baz', function (err) {
+    if (err) console.error(err)
+    else console.log('pow!')
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/index.js	(revision 484)
@@ -0,0 +1,82 @@
+var path = require('path');
+var fs = require('fs');
+
+module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
+
+function mkdirP (p, mode, f, made) {
+    if (typeof mode === 'function' || mode === undefined) {
+        f = mode;
+        mode = 0777 & (~process.umask());
+    }
+    if (!made) made = null;
+
+    var cb = f || function () {};
+    if (typeof mode === 'string') mode = parseInt(mode, 8);
+    p = path.resolve(p);
+
+    fs.mkdir(p, mode, function (er) {
+        if (!er) {
+            made = made || p;
+            return cb(null, made);
+        }
+        switch (er.code) {
+            case 'ENOENT':
+                mkdirP(path.dirname(p), mode, function (er, made) {
+                    if (er) cb(er, made);
+                    else mkdirP(p, mode, cb, made);
+                });
+                break;
+
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
+                fs.stat(p, function (er2, stat) {
+                    // if the stat fails, then that's super weird.
+                    // let the original error be the failure reason.
+                    if (er2 || !stat.isDirectory()) cb(er, made)
+                    else cb(null, made);
+                });
+                break;
+        }
+    });
+}
+
+mkdirP.sync = function sync (p, mode, made) {
+    if (mode === undefined) {
+        mode = 0777 & (~process.umask());
+    }
+    if (!made) made = null;
+
+    if (typeof mode === 'string') mode = parseInt(mode, 8);
+    p = path.resolve(p);
+
+    try {
+        fs.mkdirSync(p, mode);
+        made = made || p;
+    }
+    catch (err0) {
+        switch (err0.code) {
+            case 'ENOENT' :
+                made = sync(path.dirname(p), mode, made);
+                sync(p, mode, made);
+                break;
+
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
+                var stat;
+                try {
+                    stat = fs.statSync(p);
+                }
+                catch (err1) {
+                    throw err0;
+                }
+                if (!stat.isDirectory()) throw err0;
+                break;
+        }
+    }
+
+    return made;
+};
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/package.json	(revision 484)
@@ -0,0 +1,36 @@
+{
+  "name": "mkdirp",
+  "description": "Recursively mkdir, like `mkdir -p`",
+  "version": "0.3.4",
+  "author": {
+    "name": "James Halliday",
+    "email": "mail@substack.net",
+    "url": "http://substack.net"
+  },
+  "main": "./index",
+  "keywords": [
+    "mkdir",
+    "directory"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/substack/node-mkdirp.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "devDependencies": {
+    "tap": "~0.2.4"
+  },
+  "license": "MIT/X11",
+  "engines": {
+    "node": "*"
+  },
+  "readme": "mkdirp\n======\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\nexample\n=======\n\npow.js\n------\n    var mkdirp = require('mkdirp');\n    \n    mkdirp('/tmp/foo/bar/baz', function (err) {\n        if (err) console.error(err)\n        else console.log('pow!')\n    });\n\nOutput\n    pow!\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\nmethods\n=======\n\nvar mkdirp = require('mkdirp');\n\nmkdirp(dir, mode, cb)\n---------------------\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\nmkdirp.sync(dir, mode)\n----------------------\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\ninstall\n=======\n\nWith [npm](http://npmjs.org) do:\n\n    npm install mkdirp\n\nlicense\n=======\n\nMIT/X11\n",
+  "readmeFilename": "README.markdown",
+  "bugs": {
+    "url": "https://github.com/substack/node-mkdirp/issues"
+  },
+  "_id": "mkdirp@0.3.4",
+  "_from": "mkdirp@0.3.4"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/chmod.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/chmod.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/chmod.js	(revision 484)
@@ -0,0 +1,38 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+var ps = [ '', 'tmp' ];
+
+for (var i = 0; i < 25; i++) {
+    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    ps.push(dir);
+}
+
+var file = ps.join('/');
+
+test('chmod-pre', function (t) {
+    var mode = 0744
+    mkdirp(file, mode, function (er) {
+        t.ifError(er, 'should not error');
+        fs.stat(file, function (er, stat) {
+            t.ifError(er, 'should exist');
+            t.ok(stat && stat.isDirectory(), 'should be directory');
+            t.equal(stat && stat.mode & 0777, mode, 'should be 0744');
+            t.end();
+        });
+    });
+});
+
+test('chmod', function (t) {
+    var mode = 0755
+    mkdirp(file, mode, function (er) {
+        t.ifError(er, 'should not error');
+        fs.stat(file, function (er, stat) {
+            t.ifError(er, 'should exist');
+            t.ok(stat && stat.isDirectory(), 'should be directory');
+            t.end();
+        });
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/clobber.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/clobber.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/clobber.js	(revision 484)
@@ -0,0 +1,37 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+var ps = [ '', 'tmp' ];
+
+for (var i = 0; i < 25; i++) {
+    var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    ps.push(dir);
+}
+
+var file = ps.join('/');
+
+// a file in the way
+var itw = ps.slice(0, 3).join('/');
+
+
+test('clobber-pre', function (t) {
+    console.error("about to write to "+itw)
+    fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
+
+    fs.stat(itw, function (er, stat) {
+        t.ifError(er)
+        t.ok(stat && stat.isFile(), 'should be file')
+        t.end()
+    })
+})
+
+test('clobber', function (t) {
+    t.plan(2);
+    mkdirp(file, 0755, function (err) {
+        t.ok(err);
+        t.equal(err.code, 'ENOTDIR');
+        t.end();
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/mkdirp.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/mkdirp.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/mkdirp.js	(revision 484)
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('woo', function (t) {
+    t.plan(2);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    
+    var file = '/tmp/' + [x,y,z].join('/');
+    
+    mkdirp(file, 0755, function (err) {
+        if (err) t.fail(err);
+        else path.exists(file, function (ex) {
+            if (!ex) t.fail('file not created')
+            else fs.stat(file, function (err, stat) {
+                if (err) t.fail(err)
+                else {
+                    t.equal(stat.mode & 0777, 0755);
+                    t.ok(stat.isDirectory(), 'target not a directory');
+                    t.end();
+                }
+            })
+        })
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/perm.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/perm.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/perm.js	(revision 484)
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('async perm', function (t) {
+    t.plan(2);
+    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
+    
+    mkdirp(file, 0755, function (err) {
+        if (err) t.fail(err);
+        else path.exists(file, function (ex) {
+            if (!ex) t.fail('file not created')
+            else fs.stat(file, function (err, stat) {
+                if (err) t.fail(err)
+                else {
+                    t.equal(stat.mode & 0777, 0755);
+                    t.ok(stat.isDirectory(), 'target not a directory');
+                    t.end();
+                }
+            })
+        })
+    });
+});
+
+test('async root perm', function (t) {
+    mkdirp('/tmp', 0755, function (err) {
+        if (err) t.fail(err);
+        t.end();
+    });
+    t.end();
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/perm_sync.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/perm_sync.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/perm_sync.js	(revision 484)
@@ -0,0 +1,39 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('sync perm', function (t) {
+    t.plan(2);
+    var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
+    
+    mkdirp.sync(file, 0755);
+    path.exists(file, function (ex) {
+        if (!ex) t.fail('file not created')
+        else fs.stat(file, function (err, stat) {
+            if (err) t.fail(err)
+            else {
+                t.equal(stat.mode & 0777, 0755);
+                t.ok(stat.isDirectory(), 'target not a directory');
+                t.end();
+            }
+        })
+    });
+});
+
+test('sync root perm', function (t) {
+    t.plan(1);
+    
+    var file = '/tmp';
+    mkdirp.sync(file, 0755);
+    path.exists(file, function (ex) {
+        if (!ex) t.fail('file not created')
+        else fs.stat(file, function (err, stat) {
+            if (err) t.fail(err)
+            else {
+                t.ok(stat.isDirectory(), 'target not a directory');
+                t.end();
+            }
+        })
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/race.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/race.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/race.js	(revision 484)
@@ -0,0 +1,41 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('race', function (t) {
+    t.plan(4);
+    var ps = [ '', 'tmp' ];
+    
+    for (var i = 0; i < 25; i++) {
+        var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+        ps.push(dir);
+    }
+    var file = ps.join('/');
+    
+    var res = 2;
+    mk(file, function () {
+        if (--res === 0) t.end();
+    });
+    
+    mk(file, function () {
+        if (--res === 0) t.end();
+    });
+    
+    function mk (file, cb) {
+        mkdirp(file, 0755, function (err) {
+            if (err) t.fail(err);
+            else path.exists(file, function (ex) {
+                if (!ex) t.fail('file not created')
+                else fs.stat(file, function (err, stat) {
+                    if (err) t.fail(err)
+                    else {
+                        t.equal(stat.mode & 0777, 0755);
+                        t.ok(stat.isDirectory(), 'target not a directory');
+                        if (cb) cb();
+                    }
+                })
+            })
+        });
+    }
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/rel.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/rel.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/rel.js	(revision 484)
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('rel', function (t) {
+    t.plan(2);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    
+    var cwd = process.cwd();
+    process.chdir('/tmp');
+    
+    var file = [x,y,z].join('/');
+    
+    mkdirp(file, 0755, function (err) {
+        if (err) t.fail(err);
+        else path.exists(file, function (ex) {
+            if (!ex) t.fail('file not created')
+            else fs.stat(file, function (err, stat) {
+                if (err) t.fail(err)
+                else {
+                    process.chdir(cwd);
+                    t.equal(stat.mode & 0777, 0755);
+                    t.ok(stat.isDirectory(), 'target not a directory');
+                    t.end();
+                }
+            })
+        })
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/return.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/return.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/return.js	(revision 484)
@@ -0,0 +1,25 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('return value', function (t) {
+    t.plan(4);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+    var file = '/tmp/' + [x,y,z].join('/');
+
+    // should return the first dir created.
+    // By this point, it would be profoundly surprising if /tmp didn't
+    // already exist, since every other test makes things in there.
+    mkdirp(file, function (err, made) {
+        t.ifError(err);
+        t.equal(made, '/tmp/' + x);
+        mkdirp(file, function (err, made) {
+          t.ifError(err);
+          t.equal(made, null);
+        });
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/return_sync.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/return_sync.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/return_sync.js	(revision 484)
@@ -0,0 +1,24 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('return value', function (t) {
+    t.plan(2);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+    var file = '/tmp/' + [x,y,z].join('/');
+
+    // should return the first dir created.
+    // By this point, it would be profoundly surprising if /tmp didn't
+    // already exist, since every other test makes things in there.
+    // Note that this will throw on failure, which will fail the test.
+    var made = mkdirp.sync(file);
+    t.equal(made, '/tmp/' + x);
+
+    // making the same file again should have no effect.
+    made = mkdirp.sync(file);
+    t.equal(made, null);
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/root.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/root.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/root.js	(revision 484)
@@ -0,0 +1,18 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('root', function (t) {
+    // '/' on unix, 'c:/' on windows.
+    var file = path.resolve('/');
+
+    mkdirp(file, 0755, function (err) {
+        if (err) throw err
+        fs.stat(file, function (er, stat) {
+            if (er) throw er
+            t.ok(stat.isDirectory(), 'target is a directory');
+            t.end();
+        })
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/sync.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/sync.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/sync.js	(revision 484)
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('sync', function (t) {
+    t.plan(2);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+    var file = '/tmp/' + [x,y,z].join('/');
+
+    try {
+        mkdirp.sync(file, 0755);
+    } catch (err) {
+        t.fail(err);
+        return t.end();
+    }
+
+    path.exists(file, function (ex) {
+        if (!ex) t.fail('file not created')
+        else fs.stat(file, function (err, stat) {
+            if (err) t.fail(err)
+            else {
+                t.equal(stat.mode & 0777, 0755);
+                t.ok(stat.isDirectory(), 'target not a directory');
+                t.end();
+            }
+        });
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/umask.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/umask.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/umask.js	(revision 484)
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('implicit mode from umask', function (t) {
+    t.plan(2);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    
+    var file = '/tmp/' + [x,y,z].join('/');
+    
+    mkdirp(file, function (err) {
+        if (err) t.fail(err);
+        else path.exists(file, function (ex) {
+            if (!ex) t.fail('file not created')
+            else fs.stat(file, function (err, stat) {
+                if (err) t.fail(err)
+                else {
+                    t.equal(stat.mode & 0777, 0777 & (~process.umask()));
+                    t.ok(stat.isDirectory(), 'target not a directory');
+                    t.end();
+                }
+            })
+        })
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/umask_sync.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/umask_sync.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/mkdirp/test/umask_sync.js	(revision 484)
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('umask sync modes', function (t) {
+    t.plan(2);
+    var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+    var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+    var file = '/tmp/' + [x,y,z].join('/');
+
+    try {
+        mkdirp.sync(file);
+    } catch (err) {
+        t.fail(err);
+        return t.end();
+    }
+
+    path.exists(file, function (ex) {
+        if (!ex) t.fail('file not created')
+        else fs.stat(file, function (err, stat) {
+            if (err) t.fail(err)
+            else {
+                t.equal(stat.mode & 0777, (0777 & (~process.umask())));
+                t.ok(stat.isDirectory(), 'target not a directory');
+                t.end();
+            }
+        });
+    });
+});
Index: Dev/trunk/src/node_modules/express/node_modules/range-parser/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/range-parser/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/range-parser/.npmignore	(revision 484)
@@ -0,0 +1,1 @@
+test
Index: Dev/trunk/src/node_modules/express/node_modules/range-parser/History.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/range-parser/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/range-parser/History.md	(revision 484)
@@ -0,0 +1,15 @@
+
+0.0.4 / 2012-06-17 
+==================
+
+  * changed: ret -1 for unsatisfiable and -2 when invalid
+
+0.0.3 / 2012-06-17 
+==================
+
+  * fix last-byte-pos default to len - 1
+
+0.0.2 / 2012-06-14 
+==================
+
+  * add `.type`
Index: Dev/trunk/src/node_modules/express/node_modules/range-parser/Makefile
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/range-parser/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/range-parser/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--reporter spec \
+		--require should
+
+.PHONY: test
Index: Dev/trunk/src/node_modules/express/node_modules/range-parser/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/range-parser/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/range-parser/Readme.md	(revision 484)
@@ -0,0 +1,28 @@
+
+# node-range-parser
+
+  Range header field parser.
+
+## Example:
+
+```js
+assert(-1 == parse(200, 'bytes=500-20'));
+assert(-2 == parse(200, 'bytes=malformed'));
+parse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }]));
+parse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }]));
+parse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }]));
+parse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }]));
+parse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }]));
+parse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }]));
+parse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }]));
+parse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }]));
+parse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }]));
+parse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }]));
+parse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }]));
+```
+
+## Installation
+
+```
+$ npm install range-parser
+```
Index: Dev/trunk/src/node_modules/express/node_modules/range-parser/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/range-parser/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/range-parser/index.js	(revision 484)
@@ -0,0 +1,49 @@
+
+/**
+ * Parse "Range" header `str` relative to the given file `size`.
+ *
+ * @param {Number} size
+ * @param {String} str
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function(size, str){
+  var valid = true;
+  var i = str.indexOf('=');
+
+  if (-1 == i) return -2;
+
+  var arr = str.slice(i + 1).split(',').map(function(range){
+    var range = range.split('-')
+      , start = parseInt(range[0], 10)
+      , end = parseInt(range[1], 10);
+
+    // -nnn
+    if (isNaN(start)) {
+      start = size - end;
+      end = size - 1;
+    // nnn-
+    } else if (isNaN(end)) {
+      end = size - 1;
+    }
+
+    // limit last-byte-pos to current length
+    if (end > size - 1) end = size - 1;
+
+    // invalid
+    if (isNaN(start)
+      || isNaN(end)
+      || start > end
+      || start < 0) valid = false;
+
+    return {
+      start: start,
+      end: end
+    };
+  });
+
+  arr.type = str.slice(0, i);
+
+  return valid ? arr : -1;
+};
Index: Dev/trunk/src/node_modules/express/node_modules/range-parser/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/range-parser/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/range-parser/package.json	(revision 484)
@@ -0,0 +1,20 @@
+{
+  "name": "range-parser",
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca",
+    "url": "http://tjholowaychuk.com"
+  },
+  "description": "Range header field string parser",
+  "version": "0.0.4",
+  "main": "index.js",
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "readme": "\n# node-range-parser\n\n  Range header field parser.\n\n## Example:\n\n```js\nassert(-1 == parse(200, 'bytes=500-20'));\nassert(-2 == parse(200, 'bytes=malformed'));\nparse(200, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 199 }]));\nparse(1000, 'bytes=0-499').should.eql(arr('bytes', [{ start: 0, end: 499 }]));\nparse(1000, 'bytes=40-80').should.eql(arr('bytes', [{ start: 40, end: 80 }]));\nparse(1000, 'bytes=-500').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=-400').should.eql(arr('bytes', [{ start: 600, end: 999 }]));\nparse(1000, 'bytes=500-').should.eql(arr('bytes', [{ start: 500, end: 999 }]));\nparse(1000, 'bytes=400-').should.eql(arr('bytes', [{ start: 400, end: 999 }]));\nparse(1000, 'bytes=0-0').should.eql(arr('bytes', [{ start: 0, end: 0 }]));\nparse(1000, 'bytes=-1').should.eql(arr('bytes', [{ start: 999, end: 999 }]));\nparse(1000, 'items=0-5').should.eql(arr('items', [{ start: 0, end: 5 }]));\nparse(1000, 'bytes=40-80,-1').should.eql(arr('bytes', [{ start: 40, end: 80 }, { start: 999, end: 999 }]));\n```\n\n## Installation\n\n```\n$ npm install range-parser\n```",
+  "readmeFilename": "Readme.md",
+  "_id": "range-parser@0.0.4",
+  "_from": "range-parser@0.0.4"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/send/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/.npmignore	(revision 484)
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
Index: Dev/trunk/src/node_modules/express/node_modules/send/History.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/History.md	(revision 484)
@@ -0,0 +1,25 @@
+
+0.1.0 / 2012-08-25 
+==================
+
+  * add options parameter to send() that is passed to fs.createReadStream() [kanongil]
+
+0.0.4 / 2012-08-16 
+==================
+
+  * allow custom "Accept-Ranges" definition
+
+0.0.3 / 2012-07-16 
+==================
+
+  * fix normalization of the root directory. Closes #3
+
+0.0.2 / 2012-07-09 
+==================
+
+  * add passing of req explicitly for now (YUCK)
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
Index: Dev/trunk/src/node_modules/express/node_modules/send/Makefile
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/Makefile	(revision 484)
@@ -0,0 +1,8 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--require should \
+		--reporter spec \
+		--bail
+
+.PHONY: test
Index: Dev/trunk/src/node_modules/express/node_modules/send/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/Readme.md	(revision 484)
@@ -0,0 +1,123 @@
+
+# send
+
+  Send is Connect's `static()` extracted for generalized use, a streaming static file
+  server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.
+
+## Installation
+
+    $ npm install send
+
+## Examples
+
+  Small:
+
+```js
+var http = require('http');
+var send = require('send');
+
+var app = http.createServer(function(req, res){
+  send(req, req.url).pipe(res);
+});
+```
+
+  Serving from a root directory with custom error-handling:
+
+```js
+var http = require('http');
+var send = require('send');
+
+var app = http.createServer(function(req, res){
+  // your custom error-handling logic:
+  function error(err) {
+    res.statusCode = err.status || 500;
+    res.end(err.message);
+  }
+
+  // your custom directory handling logic:
+  function redirect() {
+    res.statusCode = 301;
+    res.setHeader('Location', req.url + '/');
+    res.end('Redirecting to ' + req.url + '/');
+  }
+
+  // transfer arbitrary files from within
+  // /www/example.com/public/*
+  send(req, url.parse(req.url).pathname)
+  .root('/www/example.com/public')
+  .on('error', error)
+  .on('directory', redirect)
+  .pipe(res);
+});
+```
+
+## API
+
+### Events
+
+  - `error` an error occurred `(err)`
+  - `directory` a directory was requested
+  - `stream` file streaming has started `(stream)`
+  - `end` streaming has completed
+
+### .root(dir)
+
+  Serve files relative to `path`. Aliased as `.from(dir)`.
+
+### .index(path)
+
+  By default send supports "index.html" files, to disable this
+  invoke `.index(false)` or to supply a new index pass a string.
+
+### .maxage(ms)
+
+  Provide a max-age in milliseconds for http caching, defaults to 0.
+
+## Error-handling
+
+  By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.
+
+## Caching
+
+  It does _not_ perform internal caching, you should use a reverse proxy cache such
+  as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).
+
+## Debugging
+
+ To enable `debug()` instrumentation output export __DEBUG__:
+
+```
+$ DEBUG=send node app
+```
+
+## Running tests
+
+```
+$ npm install
+$ make test
+```
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2012 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.
Index: Dev/trunk/src/node_modules/express/node_modules/send/index.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/index.js	(revision 484)
@@ -0,0 +1,2 @@
+
+module.exports = require('./lib/send');
Index: Dev/trunk/src/node_modules/express/node_modules/send/lib/send.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/lib/send.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/lib/send.js	(revision 484)
@@ -0,0 +1,473 @@
+
+/**
+ * Module dependencies.
+ */
+
+var debug = require('debug')('send')
+  , parseRange = require('range-parser')
+  , Stream = require('stream')
+  , mime = require('mime')
+  , fresh = require('fresh')
+  , path = require('path')
+  , http = require('http')
+  , fs = require('fs')
+  , basename = path.basename
+  , normalize = path.normalize
+  , join = path.join
+  , utils = require('./utils');
+
+/**
+ * Expose `send`.
+ */
+
+exports = module.exports = send;
+
+/**
+ * Expose mime module.
+ */
+
+exports.mime = mime;
+
+/**
+ * Return a `SendStream` for `req` and `path`.
+ *
+ * @param {Request} req
+ * @param {String} path
+ * @param {Object} options
+ * @return {SendStream}
+ * @api public
+ */
+
+function send(req, path, options) {
+  return new SendStream(req, path, options);
+}
+
+/**
+ * Initialize a `SendStream` with the given `path`.
+ *
+ * Events:
+ *
+ *  - `error` an error occurred
+ *  - `stream` file streaming has started
+ *  - `end` streaming has completed
+ *  - `directory` a directory was requested
+ *
+ * @param {Request} req
+ * @param {String} path
+ * @param {Object} options
+ * @api private
+ */
+
+function SendStream(req, path, options) {
+  var self = this;
+  this.req = req;
+  this.path = path;
+  this.options = options || {};
+  this.maxage(0);
+  this.hidden(false);
+  this.index('index.html');
+}
+
+/**
+ * Inherits from `Stream.prototype`.
+ */
+
+SendStream.prototype.__proto__ = Stream.prototype;
+
+/**
+ * Enable or disable "hidden" (dot) files.
+ *
+ * @param {Boolean} path
+ * @return {SendStream}
+ * @api public
+ */
+
+SendStream.prototype.hidden = function(val){
+  debug('hidden %s', val);
+  this._hidden = val;
+  return this;
+};
+
+/**
+ * Set index `path`, set to a falsy
+ * value to disable index support.
+ *
+ * @param {String|Boolean} path
+ * @return {SendStream}
+ * @api public
+ */
+
+SendStream.prototype.index = function(path){
+  debug('index %s', path);
+  this._index = path;
+  return this;
+};
+
+/**
+ * Set root `path`.
+ *
+ * @param {String} path
+ * @return {SendStream}
+ * @api public
+ */
+
+SendStream.prototype.root = 
+SendStream.prototype.from = function(path){
+  this._root = normalize(path);
+  return this;
+};
+
+/**
+ * Set max-age to `ms`.
+ *
+ * @param {Number} ms
+ * @return {SendStream}
+ * @api public
+ */
+
+SendStream.prototype.maxage = function(ms){
+  if (Infinity == ms) ms = 60 * 60 * 24 * 365 * 1000;
+  debug('max-age %d', ms);
+  this._maxage = ms;
+  return this;
+};
+
+/**
+ * Emit error with `status`.
+ *
+ * @param {Number} status
+ * @api private
+ */
+
+SendStream.prototype.error = function(status, err){
+  var res = this.res;
+  var msg = http.STATUS_CODES[status];
+  err = err || new Error(msg);
+  err.status = status;
+  if (this.listeners('error').length) return this.emit('error', err);
+  res.statusCode = err.status;
+  res.end(msg);
+};
+
+/**
+ * Check if the pathname is potentially malicious.
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.isMalicious = function(){
+  return !this._root && ~this.path.indexOf('..');
+};
+
+/**
+ * Check if the pathname ends with "/".
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.hasTrailingSlash = function(){
+  return '/' == this.path[this.path.length - 1];
+};
+
+/**
+ * Check if the basename leads with ".".
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.hasLeadingDot = function(){
+  return '.' == basename(this.path)[0];
+};
+
+/**
+ * Check if this is a conditional GET request.
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.isConditionalGET = function(){
+  return this.req.headers['if-none-match']
+    || this.req.headers['if-modified-since'];
+};
+
+/**
+ * Strip content-* header fields.
+ *
+ * @api private
+ */
+
+SendStream.prototype.removeContentHeaderFields = function(){
+  var res = this.res;
+  Object.keys(res._headers).forEach(function(field){
+    if (0 == field.indexOf('content')) {
+      res.removeHeader(field);
+    }
+  });
+};
+
+/**
+ * Respond with 304 not modified.
+ *
+ * @api private
+ */
+
+SendStream.prototype.notModified = function(){
+  var res = this.res;
+  debug('not modified');
+  this.removeContentHeaderFields();
+  res.statusCode = 304;
+  res.end();
+};
+
+/**
+ * Check if the request is cacheable, aka
+ * responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}).
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.isCachable = function(){
+  var res = this.res;
+  return (res.statusCode >= 200 && res.statusCode < 300) || 304 == res.statusCode;
+};
+
+/**
+ * Handle stat() error.
+ *
+ * @param {Error} err
+ * @api private
+ */
+
+SendStream.prototype.onStatError = function(err){
+  var notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'];
+  if (~notfound.indexOf(err.code)) return this.error(404, err);
+  this.error(500, err);
+};
+
+/**
+ * Check if the cache is fresh.
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+SendStream.prototype.isFresh = function(){
+  return fresh(this.req.headers, this.res._headers);
+};
+
+/**
+ * Redirect to `path`.
+ *
+ * @param {String} path
+ * @api private
+ */
+
+SendStream.prototype.redirect = function(path){
+  if (this.listeners('directory').length) return this.emit('directory');
+  var res = this.res;
+  path += '/';
+  res.statusCode = 301;
+  res.setHeader('Location', path);
+  res.end('Redirecting to ' + utils.escape(path));
+};
+
+/**
+ * Pipe to `res.
+ *
+ * @param {Stream} res
+ * @return {Stream} res
+ * @api public
+ */
+
+SendStream.prototype.pipe = function(res){
+  var self = this
+    , args = arguments
+    , path = this.path
+    , root = this._root;
+
+  // references
+  this.res = res;
+
+  // invalid request uri
+  path = utils.decode(path);
+  if (-1 == path) return this.error(400);
+
+  // null byte(s)
+  if (~path.indexOf('\0')) return this.error(400);
+
+  // join / normalize from optional root dir
+  if (root) path = normalize(join(this._root, path));
+
+  // ".." is malicious without "root"
+  if (this.isMalicious()) return this.error(403);
+
+  // malicious path
+  if (root && 0 != path.indexOf(root)) return this.error(403);
+
+  // hidden file support
+  if (!this._hidden && this.hasLeadingDot()) return this.error(404);
+
+  // index file support
+  if (this._index && this.hasTrailingSlash()) path += this._index;
+
+  debug('stat "%s"', path);
+  fs.stat(path, function(err, stat){
+    if (err) return self.onStatError(err);
+    if (stat.isDirectory()) return self.redirect(self.path);
+    self.send(path, stat);
+  });
+
+  return res;
+};
+
+/**
+ * Transfer `path`.
+ *
+ * @param {String} path
+ * @api public
+ */
+
+SendStream.prototype.send = function(path, stat){
+  var options = this.options;
+  var len = stat.size;
+  var res = this.res;
+  var req = this.req;
+  var ranges = req.headers.range;
+  var offset = options.start || 0;
+
+  // set header fields
+  this.setHeader(stat);
+
+  // set content-type
+  this.type(path);
+
+  // conditional GET support
+  if (this.isConditionalGET()
+    && this.isCachable()
+    && this.isFresh()) {
+    return this.notModified();
+  }
+
+  // adjust len to start/end options
+  len = Math.max(0, len - offset);
+  if (options.end !== undefined) {
+    var bytes = options.end - offset + 1;
+    if (len > bytes) len = bytes;
+  }
+
+  // Range support
+  if (ranges) {
+    ranges = parseRange(len, ranges);
+
+    // unsatisfiable
+    if (-1 == ranges) {
+      res.setHeader('Content-Range', 'bytes */' + stat.size);
+      return this.error(416);
+    }
+
+    // valid (syntactically invalid ranges are treated as a regular response)
+    if (-2 != ranges) {
+      options.start = offset + ranges[0].start;
+      options.end = offset + ranges[0].end;
+
+      // Content-Range
+      res.statusCode = 206;
+      res.setHeader('Content-Range', 'bytes '
+        + ranges[0].start
+        + '-'
+        + ranges[0].end
+        + '/'
+        + len);
+      len = options.end - options.start + 1;
+    }
+  }
+
+  // content-length
+  res.setHeader('Content-Length', len);
+
+  // HEAD support
+  if ('HEAD' == req.method) return res.end();
+
+  this.stream(path, options);
+};
+
+/**
+ * Stream `path` to the response.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @api private
+ */
+
+SendStream.prototype.stream = function(path, options){
+  // TODO: this is all lame, refactor meeee
+  var self = this;
+  var res = this.res;
+  var req = this.req;
+
+  // pipe
+  var stream = fs.createReadStream(path, options);
+  this.emit('stream', stream);
+  stream.pipe(res);
+
+  // socket closed, done with the fd
+  req.on('close', stream.destroy.bind(stream));
+
+  // error handling code-smell
+  stream.on('error', function(err){
+    // no hope in responding
+    if (res._header) {
+      console.error(err.stack);
+      req.destroy();
+      return;
+    }
+
+    // 500
+    err.status = 500;
+    self.emit('error', err);
+  });
+
+  // end
+  stream.on('end', function(){
+    self.emit('end');
+  });
+};
+
+/**
+ * Set content-type based on `path`
+ * if it hasn't been explicitly set.
+ *
+ * @param {String} path
+ * @api private
+ */
+
+SendStream.prototype.type = function(path){
+  var res = this.res;
+  if (res.getHeader('Content-Type')) return;
+  var type = mime.lookup(path);
+  var charset = mime.charsets.lookup(type);
+  debug('content-type %s', type);
+  res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
+};
+
+/**
+ * Set reaponse header fields, most
+ * fields may be pre-defined.
+ *
+ * @param {Object} stat
+ * @api private
+ */
+
+SendStream.prototype.setHeader = function(stat){
+  var res = this.res;
+  if (!res.getHeader('Accept-Ranges')) res.setHeader('Accept-Ranges', 'bytes');
+  if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat));
+  if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString());
+  if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (this._maxage / 1000));
+  if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
+};
Index: Dev/trunk/src/node_modules/express/node_modules/send/lib/utils.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/lib/utils.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/lib/utils.js	(revision 484)
@@ -0,0 +1,47 @@
+
+/**
+ * Return an ETag in the form of `"<size>-<mtime>"`
+ * from the given `stat`.
+ *
+ * @param {Object} stat
+ * @return {String}
+ * @api private
+ */
+
+exports.etag = function(stat) {
+  return '"' + stat.size + '-' + Number(stat.mtime) + '"';
+};
+
+/**
+ * decodeURIComponent.
+ *
+ * Allows V8 to only deoptimize this fn instead of all
+ * of send().
+ *
+ * @param {String} path
+ * @api private
+ */
+
+exports.decode = function(path){
+  try {
+    return decodeURIComponent(path);
+  } catch (err) {
+    return -1;
+  }
+};
+
+/**
+ * Escape the given string of `html`.
+ *
+ * @param {String} html
+ * @return {String}
+ * @api private
+ */
+
+exports.escape = function(html){
+  return String(html)
+    .replace(/&(?!\w+;)/g, '&amp;')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;')
+    .replace(/"/g, '&quot;');
+};
Index: Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/LICENSE	(revision 484)
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/README.md
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/README.md	(revision 484)
@@ -0,0 +1,63 @@
+# mime
+
+Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.
+
+## Install
+
+Install with [npm](http://github.com/isaacs/npm):
+
+    npm install mime
+
+## API - Queries
+
+### mime.lookup(path)
+Get the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.').  E.g.
+
+    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)
+Get the default extension for `type`
+
+    mime.extension('text/html');                 // => 'html'
+    mime.extension('application/octet-stream');  // => 'bin'
+
+### mime.charsets.lookup()
+
+Map mime-type to charset
+
+    mime.charsets.lookup('text/plain');        // => 'UTF-8'
+
+(The logic for charset lookups is pretty rudimentary.  Feel free to suggest improvements.)
+
+## API - Defining Custom Types
+
+The following APIs allow you to add your own type mappings within your project.  If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types).
+
+### mime.define()
+
+Add custom mime/extension mappings
+
+    mime.define({
+        'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
+        'application/x-my-type': ['x-mt', 'x-mtt'],
+        // etc ...
+    });
+
+    mime.lookup('x-sft');                 // => 'text/x-some-format'
+
+The first entry in the extensions array is returned by `mime.extension()`. E.g.
+
+    mime.extension('text/x-some-format'); // => 'x-sf'
+
+### mime.load(filepath)
+
+Load mappings from an Apache ".types" format file
+
+    mime.load('./my_project.types');
+
+The .types file format is simple -  See the `types` dir for examples.
Index: Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/mime.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/mime.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/mime.js	(revision 484)
@@ -0,0 +1,104 @@
+var path = require('path');
+var fs = require('fs');
+
+function Mime() {
+  // Map of extension -> mime type
+  this.types = Object.create(null);
+
+  // Map of mime type -> extension
+  this.extensions = Object.create(null);
+}
+
+/**
+ * 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
+ */
+Mime.prototype.define = function (map) {
+  for (var type in map) {
+    var exts = map[type];
+
+    for (var i = 0; i < exts.length; i++) {
+      this.types[exts[i]] = type;
+    }
+
+    // Default extension is the first one we encounter
+    if (!this.extensions[type]) {
+      this.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.
+ */
+Mime.prototype.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) {
+    // Clean up whitespace/comments, and split into fields
+    var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
+    map[fields.shift()] = fields;
+  });
+
+  this.define(map);
+};
+
+/**
+ * Lookup a mime type based on extension
+ */
+Mime.prototype.lookup = function(path, fallback) {
+  var ext = path.replace(/.*[\.\/]/, '').toLowerCase();
+
+  return this.types[ext] || fallback || this.default_type;
+};
+
+/**
+ * Return file extension associated with a mime type
+ */
+Mime.prototype.extension = function(mimeType) {
+  return this.extensions[mimeType];
+};
+
+// Default instance
+var mime = new Mime();
+
+// Load local copy of
+// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
+mime.load(path.join(__dirname, 'types/mime.types'));
+
+// Load additional types from node.js community
+mime.load(path.join(__dirname, 'types/node.types'));
+
+// Default type
+mime.default_type = mime.lookup('bin');
+
+//
+// Additional API specific to the default instance
+//
+
+mime.Mime = Mime;
+
+/**
+ * Lookup a charset based on mime type.
+ */
+mime.charsets = {
+  lookup: function(mimeType, fallback) {
+    // Assume text types are utf8
+    return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
+  }
+}
+
+module.exports = mime;
Index: Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/package.json	(revision 484)
@@ -0,0 +1,35 @@
+{
+  "author": {
+    "name": "Robert Kieffer",
+    "email": "robert@broofa.com",
+    "url": "http://github.com/broofa"
+  },
+  "contributors": [
+    {
+      "name": "Benjamin Thomas",
+      "email": "benjamin@benjaminthomas.org",
+      "url": "http://github.com/bentomas"
+    }
+  ],
+  "dependencies": {},
+  "description": "A comprehensive library for mime-type mapping",
+  "devDependencies": {},
+  "keywords": [
+    "util",
+    "mime"
+  ],
+  "main": "mime.js",
+  "name": "mime",
+  "repository": {
+    "url": "https://github.com/broofa/node-mime",
+    "type": "git"
+  },
+  "version": "1.2.6",
+  "readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n    npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.').  E.g.\n\n    var mime = require('mime');\n\n    mime.lookup('/path/to/file.txt');         // => 'text/plain'\n    mime.lookup('file.txt');                  // => 'text/plain'\n    mime.lookup('.TXT');                      // => 'text/plain'\n    mime.lookup('htm');                       // => 'text/html'\n\n### mime.extension(type)\nGet the default extension for `type`\n\n    mime.extension('text/html');                 // => 'html'\n    mime.extension('application/octet-stream');  // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n    mime.charsets.lookup('text/plain');        // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary.  Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project.  If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/bentomas/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n    mime.define({\n        'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n        'application/x-my-type': ['x-mt', 'x-mtt'],\n        // etc ...\n    });\n\n    mime.lookup('x-sft');                 // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n    mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n    mime.load('./my_project.types');\n\nThe .types file format is simple -  See the `types` dir for examples.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/broofa/node-mime/issues"
+  },
+  "_id": "mime@1.2.6",
+  "_from": "mime@1.2.6"
+}
Index: Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/test.js
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/test.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/test.js	(revision 484)
@@ -0,0 +1,55 @@
+/**
+ * Usage: node test.js
+ */
+
+var mime = require('./mime');
+var assert = require('assert');
+
+function eq(a, b) {
+  console.log('Test: ' + a + ' === ' + b);
+  assert.strictEqual.apply(null, arguments);
+}
+
+console.log(Object.keys(mime.extensions).length + ' types');
+console.log(Object.keys(mime.types).length + ' extensions\n');
+
+//
+// Test mime lookups
+//
+
+eq('text/plain', mime.lookup('text.txt'));
+eq('text/plain', mime.lookup('.text.txt'));
+eq('text/plain', mime.lookup('.txt'));
+eq('text/plain', mime.lookup('txt'));
+eq('application/octet-stream', mime.lookup('text.nope'));
+eq('fallback', mime.lookup('text.fallback', 'fallback'));
+eq('application/octet-stream', mime.lookup('constructor'));
+eq('text/plain', mime.lookup('TEXT.TXT'));
+eq('text/event-stream', mime.lookup('text/event-stream'));
+eq('application/x-web-app-manifest+json', mime.lookup('text.webapp'));
+
+//
+// Test extensions
+//
+
+eq('txt', mime.extension(mime.types.text));
+eq('html', mime.extension(mime.types.htm));
+eq('bin', mime.extension('application/octet-stream'));
+eq(undefined, mime.extension('constructor'));
+
+//
+// Test node types
+//
+
+eq('application/octet-stream', mime.lookup('file.buffer'));
+eq('audio/mp4', mime.lookup('file.m4a'));
+
+//
+// Test charsets
+//
+
+eq('UTF-8', mime.charsets.lookup('text/plain'));
+eq(undefined, mime.charsets.lookup(mime.types.js));
+eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
+
+console.log('\nOK');
Index: Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/types/mime.types
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/types/mime.types	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/types/mime.types	(revision 484)
@@ -0,0 +1,1510 @@
+# This file maps Internet media types to unique file extension(s).
+# Although created for httpd, this file is used by many software systems
+# and has been placed in the public domain for unlimited redisribution.
+#
+# The table below contains both registered and (common) unregistered types.
+# A type that has no unique extension can be ignored -- they are listed
+# here to guide configurations toward known types and to make it easier to
+# identify "new" types.  File extensions are also commonly used to indicate
+# content languages and encodings, so choose them carefully.
+#
+# Internet media types should be registered as described in RFC 4288.
+# The registry is at <http://www.iana.org/assignments/media-types/>.
+#
+# MIME type (lowercased)			Extensions
+# ============================================	==========
+# application/1d-interleaved-parityfec
+# application/3gpp-ims+xml
+# application/activemessage
+application/andrew-inset			ez
+# application/applefile
+application/applixware				aw
+application/atom+xml				atom
+application/atomcat+xml				atomcat
+# application/atomicmail
+application/atomsvc+xml				atomsvc
+# application/auth-policy+xml
+# application/batch-smtp
+# application/beep+xml
+# application/calendar+xml
+# application/cals-1840
+# application/ccmp+xml
+application/ccxml+xml				ccxml
+application/cdmi-capability			cdmia
+application/cdmi-container			cdmic
+application/cdmi-domain				cdmid
+application/cdmi-object				cdmio
+application/cdmi-queue				cdmiq
+# application/cea-2018+xml
+# application/cellml+xml
+# application/cfw
+# application/cnrp+xml
+# application/commonground
+# application/conference-info+xml
+# application/cpl+xml
+# application/csta+xml
+# application/cstadata+xml
+application/cu-seeme				cu
+# application/cybercash
+application/davmount+xml			davmount
+# application/dca-rft
+# application/dec-dx
+# application/dialog-info+xml
+# application/dicom
+# application/dns
+# application/dskpp+xml
+application/dssc+der				dssc
+application/dssc+xml				xdssc
+# application/dvcs
+application/ecmascript				ecma
+# application/edi-consent
+# application/edi-x12
+# application/edifact
+application/emma+xml				emma
+# application/epp+xml
+application/epub+zip				epub
+# application/eshop
+# application/example
+application/exi					exi
+# application/fastinfoset
+# application/fastsoap
+# application/fits
+application/font-tdpfr				pfr
+# application/framework-attributes+xml
+# application/h224
+# application/held+xml
+# application/http
+application/hyperstudio				stk
+# application/ibe-key-request+xml
+# application/ibe-pkg-reply+xml
+# application/ibe-pp-data
+# application/iges
+# application/im-iscomposing+xml
+# application/index
+# application/index.cmd
+# application/index.obj
+# application/index.response
+# application/index.vnd
+application/inkml+xml				ink inkml
+# application/iotp
+application/ipfix				ipfix
+# application/ipp
+# application/isup
+application/java-archive			jar
+application/java-serialized-object		ser
+application/java-vm				class
+application/javascript				js
+application/json				json
+# application/kpml-request+xml
+# application/kpml-response+xml
+application/lost+xml				lostxml
+application/mac-binhex40			hqx
+application/mac-compactpro			cpt
+# application/macwriteii
+application/mads+xml				mads
+application/marc				mrc
+application/marcxml+xml				mrcx
+application/mathematica				ma nb mb
+# application/mathml-content+xml
+# application/mathml-presentation+xml
+application/mathml+xml				mathml
+# application/mbms-associated-procedure-description+xml
+# application/mbms-deregister+xml
+# application/mbms-envelope+xml
+# application/mbms-msk+xml
+# application/mbms-msk-response+xml
+# application/mbms-protection-description+xml
+# application/mbms-reception-report+xml
+# application/mbms-register+xml
+# application/mbms-register-response+xml
+# application/mbms-user-service-description+xml
+application/mbox				mbox
+# application/media_control+xml
+application/mediaservercontrol+xml		mscml
+application/metalink4+xml			meta4
+application/mets+xml				mets
+# application/mikey
+application/mods+xml				mods
+# application/moss-keys
+# application/moss-signature
+# application/mosskey-data
+# application/mosskey-request
+application/mp21				m21 mp21
+application/mp4					mp4s
+# application/mpeg4-generic
+# application/mpeg4-iod
+# application/mpeg4-iod-xmt
+# application/msc-ivr+xml
+# application/msc-mixer+xml
+application/msword				doc dot
+application/mxf					mxf
+# application/nasdata
+# application/news-checkgroups
+# application/news-groupinfo
+# application/news-transmission
+# application/nss
+# application/ocsp-request
+# application/ocsp-response
+application/octet-stream	bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy
+application/oda					oda
+application/oebps-package+xml			opf
+application/ogg					ogx
+application/onenote				onetoc onetoc2 onetmp onepkg
+application/oxps				oxps
+# application/parityfec
+application/patch-ops-error+xml			xer
+application/pdf					pdf
+application/pgp-encrypted			pgp
+# application/pgp-keys
+application/pgp-signature			asc sig
+application/pics-rules				prf
+# application/pidf+xml
+# application/pidf-diff+xml
+application/pkcs10				p10
+application/pkcs7-mime				p7m p7c
+application/pkcs7-signature			p7s
+application/pkcs8				p8
+application/pkix-attr-cert			ac
+application/pkix-cert				cer
+application/pkix-crl				crl
+application/pkix-pkipath			pkipath
+application/pkixcmp				pki
+application/pls+xml				pls
+# application/poc-settings+xml
+application/postscript				ai eps ps
+# application/prs.alvestrand.titrax-sheet
+application/prs.cww				cww
+# application/prs.nprend
+# application/prs.plucker
+# application/prs.rdf-xml-crypt
+# application/prs.xsf+xml
+application/pskc+xml				pskcxml
+# application/qsig
+application/rdf+xml				rdf
+application/reginfo+xml				rif
+application/relax-ng-compact-syntax		rnc
+# application/remote-printing
+application/resource-lists+xml			rl
+application/resource-lists-diff+xml		rld
+# application/riscos
+# application/rlmi+xml
+application/rls-services+xml			rs
+application/rpki-ghostbusters			gbr
+application/rpki-manifest			mft
+application/rpki-roa				roa
+# application/rpki-updown
+application/rsd+xml				rsd
+application/rss+xml				rss
+application/rtf					rtf
+# application/rtx
+# application/samlassertion+xml
+# application/samlmetadata+xml
+application/sbml+xml				sbml
+application/scvp-cv-request			scq
+application/scvp-cv-response			scs
+application/scvp-vp-request			spq
+application/scvp-vp-response			spp
+application/sdp					sdp
+# application/set-payment
+application/set-payment-initiation		setpay
+# application/set-registration
+application/set-registration-initiation		setreg
+# application/sgml
+# application/sgml-open-catalog
+application/shf+xml				shf
+# application/sieve
+# application/simple-filter+xml
+# application/simple-message-summary
+# application/simplesymbolcontainer
+# application/slate
+# application/smil
+application/smil+xml				smi smil
+# application/soap+fastinfoset
+# application/soap+xml
+application/sparql-query			rq
+application/sparql-results+xml			srx
+# application/spirits-event+xml
+application/srgs				gram
+application/srgs+xml				grxml
+application/sru+xml				sru
+application/ssml+xml				ssml
+# application/tamp-apex-update
+# application/tamp-apex-update-confirm
+# application/tamp-community-update
+# application/tamp-community-update-confirm
+# application/tamp-error
+# application/tamp-sequence-adjust
+# application/tamp-sequence-adjust-confirm
+# application/tamp-status-query
+# application/tamp-status-response
+# application/tamp-update
+# application/tamp-update-confirm
+application/tei+xml				tei teicorpus
+application/thraud+xml				tfi
+# application/timestamp-query
+# application/timestamp-reply
+application/timestamped-data			tsd
+# application/tve-trigger
+# application/ulpfec
+# application/vcard+xml
+# application/vemmi
+# application/vividence.scriptfile
+# application/vnd.3gpp.bsf+xml
+application/vnd.3gpp.pic-bw-large		plb
+application/vnd.3gpp.pic-bw-small		psb
+application/vnd.3gpp.pic-bw-var			pvb
+# application/vnd.3gpp.sms
+# application/vnd.3gpp2.bcmcsinfo+xml
+# application/vnd.3gpp2.sms
+application/vnd.3gpp2.tcap			tcap
+application/vnd.3m.post-it-notes		pwn
+application/vnd.accpac.simply.aso		aso
+application/vnd.accpac.simply.imp		imp
+application/vnd.acucobol			acu
+application/vnd.acucorp				atc acutc
+application/vnd.adobe.air-application-installer-package+zip	air
+application/vnd.adobe.fxp			fxp fxpl
+# application/vnd.adobe.partial-upload
+application/vnd.adobe.xdp+xml			xdp
+application/vnd.adobe.xfdf			xfdf
+# application/vnd.aether.imp
+# application/vnd.ah-barcode
+application/vnd.ahead.space			ahead
+application/vnd.airzip.filesecure.azf		azf
+application/vnd.airzip.filesecure.azs		azs
+application/vnd.amazon.ebook			azw
+application/vnd.americandynamics.acc		acc
+application/vnd.amiga.ami			ami
+# application/vnd.amundsen.maze+xml
+application/vnd.android.package-archive		apk
+application/vnd.anser-web-certificate-issue-initiation	cii
+application/vnd.anser-web-funds-transfer-initiation	fti
+application/vnd.antix.game-component		atx
+application/vnd.apple.installer+xml		mpkg
+application/vnd.apple.mpegurl			m3u8
+# application/vnd.arastra.swi
+application/vnd.aristanetworks.swi		swi
+application/vnd.astraea-software.iota		iota
+application/vnd.audiograph			aep
+# application/vnd.autopackage
+# application/vnd.avistar+xml
+application/vnd.blueice.multipass		mpm
+# application/vnd.bluetooth.ep.oob
+application/vnd.bmi				bmi
+application/vnd.businessobjects			rep
+# application/vnd.cab-jscript
+# application/vnd.canon-cpdl
+# application/vnd.canon-lips
+# application/vnd.cendio.thinlinc.clientconf
+application/vnd.chemdraw+xml			cdxml
+application/vnd.chipnuts.karaoke-mmd		mmd
+application/vnd.cinderella			cdy
+# application/vnd.cirpack.isdn-ext
+application/vnd.claymore			cla
+application/vnd.cloanto.rp9			rp9
+application/vnd.clonk.c4group			c4g c4d c4f c4p c4u
+application/vnd.cluetrust.cartomobile-config		c11amc
+application/vnd.cluetrust.cartomobile-config-pkg	c11amz
+# application/vnd.collection+json
+# 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
+application/vnd.curl.car			car
+application/vnd.curl.pcurl			pcurl
+# application/vnd.cybank
+application/vnd.data-vision.rdz			rdz
+application/vnd.dece.data			uvf uvvf uvd uvvd
+application/vnd.dece.ttml+xml			uvt uvvt
+application/vnd.dece.unspecified		uvx uvvx
+application/vnd.dece.zip			uvz uvvz
+application/vnd.denovo.fcselayout-link		fe_launch
+# application/vnd.dir-bi.plate-dl-nosuffix
+application/vnd.dna				dna
+application/vnd.dolby.mlp			mlp
+# application/vnd.dolby.mobile.1
+# application/vnd.dolby.mobile.2
+application/vnd.dpgraph				dpg
+application/vnd.dreamfactory			dfac
+application/vnd.dvb.ait				ait
+# application/vnd.dvb.dvbj
+# application/vnd.dvb.esgcontainer
+# application/vnd.dvb.ipdcdftnotifaccess
+# application/vnd.dvb.ipdcesgaccess
+# application/vnd.dvb.ipdcesgaccess2
+# application/vnd.dvb.ipdcesgpdd
+# application/vnd.dvb.ipdcroaming
+# application/vnd.dvb.iptv.alfec-base
+# application/vnd.dvb.iptv.alfec-enhancement
+# application/vnd.dvb.notif-aggregate-root+xml
+# application/vnd.dvb.notif-container+xml
+# application/vnd.dvb.notif-generic+xml
+# application/vnd.dvb.notif-ia-msglist+xml
+# application/vnd.dvb.notif-ia-registration-request+xml
+# application/vnd.dvb.notif-ia-registration-response+xml
+# application/vnd.dvb.notif-init+xml
+# application/vnd.dvb.pfr
+application/vnd.dvb.service			svc
+# application/vnd.dxr
+application/vnd.dynageo				geo
+# application/vnd.easykaraoke.cdgdownload
+# application/vnd.ecdis-update
+application/vnd.ecowin.chart			mag
+# application/vnd.ecowin.filerequest
+# application/vnd.ecowin.fileupdate
+# application/vnd.ecowin.series
+# application/vnd.ecowin.seriesrequest
+# application/vnd.ecowin.seriesupdate
+# application/vnd.emclient.accessrequest+xml
+application/vnd.enliven				nml
+# application/vnd.eprints.data+xml
+application/vnd.epson.esf			esf
+application/vnd.epson.msf			msf
+application/vnd.epson.quickanime		qam
+application/vnd.epson.salt			slt
+application/vnd.epson.ssf			ssf
+# application/vnd.ericsson.quickcall
+application/vnd.eszigno3+xml			es3 et3
+# application/vnd.etsi.aoc+xml
+# application/vnd.etsi.cug+xml
+# application/vnd.etsi.iptvcommand+xml
+# application/vnd.etsi.iptvdiscovery+xml
+# application/vnd.etsi.iptvprofile+xml
+# application/vnd.etsi.iptvsad-bc+xml
+# application/vnd.etsi.iptvsad-cod+xml
+# application/vnd.etsi.iptvsad-npvr+xml
+# application/vnd.etsi.iptvservice+xml
+# application/vnd.etsi.iptvsync+xml
+# application/vnd.etsi.iptvueprofile+xml
+# application/vnd.etsi.mcid+xml
+# application/vnd.etsi.overload-control-policy-dataset+xml
+# application/vnd.etsi.sci+xml
+# application/vnd.etsi.simservs+xml
+# application/vnd.etsi.tsl+xml
+# application/vnd.etsi.tsl.der
+# application/vnd.eudora.data
+application/vnd.ezpix-album			ez2
+application/vnd.ezpix-package			ez3
+# application/vnd.f-secure.mobile
+application/vnd.fdf				fdf
+application/vnd.fdsn.mseed			mseed
+application/vnd.fdsn.seed			seed dataless
+# application/vnd.ffsns
+# application/vnd.fints
+application/vnd.flographit			gph
+application/vnd.fluxtime.clip			ftc
+# application/vnd.font-fontforge-sfd
+application/vnd.framemaker			fm frame maker book
+application/vnd.frogans.fnc			fnc
+application/vnd.frogans.ltf			ltf
+application/vnd.fsc.weblaunch			fsc
+application/vnd.fujitsu.oasys			oas
+application/vnd.fujitsu.oasys2			oa2
+application/vnd.fujitsu.oasys3			oa3
+application/vnd.fujitsu.oasysgp			fg5
+application/vnd.fujitsu.oasysprs		bh2
+# application/vnd.fujixerox.art-ex
+# application/vnd.fujixerox.art4
+# application/vnd.fujixerox.hbpl
+application/vnd.fujixerox.ddd			ddd
+application/vnd.fujixerox.docuworks		xdw
+application/vnd.fujixerox.docuworks.binder	xbd
+# application/vnd.fut-misnet
+application/vnd.fuzzysheet			fzs
+application/vnd.genomatix.tuxedo		txd
+# application/vnd.geocube+xml
+application/vnd.geogebra.file			ggb
+application/vnd.geogebra.tool			ggt
+application/vnd.geometry-explorer		gex gre
+application/vnd.geonext				gxt
+application/vnd.geoplan				g2w
+application/vnd.geospace			g3w
+# application/vnd.globalplatform.card-content-mgt
+# application/vnd.globalplatform.card-content-mgt-response
+application/vnd.gmx				gmx
+application/vnd.google-earth.kml+xml		kml
+application/vnd.google-earth.kmz		kmz
+application/vnd.grafeq				gqf gqs
+# application/vnd.gridmp
+application/vnd.groove-account			gac
+application/vnd.groove-help			ghf
+application/vnd.groove-identity-message		gim
+application/vnd.groove-injector			grv
+application/vnd.groove-tool-message		gtm
+application/vnd.groove-tool-template		tpl
+application/vnd.groove-vcard			vcg
+# application/vnd.hal+json
+application/vnd.hal+xml				hal
+application/vnd.handheld-entertainment+xml	zmm
+application/vnd.hbci				hbci
+# application/vnd.hcl-bireports
+application/vnd.hhe.lesson-player		les
+application/vnd.hp-hpgl				hpgl
+application/vnd.hp-hpid				hpid
+application/vnd.hp-hps				hps
+application/vnd.hp-jlyt				jlt
+application/vnd.hp-pcl				pcl
+application/vnd.hp-pclxl			pclxl
+# application/vnd.httphone
+application/vnd.hydrostatix.sof-data		sfd-hdstx
+application/vnd.hzn-3d-crossword		x3d
+# application/vnd.ibm.afplinedata
+# application/vnd.ibm.electronic-media
+application/vnd.ibm.minipay			mpy
+application/vnd.ibm.modcap			afp listafp list3820
+application/vnd.ibm.rights-management		irm
+application/vnd.ibm.secure-container		sc
+application/vnd.iccprofile			icc icm
+application/vnd.igloader			igl
+application/vnd.immervision-ivp			ivp
+application/vnd.immervision-ivu			ivu
+# application/vnd.informedcontrol.rms+xml
+# application/vnd.informix-visionary
+# application/vnd.infotech.project
+# application/vnd.infotech.project+xml
+application/vnd.insors.igm			igm
+application/vnd.intercon.formnet		xpw xpx
+application/vnd.intergeo			i2g
+# application/vnd.intertrust.digibox
+# application/vnd.intertrust.nncp
+application/vnd.intu.qbo			qbo
+application/vnd.intu.qfx			qfx
+# application/vnd.iptc.g2.conceptitem+xml
+# application/vnd.iptc.g2.knowledgeitem+xml
+# application/vnd.iptc.g2.newsitem+xml
+# application/vnd.iptc.g2.packageitem+xml
+application/vnd.ipunplugged.rcprofile		rcprofile
+application/vnd.irepository.package+xml		irp
+application/vnd.is-xpr				xpr
+application/vnd.isac.fcs			fcs
+application/vnd.jam				jam
+# application/vnd.japannet-directory-service
+# application/vnd.japannet-jpnstore-wakeup
+# application/vnd.japannet-payment-wakeup
+# application/vnd.japannet-registration
+# application/vnd.japannet-registration-wakeup
+# application/vnd.japannet-setstore-wakeup
+# application/vnd.japannet-verification
+# application/vnd.japannet-verification-wakeup
+application/vnd.jcp.javame.midlet-rms		rms
+application/vnd.jisp				jisp
+application/vnd.joost.joda-archive		joda
+application/vnd.kahootz				ktz ktr
+application/vnd.kde.karbon			karbon
+application/vnd.kde.kchart			chrt
+application/vnd.kde.kformula			kfo
+application/vnd.kde.kivio			flw
+application/vnd.kde.kontour			kon
+application/vnd.kde.kpresenter			kpr kpt
+application/vnd.kde.kspread			ksp
+application/vnd.kde.kword			kwd kwt
+application/vnd.kenameaapp			htke
+application/vnd.kidspiration			kia
+application/vnd.kinar				kne knp
+application/vnd.koan				skp skd skt skm
+application/vnd.kodak-descriptor		sse
+application/vnd.las.las+xml			lasxml
+# application/vnd.liberty-request+xml
+application/vnd.llamagraphics.life-balance.desktop	lbd
+application/vnd.llamagraphics.life-balance.exchange+xml	lbe
+application/vnd.lotus-1-2-3			123
+application/vnd.lotus-approach			apr
+application/vnd.lotus-freelance			pre
+application/vnd.lotus-notes			nsf
+application/vnd.lotus-organizer			org
+application/vnd.lotus-screencam			scm
+application/vnd.lotus-wordpro			lwp
+application/vnd.macports.portpkg		portpkg
+# application/vnd.marlin.drm.actiontoken+xml
+# application/vnd.marlin.drm.conftoken+xml
+# application/vnd.marlin.drm.license+xml
+# application/vnd.marlin.drm.mdcf
+application/vnd.mcd				mcd
+application/vnd.medcalcdata			mc1
+application/vnd.mediastation.cdkey		cdkey
+# application/vnd.meridian-slingshot
+application/vnd.mfer				mwf
+application/vnd.mfmp				mfm
+application/vnd.micrografx.flo			flo
+application/vnd.micrografx.igx			igx
+application/vnd.mif				mif
+# application/vnd.minisoft-hp3000-save
+# application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf			daf
+application/vnd.mobius.dis			dis
+application/vnd.mobius.mbk			mbk
+application/vnd.mobius.mqy			mqy
+application/vnd.mobius.msl			msl
+application/vnd.mobius.plc			plc
+application/vnd.mobius.txf			txf
+application/vnd.mophun.application		mpn
+application/vnd.mophun.certificate		mpc
+# application/vnd.motorola.flexsuite
+# application/vnd.motorola.flexsuite.adsi
+# application/vnd.motorola.flexsuite.fis
+# application/vnd.motorola.flexsuite.gotap
+# application/vnd.motorola.flexsuite.kmr
+# application/vnd.motorola.flexsuite.ttc
+# application/vnd.motorola.flexsuite.wem
+# application/vnd.motorola.iprm
+application/vnd.mozilla.xul+xml			xul
+application/vnd.ms-artgalry			cil
+# application/vnd.ms-asf
+application/vnd.ms-cab-compressed		cab
+application/vnd.ms-excel			xls xlm xla xlc xlt xlw
+application/vnd.ms-excel.addin.macroenabled.12		xlam
+application/vnd.ms-excel.sheet.binary.macroenabled.12	xlsb
+application/vnd.ms-excel.sheet.macroenabled.12		xlsm
+application/vnd.ms-excel.template.macroenabled.12	xltm
+application/vnd.ms-fontobject			eot
+application/vnd.ms-htmlhelp			chm
+application/vnd.ms-ims				ims
+application/vnd.ms-lrm				lrm
+# application/vnd.ms-office.activex+xml
+application/vnd.ms-officetheme			thmx
+application/vnd.ms-pki.seccat			cat
+application/vnd.ms-pki.stl			stl
+# application/vnd.ms-playready.initiator+xml
+application/vnd.ms-powerpoint			ppt pps pot
+application/vnd.ms-powerpoint.addin.macroenabled.12		ppam
+application/vnd.ms-powerpoint.presentation.macroenabled.12	pptm
+application/vnd.ms-powerpoint.slide.macroenabled.12		sldm
+application/vnd.ms-powerpoint.slideshow.macroenabled.12		ppsm
+application/vnd.ms-powerpoint.template.macroenabled.12		potm
+application/vnd.ms-project			mpp mpt
+# application/vnd.ms-tnef
+# application/vnd.ms-wmdrm.lic-chlg-req
+# application/vnd.ms-wmdrm.lic-resp
+# application/vnd.ms-wmdrm.meter-chlg-req
+# application/vnd.ms-wmdrm.meter-resp
+application/vnd.ms-word.document.macroenabled.12	docm
+application/vnd.ms-word.template.macroenabled.12	dotm
+application/vnd.ms-works			wps wks wcm wdb
+application/vnd.ms-wpl				wpl
+application/vnd.ms-xpsdocument			xps
+application/vnd.mseq				mseq
+# application/vnd.msign
+# application/vnd.multiad.creator
+# application/vnd.multiad.creator.cif
+# application/vnd.music-niff
+application/vnd.musician			mus
+application/vnd.muvee.style			msty
+application/vnd.mynfc				taglet
+# application/vnd.ncd.control
+# application/vnd.ncd.reference
+# application/vnd.nervana
+# application/vnd.netfpx
+application/vnd.neurolanguage.nlu		nlu
+application/vnd.noblenet-directory		nnd
+application/vnd.noblenet-sealer			nns
+application/vnd.noblenet-web			nnw
+# application/vnd.nokia.catalogs
+# application/vnd.nokia.conml+wbxml
+# application/vnd.nokia.conml+xml
+# application/vnd.nokia.isds-radio-presets
+# application/vnd.nokia.iptv.config+xml
+# application/vnd.nokia.landmark+wbxml
+# application/vnd.nokia.landmark+xml
+# application/vnd.nokia.landmarkcollection+xml
+# application/vnd.nokia.n-gage.ac+xml
+application/vnd.nokia.n-gage.data		ngdat
+application/vnd.nokia.n-gage.symbian.install	n-gage
+# application/vnd.nokia.ncd
+# application/vnd.nokia.pcd+wbxml
+# application/vnd.nokia.pcd+xml
+application/vnd.nokia.radio-preset		rpst
+application/vnd.nokia.radio-presets		rpss
+application/vnd.novadigm.edm			edm
+application/vnd.novadigm.edx			edx
+application/vnd.novadigm.ext			ext
+# application/vnd.ntt-local.file-transfer
+# application/vnd.ntt-local.sip-ta_remote
+# application/vnd.ntt-local.sip-ta_tcp_stream
+application/vnd.oasis.opendocument.chart		odc
+application/vnd.oasis.opendocument.chart-template	otc
+application/vnd.oasis.opendocument.database		odb
+application/vnd.oasis.opendocument.formula		odf
+application/vnd.oasis.opendocument.formula-template	odft
+application/vnd.oasis.opendocument.graphics		odg
+application/vnd.oasis.opendocument.graphics-template	otg
+application/vnd.oasis.opendocument.image		odi
+application/vnd.oasis.opendocument.image-template	oti
+application/vnd.oasis.opendocument.presentation		odp
+application/vnd.oasis.opendocument.presentation-template	otp
+application/vnd.oasis.opendocument.spreadsheet		ods
+application/vnd.oasis.opendocument.spreadsheet-template	ots
+application/vnd.oasis.opendocument.text			odt
+application/vnd.oasis.opendocument.text-master		odm
+application/vnd.oasis.opendocument.text-template	ott
+application/vnd.oasis.opendocument.text-web		oth
+# application/vnd.obn
+# application/vnd.oftn.l10n+json
+# application/vnd.oipf.contentaccessdownload+xml
+# application/vnd.oipf.contentaccessstreaming+xml
+# application/vnd.oipf.cspg-hexbinary
+# application/vnd.oipf.dae.svg+xml
+# application/vnd.oipf.dae.xhtml+xml
+# application/vnd.oipf.mippvcontrolmessage+xml
+# application/vnd.oipf.pae.gem
+# application/vnd.oipf.spdiscovery+xml
+# application/vnd.oipf.spdlist+xml
+# application/vnd.oipf.ueprofile+xml
+# application/vnd.oipf.userprofile+xml
+application/vnd.olpc-sugar			xo
+# application/vnd.oma-scws-config
+# application/vnd.oma-scws-http-request
+# application/vnd.oma-scws-http-response
+# application/vnd.oma.bcast.associated-procedure-parameter+xml
+# application/vnd.oma.bcast.drm-trigger+xml
+# application/vnd.oma.bcast.imd+xml
+# application/vnd.oma.bcast.ltkm
+# application/vnd.oma.bcast.notification+xml
+# application/vnd.oma.bcast.provisioningtrigger
+# application/vnd.oma.bcast.sgboot
+# application/vnd.oma.bcast.sgdd+xml
+# application/vnd.oma.bcast.sgdu
+# application/vnd.oma.bcast.simple-symbol-container
+# application/vnd.oma.bcast.smartcard-trigger+xml
+# application/vnd.oma.bcast.sprov+xml
+# application/vnd.oma.bcast.stkm
+# application/vnd.oma.cab-address-book+xml
+# application/vnd.oma.cab-feature-handler+xml
+# application/vnd.oma.cab-pcc+xml
+# application/vnd.oma.cab-user-prefs+xml
+# application/vnd.oma.dcd
+# application/vnd.oma.dcdc
+application/vnd.oma.dd2+xml			dd2
+# application/vnd.oma.drm.risd+xml
+# application/vnd.oma.group-usage-list+xml
+# application/vnd.oma.pal+xml
+# application/vnd.oma.poc.detailed-progress-report+xml
+# application/vnd.oma.poc.final-report+xml
+# application/vnd.oma.poc.groups+xml
+# application/vnd.oma.poc.invocation-descriptor+xml
+# application/vnd.oma.poc.optimized-progress-report+xml
+# application/vnd.oma.push
+# application/vnd.oma.scidm.messages+xml
+# application/vnd.oma.xcap-directory+xml
+# application/vnd.omads-email+xml
+# application/vnd.omads-file+xml
+# application/vnd.omads-folder+xml
+# application/vnd.omaloc-supl-init
+application/vnd.openofficeorg.extension		oxt
+# application/vnd.openxmlformats-officedocument.custom-properties+xml
+# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
+# application/vnd.openxmlformats-officedocument.drawing+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
+# application/vnd.openxmlformats-officedocument.extended-properties+xml
+# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
+# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
+# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
+application/vnd.openxmlformats-officedocument.presentationml.presentation	pptx
+# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
+application/vnd.openxmlformats-officedocument.presentationml.slide	sldx
+# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
+application/vnd.openxmlformats-officedocument.presentationml.slideshow	ppsx
+# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
+application/vnd.openxmlformats-officedocument.presentationml.template	potx
+# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet	xlsx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.template	xltx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
+# application/vnd.openxmlformats-officedocument.theme+xml
+# application/vnd.openxmlformats-officedocument.themeoverride+xml
+# application/vnd.openxmlformats-officedocument.vmldrawing
+# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.document	docx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.template	dotx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
+# application/vnd.openxmlformats-package.core-properties+xml
+# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
+# application/vnd.openxmlformats-package.relationships+xml
+# application/vnd.quobject-quoxdocument
+# application/vnd.osa.netdeploy
+application/vnd.osgeo.mapguide.package		mgp
+# application/vnd.osgi.bundle
+application/vnd.osgi.dp				dp
+# application/vnd.otps.ct-kip+xml
+application/vnd.palm				pdb pqa oprc
+# application/vnd.paos.xml
+application/vnd.pawaafile			paw
+application/vnd.pg.format			str
+application/vnd.pg.osasli			ei6
+# application/vnd.piaccess.application-licence
+application/vnd.picsel				efif
+application/vnd.pmi.widget			wg
+# application/vnd.poc.group-advertisement+xml
+application/vnd.pocketlearn			plf
+application/vnd.powerbuilder6			pbd
+# application/vnd.powerbuilder6-s
+# application/vnd.powerbuilder7
+# application/vnd.powerbuilder7-s
+# application/vnd.powerbuilder75
+# application/vnd.powerbuilder75-s
+# application/vnd.preminet
+application/vnd.previewsystems.box		box
+application/vnd.proteus.magazine		mgz
+application/vnd.publishare-delta-tree		qps
+application/vnd.pvi.ptid1			ptid
+# application/vnd.pwg-multiplexed
+# application/vnd.pwg-xhtml-print+xml
+# application/vnd.qualcomm.brew-app-res
+application/vnd.quark.quarkxpress		qxd qxt qwd qwt qxl qxb
+# application/vnd.radisys.moml+xml
+# application/vnd.radisys.msml+xml
+# application/vnd.radisys.msml-audit+xml
+# application/vnd.radisys.msml-audit-conf+xml
+# application/vnd.radisys.msml-audit-conn+xml
+# application/vnd.radisys.msml-audit-dialog+xml
+# application/vnd.radisys.msml-audit-stream+xml
+# application/vnd.radisys.msml-conf+xml
+# application/vnd.radisys.msml-dialog+xml
+# application/vnd.radisys.msml-dialog-base+xml
+# application/vnd.radisys.msml-dialog-fax-detect+xml
+# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
+# application/vnd.radisys.msml-dialog-group+xml
+# application/vnd.radisys.msml-dialog-speech+xml
+# application/vnd.radisys.msml-dialog-transform+xml
+# application/vnd.rainstor.data
+# application/vnd.rapid
+application/vnd.realvnc.bed			bed
+application/vnd.recordare.musicxml		mxl
+application/vnd.recordare.musicxml+xml		musicxml
+# application/vnd.renlearn.rlprint
+application/vnd.rig.cryptonote			cryptonote
+application/vnd.rim.cod				cod
+application/vnd.rn-realmedia			rm
+application/vnd.route66.link66+xml		link66
+# application/vnd.ruckus.download
+# application/vnd.s3sms
+application/vnd.sailingtracker.track		st
+# application/vnd.sbm.cid
+# application/vnd.sbm.mid2
+# application/vnd.scribus
+# application/vnd.sealed.3df
+# application/vnd.sealed.csf
+# application/vnd.sealed.doc
+# application/vnd.sealed.eml
+# application/vnd.sealed.mht
+# application/vnd.sealed.net
+# application/vnd.sealed.ppt
+# application/vnd.sealed.tiff
+# application/vnd.sealed.xls
+# application/vnd.sealedmedia.softseal.html
+# application/vnd.sealedmedia.softseal.pdf
+application/vnd.seemail				see
+application/vnd.sema				sema
+application/vnd.semd				semd
+application/vnd.semf				semf
+application/vnd.shana.informed.formdata		ifm
+application/vnd.shana.informed.formtemplate	itp
+application/vnd.shana.informed.interchange	iif
+application/vnd.shana.informed.package		ipk
+application/vnd.simtech-mindmapper		twd twds
+application/vnd.smaf				mmf
+# application/vnd.smart.notebook
+application/vnd.smart.teacher			teacher
+# application/vnd.software602.filler.form+xml
+# application/vnd.software602.filler.form-xml-zip
+application/vnd.solent.sdkm+xml			sdkm sdkd
+application/vnd.spotfire.dxp			dxp
+application/vnd.spotfire.sfs			sfs
+# application/vnd.sss-cod
+# application/vnd.sss-dtf
+# application/vnd.sss-ntf
+application/vnd.stardivision.calc		sdc
+application/vnd.stardivision.draw		sda
+application/vnd.stardivision.impress		sdd
+application/vnd.stardivision.math		smf
+application/vnd.stardivision.writer		sdw vor
+application/vnd.stardivision.writer-global	sgl
+application/vnd.stepmania.package		smzip
+application/vnd.stepmania.stepchart		sm
+# application/vnd.street-stream
+application/vnd.sun.xml.calc			sxc
+application/vnd.sun.xml.calc.template		stc
+application/vnd.sun.xml.draw			sxd
+application/vnd.sun.xml.draw.template		std
+application/vnd.sun.xml.impress			sxi
+application/vnd.sun.xml.impress.template	sti
+application/vnd.sun.xml.math			sxm
+application/vnd.sun.xml.writer			sxw
+application/vnd.sun.xml.writer.global		sxg
+application/vnd.sun.xml.writer.template		stw
+# application/vnd.sun.wadl+xml
+application/vnd.sus-calendar			sus susp
+application/vnd.svd				svd
+# application/vnd.swiftview-ics
+application/vnd.symbian.install			sis sisx
+application/vnd.syncml+xml			xsm
+application/vnd.syncml.dm+wbxml			bdm
+application/vnd.syncml.dm+xml			xdm
+# application/vnd.syncml.dm.notification
+# application/vnd.syncml.ds.notification
+application/vnd.tao.intent-module-archive	tao
+application/vnd.tcpdump.pcap			pcap cap dmp
+application/vnd.tmobile-livetv			tmo
+application/vnd.trid.tpt			tpt
+application/vnd.triscape.mxs			mxs
+application/vnd.trueapp				tra
+# application/vnd.truedoc
+# application/vnd.ubisoft.webplayer
+application/vnd.ufdl				ufd ufdl
+application/vnd.uiq.theme			utz
+application/vnd.umajin				umj
+application/vnd.unity				unityweb
+application/vnd.uoml+xml			uoml
+# application/vnd.uplanet.alert
+# application/vnd.uplanet.alert-wbxml
+# application/vnd.uplanet.bearer-choice
+# application/vnd.uplanet.bearer-choice-wbxml
+# application/vnd.uplanet.cacheop
+# application/vnd.uplanet.cacheop-wbxml
+# application/vnd.uplanet.channel
+# application/vnd.uplanet.channel-wbxml
+# application/vnd.uplanet.list
+# application/vnd.uplanet.list-wbxml
+# application/vnd.uplanet.listcmd
+# application/vnd.uplanet.listcmd-wbxml
+# application/vnd.uplanet.signal
+application/vnd.vcx				vcx
+# application/vnd.vd-study
+# application/vnd.vectorworks
+# application/vnd.verimatrix.vcas
+# application/vnd.vidsoft.vidconference
+application/vnd.visio				vsd vst vss vsw
+application/vnd.visionary			vis
+# application/vnd.vividence.scriptfile
+application/vnd.vsf				vsf
+# application/vnd.wap.sic
+# application/vnd.wap.slc
+application/vnd.wap.wbxml			wbxml
+application/vnd.wap.wmlc			wmlc
+application/vnd.wap.wmlscriptc			wmlsc
+application/vnd.webturbo			wtb
+# application/vnd.wfa.wsc
+# application/vnd.wmc
+# application/vnd.wmf.bootstrap
+# application/vnd.wolfram.mathematica
+# application/vnd.wolfram.mathematica.package
+application/vnd.wolfram.player			nbp
+application/vnd.wordperfect			wpd
+application/vnd.wqd				wqd
+# application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf				stf
+# application/vnd.wv.csp+wbxml
+# application/vnd.wv.csp+xml
+# application/vnd.wv.ssp+xml
+application/vnd.xara				xar
+application/vnd.xfdl				xfdl
+# application/vnd.xfdl.webform
+# application/vnd.xmi+xml
+# application/vnd.xmpie.cpkg
+# application/vnd.xmpie.dpkg
+# application/vnd.xmpie.plan
+# application/vnd.xmpie.ppkg
+# application/vnd.xmpie.xlim
+application/vnd.yamaha.hv-dic			hvd
+application/vnd.yamaha.hv-script		hvs
+application/vnd.yamaha.hv-voice			hvp
+application/vnd.yamaha.openscoreformat			osf
+application/vnd.yamaha.openscoreformat.osfpvg+xml	osfpvg
+# application/vnd.yamaha.remote-setup
+application/vnd.yamaha.smaf-audio		saf
+application/vnd.yamaha.smaf-phrase		spf
+# application/vnd.yamaha.through-ngn
+# application/vnd.yamaha.tunnel-udpencap
+application/vnd.yellowriver-custom-menu		cmp
+application/vnd.zul				zir zirz
+application/vnd.zzazz.deck+xml			zaz
+application/voicexml+xml			vxml
+# application/vq-rtcpxr
+# application/watcherinfo+xml
+# application/whoispp-query
+# application/whoispp-response
+application/widget				wgt
+application/winhlp				hlp
+# application/wita
+# application/wordperfect5.1
+application/wsdl+xml				wsdl
+application/wspolicy+xml			wspolicy
+application/x-7z-compressed			7z
+application/x-abiword				abw
+application/x-ace-compressed			ace
+application/x-authorware-bin			aab x32 u32 vox
+application/x-authorware-map			aam
+application/x-authorware-seg			aas
+application/x-bcpio				bcpio
+application/x-bittorrent			torrent
+application/x-bzip				bz
+application/x-bzip2				bz2 boz
+application/x-cdlink				vcd
+application/x-chat				chat
+application/x-chess-pgn				pgn
+# application/x-compress
+application/x-cpio				cpio
+application/x-csh				csh
+application/x-debian-package			deb udeb
+application/x-director			dir dcr dxr cst cct cxt w3d fgd swa
+application/x-doom				wad
+application/x-dtbncx+xml			ncx
+application/x-dtbook+xml			dtb
+application/x-dtbresource+xml			res
+application/x-dvi				dvi
+application/x-font-bdf				bdf
+# application/x-font-dos
+# application/x-font-framemaker
+application/x-font-ghostscript			gsf
+# application/x-font-libgrx
+application/x-font-linux-psf			psf
+application/x-font-otf				otf
+application/x-font-pcf				pcf
+application/x-font-snf				snf
+# application/x-font-speedo
+# application/x-font-sunos-news
+application/x-font-ttf				ttf ttc
+application/x-font-type1			pfa pfb pfm afm
+application/x-font-woff				woff
+# application/x-font-vfont
+application/x-futuresplash			spl
+application/x-gnumeric				gnumeric
+application/x-gtar				gtar
+# application/x-gzip
+application/x-hdf				hdf
+application/x-java-jnlp-file			jnlp
+application/x-latex				latex
+application/x-mobipocket-ebook			prc mobi
+application/x-ms-application			application
+application/x-ms-wmd				wmd
+application/x-ms-wmz				wmz
+application/x-ms-xbap				xbap
+application/x-msaccess				mdb
+application/x-msbinder				obd
+application/x-mscardfile			crd
+application/x-msclip				clp
+application/x-msdownload			exe dll com bat msi
+application/x-msmediaview			mvb m13 m14
+application/x-msmetafile			wmf
+application/x-msmoney				mny
+application/x-mspublisher			pub
+application/x-msschedule			scd
+application/x-msterminal			trm
+application/x-mswrite				wri
+application/x-netcdf				nc cdf
+application/x-pkcs12				p12 pfx
+application/x-pkcs7-certificates		p7b spc
+application/x-pkcs7-certreqresp			p7r
+application/x-rar-compressed			rar
+application/x-sh				sh
+application/x-shar				shar
+application/x-shockwave-flash			swf
+application/x-silverlight-app			xap
+application/x-stuffit				sit
+application/x-stuffitx				sitx
+application/x-sv4cpio				sv4cpio
+application/x-sv4crc				sv4crc
+application/x-tar				tar
+application/x-tcl				tcl
+application/x-tex				tex
+application/x-tex-tfm				tfm
+application/x-texinfo				texinfo texi
+application/x-ustar				ustar
+application/x-wais-source			src
+application/x-x509-ca-cert			der crt
+application/x-xfig				fig
+application/x-xpinstall				xpi
+# application/x400-bp
+# application/xcap-att+xml
+# application/xcap-caps+xml
+application/xcap-diff+xml			xdf
+# application/xcap-el+xml
+# application/xcap-error+xml
+# application/xcap-ns+xml
+# application/xcon-conference-info-diff+xml
+# application/xcon-conference-info+xml
+application/xenc+xml				xenc
+application/xhtml+xml				xhtml xht
+# application/xhtml-voice+xml
+application/xml					xml xsl
+application/xml-dtd				dtd
+# application/xml-external-parsed-entity
+# application/xmpp+xml
+application/xop+xml				xop
+application/xslt+xml				xslt
+application/xspf+xml				xspf
+application/xv+xml				mxml xhvml xvml xvm
+application/yang				yang
+application/yin+xml				yin
+application/zip					zip
+# audio/1d-interleaved-parityfec
+# audio/32kadpcm
+# audio/3gpp
+# audio/3gpp2
+# audio/ac3
+audio/adpcm					adp
+# audio/amr
+# audio/amr-wb
+# audio/amr-wb+
+# audio/asc
+# audio/atrac-advanced-lossless
+# audio/atrac-x
+# audio/atrac3
+audio/basic					au snd
+# audio/bv16
+# audio/bv32
+# audio/clearmode
+# audio/cn
+# audio/dat12
+# audio/dls
+# audio/dsr-es201108
+# audio/dsr-es202050
+# audio/dsr-es202211
+# audio/dsr-es202212
+# audio/dv
+# 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/fwdred
+# audio/g719
+# audio/g722
+# audio/g7221
+# audio/g723
+# audio/g726-16
+# audio/g726-24
+# audio/g726-32
+# audio/g726-40
+# audio/g728
+# audio/g729
+# audio/g7291
+# audio/g729d
+# audio/g729e
+# audio/gsm
+# audio/gsm-efr
+# audio/gsm-hr-08
+# audio/ilbc
+# audio/ip-mr_v2.5
+# audio/l16
+# audio/l20
+# audio/l24
+# audio/l8
+# audio/lpc
+audio/midi					mid midi kar rmi
+# audio/mobile-xmf
+audio/mp4					mp4a
+# audio/mp4a-latm
+# audio/mpa
+# audio/mpa-robust
+audio/mpeg					mpga mp2 mp2a mp3 m2a m3a
+# audio/mpeg4-generic
+audio/ogg					oga ogg spx
+# audio/parityfec
+# audio/pcma
+# audio/pcma-wb
+# audio/pcmu-wb
+# audio/pcmu
+# audio/prs.sid
+# audio/qcelp
+# audio/red
+# audio/rtp-enc-aescm128
+# audio/rtp-midi
+# audio/rtx
+# audio/smv
+# audio/smv0
+# audio/smv-qcp
+# audio/sp-midi
+# audio/speex
+# audio/t140c
+# audio/t38
+# audio/telephone-event
+# audio/tone
+# audio/uemclip
+# audio/ulpfec
+# audio/vdvi
+# audio/vmr-wb
+# audio/vnd.3gpp.iufp
+# audio/vnd.4sb
+# audio/vnd.audiokoz
+# audio/vnd.celp
+# audio/vnd.cisco.nse
+# audio/vnd.cmles.radio-events
+# audio/vnd.cns.anp1
+# audio/vnd.cns.inf1
+audio/vnd.dece.audio				uva uvva
+audio/vnd.digital-winds				eol
+# audio/vnd.dlna.adts
+# audio/vnd.dolby.heaac.1
+# audio/vnd.dolby.heaac.2
+# audio/vnd.dolby.mlp
+# audio/vnd.dolby.mps
+# audio/vnd.dolby.pl2
+# audio/vnd.dolby.pl2x
+# audio/vnd.dolby.pl2z
+# audio/vnd.dolby.pulse.1
+audio/vnd.dra					dra
+audio/vnd.dts					dts
+audio/vnd.dts.hd				dtshd
+# audio/vnd.dvb.file				dvb
+# audio/vnd.everad.plj
+# audio/vnd.hns.audio
+audio/vnd.lucent.voice				lvp
+audio/vnd.ms-playready.media.pya		pya
+# audio/vnd.nokia.mobile-xmf
+# audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800			ecelp4800
+audio/vnd.nuera.ecelp7470			ecelp7470
+audio/vnd.nuera.ecelp9600			ecelp9600
+# audio/vnd.octel.sbc
+# audio/vnd.qcelp
+# audio/vnd.rhetorex.32kadpcm
+audio/vnd.rip					rip
+# audio/vnd.sealedmedia.softseal.mpeg
+# audio/vnd.vmx.cvsd
+# audio/vorbis
+# audio/vorbis-config
+audio/webm					weba
+audio/x-aac					aac
+audio/x-aiff					aif aiff aifc
+audio/x-mpegurl					m3u
+audio/x-ms-wax					wax
+audio/x-ms-wma					wma
+audio/x-pn-realaudio				ram ra
+audio/x-pn-realaudio-plugin			rmp
+audio/x-wav					wav
+chemical/x-cdx					cdx
+chemical/x-cif					cif
+chemical/x-cmdf					cmdf
+chemical/x-cml					cml
+chemical/x-csml					csml
+# chemical/x-pdb
+chemical/x-xyz					xyz
+image/bmp					bmp
+image/cgm					cgm
+# image/example
+# image/fits
+image/g3fax					g3
+image/gif					gif
+image/ief					ief
+# image/jp2
+image/jpeg					jpeg jpg jpe
+# image/jpm
+# image/jpx
+image/ktx					ktx
+# image/naplps
+image/png					png
+image/prs.btif					btif
+# image/prs.pti
+image/svg+xml					svg svgz
+# image/t38
+image/tiff					tiff tif
+# image/tiff-fx
+image/vnd.adobe.photoshop			psd
+# image/vnd.cns.inf2
+image/vnd.dece.graphic				uvi uvvi uvg uvvg
+image/vnd.dvb.subtitle				sub
+image/vnd.djvu					djvu djv
+image/vnd.dwg					dwg
+image/vnd.dxf					dxf
+image/vnd.fastbidsheet				fbs
+image/vnd.fpx					fpx
+image/vnd.fst					fst
+image/vnd.fujixerox.edmics-mmr			mmr
+image/vnd.fujixerox.edmics-rlc			rlc
+# image/vnd.globalgraphics.pgb
+# image/vnd.microsoft.icon
+# image/vnd.mix
+image/vnd.ms-modi				mdi
+image/vnd.net-fpx				npx
+# image/vnd.radiance
+# image/vnd.sealed.png
+# image/vnd.sealedmedia.softseal.gif
+# image/vnd.sealedmedia.softseal.jpg
+# image/vnd.svf
+image/vnd.wap.wbmp				wbmp
+image/vnd.xiff					xif
+image/webp					webp
+image/x-cmu-raster				ras
+image/x-cmx					cmx
+image/x-freehand				fh fhc fh4 fh5 fh7
+image/x-icon					ico
+image/x-pcx					pcx
+image/x-pict					pic pct
+image/x-portable-anymap				pnm
+image/x-portable-bitmap				pbm
+image/x-portable-graymap			pgm
+image/x-portable-pixmap				ppm
+image/x-rgb					rgb
+image/x-xbitmap					xbm
+image/x-xpixmap					xpm
+image/x-xwindowdump				xwd
+# message/cpim
+# message/delivery-status
+# message/disposition-notification
+# message/example
+# message/external-body
+# message/feedback-report
+# message/global
+# message/global-delivery-status
+# message/global-disposition-notification
+# message/global-headers
+# message/http
+# message/imdn+xml
+# message/news
+# message/partial
+message/rfc822					eml mime
+# message/s-http
+# message/sip
+# message/sipfrag
+# message/tracking-status
+# message/vnd.si.simp
+# model/example
+model/iges					igs iges
+model/mesh					msh mesh silo
+model/vnd.collada+xml				dae
+model/vnd.dwf					dwf
+# model/vnd.flatland.3dml
+model/vnd.gdl					gdl
+# model/vnd.gs-gdl
+# model/vnd.gs.gdl
+model/vnd.gtw					gtw
+# model/vnd.moml+xml
+model/vnd.mts					mts
+# model/vnd.parasolid.transmit.binary
+# model/vnd.parasolid.transmit.text
+model/vnd.vtu					vtu
+model/vrml					wrl vrml
+# multipart/alternative
+# multipart/appledouble
+# multipart/byteranges
+# multipart/digest
+# multipart/encrypted
+# multipart/example
+# multipart/form-data
+# multipart/header-set
+# multipart/mixed
+# multipart/parallel
+# multipart/related
+# multipart/report
+# multipart/signed
+# multipart/voice-message
+# text/1d-interleaved-parityfec
+text/calendar					ics ifb
+text/css					css
+text/csv					csv
+# text/directory
+# text/dns
+# text/ecmascript
+# text/enriched
+# text/example
+# text/fwdred
+text/html					html htm
+# text/javascript
+text/n3						n3
+# text/parityfec
+text/plain					txt text conf def list log in
+# text/prs.fallenstein.rst
+text/prs.lines.tag				dsc
+# text/vnd.radisys.msml-basic-layout
+# text/red
+# text/rfc822-headers
+text/richtext					rtx
+# text/rtf
+# text/rtp-enc-aescm128
+# text/rtx
+text/sgml					sgml sgm
+# text/t140
+text/tab-separated-values			tsv
+text/troff					t tr roff man me ms
+text/turtle					ttl
+# text/ulpfec
+text/uri-list					uri uris urls
+text/vcard					vcard
+# 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.dvb.subtitle				sub
+# text/vnd.esmertec.theme-descriptor
+text/vnd.fly					fly
+text/vnd.fmi.flexstor				flx
+text/vnd.graphviz				gv
+text/vnd.in3d.3dml				3dml
+text/vnd.in3d.spot				spot
+# text/vnd.iptc.newsml
+# text/vnd.iptc.nitf
+# text/vnd.latex-z
+# text/vnd.motorola.reflex
+# text/vnd.ms-mediapackage
+# text/vnd.net2phone.commcenter.command
+# text/vnd.si.uricatalogue
+text/vnd.sun.j2me.app-descriptor		jad
+# text/vnd.trolltech.linguist
+# text/vnd.wap.si
+# text/vnd.wap.sl
+text/vnd.wap.wml				wml
+text/vnd.wap.wmlscript				wmls
+text/x-asm					s asm
+text/x-c					c cc cxx cpp h hh dic
+text/x-fortran					f for f77 f90
+text/x-pascal					p pas
+text/x-java-source				java
+text/x-setext					etx
+text/x-uuencode					uu
+text/x-vcalendar				vcs
+text/x-vcard					vcf
+# text/xml
+# text/xml-external-parsed-entity
+# video/1d-interleaved-parityfec
+video/3gpp					3gp
+# video/3gpp-tt
+video/3gpp2					3g2
+# video/bmpeg
+# video/bt656
+# video/celb
+# video/dv
+# video/example
+video/h261					h261
+video/h263					h263
+# video/h263-1998
+# video/h263-2000
+video/h264					h264
+# video/h264-rcdo
+# video/h264-svc
+video/jpeg					jpgv
+# video/jpeg2000
+video/jpm					jpm jpgm
+video/mj2					mj2 mjp2
+# video/mp1s
+# video/mp2p
+# video/mp2t
+video/mp4					mp4 mp4v mpg4
+# video/mp4v-es
+video/mpeg					mpeg mpg mpe m1v m2v
+# video/mpeg4-generic
+# video/mpv
+# video/nv
+video/ogg					ogv
+# video/parityfec
+# video/pointer
+video/quicktime					qt mov
+# video/raw
+# video/rtp-enc-aescm128
+# video/rtx
+# video/smpte292m
+# video/ulpfec
+# video/vc1
+# video/vnd.cctv
+video/vnd.dece.hd				uvh uvvh
+video/vnd.dece.mobile				uvm uvvm
+# video/vnd.dece.mp4
+video/vnd.dece.pd				uvp uvvp
+video/vnd.dece.sd				uvs uvvs
+video/vnd.dece.video				uvv uvvv
+# video/vnd.directv.mpeg
+# video/vnd.directv.mpeg-tts
+# video/vnd.dlna.mpeg-tts
+video/vnd.dvb.file				dvb
+video/vnd.fvt					fvt
+# video/vnd.hns.video
+# video/vnd.iptvforum.1dparityfec-1010
+# video/vnd.iptvforum.1dparityfec-2005
+# video/vnd.iptvforum.2dparityfec-1010
+# video/vnd.iptvforum.2dparityfec-2005
+# video/vnd.iptvforum.ttsavc
+# video/vnd.iptvforum.ttsmpeg2
+# video/vnd.motorola.video
+# video/vnd.motorola.videop
+video/vnd.mpegurl				mxu m4u
+video/vnd.ms-playready.media.pyv		pyv
+# video/vnd.nokia.interleaved-multimedia
+# video/vnd.nokia.videovoip
+# video/vnd.objectvideo
+# video/vnd.sealed.mpeg1
+# video/vnd.sealed.mpeg4
+# video/vnd.sealed.swf
+# video/vnd.sealedmedia.softseal.mov
+video/vnd.uvvu.mp4				uvu uvvu
+video/vnd.vivo					viv
+video/webm					webm
+video/x-f4v					f4v
+video/x-fli					fli
+video/x-flv					flv
+video/x-m4v					m4v
+video/x-ms-asf					asf asx
+video/x-ms-wm					wm
+video/x-ms-wmv					wmv
+video/x-ms-wmx					wmx
+video/x-ms-wvx					wvx
+video/x-msvideo					avi
+video/x-sgi-movie				movie
+x-conference/x-cooltalk				ice
Index: Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/types/node.types
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/types/node.types	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/node_modules/mime/types/node.types	(revision 484)
@@ -0,0 +1,65 @@
+# What: Google Chrome Extension
+# Why: To allow apps to (work) be served with the right content type header.
+# http://codereview.chromium.org/2830017
+# Added by: niftylettuce
+application/x-chrome-extension  crx
+
+# What: OTF Message Silencer
+# Why: To silence the "Resource interpreted as font but transferred with MIME
+# type font/otf" message that occurs in Google Chrome
+# Added by: niftylettuce
+font/opentype  otf
+
+# What: HTC support
+# Why: To properly render .htc files such as CSS3PIE
+# Added by: niftylettuce
+text/x-component  htc
+
+# What: HTML5 application cache manifest
+# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
+# per https://developer.mozilla.org/en/offline_resources_in_firefox
+# Added by: louisremi
+text/cache-manifest  appcache manifest
+
+# What: node binary buffer format
+# Why: semi-standard extension w/in the node community
+# Added by: tootallnate
+application/octet-stream  buffer
+
+# What: The "protected" MP-4 formats used by iTunes.
+# Why: Required for streaming music to browsers (?)
+# Added by: broofa
+application/mp4  m4p
+audio/mp4  m4a
+
+# What: Music playlist format (http://en.wikipedia.org/wiki/M3U)
+# Why: See https://github.com/bentomas/node-mime/pull/6
+# Added by: mjrusso
+application/x-mpegURL  m3u8
+
+# What: Video format, Part of RFC1890
+# Why: See https://github.com/bentomas/node-mime/pull/6
+# Added by: mjrusso
+video/MP2T  ts
+
+# What: The FLAC lossless codec format
+# Why: Streaming and serving FLAC audio
+# Added by: jacobrask
+audio/flac  flac
+
+# What: EventSource mime type
+# Why: mime type of Server-Sent Events stream
+# http://www.w3.org/TR/eventsource/#text-event-stream
+# Added by: francois2metz
+text/event-stream  event-stream
+
+# What: Mozilla App manifest mime type
+# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests
+# Added by: ednapiranha
+application/x-web-app-manifest+json   webapp
+
+# What: Matroska Mime Types
+# Why: http://en.wikipedia.org/wiki/Matroska
+# Added by: aduncan88
+video/x-matroska    mkv
+audio/x-matroska    mka
Index: Dev/trunk/src/node_modules/express/node_modules/send/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/node_modules/send/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/node_modules/send/package.json	(revision 484)
@@ -0,0 +1,34 @@
+{
+  "name": "send",
+  "version": "0.1.0",
+  "description": "Better streaming static file server with Range and conditional-GET support",
+  "keywords": [
+    "static",
+    "file",
+    "server"
+  ],
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca"
+  },
+  "dependencies": {
+    "debug": "*",
+    "mime": "1.2.6",
+    "fresh": "0.1.0",
+    "range-parser": "0.0.4"
+  },
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*",
+    "supertest": "0.0.1",
+    "connect": "2.x"
+  },
+  "scripts": {
+    "test": "make test"
+  },
+  "main": "index",
+  "readme": "\n# send\n\n  Send is Connect's `static()` extracted for generalized use, a streaming static file\n  server supporting partial responses (Ranges), conditional-GET negotiation, high test coverage, and granular events which may be leveraged to take appropriate actions in your application or framework.\n\n## Installation\n\n    $ npm install send\n\n## Examples\n\n  Small:\n\n```js\nvar http = require('http');\nvar send = require('send');\n\nvar app = http.createServer(function(req, res){\n  send(req, req.url).pipe(res);\n});\n```\n\n  Serving from a root directory with custom error-handling:\n\n```js\nvar http = require('http');\nvar send = require('send');\n\nvar app = http.createServer(function(req, res){\n  // your custom error-handling logic:\n  function error(err) {\n    res.statusCode = err.status || 500;\n    res.end(err.message);\n  }\n\n  // your custom directory handling logic:\n  function redirect() {\n    res.statusCode = 301;\n    res.setHeader('Location', req.url + '/');\n    res.end('Redirecting to ' + req.url + '/');\n  }\n\n  // transfer arbitrary files from within\n  // /www/example.com/public/*\n  send(req, url.parse(req.url).pathname)\n  .root('/www/example.com/public')\n  .on('error', error)\n  .on('directory', redirect)\n  .pipe(res);\n});\n```\n\n## API\n\n### Events\n\n  - `error` an error occurred `(err)`\n  - `directory` a directory was requested\n  - `stream` file streaming has started `(stream)`\n  - `end` streaming has completed\n\n### .root(dir)\n\n  Serve files relative to `path`. Aliased as `.from(dir)`.\n\n### .index(path)\n\n  By default send supports \"index.html\" files, to disable this\n  invoke `.index(false)` or to supply a new index pass a string.\n\n### .maxage(ms)\n\n  Provide a max-age in milliseconds for http caching, defaults to 0.\n\n## Error-handling\n\n  By default when no `error` listeners are present an automatic response will be made, otherwise you have full control over the response, aka you may show a 5xx page etc.\n\n## Caching\n\n  It does _not_ perform internal caching, you should use a reverse proxy cache such\n  as Varnish for this, or those fancy things called CDNs. If your application is small enough that it would benefit from single-node memory caching, it's small enough that it does not need caching at all ;).\n\n## Debugging\n\n To enable `debug()` instrumentation output export __DEBUG__:\n\n```\n$ DEBUG=send node app\n```\n\n## Running tests\n\n```\n$ npm install\n$ make test\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
+  "readmeFilename": "Readme.md",
+  "_id": "send@0.1.0",
+  "_from": "send@0.1.0"
+}
Index: Dev/trunk/src/node_modules/express/package.json
===================================================================
--- Dev/trunk/src/node_modules/express/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/express/package.json	(revision 484)
@@ -0,0 +1,84 @@
+{
+  "name": "express",
+  "description": "Sinatra inspired web development framework",
+  "version": "3.2.6",
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca"
+  },
+  "contributors": [
+    {
+      "name": "TJ Holowaychuk",
+      "email": "tj@vision-media.ca"
+    },
+    {
+      "name": "Aaron Heckmann",
+      "email": "aaron.heckmann+github@gmail.com"
+    },
+    {
+      "name": "Ciaran Jessup",
+      "email": "ciaranj@gmail.com"
+    },
+    {
+      "name": "Guillermo Rauch",
+      "email": "rauchg@gmail.com"
+    }
+  ],
+  "dependencies": {
+    "connect": "2.7.11",
+    "commander": "0.6.1",
+    "range-parser": "0.0.4",
+    "mkdirp": "0.3.4",
+    "cookie": "0.1.0",
+    "buffer-crc32": "0.2.1",
+    "fresh": "0.1.0",
+    "methods": "0.0.1",
+    "send": "0.1.0",
+    "cookie-signature": "1.0.1",
+    "debug": "*"
+  },
+  "devDependencies": {
+    "ejs": "*",
+    "mocha": "*",
+    "jade": "*",
+    "hjs": "*",
+    "stylus": "*",
+    "should": "*",
+    "connect-redis": "*",
+    "marked": "*",
+    "supertest": "0.6.0"
+  },
+  "keywords": [
+    "express",
+    "framework",
+    "sinatra",
+    "web",
+    "rest",
+    "restful",
+    "router",
+    "app",
+    "api"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/express"
+  },
+  "main": "index",
+  "bin": {
+    "express": "./bin/express"
+  },
+  "scripts": {
+    "prepublish": "npm prune",
+    "test": "make test"
+  },
+  "engines": {
+    "node": "*"
+  },
+  "readme": "![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png)\n\n  Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express) [![Dependency Status](https://gemnasium.com/visionmedia/express.png)](https://gemnasium.com/visionmedia/express)\n\n```js\nvar express = require('express');\nvar app = express();\n\napp.get('/', function(req, res){\n  res.send('Hello World');\n});\n\napp.listen(3000);\n```\n\n## Installation\n\n    $ npm install -g express\n\n## Quick Start\n\n The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:\n\n Create the app:\n\n    $ npm install -g express\n    $ express /tmp/foo && cd /tmp/foo\n\n Install dependencies:\n\n    $ npm install\n\n Start the server:\n\n    $ node app\n\n## Features\n\n  * Built on [Connect](http://github.com/senchalabs/connect)\n  * Robust routing\n  * HTTP helpers (redirection, caching, etc)\n  * View system supporting 14+ template engines\n  * Content negotiation\n  * Focus on high performance\n  * Environment based configuration\n  * Executable for generating applications quickly\n  * High test coverage\n\n## Philosophy\n\n  The Express philosophy is to provide small, robust tooling for HTTP servers. Making\n  it a great solution for single page applications, web sites, hybrids, or public\n  HTTP APIs.\n\n  Built on Connect you can use _only_ what you need, and nothing more, applications\n  can be as big or as small as you like, even a single file. Express does\n  not force you to use any specific ORM or template engine. With support for over\n  14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js)\n  you can quickly craft your perfect framework.\n\n## More Information\n\n  * Join #express on freenode\n  * [Google Group](http://groups.google.com/group/express-js) for discussion\n  * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates\n  * Visit the [Wiki](http://github.com/visionmedia/express/wiki)\n  * [Ð ÑÑÑÐºÐŸÑÐ·ÑÑÐœÐ°Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÑ](http://jsman.ru/express/)\n  * Run express examples [online](https://runnable.com/express)\n\n## Viewing Examples\n\nClone the Express repo, then install the dev dependencies to install all the example / test suite deps:\n\n    $ git clone git://github.com/visionmedia/express.git --depth 1\n    $ cd express\n    $ npm install\n\nthen run whichever tests you want:\n\n    $ node examples/content-negotiation\n\n## Running Tests\n\nTo run the test suite first invoke the following command within the repo, installing the development dependencies:\n\n    $ npm install\n\nthen run the tests:\n\n    $ make test\n\n## Contributors\n\n```\nproject: express\ncommits: 3559\nactive : 468 days\nfiles  : 237\nauthors:\n 1891\tTj Holowaychuk          53.1%\n 1285\tvisionmedia             36.1%\n  182\tTJ Holowaychuk          5.1%\n   54\tAaron Heckmann          1.5%\n   34\tcsausdev                1.0%\n   26\tciaranj                 0.7%\n   21\tRobert SkÃ¶ld            0.6%\n    6\tGuillermo Rauch         0.2%\n    3\tDav Glass               0.1%\n    3\tNick Poulden            0.1%\n    2\tRandy Merrill           0.1%\n    2\tBenny Wong              0.1%\n    2\tHunter Loftis           0.1%\n    2\tJake Gordon             0.1%\n    2\tBrian McKinney          0.1%\n    2\tRoman Shtylman          0.1%\n    2\tBen Weaver              0.1%\n    2\tDave Hoover             0.1%\n    2\tEivind Fjeldstad        0.1%\n    2\tDaniel Shaw             0.1%\n    1\tMatt Colyer             0.0%\n    1\tPau Ramon               0.0%\n    1\tPero Pejovic            0.0%\n    1\tPeter Rekdal Sunde      0.0%\n    1\tRaynos                  0.0%\n    1\tTeng Siong Ong          0.0%\n    1\tViktor Kelemen          0.0%\n    1\tctide                   0.0%\n    1\t8bitDesigner            0.0%\n    1\tisaacs                  0.0%\n    1\tmgutz                   0.0%\n    1\tpikeas                  0.0%\n    1\tshuwatto                0.0%\n    1\ttstrimple               0.0%\n    1\tewoudj                  0.0%\n    1\tAdam Sanderson          0.0%\n    1\tAndrii Kostenko         0.0%\n    1\tAndy Hiew               0.0%\n    1\tArpad Borsos            0.0%\n    1\tAshwin Purohit          0.0%\n    1\tBenjen                  0.0%\n    1\tDarren Torpey           0.0%\n    1\tGreg Ritter             0.0%\n    1\tGregory Ritter          0.0%\n    1\tJames Herdman           0.0%\n    1\tJim Snodgrass           0.0%\n    1\tJoe McCann              0.0%\n    1\tJonathan Dumaine        0.0%\n    1\tJonathan Palardy        0.0%\n    1\tJonathan Zacsh          0.0%\n    1\tJustin Lilly            0.0%\n    1\tKen Sato                0.0%\n    1\tMaciej MaÅecki          0.0%\n    1\tMasahiro Hayashi        0.0%\n```\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2009-2012 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/visionmedia/express/issues"
+  },
+  "_id": "express@3.2.6",
+  "_from": "express@~3.2.3"
+}
Index: Dev/trunk/src/node_modules/express/test.js
===================================================================
--- Dev/trunk/src/node_modules/express/test.js	(revision 484)
+++ Dev/trunk/src/node_modules/express/test.js	(revision 484)
@@ -0,0 +1,17 @@
+var express = require('./');
+var app = express();
+
+express.request.toJSON = function(){
+  return {
+    method: this.method,
+    url: this.url,
+    header: this.headers
+  }
+};
+
+app.get('*', function(req, res){
+  console.log(JSON.stringify(req));
+  res.send(200);
+});
+
+app.listen(4000)
Index: Dev/trunk/src/node_modules/passport-local/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/passport-local/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/.npmignore	(revision 484)
@@ -0,0 +1,8 @@
+*.md
+.DS_Store
+.git*
+Makefile
+docs/
+examples/
+support/
+test/
Index: Dev/trunk/src/node_modules/passport-local/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/passport-local/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/.travis.yml	(revision 484)
@@ -0,0 +1,4 @@
+language: "node_js"
+node_js:
+  - 0.4
+  - 0.6
Index: Dev/trunk/src/node_modules/passport-local/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/passport-local/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/LICENSE	(revision 484)
@@ -0,0 +1,20 @@
+(The MIT License)
+
+Copyright (c) 2011 Jared Hanson
+
+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.
Index: Dev/trunk/src/node_modules/passport-local/lib/passport-local/errors/badrequesterror.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/lib/passport-local/errors/badrequesterror.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/lib/passport-local/errors/badrequesterror.js	(revision 484)
@@ -0,0 +1,22 @@
+/**
+ * `BadRequestError` error.
+ *
+ * @api public
+ */
+function BadRequestError(message) {
+  Error.call(this);
+  Error.captureStackTrace(this, arguments.callee);
+  this.name = 'BadRequestError';
+  this.message = message || null;
+};
+
+/**
+ * Inherit from `Error`.
+ */
+BadRequestError.prototype.__proto__ = Error.prototype;
+
+
+/**
+ * Expose `BadRequestError`.
+ */
+module.exports = BadRequestError;
Index: Dev/trunk/src/node_modules/passport-local/lib/passport-local/index.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/lib/passport-local/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/lib/passport-local/index.js	(revision 484)
@@ -0,0 +1,18 @@
+/**
+ * Module dependencies.
+ */
+var Strategy = require('./strategy')
+  , BadRequestError = require('./errors/badrequesterror');
+
+
+/**
+ * Framework version.
+ */
+require('pkginfo')(module, 'version');
+
+/**
+ * Expose constructors.
+ */
+exports.Strategy = Strategy;
+
+exports.BadRequestError = BadRequestError;
Index: Dev/trunk/src/node_modules/passport-local/lib/passport-local/strategy.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/lib/passport-local/strategy.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/lib/passport-local/strategy.js	(revision 484)
@@ -0,0 +1,109 @@
+/**
+ * Module dependencies.
+ */
+var passport = require('passport')
+  , util = require('util')
+  , BadRequestError = require('./errors/badrequesterror');
+
+
+/**
+ * `Strategy` constructor.
+ *
+ * The local authentication strategy authenticates requests based on the
+ * credentials submitted through an HTML-based login form.
+ *
+ * Applications must supply a `verify` callback which accepts `username` and
+ * `password` credentials, and then calls the `done` callback supplying a
+ * `user`, which should be set to `false` if the credentials are not valid.
+ * If an exception occured, `err` should be set.
+ *
+ * Optionally, `options` can be used to change the fields in which the
+ * credentials are found.
+ *
+ * Options:
+ *   - `usernameField`  field name where the username is found, defaults to _username_
+ *   - `passwordField`  field name where the password is found, defaults to _password_
+ *   - `passReqToCallback`  when `true`, `req` is the first argument to the verify callback (default: `false`)
+ *
+ * Examples:
+ *
+ *     passport.use(new LocalStrategy(
+ *       function(username, password, done) {
+ *         User.findOne({ username: username, password: password }, function (err, user) {
+ *           done(err, user);
+ *         });
+ *       }
+ *     ));
+ *
+ * @param {Object} options
+ * @param {Function} verify
+ * @api public
+ */
+function Strategy(options, verify) {
+  if (typeof options == 'function') {
+    verify = options;
+    options = {};
+  }
+  if (!verify) throw new Error('local authentication strategy requires a verify function');
+  
+  this._usernameField = options.usernameField || 'username';
+  this._passwordField = options.passwordField || 'password';
+  
+  passport.Strategy.call(this);
+  this.name = 'local';
+  this._verify = verify;
+  this._passReqToCallback = options.passReqToCallback;
+}
+
+/**
+ * Inherit from `passport.Strategy`.
+ */
+util.inherits(Strategy, passport.Strategy);
+
+/**
+ * Authenticate request based on the contents of a form submission.
+ *
+ * @param {Object} req
+ * @api protected
+ */
+Strategy.prototype.authenticate = function(req, options) {
+  options = options || {};
+  var username = lookup(req.body, this._usernameField) || lookup(req.query, this._usernameField);
+  var password = lookup(req.body, this._passwordField) || lookup(req.query, this._passwordField);
+  
+  if (!username || !password) {
+    return this.fail(new BadRequestError(options.badRequestMessage || 'Missing credentials'));
+  }
+  
+  var self = this;
+  
+  function verified(err, user, info) {
+    if (err) { return self.error(err); }
+    if (!user) { return self.fail(info); }
+    self.success(user, info);
+  }
+  
+  if (self._passReqToCallback) {
+    this._verify(req, username, password, verified);
+  } else {
+    this._verify(username, password, verified);
+  }
+  
+  function lookup(obj, field) {
+    if (!obj) { return null; }
+    var chain = field.split(']').join('').split('[');
+    for (var i = 0, len = chain.length; i < len; i++) {
+      var prop = obj[chain[i]];
+      if (typeof(prop) === 'undefined') { return null; }
+      if (typeof(prop) !== 'object') { return prop; }
+      obj = prop;
+    }
+    return null;
+  }
+}
+
+
+/**
+ * Expose `Strategy`.
+ */ 
+module.exports = Strategy;
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/.npmignore	(revision 484)
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/README.md
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/README.md	(revision 484)
@@ -0,0 +1,85 @@
+# node-pkginfo
+
+An easy way to expose properties on a module from a package.json
+
+## Installation
+
+### Installing npm (node package manager)
+```
+  curl http://npmjs.org/install.sh | sh
+```
+
+### Installing pkginfo
+```
+  [sudo] npm install pkginfo
+```
+
+## Motivation
+How often when writing node.js modules have you written the following line(s) of code? 
+
+* Hard code your version string into your code
+
+``` js
+  exports.version = '0.1.0';
+```
+
+* Programmatically expose the version from the package.json
+
+``` js
+  exports.version = JSON.parse(fs.readFileSync('/path/to/package.json', 'utf8')).version;
+```
+
+In other words, how often have you wanted to expose basic information from your package.json onto your module programmatically? **WELL NOW YOU CAN!**
+
+## Usage
+
+Using `pkginfo` is idiot-proof, just require and invoke it. 
+
+``` js
+  var pkginfo = require('pkginfo')(module);
+  
+  console.dir(module.exports);
+```
+
+By invoking the `pkginfo` module all of the properties in your `package.json` file will be automatically exposed on the callee module (i.e. the parent module of `pkginfo`). 
+
+Here's a sample of the output:
+
+```
+  { name: 'simple-app',
+    description: 'A test fixture for pkginfo',
+    version: '0.1.0',
+    author: 'Charlie Robbins <charlie.robbins@gmail.com>',
+    keywords: [ 'test', 'fixture' ],
+    main: './index.js',
+    scripts: { test: 'vows test/*-test.js --spec' },
+    engines: { node: '>= 0.4.0' } }
+```
+
+### Expose specific properties
+If you don't want to expose **all** properties on from your `package.json` on your module then simple pass those properties to the `pkginfo` function:
+
+``` js
+  var pkginfo = require('pkginfo')(module, 'version', 'author');
+  
+  console.dir(module.exports);
+```
+
+```
+  { version: '0.1.0',
+    author: 'Charlie Robbins <charlie.robbins@gmail.com>' }
+```
+
+If you're looking for further usage see the [examples][0] included in this repository. 
+
+## Run Tests
+Tests are written in [vows][1] and give complete coverage of all APIs.
+
+```
+  vows test/*-test.js --spec
+```
+
+[0]: https://github.com/indexzero/node-pkginfo/tree/master/examples
+[1]: http://vowsjs.org
+
+#### Author: [Charlie Robbins](http://nodejitsu.com)
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/docs/docco.css
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/docs/docco.css	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/docs/docco.css	(revision 484)
@@ -0,0 +1,194 @@
+/*--------------------- Layout and Typography ----------------------------*/
+body {
+  font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
+  font-size: 15px;
+  line-height: 22px;
+  color: #252519;
+  margin: 0; padding: 0;
+}
+a {
+  color: #261a3b;
+}
+  a:visited {
+    color: #261a3b;
+  }
+p {
+  margin: 0 0 15px 0;
+}
+h4, h5, h6 {
+  color: #333;
+  margin: 6px 0 6px 0;
+  font-size: 13px;
+}
+  h2, h3 {
+    margin-bottom: 0;
+    color: #000;
+  }
+    h1 {
+      margin-top: 40px;
+      margin-bottom: 15px;
+      color: #000;
+    }
+#container {
+  position: relative;
+}
+#background {
+  position: fixed;
+  top: 0; left: 525px; right: 0; bottom: 0;
+  background: #f5f5ff;
+  border-left: 1px solid #e5e5ee;
+  z-index: -1;
+}
+#jump_to, #jump_page {
+  background: white;
+  -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
+  -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
+  font: 10px Arial;
+  text-transform: uppercase;
+  cursor: pointer;
+  text-align: right;
+}
+#jump_to, #jump_wrapper {
+  position: fixed;
+  right: 0; top: 0;
+  padding: 5px 10px;
+}
+  #jump_wrapper {
+    padding: 0;
+    display: none;
+  }
+    #jump_to:hover #jump_wrapper {
+      display: block;
+    }
+    #jump_page {
+      padding: 5px 0 3px;
+      margin: 0 0 25px 25px;
+    }
+      #jump_page .source {
+        display: block;
+        padding: 5px 10px;
+        text-decoration: none;
+        border-top: 1px solid #eee;
+      }
+        #jump_page .source:hover {
+          background: #f5f5ff;
+        }
+        #jump_page .source:first-child {
+        }
+table td {
+  border: 0;
+  outline: 0;
+}
+  td.docs, th.docs {
+    max-width: 450px;
+    min-width: 450px;
+    min-height: 5px;
+    padding: 10px 25px 1px 50px;
+    overflow-x: hidden;
+    vertical-align: top;
+    text-align: left;
+  }
+    .docs pre {
+      margin: 15px 0 15px;
+      padding-left: 15px;
+    }
+    .docs p tt, .docs p code {
+      background: #f8f8ff;
+      border: 1px solid #dedede;
+      font-size: 12px;
+      padding: 0 0.2em;
+    }
+    .pilwrap {
+      position: relative;
+    }
+      .pilcrow {
+        font: 12px Arial;
+        text-decoration: none;
+        color: #454545;
+        position: absolute;
+        top: 3px; left: -20px;
+        padding: 1px 2px;
+        opacity: 0;
+        -webkit-transition: opacity 0.2s linear;
+      }
+        td.docs:hover .pilcrow {
+          opacity: 1;
+        }
+  td.code, th.code {
+    padding: 14px 15px 16px 25px;
+    width: 100%;
+    vertical-align: top;
+    background: #f5f5ff;
+    border-left: 1px solid #e5e5ee;
+  }
+    pre, tt, code {
+      font-size: 12px; line-height: 18px;
+      font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
+      margin: 0; padding: 0;
+    }
+
+
+/*---------------------- Syntax Highlighting -----------------------------*/
+td.linenos { background-color: #f0f0f0; padding-right: 10px; }
+span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
+body .hll { background-color: #ffffcc }
+body .c { color: #408080; font-style: italic }  /* Comment */
+body .err { border: 1px solid #FF0000 }         /* Error */
+body .k { color: #954121 }                      /* Keyword */
+body .o { color: #666666 }                      /* Operator */
+body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+body .cp { color: #BC7A00 }                     /* Comment.Preproc */
+body .c1 { color: #408080; font-style: italic } /* Comment.Single */
+body .cs { color: #408080; font-style: italic } /* Comment.Special */
+body .gd { color: #A00000 }                     /* Generic.Deleted */
+body .ge { font-style: italic }                 /* Generic.Emph */
+body .gr { color: #FF0000 }                     /* Generic.Error */
+body .gh { color: #000080; font-weight: bold }  /* Generic.Heading */
+body .gi { color: #00A000 }                     /* Generic.Inserted */
+body .go { color: #808080 }                     /* Generic.Output */
+body .gp { color: #000080; font-weight: bold }  /* Generic.Prompt */
+body .gs { font-weight: bold }                  /* Generic.Strong */
+body .gu { color: #800080; font-weight: bold }  /* Generic.Subheading */
+body .gt { color: #0040D0 }                     /* Generic.Traceback */
+body .kc { color: #954121 }                     /* Keyword.Constant */
+body .kd { color: #954121; font-weight: bold }  /* Keyword.Declaration */
+body .kn { color: #954121; font-weight: bold }  /* Keyword.Namespace */
+body .kp { color: #954121 }                     /* Keyword.Pseudo */
+body .kr { color: #954121; font-weight: bold }  /* Keyword.Reserved */
+body .kt { color: #B00040 }                     /* Keyword.Type */
+body .m { color: #666666 }                      /* Literal.Number */
+body .s { color: #219161 }                      /* Literal.String */
+body .na { color: #7D9029 }                     /* Name.Attribute */
+body .nb { color: #954121 }                     /* Name.Builtin */
+body .nc { color: #0000FF; font-weight: bold }  /* Name.Class */
+body .no { color: #880000 }                     /* Name.Constant */
+body .nd { color: #AA22FF }                     /* Name.Decorator */
+body .ni { color: #999999; font-weight: bold }  /* Name.Entity */
+body .ne { color: #D2413A; font-weight: bold }  /* Name.Exception */
+body .nf { color: #0000FF }                     /* Name.Function */
+body .nl { color: #A0A000 }                     /* Name.Label */
+body .nn { color: #0000FF; font-weight: bold }  /* Name.Namespace */
+body .nt { color: #954121; font-weight: bold }  /* Name.Tag */
+body .nv { color: #19469D }                     /* Name.Variable */
+body .ow { color: #AA22FF; font-weight: bold }  /* Operator.Word */
+body .w { color: #bbbbbb }                      /* Text.Whitespace */
+body .mf { color: #666666 }                     /* Literal.Number.Float */
+body .mh { color: #666666 }                     /* Literal.Number.Hex */
+body .mi { color: #666666 }                     /* Literal.Number.Integer */
+body .mo { color: #666666 }                     /* Literal.Number.Oct */
+body .sb { color: #219161 }                     /* Literal.String.Backtick */
+body .sc { color: #219161 }                     /* Literal.String.Char */
+body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
+body .s2 { color: #219161 }                     /* Literal.String.Double */
+body .se { color: #BB6622; font-weight: bold }  /* Literal.String.Escape */
+body .sh { color: #219161 }                     /* Literal.String.Heredoc */
+body .si { color: #BB6688; font-weight: bold }  /* Literal.String.Interpol */
+body .sx { color: #954121 }                     /* Literal.String.Other */
+body .sr { color: #BB6688 }                     /* Literal.String.Regex */
+body .s1 { color: #219161 }                     /* Literal.String.Single */
+body .ss { color: #19469D }                     /* Literal.String.Symbol */
+body .bp { color: #954121 }                     /* Name.Builtin.Pseudo */
+body .vc { color: #19469D }                     /* Name.Variable.Class */
+body .vg { color: #19469D }                     /* Name.Variable.Global */
+body .vi { color: #19469D }                     /* Name.Variable.Instance */
+body .il { color: #666666 }                     /* Literal.Number.Integer.Long */
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/docs/pkginfo.html
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/docs/pkginfo.html	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/docs/pkginfo.html	(revision 484)
@@ -0,0 +1,101 @@
+<!DOCTYPE html>  <html> <head>   <title>pkginfo.js</title>   <meta http-equiv="content-type" content="text/html; charset=UTF-8">   <link rel="stylesheet" media="all" href="docco.css" /> </head> <body>   <div id="container">     <div id="background"></div>          <table cellpadding="0" cellspacing="0">       <thead>         <tr>           <th class="docs">             <h1>               pkginfo.js             </h1>           </th>           <th class="code">           </th>         </tr>       </thead>       <tbody>                               <tr id="section-1">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-1">&#182;</a>               </div>                            </td>             <td class="code">               <div class="highlight"><pre><span class="cm">/*</span>
+<span class="cm"> * pkginfo.js: Top-level include for the pkginfo module</span>
+<span class="cm"> *</span>
+<span class="cm"> * (C) 2011, Charlie Robbins</span>
+<span class="cm"> *</span>
+<span class="cm"> */</span>
+ 
+<span class="kd">var</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;fs&#39;</span><span class="p">),</span>
+    <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;path&#39;</span><span class="p">);</span></pre></div>             </td>           </tr>                               <tr id="section-2">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-2">&#182;</a>               </div>               <h3>function pkginfo ([options, 'property', 'property' ..])</h3>
+
+<h4>@pmodule {Module} Parent module to read from.</h4>
+
+<h4>@options {Object|Array|string} <strong>Optional</strong> Options used when exposing properties.</h4>
+
+<h4>@arguments {string...} <strong>Optional</strong> Specified properties to expose.</h4>
+
+<p>Exposes properties from the package.json file for the parent module on 
+it's exports. Valid usage:</p>
+
+<p><code>require('pkginfo')()</code></p>
+
+<p><code>require('pkginfo')('version', 'author');</code></p>
+
+<p><code>require('pkginfo')(['version', 'author']);</code></p>
+
+<p><code>require('pkginfo')({ include: ['version', 'author'] });</code></p>             </td>             <td class="code">               <div class="highlight"><pre><span class="kd">var</span> <span class="nx">pkginfo</span> <span class="o">=</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
+  <span class="kd">var</span> <span class="nx">args</span> <span class="o">=</span> <span class="p">[].</span><span class="nx">slice</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">arguments</span><span class="p">,</span> <span class="mi">2</span><span class="p">).</span><span class="nx">filter</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">arg</span><span class="p">)</span> <span class="p">{</span>
+    <span class="k">return</span> <span class="k">typeof</span> <span class="nx">arg</span> <span class="o">===</span> <span class="s1">&#39;string&#39;</span><span class="p">;</span>
+  <span class="p">});</span>
+  </pre></div>             </td>           </tr>                               <tr id="section-3">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-3">&#182;</a>               </div>               <p><strong>Parse variable arguments</strong></p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="k">if</span> <span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">options</span><span class="p">))</span> <span class="p">{</span></pre></div>             </td>           </tr>                               <tr id="section-4">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-4">&#182;</a>               </div>               <p>If the options passed in is an Array assume that
+it is the Array of properties to expose from the
+on the package.json file on the parent module.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="nx">options</span> <span class="p">};</span>
+  <span class="p">}</span>
+  <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">options</span> <span class="o">===</span> <span class="s1">&#39;string&#39;</span><span class="p">)</span> <span class="p">{</span></pre></div>             </td>           </tr>                               <tr id="section-5">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-5">&#182;</a>               </div>               <p>Otherwise if the first argument is a string, then
+assume that it is the first property to expose from
+the package.json file on the parent module.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="nx">options</span><span class="p">]</span> <span class="p">};</span>
+  <span class="p">}</span>
+  </pre></div>             </td>           </tr>                               <tr id="section-6">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-6">&#182;</a>               </div>               <p><strong>Setup default options</strong></p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[]</span> <span class="p">};</span>
+  
+  <span class="k">if</span> <span class="p">(</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span></pre></div>             </td>           </tr>                               <tr id="section-7">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-7">&#182;</a>               </div>               <p>If additional string arguments have been passed in
+then add them to the properties to expose on the 
+parent module. </p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nx">options</span><span class="p">.</span><span class="nx">include</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">args</span><span class="p">);</span>
+  <span class="p">}</span>
+  
+  <span class="kd">var</span> <span class="nx">pkg</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">dir</span><span class="p">).</span><span class="kr">package</span><span class="p">;</span>
+  <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">pkg</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
+    <span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="o">!~</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">key</span><span class="p">))</span> <span class="p">{</span>
+      <span class="k">return</span><span class="p">;</span>
+    <span class="p">}</span>
+    
+    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">])</span> <span class="p">{</span>
+      <span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">pkg</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
+    <span class="p">}</span>
+  <span class="p">});</span>
+  
+  <span class="k">return</span> <span class="nx">pkginfo</span><span class="p">;</span>
+<span class="p">};</span></pre></div>             </td>           </tr>                               <tr id="section-8">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-8">&#182;</a>               </div>               <h3>function find (dir)</h3>
+
+<h4>@pmodule {Module} Parent module to read from.</h4>
+
+<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4>
+
+<p>Searches up the directory tree from <code>dir</code> until it finds a directory
+which contains a <code>package.json</code> file. </p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span>
+  <span class="nx">dir</span> <span class="o">=</span> <span class="nx">dir</span> <span class="o">||</span> <span class="nx">pmodule</span><span class="p">.</span><span class="nx">filename</span><span class="p">;</span>
+  <span class="nx">dir</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span> 
+  
+  <span class="kd">var</span> <span class="nx">files</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readdirSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span>
+  
+  <span class="k">if</span> <span class="p">(</span><span class="o">~</span><span class="nx">files</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;package.json&#39;</span><span class="p">))</span> <span class="p">{</span>
+    <span class="k">return</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">dir</span><span class="p">,</span> <span class="s1">&#39;package.json&#39;</span><span class="p">);</span>
+  <span class="p">}</span>
+  
+  <span class="k">if</span> <span class="p">(</span><span class="nx">dir</span> <span class="o">===</span> <span class="s1">&#39;/&#39;</span><span class="p">)</span> <span class="p">{</span>
+    <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">&#39;Could not find package.json up from: &#39;</span> <span class="o">+</span> <span class="nx">dir</span><span class="p">);</span>
+  <span class="p">}</span>
+  
+  <span class="k">return</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span>
+<span class="p">};</span></pre></div>             </td>           </tr>                               <tr id="section-9">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-9">&#182;</a>               </div>               <h3>function read (pmodule, dir)</h3>
+
+<h4>@pmodule {Module} Parent module to read from.</h4>
+
+<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4>
+
+<p>Searches up the directory tree from <code>dir</code> until it finds a directory
+which contains a <code>package.json</code> file and returns the package information.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span> 
+  <span class="nx">dir</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">);</span>
+  
+  <span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">).</span><span class="nx">toString</span><span class="p">();</span>
+      
+  <span class="k">return</span> <span class="p">{</span>
+    <span class="nx">dir</span><span class="o">:</span> <span class="nx">dir</span><span class="p">,</span> 
+    <span class="kr">package</span><span class="o">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span>
+  <span class="p">};</span>
+<span class="p">};</span></pre></div>             </td>           </tr>                               <tr id="section-10">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-10">&#182;</a>               </div>               <p>Call <code>pkginfo</code> on this module and expose version.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">(</span><span class="nx">module</span><span class="p">,</span> <span class="p">{</span>
+  <span class="nx">dir</span><span class="o">:</span> <span class="nx">__dirname</span><span class="p">,</span>
+  <span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;version&#39;</span><span class="p">],</span>
+  <span class="nx">target</span><span class="o">:</span> <span class="nx">pkginfo</span>
+<span class="p">});</span>
+
+</pre></div>             </td>           </tr>                </tbody>     </table>   </div> </body> </html> 
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/all-properties.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/all-properties.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/all-properties.js	(revision 484)
@@ -0,0 +1,19 @@
+/*
+ * all-properties.js: Sample of including all properties from a package.json file
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module);
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/array-argument.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/array-argument.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/array-argument.js	(revision 484)
@@ -0,0 +1,20 @@
+/*
+ * array-argument.js: Sample of including specific properties from a package.json file
+ *                    using Array argument syntax.
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module, ['version', 'author']);
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/multiple-properties.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/multiple-properties.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/multiple-properties.js	(revision 484)
@@ -0,0 +1,19 @@
+/*
+ * multiple-properties.js: Sample of including multiple properties from a package.json file
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module, 'version', 'author');
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/object-argument.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/object-argument.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/object-argument.js	(revision 484)
@@ -0,0 +1,22 @@
+/*
+ * object-argument.js: Sample of including specific properties from a package.json file
+ *                     using Object argument syntax.
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module, {
+      include: ['version', 'author']
+    });
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/package.json
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/package.json	(revision 484)
@@ -0,0 +1,10 @@
+{
+  "name": "simple-app",
+  "description": "A test fixture for pkginfo",
+  "version": "0.1.0",
+  "author": "Charlie Robbins <charlie.robbins@gmail.com>",
+  "keywords": ["test", "fixture"],
+  "main": "./index.js",
+  "scripts": { "test": "vows test/*-test.js --spec" },
+  "engines": { "node": ">= 0.4.0" }
+}
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/single-property.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/single-property.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/examples/single-property.js	(revision 484)
@@ -0,0 +1,19 @@
+/*
+ * single-property.js: Sample of including a single specific properties from a package.json file
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module, 'version');
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/lib/pkginfo.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/lib/pkginfo.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/lib/pkginfo.js	(revision 484)
@@ -0,0 +1,132 @@
+/*
+ * pkginfo.js: Top-level include for the pkginfo module
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var fs = require('fs'),
+    path = require('path');
+
+//
+// ### function pkginfo ([options, 'property', 'property' ..])
+// #### @pmodule {Module} Parent module to read from.
+// #### @options {Object|Array|string} **Optional** Options used when exposing properties.
+// #### @arguments {string...} **Optional** Specified properties to expose.
+// Exposes properties from the package.json file for the parent module on 
+// it's exports. Valid usage:
+//
+// `require('pkginfo')()`
+//
+// `require('pkginfo')('version', 'author');`
+//
+// `require('pkginfo')(['version', 'author']);`
+//
+// `require('pkginfo')({ include: ['version', 'author'] });`
+//
+var pkginfo = module.exports = function (pmodule, options) {
+  var args = [].slice.call(arguments, 2).filter(function (arg) {
+    return typeof arg === 'string';
+  });
+  
+  //
+  // **Parse variable arguments**
+  //
+  if (Array.isArray(options)) {
+    //
+    // If the options passed in is an Array assume that
+    // it is the Array of properties to expose from the
+    // on the package.json file on the parent module.
+    //
+    options = { include: options };
+  }
+  else if (typeof options === 'string') {
+    //
+    // Otherwise if the first argument is a string, then
+    // assume that it is the first property to expose from
+    // the package.json file on the parent module.
+    //
+    options = { include: [options] };
+  }
+  
+  //
+  // **Setup default options**
+  //
+  options = options || { include: [] };
+  
+  if (args.length > 0) {
+    //
+    // If additional string arguments have been passed in
+    // then add them to the properties to expose on the 
+    // parent module. 
+    //
+    options.include = options.include.concat(args);
+  }
+  
+  var pkg = pkginfo.read(pmodule, options.dir).package;
+  Object.keys(pkg).forEach(function (key) {
+    if (options.include.length > 0 && !~options.include.indexOf(key)) {
+      return;
+    }
+    
+    if (!pmodule.exports[key]) {
+      pmodule.exports[key] = pkg[key];
+    }
+  });
+  
+  return pkginfo;
+};
+
+//
+// ### function find (dir)
+// #### @pmodule {Module} Parent module to read from.
+// #### @dir {string} **Optional** Directory to start search from.
+// Searches up the directory tree from `dir` until it finds a directory
+// which contains a `package.json` file. 
+//
+pkginfo.find = function (pmodule, dir) {
+  dir = dir || pmodule.filename;
+  dir = path.dirname(dir); 
+  
+  var files = fs.readdirSync(dir);
+  
+  if (~files.indexOf('package.json')) {
+    return path.join(dir, 'package.json');
+  }
+  
+  if (dir === '/') {
+    throw new Error('Could not find package.json up from: ' + dir);
+  }
+  else if (!dir || dir === '.') {
+    throw new Error('Cannot find package.json from unspecified directory');
+  }
+  
+  return pkginfo.find(pmodule, dir);
+};
+
+//
+// ### function read (pmodule, dir)
+// #### @pmodule {Module} Parent module to read from.
+// #### @dir {string} **Optional** Directory to start search from.
+// Searches up the directory tree from `dir` until it finds a directory
+// which contains a `package.json` file and returns the package information.
+//
+pkginfo.read = function (pmodule, dir) { 
+  dir = pkginfo.find(pmodule, dir);
+  
+  var data = fs.readFileSync(dir).toString();
+      
+  return {
+    dir: dir, 
+    package: JSON.parse(data)
+  };
+};
+
+//
+// Call `pkginfo` on this module and expose version.
+//
+pkginfo(module, {
+  dir: __dirname,
+  include: ['version'],
+  target: pkginfo
+});
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/package.json
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/package.json	(revision 484)
@@ -0,0 +1,35 @@
+{
+  "name": "pkginfo",
+  "version": "0.2.3",
+  "description": "An easy way to expose properties on a module from a package.json",
+  "author": {
+    "name": "Charlie Robbins",
+    "email": "charlie.robbins@gmail.com"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/indexzero/node-pkginfo.git"
+  },
+  "keywords": [
+    "info",
+    "tools",
+    "package.json"
+  ],
+  "devDependencies": {
+    "vows": "0.6.x"
+  },
+  "main": "./lib/pkginfo",
+  "scripts": {
+    "test": "vows test/*-test.js --spec"
+  },
+  "engines": {
+    "node": ">= 0.4.0"
+  },
+  "readme": "# node-pkginfo\n\nAn easy way to expose properties on a module from a package.json\n\n## Installation\n\n### Installing npm (node package manager)\n```\n  curl http://npmjs.org/install.sh | sh\n```\n\n### Installing pkginfo\n```\n  [sudo] npm install pkginfo\n```\n\n## Motivation\nHow often when writing node.js modules have you written the following line(s) of code? \n\n* Hard code your version string into your code\n\n``` js\n  exports.version = '0.1.0';\n```\n\n* Programmatically expose the version from the package.json\n\n``` js\n  exports.version = JSON.parse(fs.readFileSync('/path/to/package.json', 'utf8')).version;\n```\n\nIn other words, how often have you wanted to expose basic information from your package.json onto your module programmatically? **WELL NOW YOU CAN!**\n\n## Usage\n\nUsing `pkginfo` is idiot-proof, just require and invoke it. \n\n``` js\n  var pkginfo = require('pkginfo')(module);\n  \n  console.dir(module.exports);\n```\n\nBy invoking the `pkginfo` module all of the properties in your `package.json` file will be automatically exposed on the callee module (i.e. the parent module of `pkginfo`). \n\nHere's a sample of the output:\n\n```\n  { name: 'simple-app',\n    description: 'A test fixture for pkginfo',\n    version: '0.1.0',\n    author: 'Charlie Robbins <charlie.robbins@gmail.com>',\n    keywords: [ 'test', 'fixture' ],\n    main: './index.js',\n    scripts: { test: 'vows test/*-test.js --spec' },\n    engines: { node: '>= 0.4.0' } }\n```\n\n### Expose specific properties\nIf you don't want to expose **all** properties on from your `package.json` on your module then simple pass those properties to the `pkginfo` function:\n\n``` js\n  var pkginfo = require('pkginfo')(module, 'version', 'author');\n  \n  console.dir(module.exports);\n```\n\n```\n  { version: '0.1.0',\n    author: 'Charlie Robbins <charlie.robbins@gmail.com>' }\n```\n\nIf you're looking for further usage see the [examples][0] included in this repository. \n\n## Run Tests\nTests are written in [vows][1] and give complete coverage of all APIs.\n\n```\n  vows test/*-test.js --spec\n```\n\n[0]: https://github.com/indexzero/node-pkginfo/tree/master/examples\n[1]: http://vowsjs.org\n\n#### Author: [Charlie Robbins](http://nodejitsu.com)",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/indexzero/node-pkginfo/issues"
+  },
+  "_id": "pkginfo@0.2.3",
+  "_from": "pkginfo@0.2.x"
+}
Index: Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/test/pkginfo-test.js
===================================================================
--- Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/test/pkginfo-test.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/node_modules/pkginfo/test/pkginfo-test.js	(revision 484)
@@ -0,0 +1,69 @@
+/*
+ * pkginfo-test.js: Tests for the pkginfo module.
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+
+var assert = require('assert'),
+    exec = require('child_process').exec,
+    fs = require('fs'),
+    path = require('path'),
+    vows = require('vows'),
+    pkginfo = require('../lib/pkginfo');
+
+function assertProperties (source, target) {
+  assert.lengthOf(source, target.length + 1);
+  target.forEach(function (prop) {
+    assert.isTrue(!!~source.indexOf(prop));
+  });
+}
+
+function testExposes (options) {
+  return {
+    topic: function () {
+      exec('node ' + path.join(__dirname, '..', 'examples', options.script), this.callback);
+    },
+    "should expose that property correctly": function (err, stdout, stderr) {
+      assert.isNull(err);
+      
+      var exposed = stderr.match(/'(\w+)'/ig).map(function (p) { 
+        return p.substring(1, p.length - 1);
+      });
+      
+      return !options.assert 
+        ? assertProperties(exposed, options.properties)
+        : options.assert(exposed);
+    }
+  }
+}
+
+vows.describe('pkginfo').addBatch({
+  "When using the pkginfo module": {
+    "and passed a single `string` argument": testExposes({
+      script: 'single-property.js',
+      properties: ['version']
+    }),
+    "and passed multiple `string` arguments": testExposes({
+      script: 'multiple-properties.js',
+      properties: ['version', 'author']
+    }),
+    "and passed an `object` argument": testExposes({
+      script: 'object-argument.js',
+      properties: ['version', 'author']
+    }),
+    "and passed an `array` argument": testExposes({
+      script: 'array-argument.js',
+      properties: ['version', 'author']
+    }),
+    "and passed no arguments": testExposes({
+      script: 'all-properties.js',
+      assert: function (exposed) {
+        var pkg = fs.readFileSync(path.join(__dirname, '..', 'examples', 'package.json')).toString(),
+            keys = Object.keys(JSON.parse(pkg));
+        
+        assertProperties(exposed, keys);
+      }
+    })
+  }
+}).export(module);
Index: Dev/trunk/src/node_modules/passport-local/package.json
===================================================================
--- Dev/trunk/src/node_modules/passport-local/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/passport-local/package.json	(revision 484)
@@ -0,0 +1,51 @@
+{
+  "name": "passport-local",
+  "version": "0.1.6",
+  "description": "Local username and password authentication strategy for Passport.",
+  "author": {
+    "name": "Jared Hanson",
+    "email": "jaredhanson@gmail.com",
+    "url": "http://www.jaredhanson.net/"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/jaredhanson/passport-local.git"
+  },
+  "bugs": {
+    "url": "http://github.com/jaredhanson/passport-local/issues"
+  },
+  "main": "./lib/passport-local",
+  "dependencies": {
+    "pkginfo": "0.2.x",
+    "passport": "~0.1.1"
+  },
+  "devDependencies": {
+    "vows": "0.6.x"
+  },
+  "scripts": {
+    "test": "NODE_PATH=lib node_modules/.bin/vows test/*-test.js"
+  },
+  "engines": {
+    "node": ">= 0.4.0"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "http://www.opensource.org/licenses/MIT"
+    }
+  ],
+  "keywords": [
+    "passport",
+    "local",
+    "auth",
+    "authn",
+    "authentication"
+  ],
+  "readme": "ERROR: No README data found!",
+  "_id": "passport-local@0.1.6",
+  "dist": {
+    "shasum": "3179518b5409abbb0d72960098126cc6f3919828"
+  },
+  "_from": "passport-local@",
+  "_resolved": "https://registry.npmjs.org/passport-local/-/passport-local-0.1.6.tgz"
+}
Index: Dev/trunk/src/node_modules/passport/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/passport/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/passport/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: "node_js"
+node_js:
+  - 0.4
+  - 0.6
+  - 0.8
Index: Dev/trunk/src/node_modules/passport/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/passport/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/passport/LICENSE	(revision 484)
@@ -0,0 +1,20 @@
+(The MIT License)
+
+Copyright (c) 2011-2013 Jared Hanson
+
+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.
Index: Dev/trunk/src/node_modules/passport/README.md
===================================================================
--- Dev/trunk/src/node_modules/passport/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/passport/README.md	(revision 484)
@@ -0,0 +1,138 @@
+# Passport
+
+Passport is [Express](http://expressjs.com/)-compatible authentication
+middleware for [Node.js](http://nodejs.org/).
+
+Passport's sole purpose is to authenticate requests, which it does through an
+extensible set of plugins known as _strategies_.  Passport does not mount
+routes or assume any particular database schema, which maximizes flexiblity and
+allows application-level decisions to be made by the developer.  The API is
+simple: you provide Passport a request to authenticate, and Passport provides
+hooks for controlling what occurs when authentication succeeds or fails.
+
+## Install
+
+    $ npm install passport
+
+## Usage
+
+#### Strategies
+
+Passport uses the concept of strategies to authenticate requests.  Strategies
+can range from verifying username and password credentials, delegated
+authentication using [OAuth](http://oauth.net/) (for example, via [Facebook](http://www.facebook.com/)
+or [Twitter](http://twitter.com/)), or federated authentication using [OpenID](http://openid.net/).
+
+Before authenticating requests, the strategy (or strategies) used by an
+application must be configured.
+
+    passport.use(new LocalStrategy(
+      function(username, password, done) {
+        User.findOne({ username: username, password: password }, function (err, user) {
+          done(err, user);
+        });
+      }
+    ));
+
+#### Sessions
+
+Passport will maintain persistent login sessions.  In order for persistent
+sessions to work, the authenticated user must be serialized to the session, and
+deserialized when subsequent requests are made.
+
+Passport does not impose any restrictions on how your user records are stored.
+Instead, you provide functions to Passport which implements the necessary
+serialization and deserialization logic.  In a typical application, this will be
+as simple as serializing the user ID, and finding the user by ID when
+deserializing.
+
+    passport.serializeUser(function(user, done) {
+      done(null, user.id);
+    });
+
+    passport.deserializeUser(function(id, done) {
+      User.findById(id, function (err, user) {
+        done(err, user);
+      });
+    });
+
+#### Middleware
+
+To use Passport in an [Express](http://expressjs.com/) or
+[Connect](http://senchalabs.github.com/connect/)-based application, configure it
+with the required `passport.initialize()` middleware.  If your application uses
+persistent login sessions (recommended, but not required), `passport.session()`
+middleware must also be used.
+
+    app.configure(function() {
+      app.use(express.static(__dirname + '/../../public'));
+      app.use(express.cookieParser());
+      app.use(express.bodyParser());
+      app.use(express.session({ secret: 'keyboard cat' }));
+      app.use(passport.initialize());
+      app.use(passport.session());
+      app.use(app.router);
+    });
+
+#### Authenticate Requests
+
+Passport provides an `authenticate()` function, which is used as route
+middleware to authenticate requests.
+
+    app.post('/login', 
+      passport.authenticate('local', { failureRedirect: '/login' }),
+      function(req, res) {
+        res.redirect('/');
+      });
+
+## Examples
+
+For a complete, working example, refer to the [login example](https://github.com/jaredhanson/passport-local/tree/master/examples/login)
+included in [passport-local](https://github.com/jaredhanson/passport-local).
+
+## Strategies
+
+Passport has a comprehensive set of **over 120** authentication strategies
+covering social networking, enterprise integration, API services, and more.
+The [complete list](https://github.com/jaredhanson/passport/wiki/Strategies) is
+available on the [wiki](https://github.com/jaredhanson/passport/wiki).
+
+The following table lists commonly used strategies:
+
+|Strategy                                                       | Protocol                 |Developer                                       |
+|---------------------------------------------------------------|--------------------------|------------------------------------------------|
+|[Local](https://github.com/jaredhanson/passport-local)         | HTML form                |[Jared Hanson](https://github.com/jaredhanson)  |
+|[OpenID](https://github.com/jaredhanson/passport-openid)       | OpenID                   |[Jared Hanson](https://github.com/jaredhanson)  |
+|[BrowserID](https://github.com/jaredhanson/passport-browserid) | BrowserID                |[Jared Hanson](https://github.com/jaredhanson)  |
+|[Facebook](https://github.com/jaredhanson/passport-facebook)   | OAuth 2.0                |[Jared Hanson](https://github.com/jaredhanson)  |
+|[Google](https://github.com/jaredhanson/passport-google)       | OpenID                   |[Jared Hanson](https://github.com/jaredhanson)  |
+|[Google](https://github.com/jaredhanson/passport-google-oauth) | OAuth / OAuth 2.0        |[Jared Hanson](https://github.com/jaredhanson)  |
+|[Twitter](https://github.com/jaredhanson/passport-twitter)     | OAuth                    |[Jared Hanson](https://github.com/jaredhanson)  |
+
+## Related Modules
+
+- [Locomotive](https://github.com/jaredhanson/locomotive) â Powerful MVC web framework
+- [OAuthorize](https://github.com/jaredhanson/oauthorize) â OAuth service provider toolkit
+- [OAuth2orize](https://github.com/jaredhanson/oauth2orize) â OAuth 2.0 authorization server toolkit
+- [connect-ensure-login](https://github.com/jaredhanson/connect-ensure-login)  â middleware to ensure login sessions
+
+The [modules](https://github.com/jaredhanson/passport/wiki/Modules) page on the
+[wiki](https://github.com/jaredhanson/passport/wiki) lists other useful modules
+that build upon or integrate with Passport.
+
+## Tests
+
+    $ npm install --dev
+    $ make test
+
+[![Build Status](https://secure.travis-ci.org/jaredhanson/passport.png)](http://travis-ci.org/jaredhanson/passport)
+
+## Credits
+
+  - [Jared Hanson](http://github.com/jaredhanson)
+
+## License
+
+[The MIT License](http://opensource.org/licenses/MIT)
+
+Copyright (c) 2011-2013 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)>
Index: Dev/trunk/src/node_modules/passport/lib/passport/context/http/actions.js
===================================================================
--- Dev/trunk/src/node_modules/passport/lib/passport/context/http/actions.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/lib/passport/context/http/actions.js	(revision 484)
@@ -0,0 +1,93 @@
+/**
+ * Export actions prototype for strategies operating within an HTTP context.
+ */
+var actions = module.exports = {};
+
+
+/**
+ * Authenticate `user`, with optional `info`.
+ *
+ * Strategies should call this function to successfully authenticate a user.
+ * `user` should be an object supplied by the application after it has been
+ * given an opportunity to verify credentials.  `info` is an optional argument
+ * containing additional user information.  This is useful for third-party
+ * authentication strategies to pass profile details.
+ *
+ * @param {Object} user
+ * @param {Object} info
+ * @api public
+ */
+actions.success = function(user, info) {
+  this.delegate.success.apply(this, arguments);
+}
+
+/**
+ * Fail authentication, with optional `challenge` and `status`, defaulting to
+ * 401.
+ *
+ * Strategies should call this function to fail an authentication attempt.
+ *
+ * @param {String} challenge
+ * @param {Number} status
+ * @api public
+ */
+actions.fail = function(challenge, status) {
+  this.delegate.fail.apply(this, arguments);
+}
+
+/**
+ * Redirect to `url` with optional `status`, defaulting to 302.
+ *
+ * Strategies should call this function to redirect the user (via their user
+ * agent) to a third-party website for authentication.
+ *
+ * @param {String} url
+ * @param {Number} status
+ * @api public
+ */
+actions.redirect = function(url, status) {
+  var res = this.res;
+  if (typeof res.redirect == 'function') {
+    // If possible use redirect method on the response
+    // Assume Express API, optional status param comes first
+    if (status) {
+      res.redirect(status, url);
+    } else {
+      res.redirect(url);
+    }
+  } else {
+    // Otherwise fall back to native methods
+    res.statusCode = status || 302;
+    res.setHeader('Location', url);
+    res.setHeader('Content-Length', '0');
+    res.end();
+  }
+}
+
+/**
+ * Pass without making a success or fail decision.
+ *
+ * Under most circumstances, Strategies should not need to call this function.
+ * It exists primarily to allow previous authentication state to be restored,
+ * for example from an HTTP session.
+ *
+ * @api public
+ */
+actions.pass = function() {
+  this.next();
+}
+
+/**
+ * Internal error while performing authentication.
+ *
+ * Strategies should call this function when an internal error occurs during the
+ * process of performing authentication; for example, if the user directory is
+ * not available.
+ *
+ * @param {Error} err
+ * @api public
+ */
+actions.error = function(err) {
+  this.next(err);
+}
+
Index: Dev/trunk/src/node_modules/passport/lib/passport/context/http/context.js
===================================================================
--- Dev/trunk/src/node_modules/passport/lib/passport/context/http/context.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/lib/passport/context/http/context.js	(revision 484)
@@ -0,0 +1,17 @@
+/**
+ * `Context` constructor.
+ *
+ * @api private
+ */
+function Context(delegate, req, res, next) {
+  this.delegate = delegate;
+  this.req = req;
+  this.res = res;
+  this.next = next;
+}
+
+
+/**
+ * Expose `Context`.
+ */
+module.exports = Context;
Index: Dev/trunk/src/node_modules/passport/lib/passport/http/request.js
===================================================================
--- Dev/trunk/src/node_modules/passport/lib/passport/http/request.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/lib/passport/http/request.js	(revision 484)
@@ -0,0 +1,91 @@
+/**
+ * Module dependencies.
+ */
+var http = require('http')
+  , req = http.IncomingMessage.prototype;
+
+
+/**
+ * Intiate a login session for `user`.
+ *
+ * Options:
+ *   - `session`  Save login state in session, defaults to _true_
+ *
+ * Examples:
+ *
+ *     req.logIn(user, { session: false });
+ *
+ *     req.logIn(user, function(err) {
+ *       if (err) { throw err; }
+ *       // session saved
+ *     });
+ *
+ * @param {User} user
+ * @param {Object} options
+ * @param {Function} done
+ * @api public
+ */
+req.login =
+req.logIn = function(user, options, done) {
+  if (!this._passport) throw new Error('passport.initialize() middleware not in use');
+  
+  if (!done && typeof options === 'function') {
+    done = options;
+    options = {};
+  }
+  options = options || {};
+  var property = this._passport.instance._userProperty || 'user';
+  var session = (options.session === undefined) ? true : options.session;
+  
+  this[property] = user;
+  if (session) {
+    var self = this;
+    this._passport.instance.serializeUser(user, function(err, obj) {
+      if (err) { self[property] = null; return done(err); }
+      self._passport.session.user = obj;
+      done();
+    });
+  } else {
+    done && done();
+  }
+}
+
+/**
+ * Terminate an existing login session.
+ *
+ * @api public
+ */
+req.logout =
+req.logOut = function() {
+  if (!this._passport) throw new Error('passport.initialize() middleware not in use');
+  
+  var property = this._passport.instance._userProperty || 'user';
+  
+  this[property] = null;
+  delete this._passport.session.user;
+};
+
+/**
+ * Test if request is authenticated.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+req.isAuthenticated = function() {
+  var property = 'user';
+  if (this._passport && this._passport.instance._userProperty) {
+    property = this._passport.instance._userProperty;
+  }
+  
+  return (this[property]) ? true : false;
+};
+
+/**
+ * Test if request is unauthenticated.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+req.isUnauthenticated = function() {
+  return !this.isAuthenticated();
+};
Index: Dev/trunk/src/node_modules/passport/lib/passport/index.js
===================================================================
--- Dev/trunk/src/node_modules/passport/lib/passport/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/lib/passport/index.js	(revision 484)
@@ -0,0 +1,453 @@
+/**
+ * Module dependencies.
+ */
+var fs = require('fs')
+  , path = require('path')
+  , util = require('util')
+  , Strategy = require('./strategy')
+  , SessionStrategy = require('./strategies/session')
+  , initialize = require('./middleware/initialize')
+  , authenticate = require('./middleware/authenticate');
+
+
+/**
+ * `Passport` constructor.
+ *
+ * @api public
+ */
+function Passport() {
+  this._key = 'passport';
+  this._strategies = {};
+  this._serializers = [];
+  this._deserializers = [];
+  this._infoTransformers = [];
+  this._framework = null;
+  
+  this._userProperty = 'user';
+  
+  this.use(new SessionStrategy());
+};
+
+/**
+ * Utilize the given `strategy` with optional `name`, overridding the strategy's
+ * default name.
+ *
+ * Examples:
+ *
+ *     passport.use(new TwitterStrategy(...));
+ *
+ *     passport.use('api', new http.BasicStrategy(...));
+ *
+ * @param {String|Strategy} name
+ * @param {Strategy} strategy
+ * @return {Passport} for chaining
+ * @api public
+ */
+Passport.prototype.use = function(name, strategy) {
+  if (!strategy) {
+    strategy = name;
+    name = strategy.name;
+  }
+  if (!name) throw new Error('authentication strategies must have a name');
+  
+  this._strategies[name] = strategy;
+  return this;
+};
+
+/**
+ * Un-utilize the `strategy` with given `name`.
+ *
+ * In typical applications, the necessary authentication strategies are static,
+ * configured once and always available.  As such, there is often no need to
+ * invoke this function.
+ *
+ * However, in certain situations, applications may need dynamically configure
+ * and de-configure authentication strategies.  The `use()`/`unuse()`
+ * combination satisfies these scenarios.
+ *
+ * Examples:
+ *
+ *     passport.unuse('legacy-api');
+ *
+ * @param {String} name
+ * @return {Passport} for chaining
+ * @api public
+ */
+Passport.prototype.unuse = function(name) {
+  delete this._strategies[name];
+  return this;
+}
+
+/**
+ * Setup Passport to be used under framework.
+ *
+ * By default, Passport exposes middleware that operate using Connect-style
+ * middleware using a `fn(req, res, next)` signature.  Other popular frameworks
+ * have different expectations, and this function allows Passport to be adapted
+ * to operate within such environments.
+ *
+ * If you are using a Connect-compatible framework, including Express, there is
+ * no need to invoke this function.
+ *
+ * Examples:
+ *
+ *     passport.framework(require('hapi-passport')());
+ *
+ * @param {Object} name
+ * @return {Passport} for chaining
+ * @api public
+ */
+Passport.prototype.framework = function(fw) {
+  this._framework = fw;
+  return this;
+}
+
+/**
+ * Passport's primary initialization middleware.
+ *
+ * This middleware must be in use by the Connect/Express application for
+ * Passport to operate.
+ *
+ * Options:
+ *   - `userProperty`  Property to set on `req` upon login, defaults to _user_
+ *
+ * Examples:
+ *
+ *     app.configure(function() {
+ *       app.use(passport.initialize());
+ *     });
+ *
+ *     app.configure(function() {
+ *       app.use(passport.initialize({ userProperty: 'currentUser' }));
+ *     });
+ *
+ * @param {Object} options
+ * @return {Function} middleware
+ * @api public
+ */
+Passport.prototype.initialize = function(options) {
+  options = options || {};
+  this._userProperty = options.userProperty || 'user';
+  
+  if (this._framework && this._framework.initialize) {
+    return this._framework.initialize().bind(this);
+  }
+  
+  return initialize().bind(this);
+}
+
+/**
+ * Middleware that will restore login state from a session.
+ *
+ * Web applications typically use sessions to maintain login state between
+ * requests.  For example, a user will authenticate by entering credentials into
+ * a form which is submitted to the server.  If the credentials are valid, a
+ * login session is established by setting a cookie containing a session
+ * identifier in the user's web browser.  The web browser will send this cookie
+ * in subsequent requests to the server, allowing a session to be maintained.
+ *
+ * If sessions are being utilized, and a login session has been established,
+ * this middleware will populate `req.user` with the current user.
+ *
+ * Note that sessions are not strictly required for Passport to operate.
+ * However, as a general rule, most web applications will make use of sessions.
+ * An exception to this rule would be an API server, which expects each HTTP
+ * request to provide credentials in an Authorization header.
+ *
+ * Examples:
+ *
+ *     app.configure(function() {
+ *       app.use(connect.cookieParser());
+ *       app.use(connect.session({ secret: 'keyboard cat' }));
+ *       app.use(passport.initialize());
+ *       app.use(passport.session());
+ *     });
+ *
+ * Options:
+ *   - `pauseStream`      Pause the request stream before deserializing the user
+ *                        object from the session.  Defaults to _false_.  Should
+ *                        be set to true in cases where middleware consuming the
+ *                        request body is configured after passport and the
+ *                        deserializeUser method is asynchronous.
+ *
+ * @param {Object} options
+ * @return {Function} middleware
+ * @api public
+ */
+Passport.prototype.session = function(options) {
+  return this.authenticate('session', options);
+}
+
+/**
+ * Middleware that will authenticate a request using the given `strategy` name,
+ * with optional `options` and `callback`.
+ *
+ * Examples:
+ *
+ *     passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' })(req, res);
+ *
+ *     passport.authenticate('local', function(err, user) {
+ *       if (!user) { return res.redirect('/login'); }
+ *       res.end('Authenticated!');
+ *     })(req, res);
+ *
+ *     passport.authenticate('basic', { session: false })(req, res);
+ *
+ *     app.get('/auth/twitter', passport.authenticate('twitter'), function(req, res) {
+ *       // request will be redirected to Twitter
+ *     });
+ *     app.get('/auth/twitter/callback', passport.authenticate('twitter'), function(req, res) {
+ *       res.json(req.user);
+ *     });
+ *
+ * @param {String} strategy
+ * @param {Object} options
+ * @param {Function} callback
+ * @return {Function} middleware
+ * @api public
+ */
+Passport.prototype.authenticate = function(strategy, options, callback) {
+  if (this._framework && this._framework.authenticate) {
+    return this._framework.authenticate(strategy, options, callback).bind(this);
+  }
+  
+  return authenticate(strategy, options, callback).bind(this);
+}
+
+/**
+ * Middleware that will authorize a third-party account using the given
+ * `strategy` name, with optional `options`.
+ *
+ * If authorization is successful, the result provided by the strategy's verify
+ * callback will be assigned to `req.account`.  The existing login session and
+ * `req.user` will be unaffected.
+ *
+ * This function is particularly useful when connecting third-party accounts
+ * to the local account of a user that is currently authenticated.
+ *
+ * Examples:
+ *
+ *    passport.authorize('twitter-authz', { failureRedirect: '/account' });
+ *
+ * @param {String} strategy
+ * @param {Object} options
+ * @return {Function} middleware
+ * @api public
+ */
+Passport.prototype.authorize = function(strategy, options, callback) {
+  options = options || {};
+  options.assignProperty = 'account';
+  
+  return authenticate(strategy, options, callback).bind(this);
+}
+
+/**
+ * Registers a function used to serialize user objects into the session.
+ *
+ * Examples:
+ *
+ *     passport.serializeUser(function(user, done) {
+ *       done(null, user.id);
+ *     });
+ *
+ * @api public
+ */
+Passport.prototype.serializeUser = function(fn, done) {
+  if (typeof fn === 'function') {
+    return this._serializers.push(fn);
+  }
+  
+  // private implementation that traverses the chain of serializers, attempting
+  // to serialize a user
+  var user = fn;
+  
+  var stack = this._serializers;
+  (function pass(i, err, obj) {
+    // serializers use 'pass' as an error to skip processing
+    if ('pass' === err) {
+      err = undefined;
+    }
+    // an error or serialized object was obtained, done
+    if (err || obj || obj === 0) { return done(err, obj); }
+    
+    var layer = stack[i];
+    if (!layer) {
+      return done(new Error('failed to serialize user into session'));
+    }
+    
+    try {
+      layer(user, function(e, o) { pass(i + 1, e, o); } )
+    } catch(e) {
+      return done(e);
+    }
+  })(0);
+}
+
+/**
+ * Registers a function used to deserialize user objects out of the session.
+ *
+ * Examples:
+ *
+ *     passport.deserializeUser(function(id, done) {
+ *       User.findById(id, function (err, user) {
+ *         done(err, user);
+ *       });
+ *     });
+ *
+ * @api public
+ */
+Passport.prototype.deserializeUser = function(fn, done) {
+  if (typeof fn === 'function') {
+    return this._deserializers.push(fn);
+  }
+  
+  // private implementation that traverses the chain of deserializers,
+  // attempting to deserialize a user
+  var obj = fn;
+  
+  var stack = this._deserializers;
+  (function pass(i, err, user) {
+    // deserializers use 'pass' as an error to skip processing
+    if ('pass' === err) {
+      err = undefined;
+    }
+    // an error or deserialized user was obtained, done
+    if (err || user) { return done(err, user); }
+    // a valid user existed when establishing the session, but that user has
+    // since been removed
+    if (user === null || user === false) { return done(null, false); }
+    
+    var layer = stack[i];
+    if (!layer) {
+      return done(new Error('failed to deserialize user out of session'));
+    }
+    
+    try {
+      layer(obj, function(e, u) { pass(i + 1, e, u); } )
+    } catch(e) {
+      return done(e);
+    }
+  })(0);
+}
+
+/**
+ * Registers a function used to transform auth info.
+ *
+ * In some circumstances authorization details are contained in authentication
+ * credentials or loaded as part of verification.
+ *
+ * For example, when using bearer tokens for API authentication, the tokens may
+ * encode (either directly or indirectly in a database), details such as scope
+ * of access or the client to which the token was issued.
+ *
+ * Such authorization details should be enforced separately from authentication.
+ * Because Passport deals only with the latter, this is the responsiblity of
+ * middleware or routes further along the chain.  However, it is not optimal to
+ * decode the same data or execute the same database query later.  To avoid
+ * this, Passport accepts optional `info` along with the authenticated `user`
+ * in a strategy's `success()` action.  This info is set at `req.authInfo`,
+ * where said later middlware or routes can access it.
+ *
+ * Optionally, applications can register transforms to proccess this info,
+ * which take effect prior to `req.authInfo` being set.  This is useful, for
+ * example, when the info contains a client ID.  The transform can load the
+ * client from the database and include the instance in the transformed info,
+ * allowing the full set of client properties to be convieniently accessed.
+ *
+ * If no transforms are registered, `info` supplied by the strategy will be left
+ * unmodified.
+ *
+ * Examples:
+ *
+ *     passport.transformAuthInfo(function(info, done) {
+ *       Client.findById(info.clientID, function (err, client) {
+ *         info.client = client;
+ *         done(err, info);
+ *       });
+ *     });
+ *
+ * @api public
+ */
+Passport.prototype.transformAuthInfo = function(fn, done) {
+  if (typeof fn === 'function') {
+    return this._infoTransformers.push(fn);
+  }
+  
+  // private implementation that traverses the chain of transformers,
+  // attempting to transform auth info
+  var info = fn;
+  
+  var stack = this._infoTransformers;
+  (function pass(i, err, tinfo) {
+    // transformers use 'pass' as an error to skip processing
+    if ('pass' === err) {
+      err = undefined;
+    }
+    // an error or transformed info was obtained, done
+    if (err || tinfo) { return done(err, tinfo); }
+    
+    var layer = stack[i];
+    if (!layer) {
+      // if no transformers are registered (or they all pass), the default
+      // behavior is to use the un-transformed info as-is
+      return done(null, info);
+    }
+    
+    try {
+      var arity = layer.length;
+      if (arity == 1) {
+        // sync
+        var t = layer(info);
+        pass(i + 1, null, t);
+      } else {
+        // async
+        layer(info, function(e, t) { pass(i + 1, e, t); } )
+      }
+    } catch(e) {
+      return done(e);
+    }
+  })(0);
+}
+
+/**
+ * Return strategy with given `name`. 
+ *
+ * @param {String} name
+ * @return {Strategy}
+ * @api private
+ */
+Passport.prototype._strategy = function(name) {
+  return this._strategies[name];
+}
+
+
+/**
+ * Export default singleton.
+ *
+ * @api public
+ */
+exports = module.exports = new Passport();
+
+/**
+ * Framework version.
+ */
+require('pkginfo')(module, 'version');
+
+/**
+ * Expose constructors.
+ */
+exports.Passport = Passport;
+exports.Strategy = Strategy;
+
+
+/**
+ * Expose strategies.
+ */
+exports.strategies = {};
+exports.strategies.SessionStrategy = SessionStrategy;
+
+
+/**
+ * HTTP extensions.
+ */
+require('./http/request');
Index: Dev/trunk/src/node_modules/passport/lib/passport/middleware/authenticate.js
===================================================================
--- Dev/trunk/src/node_modules/passport/lib/passport/middleware/authenticate.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/lib/passport/middleware/authenticate.js	(revision 484)
@@ -0,0 +1,253 @@
+/**
+ * Module dependencies.
+ */
+var util = require('util')
+  , actions = require('../context/http/actions')
+  , Context = require('../context/http/context')
+
+
+/**
+ * Authenticates requests.
+ *
+ * Applies the `name`ed strategy (or strategies) to the incoming request, in
+ * order to authenticate the request.  If authentication is successful, the user
+ * will be logged in and populated at `req.user` and a session will be
+ * established by default.  If authentication fails, an unauthorized response
+ * will be sent.
+ *
+ * Options:
+ *   - `session`          Save login state in session, defaults to _true_
+ *   - `successRedirect`  After successful login, redirect to given URL
+ *   - `failureRedirect`  After failed login, redirect to given URL
+ *   - `assignProperty`   Assign the object provided by the verify callback to given property
+ *
+ * An optional `callback` can be supplied to allow the application to overrride
+ * the default manner in which authentication attempts are handled.  The
+ * callback has the following signature, where `user` will be set to the
+ * authenticated user on a successful authentication attempt, or `false`
+ * otherwise.  An optional `info` argument will be passed, containing additional
+ * details provided by the strategy's verify callback.
+ *
+ *     app.get('/protected', function(req, res, next) {
+ *       passport.authenticate('local', function(err, user, info) {
+ *         if (err) { return next(err) }
+ *         if (!user) { return res.redirect('/signin') }
+ *         res.redirect('/account');
+ *       })(req, res, next);
+ *     });
+ *
+ * Note that if a callback is supplied, it becomes the application's
+ * responsibility to log-in the user, establish a session, and otherwise perform
+ * the desired operations.
+ *
+ * Examples:
+ *
+ *     passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' });
+ *
+ *     passport.authenticate('basic', { session: false });
+ *
+ *     passport.authenticate('twitter');
+ *
+ * @param {String} name
+ * @param {Object} options
+ * @param {Function} callback
+ * @return {Function}
+ * @api public
+ */
+module.exports = function authenticate(name, options, callback) {
+  if (!callback && typeof options === 'function') {
+    callback = options;
+    options = {};
+  }
+  options = options || {};
+  
+  // Cast `name` to an array, allowing authentication to pass through a chain of
+  // strategies.  The first strategy to succeed, redirect, or error will halt
+  // the chain.  Authentication failures will proceed through each strategy in
+  // series, ultimately failing if all strategies fail.
+  //
+  // This is typically used on API endpoints to allow clients to authenticate
+  // using their preferred choice of Basic, Digest, token-based schemes, etc.
+  // It is not feasible to construct a chain of multiple strategies that involve
+  // redirection (for example both Facebook and Twitter), since the first one to
+  // redirect will halt the chain.
+  if (!Array.isArray(name)) {
+    name = [ name ];
+  }
+  
+  return function authenticate(req, res, next) {
+    var passport = this;
+    
+    // accumulator for failures from each strategy in the chain
+    var failures = [];
+    
+    function allFailed() {
+      if (callback) {
+        if (failures.length == 1) {
+          return callback(null, false, failures[0].challenge, failures[0].status);
+        } else {
+          var challenges = failures.map(function(f) { return f.challenge; });
+          var statuses = failures.map(function(f) { return f.status; })
+          return callback(null, false, challenges, statuses);
+        }
+      }
+      
+      // Strategies are ordered by priority.  For the purpose of flashing a
+      // message, the first failure will be displayed.
+      var failure = failures[0] || {}
+        , challenge = failure.challenge || {};
+    
+      if (options.failureFlash) {
+        var flash = options.failureFlash;
+        if (typeof flash == 'string') {
+          flash = { type: 'error', message: flash };
+        }
+        flash.type = flash.type || 'error';
+      
+        var type = flash.type || challenge.type || 'error';
+        var msg = flash.message || challenge.message || challenge;
+        if (typeof msg == 'string') {
+          req.flash(type, msg);
+        }
+      }
+      if (options.failureMessage) {
+        var msg = options.failureMessage;
+        if (typeof msg == 'boolean') {
+          msg = challenge.message || challenge;
+        }
+        if (typeof msg == 'string') {
+          req.session.messages = req.session.messages || [];
+          req.session.messages.push(msg);
+        }
+      }
+      if (options.failureRedirect) {
+        return res.redirect(options.failureRedirect);
+      }
+    
+      // When failure handling is not delegated to the application, the default
+      // is to respond with 401 Unauthorized.  Note that the WWW-Authenticate
+      // header will be set according to the strategies in use (see
+      // actions#fail).  If multiple strategies failed, each of their challenges
+      // will be included in the response.
+      var rchallenge = []
+        , rstatus;
+      
+      for (var j = 0, len = failures.length; j < len; j++) {
+        var failure = failures[j]
+          , challenge = failure.challenge || {}
+          , status = failure.status;
+        if (typeof challenge == 'number') {
+          status = challenge;
+          challenge = null;
+        }
+          
+        rstatus = rstatus || status;
+        if (typeof challenge == 'string') {
+          rchallenge.push(challenge)
+        }
+      }
+    
+      res.statusCode = rstatus || 401;
+      if (rchallenge.length) {
+        res.setHeader('WWW-Authenticate', rchallenge);
+      }
+      res.end('Unauthorized');
+    }
+    
+    (function attempt(i) {
+      var delegate = {};
+      delegate.success = function(user, info) {
+        if (callback) {
+          return callback(null, user, info);
+        }
+      
+        info = info || {}
+      
+        if (options.successFlash) {
+          var flash = options.successFlash;
+          if (typeof flash == 'string') {
+            flash = { type: 'success', message: flash };
+          }
+          flash.type = flash.type || 'success';
+        
+          var type = flash.type || info.type || 'success';
+          var msg = flash.message || info.message || info;
+          if (typeof msg == 'string') {
+            req.flash(type, msg);
+          }
+        }
+        if (options.successMessage) {
+          var msg = options.successMessage;
+          if (typeof msg == 'boolean') {
+            msg = info.message || info;
+          }
+          if (typeof msg == 'string') {
+            req.session.messages = req.session.messages || [];
+            req.session.messages.push(msg);
+          }
+        }
+        if (options.assignProperty) {
+          req[options.assignProperty] = user;
+          return next();
+        }
+      
+        req.logIn(user, options, function(err) {
+          if (err) { return next(err); }
+          if (options.authInfo || options.authInfo === undefined) {
+            passport.transformAuthInfo(info, function(err, tinfo) {
+              if (err) { return next(err); }
+              req.authInfo = tinfo;
+              complete();
+            });
+          } else {
+            complete();
+          }
+        
+          function complete() {
+            if (options.successReturnToOrRedirect) {
+              var url = options.successReturnToOrRedirect;
+              if (req.session && req.session.returnTo) {
+                url = req.session.returnTo;
+                delete req.session.returnTo;
+              }
+              return res.redirect(url);
+            }
+            if (options.successRedirect) {
+              return res.redirect(options.successRedirect);
+            }
+            next();
+          }
+        });
+      }
+      delegate.fail = function(challenge, status) {
+        // push this failure into the accumulator and attempt authentication
+        // using the next strategy
+        failures.push({ challenge: challenge, status: status });
+        attempt(i + 1);
+      }
+    
+      var layer = name[i];
+      // If no more strategies exist in the chain, authentication has failed.
+      if (!layer) { return allFailed(); }
+    
+      // Get the strategy, which will be used as prototype from which to create
+      // a new instance.  Action functions will then be bound to the strategy
+      // within the context of the HTTP request/response pair.
+      var prototype = passport._strategy(layer);
+      if (!prototype) { return next(new Error('no strategy registered under name: ' + layer)); }
+    
+      var strategy = Object.create(prototype);
+      var context = new Context(delegate, req, res, next);
+      augment(strategy, actions, context);
+    
+      strategy.authenticate(req, options);
+    })(0); // attempt
+  }
+}
+
+
+function augment(strategy, actions, ctx) {
+  for (var method in actions) {
+    strategy[method] = actions[method].bind(ctx);
+  }
+}
Index: Dev/trunk/src/node_modules/passport/lib/passport/middleware/initialize.js
===================================================================
--- Dev/trunk/src/node_modules/passport/lib/passport/middleware/initialize.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/lib/passport/middleware/initialize.js	(revision 484)
@@ -0,0 +1,71 @@
+/**
+ * Module dependencies.
+ */
+var util = require('util');
+
+
+/**
+ * Passport initialization.
+ *
+ * Intializes Passport for incoming requests, allowing authentication strategies
+ * to be applied.
+ *
+ * If sessions are being utilized, applications must set up Passport with
+ * functions to serialize a user into and out of a session.  For example, a
+ * common pattern is to serialize just the user ID into the session (due to the
+ * fact that it is desirable to store the minimum amount of data in a session).
+ * When a subsequent request arrives for the session, the full User object can
+ * be loaded from the database by ID.
+ *
+ * Note that additional middleware is required to persist login state, so we
+ * must use the `connect.session()` middleware _before_ `passport.initialize()`.
+ *
+ * This middleware must be in use by the Connect/Express application for
+ * Passport to operate.
+ *
+ * Examples:
+ *
+ *     app.configure(function() {
+ *       app.use(connect.cookieParser());
+ *       app.use(connect.session({ secret: 'keyboard cat' }));
+ *       app.use(passport.initialize());
+ *       app.use(passport.session());
+ *     });
+ *
+ *     passport.serializeUser(function(user, done) {
+ *       done(null, user.id);
+ *     });
+ *
+ *     passport.deserializeUser(function(id, done) {
+ *       User.findById(id, function (err, user) {
+ *         done(err, user);
+ *       });
+ *     });
+ *
+ * @return {Function}
+ * @api public
+ */
+module.exports = function initialize() {
+  
+  return function initialize(req, res, next) {
+    var passport = this;
+    req._passport = {};
+    req._passport.instance = passport;
+
+    //console.log('!! session: ' + util.inspect(req.session));
+    
+    if (req.session && req.session[passport._key]) {
+      // load data from existing session
+      req._passport.session = req.session[passport._key];
+    } else if (req.session) {
+      // initialize new session
+      req.session[passport._key] = {};
+      req._passport.session = req.session[passport._key];
+    } else {
+      // no session is available
+      req._passport.session = {};
+    }
+    
+    next();
+  }
+}
Index: Dev/trunk/src/node_modules/passport/lib/passport/strategies/session.js
===================================================================
--- Dev/trunk/src/node_modules/passport/lib/passport/strategies/session.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/lib/passport/strategies/session.js	(revision 484)
@@ -0,0 +1,75 @@
+/**
+ * Module dependencies.
+ */
+var pause = require('pause')
+  , util = require('util')
+  , Strategy = require('../strategy');
+
+
+/**
+ * `SessionStrategy` constructor.
+ *
+ * @api protected
+ */
+function SessionStrategy() {
+  Strategy.call(this);
+  this.name = 'session';
+}
+
+/**
+ * Inherit from `Strategy`.
+ */
+util.inherits(SessionStrategy, Strategy);
+
+/**
+ * Authenticate request based on the current session state.
+ *
+ * The session authentication strategy uses the session to restore any login
+ * state across requests.  If a login session has been established, `req.user`
+ * will be populated with the current user.
+ *
+ * This strategy is registered automatically by Passport.
+ *
+ * @param {Object} req
+ * @param {Object} options
+ * @api protected
+ */
+SessionStrategy.prototype.authenticate = function(req, options) {
+  if (!req._passport) { return this.error(new Error('passport.initialize() middleware not in use')); }
+  options = options || {};
+
+  var self = this
+    , su = req._passport.session.user;
+  if (su || su === 0) {
+    // NOTE: Stream pausing is desirable in the case where later middleware is
+    //       listening for events emitted from request.  For discussion on the
+    //       matter, refer to: https://github.com/jaredhanson/passport/pull/106
+    
+    var paused = options.pauseStream ? pause(req) : null;
+    req._passport.instance.deserializeUser(su, function(err, user) {
+      if (err) { return self.error(err); }
+      if (!user) {
+        delete req._passport.session.user;
+        self.pass();
+        if (paused) {
+          paused.resume();
+        }
+        return;
+      };
+      var property = req._passport.instance._userProperty || 'user';
+      req[property] = user;
+      self.pass();
+      if (paused) {
+        paused.resume();
+      }
+    });
+  } else {
+    self.pass();
+  }
+}
+
+
+/**
+ * Expose `SessionStrategy`.
+ */ 
+module.exports = SessionStrategy;
Index: Dev/trunk/src/node_modules/passport/lib/passport/strategy.js
===================================================================
--- Dev/trunk/src/node_modules/passport/lib/passport/strategy.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/lib/passport/strategy.js	(revision 484)
@@ -0,0 +1,33 @@
+/**
+ * Module dependencies.
+ */
+var util = require('util');
+
+
+/**
+ * `Strategy` constructor.
+ *
+ * @api public
+ */
+function Strategy() {
+}
+
+/**
+ * Authenticate request.
+ *
+ * This function must be overridden by subclasses.  In abstract form, it always
+ * throws an exception.
+ *
+ * @param {Object} req
+ * @param {Object} options
+ * @api protected
+ */
+Strategy.prototype.authenticate = function(req, options) {
+  throw new Error('Strategy#authenticate must be overridden by subclass');
+}
+
+
+/**
+ * Expose `Strategy`.
+ */
+module.exports = Strategy;
Index: Dev/trunk/src/node_modules/passport/node_modules/pause/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pause/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pause/.npmignore	(revision 484)
@@ -0,0 +1,4 @@
+support
+test
+examples
+*.sock
Index: Dev/trunk/src/node_modules/passport/node_modules/pause/History.md
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pause/History.md	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pause/History.md	(revision 484)
@@ -0,0 +1,5 @@
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
Index: Dev/trunk/src/node_modules/passport/node_modules/pause/Makefile
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pause/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pause/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+
+test:
+	@./node_modules/.bin/mocha \
+		--require should \
+		--reporter spec
+
+.PHONY: test
Index: Dev/trunk/src/node_modules/passport/node_modules/pause/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pause/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pause/Readme.md	(revision 484)
@@ -0,0 +1,29 @@
+
+# pause
+
+  Pause streams...
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2012 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.
Index: Dev/trunk/src/node_modules/passport/node_modules/pause/index.js
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pause/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pause/index.js	(revision 484)
@@ -0,0 +1,29 @@
+
+module.exports = 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]);
+      }
+    }
+  };
+};
Index: Dev/trunk/src/node_modules/passport/node_modules/pause/package.json
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pause/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pause/package.json	(revision 484)
@@ -0,0 +1,24 @@
+{
+  "name": "pause",
+  "version": "0.0.1",
+  "description": "Pause streams...",
+  "keywords": [],
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "main": "index",
+  "readme": "\n# pause\n\n  Pause streams...\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
+  "readmeFilename": "Readme.md",
+  "_id": "pause@0.0.1",
+  "dist": {
+    "shasum": "dc3b2287742f3f6249f2d228e74cff5a3f9fe8da"
+  },
+  "_from": "pause@0.0.1",
+  "_resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz"
+}
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/.npmignore	(revision 484)
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/README.md
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/README.md	(revision 484)
@@ -0,0 +1,85 @@
+# node-pkginfo
+
+An easy way to expose properties on a module from a package.json
+
+## Installation
+
+### Installing npm (node package manager)
+```
+  curl http://npmjs.org/install.sh | sh
+```
+
+### Installing pkginfo
+```
+  [sudo] npm install pkginfo
+```
+
+## Motivation
+How often when writing node.js modules have you written the following line(s) of code? 
+
+* Hard code your version string into your code
+
+``` js
+  exports.version = '0.1.0';
+```
+
+* Programmatically expose the version from the package.json
+
+``` js
+  exports.version = JSON.parse(fs.readFileSync('/path/to/package.json', 'utf8')).version;
+```
+
+In other words, how often have you wanted to expose basic information from your package.json onto your module programmatically? **WELL NOW YOU CAN!**
+
+## Usage
+
+Using `pkginfo` is idiot-proof, just require and invoke it. 
+
+``` js
+  var pkginfo = require('pkginfo')(module);
+  
+  console.dir(module.exports);
+```
+
+By invoking the `pkginfo` module all of the properties in your `package.json` file will be automatically exposed on the callee module (i.e. the parent module of `pkginfo`). 
+
+Here's a sample of the output:
+
+```
+  { name: 'simple-app',
+    description: 'A test fixture for pkginfo',
+    version: '0.1.0',
+    author: 'Charlie Robbins <charlie.robbins@gmail.com>',
+    keywords: [ 'test', 'fixture' ],
+    main: './index.js',
+    scripts: { test: 'vows test/*-test.js --spec' },
+    engines: { node: '>= 0.4.0' } }
+```
+
+### Expose specific properties
+If you don't want to expose **all** properties on from your `package.json` on your module then simple pass those properties to the `pkginfo` function:
+
+``` js
+  var pkginfo = require('pkginfo')(module, 'version', 'author');
+  
+  console.dir(module.exports);
+```
+
+```
+  { version: '0.1.0',
+    author: 'Charlie Robbins <charlie.robbins@gmail.com>' }
+```
+
+If you're looking for further usage see the [examples][0] included in this repository. 
+
+## Run Tests
+Tests are written in [vows][1] and give complete coverage of all APIs.
+
+```
+  vows test/*-test.js --spec
+```
+
+[0]: https://github.com/indexzero/node-pkginfo/tree/master/examples
+[1]: http://vowsjs.org
+
+#### Author: [Charlie Robbins](http://nodejitsu.com)
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/docs/docco.css
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/docs/docco.css	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/docs/docco.css	(revision 484)
@@ -0,0 +1,194 @@
+/*--------------------- Layout and Typography ----------------------------*/
+body {
+  font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
+  font-size: 15px;
+  line-height: 22px;
+  color: #252519;
+  margin: 0; padding: 0;
+}
+a {
+  color: #261a3b;
+}
+  a:visited {
+    color: #261a3b;
+  }
+p {
+  margin: 0 0 15px 0;
+}
+h4, h5, h6 {
+  color: #333;
+  margin: 6px 0 6px 0;
+  font-size: 13px;
+}
+  h2, h3 {
+    margin-bottom: 0;
+    color: #000;
+  }
+    h1 {
+      margin-top: 40px;
+      margin-bottom: 15px;
+      color: #000;
+    }
+#container {
+  position: relative;
+}
+#background {
+  position: fixed;
+  top: 0; left: 525px; right: 0; bottom: 0;
+  background: #f5f5ff;
+  border-left: 1px solid #e5e5ee;
+  z-index: -1;
+}
+#jump_to, #jump_page {
+  background: white;
+  -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
+  -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
+  font: 10px Arial;
+  text-transform: uppercase;
+  cursor: pointer;
+  text-align: right;
+}
+#jump_to, #jump_wrapper {
+  position: fixed;
+  right: 0; top: 0;
+  padding: 5px 10px;
+}
+  #jump_wrapper {
+    padding: 0;
+    display: none;
+  }
+    #jump_to:hover #jump_wrapper {
+      display: block;
+    }
+    #jump_page {
+      padding: 5px 0 3px;
+      margin: 0 0 25px 25px;
+    }
+      #jump_page .source {
+        display: block;
+        padding: 5px 10px;
+        text-decoration: none;
+        border-top: 1px solid #eee;
+      }
+        #jump_page .source:hover {
+          background: #f5f5ff;
+        }
+        #jump_page .source:first-child {
+        }
+table td {
+  border: 0;
+  outline: 0;
+}
+  td.docs, th.docs {
+    max-width: 450px;
+    min-width: 450px;
+    min-height: 5px;
+    padding: 10px 25px 1px 50px;
+    overflow-x: hidden;
+    vertical-align: top;
+    text-align: left;
+  }
+    .docs pre {
+      margin: 15px 0 15px;
+      padding-left: 15px;
+    }
+    .docs p tt, .docs p code {
+      background: #f8f8ff;
+      border: 1px solid #dedede;
+      font-size: 12px;
+      padding: 0 0.2em;
+    }
+    .pilwrap {
+      position: relative;
+    }
+      .pilcrow {
+        font: 12px Arial;
+        text-decoration: none;
+        color: #454545;
+        position: absolute;
+        top: 3px; left: -20px;
+        padding: 1px 2px;
+        opacity: 0;
+        -webkit-transition: opacity 0.2s linear;
+      }
+        td.docs:hover .pilcrow {
+          opacity: 1;
+        }
+  td.code, th.code {
+    padding: 14px 15px 16px 25px;
+    width: 100%;
+    vertical-align: top;
+    background: #f5f5ff;
+    border-left: 1px solid #e5e5ee;
+  }
+    pre, tt, code {
+      font-size: 12px; line-height: 18px;
+      font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
+      margin: 0; padding: 0;
+    }
+
+
+/*---------------------- Syntax Highlighting -----------------------------*/
+td.linenos { background-color: #f0f0f0; padding-right: 10px; }
+span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
+body .hll { background-color: #ffffcc }
+body .c { color: #408080; font-style: italic }  /* Comment */
+body .err { border: 1px solid #FF0000 }         /* Error */
+body .k { color: #954121 }                      /* Keyword */
+body .o { color: #666666 }                      /* Operator */
+body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+body .cp { color: #BC7A00 }                     /* Comment.Preproc */
+body .c1 { color: #408080; font-style: italic } /* Comment.Single */
+body .cs { color: #408080; font-style: italic } /* Comment.Special */
+body .gd { color: #A00000 }                     /* Generic.Deleted */
+body .ge { font-style: italic }                 /* Generic.Emph */
+body .gr { color: #FF0000 }                     /* Generic.Error */
+body .gh { color: #000080; font-weight: bold }  /* Generic.Heading */
+body .gi { color: #00A000 }                     /* Generic.Inserted */
+body .go { color: #808080 }                     /* Generic.Output */
+body .gp { color: #000080; font-weight: bold }  /* Generic.Prompt */
+body .gs { font-weight: bold }                  /* Generic.Strong */
+body .gu { color: #800080; font-weight: bold }  /* Generic.Subheading */
+body .gt { color: #0040D0 }                     /* Generic.Traceback */
+body .kc { color: #954121 }                     /* Keyword.Constant */
+body .kd { color: #954121; font-weight: bold }  /* Keyword.Declaration */
+body .kn { color: #954121; font-weight: bold }  /* Keyword.Namespace */
+body .kp { color: #954121 }                     /* Keyword.Pseudo */
+body .kr { color: #954121; font-weight: bold }  /* Keyword.Reserved */
+body .kt { color: #B00040 }                     /* Keyword.Type */
+body .m { color: #666666 }                      /* Literal.Number */
+body .s { color: #219161 }                      /* Literal.String */
+body .na { color: #7D9029 }                     /* Name.Attribute */
+body .nb { color: #954121 }                     /* Name.Builtin */
+body .nc { color: #0000FF; font-weight: bold }  /* Name.Class */
+body .no { color: #880000 }                     /* Name.Constant */
+body .nd { color: #AA22FF }                     /* Name.Decorator */
+body .ni { color: #999999; font-weight: bold }  /* Name.Entity */
+body .ne { color: #D2413A; font-weight: bold }  /* Name.Exception */
+body .nf { color: #0000FF }                     /* Name.Function */
+body .nl { color: #A0A000 }                     /* Name.Label */
+body .nn { color: #0000FF; font-weight: bold }  /* Name.Namespace */
+body .nt { color: #954121; font-weight: bold }  /* Name.Tag */
+body .nv { color: #19469D }                     /* Name.Variable */
+body .ow { color: #AA22FF; font-weight: bold }  /* Operator.Word */
+body .w { color: #bbbbbb }                      /* Text.Whitespace */
+body .mf { color: #666666 }                     /* Literal.Number.Float */
+body .mh { color: #666666 }                     /* Literal.Number.Hex */
+body .mi { color: #666666 }                     /* Literal.Number.Integer */
+body .mo { color: #666666 }                     /* Literal.Number.Oct */
+body .sb { color: #219161 }                     /* Literal.String.Backtick */
+body .sc { color: #219161 }                     /* Literal.String.Char */
+body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
+body .s2 { color: #219161 }                     /* Literal.String.Double */
+body .se { color: #BB6622; font-weight: bold }  /* Literal.String.Escape */
+body .sh { color: #219161 }                     /* Literal.String.Heredoc */
+body .si { color: #BB6688; font-weight: bold }  /* Literal.String.Interpol */
+body .sx { color: #954121 }                     /* Literal.String.Other */
+body .sr { color: #BB6688 }                     /* Literal.String.Regex */
+body .s1 { color: #219161 }                     /* Literal.String.Single */
+body .ss { color: #19469D }                     /* Literal.String.Symbol */
+body .bp { color: #954121 }                     /* Name.Builtin.Pseudo */
+body .vc { color: #19469D }                     /* Name.Variable.Class */
+body .vg { color: #19469D }                     /* Name.Variable.Global */
+body .vi { color: #19469D }                     /* Name.Variable.Instance */
+body .il { color: #666666 }                     /* Literal.Number.Integer.Long */
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/docs/pkginfo.html
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/docs/pkginfo.html	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/docs/pkginfo.html	(revision 484)
@@ -0,0 +1,101 @@
+<!DOCTYPE html>  <html> <head>   <title>pkginfo.js</title>   <meta http-equiv="content-type" content="text/html; charset=UTF-8">   <link rel="stylesheet" media="all" href="docco.css" /> </head> <body>   <div id="container">     <div id="background"></div>          <table cellpadding="0" cellspacing="0">       <thead>         <tr>           <th class="docs">             <h1>               pkginfo.js             </h1>           </th>           <th class="code">           </th>         </tr>       </thead>       <tbody>                               <tr id="section-1">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-1">&#182;</a>               </div>                            </td>             <td class="code">               <div class="highlight"><pre><span class="cm">/*</span>
+<span class="cm"> * pkginfo.js: Top-level include for the pkginfo module</span>
+<span class="cm"> *</span>
+<span class="cm"> * (C) 2011, Charlie Robbins</span>
+<span class="cm"> *</span>
+<span class="cm"> */</span>
+ 
+<span class="kd">var</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;fs&#39;</span><span class="p">),</span>
+    <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;path&#39;</span><span class="p">);</span></pre></div>             </td>           </tr>                               <tr id="section-2">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-2">&#182;</a>               </div>               <h3>function pkginfo ([options, 'property', 'property' ..])</h3>
+
+<h4>@pmodule {Module} Parent module to read from.</h4>
+
+<h4>@options {Object|Array|string} <strong>Optional</strong> Options used when exposing properties.</h4>
+
+<h4>@arguments {string...} <strong>Optional</strong> Specified properties to expose.</h4>
+
+<p>Exposes properties from the package.json file for the parent module on 
+it's exports. Valid usage:</p>
+
+<p><code>require('pkginfo')()</code></p>
+
+<p><code>require('pkginfo')('version', 'author');</code></p>
+
+<p><code>require('pkginfo')(['version', 'author']);</code></p>
+
+<p><code>require('pkginfo')({ include: ['version', 'author'] });</code></p>             </td>             <td class="code">               <div class="highlight"><pre><span class="kd">var</span> <span class="nx">pkginfo</span> <span class="o">=</span> <span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
+  <span class="kd">var</span> <span class="nx">args</span> <span class="o">=</span> <span class="p">[].</span><span class="nx">slice</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">arguments</span><span class="p">,</span> <span class="mi">2</span><span class="p">).</span><span class="nx">filter</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">arg</span><span class="p">)</span> <span class="p">{</span>
+    <span class="k">return</span> <span class="k">typeof</span> <span class="nx">arg</span> <span class="o">===</span> <span class="s1">&#39;string&#39;</span><span class="p">;</span>
+  <span class="p">});</span>
+  </pre></div>             </td>           </tr>                               <tr id="section-3">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-3">&#182;</a>               </div>               <p><strong>Parse variable arguments</strong></p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="k">if</span> <span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">(</span><span class="nx">options</span><span class="p">))</span> <span class="p">{</span></pre></div>             </td>           </tr>                               <tr id="section-4">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-4">&#182;</a>               </div>               <p>If the options passed in is an Array assume that
+it is the Array of properties to expose from the
+on the package.json file on the parent module.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="nx">options</span> <span class="p">};</span>
+  <span class="p">}</span>
+  <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">options</span> <span class="o">===</span> <span class="s1">&#39;string&#39;</span><span class="p">)</span> <span class="p">{</span></pre></div>             </td>           </tr>                               <tr id="section-5">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-5">&#182;</a>               </div>               <p>Otherwise if the first argument is a string, then
+assume that it is the first property to expose from
+the package.json file on the parent module.</p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="nx">options</span><span class="p">]</span> <span class="p">};</span>
+  <span class="p">}</span>
+  </pre></div>             </td>           </tr>                               <tr id="section-6">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-6">&#182;</a>               </div>               <p><strong>Setup default options</strong></p>             </td>             <td class="code">               <div class="highlight"><pre>  <span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{</span> <span class="nx">include</span><span class="o">:</span> <span class="p">[]</span> <span class="p">};</span>
+  
+  <span class="k">if</span> <span class="p">(</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span></pre></div>             </td>           </tr>                               <tr id="section-7">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-7">&#182;</a>               </div>               <p>If additional string arguments have been passed in
+then add them to the properties to expose on the 
+parent module. </p>             </td>             <td class="code">               <div class="highlight"><pre>    <span class="nx">options</span><span class="p">.</span><span class="nx">include</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">args</span><span class="p">);</span>
+  <span class="p">}</span>
+  
+  <span class="kd">var</span> <span class="nx">pkg</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">dir</span><span class="p">).</span><span class="kr">package</span><span class="p">;</span>
+  <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">pkg</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
+    <span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="o">!~</span><span class="nx">options</span><span class="p">.</span><span class="nx">include</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">key</span><span class="p">))</span> <span class="p">{</span>
+      <span class="k">return</span><span class="p">;</span>
+    <span class="p">}</span>
+    
+    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">])</span> <span class="p">{</span>
+      <span class="nx">pmodule</span><span class="p">.</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">pkg</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
+    <span class="p">}</span>
+  <span class="p">});</span>
+  
+  <span class="k">return</span> <span class="nx">pkginfo</span><span class="p">;</span>
+<span class="p">};</span></pre></div>             </td>           </tr>                               <tr id="section-8">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-8">&#182;</a>               </div>               <h3>function find (dir)</h3>
+
+<h4>@pmodule {Module} Parent module to read from.</h4>
+
+<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4>
+
+<p>Searches up the directory tree from <code>dir</code> until it finds a directory
+which contains a <code>package.json</code> file. </p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span>
+  <span class="nx">dir</span> <span class="o">=</span> <span class="nx">dir</span> <span class="o">||</span> <span class="nx">pmodule</span><span class="p">.</span><span class="nx">filename</span><span class="p">;</span>
+  <span class="nx">dir</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span> 
+  
+  <span class="kd">var</span> <span class="nx">files</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readdirSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span>
+  
+  <span class="k">if</span> <span class="p">(</span><span class="o">~</span><span class="nx">files</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;package.json&#39;</span><span class="p">))</span> <span class="p">{</span>
+    <span class="k">return</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">dir</span><span class="p">,</span> <span class="s1">&#39;package.json&#39;</span><span class="p">);</span>
+  <span class="p">}</span>
+  
+  <span class="k">if</span> <span class="p">(</span><span class="nx">dir</span> <span class="o">===</span> <span class="s1">&#39;/&#39;</span><span class="p">)</span> <span class="p">{</span>
+    <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">&#39;Could not find package.json up from: &#39;</span> <span class="o">+</span> <span class="nx">dir</span><span class="p">);</span>
+  <span class="p">}</span>
+  
+  <span class="k">return</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">dir</span><span class="p">);</span>
+<span class="p">};</span></pre></div>             </td>           </tr>                               <tr id="section-9">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-9">&#182;</a>               </div>               <h3>function read (pmodule, dir)</h3>
+
+<h4>@pmodule {Module} Parent module to read from.</h4>
+
+<h4>@dir {string} <strong>Optional</strong> Directory to start search from.</h4>
+
+<p>Searches up the directory tree from <code>dir</code> until it finds a directory
+which contains a <code>package.json</code> file and returns the package information.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">.</span><span class="nx">read</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">)</span> <span class="p">{</span> 
+  <span class="nx">dir</span> <span class="o">=</span> <span class="nx">pkginfo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">pmodule</span><span class="p">,</span> <span class="nx">dir</span><span class="p">);</span>
+  
+  <span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">dir</span><span class="p">).</span><span class="nx">toString</span><span class="p">();</span>
+      
+  <span class="k">return</span> <span class="p">{</span>
+    <span class="nx">dir</span><span class="o">:</span> <span class="nx">dir</span><span class="p">,</span> 
+    <span class="kr">package</span><span class="o">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span>
+  <span class="p">};</span>
+<span class="p">};</span></pre></div>             </td>           </tr>                               <tr id="section-10">             <td class="docs">               <div class="pilwrap">                 <a class="pilcrow" href="#section-10">&#182;</a>               </div>               <p>Call <code>pkginfo</code> on this module and expose version.</p>             </td>             <td class="code">               <div class="highlight"><pre><span class="nx">pkginfo</span><span class="p">(</span><span class="nx">module</span><span class="p">,</span> <span class="p">{</span>
+  <span class="nx">dir</span><span class="o">:</span> <span class="nx">__dirname</span><span class="p">,</span>
+  <span class="nx">include</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;version&#39;</span><span class="p">],</span>
+  <span class="nx">target</span><span class="o">:</span> <span class="nx">pkginfo</span>
+<span class="p">});</span>
+
+</pre></div>             </td>           </tr>                </tbody>     </table>   </div> </body> </html> 
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/all-properties.js
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/all-properties.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/all-properties.js	(revision 484)
@@ -0,0 +1,19 @@
+/*
+ * all-properties.js: Sample of including all properties from a package.json file
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module);
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/array-argument.js
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/array-argument.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/array-argument.js	(revision 484)
@@ -0,0 +1,20 @@
+/*
+ * array-argument.js: Sample of including specific properties from a package.json file
+ *                    using Array argument syntax.
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module, ['version', 'author']);
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/multiple-properties.js
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/multiple-properties.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/multiple-properties.js	(revision 484)
@@ -0,0 +1,19 @@
+/*
+ * multiple-properties.js: Sample of including multiple properties from a package.json file
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module, 'version', 'author');
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/object-argument.js
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/object-argument.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/object-argument.js	(revision 484)
@@ -0,0 +1,22 @@
+/*
+ * object-argument.js: Sample of including specific properties from a package.json file
+ *                     using Object argument syntax.
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module, {
+      include: ['version', 'author']
+    });
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/package.json
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/package.json	(revision 484)
@@ -0,0 +1,10 @@
+{
+  "name": "simple-app",
+  "description": "A test fixture for pkginfo",
+  "version": "0.1.0",
+  "author": "Charlie Robbins <charlie.robbins@gmail.com>",
+  "keywords": ["test", "fixture"],
+  "main": "./index.js",
+  "scripts": { "test": "vows test/*-test.js --spec" },
+  "engines": { "node": ">= 0.4.0" }
+}
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/single-property.js
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/single-property.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/examples/single-property.js	(revision 484)
@@ -0,0 +1,19 @@
+/*
+ * single-property.js: Sample of including a single specific properties from a package.json file
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var util = require('util'),
+    pkginfo = require('../lib/pkginfo')(module, 'version');
+
+exports.someFunction = function () {
+  console.log('some of your custom logic here');
+};
+
+console.log('Inspecting module:');
+console.dir(module.exports);
+
+console.log('\nAll exports exposed:');
+console.error(Object.keys(module.exports));
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/lib/pkginfo.js
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/lib/pkginfo.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/lib/pkginfo.js	(revision 484)
@@ -0,0 +1,132 @@
+/*
+ * pkginfo.js: Top-level include for the pkginfo module
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+ 
+var fs = require('fs'),
+    path = require('path');
+
+//
+// ### function pkginfo ([options, 'property', 'property' ..])
+// #### @pmodule {Module} Parent module to read from.
+// #### @options {Object|Array|string} **Optional** Options used when exposing properties.
+// #### @arguments {string...} **Optional** Specified properties to expose.
+// Exposes properties from the package.json file for the parent module on 
+// it's exports. Valid usage:
+//
+// `require('pkginfo')()`
+//
+// `require('pkginfo')('version', 'author');`
+//
+// `require('pkginfo')(['version', 'author']);`
+//
+// `require('pkginfo')({ include: ['version', 'author'] });`
+//
+var pkginfo = module.exports = function (pmodule, options) {
+  var args = [].slice.call(arguments, 2).filter(function (arg) {
+    return typeof arg === 'string';
+  });
+  
+  //
+  // **Parse variable arguments**
+  //
+  if (Array.isArray(options)) {
+    //
+    // If the options passed in is an Array assume that
+    // it is the Array of properties to expose from the
+    // on the package.json file on the parent module.
+    //
+    options = { include: options };
+  }
+  else if (typeof options === 'string') {
+    //
+    // Otherwise if the first argument is a string, then
+    // assume that it is the first property to expose from
+    // the package.json file on the parent module.
+    //
+    options = { include: [options] };
+  }
+  
+  //
+  // **Setup default options**
+  //
+  options = options || { include: [] };
+  
+  if (args.length > 0) {
+    //
+    // If additional string arguments have been passed in
+    // then add them to the properties to expose on the 
+    // parent module. 
+    //
+    options.include = options.include.concat(args);
+  }
+  
+  var pkg = pkginfo.read(pmodule, options.dir).package;
+  Object.keys(pkg).forEach(function (key) {
+    if (options.include.length > 0 && !~options.include.indexOf(key)) {
+      return;
+    }
+    
+    if (!pmodule.exports[key]) {
+      pmodule.exports[key] = pkg[key];
+    }
+  });
+  
+  return pkginfo;
+};
+
+//
+// ### function find (dir)
+// #### @pmodule {Module} Parent module to read from.
+// #### @dir {string} **Optional** Directory to start search from.
+// Searches up the directory tree from `dir` until it finds a directory
+// which contains a `package.json` file. 
+//
+pkginfo.find = function (pmodule, dir) {
+  dir = dir || pmodule.filename;
+  dir = path.dirname(dir); 
+  
+  var files = fs.readdirSync(dir);
+  
+  if (~files.indexOf('package.json')) {
+    return path.join(dir, 'package.json');
+  }
+  
+  if (dir === '/') {
+    throw new Error('Could not find package.json up from: ' + dir);
+  }
+  else if (!dir || dir === '.') {
+    throw new Error('Cannot find package.json from unspecified directory');
+  }
+  
+  return pkginfo.find(pmodule, dir);
+};
+
+//
+// ### function read (pmodule, dir)
+// #### @pmodule {Module} Parent module to read from.
+// #### @dir {string} **Optional** Directory to start search from.
+// Searches up the directory tree from `dir` until it finds a directory
+// which contains a `package.json` file and returns the package information.
+//
+pkginfo.read = function (pmodule, dir) { 
+  dir = pkginfo.find(pmodule, dir);
+  
+  var data = fs.readFileSync(dir).toString();
+      
+  return {
+    dir: dir, 
+    package: JSON.parse(data)
+  };
+};
+
+//
+// Call `pkginfo` on this module and expose version.
+//
+pkginfo(module, {
+  dir: __dirname,
+  include: ['version'],
+  target: pkginfo
+});
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/package.json
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/package.json	(revision 484)
@@ -0,0 +1,39 @@
+{
+  "name": "pkginfo",
+  "version": "0.2.3",
+  "description": "An easy way to expose properties on a module from a package.json",
+  "author": {
+    "name": "Charlie Robbins",
+    "email": "charlie.robbins@gmail.com"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/indexzero/node-pkginfo.git"
+  },
+  "keywords": [
+    "info",
+    "tools",
+    "package.json"
+  ],
+  "devDependencies": {
+    "vows": "0.6.x"
+  },
+  "main": "./lib/pkginfo",
+  "scripts": {
+    "test": "vows test/*-test.js --spec"
+  },
+  "engines": {
+    "node": ">= 0.4.0"
+  },
+  "readme": "# node-pkginfo\n\nAn easy way to expose properties on a module from a package.json\n\n## Installation\n\n### Installing npm (node package manager)\n```\n  curl http://npmjs.org/install.sh | sh\n```\n\n### Installing pkginfo\n```\n  [sudo] npm install pkginfo\n```\n\n## Motivation\nHow often when writing node.js modules have you written the following line(s) of code? \n\n* Hard code your version string into your code\n\n``` js\n  exports.version = '0.1.0';\n```\n\n* Programmatically expose the version from the package.json\n\n``` js\n  exports.version = JSON.parse(fs.readFileSync('/path/to/package.json', 'utf8')).version;\n```\n\nIn other words, how often have you wanted to expose basic information from your package.json onto your module programmatically? **WELL NOW YOU CAN!**\n\n## Usage\n\nUsing `pkginfo` is idiot-proof, just require and invoke it. \n\n``` js\n  var pkginfo = require('pkginfo')(module);\n  \n  console.dir(module.exports);\n```\n\nBy invoking the `pkginfo` module all of the properties in your `package.json` file will be automatically exposed on the callee module (i.e. the parent module of `pkginfo`). \n\nHere's a sample of the output:\n\n```\n  { name: 'simple-app',\n    description: 'A test fixture for pkginfo',\n    version: '0.1.0',\n    author: 'Charlie Robbins <charlie.robbins@gmail.com>',\n    keywords: [ 'test', 'fixture' ],\n    main: './index.js',\n    scripts: { test: 'vows test/*-test.js --spec' },\n    engines: { node: '>= 0.4.0' } }\n```\n\n### Expose specific properties\nIf you don't want to expose **all** properties on from your `package.json` on your module then simple pass those properties to the `pkginfo` function:\n\n``` js\n  var pkginfo = require('pkginfo')(module, 'version', 'author');\n  \n  console.dir(module.exports);\n```\n\n```\n  { version: '0.1.0',\n    author: 'Charlie Robbins <charlie.robbins@gmail.com>' }\n```\n\nIf you're looking for further usage see the [examples][0] included in this repository. \n\n## Run Tests\nTests are written in [vows][1] and give complete coverage of all APIs.\n\n```\n  vows test/*-test.js --spec\n```\n\n[0]: https://github.com/indexzero/node-pkginfo/tree/master/examples\n[1]: http://vowsjs.org\n\n#### Author: [Charlie Robbins](http://nodejitsu.com)",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/indexzero/node-pkginfo/issues"
+  },
+  "_id": "pkginfo@0.2.3",
+  "dist": {
+    "shasum": "58124620563fa62cb389f5f82323c6089d5033a4"
+  },
+  "_from": "pkginfo@0.2.x",
+  "_resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.2.3.tgz"
+}
Index: Dev/trunk/src/node_modules/passport/node_modules/pkginfo/test/pkginfo-test.js
===================================================================
--- Dev/trunk/src/node_modules/passport/node_modules/pkginfo/test/pkginfo-test.js	(revision 484)
+++ Dev/trunk/src/node_modules/passport/node_modules/pkginfo/test/pkginfo-test.js	(revision 484)
@@ -0,0 +1,69 @@
+/*
+ * pkginfo-test.js: Tests for the pkginfo module.
+ *
+ * (C) 2011, Charlie Robbins
+ *
+ */
+
+var assert = require('assert'),
+    exec = require('child_process').exec,
+    fs = require('fs'),
+    path = require('path'),
+    vows = require('vows'),
+    pkginfo = require('../lib/pkginfo');
+
+function assertProperties (source, target) {
+  assert.lengthOf(source, target.length + 1);
+  target.forEach(function (prop) {
+    assert.isTrue(!!~source.indexOf(prop));
+  });
+}
+
+function testExposes (options) {
+  return {
+    topic: function () {
+      exec('node ' + path.join(__dirname, '..', 'examples', options.script), this.callback);
+    },
+    "should expose that property correctly": function (err, stdout, stderr) {
+      assert.isNull(err);
+      
+      var exposed = stderr.match(/'(\w+)'/ig).map(function (p) { 
+        return p.substring(1, p.length - 1);
+      });
+      
+      return !options.assert 
+        ? assertProperties(exposed, options.properties)
+        : options.assert(exposed);
+    }
+  }
+}
+
+vows.describe('pkginfo').addBatch({
+  "When using the pkginfo module": {
+    "and passed a single `string` argument": testExposes({
+      script: 'single-property.js',
+      properties: ['version']
+    }),
+    "and passed multiple `string` arguments": testExposes({
+      script: 'multiple-properties.js',
+      properties: ['version', 'author']
+    }),
+    "and passed an `object` argument": testExposes({
+      script: 'object-argument.js',
+      properties: ['version', 'author']
+    }),
+    "and passed an `array` argument": testExposes({
+      script: 'array-argument.js',
+      properties: ['version', 'author']
+    }),
+    "and passed no arguments": testExposes({
+      script: 'all-properties.js',
+      assert: function (exposed) {
+        var pkg = fs.readFileSync(path.join(__dirname, '..', 'examples', 'package.json')).toString(),
+            keys = Object.keys(JSON.parse(pkg));
+        
+        assertProperties(exposed, keys);
+      }
+    })
+  }
+}).export(module);
Index: Dev/trunk/src/node_modules/passport/package.json
===================================================================
--- Dev/trunk/src/node_modules/passport/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/passport/package.json	(revision 484)
@@ -0,0 +1,53 @@
+{
+  "name": "passport",
+  "version": "0.1.17",
+  "description": "Simple, unobtrusive authentication for Node.js.",
+  "keywords": [
+    "express",
+    "connect",
+    "auth",
+    "authn",
+    "authentication"
+  ],
+  "homepage": "http://passportjs.org/",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/jaredhanson/passport.git"
+  },
+  "bugs": {
+    "url": "http://github.com/jaredhanson/passport/issues"
+  },
+  "author": {
+    "name": "Jared Hanson",
+    "email": "jaredhanson@gmail.com",
+    "url": "http://www.jaredhanson.net/"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "http://www.opensource.org/licenses/MIT"
+    }
+  ],
+  "main": "./lib/passport",
+  "dependencies": {
+    "pkginfo": "0.2.x",
+    "pause": "0.0.1"
+  },
+  "devDependencies": {
+    "vows": "0.6.x"
+  },
+  "scripts": {
+    "test": "NODE_PATH=lib node_modules/.bin/vows test/*-test.js test/**/*-test.js test/context/http/*-test.js"
+  },
+  "engines": {
+    "node": ">= 0.4.0"
+  },
+  "readme": "# Passport\n\nPassport is [Express](http://expressjs.com/)-compatible authentication\nmiddleware for [Node.js](http://nodejs.org/).\n\nPassport's sole purpose is to authenticate requests, which it does through an\nextensible set of plugins known as _strategies_.  Passport does not mount\nroutes or assume any particular database schema, which maximizes flexiblity and\nallows application-level decisions to be made by the developer.  The API is\nsimple: you provide Passport a request to authenticate, and Passport provides\nhooks for controlling what occurs when authentication succeeds or fails.\n\n## Install\n\n    $ npm install passport\n\n## Usage\n\n#### Strategies\n\nPassport uses the concept of strategies to authenticate requests.  Strategies\ncan range from verifying username and password credentials, delegated\nauthentication using [OAuth](http://oauth.net/) (for example, via [Facebook](http://www.facebook.com/)\nor [Twitter](http://twitter.com/)), or federated authentication using [OpenID](http://openid.net/).\n\nBefore authenticating requests, the strategy (or strategies) used by an\napplication must be configured.\n\n    passport.use(new LocalStrategy(\n      function(username, password, done) {\n        User.findOne({ username: username, password: password }, function (err, user) {\n          done(err, user);\n        });\n      }\n    ));\n\n#### Sessions\n\nPassport will maintain persistent login sessions.  In order for persistent\nsessions to work, the authenticated user must be serialized to the session, and\ndeserialized when subsequent requests are made.\n\nPassport does not impose any restrictions on how your user records are stored.\nInstead, you provide functions to Passport which implements the necessary\nserialization and deserialization logic.  In a typical application, this will be\nas simple as serializing the user ID, and finding the user by ID when\ndeserializing.\n\n    passport.serializeUser(function(user, done) {\n      done(null, user.id);\n    });\n\n    passport.deserializeUser(function(id, done) {\n      User.findById(id, function (err, user) {\n        done(err, user);\n      });\n    });\n\n#### Middleware\n\nTo use Passport in an [Express](http://expressjs.com/) or\n[Connect](http://senchalabs.github.com/connect/)-based application, configure it\nwith the required `passport.initialize()` middleware.  If your application uses\npersistent login sessions (recommended, but not required), `passport.session()`\nmiddleware must also be used.\n\n    app.configure(function() {\n      app.use(express.static(__dirname + '/../../public'));\n      app.use(express.cookieParser());\n      app.use(express.bodyParser());\n      app.use(express.session({ secret: 'keyboard cat' }));\n      app.use(passport.initialize());\n      app.use(passport.session());\n      app.use(app.router);\n    });\n\n#### Authenticate Requests\n\nPassport provides an `authenticate()` function, which is used as route\nmiddleware to authenticate requests.\n\n    app.post('/login', \n      passport.authenticate('local', { failureRedirect: '/login' }),\n      function(req, res) {\n        res.redirect('/');\n      });\n\n## Examples\n\nFor a complete, working example, refer to the [login example](https://github.com/jaredhanson/passport-local/tree/master/examples/login)\nincluded in [passport-local](https://github.com/jaredhanson/passport-local).\n\n## Strategies\n\nPassport has a comprehensive set of **over 120** authentication strategies\ncovering social networking, enterprise integration, API services, and more.\nThe [complete list](https://github.com/jaredhanson/passport/wiki/Strategies) is\navailable on the [wiki](https://github.com/jaredhanson/passport/wiki).\n\nThe following table lists commonly used strategies:\n\n|Strategy                                                       | Protocol                 |Developer                                       |\n|---------------------------------------------------------------|--------------------------|------------------------------------------------|\n|[Local](https://github.com/jaredhanson/passport-local)         | HTML form                |[Jared Hanson](https://github.com/jaredhanson)  |\n|[OpenID](https://github.com/jaredhanson/passport-openid)       | OpenID                   |[Jared Hanson](https://github.com/jaredhanson)  |\n|[BrowserID](https://github.com/jaredhanson/passport-browserid) | BrowserID                |[Jared Hanson](https://github.com/jaredhanson)  |\n|[Facebook](https://github.com/jaredhanson/passport-facebook)   | OAuth 2.0                |[Jared Hanson](https://github.com/jaredhanson)  |\n|[Google](https://github.com/jaredhanson/passport-google)       | OpenID                   |[Jared Hanson](https://github.com/jaredhanson)  |\n|[Google](https://github.com/jaredhanson/passport-google-oauth) | OAuth / OAuth 2.0        |[Jared Hanson](https://github.com/jaredhanson)  |\n|[Twitter](https://github.com/jaredhanson/passport-twitter)     | OAuth                    |[Jared Hanson](https://github.com/jaredhanson)  |\n\n## Related Modules\n\n- [Locomotive](https://github.com/jaredhanson/locomotive) â Powerful MVC web framework\n- [OAuthorize](https://github.com/jaredhanson/oauthorize) â OAuth service provider toolkit\n- [OAuth2orize](https://github.com/jaredhanson/oauth2orize) â OAuth 2.0 authorization server toolkit\n- [connect-ensure-login](https://github.com/jaredhanson/connect-ensure-login)  â middleware to ensure login sessions\n\nThe [modules](https://github.com/jaredhanson/passport/wiki/Modules) page on the\n[wiki](https://github.com/jaredhanson/passport/wiki) lists other useful modules\nthat build upon or integrate with Passport.\n\n## Tests\n\n    $ npm install --dev\n    $ make test\n\n[![Build Status](https://secure.travis-ci.org/jaredhanson/passport.png)](http://travis-ci.org/jaredhanson/passport)\n\n## Credits\n\n  - [Jared Hanson](http://github.com/jaredhanson)\n\n## License\n\n[The MIT License](http://opensource.org/licenses/MIT)\n\nCopyright (c) 2011-2013 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)>\n",
+  "readmeFilename": "README.md",
+  "_id": "passport@0.1.17",
+  "dist": {
+    "shasum": "7743a467789ec0ed38be04e8820104cbadded67c"
+  },
+  "_from": "passport@",
+  "_resolved": "https://registry.npmjs.org/passport/-/passport-0.1.17.tgz"
+}
Index: Dev/trunk/src/node_modules/q/CONTRIBUTING.md
===================================================================
--- Dev/trunk/src/node_modules/q/CONTRIBUTING.md	(revision 484)
+++ Dev/trunk/src/node_modules/q/CONTRIBUTING.md	(revision 484)
@@ -0,0 +1,40 @@
+
+For pull requests:
+
+-   Be consistent with prevalent style and design decisions.
+-   Add a Jasmine spec to `specs/q-spec.js`.
+-   Use `npm test` to avoid regressions.
+-   Run tests in `q-spec/run.html` in as many supported browsers as you
+    can find the will to deal with.
+-   Do not build minified versions; we do this each release.
+-   If you would be so kind, add a note to `CHANGES.md` in an
+    appropriate section:
+
+    -   `Next Major Version` if it introduces backward incompatibilities
+        to code in the wild using documented features.
+    -   `Next Minor Version` if it adds a new feature.
+    -   `Next Patch Version` if it fixes a bug.
+
+For releases:
+
+-   Run `npm test`.
+-   Run tests in `q-spec/run.html` in a representative sample of every
+    browser under the sun.
+-   Run `npm run cover` and make sure you're happy with the results.
+-   Run `npm run minify` and be sure to commit the resulting `q.min.js`.
+-   Note the Gzipped size output by the previous command, and update
+    `README.md` if it has changed to 1 significant digit.
+-   Stash any local changes.
+-   Update `CHANGES.md` to reflect all changes in the differences
+    between `HEAD` and the previous tagged version.  Give credit where
+    credit is due.
+-   Update `README.md` to address all new, non-experimental features.
+-   Update the API reference on the Wiki to reflect all non-experimental
+    features.
+-   Use `npm version major|minor|patch` to update `package.json`,
+    commit, and tag the new version.
+-   Use `npm publish` to send up a new release.
+-   Send an email to the q-continuum mailing list announcing the new
+    release and the notes from the change log.  This helps folks
+    maintaining other package ecosystems.
+
Index: Dev/trunk/src/node_modules/q/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/q/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/q/LICENSE	(revision 484)
@@ -0,0 +1,19 @@
+
+Copyright 2009â2012 Kristopher Michael Kowal. All rights reserved.
+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.
Index: Dev/trunk/src/node_modules/q/README.md
===================================================================
--- Dev/trunk/src/node_modules/q/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/q/README.md	(revision 484)
@@ -0,0 +1,802 @@
+[![Build Status](https://secure.travis-ci.org/kriskowal/q.png?branch=master)](http://travis-ci.org/kriskowal/q)
+
+<a href="http://promises-aplus.github.com/promises-spec">
+    <img src="http://promises-aplus.github.com/promises-spec/assets/logo-small.png"
+         align="right" alt="Promises/A+ logo" />
+</a>
+
+If a function cannot return a value or throw an exception without
+blocking, it can return a promise instead.  A promise is an object
+that represents the return value or the thrown exception that the
+function may eventually provide.  A promise can also be used as a
+proxy for a [remote object][Q-Connection] to overcome latency.
+
+[Q-Connection]: https://github.com/kriskowal/q-connection
+
+On the first pass, promises can mitigate the â[Pyramid of
+Doom][POD]â: the situation where code marches to the right faster
+than it marches forward.
+
+[POD]: http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/
+
+```javascript
+step1(function (value1) {
+    step2(value1, function(value2) {
+        step3(value2, function(value3) {
+            step4(value3, function(value4) {
+                // Do something with value4
+            });
+        });
+    });
+});
+```
+
+With a promise library, you can flatten the pyramid.
+
+```javascript
+Q.fcall(step1)
+.then(step2)
+.then(step3)
+.then(step4)
+.then(function (value4) {
+    // Do something with value4
+}, function (error) {
+    // Handle any error from step1 through step4
+})
+.done();
+```
+
+With this approach, you also get implicit error propagation,
+just like ``try``, ``catch``, and ``finally``.  An error in
+``step1`` will flow all the way to ``step5``, where itâs
+caught and handled.
+
+The callback approach is called an âinversion of controlâ.
+A function that accepts a callback instead of a return value
+is saying, âDonât call me, Iâll call you.â.  Promises
+[un-invert][IOC] the inversion, cleanly separating the input
+arguments from control flow arguments.  This simplifies the
+use and creation of APIâs, particularly variadic,
+rest and spread arguments.
+
+[IOC]: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript
+
+
+## Getting Started
+
+The Q module can be loaded as:
+
+-   A ``<script>`` tag (creating a ``Q`` global variable): ~2.5 KB minified and
+    gzipped.
+-   A Node.js and CommonJS module, available in [npm](https://npmjs.org/) as
+    the [q](https://npmjs.org/package/q) package
+-   An AMD module
+-   A [component](https://github.com/component/component) as ``microjs/q``
+-   Using [bower](http://bower.io/) as ``q``
+-   Using [NuGet](http://nuget.org/) as [Q](https://nuget.org/packages/q)
+
+Q can exchange promises with jQuery, Dojo, When.js, WinJS, and more.
+Additionally, there are many libraries that produce and consume Q promises for
+everything from file system/database access or RPC to templating. For a list of
+some of the more popular ones, see [Libraries][].
+
+Please join the Q-Continuum [mailing list](https://groups.google.com/forum/#!forum/q-continuum).
+
+[Libraries]: https://github.com/kriskowal/q/wiki/Libraries
+
+
+## Tutorial
+
+Promises have a ``then`` method, which you can use to get the eventual
+return value (fulfillment) or thrown exception (rejection).
+
+```javascript
+promiseMeSomething()
+.then(function (value) {
+}, function (reason) {
+});
+```
+
+If ``promiseMeSomething`` returns a promise that gets fulfilled later
+with a return value, the first function (the fulfillment handler) will be
+called with the value.  However, if the ``promiseMeSomething`` function
+gets rejected later by a thrown exception, the second function (the
+rejection handler) will be called with the exception.
+
+Note that resolution of a promise is always asynchronous: that is, the
+fulfillment or rejection handler will always be called in the next turn of the
+event loop (i.e. `process.nextTick` in Node). This gives you a nice
+guarantee when mentally tracing the flow of your code, namely that
+``then`` will always return before either handler is executed.
+
+
+### Propagation
+
+The ``then`` method returns a promise, which in this example, Iâm
+assigning to ``outputPromise``.
+
+```javascript
+var outputPromise = getInputPromise()
+.then(function (input) {
+}, function (reason) {
+});
+```
+
+The ``outputPromise`` variable becomes a new promise for the return
+value of either handler.  Since a function can only either return a
+value or throw an exception, only one handler will ever be called and it
+will be responsible for resolving ``outputPromise``.
+
+-   If you return a value in a handler, ``outputPromise`` will get
+    fulfilled.
+
+-   If you throw an exception in a handler, ``outputPromise`` will get
+    rejected.
+
+-   If you return a **promise** in a handler, ``outputPromise`` will
+    âbecomeâ that promise.  Being able to become a new promise is useful
+    for managing delays, combining results, or recovering from errors.
+
+If the ``getInputPromise()`` promise gets rejected and you omit the
+rejection handler, the **error** will go to ``outputPromise``:
+
+```javascript
+var outputPromise = getInputPromise()
+.then(function (value) {
+});
+```
+
+If the input promise gets fulfilled and you omit the fulfillment handler, the
+**value** will go to ``outputPromise``:
+
+```javascript
+var outputPromise = getInputPromise()
+.then(null, function (error) {
+});
+```
+
+Q promises provide a ``fail`` shorthand for ``then`` when you are only
+interested in handling the error:
+
+```javascript
+var outputPromise = getInputPromise()
+.fail(function (error) {
+});
+```
+
+If you are writing JavaScript for modern engines only or using
+CoffeeScript, you may use `catch` instead of `fail`.
+
+Promises also have a ``fin`` function that is like a ``finally`` clause.
+The final handler gets called, with no arguments, when the promise
+returned by ``getInputPromise()`` either returns a value or throws an
+error.  The value returned or error thrown by ``getInputPromise()``
+passes directly to ``outputPromise`` unless the final handler fails, and
+may be delayed if the final handler returns a promise.
+
+```javascript
+var outputPromise = getInputPromise()
+.fin(function () {
+    // close files, database connections, stop servers, conclude tests
+});
+```
+
+-   If the handler returns a value, the value is ignored
+-   If the handler throws an error, the error passes to ``outputPromise``
+-   If the handler returns a promise, ``outputPromise`` gets postponed.  The
+    eventual value or error has the same effect as an immediate return
+    value or thrown error: a value would be ignored, an error would be
+    forwarded.
+
+If you are writing JavaScript for modern engines only or using
+CoffeeScript, you may use `finally` instead of `fin`.
+
+### Chaining
+
+There are two ways to chain promises.  You can chain promises either
+inside or outside handlers.  The next two examples are equivalent.
+
+```javascript
+return getUsername()
+.then(function (username) {
+    return getUser(username)
+    .then(function (user) {
+        // if we get here without an error,
+        // the value returned here
+        // or the exception thrown here
+        // resolves the promise returned
+        // by the first line
+    })
+});
+```
+
+```javascript
+return getUsername()
+.then(function (username) {
+    return getUser(username);
+})
+.then(function (user) {
+    // if we get here without an error,
+    // the value returned here
+    // or the exception thrown here
+    // resolves the promise returned
+    // by the first line
+});
+```
+
+The only difference is nesting.  Itâs useful to nest handlers if you
+need to capture multiple input values in your closure.
+
+```javascript
+function authenticate() {
+    return getUsername()
+    .then(function (username) {
+        return getUser(username);
+    })
+    // chained because we will not need the user name in the next event
+    .then(function (user) {
+        return getPassword()
+        // nested because we need both user and password next
+        .then(function (password) {
+            if (user.passwordHash !== hash(password)) {
+                throw new Error("Can't authenticate");
+            }
+        });
+    });
+}
+```
+
+
+### Combination
+
+You can turn an array of promises into a promise for the whole,
+fulfilled array using ``all``.
+
+```javascript
+return Q.all([
+    eventualAdd(2, 2),
+    eventualAdd(10, 20)
+]);
+```
+
+If you have a promise for an array, you can use ``spread`` as a
+replacement for ``then``.  The ``spread`` function âspreadsâ the
+values over the arguments of the fulfillment handler.  The rejection handler
+will get called at the first sign of failure.  That is, whichever of
+the recived promises fails first gets handled by the rejection handler.
+
+```javascript
+function eventualAdd(a, b) {
+    return Q.spread([a, b], function (a, b) {
+        return a + b;
+    })
+}
+```
+
+But ``spread`` calls ``all`` initially, so you can skip it in chains.
+
+```javascript
+return getUsername()
+.then(function (username) {
+    return [username, getUser(username)];
+})
+.spread(function (username, user) {
+});
+```
+
+The ``all`` function returns a promise for an array of values.  When this
+promise is fulfilled, the array contains the fulfillment values of the original
+promises, in the same order as those promises.  If one of the given promises
+is rejected, the returned promise is immediately rejected, not waiting for the
+rest of the batch.  If you want to wait for all of the promises to either be
+fulfilled or rejected, you can use ``allSettled``.
+
+```javascript
+Q.allSettled(promises)
+.then(function (results) {
+    results.forEach(function (result) {
+        if (result.state === "fulfilled") {
+            var value = result.value;
+        } else {
+            var reason = result.reason;
+        }
+    });
+});
+```
+
+
+### Sequences
+
+If you have a number of promise-producing functions that need
+to be run sequentially, you can of course do so manually:
+
+```javascript
+return foo(initialVal).then(bar).then(baz).then(qux);
+```
+
+However, if you want to run a dynamically constructed sequence of
+functions, you'll want something like this:
+
+```javascript
+var funcs = [foo, bar, baz, qux];
+
+var result = Q.resolve(initialVal);
+funcs.forEach(function (f) {
+    result = result.then(f);
+});
+return result;
+```
+
+You can make this slightly more compact using `reduce`:
+
+```javascript
+return funcs.reduce(function (soFar, f) {
+    return soFar.then(f);
+}, Q.resolve(initialVal));
+```
+
+Or, you could use th ultra-compact version:
+
+```javascript
+return funcs.reduce(Q.when, Q());
+```
+
+### Handling Errors
+
+One sometimes-unintuive aspect of promises is that if you throw an
+exception in the fulfillment handler, it will not be be caught by the error
+handler.
+
+```javascript
+return foo()
+.then(function (value) {
+    throw new Error("Can't bar.");
+}, function (error) {
+    // We only get here if "foo" fails
+});
+```
+
+To see why this is, consider the parallel between promises and
+``try``/``catch``. We are ``try``-ing to execute ``foo()``: the error
+handler represents a ``catch`` for ``foo()``, while the fulfillment handler
+represents code that happens *after* the ``try``/``catch`` block.
+That code then needs its own ``try``/``catch`` block.
+
+In terms of promises, this means chaining your rejection handler:
+
+```javascript
+return foo()
+.then(function (value) {
+    throw new Error("Can't bar.");
+})
+.fail(function (error) {
+    // We get here with either foo's error or bar's error
+});
+```
+
+### Progress Notification
+
+It's possible for promises to report their progress, e.g. for tasks that take a
+long time like a file upload. Not all promises will implement progress
+notifications, but for those that do, you can consume the progress values using
+a third parameter to ``then``:
+
+```javascript
+return uploadFile()
+.then(function () {
+    // Success uploading the file
+}, function (err) {
+    // There was an error, and we get the reason for error
+}, function (progress) {
+    // We get notified of the upload's progress as it is executed
+});
+```
+
+Like `fail`, Q also provides a shorthand for progress callbacks
+called `progress`:
+
+```javascript
+return uploadFile().progress(function (progress) {
+    // We get notified of the upload's progress
+});
+```
+
+### The End
+
+When you get to the end of a chain of promises, you should either
+return the last promise or end the chain.  Since handlers catch
+errors, itâs an unfortunate pattern that the exceptions can go
+unobserved.
+
+So, either return it,
+
+```javascript
+return foo()
+.then(function () {
+    return "bar";
+});
+```
+
+Or, end it.
+
+```javascript
+foo()
+.then(function () {
+    return "bar";
+})
+.done();
+```
+
+Ending a promise chain makes sure that, if an error doesnât get
+handled before the end, it will get rethrown and reported.
+
+This is a stopgap. We are exploring ways to make unhandled errors
+visible without any explicit handling.
+
+
+### The Beginning
+
+Everything above assumes you get a promise from somewhere else.  This
+is the common case.  Every once in a while, you will need to create a
+promise from scratch.
+
+#### Using ``Q.fcall``
+
+You can create a promise from a value using ``Q.fcall``.  This returns a
+promise for 10.
+
+```javascript
+return Q.fcall(function () {
+    return 10;
+});
+```
+
+You can also use ``fcall`` to get a promise for an exception.
+
+```javascript
+return Q.fcall(function () {
+    throw new Error("Can't do it");
+});
+```
+
+As the name implies, ``fcall`` can call functions, or even promised
+functions.  This uses the ``eventualAdd`` function above to add two
+numbers.
+
+```javascript
+return Q.fcall(eventualAdd, 2, 2);
+```
+
+
+#### Using Deferreds
+
+If you have to interface with asynchronous functions that are callback-based
+instead of promise-based, Q provides a few shortcuts (like ``Q.nfcall`` and
+friends). But much of the time, the solution will be to use *deferreds*.
+
+```javascript
+var deferred = Q.defer();
+FS.readFile("foo.txt", "utf-8", function (error, text) {
+    if (error) {
+        deferred.reject(new Error(error));
+    } else {
+        deferred.resolve(text);
+    }
+});
+return deferred.promise;
+```
+
+Note that a deferred can be resolved with a value or a promise.  The
+``reject`` function is a shorthand for resolving with a rejected
+promise.
+
+```javascript
+// this:
+deferred.reject(new Error("Can't do it"));
+
+// is shorthand for:
+var rejection = Q.fcall(function () {
+    throw new Error("Can't do it");
+});
+deferred.resolve(rejection);
+```
+
+This is a simplified implementation of ``Q.delay``.
+
+```javascript
+function delay(ms) {
+    var deferred = Q.defer();
+    setTimeout(deferred.resolve, ms);
+    return deferred.promise;
+}
+```
+
+This is a simplified implementation of ``Q.timeout``
+
+```javascript
+function timeout(promise, ms) {
+    var deferred = Q.defer();
+    Q.when(promise, deferred.resolve);
+    Q.when(delay(ms), function () {
+        deferred.reject(new Error("Timed out"));
+    });
+    return deferred.promise;
+}
+```
+
+Finally, you can send a progress notification to the promise with
+``deferred.notify``.
+
+For illustration, this is a wrapper for XML HTTP requests in the browser. Note
+that a more [thorough][XHR] implementation would be in order in practice.
+
+[XHR]: https://github.com/montagejs/mr/blob/71e8df99bb4f0584985accd6f2801ef3015b9763/browser.js#L29-L73
+
+```javascript
+function requestOkText(url) {
+    var request = new XMLHttpRequest();
+    var deferred = Q.defer();
+
+    request.open("GET", url, true);
+    request.onload = onload;
+    request.onerror = onerror;
+    request.onprogress = onprogress;
+    request.send();
+
+    function onload() {
+        if (request.status === 200) {
+            deferred.resolve(request.responseText);
+        } else {
+            deferred.reject(new Error("Status code was " + request.status));
+        }
+    }
+
+    function onerror() {
+        deferred.reject(new Error("Can't XHR " + JSON.stringify(url)));
+    }
+
+    function onprogress(event) {
+        deferred.notify(event.loaded / event.total);
+    }
+
+    return deferred.promise;
+}
+```
+
+Below is an example of how to use this ``requestOkText`` function:
+
+```javascript
+requestOkText("http://localhost:3000")
+.then(function (responseText) {
+    // If the HTTP response returns 200 OK, log the response text.
+    console.log(responseText);
+}, function (error) {
+    // If there's an error or a non-200 status code, log the error.
+    console.error(error);
+}, function (progress) {
+    // Log the progress as it comes in.
+    console.log("Request progress: " + Math.round(progress * 100) + "%");
+});
+```
+
+### The Middle
+
+If you are using a function that may return a promise, but just might
+return a value if it doesnât need to defer, you can use the âstaticâ
+methods of the Q library.
+
+The ``when`` function is the static equivalent for ``then``.
+
+```javascript
+return Q.when(valueOrPromise, function (value) {
+}, function (error) {
+});
+```
+
+All of the other methods on a promise have static analogs with the
+same name.
+
+The following are equivalent:
+
+```javascript
+return Q.all([a, b]);
+```
+
+```javascript
+return Q.fcall(function () {
+    return [a, b];
+})
+.all();
+```
+
+When working with promises provided by other libraries, you should
+convert it to a Q promise.  Not all promise libraries make the same
+guarantees as Q and certainly donât provide all of the same methods.
+Most libraries only provide a partially functional ``then`` method.
+This thankfully is all we need to turn them into vibrant Q promises.
+
+```javascript
+return Q.when($.ajax(...))
+.then(function () {
+});
+```
+
+If there is any chance that the promise you receive is not a Q promise
+as provided by your library, you should wrap it using a Q function.
+You can even use ``Q.invoke`` as a shorthand.
+
+```javascript
+return Q.invoke($, 'ajax', ...)
+.then(function () {
+});
+```
+
+
+### Over the Wire
+
+A promise can serve as a proxy for another object, even a remote
+object.  There are methods that allow you to optimistically manipulate
+properties or call functions.  All of these interactions return
+promises, so they can be chained.
+
+```
+direct manipulation         using a promise as a proxy
+--------------------------  -------------------------------
+value.foo                   promise.get("foo")
+value.foo = value           promise.put("foo", value)
+delete value.foo            promise.del("foo")
+value.foo(...args)          promise.post("foo", [args])
+value.foo(...args)          promise.invoke("foo", ...args)
+value(...args)              promise.fapply([args])
+value(...args)              promise.fcall(...args)
+```
+
+If the promise is a proxy for a remote object, you can shave
+round-trips by using these functions instead of ``then``.  To take
+advantage of promises for remote objects, check out [Q-Connection][].
+
+[Q-Connection]: https://github.com/kriskowal/q-connection
+
+Even in the case of non-remote objects, these methods can be used as
+shorthand for particularly-simple fulfillment handlers. For example, you
+can replace
+
+```javascript
+return Q.fcall(function () {
+    return [{ foo: "bar" }, { foo: "baz" }];
+})
+.then(function (value) {
+    return value[0].foo;
+});
+```
+
+with
+
+```javascript
+return Q.fcall(function () {
+    return [{ foo: "bar" }, { foo: "baz" }];
+})
+.get(0)
+.get("foo");
+```
+
+
+### Adapting Node
+
+If you're working with functions that make use of the Node.js callback pattern,
+Q provides a few useful utility functions for converting between them. The
+most straightforward are probably `Q.nfcall` and `Q.nfapply` ("Node function
+call/apply") for calling Node.js-style functions and getting back a promise:
+
+```javascript
+return Q.nfcall(FS.readFile, "foo.txt", "utf-8");
+return Q.nfapply(FS.readFile, ["foo.txt", "utf-8"]);
+```
+
+If you are working with methods, instead of simple functions, you can easily
+run in to the usual problems where passing a method to another functionâlike
+`Q.nfcall`â"un-binds" the method from its owner. To avoid this, you can either
+use `Function.prototype.bind` or some nice shortcut methods we provide:
+
+```javascript
+return Q.ninvoke(redisClient, "get", "user:1:id");
+return Q.npost(redisClient, "get", ["user:1:id"]);
+```
+
+You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
+
+```javascript
+var readFile = Q.denodeify(FS.readFile);
+return readFile("foo.txt", "utf-8");
+
+var redisClientGet = Q.nbind(redisClient.get, redisClient);
+return redisClientGet("user:1:id");
+```
+
+Finally, if you're working with raw deferred objects, there is a
+`makeNodeResolver` method on deferreds that can be handy:
+
+```javascript
+var deferred = Q.defer();
+FS.readFile("foo.txt", "utf-8", deferred.makeNodeResolver());
+return deferred.promise;
+```
+
+### Long Stack Traces
+
+Q comes with optional support for âlong stack traces,â wherein the `stack`
+property of `Error` rejection reasons is rewritten to be traced along
+asynchronous jumps instead of stopping at the most recent one. As an example:
+
+```js
+function theDepthsOfMyProgram() {
+  Q.delay(100).done(function explode() {
+    throw new Error("boo!");
+  });
+}
+
+theDepthsOfMyProgram();
+```
+
+usually would give a rather unhelpful stack trace looking something like
+
+```
+Error: boo!
+    at explode (/path/to/test.js:3:11)
+    at _fulfilled (/path/to/test.js:q:54)
+    at resolvedValue.promiseDispatch.done (/path/to/q.js:823:30)
+    at makePromise.promise.promiseDispatch (/path/to/q.js:496:13)
+    at pending (/path/to/q.js:397:39)
+    at process.startup.processNextTick.process._tickCallback (node.js:244:9)
+```
+
+But, if you turn this feature on by setting
+
+```js
+Q.longStackSupport = true;
+```
+
+then the above code gives a nice stack trace to the tune of
+
+```
+Error: boo!
+    at explode (/path/to/test.js:3:11)
+From previous event:
+    at theDepthsOfMyProgram (/path/to/test.js:2:16)
+    at Object.<anonymous> (/path/to/test.js:7:1)
+```
+
+Note how you can see the the function that triggered the async operation in the
+stack trace! This is very helpful for debugging, as otherwise you end up getting
+only the first line, plus a bunch of Q internals, with no sign of where the
+operation started.
+
+This feature does come with somewhat-serious performance and memory overhead,
+however. If you're working with lots of promises, or trying to scale a server
+to many users, you should probably keep it off. But in development, go for it!
+
+## Reference
+
+A method-by-method [Q API reference][reference] is available on the wiki.
+
+[reference]: https://github.com/kriskowal/q/wiki/API-Reference
+
+## More Examples
+
+A growing [examples gallery][examples] is available on the wiki, showing how Q
+can be used to make everything better. From XHR to database access to accessing
+the Flickr API, Q is there for you.
+
+[examples]: https://github.com/kriskowal/q/wiki/Examples-Gallery
+
+## Tests
+
+You can view the results of the Q test suite [in your browser][tests]!
+
+[tests]: https://rawgithub.com/kriskowal/q/master/spec/q-spec.html
+
+---
+
+Copyright 2009-2012 Kristopher Michael Kowal
+MIT License (enclosed)
+
Index: Dev/trunk/src/node_modules/q/package.json
===================================================================
--- Dev/trunk/src/node_modules/q/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/q/package.json	(revision 484)
@@ -0,0 +1,97 @@
+{
+  "name": "q",
+  "version": "0.9.6",
+  "description": "A library for promises (CommonJS/Promises/A,B,D)",
+  "homepage": "https://github.com/kriskowal/q",
+  "author": {
+    "name": "Kris Kowal",
+    "email": "kris@cixar.com",
+    "url": "https://github.com/kriskowal"
+  },
+  "keywords": [
+    "q",
+    "promise",
+    "promises",
+    "promises-a",
+    "promises-aplus",
+    "deferred",
+    "future",
+    "async",
+    "flow control",
+    "fluent",
+    "browser",
+    "node"
+  ],
+  "contributors": [
+    {
+      "name": "Kris Kowal",
+      "email": "kris@cixar.com",
+      "url": "https://github.com/kriskowal"
+    },
+    {
+      "name": "Irakli Gozalishvili",
+      "email": "rfobic@gmail.com",
+      "url": "http://jeditoolkit.com"
+    },
+    {
+      "name": "Domenic Denicola",
+      "email": "domenic@domenicdenicola.com",
+      "url": "http://domenicdenicola.com"
+    }
+  ],
+  "bugs": {
+    "url": "http://github.com/kriskowal/q/issues"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "http://github.com/kriskowal/q/raw/master/LICENSE"
+    }
+  ],
+  "main": "q.js",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/kriskowal/q.git"
+  },
+  "engines": {
+    "node": ">=0.6.0",
+    "teleport": ">=0.2.0"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "jshint": "~2.1.3",
+    "cover": "*",
+    "jasmine-node": "1.2.2",
+    "opener": "*",
+    "promises-aplus-tests": "1.x",
+    "grunt": "~0.4.1",
+    "grunt-cli": "~0.1.9",
+    "grunt-contrib-uglify": "~0.2.2"
+  },
+  "scripts": {
+    "test": "jasmine-node spec && promises-aplus-tests spec/aplus-adapter",
+    "test-browser": "opener spec/q-spec.html",
+    "lint": "jshint q.js",
+    "cover": "cover run node_modules/jasmine-node/bin/jasmine-node spec && cover report html && opener cover_html/index.html",
+    "minify": "grunt",
+    "prepublish": "grunt"
+  },
+  "overlay": {
+    "teleport": {
+      "dependencies": {
+        "system": ">=0.0.4"
+      }
+    }
+  },
+  "directories": {
+    "test": "./spec"
+  },
+  "readme": "[![Build Status](https://secure.travis-ci.org/kriskowal/q.png?branch=master)](http://travis-ci.org/kriskowal/q)\n\n<a href=\"http://promises-aplus.github.com/promises-spec\">\n    <img src=\"http://promises-aplus.github.com/promises-spec/assets/logo-small.png\"\n         align=\"right\" alt=\"Promises/A+ logo\" />\n</a>\n\nIf a function cannot return a value or throw an exception without\nblocking, it can return a promise instead.  A promise is an object\nthat represents the return value or the thrown exception that the\nfunction may eventually provide.  A promise can also be used as a\nproxy for a [remote object][Q-Connection] to overcome latency.\n\n[Q-Connection]: https://github.com/kriskowal/q-connection\n\nOn the first pass, promises can mitigate the â[Pyramid of\nDoom][POD]â: the situation where code marches to the right faster\nthan it marches forward.\n\n[POD]: http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/\n\n```javascript\nstep1(function (value1) {\n    step2(value1, function(value2) {\n        step3(value2, function(value3) {\n            step4(value3, function(value4) {\n                // Do something with value4\n            });\n        });\n    });\n});\n```\n\nWith a promise library, you can flatten the pyramid.\n\n```javascript\nQ.fcall(step1)\n.then(step2)\n.then(step3)\n.then(step4)\n.then(function (value4) {\n    // Do something with value4\n}, function (error) {\n    // Handle any error from step1 through step4\n})\n.done();\n```\n\nWith this approach, you also get implicit error propagation,\njust like ``try``, ``catch``, and ``finally``.  An error in\n``step1`` will flow all the way to ``step5``, where itâs\ncaught and handled.\n\nThe callback approach is called an âinversion of controlâ.\nA function that accepts a callback instead of a return value\nis saying, âDonât call me, Iâll call you.â.  Promises\n[un-invert][IOC] the inversion, cleanly separating the input\narguments from control flow arguments.  This simplifies the\nuse and creation of APIâs, particularly variadic,\nrest and spread arguments.\n\n[IOC]: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript\n\n\n## Getting Started\n\nThe Q module can be loaded as:\n\n-   A ``<script>`` tag (creating a ``Q`` global variable): ~2.5 KB minified and\n    gzipped.\n-   A Node.js and CommonJS module, available in [npm](https://npmjs.org/) as\n    the [q](https://npmjs.org/package/q) package\n-   An AMD module\n-   A [component](https://github.com/component/component) as ``microjs/q``\n-   Using [bower](http://bower.io/) as ``q``\n-   Using [NuGet](http://nuget.org/) as [Q](https://nuget.org/packages/q)\n\nQ can exchange promises with jQuery, Dojo, When.js, WinJS, and more.\nAdditionally, there are many libraries that produce and consume Q promises for\neverything from file system/database access or RPC to templating. For a list of\nsome of the more popular ones, see [Libraries][].\n\nPlease join the Q-Continuum [mailing list](https://groups.google.com/forum/#!forum/q-continuum).\n\n[Libraries]: https://github.com/kriskowal/q/wiki/Libraries\n\n\n## Tutorial\n\nPromises have a ``then`` method, which you can use to get the eventual\nreturn value (fulfillment) or thrown exception (rejection).\n\n```javascript\npromiseMeSomething()\n.then(function (value) {\n}, function (reason) {\n});\n```\n\nIf ``promiseMeSomething`` returns a promise that gets fulfilled later\nwith a return value, the first function (the fulfillment handler) will be\ncalled with the value.  However, if the ``promiseMeSomething`` function\ngets rejected later by a thrown exception, the second function (the\nrejection handler) will be called with the exception.\n\nNote that resolution of a promise is always asynchronous: that is, the\nfulfillment or rejection handler will always be called in the next turn of the\nevent loop (i.e. `process.nextTick` in Node). This gives you a nice\nguarantee when mentally tracing the flow of your code, namely that\n``then`` will always return before either handler is executed.\n\n\n### Propagation\n\nThe ``then`` method returns a promise, which in this example, Iâm\nassigning to ``outputPromise``.\n\n```javascript\nvar outputPromise = getInputPromise()\n.then(function (input) {\n}, function (reason) {\n});\n```\n\nThe ``outputPromise`` variable becomes a new promise for the return\nvalue of either handler.  Since a function can only either return a\nvalue or throw an exception, only one handler will ever be called and it\nwill be responsible for resolving ``outputPromise``.\n\n-   If you return a value in a handler, ``outputPromise`` will get\n    fulfilled.\n\n-   If you throw an exception in a handler, ``outputPromise`` will get\n    rejected.\n\n-   If you return a **promise** in a handler, ``outputPromise`` will\n    âbecomeâ that promise.  Being able to become a new promise is useful\n    for managing delays, combining results, or recovering from errors.\n\nIf the ``getInputPromise()`` promise gets rejected and you omit the\nrejection handler, the **error** will go to ``outputPromise``:\n\n```javascript\nvar outputPromise = getInputPromise()\n.then(function (value) {\n});\n```\n\nIf the input promise gets fulfilled and you omit the fulfillment handler, the\n**value** will go to ``outputPromise``:\n\n```javascript\nvar outputPromise = getInputPromise()\n.then(null, function (error) {\n});\n```\n\nQ promises provide a ``fail`` shorthand for ``then`` when you are only\ninterested in handling the error:\n\n```javascript\nvar outputPromise = getInputPromise()\n.fail(function (error) {\n});\n```\n\nIf you are writing JavaScript for modern engines only or using\nCoffeeScript, you may use `catch` instead of `fail`.\n\nPromises also have a ``fin`` function that is like a ``finally`` clause.\nThe final handler gets called, with no arguments, when the promise\nreturned by ``getInputPromise()`` either returns a value or throws an\nerror.  The value returned or error thrown by ``getInputPromise()``\npasses directly to ``outputPromise`` unless the final handler fails, and\nmay be delayed if the final handler returns a promise.\n\n```javascript\nvar outputPromise = getInputPromise()\n.fin(function () {\n    // close files, database connections, stop servers, conclude tests\n});\n```\n\n-   If the handler returns a value, the value is ignored\n-   If the handler throws an error, the error passes to ``outputPromise``\n-   If the handler returns a promise, ``outputPromise`` gets postponed.  The\n    eventual value or error has the same effect as an immediate return\n    value or thrown error: a value would be ignored, an error would be\n    forwarded.\n\nIf you are writing JavaScript for modern engines only or using\nCoffeeScript, you may use `finally` instead of `fin`.\n\n### Chaining\n\nThere are two ways to chain promises.  You can chain promises either\ninside or outside handlers.  The next two examples are equivalent.\n\n```javascript\nreturn getUsername()\n.then(function (username) {\n    return getUser(username)\n    .then(function (user) {\n        // if we get here without an error,\n        // the value returned here\n        // or the exception thrown here\n        // resolves the promise returned\n        // by the first line\n    })\n});\n```\n\n```javascript\nreturn getUsername()\n.then(function (username) {\n    return getUser(username);\n})\n.then(function (user) {\n    // if we get here without an error,\n    // the value returned here\n    // or the exception thrown here\n    // resolves the promise returned\n    // by the first line\n});\n```\n\nThe only difference is nesting.  Itâs useful to nest handlers if you\nneed to capture multiple input values in your closure.\n\n```javascript\nfunction authenticate() {\n    return getUsername()\n    .then(function (username) {\n        return getUser(username);\n    })\n    // chained because we will not need the user name in the next event\n    .then(function (user) {\n        return getPassword()\n        // nested because we need both user and password next\n        .then(function (password) {\n            if (user.passwordHash !== hash(password)) {\n                throw new Error(\"Can't authenticate\");\n            }\n        });\n    });\n}\n```\n\n\n### Combination\n\nYou can turn an array of promises into a promise for the whole,\nfulfilled array using ``all``.\n\n```javascript\nreturn Q.all([\n    eventualAdd(2, 2),\n    eventualAdd(10, 20)\n]);\n```\n\nIf you have a promise for an array, you can use ``spread`` as a\nreplacement for ``then``.  The ``spread`` function âspreadsâ the\nvalues over the arguments of the fulfillment handler.  The rejection handler\nwill get called at the first sign of failure.  That is, whichever of\nthe recived promises fails first gets handled by the rejection handler.\n\n```javascript\nfunction eventualAdd(a, b) {\n    return Q.spread([a, b], function (a, b) {\n        return a + b;\n    })\n}\n```\n\nBut ``spread`` calls ``all`` initially, so you can skip it in chains.\n\n```javascript\nreturn getUsername()\n.then(function (username) {\n    return [username, getUser(username)];\n})\n.spread(function (username, user) {\n});\n```\n\nThe ``all`` function returns a promise for an array of values.  When this\npromise is fulfilled, the array contains the fulfillment values of the original\npromises, in the same order as those promises.  If one of the given promises\nis rejected, the returned promise is immediately rejected, not waiting for the\nrest of the batch.  If you want to wait for all of the promises to either be\nfulfilled or rejected, you can use ``allSettled``.\n\n```javascript\nQ.allSettled(promises)\n.then(function (results) {\n    results.forEach(function (result) {\n        if (result.state === \"fulfilled\") {\n            var value = result.value;\n        } else {\n            var reason = result.reason;\n        }\n    });\n});\n```\n\n\n### Sequences\n\nIf you have a number of promise-producing functions that need\nto be run sequentially, you can of course do so manually:\n\n```javascript\nreturn foo(initialVal).then(bar).then(baz).then(qux);\n```\n\nHowever, if you want to run a dynamically constructed sequence of\nfunctions, you'll want something like this:\n\n```javascript\nvar funcs = [foo, bar, baz, qux];\n\nvar result = Q.resolve(initialVal);\nfuncs.forEach(function (f) {\n    result = result.then(f);\n});\nreturn result;\n```\n\nYou can make this slightly more compact using `reduce`:\n\n```javascript\nreturn funcs.reduce(function (soFar, f) {\n    return soFar.then(f);\n}, Q.resolve(initialVal));\n```\n\nOr, you could use th ultra-compact version:\n\n```javascript\nreturn funcs.reduce(Q.when, Q());\n```\n\n### Handling Errors\n\nOne sometimes-unintuive aspect of promises is that if you throw an\nexception in the fulfillment handler, it will not be be caught by the error\nhandler.\n\n```javascript\nreturn foo()\n.then(function (value) {\n    throw new Error(\"Can't bar.\");\n}, function (error) {\n    // We only get here if \"foo\" fails\n});\n```\n\nTo see why this is, consider the parallel between promises and\n``try``/``catch``. We are ``try``-ing to execute ``foo()``: the error\nhandler represents a ``catch`` for ``foo()``, while the fulfillment handler\nrepresents code that happens *after* the ``try``/``catch`` block.\nThat code then needs its own ``try``/``catch`` block.\n\nIn terms of promises, this means chaining your rejection handler:\n\n```javascript\nreturn foo()\n.then(function (value) {\n    throw new Error(\"Can't bar.\");\n})\n.fail(function (error) {\n    // We get here with either foo's error or bar's error\n});\n```\n\n### Progress Notification\n\nIt's possible for promises to report their progress, e.g. for tasks that take a\nlong time like a file upload. Not all promises will implement progress\nnotifications, but for those that do, you can consume the progress values using\na third parameter to ``then``:\n\n```javascript\nreturn uploadFile()\n.then(function () {\n    // Success uploading the file\n}, function (err) {\n    // There was an error, and we get the reason for error\n}, function (progress) {\n    // We get notified of the upload's progress as it is executed\n});\n```\n\nLike `fail`, Q also provides a shorthand for progress callbacks\ncalled `progress`:\n\n```javascript\nreturn uploadFile().progress(function (progress) {\n    // We get notified of the upload's progress\n});\n```\n\n### The End\n\nWhen you get to the end of a chain of promises, you should either\nreturn the last promise or end the chain.  Since handlers catch\nerrors, itâs an unfortunate pattern that the exceptions can go\nunobserved.\n\nSo, either return it,\n\n```javascript\nreturn foo()\n.then(function () {\n    return \"bar\";\n});\n```\n\nOr, end it.\n\n```javascript\nfoo()\n.then(function () {\n    return \"bar\";\n})\n.done();\n```\n\nEnding a promise chain makes sure that, if an error doesnât get\nhandled before the end, it will get rethrown and reported.\n\nThis is a stopgap. We are exploring ways to make unhandled errors\nvisible without any explicit handling.\n\n\n### The Beginning\n\nEverything above assumes you get a promise from somewhere else.  This\nis the common case.  Every once in a while, you will need to create a\npromise from scratch.\n\n#### Using ``Q.fcall``\n\nYou can create a promise from a value using ``Q.fcall``.  This returns a\npromise for 10.\n\n```javascript\nreturn Q.fcall(function () {\n    return 10;\n});\n```\n\nYou can also use ``fcall`` to get a promise for an exception.\n\n```javascript\nreturn Q.fcall(function () {\n    throw new Error(\"Can't do it\");\n});\n```\n\nAs the name implies, ``fcall`` can call functions, or even promised\nfunctions.  This uses the ``eventualAdd`` function above to add two\nnumbers.\n\n```javascript\nreturn Q.fcall(eventualAdd, 2, 2);\n```\n\n\n#### Using Deferreds\n\nIf you have to interface with asynchronous functions that are callback-based\ninstead of promise-based, Q provides a few shortcuts (like ``Q.nfcall`` and\nfriends). But much of the time, the solution will be to use *deferreds*.\n\n```javascript\nvar deferred = Q.defer();\nFS.readFile(\"foo.txt\", \"utf-8\", function (error, text) {\n    if (error) {\n        deferred.reject(new Error(error));\n    } else {\n        deferred.resolve(text);\n    }\n});\nreturn deferred.promise;\n```\n\nNote that a deferred can be resolved with a value or a promise.  The\n``reject`` function is a shorthand for resolving with a rejected\npromise.\n\n```javascript\n// this:\ndeferred.reject(new Error(\"Can't do it\"));\n\n// is shorthand for:\nvar rejection = Q.fcall(function () {\n    throw new Error(\"Can't do it\");\n});\ndeferred.resolve(rejection);\n```\n\nThis is a simplified implementation of ``Q.delay``.\n\n```javascript\nfunction delay(ms) {\n    var deferred = Q.defer();\n    setTimeout(deferred.resolve, ms);\n    return deferred.promise;\n}\n```\n\nThis is a simplified implementation of ``Q.timeout``\n\n```javascript\nfunction timeout(promise, ms) {\n    var deferred = Q.defer();\n    Q.when(promise, deferred.resolve);\n    Q.when(delay(ms), function () {\n        deferred.reject(new Error(\"Timed out\"));\n    });\n    return deferred.promise;\n}\n```\n\nFinally, you can send a progress notification to the promise with\n``deferred.notify``.\n\nFor illustration, this is a wrapper for XML HTTP requests in the browser. Note\nthat a more [thorough][XHR] implementation would be in order in practice.\n\n[XHR]: https://github.com/montagejs/mr/blob/71e8df99bb4f0584985accd6f2801ef3015b9763/browser.js#L29-L73\n\n```javascript\nfunction requestOkText(url) {\n    var request = new XMLHttpRequest();\n    var deferred = Q.defer();\n\n    request.open(\"GET\", url, true);\n    request.onload = onload;\n    request.onerror = onerror;\n    request.onprogress = onprogress;\n    request.send();\n\n    function onload() {\n        if (request.status === 200) {\n            deferred.resolve(request.responseText);\n        } else {\n            deferred.reject(new Error(\"Status code was \" + request.status));\n        }\n    }\n\n    function onerror() {\n        deferred.reject(new Error(\"Can't XHR \" + JSON.stringify(url)));\n    }\n\n    function onprogress(event) {\n        deferred.notify(event.loaded / event.total);\n    }\n\n    return deferred.promise;\n}\n```\n\nBelow is an example of how to use this ``requestOkText`` function:\n\n```javascript\nrequestOkText(\"http://localhost:3000\")\n.then(function (responseText) {\n    // If the HTTP response returns 200 OK, log the response text.\n    console.log(responseText);\n}, function (error) {\n    // If there's an error or a non-200 status code, log the error.\n    console.error(error);\n}, function (progress) {\n    // Log the progress as it comes in.\n    console.log(\"Request progress: \" + Math.round(progress * 100) + \"%\");\n});\n```\n\n### The Middle\n\nIf you are using a function that may return a promise, but just might\nreturn a value if it doesnât need to defer, you can use the âstaticâ\nmethods of the Q library.\n\nThe ``when`` function is the static equivalent for ``then``.\n\n```javascript\nreturn Q.when(valueOrPromise, function (value) {\n}, function (error) {\n});\n```\n\nAll of the other methods on a promise have static analogs with the\nsame name.\n\nThe following are equivalent:\n\n```javascript\nreturn Q.all([a, b]);\n```\n\n```javascript\nreturn Q.fcall(function () {\n    return [a, b];\n})\n.all();\n```\n\nWhen working with promises provided by other libraries, you should\nconvert it to a Q promise.  Not all promise libraries make the same\nguarantees as Q and certainly donât provide all of the same methods.\nMost libraries only provide a partially functional ``then`` method.\nThis thankfully is all we need to turn them into vibrant Q promises.\n\n```javascript\nreturn Q.when($.ajax(...))\n.then(function () {\n});\n```\n\nIf there is any chance that the promise you receive is not a Q promise\nas provided by your library, you should wrap it using a Q function.\nYou can even use ``Q.invoke`` as a shorthand.\n\n```javascript\nreturn Q.invoke($, 'ajax', ...)\n.then(function () {\n});\n```\n\n\n### Over the Wire\n\nA promise can serve as a proxy for another object, even a remote\nobject.  There are methods that allow you to optimistically manipulate\nproperties or call functions.  All of these interactions return\npromises, so they can be chained.\n\n```\ndirect manipulation         using a promise as a proxy\n--------------------------  -------------------------------\nvalue.foo                   promise.get(\"foo\")\nvalue.foo = value           promise.put(\"foo\", value)\ndelete value.foo            promise.del(\"foo\")\nvalue.foo(...args)          promise.post(\"foo\", [args])\nvalue.foo(...args)          promise.invoke(\"foo\", ...args)\nvalue(...args)              promise.fapply([args])\nvalue(...args)              promise.fcall(...args)\n```\n\nIf the promise is a proxy for a remote object, you can shave\nround-trips by using these functions instead of ``then``.  To take\nadvantage of promises for remote objects, check out [Q-Connection][].\n\n[Q-Connection]: https://github.com/kriskowal/q-connection\n\nEven in the case of non-remote objects, these methods can be used as\nshorthand for particularly-simple fulfillment handlers. For example, you\ncan replace\n\n```javascript\nreturn Q.fcall(function () {\n    return [{ foo: \"bar\" }, { foo: \"baz\" }];\n})\n.then(function (value) {\n    return value[0].foo;\n});\n```\n\nwith\n\n```javascript\nreturn Q.fcall(function () {\n    return [{ foo: \"bar\" }, { foo: \"baz\" }];\n})\n.get(0)\n.get(\"foo\");\n```\n\n\n### Adapting Node\n\nIf you're working with functions that make use of the Node.js callback pattern,\nQ provides a few useful utility functions for converting between them. The\nmost straightforward are probably `Q.nfcall` and `Q.nfapply` (\"Node function\ncall/apply\") for calling Node.js-style functions and getting back a promise:\n\n```javascript\nreturn Q.nfcall(FS.readFile, \"foo.txt\", \"utf-8\");\nreturn Q.nfapply(FS.readFile, [\"foo.txt\", \"utf-8\"]);\n```\n\nIf you are working with methods, instead of simple functions, you can easily\nrun in to the usual problems where passing a method to another functionâlike\n`Q.nfcall`â\"un-binds\" the method from its owner. To avoid this, you can either\nuse `Function.prototype.bind` or some nice shortcut methods we provide:\n\n```javascript\nreturn Q.ninvoke(redisClient, \"get\", \"user:1:id\");\nreturn Q.npost(redisClient, \"get\", [\"user:1:id\"]);\n```\n\nYou can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:\n\n```javascript\nvar readFile = Q.denodeify(FS.readFile);\nreturn readFile(\"foo.txt\", \"utf-8\");\n\nvar redisClientGet = Q.nbind(redisClient.get, redisClient);\nreturn redisClientGet(\"user:1:id\");\n```\n\nFinally, if you're working with raw deferred objects, there is a\n`makeNodeResolver` method on deferreds that can be handy:\n\n```javascript\nvar deferred = Q.defer();\nFS.readFile(\"foo.txt\", \"utf-8\", deferred.makeNodeResolver());\nreturn deferred.promise;\n```\n\n### Long Stack Traces\n\nQ comes with optional support for âlong stack traces,â wherein the `stack`\nproperty of `Error` rejection reasons is rewritten to be traced along\nasynchronous jumps instead of stopping at the most recent one. As an example:\n\n```js\nfunction theDepthsOfMyProgram() {\n  Q.delay(100).done(function explode() {\n    throw new Error(\"boo!\");\n  });\n}\n\ntheDepthsOfMyProgram();\n```\n\nusually would give a rather unhelpful stack trace looking something like\n\n```\nError: boo!\n    at explode (/path/to/test.js:3:11)\n    at _fulfilled (/path/to/test.js:q:54)\n    at resolvedValue.promiseDispatch.done (/path/to/q.js:823:30)\n    at makePromise.promise.promiseDispatch (/path/to/q.js:496:13)\n    at pending (/path/to/q.js:397:39)\n    at process.startup.processNextTick.process._tickCallback (node.js:244:9)\n```\n\nBut, if you turn this feature on by setting\n\n```js\nQ.longStackSupport = true;\n```\n\nthen the above code gives a nice stack trace to the tune of\n\n```\nError: boo!\n    at explode (/path/to/test.js:3:11)\nFrom previous event:\n    at theDepthsOfMyProgram (/path/to/test.js:2:16)\n    at Object.<anonymous> (/path/to/test.js:7:1)\n```\n\nNote how you can see the the function that triggered the async operation in the\nstack trace! This is very helpful for debugging, as otherwise you end up getting\nonly the first line, plus a bunch of Q internals, with no sign of where the\noperation started.\n\nThis feature does come with somewhat-serious performance and memory overhead,\nhowever. If you're working with lots of promises, or trying to scale a server\nto many users, you should probably keep it off. But in development, go for it!\n\n## Reference\n\nA method-by-method [Q API reference][reference] is available on the wiki.\n\n[reference]: https://github.com/kriskowal/q/wiki/API-Reference\n\n## More Examples\n\nA growing [examples gallery][examples] is available on the wiki, showing how Q\ncan be used to make everything better. From XHR to database access to accessing\nthe Flickr API, Q is there for you.\n\n[examples]: https://github.com/kriskowal/q/wiki/Examples-Gallery\n\n## Tests\n\nYou can view the results of the Q test suite [in your browser][tests]!\n\n[tests]: https://rawgithub.com/kriskowal/q/master/spec/q-spec.html\n\n---\n\nCopyright 2009-2012 Kristopher Michael Kowal\nMIT License (enclosed)\n\n",
+  "readmeFilename": "README.md",
+  "_id": "q@0.9.6",
+  "dist": {
+    "shasum": "ff68447a49ea86f1e926dea6eb7487a110c764d5"
+  },
+  "_from": "q@",
+  "_resolved": "https://registry.npmjs.org/q/-/q-0.9.6.tgz"
+}
Index: Dev/trunk/src/node_modules/q/q.js
===================================================================
--- Dev/trunk/src/node_modules/q/q.js	(revision 484)
+++ Dev/trunk/src/node_modules/q/q.js	(revision 484)
@@ -0,0 +1,1751 @@
+// vim:ts=4:sts=4:sw=4:
+/*!
+ *
+ * Copyright 2009-2012 Kris Kowal under the terms of the MIT
+ * license found at http://github.com/kriskowal/q/raw/master/LICENSE
+ *
+ * With parts by Tyler Close
+ * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
+ * at http://www.opensource.org/licenses/mit-license.html
+ * Forked at ref_send.js version: 2009-05-11
+ *
+ * With parts by Mark Miller
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+(function (definition) {
+    // Turn off strict mode for this function so we can assign to global.Q
+    /* jshint strict: false */
+
+    // This file will function properly as a <script> tag, or a module
+    // using CommonJS and NodeJS or RequireJS module formats.  In
+    // Common/Node/RequireJS, the module exports the Q API and when
+    // executed as a simple <script>, it creates a Q global instead.
+
+    // Montage Require
+    if (typeof bootstrap === "function") {
+        bootstrap("promise", definition);
+
+    // CommonJS
+    } else if (typeof exports === "object") {
+        module.exports = definition();
+
+    // RequireJS
+    } else if (typeof define === "function" && define.amd) {
+        define(definition);
+
+    // SES (Secure EcmaScript)
+    } else if (typeof ses !== "undefined") {
+        if (!ses.ok()) {
+            return;
+        } else {
+            ses.makeQ = definition;
+        }
+
+    // <script>
+    } else {
+        Q = definition();
+    }
+
+})(function () {
+"use strict";
+
+var hasStacks = false;
+try {
+    throw new Error();
+} catch (e) {
+    hasStacks = !!e.stack;
+}
+
+// All code after this point will be filtered from stack traces reported
+// by Q.
+var qStartingLine = captureLine();
+var qFileName;
+
+// shims
+
+// used for fallback in "allResolved"
+var noop = function () {};
+
+// Use the fastest possible means to execute a task in a future turn
+// of the event loop.
+var nextTick =(function () {
+    // linked list of tasks (single, with head node)
+    var head = {task: void 0, next: null};
+    var tail = head;
+    var flushing = false;
+    var requestTick = void 0;
+    var isNodeJS = false;
+
+    function flush() {
+        while (head.next) {
+            head = head.next;
+            var task = head.task;
+            head.task = void 0;
+            var domain = head.domain;
+
+            if (domain) {
+                head.domain = void 0;
+                domain.enter();
+            }
+
+            try {
+                task();
+
+            } catch (e) {
+                if (isNodeJS) {
+                    // In node, uncaught exceptions are considered fatal errors.
+                    // Re-throw them synchronously to interrupt flushing!
+
+                    // Ensure continuation if the uncaught exception is suppressed
+                    // listening "uncaughtException" events (as domains does).
+                    // Continue in next event to avoid tick recursion.
+                    domain && domain.exit();
+                    setTimeout(flush, 0);
+                    domain && domain.enter();
+
+                    throw e;
+
+                } else {
+                    // In browsers, uncaught exceptions are not fatal.
+                    // Re-throw them asynchronously to avoid slow-downs.
+                    setTimeout(function() {
+                       throw e;
+                    }, 0);
+                }
+            }
+
+            if (domain) {
+                domain.exit();
+            }
+        }
+
+        flushing = false;
+    }
+
+    nextTick = function (task) {
+        tail = tail.next = {
+            task: task,
+            domain: isNodeJS && process.domain,
+            next: null
+        };
+
+        if (!flushing) {
+            flushing = true;
+            requestTick();
+        }
+    };
+
+    if (typeof process !== "undefined" && process.nextTick) {
+        // Node.js before 0.9. Note that some fake-Node environments, like the
+        // Mocha test runner, introduce a `process` global without a `nextTick`.
+        isNodeJS = true;
+
+        requestTick = function () {
+            process.nextTick(flush);
+        };
+
+    } else if (typeof setImmediate === "function") {
+        // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
+        if (typeof window !== "undefined") {
+            requestTick = setImmediate.bind(window, flush);
+        } else {
+            requestTick = function () {
+                setImmediate(flush);
+            };
+        }
+
+    } else if (typeof MessageChannel !== "undefined") {
+        // modern browsers
+        // http://www.nonblocking.io/2011/06/windownexttick.html
+        var channel = new MessageChannel();
+        channel.port1.onmessage = flush;
+        requestTick = function () {
+            channel.port2.postMessage(0);
+        };
+
+    } else {
+        // old browsers
+        requestTick = function () {
+            setTimeout(flush, 0);
+        };
+    }
+
+    return nextTick;
+})();
+
+// Attempt to make generics safe in the face of downstream
+// modifications.
+// There is no situation where this is necessary.
+// If you need a security guarantee, these primordials need to be
+// deeply frozen anyway, and if you donât need a security guarantee,
+// this is just plain paranoid.
+// However, this does have the nice side-effect of reducing the size
+// of the code by reducing x.call() to merely x(), eliminating many
+// hard-to-minify characters.
+// See Mark Millerâs explanation of what this does.
+// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
+function uncurryThis(f) {
+    var call = Function.call;
+    return function () {
+        return call.apply(f, arguments);
+    };
+}
+// This is equivalent, but slower:
+// uncurryThis = Function_bind.bind(Function_bind.call);
+// http://jsperf.com/uncurrythis
+
+var array_slice = uncurryThis(Array.prototype.slice);
+
+var array_reduce = uncurryThis(
+    Array.prototype.reduce || function (callback, basis) {
+        var index = 0,
+            length = this.length;
+        // concerning the initial value, if one is not provided
+        if (arguments.length === 1) {
+            // seek to the first value in the array, accounting
+            // for the possibility that is is a sparse array
+            do {
+                if (index in this) {
+                    basis = this[index++];
+                    break;
+                }
+                if (++index >= length) {
+                    throw new TypeError();
+                }
+            } while (1);
+        }
+        // reduce
+        for (; index < length; index++) {
+            // account for the possibility that the array is sparse
+            if (index in this) {
+                basis = callback(basis, this[index], index);
+            }
+        }
+        return basis;
+    }
+);
+
+var array_indexOf = uncurryThis(
+    Array.prototype.indexOf || function (value) {
+        // not a very good shim, but good enough for our one use of it
+        for (var i = 0; i < this.length; i++) {
+            if (this[i] === value) {
+                return i;
+            }
+        }
+        return -1;
+    }
+);
+
+var array_map = uncurryThis(
+    Array.prototype.map || function (callback, thisp) {
+        var self = this;
+        var collect = [];
+        array_reduce(self, function (undefined, value, index) {
+            collect.push(callback.call(thisp, value, index, self));
+        }, void 0);
+        return collect;
+    }
+);
+
+var object_create = Object.create || function (prototype) {
+    function Type() { }
+    Type.prototype = prototype;
+    return new Type();
+};
+
+var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
+
+var object_keys = Object.keys || function (object) {
+    var keys = [];
+    for (var key in object) {
+        if (object_hasOwnProperty(object, key)) {
+            keys.push(key);
+        }
+    }
+    return keys;
+};
+
+var object_toString = uncurryThis(Object.prototype.toString);
+
+function isObject(value) {
+    return value === Object(value);
+}
+
+// generator related shims
+
+// FIXME: Remove this function once ES6 generators are in SpiderMonkey.
+function isStopIteration(exception) {
+    return (
+        object_toString(exception) === "[object StopIteration]" ||
+        exception instanceof QReturnValue
+    );
+}
+
+// FIXME: Remove this helper and Q.return once ES6 generators are in
+// SpiderMonkey.
+var QReturnValue;
+if (typeof ReturnValue !== "undefined") {
+    QReturnValue = ReturnValue;
+} else {
+    QReturnValue = function (value) {
+        this.value = value;
+    };
+}
+
+// Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
+// engine that has a deployed base of browsers that support generators.
+// However, SM's generators use the Python-inspired semantics of
+// outdated ES6 drafts.  We would like to support ES6, but we'd also
+// like to make it possible to use generators in deployed browsers, so
+// we also support Python-style generators.  At some point we can remove
+// this block.
+var hasES6Generators;
+try {
+    /* jshint evil: true, nonew: false */
+    new Function("(function* (){ yield 1; })");
+    hasES6Generators = true;
+} catch (e) {
+    hasES6Generators = false;
+}
+
+// long stack traces
+
+var STACK_JUMP_SEPARATOR = "From previous event:";
+
+function makeStackTraceLong(error, promise) {
+    // If possible, transform the error stack trace by removing Node and Q
+    // cruft, then concatenating with the stack trace of `promise`. See #57.
+    if (hasStacks &&
+        promise.stack &&
+        typeof error === "object" &&
+        error !== null &&
+        error.stack &&
+        error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
+    ) {
+        var stacks = [];
+        for (var p = promise; !!p; p = p.source) {
+            if (p.stack) {
+                stacks.unshift(p.stack);
+            }
+        }
+        stacks.unshift(error.stack);
+
+        var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
+        error.stack = filterStackString(concatedStacks);
+    }
+}
+
+function filterStackString(stackString) {
+    var lines = stackString.split("\n");
+    var desiredLines = [];
+    for (var i = 0; i < lines.length; ++i) {
+        var line = lines[i];
+
+        if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
+            desiredLines.push(line);
+        }
+    }
+    return desiredLines.join("\n");
+}
+
+function isNodeFrame(stackLine) {
+    return stackLine.indexOf("(module.js:") !== -1 ||
+           stackLine.indexOf("(node.js:") !== -1;
+}
+
+function getFileNameAndLineNumber(stackLine) {
+    // Named functions: "at functionName (filename:lineNumber:columnNumber)"
+    // In IE10 function name can have spaces ("Anonymous function") O_o
+    var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
+    if (attempt1) {
+        return [attempt1[1], Number(attempt1[2])];
+    }
+
+    // Anonymous functions: "at filename:lineNumber:columnNumber"
+    var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
+    if (attempt2) {
+        return [attempt2[1], Number(attempt2[2])];
+    }
+
+    // Firefox style: "function@filename:lineNumber or @filename:lineNumber"
+    var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
+    if (attempt3) {
+        return [attempt3[1], Number(attempt3[2])];
+    }
+}
+
+function isInternalFrame(stackLine) {
+    var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
+
+    if (!fileNameAndLineNumber) {
+        return false;
+    }
+
+    var fileName = fileNameAndLineNumber[0];
+    var lineNumber = fileNameAndLineNumber[1];
+
+    return fileName === qFileName &&
+        lineNumber >= qStartingLine &&
+        lineNumber <= qEndingLine;
+}
+
+// discover own file name and line number range for filtering stack
+// traces
+function captureLine() {
+    if (!hasStacks) {
+        return;
+    }
+
+    try {
+        throw new Error();
+    } catch (e) {
+        var lines = e.stack.split("\n");
+        var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
+        var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
+        if (!fileNameAndLineNumber) {
+            return;
+        }
+
+        qFileName = fileNameAndLineNumber[0];
+        return fileNameAndLineNumber[1];
+    }
+}
+
+function deprecate(callback, name, alternative) {
+    return function () {
+        if (typeof console !== "undefined" &&
+            typeof console.warn === "function") {
+            console.warn(name + " is deprecated, use " + alternative +
+                         " instead.", new Error("").stack);
+        }
+        return callback.apply(callback, arguments);
+    };
+}
+
+// end of shims
+// beginning of real work
+
+/**
+ * Creates fulfilled promises from non-thenables,
+ * Passes Q promises through,
+ * Coerces other thenables to Q promises.
+ */
+function Q(value) {
+    return resolve(value);
+}
+
+/**
+ * Performs a task in a future turn of the event loop.
+ * @param {Function} task
+ */
+Q.nextTick = nextTick;
+
+/**
+ * Controls whether or not long stack traces will be on
+ */
+Q.longStackSupport = false;
+
+/**
+ * Constructs a {promise, resolve, reject} object.
+ *
+ * `resolve` is a callback to invoke with a more resolved value for the
+ * promise. To fulfill the promise, invoke `resolve` with any value that is
+ * not a thenable. To reject the promise, invoke `resolve` with a rejected
+ * thenable, or invoke `reject` with the reason directly. To resolve the
+ * promise to another thenable, thus putting it in the same state, invoke
+ * `resolve` with that other thenable.
+ */
+Q.defer = defer;
+function defer() {
+    // if "messages" is an "Array", that indicates that the promise has not yet
+    // been resolved.  If it is "undefined", it has been resolved.  Each
+    // element of the messages array is itself an array of complete arguments to
+    // forward to the resolved promise.  We coerce the resolution value to a
+    // promise using the `resolve` function because it handles both fully
+    // non-thenable values and other thenables gracefully.
+    var messages = [], progressListeners = [], resolvedPromise;
+
+    var deferred = object_create(defer.prototype);
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, operands) {
+        var args = array_slice(arguments);
+        if (messages) {
+            messages.push(args);
+            if (op === "when" && operands[1]) { // progress operand
+                progressListeners.push(operands[1]);
+            }
+        } else {
+            nextTick(function () {
+                resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
+            });
+        }
+    };
+
+    // XXX deprecated
+    promise.valueOf = deprecate(function () {
+        if (messages) {
+            return promise;
+        }
+        var nearerValue = nearer(resolvedPromise);
+        if (isPromise(nearerValue)) {
+            resolvedPromise = nearerValue; // shorten chain
+        }
+        return nearerValue;
+    }, "valueOf", "inspect");
+
+    promise.inspect = function () {
+        if (!resolvedPromise) {
+            return { state: "pending" };
+        }
+        return resolvedPromise.inspect();
+    };
+
+    if (Q.longStackSupport && hasStacks) {
+        try {
+            throw new Error();
+        } catch (e) {
+            // NOTE: don't try to use `Error.captureStackTrace` or transfer the
+            // accessor around; that causes memory leaks as per GH-111. Just
+            // reify the stack trace as a string ASAP.
+            //
+            // At the same time, cut off the first line; it's always just
+            // "[object Promise]\n", as per the `toString`.
+            promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
+        }
+    }
+
+    // NOTE: we do the checks for `resolvedPromise` in each method, instead of
+    // consolidating them into `become`, since otherwise we'd create new
+    // promises with the lines `become(whatever(value))`. See e.g. GH-252.
+
+    function become(newPromise) {
+        resolvedPromise = newPromise;
+        promise.source = newPromise;
+
+        array_reduce(messages, function (undefined, message) {
+            nextTick(function () {
+                newPromise.promiseDispatch.apply(newPromise, message);
+            });
+        }, void 0);
+
+        messages = void 0;
+        progressListeners = void 0;
+    }
+
+    deferred.promise = promise;
+    deferred.resolve = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(resolve(value));
+    };
+
+    deferred.fulfill = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(fulfill(value));
+    };
+    deferred.reject = function (reason) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(reject(reason));
+    };
+    deferred.notify = function (progress) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        array_reduce(progressListeners, function (undefined, progressListener) {
+            nextTick(function () {
+                progressListener(progress);
+            });
+        }, void 0);
+    };
+
+    return deferred;
+}
+
+/**
+ * Creates a Node-style callback that will resolve or reject the deferred
+ * promise.
+ * @returns a nodeback
+ */
+defer.prototype.makeNodeResolver = function () {
+    var self = this;
+    return function (error, value) {
+        if (error) {
+            self.reject(error);
+        } else if (arguments.length > 2) {
+            self.resolve(array_slice(arguments, 1));
+        } else {
+            self.resolve(value);
+        }
+    };
+};
+
+/**
+ * @param resolver {Function} a function that returns nothing and accepts
+ * the resolve, reject, and notify functions for a deferred.
+ * @returns a promise that may be resolved with the given resolve and reject
+ * functions, or rejected by a thrown exception in resolver
+ */
+Q.promise = promise;
+function promise(resolver) {
+    if (typeof resolver !== "function") {
+        throw new TypeError("resolver must be a function.");
+    }
+
+    var deferred = defer();
+    fcall(
+        resolver,
+        deferred.resolve,
+        deferred.reject,
+        deferred.notify
+    ).fail(deferred.reject);
+    return deferred.promise;
+}
+
+/**
+ * Constructs a Promise with a promise descriptor object and optional fallback
+ * function.  The descriptor contains methods like when(rejected), get(name),
+ * set(name, value), post(name, args), and delete(name), which all
+ * return either a value, a promise for a value, or a rejection.  The fallback
+ * accepts the operation name, a resolver, and any further arguments that would
+ * have been forwarded to the appropriate method above had a method been
+ * provided with the proper name.  The API makes no guarantees about the nature
+ * of the returned object, apart from that it is usable whereever promises are
+ * bought and sold.
+ */
+Q.makePromise = Promise;
+function Promise(descriptor, fallback, inspect) {
+    if (fallback === void 0) {
+        fallback = function (op) {
+            return reject(new Error(
+                "Promise does not support operation: " + op
+            ));
+        };
+    }
+    if (inspect === void 0) {
+        inspect = function () {
+            return {state: "unknown"};
+        };
+    }
+
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, args) {
+        var result;
+        try {
+            if (descriptor[op]) {
+                result = descriptor[op].apply(promise, args);
+            } else {
+                result = fallback.call(promise, op, args);
+            }
+        } catch (exception) {
+            result = reject(exception);
+        }
+        if (resolve) {
+            resolve(result);
+        }
+    };
+
+    promise.inspect = inspect;
+
+    // XXX deprecated `valueOf` and `exception` support
+    if (inspect) {
+        var inspected = inspect();
+        if (inspected.state === "rejected") {
+            promise.exception = inspected.reason;
+        }
+
+        promise.valueOf = deprecate(function () {
+            var inspected = inspect();
+            if (inspected.state === "pending" ||
+                inspected.state === "rejected") {
+                return promise;
+            }
+            return inspected.value;
+        });
+    }
+
+    return promise;
+}
+
+Promise.prototype.then = function (fulfilled, rejected, progressed) {
+    var self = this;
+    var deferred = defer();
+    var done = false;   // ensure the untrusted promise makes at most a
+                        // single call to one of the callbacks
+
+    function _fulfilled(value) {
+        try {
+            return typeof fulfilled === "function" ? fulfilled(value) : value;
+        } catch (exception) {
+            return reject(exception);
+        }
+    }
+
+    function _rejected(exception) {
+        if (typeof rejected === "function") {
+            makeStackTraceLong(exception, self);
+            try {
+                return rejected(exception);
+            } catch (newException) {
+                return reject(newException);
+            }
+        }
+        return reject(exception);
+    }
+
+    function _progressed(value) {
+        return typeof progressed === "function" ? progressed(value) : value;
+    }
+
+    nextTick(function () {
+        self.promiseDispatch(function (value) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_fulfilled(value));
+        }, "when", [function (exception) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_rejected(exception));
+        }]);
+    });
+
+    // Progress propagator need to be attached in the current tick.
+    self.promiseDispatch(void 0, "when", [void 0, function (value) {
+        var newValue;
+        var threw = false;
+        try {
+            newValue = _progressed(value);
+        } catch (e) {
+            threw = true;
+            if (Q.onerror) {
+                Q.onerror(e);
+            } else {
+                throw e;
+            }
+        }
+
+        if (!threw) {
+            deferred.notify(newValue);
+        }
+    }]);
+
+    return deferred.promise;
+};
+
+Promise.prototype.thenResolve = function (value) {
+    return when(this, function () { return value; });
+};
+
+Promise.prototype.thenReject = function (reason) {
+    return when(this, function () { throw reason; });
+};
+
+// Chainable methods
+array_reduce(
+    [
+        "isFulfilled", "isRejected", "isPending",
+        "dispatch",
+        "when", "spread",
+        "get", "set", "del", "delete",
+        "post", "send", "mapply", "invoke", "mcall",
+        "keys",
+        "fapply", "fcall", "fbind",
+        "all", "allResolved",
+        "timeout", "delay",
+        "catch", "finally", "fail", "fin", "progress", "done",
+        "nfcall", "nfapply", "nfbind", "denodeify", "nbind",
+        "npost", "nsend", "nmapply", "ninvoke", "nmcall",
+        "nodeify"
+    ],
+    function (undefined, name) {
+        Promise.prototype[name] = function () {
+            return Q[name].apply(
+                Q,
+                [this].concat(array_slice(arguments))
+            );
+        };
+    },
+    void 0
+);
+
+Promise.prototype.toSource = function () {
+    return this.toString();
+};
+
+Promise.prototype.toString = function () {
+    return "[object Promise]";
+};
+
+/**
+ * If an object is not a promise, it is as "near" as possible.
+ * If a promise is rejected, it is as "near" as possible too.
+ * If itâs a fulfilled promise, the fulfillment value is nearer.
+ * If itâs a deferred promise and the deferred has been resolved, the
+ * resolution is "nearer".
+ * @param object
+ * @returns most resolved (nearest) form of the object
+ */
+
+// XXX should we re-do this?
+Q.nearer = nearer;
+function nearer(value) {
+    if (isPromise(value)) {
+        var inspected = value.inspect();
+        if (inspected.state === "fulfilled") {
+            return inspected.value;
+        }
+    }
+    return value;
+}
+
+/**
+ * @returns whether the given object is a promise.
+ * Otherwise it is a fulfilled value.
+ */
+Q.isPromise = isPromise;
+function isPromise(object) {
+    return isObject(object) &&
+        typeof object.promiseDispatch === "function" &&
+        typeof object.inspect === "function";
+}
+
+Q.isPromiseAlike = isPromiseAlike;
+function isPromiseAlike(object) {
+    return isObject(object) && typeof object.then === "function";
+}
+
+/**
+ * @returns whether the given object is a pending promise, meaning not
+ * fulfilled or rejected.
+ */
+Q.isPending = isPending;
+function isPending(object) {
+    return isPromise(object) && object.inspect().state === "pending";
+}
+
+/**
+ * @returns whether the given object is a value or fulfilled
+ * promise.
+ */
+Q.isFulfilled = isFulfilled;
+function isFulfilled(object) {
+    return !isPromise(object) || object.inspect().state === "fulfilled";
+}
+
+/**
+ * @returns whether the given object is a rejected promise.
+ */
+Q.isRejected = isRejected;
+function isRejected(object) {
+    return isPromise(object) && object.inspect().state === "rejected";
+}
+
+//// BEGIN UNHANDLED REJECTION TRACKING
+
+// This promise library consumes exceptions thrown in handlers so they can be
+// handled by a subsequent promise.  The exceptions get added to this array when
+// they are created, and removed when they are handled.  Note that in ES6 or
+// shimmed environments, this would naturally be a `Set`.
+var unhandledReasons = [];
+var unhandledRejections = [];
+var unhandledReasonsDisplayed = false;
+var trackUnhandledRejections = true;
+function displayUnhandledReasons() {
+    if (
+        !unhandledReasonsDisplayed &&
+        typeof window !== "undefined" &&
+        !window.Touch &&
+        window.console
+    ) {
+        console.warn("[Q] Unhandled rejection reasons (should be empty):",
+                     unhandledReasons);
+    }
+
+    unhandledReasonsDisplayed = true;
+}
+
+function logUnhandledReasons() {
+    for (var i = 0; i < unhandledReasons.length; i++) {
+        var reason = unhandledReasons[i];
+        if (reason && typeof reason.stack !== "undefined") {
+            console.warn("Unhandled rejection reason:", reason.stack);
+        } else {
+            console.warn("Unhandled rejection reason (no stack):", reason);
+        }
+    }
+}
+
+function resetUnhandledRejections() {
+    unhandledReasons.length = 0;
+    unhandledRejections.length = 0;
+    unhandledReasonsDisplayed = false;
+
+    if (!trackUnhandledRejections) {
+        trackUnhandledRejections = true;
+
+        // Show unhandled rejection reasons if Node exits without handling an
+        // outstanding rejection.  (Note that Browserify presently produces a
+        // `process` global without the `EventEmitter` `on` method.)
+        if (typeof process !== "undefined" && process.on) {
+            process.on("exit", logUnhandledReasons);
+        }
+    }
+}
+
+function trackRejection(promise, reason) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+
+    unhandledRejections.push(promise);
+    unhandledReasons.push(reason);
+    displayUnhandledReasons();
+}
+
+function untrackRejection(promise) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+
+    var at = array_indexOf(unhandledRejections, promise);
+    if (at !== -1) {
+        unhandledRejections.splice(at, 1);
+        unhandledReasons.splice(at, 1);
+    }
+}
+
+Q.resetUnhandledRejections = resetUnhandledRejections;
+
+Q.getUnhandledReasons = function () {
+    // Make a copy so that consumers can't interfere with our internal state.
+    return unhandledReasons.slice();
+};
+
+Q.stopUnhandledRejectionTracking = function () {
+    resetUnhandledRejections();
+    if (typeof process !== "undefined" && process.on) {
+        process.removeListener("exit", logUnhandledReasons);
+    }
+    trackUnhandledRejections = false;
+};
+
+resetUnhandledRejections();
+
+//// END UNHANDLED REJECTION TRACKING
+
+/**
+ * Constructs a rejected promise.
+ * @param reason value describing the failure
+ */
+Q.reject = reject;
+function reject(reason) {
+    var rejection = Promise({
+        "when": function (rejected) {
+            // note that the error has been handled
+            if (rejected) {
+                untrackRejection(this);
+            }
+            return rejected ? rejected(reason) : this;
+        }
+    }, function fallback() {
+        return this;
+    }, function inspect() {
+        return { state: "rejected", reason: reason };
+    });
+
+    // Note that the reason has not been handled.
+    trackRejection(rejection, reason);
+
+    return rejection;
+}
+
+/**
+ * Constructs a fulfilled promise for an immediate reference.
+ * @param value immediate reference
+ */
+Q.fulfill = fulfill;
+function fulfill(value) {
+    return Promise({
+        "when": function () {
+            return value;
+        },
+        "get": function (name) {
+            return value[name];
+        },
+        "set": function (name, rhs) {
+            value[name] = rhs;
+        },
+        "delete": function (name) {
+            delete value[name];
+        },
+        "post": function (name, args) {
+            // Mark Miller proposes that post with no name should apply a
+            // promised function.
+            if (name === null || name === void 0) {
+                return value.apply(void 0, args);
+            } else {
+                return value[name].apply(value, args);
+            }
+        },
+        "apply": function (thisP, args) {
+            return value.apply(thisP, args);
+        },
+        "keys": function () {
+            return object_keys(value);
+        }
+    }, void 0, function inspect() {
+        return { state: "fulfilled", value: value };
+    });
+}
+
+/**
+ * Constructs a promise for an immediate reference, passes promises through, or
+ * coerces promises from different systems.
+ * @param value immediate reference or promise
+ */
+Q.resolve = resolve;
+function resolve(value) {
+    // If the object is already a Promise, return it directly.  This enables
+    // the resolve function to both be used to created references from objects,
+    // but to tolerably coerce non-promises to promises.
+    if (isPromise(value)) {
+        return value;
+    }
+
+    // assimilate thenables
+    if (isPromiseAlike(value)) {
+        return coerce(value);
+    } else {
+        return fulfill(value);
+    }
+}
+
+/**
+ * Converts thenables to Q promises.
+ * @param promise thenable promise
+ * @returns a Q promise
+ */
+function coerce(promise) {
+    var deferred = defer();
+    nextTick(function () {
+        try {
+            promise.then(deferred.resolve, deferred.reject, deferred.notify);
+        } catch (exception) {
+            deferred.reject(exception);
+        }
+    });
+    return deferred.promise;
+}
+
+/**
+ * Annotates an object such that it will never be
+ * transferred away from this process over any promise
+ * communication channel.
+ * @param object
+ * @returns promise a wrapping of that object that
+ * additionally responds to the "isDef" message
+ * without a rejection.
+ */
+Q.master = master;
+function master(object) {
+    return Promise({
+        "isDef": function () {}
+    }, function fallback(op, args) {
+        return dispatch(object, op, args);
+    }, function () {
+        return resolve(object).inspect();
+    });
+}
+
+/**
+ * Registers an observer on a promise.
+ *
+ * Guarantees:
+ *
+ * 1. that fulfilled and rejected will be called only once.
+ * 2. that either the fulfilled callback or the rejected callback will be
+ *    called, but not both.
+ * 3. that fulfilled and rejected will not be called in this turn.
+ *
+ * @param value      promise or immediate reference to observe
+ * @param fulfilled  function to be called with the fulfilled value
+ * @param rejected   function to be called with the rejection exception
+ * @param progressed function to be called on any progress notifications
+ * @return promise for the return value from the invoked callback
+ */
+Q.when = when;
+function when(value, fulfilled, rejected, progressed) {
+    return Q(value).then(fulfilled, rejected, progressed);
+}
+
+/**
+ * Spreads the values of a promised array of arguments into the
+ * fulfillment callback.
+ * @param fulfilled callback that receives variadic arguments from the
+ * promised array
+ * @param rejected callback that receives the exception if the promise
+ * is rejected.
+ * @returns a promise for the return value or thrown exception of
+ * either callback.
+ */
+Q.spread = spread;
+function spread(promise, fulfilled, rejected) {
+    return when(promise, function (valuesOrPromises) {
+        return all(valuesOrPromises).then(function (values) {
+            return fulfilled.apply(void 0, values);
+        }, rejected);
+    }, rejected);
+}
+
+/**
+ * The async function is a decorator for generator functions, turning
+ * them into asynchronous generators.  Although generators are only part
+ * of the newest ECMAScript 6 drafts, this code does not cause syntax
+ * errors in older engines.  This code should continue to work and will
+ * in fact improve over time as the language improves.
+ *
+ * ES6 generators are currently part of V8 version 3.19 with the
+ * --harmony-generators runtime flag enabled.  SpiderMonkey has had them
+ * for longer, but under an older Python-inspired form.  This function
+ * works on both kinds of generators.
+ *
+ * Decorates a generator function such that:
+ *  - it may yield promises
+ *  - execution will continue when that promise is fulfilled
+ *  - the value of the yield expression will be the fulfilled value
+ *  - it returns a promise for the return value (when the generator
+ *    stops iterating)
+ *  - the decorated function returns a promise for the return value
+ *    of the generator or the first rejected promise among those
+ *    yielded.
+ *  - if an error is thrown in the generator, it propagates through
+ *    every following yield until it is caught, or until it escapes
+ *    the generator function altogether, and is translated into a
+ *    rejection for the promise returned by the decorated generator.
+ */
+Q.async = async;
+function async(makeGenerator) {
+    return function () {
+        // when verb is "send", arg is a value
+        // when verb is "throw", arg is an exception
+        function continuer(verb, arg) {
+            var result;
+            if (hasES6Generators) {
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    return reject(exception);
+                }
+                if (result.done) {
+                    return result.value;
+                } else {
+                    return when(result.value, callback, errback);
+                }
+            } else {
+                // FIXME: Remove this case when SM does ES6 generators.
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    if (isStopIteration(exception)) {
+                        return exception.value;
+                    } else {
+                        return reject(exception);
+                    }
+                }
+                return when(result, callback, errback);
+            }
+        }
+        var generator = makeGenerator.apply(this, arguments);
+        var callback = continuer.bind(continuer, "send");
+        var errback = continuer.bind(continuer, "throw");
+        return callback();
+    };
+}
+
+/**
+ * The spawn function is a small wrapper around async that immediately
+ * calls the generator and also ends the promise chain, so that any
+ * unhandled errors are thrown instead of forwarded to the error
+ * handler. This is useful because it's extremely common to run
+ * generators at the top-level to work with libraries.
+ */
+Q.spawn = spawn;
+function spawn(makeGenerator) {
+    Q.done(Q.async(makeGenerator)());
+}
+
+// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
+/**
+ * Throws a ReturnValue exception to stop an asynchronous generator.
+ *
+ * This interface is a stop-gap measure to support generator return
+ * values in older Firefox/SpiderMonkey.  In browsers that support ES6
+ * generators like Chromium 29, just use "return" in your generator
+ * functions.
+ *
+ * @param value the return value for the surrounding generator
+ * @throws ReturnValue exception with the value.
+ * @example
+ * // ES6 style
+ * Q.async(function* () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      return foo + bar;
+ * })
+ * // Older SpiderMonkey style
+ * Q.async(function () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      Q.return(foo + bar);
+ * })
+ */
+Q["return"] = _return;
+function _return(value) {
+    throw new QReturnValue(value);
+}
+
+/**
+ * The promised function decorator ensures that any promise arguments
+ * are settled and passed as values (`this` is also settled and passed
+ * as a value).  It will also ensure that the result of a function is
+ * always a promise.
+ *
+ * @example
+ * var add = Q.promised(function (a, b) {
+ *     return a + b;
+ * });
+ * add(Q.resolve(a), Q.resolve(B));
+ *
+ * @param {function} callback The function to decorate
+ * @returns {function} a function that has been decorated.
+ */
+Q.promised = promised;
+function promised(callback) {
+    return function () {
+        return spread([this, all(arguments)], function (self, args) {
+            return callback.apply(self, args);
+        });
+    };
+}
+
+/**
+ * sends a message to a value in a future turn
+ * @param object* the recipient
+ * @param op the name of the message operation, e.g., "when",
+ * @param args further arguments to be forwarded to the operation
+ * @returns result {Promise} a promise for the result of the operation
+ */
+Q.dispatch = dispatch;
+function dispatch(object, op, args) {
+    var deferred = defer();
+    nextTick(function () {
+        resolve(object).promiseDispatch(deferred.resolve, op, args);
+    });
+    return deferred.promise;
+}
+
+/**
+ * Constructs a promise method that can be used to safely observe resolution of
+ * a promise for an arbitrarily named method like "propfind" in a future turn.
+ *
+ * "dispatcher" constructs methods like "get(promise, name)" and "set(promise)".
+ */
+Q.dispatcher = dispatcher;
+function dispatcher(op) {
+    return function (object) {
+        var args = array_slice(arguments, 1);
+        return dispatch(object, op, args);
+    };
+}
+
+/**
+ * Gets the value of a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to get
+ * @return promise for the property value
+ */
+Q.get = dispatcher("get");
+
+/**
+ * Sets the value of a property in a future turn.
+ * @param object    promise or immediate reference for object object
+ * @param name      name of property to set
+ * @param value     new value of property
+ * @return promise for the return value
+ */
+Q.set = dispatcher("set");
+
+/**
+ * Deletes a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to delete
+ * @return promise for the return value
+ */
+Q["delete"] = // XXX experimental
+Q.del = dispatcher("delete");
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param value     a value to post, typically an array of
+ *                  invocation arguments for promises that
+ *                  are ultimately backed with `resolve` values,
+ *                  as opposed to those backed with URLs
+ *                  wherein the posted value can be any
+ *                  JSON serializable object.
+ * @return promise for the return value
+ */
+// bound locally because it is used by other methods
+var post = Q.post = dispatcher("post");
+Q.mapply = post; // experimental
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param ...args   array of invocation arguments
+ * @return promise for the return value
+ */
+Q.send = send;
+Q.invoke = send; // synonyms
+Q.mcall = send; // experimental
+function send(value, name) {
+    var args = array_slice(arguments, 2);
+    return post(value, name, args);
+}
+
+/**
+ * Applies the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param args      array of application arguments
+ */
+Q.fapply = fapply;
+function fapply(value, args) {
+    return dispatch(value, "apply", [void 0, args]);
+}
+
+/**
+ * Calls the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q["try"] = fcall; // XXX experimental
+Q.fcall = fcall;
+function fcall(value) {
+    var args = array_slice(arguments, 1);
+    return fapply(value, args);
+}
+
+/**
+ * Binds the promised function, transforming return values into a fulfilled
+ * promise and thrown errors into a rejected one.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q.fbind = fbind;
+function fbind(value) {
+    var args = array_slice(arguments, 1);
+    return function fbound() {
+        var allArgs = args.concat(array_slice(arguments));
+        return dispatch(value, "apply", [this, allArgs]);
+    };
+}
+
+/**
+ * Requests the names of the owned properties of a promised
+ * object in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @return promise for the keys of the eventually settled object
+ */
+Q.keys = dispatcher("keys");
+
+/**
+ * Turns an array of promises into a promise for an array.  If any of
+ * the promises gets rejected, the whole array is rejected immediately.
+ * @param {Array*} an array (or promise for an array) of values (or
+ * promises for values)
+ * @returns a promise for an array of the corresponding values
+ */
+// By Mark Miller
+// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
+Q.all = all;
+function all(promises) {
+    return when(promises, function (promises) {
+        var countDown = 0;
+        var deferred = defer();
+        array_reduce(promises, function (undefined, promise, index) {
+            var snapshot;
+            if (
+                isPromise(promise) &&
+                (snapshot = promise.inspect()).state === "fulfilled"
+            ) {
+                promises[index] = snapshot.value;
+            } else {
+                ++countDown;
+                when(promise, function (value) {
+                    promises[index] = value;
+                    if (--countDown === 0) {
+                        deferred.resolve(promises);
+                    }
+                }, deferred.reject);
+            }
+        }, void 0);
+        if (countDown === 0) {
+            deferred.resolve(promises);
+        }
+        return deferred.promise;
+    });
+}
+
+/**
+ * Waits for all promises to be settled, either fulfilled or
+ * rejected.  This is distinct from `all` since that would stop
+ * waiting at the first rejection.  The promise returned by
+ * `allResolved` will never be rejected.
+ * @param promises a promise for an array (or an array) of promises
+ * (or values)
+ * @return a promise for an array of promises
+ */
+Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
+function allResolved(promises) {
+    return when(promises, function (promises) {
+        promises = array_map(promises, resolve);
+        return when(all(array_map(promises, function (promise) {
+            return when(promise, noop, noop);
+        })), function () {
+            return promises;
+        });
+    });
+}
+
+Q.allSettled = allSettled;
+function allSettled(values) {
+    return when(values, function (values) {
+        return all(array_map(values, function (value, i) {
+            return when(
+                value,
+                function (fulfillmentValue) {
+                    values[i] = { state: "fulfilled", value: fulfillmentValue };
+                    return values[i];
+                },
+                function (reason) {
+                    values[i] = { state: "rejected", reason: reason };
+                    return values[i];
+                }
+            );
+        })).thenResolve(values);
+    });
+}
+
+/**
+ * Captures the failure of a promise, giving an oportunity to recover
+ * with a callback.  If the given promise is fulfilled, the returned
+ * promise is fulfilled.
+ * @param {Any*} promise for something
+ * @param {Function} callback to fulfill the returned promise if the
+ * given promise is rejected
+ * @returns a promise for the return value of the callback
+ */
+Q["catch"] = // XXX experimental
+Q.fail = fail;
+function fail(promise, rejected) {
+    return when(promise, void 0, rejected);
+}
+
+/**
+ * Attaches a listener that can respond to progress notifications from a
+ * promise's originating deferred. This listener receives the exact arguments
+ * passed to ``deferred.notify``.
+ * @param {Any*} promise for something
+ * @param {Function} callback to receive any progress notifications
+ * @returns the given promise, unchanged
+ */
+Q.progress = progress;
+function progress(promise, progressed) {
+    return when(promise, void 0, void 0, progressed);
+}
+
+/**
+ * Provides an opportunity to observe the settling of a promise,
+ * regardless of whether the promise is fulfilled or rejected.  Forwards
+ * the resolution to the returned promise when the callback is done.
+ * The callback can return a promise to defer completion.
+ * @param {Any*} promise
+ * @param {Function} callback to observe the resolution of the given
+ * promise, takes no arguments.
+ * @returns a promise for the resolution of the given promise when
+ * ``fin`` is done.
+ */
+Q["finally"] = // XXX experimental
+Q.fin = fin;
+function fin(promise, callback) {
+    return when(promise, function (value) {
+        return when(callback(), function () {
+            return value;
+        });
+    }, function (exception) {
+        return when(callback(), function () {
+            return reject(exception);
+        });
+    });
+}
+
+/**
+ * Terminates a chain of promises, forcing rejections to be
+ * thrown as exceptions.
+ * @param {Any*} promise at the end of a chain of promises
+ * @returns nothing
+ */
+Q.done = done;
+function done(promise, fulfilled, rejected, progress) {
+    var onUnhandledError = function (error) {
+        // forward to a future turn so that ``when``
+        // does not catch it and turn it into a rejection.
+        nextTick(function () {
+            makeStackTraceLong(error, promise);
+
+            if (Q.onerror) {
+                Q.onerror(error);
+            } else {
+                throw error;
+            }
+        });
+    };
+
+    // Avoid unnecessary `nextTick`ing via an unnecessary `when`.
+    var promiseToHandle = fulfilled || rejected || progress ?
+        when(promise, fulfilled, rejected, progress) :
+        promise;
+
+    if (typeof process === "object" && process && process.domain) {
+        onUnhandledError = process.domain.bind(onUnhandledError);
+    }
+    fail(promiseToHandle, onUnhandledError);
+}
+
+/**
+ * Causes a promise to be rejected if it does not get fulfilled before
+ * some milliseconds time out.
+ * @param {Any*} promise
+ * @param {Number} milliseconds timeout
+ * @param {String} custom error message (optional)
+ * @returns a promise for the resolution of the given promise if it is
+ * fulfilled before the timeout, otherwise rejected.
+ */
+Q.timeout = timeout;
+function timeout(promise, ms, msg) {
+    var deferred = defer();
+    var timeoutId = setTimeout(function () {
+        deferred.reject(new Error(msg || "Timed out after " + ms + " ms"));
+    }, ms);
+
+    when(promise, function (value) {
+        clearTimeout(timeoutId);
+        deferred.resolve(value);
+    }, function (exception) {
+        clearTimeout(timeoutId);
+        deferred.reject(exception);
+    }, deferred.notify);
+
+    return deferred.promise;
+}
+
+/**
+ * Returns a promise for the given value (or promised value) after some
+ * milliseconds.
+ * @param {Any*} promise
+ * @param {Number} milliseconds
+ * @returns a promise for the resolution of the given promise after some
+ * time has elapsed.
+ */
+Q.delay = delay;
+function delay(promise, timeout) {
+    if (timeout === void 0) {
+        timeout = promise;
+        promise = void 0;
+    }
+
+    var deferred = defer();
+
+    when(promise, undefined, undefined, deferred.notify);
+    setTimeout(function () {
+        deferred.resolve(promise);
+    }, timeout);
+
+    return deferred.promise;
+}
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided as an array, and returns a promise.
+ *
+ *      Q.nfapply(FS.readFile, [__filename])
+ *      .then(function (content) {
+ *      })
+ *
+ */
+Q.nfapply = nfapply;
+function nfapply(callback, args) {
+    var nodeArgs = array_slice(args);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+
+    fapply(callback, nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+}
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided individually, and returns a promise.
+ *
+ *      Q.nfcall(FS.readFile, __filename)
+ *      .then(function (content) {
+ *      })
+ *
+ */
+Q.nfcall = nfcall;
+function nfcall(callback/*, ...args */) {
+    var nodeArgs = array_slice(arguments, 1);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+
+    fapply(callback, nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+}
+
+/**
+ * Wraps a NodeJS continuation passing function and returns an equivalent
+ * version that returns a promise.
+ *
+ *      Q.nfbind(FS.readFile, __filename)("utf-8")
+ *      .then(console.log)
+ *      .done()
+ *
+ */
+Q.nfbind = nfbind;
+Q.denodeify = Q.nfbind; // synonyms
+function nfbind(callback/*, ...args */) {
+    var baseArgs = array_slice(arguments, 1);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+
+        fapply(callback, nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+}
+
+Q.nbind = nbind;
+function nbind(callback, thisArg /*, ... args*/) {
+    var baseArgs = array_slice(arguments, 2);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+
+        function bound() {
+            return callback.apply(thisArg, arguments);
+        }
+
+        fapply(bound, nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+}
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback with a given array of arguments, plus a provided callback.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param {Array} args arguments to pass to the method; the callback
+ * will be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.npost = npost;
+Q.nmapply = npost; // synonyms
+function npost(object, name, args) {
+    var nodeArgs = array_slice(args || []);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+
+    post(object, name, nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+}
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback, forwarding the given variadic arguments, plus a provided
+ * callback argument.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param ...args arguments to pass to the method; the callback will
+ * be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.nsend = nsend;
+Q.ninvoke = Q.nsend; // synonyms
+Q.nmcall = Q.nsend; // synonyms
+function nsend(object, name /*, ...args*/) {
+    var nodeArgs = array_slice(arguments, 2);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    post(object, name, nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+}
+
+Q.nodeify = nodeify;
+function nodeify(promise, nodeback) {
+    if (nodeback) {
+        promise.then(function (value) {
+            nextTick(function () {
+                nodeback(null, value);
+            });
+        }, function (error) {
+            nextTick(function () {
+                nodeback(error);
+            });
+        });
+    } else {
+        return promise;
+    }
+}
+
+// All code before this point will be filtered from stack traces.
+var qEndingLine = captureLine();
+
+return Q;
+
+});
Index: Dev/trunk/src/node_modules/q/queue.js
===================================================================
--- Dev/trunk/src/node_modules/q/queue.js	(revision 484)
+++ Dev/trunk/src/node_modules/q/queue.js	(revision 484)
@@ -0,0 +1,35 @@
+
+var Q = require("./q");
+
+module.exports = Queue;
+function Queue() {
+    var ends = Q.defer();
+    var closed = Q.defer();
+    return {
+        put: function (value) {
+            var next = Q.defer();
+            ends.resolve({
+                head: value,
+                tail: next.promise
+            });
+            ends.resolve = next.resolve;
+        },
+        get: function () {
+            var result = ends.promise.get("head");
+            ends.promise = ends.promise.get("tail");
+            return result.fail(function (error) {
+                closed.resolve(error);
+                throw error;
+            });
+        },
+        closed: closed.promise,
+        close: function (error) {
+            error = error || new Error("Can't get value from closed queue");
+            var end = {head: Q.reject(error)};
+            end.tail = end;
+            ends.resolve(end);
+            return closed.promise;
+        }
+    };
+}
+
Index: Dev/trunk/src/node_modules/request/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/LICENSE	(revision 484)
@@ -0,0 +1,55 @@
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
Index: Dev/trunk/src/node_modules/request/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/README.md	(revision 484)
@@ -0,0 +1,344 @@
+# Request -- Simplified HTTP request method
+
+## Install
+
+<pre>
+  npm install request
+</pre>
+
+Or from source:
+
+<pre>
+  git clone git://github.com/mikeal/request.git 
+  cd request
+  npm link
+</pre>
+
+## Super simple to use
+
+Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.
+
+```javascript
+var request = require('request');
+request('http://www.google.com', function (error, response, body) {
+  if (!error && response.statusCode == 200) {
+    console.log(body) // Print the google web page.
+  }
+})
+```
+
+## Streaming
+
+You can stream any response to a file stream.
+
+```javascript
+request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))
+```
+
+You can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.
+
+```javascript
+fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))
+```
+
+Request can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.
+
+```javascript
+request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))
+```
+
+Now let's get fancy.
+
+```javascript
+http.createServer(function (req, resp) {
+  if (req.url === '/doodle.png') {
+    if (req.method === 'PUT') {
+      req.pipe(request.put('http://mysite.com/doodle.png'))
+    } else if (req.method === 'GET' || req.method === 'HEAD') {
+      request.get('http://mysite.com/doodle.png').pipe(resp)
+    } 
+  }
+})
+```
+
+You can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:
+
+```javascript
+http.createServer(function (req, resp) {
+  if (req.url === '/doodle.png') {
+    var x = request('http://mysite.com/doodle.png')
+    req.pipe(x)
+    x.pipe(resp)
+  }
+})
+```
+
+And since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)
+
+```javascript
+req.pipe(request('http://mysite.com/doodle.png')).pipe(resp)
+```
+
+Also, none of this new functionality conflicts with requests previous features, it just expands them.
+
+```javascript
+var r = request.defaults({'proxy':'http://localproxy.com'})
+
+http.createServer(function (req, resp) {
+  if (req.url === '/doodle.png') {
+    r.get('http://google.com/doodle.png').pipe(resp)
+  }
+})
+```
+You can still use intermediate proxies, the requests will still follow HTTP forwards, etc.
+
+## Forms
+
+`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.
+
+Url encoded forms are simple
+
+```javascript
+request.post('http://service.com/upload', {form:{key:'value'}})
+// or
+request.post('http://service.com/upload').form({key:'value'})
+```
+
+For `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you.
+
+```javascript
+var r = request.post('http://service.com/upload')
+var form = r.form()
+form.append('my_field', 'my_value')
+form.append('my_buffer', new Buffer([1, 2, 3]))
+form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))
+form.append('remote_file', request('http://google.com/doodle.png'))
+```
+
+## HTTP Authentication
+
+```javascript
+request.auth('username', 'password', false).get('http://some.server.com/');
+// or
+request.get('http://some.server.com/', {
+  'auth': {
+    'user': 'username',
+    'pass': 'password',
+    'sendImmediately': false
+  }
+});
+```
+
+If passed as an option, `auth` should be a hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional).  The method form takes parameters `auth(username, password, sendImmediately)`.
+
+`sendImmediately` defaults to true, which will cause a basic authentication header to be sent.  If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a 401 response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method).
+
+Digest authentication is supported, but it only works with `sendImmediately` set to `false` (otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail).
+
+## OAuth Signing
+
+```javascript
+// Twitter OAuth
+var qs = require('querystring')
+  , oauth =
+    { callback: 'http://mysite.com/callback/'
+    , consumer_key: CONSUMER_KEY
+    , consumer_secret: CONSUMER_SECRET
+    }
+  , url = 'https://api.twitter.com/oauth/request_token'
+  ;
+request.post({url:url, oauth:oauth}, function (e, r, body) {
+  // Ideally, you would take the body in the response
+  // and construct a URL that a user clicks on (like a sign in button).
+  // The verifier is only available in the response after a user has 
+  // verified with twitter that they are authorizing your app.
+  var access_token = qs.parse(body)
+    , oauth = 
+      { consumer_key: CONSUMER_KEY
+      , consumer_secret: CONSUMER_SECRET
+      , token: access_token.oauth_token
+      , verifier: access_token.oauth_verifier
+      }
+    , url = 'https://api.twitter.com/oauth/access_token'
+    ;
+  request.post({url:url, oauth:oauth}, function (e, r, body) {
+    var perm_token = qs.parse(body)
+      , oauth = 
+        { consumer_key: CONSUMER_KEY
+        , consumer_secret: CONSUMER_SECRET
+        , token: perm_token.oauth_token
+        , token_secret: perm_token.oauth_token_secret
+        }
+      , url = 'https://api.twitter.com/1/users/show.json?'
+      , params = 
+        { screen_name: perm_token.screen_name
+        , user_id: perm_token.user_id
+        }
+      ;
+    url += qs.stringify(params)
+    request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {
+      console.log(user)
+    })
+  })
+})
+```
+
+
+
+### request(options, callback)
+
+The first argument can be either a url or an options object. The only required option is uri, all others are optional.
+
+* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()
+* `qs` - object containing querystring values to be appended to the uri
+* `method` - http method, defaults to GET
+* `headers` - http headers, defaults to {}
+* `body` - entity body for PATCH, POST and PUT requests. Must be buffer or string.
+* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request.
+* `auth` - A hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional).  See documentation above.
+* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.  Additionally, parses the response body as json.
+* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.
+* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.
+* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.
+* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.
+* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.
+* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.
+* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.
+* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request	
+* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.
+* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.
+* `hawk` - Options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example).
+* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.
+* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)
+* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services)
+* `httpSignature` - Options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options.
+* `localAddress` - Local interface to bind for network connections.
+
+
+The callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.
+
+## Convenience methods
+
+There are also shorthand methods for different HTTP METHODs and some other conveniences.
+
+### request.defaults(options)  
+  
+This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.
+
+### request.put
+
+Same as request() but defaults to `method: "PUT"`.
+
+```javascript
+request.put(url)
+```
+
+### request.patch
+
+Same as request() but defaults to `method: "PATCH"`.
+
+```javascript
+request.patch(url)
+```
+
+### request.post
+
+Same as request() but defaults to `method: "POST"`.
+
+```javascript
+request.post(url)
+```
+
+### request.head
+
+Same as request() but defaults to `method: "HEAD"`.
+
+```javascript
+request.head(url)
+```
+
+### request.del
+
+Same as request() but defaults to `method: "DELETE"`.
+
+```javascript
+request.del(url)
+```
+
+### request.get
+
+Alias to normal request method for uniformity.
+
+```javascript
+request.get(url)
+```
+### request.cookie
+
+Function that creates a new cookie.
+
+```javascript
+request.cookie('cookie_string_here')
+```
+### request.jar
+
+Function that creates a new cookie jar.
+
+```javascript
+request.jar()
+```
+
+
+## Examples:
+
+```javascript
+  var request = require('request')
+    , rand = Math.floor(Math.random()*100000000).toString()
+    ;
+  request(
+    { method: 'PUT'
+    , uri: 'http://mikeal.iriscouch.com/testjs/' + rand
+    , multipart: 
+      [ { 'content-type': 'application/json'
+        ,  body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
+        }
+      , { body: 'I am an attachment' }
+      ] 
+    }
+  , function (error, response, body) {
+      if(response.statusCode == 201){
+        console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)
+      } else {
+        console.log('error: '+ response.statusCode)
+        console.log(body)
+      }
+    }
+  )
+```
+Cookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).
+
+```javascript
+var request = request.defaults({jar: false})
+request('http://www.google.com', function () {
+  request('http://images.google.com')
+})
+```
+
+If you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:
+
+```javascript
+var j = request.jar()
+var request = request.defaults({jar:j})
+request('http://www.google.com', function () {
+  request('http://images.google.com')
+})
+```
+OR
+
+```javascript
+var j = request.jar()
+var cookie = request.cookie('your_cookie_here')
+j.add(cookie)
+request({url: 'http://www.google.com', jar: j}, function () {
+  request('http://images.google.com')
+})
+```
Index: Dev/trunk/src/node_modules/request/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/index.js	(revision 484)
@@ -0,0 +1,1365 @@
+// Copyright 2010-2012 Mikeal Rogers
+//
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+
+var http = require('http')
+  , https = false
+  , tls = false
+  , url = require('url')
+  , util = require('util')
+  , stream = require('stream')
+  , qs = require('qs')
+  , querystring = require('querystring')
+  , crypto = require('crypto')
+
+  , oauth = require('oauth-sign')
+  , hawk = require('hawk')
+  , aws = require('aws-sign')
+  , httpSignature = require('http-signature')
+  , uuid = require('node-uuid')
+  , mime = require('mime')
+  , tunnel = require('tunnel-agent')
+  , safeStringify = require('json-stringify-safe')
+
+  , ForeverAgent = require('forever-agent')
+  , FormData = require('form-data')
+
+  , Cookie = require('cookie-jar')
+  , CookieJar = Cookie.Jar
+  , cookieJar = new CookieJar
+  ;
+
+try {
+  https = require('https')
+} catch (e) {}
+
+try {
+  tls = require('tls')
+} catch (e) {}
+
+var debug
+if (/\brequest\b/.test(process.env.NODE_DEBUG)) {
+  debug = function() {
+    console.error('REQUEST %s', util.format.apply(util, arguments))
+  }
+} else {
+  debug = function() {}
+}
+
+function toBase64 (str) {
+  return (new Buffer(str || "", "ascii")).toString("base64")
+}
+
+function md5 (str) {
+  return crypto.createHash('md5').update(str).digest('hex')
+}
+
+// Hacky fix for pre-0.4.4 https
+if (https && !https.Agent) {
+  https.Agent = function (options) {
+    http.Agent.call(this, options)
+  }
+  util.inherits(https.Agent, http.Agent)
+  https.Agent.prototype._getConnection = function (host, port, cb) {
+    var s = tls.connect(port, host, this.options, function () {
+      // do other checks here?
+      if (cb) cb()
+    })
+    return s
+  }
+}
+
+function isReadStream (rs) {
+  if (rs.readable && rs.path && rs.mode) {
+    return true
+  }
+}
+
+function copy (obj) {
+  var o = {}
+  Object.keys(obj).forEach(function (i) {
+    o[i] = obj[i]
+  })
+  return o
+}
+
+var isUrl = /^https?:/
+
+var globalPool = {}
+
+function Request (options) {
+  stream.Stream.call(this)
+  this.readable = true
+  this.writable = true
+
+  if (typeof options === 'string') {
+    options = {uri:options}
+  }
+
+  var reserved = Object.keys(Request.prototype)
+  for (var i in options) {
+    if (reserved.indexOf(i) === -1) {
+      this[i] = options[i]
+    } else {
+      if (typeof options[i] === 'function') {
+        delete options[i]
+      }
+    }
+  }
+
+  if (options.method) {
+    this.explicitMethod = true
+  }
+
+  this.init(options)
+}
+util.inherits(Request, stream.Stream)
+Request.prototype.init = function (options) {
+  // init() contains all the code to setup the request object.
+  // the actual outgoing request is not started until start() is called
+  // this function is called from both the constructor and on redirect.
+  var self = this
+  if (!options) options = {}
+
+  if (!self.method) self.method = options.method || 'GET'
+  self.localAddress = options.localAddress
+
+  debug(options)
+  if (!self.pool && self.pool !== false) self.pool = globalPool
+  self.dests = self.dests || []
+  self.__isRequestRequest = true
+
+  // Protect against double callback
+  if (!self._callback && self.callback) {
+    self._callback = self.callback
+    self.callback = function () {
+      if (self._callbackCalled) return // Print a warning maybe?
+      self._callbackCalled = true
+      self._callback.apply(self, arguments)
+    }
+    self.on('error', self.callback.bind())
+    self.on('complete', self.callback.bind(self, null))
+  }
+
+  if (self.url) {
+    // People use this property instead all the time so why not just support it.
+    self.uri = self.url
+    delete self.url
+  }
+
+  if (!self.uri) {
+    // this will throw if unhandled but is handleable when in a redirect
+    return self.emit('error', new Error("options.uri is a required argument"))
+  } else {
+    if (typeof self.uri == "string") self.uri = url.parse(self.uri)
+  }
+
+  if (self.strictSSL === false) {
+    self.rejectUnauthorized = false
+  }
+
+  if (self.proxy) {
+    if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy)
+
+    // do the HTTP CONNECT dance using koichik/node-tunnel
+    if (http.globalAgent && self.uri.protocol === "https:") {
+      var tunnelFn = self.proxy.protocol === "http:"
+                   ? tunnel.httpsOverHttp : tunnel.httpsOverHttps
+
+      var tunnelOptions = { proxy: { host: self.proxy.hostname
+                                   , port: +self.proxy.port
+                                   , proxyAuth: self.proxy.auth
+                                   , headers: { Host: self.uri.hostname + ':' +
+                                        (self.uri.port || self.uri.protocol === 'https:' ? 443 : 80) }}
+                          , rejectUnauthorized: self.rejectUnauthorized
+                          , ca: this.ca }
+
+      self.agent = tunnelFn(tunnelOptions)
+      self.tunnel = true
+    }
+  }
+
+  if (!self.uri.host || !self.uri.pathname) {
+    // Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar
+    // Detect and reject it as soon as possible
+    var faultyUri = url.format(self.uri)
+    var message = 'Invalid URI "' + faultyUri + '"'
+    if (Object.keys(options).length === 0) {
+      // No option ? This can be the sign of a redirect
+      // As this is a case where the user cannot do anything (he didn't call request directly with this URL)
+      // he should be warned that it can be caused by a redirection (can save some hair)
+      message += '. This can be caused by a crappy redirection.'
+    }
+    self.emit('error', new Error(message))
+    return // This error was fatal
+  }
+
+  self._redirectsFollowed = self._redirectsFollowed || 0
+  self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10
+  self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true
+  self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false
+  if (self.followRedirect || self.followAllRedirects)
+    self.redirects = self.redirects || []
+
+  self.headers = self.headers ? copy(self.headers) : {}
+
+  self.setHost = false
+  if (!(self.headers.host || self.headers.Host)) {
+    self.headers.host = self.uri.hostname
+    if (self.uri.port) {
+      if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') &&
+           !(self.uri.port === 443 && self.uri.protocol === 'https:') )
+      self.headers.host += (':'+self.uri.port)
+    }
+    self.setHost = true
+  }
+
+  self.jar(self._jar || options.jar)
+
+  if (!self.uri.pathname) {self.uri.pathname = '/'}
+  if (!self.uri.port) {
+    if (self.uri.protocol == 'http:') {self.uri.port = 80}
+    else if (self.uri.protocol == 'https:') {self.uri.port = 443}
+  }
+
+  if (self.proxy && !self.tunnel) {
+    self.port = self.proxy.port
+    self.host = self.proxy.hostname
+  } else {
+    self.port = self.uri.port
+    self.host = self.uri.hostname
+  }
+
+  self.clientErrorHandler = function (error) {
+    if (self._aborted) return
+
+    if (self.req && self.req._reusedSocket && error.code === 'ECONNRESET'
+        && self.agent.addRequestNoreuse) {
+      self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) }
+      self.start()
+      self.req.end()
+      return
+    }
+    if (self.timeout && self.timeoutTimer) {
+      clearTimeout(self.timeoutTimer)
+      self.timeoutTimer = null
+    }
+    self.emit('error', error)
+  }
+
+  self._parserErrorHandler = function (error) {
+    if (this.res) {
+      if (this.res.request) {
+        this.res.request.emit('error', error)
+      } else {
+        this.res.emit('error', error)
+      }
+    } else {
+      this._httpMessage.emit('error', error)
+    }
+  }
+
+  if (options.form) {
+    self.form(options.form)
+  }
+
+  if (options.qs) self.qs(options.qs)
+
+  if (self.uri.path) {
+    self.path = self.uri.path
+  } else {
+    self.path = self.uri.pathname + (self.uri.search || "")
+  }
+
+  if (self.path.length === 0) self.path = '/'
+
+
+  // Auth must happen last in case signing is dependent on other headers
+  if (options.oauth) {
+    self.oauth(options.oauth)
+  }
+
+  if (options.aws) {
+    self.aws(options.aws)
+  }
+
+  if (options.hawk) {
+    self.hawk(options.hawk)
+  }
+
+  if (options.httpSignature) {
+    self.httpSignature(options.httpSignature)
+  }
+
+  if (options.auth) {
+    self.auth(
+      (options.auth.user==="") ? options.auth.user : (options.auth.user || options.auth.username ),
+      options.auth.pass || options.auth.password,
+      options.auth.sendImmediately)
+  }
+
+  if (self.uri.auth && !self.headers.authorization) {
+    var authPieces = self.uri.auth.split(':').map(function(item){ return querystring.unescape(item) })
+    self.auth(authPieces[0], authPieces.slice(1).join(':'), true)
+  }
+  if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization'] && !self.tunnel) {
+    self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return querystring.unescape(item)}).join(':'))
+  }
+
+
+  if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path)
+
+  if (options.json) {
+    self.json(options.json)
+  } else if (options.multipart) {
+    self.boundary = uuid()
+    self.multipart(options.multipart)
+  }
+
+  if (self.body) {
+    var length = 0
+    if (!Buffer.isBuffer(self.body)) {
+      if (Array.isArray(self.body)) {
+        for (var i = 0; i < self.body.length; i++) {
+          length += self.body[i].length
+        }
+      } else {
+        self.body = new Buffer(self.body)
+        length = self.body.length
+      }
+    } else {
+      length = self.body.length
+    }
+    if (length) {
+      if(!self.headers['content-length'] && !self.headers['Content-Length'])
+      self.headers['content-length'] = length
+    } else {
+      throw new Error('Argument error, options.body.')
+    }
+  }
+
+  var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol
+    , defaultModules = {'http:':http, 'https:':https}
+    , httpModules = self.httpModules || {}
+    ;
+  self.httpModule = httpModules[protocol] || defaultModules[protocol]
+
+  if (!self.httpModule) return this.emit('error', new Error("Invalid protocol"))
+
+  if (options.ca) self.ca = options.ca
+
+  if (!self.agent) {
+    if (options.agentOptions) self.agentOptions = options.agentOptions
+
+    if (options.agentClass) {
+      self.agentClass = options.agentClass
+    } else if (options.forever) {
+      self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL
+    } else {
+      self.agentClass = self.httpModule.Agent
+    }
+  }
+
+  if (self.pool === false) {
+    self.agent = false
+  } else {
+    self.agent = self.agent || self.getAgent()
+    if (self.maxSockets) {
+      // Don't use our pooling if node has the refactored client
+      self.agent.maxSockets = self.maxSockets
+    }
+    if (self.pool.maxSockets) {
+      // Don't use our pooling if node has the refactored client
+      self.agent.maxSockets = self.pool.maxSockets
+    }
+  }
+
+  self.once('pipe', function (src) {
+    if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.")
+    self.src = src
+    if (isReadStream(src)) {
+      if (!self.headers['content-type'] && !self.headers['Content-Type'])
+        self.headers['content-type'] = mime.lookup(src.path)
+    } else {
+      if (src.headers) {
+        for (var i in src.headers) {
+          if (!self.headers[i]) {
+            self.headers[i] = src.headers[i]
+          }
+        }
+      }
+      if (self._json && !self.headers['content-type'] && !self.headers['Content-Type'])
+        self.headers['content-type'] = 'application/json'
+      if (src.method && !self.explicitMethod) {
+        self.method = src.method
+      }
+    }
+
+    self.on('pipe', function () {
+      console.error("You have already piped to this stream. Pipeing twice is likely to break the request.")
+    })
+  })
+
+  process.nextTick(function () {
+    if (self._aborted) return
+
+    if (self._form) {
+      self.setHeaders(self._form.getHeaders())
+      self._form.pipe(self)
+    }
+    if (self.body) {
+      if (Array.isArray(self.body)) {
+        self.body.forEach(function (part) {
+          self.write(part)
+        })
+      } else {
+        self.write(self.body)
+      }
+      self.end()
+    } else if (self.requestBodyStream) {
+      console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.")
+      self.requestBodyStream.pipe(self)
+    } else if (!self.src) {
+      if (self.method !== 'GET' && typeof self.method !== 'undefined') {
+        self.headers['content-length'] = 0
+      }
+      self.end()
+    }
+    self.ntick = true
+  })
+}
+
+// Must call this when following a redirect from https to http or vice versa
+// Attempts to keep everything as identical as possible, but update the
+// httpModule, Tunneling agent, and/or Forever Agent in use.
+Request.prototype._updateProtocol = function () {
+  var self = this
+  var protocol = self.uri.protocol
+
+  if (protocol === 'https:') {
+    // previously was doing http, now doing https
+    // if it's https, then we might need to tunnel now.
+    if (self.proxy) {
+      self.tunnel = true
+      var tunnelFn = self.proxy.protocol === 'http:'
+                   ? tunnel.httpsOverHttp : tunnel.httpsOverHttps
+      var tunnelOptions = { proxy: { host: self.proxy.hostname
+                                   , port: +self.proxy.port
+                                   , proxyAuth: self.proxy.auth }
+                          , rejectUnauthorized: self.rejectUnauthorized
+                          , ca: self.ca }
+      self.agent = tunnelFn(tunnelOptions)
+      return
+    }
+
+    self.httpModule = https
+    switch (self.agentClass) {
+      case ForeverAgent:
+        self.agentClass = ForeverAgent.SSL
+        break
+      case http.Agent:
+        self.agentClass = https.Agent
+        break
+      default:
+        // nothing we can do.  Just hope for the best.
+        return
+    }
+
+    // if there's an agent, we need to get a new one.
+    if (self.agent) self.agent = self.getAgent()
+
+  } else {
+    // previously was doing https, now doing http
+    // stop any tunneling.
+    if (self.tunnel) self.tunnel = false
+    self.httpModule = http
+    switch (self.agentClass) {
+      case ForeverAgent.SSL:
+        self.agentClass = ForeverAgent
+        break
+      case https.Agent:
+        self.agentClass = http.Agent
+        break
+      default:
+        // nothing we can do.  just hope for the best
+        return
+    }
+
+    // if there's an agent, then get a new one.
+    if (self.agent) {
+      self.agent = null
+      self.agent = self.getAgent()
+    }
+  }
+}
+
+Request.prototype.getAgent = function () {
+  var Agent = this.agentClass
+  var options = {}
+  if (this.agentOptions) {
+    for (var i in this.agentOptions) {
+      options[i] = this.agentOptions[i]
+    }
+  }
+  if (this.ca) options.ca = this.ca
+  if (typeof this.rejectUnauthorized !== 'undefined') options.rejectUnauthorized = this.rejectUnauthorized
+
+  if (this.cert && this.key) {
+    options.key = this.key
+    options.cert = this.cert
+  }
+
+  var poolKey = ''
+
+  // different types of agents are in different pools
+  if (Agent !== this.httpModule.Agent) {
+    poolKey += Agent.name
+  }
+
+  if (!this.httpModule.globalAgent) {
+    // node 0.4.x
+    options.host = this.host
+    options.port = this.port
+    if (poolKey) poolKey += ':'
+    poolKey += this.host + ':' + this.port
+  }
+
+  // ca option is only relevant if proxy or destination are https
+  var proxy = this.proxy
+  if (typeof proxy === 'string') proxy = url.parse(proxy)
+  var isHttps = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:'
+  if (isHttps) {
+    if (options.ca) {
+      if (poolKey) poolKey += ':'
+      poolKey += options.ca
+    }
+
+    if (typeof options.rejectUnauthorized !== 'undefined') {
+      if (poolKey) poolKey += ':'
+      poolKey += options.rejectUnauthorized
+    }
+
+    if (options.cert)
+      poolKey += options.cert.toString('ascii') + options.key.toString('ascii')
+  }
+
+  if (!poolKey && Agent === this.httpModule.Agent && this.httpModule.globalAgent) {
+    // not doing anything special.  Use the globalAgent
+    return this.httpModule.globalAgent
+  }
+
+  // we're using a stored agent.  Make sure it's protocol-specific
+  poolKey = this.uri.protocol + poolKey
+
+  // already generated an agent for this setting
+  if (this.pool[poolKey]) return this.pool[poolKey]
+
+  return this.pool[poolKey] = new Agent(options)
+}
+
+Request.prototype.start = function () {
+  // start() is called once we are ready to send the outgoing HTTP request.
+  // this is usually called on the first write(), end() or on nextTick()
+  var self = this
+
+  if (self._aborted) return
+
+  self._started = true
+  self.method = self.method || 'GET'
+  self.href = self.uri.href
+
+  if (self.src && self.src.stat && self.src.stat.size && !self.headers['content-length'] && !self.headers['Content-Length']) {
+    self.headers['content-length'] = self.src.stat.size
+  }
+  if (self._aws) {
+    self.aws(self._aws, true)
+  }
+
+  // We have a method named auth, which is completely different from the http.request
+  // auth option.  If we don't remove it, we're gonna have a bad time.
+  var reqOptions = copy(self)
+  delete reqOptions.auth
+
+  debug('make request', self.uri.href)
+  self.req = self.httpModule.request(reqOptions, self.onResponse.bind(self))
+
+  if (self.timeout && !self.timeoutTimer) {
+    self.timeoutTimer = setTimeout(function () {
+      self.req.abort()
+      var e = new Error("ETIMEDOUT")
+      e.code = "ETIMEDOUT"
+      self.emit("error", e)
+    }, self.timeout)
+
+    // Set additional timeout on socket - in case if remote
+    // server freeze after sending headers
+    if (self.req.setTimeout) { // only works on node 0.6+
+      self.req.setTimeout(self.timeout, function () {
+        if (self.req) {
+          self.req.abort()
+          var e = new Error("ESOCKETTIMEDOUT")
+          e.code = "ESOCKETTIMEDOUT"
+          self.emit("error", e)
+        }
+      })
+    }
+  }
+
+  self.req.on('error', self.clientErrorHandler)
+  self.req.on('drain', function() {
+    self.emit('drain')
+  })
+  self.on('end', function() {
+    if ( self.req.connection ) self.req.connection.removeListener('error', self._parserErrorHandler)
+  })
+  self.emit('request', self.req)
+}
+Request.prototype.onResponse = function (response) {
+  var self = this
+  debug('onResponse', self.uri.href, response.statusCode, response.headers)
+  response.on('end', function() {
+    debug('response end', self.uri.href, response.statusCode, response.headers)
+  });
+
+  if (response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) {
+    response.connection.once('error', self._parserErrorHandler)
+  }
+  if (self._aborted) {
+    debug('aborted', self.uri.href)
+    response.resume()
+    return
+  }
+  if (self._paused) response.pause()
+  else response.resume()
+
+  self.response = response
+  response.request = self
+  response.toJSON = toJSON
+
+  // XXX This is different on 0.10, because SSL is strict by default
+  if (self.httpModule === https &&
+      self.strictSSL &&
+      !response.client.authorized) {
+    debug('strict ssl error', self.uri.href)
+    var sslErr = response.client.authorizationError
+    self.emit('error', new Error('SSL Error: '+ sslErr))
+    return
+  }
+
+  if (self.setHost) delete self.headers.host
+  if (self.timeout && self.timeoutTimer) {
+    clearTimeout(self.timeoutTimer)
+    self.timeoutTimer = null
+  }
+
+  var addCookie = function (cookie) {
+    if (self._jar) self._jar.add(new Cookie(cookie))
+    else cookieJar.add(new Cookie(cookie))
+  }
+
+  if (response.headers['set-cookie'] && (!self._disableCookies)) {
+    if (Array.isArray(response.headers['set-cookie'])) response.headers['set-cookie'].forEach(addCookie)
+    else addCookie(response.headers['set-cookie'])
+  }
+
+  var redirectTo = null
+  if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
+    debug('redirect', response.headers.location)
+
+    if (self.followAllRedirects) {
+      redirectTo = response.headers.location
+    } else if (self.followRedirect) {
+      switch (self.method) {
+        case 'PATCH':
+        case 'PUT':
+        case 'POST':
+        case 'DELETE':
+          // Do not follow redirects
+          break
+        default:
+          redirectTo = response.headers.location
+          break
+      }
+    }
+  } else if (response.statusCode == 401 && self._hasAuth && !self._sentAuth) {
+    var authHeader = response.headers['www-authenticate']
+    var authVerb = authHeader && authHeader.split(' ')[0]
+    debug('reauth', authVerb)
+
+    switch (authVerb) {
+      case 'Basic':
+        self.auth(self._user, self._pass, true)
+        redirectTo = self.uri
+        break
+
+      case 'Digest':
+        // TODO: More complete implementation of RFC 2617.  For reference:
+        // http://tools.ietf.org/html/rfc2617#section-3
+        // https://github.com/bagder/curl/blob/master/lib/http_digest.c
+
+        var matches = authHeader.match(/([a-z0-9_-]+)="([^"]+)"/gi)
+        var challenge = {}
+
+        for (var i = 0; i < matches.length; i++) {
+          var eqPos = matches[i].indexOf('=')
+          var key = matches[i].substring(0, eqPos)
+          var quotedValue = matches[i].substring(eqPos + 1)
+          challenge[key] = quotedValue.substring(1, quotedValue.length - 1)
+        }
+
+        var ha1 = md5(self._user + ':' + challenge.realm + ':' + self._pass)
+        var ha2 = md5(self.method + ':' + self.uri.path)
+        var digestResponse = md5(ha1 + ':' + challenge.nonce + ':1::auth:' + ha2)
+        var authValues = {
+          username: self._user,
+          realm: challenge.realm,
+          nonce: challenge.nonce,
+          uri: self.uri.path,
+          qop: challenge.qop,
+          response: digestResponse,
+          nc: 1,
+          cnonce: ''
+        }
+
+        authHeader = []
+        for (var k in authValues) {
+          authHeader.push(k + '="' + authValues[k] + '"')
+        }
+        authHeader = 'Digest ' + authHeader.join(', ')
+        self.setHeader('authorization', authHeader)
+        self._sentAuth = true
+
+        redirectTo = self.uri
+        break
+    }
+  }
+
+  if (redirectTo) {
+    debug('redirect to', redirectTo)
+
+    // ignore any potential response body.  it cannot possibly be useful
+    // to us at this point.
+    if (self._paused) response.resume()
+
+    if (self._redirectsFollowed >= self.maxRedirects) {
+      self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop "+self.uri.href))
+      return
+    }
+    self._redirectsFollowed += 1
+
+    if (!isUrl.test(redirectTo)) {
+      redirectTo = url.resolve(self.uri.href, redirectTo)
+    }
+
+    var uriPrev = self.uri
+    self.uri = url.parse(redirectTo)
+
+    // handle the case where we change protocol from https to http or vice versa
+    if (self.uri.protocol !== uriPrev.protocol) {
+      self._updateProtocol()
+    }
+
+    self.redirects.push(
+      { statusCode : response.statusCode
+      , redirectUri: redirectTo
+      }
+    )
+    if (self.followAllRedirects && response.statusCode != 401) self.method = 'GET'
+    // self.method = 'GET' // Force all redirects to use GET || commented out fixes #215
+    delete self.src
+    delete self.req
+    delete self.agent
+    delete self._started
+    if (response.statusCode != 401) {
+      // Remove parameters from the previous response, unless this is the second request
+      // for a server that requires digest authentication.
+      delete self.body
+      delete self._form
+      if (self.headers) {
+        delete self.headers.host
+        delete self.headers['content-type']
+        delete self.headers['content-length']
+      }
+    }
+
+    self.emit('redirect');
+
+    self.init()
+    return // Ignore the rest of the response
+  } else {
+    self._redirectsFollowed = self._redirectsFollowed || 0
+    // Be a good stream and emit end when the response is finished.
+    // Hack to emit end on close because of a core bug that never fires end
+    response.on('close', function () {
+      if (!self._ended) self.response.emit('end')
+    })
+
+    if (self.encoding) {
+      if (self.dests.length !== 0) {
+        console.error("Ingoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.")
+      } else {
+        response.setEncoding(self.encoding)
+      }
+    }
+
+    self.emit('response', response)
+
+    self.dests.forEach(function (dest) {
+      self.pipeDest(dest)
+    })
+
+    response.on("data", function (chunk) {
+      self._destdata = true
+      self.emit("data", chunk)
+    })
+    response.on("end", function (chunk) {
+      self._ended = true
+      self.emit("end", chunk)
+    })
+    response.on("close", function () {self.emit("close")})
+
+    if (self.callback) {
+      var buffer = []
+      var bodyLen = 0
+      self.on("data", function (chunk) {
+        buffer.push(chunk)
+        bodyLen += chunk.length
+      })
+      self.on("end", function () {
+        debug('end event', self.uri.href)
+        if (self._aborted) {
+          debug('aborted', self.uri.href)
+          return
+        }
+
+        if (buffer.length && Buffer.isBuffer(buffer[0])) {
+          debug('has body', self.uri.href, bodyLen)
+          var body = new Buffer(bodyLen)
+          var i = 0
+          buffer.forEach(function (chunk) {
+            chunk.copy(body, i, 0, chunk.length)
+            i += chunk.length
+          })
+          if (self.encoding === null) {
+            response.body = body
+          } else {
+            response.body = body.toString(self.encoding)
+          }
+        } else if (buffer.length) {
+          // The UTF8 BOM [0xEF,0xBB,0xBF] is converted to [0xFE,0xFF] in the JS UTC16/UCS2 representation.
+          // Strip this value out when the encoding is set to 'utf8', as upstream consumers won't expect it and it breaks JSON.parse().
+          if (self.encoding === 'utf8' && buffer[0].length > 0 && buffer[0][0] === "\uFEFF") {
+            buffer[0] = buffer[0].substring(1)
+          }
+          response.body = buffer.join('')
+        }
+
+        if (self._json) {
+          try {
+            response.body = JSON.parse(response.body)
+          } catch (e) {}
+        }
+        debug('emitting complete', self.uri.href)
+        if(response.body == undefined && !self._json) {
+          response.body = "";
+        }
+        self.emit('complete', response, response.body)
+      })
+    }
+  }
+  debug('finish init function', self.uri.href)
+}
+
+Request.prototype.abort = function () {
+  this._aborted = true
+
+  if (this.req) {
+    this.req.abort()
+  }
+  else if (this.response) {
+    this.response.abort()
+  }
+
+  this.emit("abort")
+}
+
+Request.prototype.pipeDest = function (dest) {
+  var response = this.response
+  // Called after the response is received
+  if (dest.headers) {
+    dest.headers['content-type'] = response.headers['content-type']
+    if (response.headers['content-length']) {
+      dest.headers['content-length'] = response.headers['content-length']
+    }
+  }
+  if (dest.setHeader) {
+    for (var i in response.headers) {
+      dest.setHeader(i, response.headers[i])
+    }
+    dest.statusCode = response.statusCode
+  }
+  if (this.pipefilter) this.pipefilter(response, dest)
+}
+
+// Composable API
+Request.prototype.setHeader = function (name, value, clobber) {
+  if (clobber === undefined) clobber = true
+  if (clobber || !this.headers.hasOwnProperty(name)) this.headers[name] = value
+  else this.headers[name] += ',' + value
+  return this
+}
+Request.prototype.setHeaders = function (headers) {
+  for (var i in headers) {this.setHeader(i, headers[i])}
+  return this
+}
+Request.prototype.qs = function (q, clobber) {
+  var base
+  if (!clobber && this.uri.query) base = qs.parse(this.uri.query)
+  else base = {}
+
+  for (var i in q) {
+    base[i] = q[i]
+  }
+
+  if (qs.stringify(base) === ''){
+    return this
+  }
+
+  this.uri = url.parse(this.uri.href.split('?')[0] + '?' + qs.stringify(base))
+  this.url = this.uri
+  this.path = this.uri.path
+
+  return this
+}
+Request.prototype.form = function (form) {
+  if (form) {
+    this.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8'
+    this.body = qs.stringify(form).toString('utf8')
+    return this
+  }
+  // create form-data object
+  this._form = new FormData()
+  return this._form
+}
+Request.prototype.multipart = function (multipart) {
+  var self = this
+  self.body = []
+
+  if (!self.headers['content-type']) {
+    self.headers['content-type'] = 'multipart/related; boundary=' + self.boundary
+  } else {
+    self.headers['content-type'] = self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary
+  }
+
+  if (!multipart.forEach) throw new Error('Argument error, options.multipart.')
+
+  if (self.preambleCRLF) {
+    self.body.push(new Buffer('\r\n'))
+  }
+
+  multipart.forEach(function (part) {
+    var body = part.body
+    if(body == null) throw Error('Body attribute missing in multipart.')
+    delete part.body
+    var preamble = '--' + self.boundary + '\r\n'
+    Object.keys(part).forEach(function (key) {
+      preamble += key + ': ' + part[key] + '\r\n'
+    })
+    preamble += '\r\n'
+    self.body.push(new Buffer(preamble))
+    self.body.push(new Buffer(body))
+    self.body.push(new Buffer('\r\n'))
+  })
+  self.body.push(new Buffer('--' + self.boundary + '--'))
+  return self
+}
+Request.prototype.json = function (val) {
+  var self = this;
+  var setAcceptHeader = function() {
+  	if (!self.headers['accept'] && !self.headers['Accept']) {
+			  self.setHeader('accept', 'application/json')
+		}
+	}
+  setAcceptHeader();
+  this._json = true
+  if (typeof val === 'boolean') {
+    if (typeof this.body === 'object') {
+      setAcceptHeader();
+      this.body = safeStringify(this.body)
+      self.setHeader('content-type', 'application/json')
+    }
+  } else {
+    setAcceptHeader();
+    this.body = safeStringify(val)
+    self.setHeader('content-type', 'application/json')
+  }
+  return this
+}
+function getHeader(name, headers) {
+    var result, re, match
+    Object.keys(headers).forEach(function (key) {
+        re = new RegExp(name, 'i')
+        match = key.match(re)
+        if (match) result = headers[key]
+    })
+    return result
+}
+Request.prototype.auth = function (user, pass, sendImmediately) {
+  if (typeof user !== 'string' || (pass !== undefined && typeof pass !== 'string')) {
+    throw new Error('auth() received invalid user or password')
+  }
+  this._user = user
+  this._pass = pass
+  this._hasAuth = true
+  if (sendImmediately || typeof sendImmediately == 'undefined') {
+    this.setHeader('authorization', 'Basic ' + toBase64(user + ':' + pass))
+    this._sentAuth = true
+  }
+  return this
+}
+Request.prototype.aws = function (opts, now) {
+  if (!now) {
+    this._aws = opts
+    return this
+  }
+  var date = new Date()
+  this.setHeader('date', date.toUTCString())
+  var auth =
+    { key: opts.key
+    , secret: opts.secret
+    , verb: this.method.toUpperCase()
+    , date: date
+    , contentType: getHeader('content-type', this.headers) || ''
+    , md5: getHeader('content-md5', this.headers) || ''
+    , amazonHeaders: aws.canonicalizeHeaders(this.headers)
+    }
+  if (opts.bucket && this.path) {
+    auth.resource = '/' + opts.bucket + this.path
+  } else if (opts.bucket && !this.path) {
+    auth.resource = '/' + opts.bucket
+  } else if (!opts.bucket && this.path) {
+    auth.resource = this.path
+  } else if (!opts.bucket && !this.path) {
+    auth.resource = '/'
+  }
+  auth.resource = aws.canonicalizeResource(auth.resource)
+  this.setHeader('authorization', aws.authorization(auth))
+
+  return this
+}
+Request.prototype.httpSignature = function (opts) {
+  var req = this
+  httpSignature.signRequest({
+    getHeader: function(header) {
+      return getHeader(header, req.headers)
+    },
+    setHeader: function(header, value) {
+      req.setHeader(header, value)
+    },
+    method: this.method,
+    path: this.path
+  }, opts)
+  debug('httpSignature authorization', getHeader('authorization', this.headers))
+
+  return this
+}
+
+Request.prototype.hawk = function (opts) {
+  this.headers.Authorization = hawk.client.header(this.uri, this.method, opts).field
+}
+
+Request.prototype.oauth = function (_oauth) {
+  var form
+  if (this.headers['content-type'] &&
+      this.headers['content-type'].slice(0, 'application/x-www-form-urlencoded'.length) ===
+        'application/x-www-form-urlencoded'
+     ) {
+    form = qs.parse(this.body)
+  }
+  if (this.uri.query) {
+    form = qs.parse(this.uri.query)
+  }
+  if (!form) form = {}
+  var oa = {}
+  for (var i in form) oa[i] = form[i]
+  for (var i in _oauth) oa['oauth_'+i] = _oauth[i]
+  if (!oa.oauth_version) oa.oauth_version = '1.0'
+  if (!oa.oauth_timestamp) oa.oauth_timestamp = Math.floor( Date.now() / 1000 ).toString()
+  if (!oa.oauth_nonce) oa.oauth_nonce = uuid().replace(/-/g, '')
+
+  oa.oauth_signature_method = 'HMAC-SHA1'
+
+  var consumer_secret = oa.oauth_consumer_secret
+  delete oa.oauth_consumer_secret
+  var token_secret = oa.oauth_token_secret
+  delete oa.oauth_token_secret
+  var timestamp = oa.oauth_timestamp
+
+  var baseurl = this.uri.protocol + '//' + this.uri.host + this.uri.pathname
+  var signature = oauth.hmacsign(this.method, baseurl, oa, consumer_secret, token_secret)
+
+  // oa.oauth_signature = signature
+  for (var i in form) {
+    if ( i.slice(0, 'oauth_') in _oauth) {
+      // skip
+    } else {
+      delete oa['oauth_'+i]
+      if (i !== 'x_auth_mode') delete oa[i]
+    }
+  }
+  oa.oauth_timestamp = timestamp
+  this.headers.Authorization =
+    'OAuth '+Object.keys(oa).sort().map(function (i) {return i+'="'+oauth.rfc3986(oa[i])+'"'}).join(',')
+  this.headers.Authorization += ',oauth_signature="' + oauth.rfc3986(signature) + '"'
+  return this
+}
+Request.prototype.jar = function (jar) {
+  var cookies
+
+  if (this._redirectsFollowed === 0) {
+    this.originalCookieHeader = this.headers.cookie
+  }
+
+  if (jar === false) {
+    // disable cookies
+    cookies = false
+    this._disableCookies = true
+  } else if (jar) {
+    // fetch cookie from the user defined cookie jar
+    cookies = jar.get({ url: this.uri.href })
+  } else {
+    // fetch cookie from the global cookie jar
+    cookies = cookieJar.get({ url: this.uri.href })
+  }
+
+  if (cookies && cookies.length) {
+    var cookieString = cookies.map(function (c) {
+      return c.name + "=" + c.value
+    }).join("; ")
+
+    if (this.originalCookieHeader) {
+      // Don't overwrite existing Cookie header
+      this.headers.cookie = this.originalCookieHeader + '; ' + cookieString
+    } else {
+      this.headers.cookie = cookieString
+    }
+  }
+  this._jar = jar
+  return this
+}
+
+
+// Stream API
+Request.prototype.pipe = function (dest, opts) {
+  if (this.response) {
+    if (this._destdata) {
+      throw new Error("You cannot pipe after data has been emitted from the response.")
+    } else if (this._ended) {
+      throw new Error("You cannot pipe after the response has been ended.")
+    } else {
+      stream.Stream.prototype.pipe.call(this, dest, opts)
+      this.pipeDest(dest)
+      return dest
+    }
+  } else {
+    this.dests.push(dest)
+    stream.Stream.prototype.pipe.call(this, dest, opts)
+    return dest
+  }
+}
+Request.prototype.write = function () {
+  if (!this._started) this.start()
+  return this.req.write.apply(this.req, arguments)
+}
+Request.prototype.end = function (chunk) {
+  if (chunk) this.write(chunk)
+  if (!this._started) this.start()
+  this.req.end()
+}
+Request.prototype.pause = function () {
+  if (!this.response) this._paused = true
+  else this.response.pause.apply(this.response, arguments)
+}
+Request.prototype.resume = function () {
+  if (!this.response) this._paused = false
+  else this.response.resume.apply(this.response, arguments)
+}
+Request.prototype.destroy = function () {
+  if (!this._ended) this.end()
+  else if (this.response) this.response.destroy()
+}
+
+// organize params for patch, post, put, head, del
+function initParams(uri, options, callback) {
+  if ((typeof options === 'function') && !callback) callback = options
+  if (options && typeof options === 'object') {
+    options.uri = uri
+  } else if (typeof uri === 'string') {
+    options = {uri:uri}
+  } else {
+    options = uri
+    uri = options.uri
+  }
+  return { uri: uri, options: options, callback: callback }
+}
+
+function request (uri, options, callback) {
+  if (typeof uri === 'undefined') throw new Error('undefined is not a valid uri or options object.')
+  if ((typeof options === 'function') && !callback) callback = options
+  if (options && typeof options === 'object') {
+    options.uri = uri
+  } else if (typeof uri === 'string') {
+    options = {uri:uri}
+  } else {
+    options = uri
+  }
+
+  options = copy(options)
+
+  if (callback) options.callback = callback
+  var r = new Request(options)
+  return r
+}
+
+module.exports = request
+
+request.debug = process.env.NODE_DEBUG && /request/.test(process.env.NODE_DEBUG)
+
+request.initParams = initParams
+
+request.defaults = function (options, requester) {
+  var def = function (method) {
+    var d = function (uri, opts, callback) {
+      var params = initParams(uri, opts, callback)
+      for (var i in options) {
+        if (params.options[i] === undefined) params.options[i] = options[i]
+      }
+      if(typeof requester === 'function') {
+        if(method === request) {
+          method = requester
+        } else {
+          params.options._requester = requester
+        }
+      }
+      return method(params.options, params.callback)
+    }
+    return d
+  }
+  var de = def(request)
+  de.get = def(request.get)
+  de.patch = def(request.patch)
+  de.post = def(request.post)
+  de.put = def(request.put)
+  de.head = def(request.head)
+  de.del = def(request.del)
+  de.cookie = def(request.cookie)
+  de.jar = request.jar
+  return de
+}
+
+request.forever = function (agentOptions, optionsArg) {
+  var options = {}
+  if (optionsArg) {
+    for (option in optionsArg) {
+      options[option] = optionsArg[option]
+    }
+  }
+  if (agentOptions) options.agentOptions = agentOptions
+  options.forever = true
+  return request.defaults(options)
+}
+
+request.get = request
+request.post = function (uri, options, callback) {
+  var params = initParams(uri, options, callback)
+  params.options.method = 'POST'
+  return request(params.uri || null, params.options, params.callback)
+}
+request.put = function (uri, options, callback) {
+  var params = initParams(uri, options, callback)
+  params.options.method = 'PUT'
+  return request(params.uri || null, params.options, params.callback)
+}
+request.patch = function (uri, options, callback) {
+  var params = initParams(uri, options, callback)
+  params.options.method = 'PATCH'
+  return request(params.uri || null, params.options, params.callback)
+}
+request.head = function (uri, options, callback) {
+  var params = initParams(uri, options, callback)
+  params.options.method = 'HEAD'
+  if (params.options.body ||
+      params.options.requestBodyStream ||
+      (params.options.json && typeof params.options.json !== 'boolean') ||
+      params.options.multipart) {
+    throw new Error("HTTP HEAD requests MUST NOT include a request body.")
+  }
+  return request(params.uri || null, params.options, params.callback)
+}
+request.del = function (uri, options, callback) {
+  var params = initParams(uri, options, callback)
+  params.options.method = 'DELETE'
+  if(typeof params.options._requester === 'function') {
+    request = params.options._requester
+  }
+  return request(params.uri || null, params.options, params.callback)
+}
+request.jar = function () {
+  return new CookieJar
+}
+request.cookie = function (str) {
+  if (str && str.uri) str = str.uri
+  if (typeof str !== 'string') throw new Error("The cookie function only accepts STRING as param")
+  return new Cookie(str)
+}
+
+// Safe toJSON
+
+function getSafe (self, uuid) {
+  if (typeof self === 'object' || typeof self === 'function') var safe = {}
+  if (Array.isArray(self)) var safe = []
+
+  var recurse = []
+
+  Object.defineProperty(self, uuid, {})
+
+  var attrs = Object.keys(self).filter(function (i) {
+    if (i === uuid) return false
+    if ( (typeof self[i] !== 'object' && typeof self[i] !== 'function') || self[i] === null) return true
+    return !(Object.getOwnPropertyDescriptor(self[i], uuid))
+  })
+
+
+  for (var i=0;i<attrs.length;i++) {
+    if ( (typeof self[attrs[i]] !== 'object' && typeof self[attrs[i]] !== 'function') ||
+          self[attrs[i]] === null
+        ) {
+      safe[attrs[i]] = self[attrs[i]]
+    } else {
+      recurse.push(attrs[i])
+      Object.defineProperty(self[attrs[i]], uuid, {})
+    }
+  }
+
+  for (var i=0;i<recurse.length;i++) {
+    safe[recurse[i]] = getSafe(self[recurse[i]], uuid)
+  }
+
+  return safe
+}
+
+function toJSON () {
+  return getSafe(this, '__' + (((1+Math.random())*0x10000)|0).toString(16))
+}
+
+Request.prototype.toJSON = toJSON
Index: Dev/trunk/src/node_modules/request/node_modules/aws-sign/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/aws-sign/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/aws-sign/LICENSE	(revision 484)
@@ -0,0 +1,55 @@
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
Index: Dev/trunk/src/node_modules/request/node_modules/aws-sign/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/aws-sign/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/aws-sign/README.md	(revision 484)
@@ -0,0 +1,4 @@
+aws-sign
+========
+
+AWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.
Index: Dev/trunk/src/node_modules/request/node_modules/aws-sign/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/aws-sign/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/aws-sign/index.js	(revision 484)
@@ -0,0 +1,202 @@
+
+/*!
+ * knox - auth
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var crypto = require('crypto')
+  , parse = require('url').parse
+  ;
+
+/**
+ * Valid keys.
+ */
+
+var keys = 
+  [ 'acl'
+  , 'location'
+  , 'logging'
+  , 'notification'
+  , 'partNumber'
+  , 'policy'
+  , 'requestPayment'
+  , 'torrent'
+  , 'uploadId'
+  , 'uploads'
+  , 'versionId'
+  , 'versioning'
+  , 'versions'
+  , 'website'
+  ]
+
+/**
+ * Return an "Authorization" header value with the given `options`
+ * in the form of "AWS <key>:<signature>"
+ *
+ * @param {Object} options
+ * @return {String}
+ * @api private
+ */
+
+function authorization (options) {
+  return 'AWS ' + options.key + ':' + sign(options)
+}
+
+module.exports = authorization
+module.exports.authorization = authorization
+
+/**
+ * Simple HMAC-SHA1 Wrapper
+ *
+ * @param {Object} options
+ * @return {String}
+ * @api private
+ */ 
+
+function hmacSha1 (options) {
+  return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64')
+}
+
+module.exports.hmacSha1 = hmacSha1
+
+/**
+ * Create a base64 sha1 HMAC for `options`. 
+ * 
+ * @param {Object} options
+ * @return {String}
+ * @api private
+ */
+
+function sign (options) {
+  options.message = stringToSign(options)
+  return hmacSha1(options)
+}
+module.exports.sign = sign
+
+/**
+ * Create a base64 sha1 HMAC for `options`. 
+ *
+ * Specifically to be used with S3 presigned URLs
+ * 
+ * @param {Object} options
+ * @return {String}
+ * @api private
+ */
+
+function signQuery (options) {
+  options.message = queryStringToSign(options)
+  return hmacSha1(options)
+}
+module.exports.signQuery= signQuery
+
+/**
+ * Return a string for sign() with the given `options`.
+ *
+ * Spec:
+ * 
+ *    <verb>\n
+ *    <md5>\n
+ *    <content-type>\n
+ *    <date>\n
+ *    [headers\n]
+ *    <resource>
+ *
+ * @param {Object} options
+ * @return {String}
+ * @api private
+ */
+
+function stringToSign (options) {
+  var headers = options.amazonHeaders || ''
+  if (headers) headers += '\n'
+  var r = 
+    [ options.verb
+    , options.md5
+    , options.contentType
+    , options.date.toUTCString()
+    , headers + options.resource
+    ]
+  return r.join('\n')
+}
+module.exports.queryStringToSign = stringToSign
+
+/**
+ * Return a string for sign() with the given `options`, but is meant exclusively
+ * for S3 presigned URLs
+ *
+ * Spec:
+ * 
+ *    <date>\n
+ *    <resource>
+ *
+ * @param {Object} options
+ * @return {String}
+ * @api private
+ */
+
+function queryStringToSign (options){
+  return 'GET\n\n\n' + options.date + '\n' + options.resource
+}
+module.exports.queryStringToSign = queryStringToSign
+
+/**
+ * Perform the following:
+ *
+ *  - ignore non-amazon headers
+ *  - lowercase fields
+ *  - sort lexicographically
+ *  - trim whitespace between ":"
+ *  - join with newline
+ *
+ * @param {Object} headers
+ * @return {String}
+ * @api private
+ */
+
+function canonicalizeHeaders (headers) {
+  var buf = []
+    , fields = Object.keys(headers)
+    ;
+  for (var i = 0, len = fields.length; i < len; ++i) {
+    var field = fields[i]
+      , val = headers[field]
+      , field = field.toLowerCase()
+      ;
+    if (0 !== field.indexOf('x-amz')) continue
+    buf.push(field + ':' + val)
+  }
+  return buf.sort().join('\n')
+}
+module.exports.canonicalizeHeaders = canonicalizeHeaders
+
+/**
+ * Perform the following:
+ *
+ *  - ignore non sub-resources
+ *  - sort lexicographically
+ *
+ * @param {String} resource
+ * @return {String}
+ * @api private
+ */
+
+function canonicalizeResource (resource) {
+  var url = parse(resource, true)
+    , path = url.pathname
+    , buf = []
+    ;
+
+  Object.keys(url.query).forEach(function(key){
+    if (!~keys.indexOf(key)) return
+    var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key])
+    buf.push(key + val)
+  })
+
+  return path + (buf.length ? '?' + buf.sort().join('&') : '')
+}
+module.exports.canonicalizeResource = canonicalizeResource
Index: Dev/trunk/src/node_modules/request/node_modules/aws-sign/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/aws-sign/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/aws-sign/package.json	(revision 484)
@@ -0,0 +1,28 @@
+{
+  "author": {
+    "name": "Mikeal Rogers",
+    "email": "mikeal.rogers@gmail.com",
+    "url": "http://www.futurealoof.com"
+  },
+  "name": "aws-sign",
+  "description": "AWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.",
+  "version": "0.3.0",
+  "repository": {
+    "url": "https://github.com/mikeal/aws-sign"
+  },
+  "main": "index.js",
+  "dependencies": {},
+  "devDependencies": {},
+  "optionalDependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "readme": "aws-sign\n========\n\nAWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/mikeal/aws-sign/issues"
+  },
+  "homepage": "https://github.com/mikeal/aws-sign",
+  "_id": "aws-sign@0.3.0",
+  "_from": "aws-sign@~0.3.0"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/cookie-jar/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/cookie-jar/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/cookie-jar/LICENSE	(revision 484)
@@ -0,0 +1,55 @@
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
Index: Dev/trunk/src/node_modules/request/node_modules/cookie-jar/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/cookie-jar/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/cookie-jar/README.md	(revision 484)
@@ -0,0 +1,4 @@
+cookie-jar
+==========
+
+Cookie Jar. Originally pulled from LearnBoost/tobi, maintained as vendor in request, now a standalone module.
Index: Dev/trunk/src/node_modules/request/node_modules/cookie-jar/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/cookie-jar/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/cookie-jar/index.js	(revision 484)
@@ -0,0 +1,67 @@
+/*!
+ * Tobi - Cookie
+ * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var url = require('url');
+
+/**
+ * Initialize a new `Cookie` with the given cookie `str` and `req`.
+ *
+ * @param {String} str
+ * @param {IncomingRequest} req
+ * @api private
+ */
+
+var Cookie = exports = module.exports = function Cookie(str, req) {
+  this.str = str;
+
+  // Map the key/val pairs
+  str.split(/ *; */).reduce(function(obj, pair){
+   var p = pair.indexOf('=');
+   var key = p > 0 ? pair.substring(0, p).trim() : pair.trim();
+   var lowerCasedKey = key.toLowerCase();
+   var value = p > 0 ? pair.substring(p + 1).trim() : true;
+
+   if (!obj.name) {
+    // First key is the name
+    obj.name = key;
+    obj.value = value;
+   }
+   else if (lowerCasedKey === 'httponly') {
+    obj.httpOnly = value;
+   }
+   else {
+    obj[lowerCasedKey] = value;
+   }
+   return obj;
+  }, this);
+
+  // Expires
+  this.expires = this.expires
+    ? new Date(this.expires)
+    : Infinity;
+
+  // Default or trim path
+  this.path = this.path
+    ? this.path.trim(): req 
+    ? url.parse(req.url).pathname: '/';
+};
+
+/**
+ * Return the original cookie string.
+ *
+ * @return {String}
+ * @api public
+ */
+
+Cookie.prototype.toString = function(){
+  return this.str;
+};
+
+module.exports.Jar = require('./jar')
Index: Dev/trunk/src/node_modules/request/node_modules/cookie-jar/jar.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/cookie-jar/jar.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/cookie-jar/jar.js	(revision 484)
@@ -0,0 +1,72 @@
+/*!
+* Tobi - CookieJar
+* Copyright(c) 2010 LearnBoost <dev@learnboost.com>
+* MIT Licensed
+*/
+
+/**
+* Module dependencies.
+*/
+
+var url = require('url');
+
+/**
+* Initialize a new `CookieJar`.
+*
+* @api private
+*/
+
+var CookieJar = exports = module.exports = function CookieJar() {
+  this.cookies = [];
+};
+
+/**
+* Add the given `cookie` to the jar.
+*
+* @param {Cookie} cookie
+* @api private
+*/
+
+CookieJar.prototype.add = function(cookie){
+  this.cookies = this.cookies.filter(function(c){
+    // Avoid duplication (same path, same name)
+    return !(c.name == cookie.name && c.path == cookie.path);
+  });
+  this.cookies.push(cookie);
+};
+
+/**
+* Get cookies for the given `req`.
+*
+* @param {IncomingRequest} req
+* @return {Array}
+* @api private
+*/
+
+CookieJar.prototype.get = function(req){
+  var path = url.parse(req.url).pathname
+    , now = new Date
+    , specificity = {};
+  return this.cookies.filter(function(cookie){
+    if (0 == path.indexOf(cookie.path) && now < cookie.expires
+      && cookie.path.length > (specificity[cookie.name] || 0))
+      return specificity[cookie.name] = cookie.path.length;
+  });
+};
+
+/**
+* Return Cookie string for the given `req`.
+*
+* @param {IncomingRequest} req
+* @return {String}
+* @api private
+*/
+
+CookieJar.prototype.cookieString = function(req){
+  var cookies = this.get(req);
+  if (cookies.length) {
+    return cookies.map(function(cookie){
+      return cookie.name + '=' + cookie.value;
+    }).join('; ');
+  }
+};
Index: Dev/trunk/src/node_modules/request/node_modules/cookie-jar/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/cookie-jar/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/cookie-jar/package.json	(revision 484)
@@ -0,0 +1,31 @@
+{
+  "author": {
+    "name": "Mikeal Rogers",
+    "email": "mikeal.rogers@gmail.com",
+    "url": "http://www.futurealoof.com"
+  },
+  "name": "cookie-jar",
+  "description": "Cookie Jar. Originally pulled form tobi, maintained as vendor in request, now a standalone module.",
+  "version": "0.3.0",
+  "repository": {
+    "url": "https://github.com/mikeal/cookie-jar"
+  },
+  "main": "index.js",
+  "scripts": {
+    "test": "node tests/run.js"
+  },
+  "dependencies": {},
+  "devDependencies": {},
+  "optionalDependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "readme": "cookie-jar\n==========\n\nCookie Jar. Originally pulled from LearnBoost/tobi, maintained as vendor in request, now a standalone module.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/mikeal/cookie-jar/issues"
+  },
+  "homepage": "https://github.com/mikeal/cookie-jar",
+  "_id": "cookie-jar@0.3.0",
+  "_from": "cookie-jar@~0.3.0"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/cookie-jar/tests/run.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/cookie-jar/tests/run.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/cookie-jar/tests/run.js	(revision 484)
@@ -0,0 +1,40 @@
+var spawn = require('child_process').spawn
+  , exitCode = 0
+  , timeout = 10000
+  , fs = require('fs')
+  ;
+
+fs.readdir(__dirname, function (e, files) {
+  if (e) throw e
+
+  var tests = files.filter(function (f) {return f.slice(0, 'test-'.length) === 'test-'})
+
+  var next = function () {
+    if (tests.length === 0) process.exit(exitCode);
+
+    var file = tests.shift()
+    console.log(file)
+    var proc = spawn('node', [ 'tests/' + file ])
+
+    var killed = false
+    var t = setTimeout(function () {
+      proc.kill()
+      exitCode += 1
+      console.error(file + ' timeout')
+      killed = true
+    }, timeout)
+
+    proc.stdout.pipe(process.stdout)
+    proc.stderr.pipe(process.stderr)
+    proc.on('exit', function (code) {
+      if (code && !killed) console.error(file + ' failed')
+      exitCode += code || 0
+      clearTimeout(t)
+      next()
+    })
+  }
+  next()
+    
+})
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/cookie-jar/tests/test-cookie.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/cookie-jar/tests/test-cookie.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/cookie-jar/tests/test-cookie.js	(revision 484)
@@ -0,0 +1,29 @@
+var Cookie = require('../index')
+  , assert = require('assert');
+
+var str = 'Sid="s543qactge.wKE61E01Bs%2BKhzmxrwrnug="; Path=/; httpOnly; Expires=Sat, 04 Dec 2010 23:27:28 GMT';
+var cookie = new Cookie(str);
+
+// test .toString()
+assert.equal(cookie.toString(), str);
+
+// test .path
+assert.equal(cookie.path, '/');
+
+// test .httpOnly
+assert.equal(cookie.httpOnly, true);
+
+// test .name
+assert.equal(cookie.name, 'Sid');
+
+// test .value
+assert.equal(cookie.value, '"s543qactge.wKE61E01Bs%2BKhzmxrwrnug="');
+
+// test .expires
+assert.equal(cookie.expires instanceof Date, true);
+
+// test .path default
+var cookie = new Cookie('foo=bar', { url: 'http://foo.com/bar' });
+assert.equal(cookie.path, '/bar');
+
+console.log('All tests passed');
Index: Dev/trunk/src/node_modules/request/node_modules/cookie-jar/tests/test-cookiejar.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/cookie-jar/tests/test-cookiejar.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/cookie-jar/tests/test-cookiejar.js	(revision 484)
@@ -0,0 +1,90 @@
+var Cookie = require('../index')
+  , Jar = Cookie.Jar
+  , assert = require('assert');
+
+function expires(ms) {
+  return new Date(Date.now() + ms).toUTCString();
+}
+
+// test .get() expiration
+(function() {
+  var jar = new Jar;
+  var cookie = new Cookie('sid=1234; path=/; expires=' + expires(1000));
+  jar.add(cookie);
+  setTimeout(function(){
+    var cookies = jar.get({ url: 'http://foo.com/foo' });
+    assert.equal(cookies.length, 1);
+    assert.equal(cookies[0], cookie);
+    setTimeout(function(){
+      var cookies = jar.get({ url: 'http://foo.com/foo' });
+      assert.equal(cookies.length, 0);
+    }, 1000);
+  }, 5);
+})();
+
+// test .get() path support
+(function() {
+  var jar = new Jar;
+  var a = new Cookie('sid=1234; path=/');
+  var b = new Cookie('sid=1111; path=/foo/bar');
+  var c = new Cookie('sid=2222; path=/');
+  jar.add(a);
+  jar.add(b);
+  jar.add(c);
+
+  // should remove the duplicates
+  assert.equal(jar.cookies.length, 2);
+
+  // same name, same path, latter prevails
+  var cookies = jar.get({ url: 'http://foo.com/' });
+  assert.equal(cookies.length, 1);
+  assert.equal(cookies[0], c);
+
+  // same name, diff path, path specifity prevails, latter prevails
+  var cookies = jar.get({ url: 'http://foo.com/foo/bar' });
+  assert.equal(cookies.length, 1);
+  assert.equal(cookies[0], b);
+
+  var jar = new Jar;
+  var a = new Cookie('sid=1111; path=/foo/bar');
+  var b = new Cookie('sid=1234; path=/');
+  jar.add(a);
+  jar.add(b);
+
+  var cookies = jar.get({ url: 'http://foo.com/foo/bar' });
+  assert.equal(cookies.length, 1);
+  assert.equal(cookies[0], a);
+
+  var cookies = jar.get({ url: 'http://foo.com/' });
+  assert.equal(cookies.length, 1);
+  assert.equal(cookies[0], b);
+
+  var jar = new Jar;
+  var a = new Cookie('sid=1111; path=/foo/bar');
+  var b = new Cookie('sid=3333; path=/foo/bar');
+  var c = new Cookie('pid=3333; path=/foo/bar');
+  var d = new Cookie('sid=2222; path=/foo/');
+  var e = new Cookie('sid=1234; path=/');
+  jar.add(a);
+  jar.add(b);
+  jar.add(c);
+  jar.add(d);
+  jar.add(e);
+
+  var cookies = jar.get({ url: 'http://foo.com/foo/bar' });
+  assert.equal(cookies.length, 2);
+  assert.equal(cookies[0], b);
+  assert.equal(cookies[1], c);
+
+  var cookies = jar.get({ url: 'http://foo.com/foo/' });
+  assert.equal(cookies.length, 1);
+  assert.equal(cookies[0], d);
+
+  var cookies = jar.get({ url: 'http://foo.com/' });
+  assert.equal(cookies.length, 1);
+  assert.equal(cookies[0], e);
+})();
+
+setTimeout(function() {
+  console.log('All tests passed');
+}, 1200);
Index: Dev/trunk/src/node_modules/request/node_modules/forever-agent/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/forever-agent/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/forever-agent/LICENSE	(revision 484)
@@ -0,0 +1,55 @@
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
Index: Dev/trunk/src/node_modules/request/node_modules/forever-agent/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/forever-agent/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/forever-agent/README.md	(revision 484)
@@ -0,0 +1,4 @@
+forever-agent
+=============
+
+HTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.
Index: Dev/trunk/src/node_modules/request/node_modules/forever-agent/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/forever-agent/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/forever-agent/index.js	(revision 484)
@@ -0,0 +1,119 @@
+module.exports = ForeverAgent
+ForeverAgent.SSL = ForeverAgentSSL
+
+var util = require('util')
+  , Agent = require('http').Agent
+  , net = require('net')
+  , tls = require('tls')
+  , AgentSSL = require('https').Agent
+
+function ForeverAgent(options) {
+  var self = this
+  self.options = options || {}
+  self.requests = {}
+  self.sockets = {}
+  self.freeSockets = {}
+  self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets
+  self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets
+  self.on('free', function(socket, host, port) {
+    var name = host + ':' + port
+    if (self.requests[name] && self.requests[name].length) {
+      self.requests[name].shift().onSocket(socket)
+    } else if (self.sockets[name].length < self.minSockets) {
+      if (!self.freeSockets[name]) self.freeSockets[name] = []
+      self.freeSockets[name].push(socket)
+      
+      // if an error happens while we don't use the socket anyway, meh, throw the socket away
+      function onIdleError() {
+        socket.destroy()
+      }
+      socket._onIdleError = onIdleError
+      socket.on('error', onIdleError)
+    } else {
+      // If there are no pending requests just destroy the
+      // socket and it will get removed from the pool. This
+      // gets us out of timeout issues and allows us to
+      // default to Connection:keep-alive.
+      socket.destroy()
+    }
+  })
+
+}
+util.inherits(ForeverAgent, Agent)
+
+ForeverAgent.defaultMinSockets = 5
+
+
+ForeverAgent.prototype.createConnection = net.createConnection
+ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest
+ForeverAgent.prototype.addRequest = function(req, host, port) {
+  var name = host + ':' + port
+  if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) {
+    var idleSocket = this.freeSockets[name].pop()
+    idleSocket.removeListener('error', idleSocket._onIdleError)
+    delete idleSocket._onIdleError
+    req._reusedSocket = true
+    req.onSocket(idleSocket)
+  } else {
+    this.addRequestNoreuse(req, host, port)
+  }
+}
+
+ForeverAgent.prototype.removeSocket = function(s, name, host, port) {
+  if (this.sockets[name]) {
+    var index = this.sockets[name].indexOf(s)
+    if (index !== -1) {
+      this.sockets[name].splice(index, 1)
+    }
+  } else if (this.sockets[name] && this.sockets[name].length === 0) {
+    // don't leak
+    delete this.sockets[name]
+    delete this.requests[name]
+  }
+  
+  if (this.freeSockets[name]) {
+    var index = this.freeSockets[name].indexOf(s)
+    if (index !== -1) {
+      this.freeSockets[name].splice(index, 1)
+      if (this.freeSockets[name].length === 0) {
+        delete this.freeSockets[name]
+      }
+    }
+  }
+
+  if (this.requests[name] && this.requests[name].length) {
+    // If we have pending requests and a socket gets closed a new one
+    // needs to be created to take over in the pool for the one that closed.
+    this.createSocket(name, host, port).emit('free')
+  }
+}
+
+function ForeverAgentSSL (options) {
+  ForeverAgent.call(this, options)
+}
+util.inherits(ForeverAgentSSL, ForeverAgent)
+
+ForeverAgentSSL.prototype.createConnection = createConnectionSSL
+ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest
+
+function createConnectionSSL (port, host, options) {
+  if (typeof port === 'object') {
+    options = port;
+  } else if (typeof host === 'object') {
+    options = host;
+  } else if (typeof options === 'object') {
+    options = options;
+  } else {
+    options = {};
+  }
+
+  if (typeof port === 'number') {
+    options.port = port;
+  }
+
+  if (typeof host === 'string') {
+    options.host = host;
+  }
+
+  return tls.connect(options);
+}
Index: Dev/trunk/src/node_modules/request/node_modules/forever-agent/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/forever-agent/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/forever-agent/package.json	(revision 484)
@@ -0,0 +1,28 @@
+{
+  "author": {
+    "name": "Mikeal Rogers",
+    "email": "mikeal.rogers@gmail.com",
+    "url": "http://www.futurealoof.com"
+  },
+  "name": "forever-agent",
+  "description": "HTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.",
+  "version": "0.5.0",
+  "repository": {
+    "url": "https://github.com/mikeal/forever-agent"
+  },
+  "main": "index.js",
+  "dependencies": {},
+  "devDependencies": {},
+  "optionalDependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "readme": "forever-agent\n=============\n\nHTTP Agent that keeps socket connections alive between keep-alive requests. Formerly part of mikeal/request, now a standalone module.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/mikeal/forever-agent/issues"
+  },
+  "homepage": "https://github.com/mikeal/forever-agent",
+  "_id": "forever-agent@0.5.0",
+  "_from": "forever-agent@~0.5.0"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/.npmignore	(revision 484)
@@ -0,0 +1,5 @@
+*.un~
+/node_modules/*
+/test/tmp
+/.idea
+*.iml
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/.travis.yml	(revision 484)
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+  - "0.6"
+  - "0.8"
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/License
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/License	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/License	(revision 484)
@@ -0,0 +1,19 @@
+Copyright (c) 2012 Felix GeisendÃ¶rfer (felix@debuggable.com) and contributors
+
+ 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.
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+SHELL := /bin/bash
+
+test:
+	@./test/run.js
+
+.PHONY: test
+
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/Readme.md	(revision 484)
@@ -0,0 +1,146 @@
+# Form-Data [![Build Status](https://travis-ci.org/alexindigo/node-form-data.png?branch=master)](https://travis-ci.org/alexindigo/node-form-data)
+
+A module to create readable `"multipart/form-data"` streams.  Can be used to
+submit forms and file uploads to other web applications.
+
+The API of this module is inspired by the
+[XMLHttpRequest-2 FormData Interface][xhr2-fd].
+
+[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface
+
+## Install
+
+```
+npm install form-data
+```
+
+## Usage
+
+In this example we are constructing a form with 3 fields that contain a string,
+a buffer and a file stream.
+
+``` javascript
+var FormData = require('form-data');
+var fs = require('fs');
+
+var form = new FormData();
+form.append('my_field', 'my value');
+form.append('my_buffer', new Buffer(10));
+form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
+```
+
+Also you can use http-response stream:
+
+``` javascript
+var FormData = require('form-data');
+var http = require('http');
+
+var form = new FormData();
+
+http.request('http://nodejs.org/images/logo.png', function(response) {
+  form.append('my_field', 'my value');
+  form.append('my_buffer', new Buffer(10));
+  form.append('my_logo', response);
+});
+```
+
+Or @mikeal's request stream:
+
+``` javascript
+var FormData = require('form-data');
+var request = require('request');
+
+var form = new FormData();
+
+form.append('my_field', 'my value');
+form.append('my_buffer', new Buffer(10));
+form.append('my_logo', request('http://nodejs.org/images/logo.png'));
+```
+
+In order to submit this form to a web application, you can use node's http
+client interface:
+
+``` javascript
+var http = require('http');
+
+var request = http.request({
+  method: 'post',
+  host: 'example.org',
+  path: '/upload',
+  headers: form.getHeaders()
+});
+
+form.pipe(request);
+
+request.on('response', function(res) {
+  console.log(res.statusCode);
+});
+```
+
+Or if you would prefer the `'Content-Length'` header to be set for you:
+
+``` javascript
+form.submit('example.org/upload', function(err, res) {
+  console.log(res.statusCode);
+});
+```
+
+To use custom headers and pre-known length in parts:
+
+``` javascript
+var CRLF = '\r\n';
+var form = new FormData();
+
+var options = {
+  header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,
+  knownLength: 1
+};
+
+form.append('my_buffer', buffer, options);
+
+form.submit('http://example.com/', function(err, res) {
+  if (err) throw err;
+  console.log('Done');
+});
+```
+
+Form-Data can recognize and fetch all the required information from common types of streams (fs.readStream, http.response and mikeal's request), for some other types of streams you'd need to provide "file"-related information manually:
+
+``` javascript
+someModule.stream(function(err, stdout, stderr) {
+  if (err) throw err;
+
+  var form = new FormData();
+
+  form.append('file', stdout, {
+    filename: 'unicycle.jpg',
+    contentType: 'image/jpg',
+    knownLength: 19806
+  });
+
+  form.submit('http://example.com/', function(err, res) {
+    if (err) throw err;
+    console.log('Done');
+  });
+});
+```
+
+For edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter:
+
+``` javascript
+form.submit({
+  host: 'example.com',
+  path: '/probably.php?extra=params',
+  auth: 'username:password'
+}, function(err, res) {
+  console.log(res.statusCode);
+});
+```
+
+## TODO
+
+- Add new streams (0.10) support and try really hard not to break it for 0.8.x.
+
+## License
+
+Form-Data is licensed under the MIT license.
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/lib/form_data.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/lib/form_data.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/lib/form_data.js	(revision 484)
@@ -0,0 +1,292 @@
+var CombinedStream = require('combined-stream');
+var util = require('util');
+var path = require('path');
+var http = require('http');
+var https = require('https');
+var parseUrl = require('url').parse;
+var fs = require('fs');
+var mime = require('mime');
+var async = require('async');
+
+module.exports = FormData;
+function FormData() {
+  this._overheadLength = 0;
+  this._valueLength = 0;
+  this._lengthRetrievers = [];
+
+  CombinedStream.call(this);
+}
+util.inherits(FormData, CombinedStream);
+
+FormData.LINE_BREAK = '\r\n';
+
+FormData.prototype.append = function(field, value, options) {
+  options = options || {};
+
+  var append = CombinedStream.prototype.append.bind(this);
+
+  // all that streamy business can't handle numbers
+  if (typeof value == 'number') value = ''+value;
+
+  var header = this._multiPartHeader(field, value, options);
+  var footer = this._multiPartFooter(field, value, options);
+
+  append(header);
+  append(value);
+  append(footer);
+
+  // pass along options.knownLength
+  this._trackLength(header, value, options);
+};
+
+FormData.prototype._trackLength = function(header, value, options) {
+  var valueLength = 0;
+
+  // used w/ trackLengthSync(), when length is known.
+  // e.g. for streaming directly from a remote server,
+  // w/ a known file a size, and not wanting to wait for
+  // incoming file to finish to get its size.
+  if (options.knownLength != null) {
+    valueLength += +options.knownLength;
+  } else if (Buffer.isBuffer(value)) {
+    valueLength = value.length;
+  } else if (typeof value === 'string') {
+    valueLength = Buffer.byteLength(value);
+  }
+
+  this._valueLength += valueLength;
+
+  // @check why add CRLF? does this account for custom/multiple CRLFs?
+  this._overheadLength +=
+    Buffer.byteLength(header) +
+    + FormData.LINE_BREAK.length;
+
+  // empty or either doesn't have path or not an http response
+  if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) )) {
+    return;
+  }
+
+  this._lengthRetrievers.push(function(next) {
+
+    // do we already know the size?
+    // 0 additional leaves value from getSyncLength()
+    if (options.knownLength != null) {
+      next(null, 0);
+
+    // check if it's local file
+    } else if (value.hasOwnProperty('fd')) {
+      fs.stat(value.path, function(err, stat) {
+        if (err) {
+          next(err);
+          return;
+        }
+
+        next(null, stat.size);
+      });
+
+    // or http response
+    } else if (value.hasOwnProperty('httpVersion')) {
+      next(null, +value.headers['content-length']);
+
+    // or request stream http://github.com/mikeal/request
+    } else if (value.hasOwnProperty('httpModule')) {
+      // wait till response come back
+      value.on('response', function(response) {
+        value.pause();
+        next(null, +response.headers['content-length']);
+      });
+      value.resume();
+
+    // something else
+    } else {
+      next('Unknown stream');
+    }
+  });
+};
+
+FormData.prototype._multiPartHeader = function(field, value, options) {
+  var boundary = this.getBoundary();
+  var header = '';
+
+  // custom header specified (as string)?
+  // it becomes responsible for boundary
+  // (e.g. to handle extra CRLFs on .NET servers)
+  if (options.header != null) {
+    header = options.header;
+  } else {
+    header += '--' + boundary + FormData.LINE_BREAK +
+      'Content-Disposition: form-data; name="' + field + '"';
+
+    // fs- and request- streams have path property
+    // or use custom filename and/or contentType
+    // TODO: Use request's response mime-type
+    if (options.filename || value.path) {
+      header +=
+        '; filename="' + path.basename(options.filename || value.path) + '"' + FormData.LINE_BREAK +
+        'Content-Type: ' +  (options.contentType || mime.lookup(options.filename || value.path));
+
+    // http response has not
+    } else if (value.readable && value.hasOwnProperty('httpVersion')) {
+      header +=
+        '; filename="' + path.basename(value.client._httpMessage.path) + '"' + FormData.LINE_BREAK +
+        'Content-Type: ' + value.headers['content-type'];
+    }
+
+    header += FormData.LINE_BREAK + FormData.LINE_BREAK;
+  }
+
+  return header;
+};
+
+FormData.prototype._multiPartFooter = function(field, value, options) {
+  return function(next) {
+    var footer = FormData.LINE_BREAK;
+
+    var lastPart = (this._streams.length === 0);
+    if (lastPart) {
+      footer += this._lastBoundary();
+    }
+
+    next(footer);
+  }.bind(this);
+};
+
+FormData.prototype._lastBoundary = function() {
+  return '--' + this.getBoundary() + '--';
+};
+
+FormData.prototype.getHeaders = function(userHeaders) {
+  var formHeaders = {
+    'content-type': 'multipart/form-data; boundary=' + this.getBoundary()
+  };
+
+  for (var header in userHeaders) {
+    formHeaders[header.toLowerCase()] = userHeaders[header];
+  }
+
+  return formHeaders;
+}
+
+FormData.prototype.getCustomHeaders = function(contentType) {
+    contentType = contentType ? contentType : 'multipart/form-data';
+
+    var formHeaders = {
+        'content-type': contentType + '; boundary=' + this.getBoundary(),
+        'content-length': this.getLengthSync()
+    };
+
+    return formHeaders;
+}
+
+FormData.prototype.getBoundary = function() {
+  if (!this._boundary) {
+    this._generateBoundary();
+  }
+
+  return this._boundary;
+};
+
+FormData.prototype._generateBoundary = function() {
+  // This generates a 50 character boundary similar to those used by Firefox.
+  // They are optimized for boyer-moore parsing.
+  var boundary = '--------------------------';
+  for (var i = 0; i < 24; i++) {
+    boundary += Math.floor(Math.random() * 10).toString(16);
+  }
+
+  this._boundary = boundary;
+};
+
+FormData.prototype.getLengthSync = function() {
+    var knownLength = this._overheadLength + this._valueLength;
+
+    if (this._streams.length) {
+        knownLength += this._lastBoundary().length;
+    }
+
+    return knownLength;
+};
+
+FormData.prototype.getLength = function(cb) {
+  var knownLength = this._overheadLength + this._valueLength;
+
+  if (this._streams.length) {
+    knownLength += this._lastBoundary().length;
+  }
+
+  if (!this._lengthRetrievers.length) {
+    process.nextTick(cb.bind(this, null, knownLength));
+    return;
+  }
+
+  async.parallel(this._lengthRetrievers, function(err, values) {
+    if (err) {
+      cb(err);
+      return;
+    }
+
+    values.forEach(function(length) {
+      knownLength += length;
+    });
+
+    cb(null, knownLength);
+  });
+};
+
+FormData.prototype.submit = function(params, cb) {
+  this.getLength(function(err, length) {
+
+    var request
+      , options
+      , defaults = {
+          method : 'post',
+          port   : 80,
+          headers: this.getHeaders({'Content-Length': length})
+      };
+
+    // parse provided url if it's string
+    // or treat it as options object
+    if (typeof params == 'string') {
+      params = parseUrl(params);
+
+      options = populate({
+        port: params.port,
+        path: params.pathname,
+        host: params.hostname
+      }, defaults);
+    }
+    else // use custom params
+    {
+      options = populate(params, defaults);
+    }
+
+    // https if specified, fallback to http in any other case
+    if (params.protocol == 'https:') {
+      // override default port
+      if (!params.port) options.port = 443;
+      request = https.request(options);
+    } else {
+      request = http.request(options);
+    }
+
+    this.pipe(request);
+    if (cb) {
+      request.on('error', cb);
+      request.on('response', cb.bind(this, null));
+    }
+
+    return request;
+  }.bind(this));
+};
+
+/*
+ * Santa's little helpers
+ */
+
+// populates missing values
+function populate(dst, src) {
+  for (var prop in src) {
+    if (!dst[prop]) dst[prop] = src[prop];
+  }
+  return dst;
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node-form-data.sublime-project
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node-form-data.sublime-project	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node-form-data.sublime-project	(revision 484)
@@ -0,0 +1,8 @@
+{
+	"folders":
+	[
+		{
+			"path": "/Users/alexi/Dropbox/Projects/node-form-data"
+		}
+	]
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node-form-data.sublime-workspace
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node-form-data.sublime-workspace	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node-form-data.sublime-workspace	(revision 484)
@@ -0,0 +1,673 @@
+{
+	"auto_complete":
+	{
+		"selected_items":
+		[
+			[
+				"back",
+				"background-clip"
+			],
+			[
+				"di",
+				"display"
+			],
+			[
+				"background-",
+				"background-position"
+			],
+			[
+				"de",
+				"defaults"
+			],
+			[
+				"no",
+				"normal"
+			],
+			[
+				"line",
+				"line-height"
+			]
+		]
+	},
+	"buffers":
+	[
+		{
+			"file": "test/integration/test-pipe.js",
+			"settings":
+			{
+				"buffer_size": 3625,
+				"line_ending": "Unix"
+			}
+		},
+		{
+			"file": "package.json",
+			"settings":
+			{
+				"buffer_size": 673,
+				"line_ending": "Unix"
+			}
+		},
+		{
+			"file": "lib/form_data.js",
+			"settings":
+			{
+				"buffer_size": 7510,
+				"line_ending": "Unix"
+			}
+		},
+		{
+			"contents": "/*!\n * jQuery JavaScript Library v1.8.3\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: Tue Nov 13 2012 08:20:33 GMT-0500 (Eastern Standard Time)\n */\n(function( window, undefined ) {\nvar\n  // A central reference to the root jQuery(document)\n  rootjQuery,\n\n  // The deferred used on DOM ready\n  readyList,\n\n  // Use the correct document accordingly with window argument (sandbox)\n  document = window.document,\n  location = window.location,\n  navigator = window.navigator,\n\n  // Map over jQuery in case of overwrite\n  _jQuery = window.jQuery,\n\n  // Map over the $ in case of overwrite\n  _$ = window.$,\n\n  // Save a reference to some core methods\n  core_push = Array.prototype.push,\n  core_slice = Array.prototype.slice,\n  core_indexOf = Array.prototype.indexOf,\n  core_toString = Object.prototype.toString,\n  core_hasOwn = Object.prototype.hasOwnProperty,\n  core_trim = String.prototype.trim,\n\n  // Define a local copy of jQuery\n  jQuery = function( selector, context ) {\n    // The jQuery object is actually just the init constructor 'enhanced'\n    return new jQuery.fn.init( selector, context, rootjQuery );\n  },\n\n  // Used for matching numbers\n  core_pnum = /[\\-+]?(?:\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/.source,\n\n  // Used for detecting and trimming whitespace\n  core_rnotwhite = /\\S/,\n  core_rspace = /\\s+/,\n\n  // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)\n  rtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n  // A simple way to check for HTML strings\n  // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n  rquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n  // Match a standalone tag\n  rsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n\n  // JSON RegExp\n  rvalidchars = /^[\\],:{}\\s]*$/,\n  rvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n  rvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,\n  rvalidtokens = /\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/g,\n\n  // Matches dashed string for camelizing\n  rmsPrefix = /^-ms-/,\n  rdashAlpha = /-([\\da-z])/gi,\n\n  // Used by jQuery.camelCase as callback to replace()\n  fcamelCase = function( all, letter ) {\n    return ( letter + \"\" ).toUpperCase();\n  },\n\n  // The ready event handler and self cleanup method\n  DOMContentLoaded = function() {\n    if ( document.addEventListener ) {\n      document.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n      jQuery.ready();\n    } else if ( document.readyState === \"complete\" ) {\n      // we're here because readyState === \"complete\" in oldIE\n      // which is good enough for us to call the dom ready!\n      document.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n      jQuery.ready();\n    }\n  },\n\n  // [[Class]] -> type pairs\n  class2type = {};\n\njQuery.fn = jQuery.prototype = {\n  constructor: jQuery,\n  init: function( selector, context, rootjQuery ) {\n    var match, elem, ret, doc;\n\n    // Handle $(\"\"), $(null), $(undefined), $(false)\n    if ( !selector ) {\n      return this;\n    }\n\n    // Handle $(DOMElement)\n    if ( selector.nodeType ) {\n      this.context = this[0] = selector;\n      this.length = 1;\n      return this;\n    }\n\n    // Handle HTML strings\n    if ( typeof selector === \"string\" ) {\n      if ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n        // Assume that strings that start and end with <> are HTML and skip the regex check\n        match = [ null, selector, null ];\n\n      } else {\n        match = rquickExpr.exec( selector );\n      }\n\n      // Match html or make sure no context is specified for #id\n      if ( match && (match[1] || !context) ) {\n\n        // HANDLE: $(html) -> $(array)\n        if ( match[1] ) {\n          context = context instanceof jQuery ? context[0] : context;\n          doc = ( context && context.nodeType ? context.ownerDocument || context : document );\n\n          // scripts is true for back-compat\n          selector = jQuery.parseHTML( match[1], doc, true );\n          if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n            this.attr.call( selector, context, true );\n          }\n\n          return jQuery.merge( this, selector );\n\n        // HANDLE: $(#id)\n        } else {\n          elem = document.getElementById( match[2] );\n\n          // Check parentNode to catch when Blackberry 4.6 returns\n          // nodes that are no longer in the document #6963\n          if ( elem && elem.parentNode ) {\n            // Handle the case where IE and Opera return items\n            // by name instead of ID\n            if ( elem.id !== match[2] ) {\n              return rootjQuery.find( selector );\n            }\n\n            // Otherwise, we inject the element directly into the jQuery object\n            this.length = 1;\n            this[0] = elem;\n          }\n\n          this.context = document;\n          this.selector = selector;\n          return this;\n        }\n\n      // HANDLE: $(expr, $(...))\n      } else if ( !context || context.jquery ) {\n        return ( context || rootjQuery ).find( selector );\n\n      // HANDLE: $(expr, context)\n      // (which is just equivalent to: $(context).find(expr)\n      } else {\n        return this.constructor( context ).find( selector );\n      }\n\n    // HANDLE: $(function)\n    // Shortcut for document ready\n    } else if ( jQuery.isFunction( selector ) ) {\n      return rootjQuery.ready( selector );\n    }\n\n    if ( selector.selector !== undefined ) {\n      this.selector = selector.selector;\n      this.context = selector.context;\n    }\n\n    return jQuery.makeArray( selector, this );\n  },\n\n  // Start with an empty selector\n  selector: \"\",\n\n  // The current version of jQuery being used\n  jquery: \"1.8.3\",\n\n  // The default length of a jQuery object is 0\n  length: 0,\n\n  // The number of elements contained in the matched element set\n  size: function() {\n    return this.length;\n  },\n\n  toArray: function() {\n    return core_slice.call( this );\n  },\n\n  // Get the Nth element in the matched element set OR\n  // Get the whole matched element set as a clean array\n  get: function( num ) {\n    return num == null ?\n\n      // Return a 'clean' array\n      this.toArray() :\n\n      // Return just the object\n      ( num < 0 ? this[ this.length + num ] : this[ num ] );\n  },\n\n  // Take an array of elements and push it onto the stack\n  // (returning the new matched element set)\n  pushStack: function( elems, name, selector ) {\n\n    // Build a new jQuery matched element set\n    var ret = jQuery.merge( this.constructor(), elems );\n\n    // Add the old object onto the stack (as a reference)\n    ret.prevObject = this;\n\n    ret.context = this.context;\n\n    if ( name === \"find\" ) {\n      ret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n    } else if ( name ) {\n      ret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n    }\n\n    // Return the newly-formed element set\n    return ret;\n  },\n\n  // Execute a callback for every element in the matched set.\n  // (You can seed the arguments with an array of args, but this is\n  // only used internally.)\n  each: function( callback, args ) {\n    return jQuery.each( this, callback, args );\n  },\n\n  ready: function( fn ) {\n    // Add the callback\n    jQuery.ready.promise().done( fn );\n\n    return this;\n  },\n\n  eq: function( i ) {\n    i = +i;\n    return i === -1 ?\n      this.slice( i ) :\n      this.slice( i, i + 1 );\n  },\n\n  first: function() {\n    return this.eq( 0 );\n  },\n\n  last: function() {\n    return this.eq( -1 );\n  },\n\n  slice: function() {\n    return this.pushStack( core_slice.apply( this, arguments ),\n      \"slice\", core_slice.call(arguments).join(\",\") );\n  },\n\n  map: function( callback ) {\n    return this.pushStack( jQuery.map(this, function( elem, i ) {\n      return callback.call( elem, i, elem );\n    }));\n  },\n\n  end: function() {\n    return this.prevObject || this.constructor(null);\n  },\n\n  // For internal use only.\n  // Behaves like an Array's method, not like a jQuery method.\n  push: core_push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n  var options, name, src, copy, copyIsArray, clone,\n    target = arguments[0] || {},\n    i = 1,\n    length = arguments.length,\n    deep = false;\n\n  // Handle a deep copy situation\n  if ( typeof target === \"boolean\" ) {\n    deep = target;\n    target = arguments[1] || {};\n    // skip the boolean and the target\n    i = 2;\n  }\n\n  // Handle case when target is a string or something (possible in deep copy)\n  if ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n    target = {};\n  }\n\n  // extend jQuery itself if only one argument is passed\n  if ( length === i ) {\n    target = this;\n    --i;\n  }\n\n  for ( ; i < length; i++ ) {\n    // Only deal with non-null/undefined values\n    if ( (options = arguments[ i ]) != null ) {\n      // Extend the base object\n      for ( name in options ) {\n        src = target[ name ];\n        copy = options[ name ];\n\n        // Prevent never-ending loop\n        if ( target === copy ) {\n          continue;\n        }\n\n        // Recurse if we're merging plain objects or arrays\n        if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n          if ( copyIsArray ) {\n            copyIsArray = false;\n            clone = src && jQuery.isArray(src) ? src : [];\n\n          } else {\n            clone = src && jQuery.isPlainObject(src) ? src : {};\n          }\n\n          // Never move original objects, clone them\n          target[ name ] = jQuery.extend( deep, clone, copy );\n\n        // Don't bring in undefined values\n        } else if ( copy !== undefined ) {\n          target[ name ] = copy;\n        }\n      }\n    }\n  }\n\n  // Return the modified object\n  return target;\n};\n\njQuery.extend({\n  noConflict: function( deep ) {\n    if ( window.$ === jQuery ) {\n      window.$ = _$;\n    }\n\n    if ( deep && window.jQuery === jQuery ) {\n      window.jQuery = _jQuery;\n    }\n\n    return jQuery;\n  },\n\n  // Is the DOM ready to be used? Set to true once it occurs.\n  isReady: false,\n\n  // A counter to track how many items to wait for before\n  // the ready event fires. See #6781\n  readyWait: 1,\n\n  // Hold (or release) the ready event\n  holdReady: function( hold ) {\n    if ( hold ) {\n      jQuery.readyWait++;\n    } else {\n      jQuery.ready( true );\n    }\n  },\n\n  // Handle when the DOM is ready\n  ready: function( wait ) {\n\n    // Abort if there are pending holds or we're already ready\n    if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n      return;\n    }\n\n    // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n    if ( !document.body ) {\n      return setTimeout( jQuery.ready, 1 );\n    }\n\n    // Remember that the DOM is ready\n    jQuery.isReady = true;\n\n    // If a normal DOM Ready event fired, decrement, and wait if need be\n    if ( wait !== true && --jQuery.readyWait > 0 ) {\n      return;\n    }\n\n    // If there are functions bound, to execute\n    readyList.resolveWith( document, [ jQuery ] );\n\n    // Trigger any bound ready events\n    if ( jQuery.fn.trigger ) {\n      jQuery( document ).trigger(\"ready\").off(\"ready\");\n    }\n  },\n\n  // See test/unit/core.js for details concerning isFunction.\n  // Since version 1.3, DOM methods and functions like alert\n  // aren't supported. They return false on IE (#2968).\n  isFunction: function( obj ) {\n    return jQuery.type(obj) === \"function\";\n  },\n\n  isArray: Array.isArray || function( obj ) {\n    return jQuery.type(obj) === \"array\";\n  },\n\n  isWindow: function( obj ) {\n    return obj != null && obj == obj.window;\n  },\n\n  isNumeric: function( obj ) {\n    return !isNaN( parseFloat(obj) ) && isFinite( obj );\n  },\n\n  type: function( obj ) {\n    return obj == null ?\n      String( obj ) :\n      class2type[ core_toString.call(obj) ] || \"object\";\n  },\n\n  isPlainObject: function( obj ) {\n    // Must be an Object.\n    // Because of IE, we also have to check the presence of the constructor property.\n    // Make sure that DOM nodes and window objects don't pass through, as well\n    if ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n      return false;\n    }\n\n    try {\n      // Not own constructor property must be Object\n      if ( obj.constructor &&\n        !core_hasOwn.call(obj, \"constructor\") &&\n        !core_hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n        return false;\n      }\n    } catch ( e ) {\n      // IE8,9 Will throw exceptions on certain host objects #9897\n      return false;\n    }\n\n    // Own properties are enumerated firstly, so to speed up,\n    // if last one is own, then all properties are own.\n\n    var key;\n    for ( key in obj ) {}\n\n    return key === undefined || core_hasOwn.call( obj, key );\n  },\n\n  isEmptyObject: function( obj ) {\n    var name;\n    for ( name in obj ) {\n      return false;\n    }\n    return true;\n  },\n\n  error: function( msg ) {\n    throw new Error( msg );\n  },\n\n  // data: string of html\n  // context (optional): If specified, the fragment will be created in this context, defaults to document\n  // scripts (optional): If true, will include scripts passed in the html string\n  parseHTML: function( data, context, scripts ) {\n    var parsed;\n    if ( !data || typeof data !== \"string\" ) {\n      return null;\n    }\n    if ( typeof context === \"boolean\" ) {\n      scripts = context;\n      context = 0;\n    }\n    context = context || document;\n\n    // Single tag\n    if ( (parsed = rsingleTag.exec( data )) ) {\n      return [ context.createElement( parsed[1] ) ];\n    }\n\n    parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );\n    return jQuery.merge( [],\n      (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );\n  },\n\n  parseJSON: function( data ) {\n    if ( !data || typeof data !== \"string\") {\n      return null;\n    }\n\n    // Make sure leading/trailing whitespace is removed (IE can't handle it)\n    data = jQuery.trim( data );\n\n    // Attempt to parse using the native JSON parser first\n    if ( window.JSON && window.JSON.parse ) {\n      return window.JSON.parse( data );\n    }\n\n    // Make sure the incoming data is actual JSON\n    // Logic borrowed from http://json.org/json2.js\n    if ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n      .replace( rvalidtokens, \"]\" )\n      .replace( rvalidbraces, \"\")) ) {\n\n      return ( new Function( \"return \" + data ) )();\n\n    }\n    jQuery.error( \"Invalid JSON: \" + data );\n  },\n\n  // Cross-browser xml parsing\n  parseXML: function( data ) {\n    var xml, tmp;\n    if ( !data || typeof data !== \"string\" ) {\n      return null;\n    }\n    try {\n      if ( window.DOMParser ) { // Standard\n        tmp = new DOMParser();\n        xml = tmp.parseFromString( data , \"text/xml\" );\n      } else { // IE\n        xml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n        xml.async = \"false\";\n        xml.loadXML( data );\n      }\n    } catch( e ) {\n      xml = undefined;\n    }\n    if ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n      jQuery.error( \"Invalid XML: \" + data );\n    }\n    return xml;\n  },\n\n  noop: function() {},\n\n  // Evaluates a script in a global context\n  // Workarounds based on findings by Jim Driscoll\n  // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n  globalEval: function( data ) {\n    if ( data && core_rnotwhite.test( data ) ) {\n      // We use execScript on Internet Explorer\n      // We use an anonymous function so that context is window\n      // rather than jQuery in Firefox\n      ( window.execScript || function( data ) {\n        window[ \"eval\" ].call( window, data );\n      } )( data );\n    }\n  },\n\n  // Convert dashed to camelCase; used by the css and data modules\n  // Microsoft forgot to hump their vendor prefix (#9572)\n  camelCase: function( string ) {\n    return string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n  },\n\n  nodeName: function( elem, name ) {\n    return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n  },\n\n  // args is for internal usage only\n  each: function( obj, callback, args ) {\n    var name,\n      i = 0,\n      length = obj.length,\n      isObj = length === undefined || jQuery.isFunction( obj );\n\n    if ( args ) {\n      if ( isObj ) {\n        for ( name in obj ) {\n          if ( callback.apply( obj[ name ], args ) === false ) {\n            break;\n          }\n        }\n      } else {\n        for ( ; i < length; ) {\n          if ( callback.apply( obj[ i++ ], args ) === false ) {\n            break;\n          }\n        }\n      }\n\n    // A special, fast, case for the most common use of each\n    } else {\n      if ( isObj ) {\n        for ( name in obj ) {\n          if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {\n            break;\n          }\n        }\n      } else {\n        for ( ; i < length; ) {\n          if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {\n            break;\n          }\n        }\n      }\n    }\n\n    return obj;\n  },\n\n  // Use native String.trim function wherever possible\n  trim: core_trim && !core_trim.call(\"\\uFEFF\\xA0\") ?\n    function( text ) {\n      return text == null ?\n        \"\" :\n        core_trim.call( text );\n    } :\n\n    // Otherwise use our own trimming functionality\n    function( text ) {\n      return text == null ?\n        \"\" :\n        ( text + \"\" ).replace( rtrim, \"\" );\n    },\n\n  // results is for internal usage only\n  makeArray: function( arr, results ) {\n    var type,\n      ret = results || [];\n\n    if ( arr != null ) {\n      // The window, strings (and functions) also have 'length'\n      // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n      type = jQuery.type( arr );\n\n      if ( arr.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( arr ) ) {\n        core_push.call( ret, arr );\n      } else {\n        jQuery.merge( ret, arr );\n      }\n    }\n\n    return ret;\n  },\n\n  inArray: function( elem, arr, i ) {\n    var len;\n\n    if ( arr ) {\n      if ( core_indexOf ) {\n        return core_indexOf.call( arr, elem, i );\n      }\n\n      len = arr.length;\n      i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n      for ( ; i < len; i++ ) {\n        // Skip accessing in sparse arrays\n        if ( i in arr && arr[ i ] === elem ) {\n          return i;\n        }\n      }\n    }\n\n    return -1;\n  },\n\n  merge: function( first, second ) {\n    var l = second.length,\n      i = first.length,\n      j = 0;\n\n    if ( typeof l === \"number\" ) {\n      for ( ; j < l; j++ ) {\n        first[ i++ ] = second[ j ];\n      }\n\n    } else {\n      while ( second[j] !== undefined ) {\n        first[ i++ ] = second[ j++ ];\n      }\n    }\n\n    first.length = i;\n\n    return first;\n  },\n\n  grep: function( elems, callback, inv ) {\n    var retVal,\n      ret = [],\n      i = 0,\n      length = elems.length;\n    inv = !!inv;\n\n    // Go through the array, only saving the items\n    // that pass the validator function\n    for ( ; i < length; i++ ) {\n      retVal = !!callback( elems[ i ], i );\n      if ( inv !== retVal ) {\n        ret.push( elems[ i ] );\n      }\n    }\n\n    return ret;\n  },\n\n  // arg is for internal usage only\n  map: function( elems, callback, arg ) {\n    var value, key,\n      ret = [],\n      i = 0,\n      length = elems.length,\n      // jquery objects are treated as arrays\n      isArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n    // Go through the array, translating each of the items to their\n    if ( isArray ) {\n      for ( ; i < length; i++ ) {\n        value = callback( elems[ i ], i, arg );\n\n        if ( value != null ) {\n          ret[ ret.length ] = value;\n        }\n      }\n\n    // Go through every key on the object,\n    } else {\n      for ( key in elems ) {\n        value = callback( elems[ key ], key, arg );\n\n        if ( value != null ) {\n          ret[ ret.length ] = value;\n        }\n      }\n    }\n\n    // Flatten any nested arrays\n    return ret.concat.apply( [], ret );\n  },\n\n  // A global GUID counter for objects\n  guid: 1,\n\n  // Bind a function to a context, optionally partially applying any\n  // arguments.\n  proxy: function( fn, context ) {\n    var tmp, args, proxy;\n\n    if ( typeof context === \"string\" ) {\n      tmp = fn[ context ];\n      context = fn;\n      fn = tmp;\n    }\n\n    // Quick check to determine if target is callable, in the spec\n    // this throws a TypeError, but we will just return undefined.\n    if ( !jQuery.isFunction( fn ) ) {\n      return undefined;\n    }\n\n    // Simulated bind\n    args = core_slice.call( arguments, 2 );\n    proxy = function() {\n      return fn.apply( context, args.concat( core_slice.call( arguments ) ) );\n    };\n\n    // Set the guid of unique handler to the same of original handler, so it can be removed\n    proxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n    return proxy;\n  },\n\n  // Multifunctional method to get and set values of a collection\n  // The value/s can optionally be executed if it's a function\n  access: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n    var exec,\n      bulk = key == null,\n      i = 0,\n      length = elems.length;\n\n    // Sets many values\n    if ( key && typeof key === \"object\" ) {\n      for ( i in key ) {\n        jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n      }\n      chainable = 1;\n\n    // Sets one value\n    } else if ( value !== undefined ) {\n      // Optionally, function values get executed if exec is true\n      exec = pass === undefined && jQuery.isFunction( value );\n\n      if ( bulk ) {\n        // Bulk operations only iterate when executing function values\n        if ( exec ) {\n          exec = fn;\n          fn = function( elem, key, value ) {\n            return exec.call( jQuery( elem ), value );\n          };\n\n        // Otherwise they run against the entire set\n        } else {\n          fn.call( elems, value );\n          fn = null;\n        }\n      }\n\n      if ( fn ) {\n        for (; i < length; i++ ) {\n          fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n        }\n      }\n\n      chainable = 1;\n    }\n\n    return chainable ?\n      elems :\n\n      // Gets\n      bulk ?\n        fn.call( elems ) :\n        length ? fn( elems[0], key ) : emptyGet;\n  },\n\n  now: function() {\n    return ( new Date() ).getTime();\n  }\n});\n\njQuery.ready.promise = function( obj ) {\n  if ( !readyList ) {\n\n    readyList = jQuery.Deferred();\n\n    // Catch cases where $(document).ready() is called after the browser event has already occurred.\n    // we once tried to use readyState \"interactive\" here, but it caused issues like the one\n    // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n    if ( document.readyState === \"complete\" ) {\n      // Handle it asynchronously to allow scripts the opportunity to delay ready\n      setTimeout( jQuery.ready, 1 );\n\n    // Standards-based browsers support DOMContentLoaded\n    } else if ( document.addEventListener ) {\n      // Use the handy event callback\n      document.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n      // A fallback to window.onload, that will always work\n      window.addEventListener( \"load\", jQuery.ready, false );\n\n    // If IE event model is used\n    } else {\n      // Ensure firing before onload, maybe late but safe also for iframes\n      document.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n      // A fallback to window.onload, that will always work\n      window.attachEvent( \"onload\", jQuery.ready );\n\n      // If IE and not a frame\n      // continually check to see if the document is ready\n      var top = false;\n\n      try {\n        top = window.frameElement == null && document.documentElement;\n      } catch(e) {}\n\n      if ( top && top.doScroll ) {\n        (function doScrollCheck() {\n          if ( !jQuery.isReady ) {\n\n            try {\n              // Use the trick by Diego Perini\n              // http://javascript.nwbox.com/IEContentLoaded/\n              top.doScroll(\"left\");\n            } catch(e) {\n              return setTimeout( doScrollCheck, 50 );\n            }\n\n            // and execute any waiting functions\n            jQuery.ready();\n          }\n        })();\n      }\n    }\n  }\n  return readyList.promise( obj );\n};\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n  class2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n  var object = optionsCache[ options ] = {};\n  jQuery.each( options.split( core_rspace ), function( _, flag ) {\n    object[ flag ] = true;\n  });\n  return object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *  options: an optional list of space-separated options that will change how\n *      the callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *  once:     will ensure the callback list can only be fired once (like a Deferred)\n *\n *  memory:     will keep track of previous values and will call any callback added\n *          after the list has been fired right away with the latest \"memorized\"\n *          values (like a Deferred)\n *\n *  unique:     will ensure a callback can only be added once (no duplicate in the list)\n *\n *  stopOnFalse:  interrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n  // Convert options from String-formatted to Object-formatted if needed\n  // (we check in cache first)\n  options = typeof options === \"string\" ?\n    ( optionsCache[ options ] || createOptions( options ) ) :\n    jQuery.extend( {}, options );\n\n  var // Last fire value (for non-forgettable lists)\n    memory,\n    // Flag to know if list was already fired\n    fired,\n    // Flag to know if list is currently firing\n    firing,\n    // First callback to fire (used internally by add and fireWith)\n    firingStart,\n    // End of the loop when firing\n    firingLength,\n    // Index of currently firing callback (modified by remove if needed)\n    firingIndex,\n    // Actual callback list\n    list = [],\n    // Stack of fire calls for repeatable lists\n    stack = !options.once && [],\n    // Fire callbacks\n    fire = function( data ) {\n      memory = options.memory && data;\n      fired = true;\n      firingIndex = firingStart || 0;\n      firingStart = 0;\n      firingLength = list.length;\n      firing = true;\n      for ( ; list && firingIndex < firingLength; firingIndex++ ) {\n        if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n          memory = false; // To prevent further calls using add\n          break;\n        }\n      }\n      firing = false;\n      if ( list ) {\n        if ( stack ) {\n          if ( stack.length ) {\n            fire( stack.shift() );\n          }\n        } else if ( memory ) {\n          list = [];\n        } else {\n          self.disable();\n        }\n      }\n    },\n    // Actual Callbacks object\n    self = {\n      // Add a callback or a collection of callbacks to the list\n      add: function() {\n        if ( list ) {\n          // First, we save the current length\n          var start = list.length;\n          (function add( args ) {\n            jQuery.each( args, function( _, arg ) {\n              var type = jQuery.type( arg );\n              if ( type === \"function\" ) {\n                if ( !options.unique || !self.has( arg ) ) {\n                  list.push( arg );\n                }\n              } else if ( arg && arg.length && type !== \"string\" ) {\n                // Inspect recursively\n                add( arg );\n              }\n            });\n          })( arguments );\n          // Do we need to add the callbacks to the\n          // current firing batch?\n          if ( firing ) {\n            firingLength = list.length;\n          // With memory, if we're not firing then\n          // we should call right away\n          } else if ( memory ) {\n            firingStart = start;\n            fire( memory );\n          }\n        }\n        return this;\n      },\n      // Remove a callback from the list\n      remove: function() {\n        if ( list ) {\n          jQuery.each( arguments, function( _, arg ) {\n            var index;\n            while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n              list.splice( index, 1 );\n              // Handle firing indexes\n              if ( firing ) {\n                if ( index <= firingLength ) {\n                  firingLength--;\n                }\n                if ( index <= firingIndex ) {\n                  firingIndex--;\n                }\n              }\n            }\n          });\n        }\n        return this;\n      },\n      // Control if a given callback is in the list\n      has: function( fn ) {\n        return jQuery.inArray( fn, list ) > -1;\n      },\n      // Remove all callbacks from the list\n      empty: function() {\n        list = [];\n        return this;\n      },\n      // Have the list do nothing anymore\n      disable: function() {\n        list = stack = memory = undefined;\n        return this;\n      },\n      // Is it disabled?\n      disabled: function() {\n        return !list;\n      },\n      // Lock the list in its current state\n      lock: function() {\n        stack = undefined;\n        if ( !memory ) {\n          self.disable();\n        }\n        return this;\n      },\n      // Is it locked?\n      locked: function() {\n        return !stack;\n      },\n      // Call all callbacks with the given context and arguments\n      fireWith: function( context, args ) {\n        args = args || [];\n        args = [ context, args.slice ? args.slice() : args ];\n        if ( list && ( !fired || stack ) ) {\n          if ( firing ) {\n            stack.push( args );\n          } else {\n            fire( args );\n          }\n        }\n        return this;\n      },\n      // Call all the callbacks with the given arguments\n      fire: function() {\n        self.fireWith( this, arguments );\n        return this;\n      },\n      // To know if the callbacks have already been called at least once\n      fired: function() {\n        return !!fired;\n      }\n    };\n\n  return self;\n};\njQuery.extend({\n\n  Deferred: function( func ) {\n    var tuples = [\n        // action, add listener, listener list, final state\n        [ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n        [ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n        [ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n      ],\n      state = \"pending\",\n      promise = {\n        state: function() {\n          return state;\n        },\n        always: function() {\n          deferred.done( arguments ).fail( arguments );\n          return this;\n        },\n        then: function( /* fnDone, fnFail, fnProgress */ ) {\n          var fns = arguments;\n          return jQuery.Deferred(function( newDefer ) {\n            jQuery.each( tuples, function( i, tuple ) {\n              var action = tuple[ 0 ],\n                fn = fns[ i ];\n              // deferred[ done | fail | progress ] for forwarding actions to newDefer\n              deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?\n                function() {\n                  var returned = fn.apply( this, arguments );\n                  if ( returned && jQuery.isFunction( returned.promise ) ) {\n                    returned.promise()\n                      .done( newDefer.resolve )\n                      .fail( newDefer.reject )\n                      .progress( newDefer.notify );\n                  } else {\n                    newDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n                  }\n                } :\n                newDefer[ action ]\n              );\n            });\n            fns = null;\n          }).promise();\n        },\n        // Get a promise for this deferred\n        // If obj is provided, the promise aspect is added to the object\n        promise: function( obj ) {\n          return obj != null ? jQuery.extend( obj, promise ) : promise;\n        }\n      },\n      deferred = {};\n\n    // Keep pipe for back-compat\n    promise.pipe = promise.then;\n\n    // Add list-specific methods\n    jQuery.each( tuples, function( i, tuple ) {\n      var list = tuple[ 2 ],\n        stateString = tuple[ 3 ];\n\n      // promise[ done | fail | progress ] = list.add\n      promise[ tuple[1] ] = list.add;\n\n      // Handle state\n      if ( stateString ) {\n        list.add(function() {\n          // state = [ resolved | rejected ]\n          state = stateString;\n\n        // [ reject_list | resolve_list ].disable; progress_list.lock\n        }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n      }\n\n      // deferred[ resolve | reject | notify ] = list.fire\n      deferred[ tuple[0] ] = list.fire;\n      deferred[ tuple[0] + \"With\" ] = list.fireWith;\n    });\n\n    // Make the deferred a promise\n    promise.promise( deferred );\n\n    // Call given func if any\n    if ( func ) {\n      func.call( deferred, deferred );\n    }\n\n    // All done!\n    return deferred;\n  },\n\n  // Deferred helper\n  when: function( subordinate /* , ..., subordinateN */ ) {\n    var i = 0,\n      resolveValues = core_slice.call( arguments ),\n      length = resolveValues.length,\n\n      // the count of uncompleted subordinates\n      remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n      // the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n      deferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n      // Update function for both resolve and progress values\n      updateFunc = function( i, contexts, values ) {\n        return function( value ) {\n          contexts[ i ] = this;\n          values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;\n          if( values === progressValues ) {\n            deferred.notifyWith( contexts, values );\n          } else if ( !( --remaining ) ) {\n            deferred.resolveWith( contexts, values );\n          }\n        };\n      },\n\n      progressValues, progressContexts, resolveContexts;\n\n    // add listeners to Deferred subordinates; treat others as resolved\n    if ( length > 1 ) {\n      progressValues = new Array( length );\n      progressContexts = new Array( length );\n      resolveContexts = new Array( length );\n      for ( ; i < length; i++ ) {\n        if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n          resolveValues[ i ].promise()\n            .done( updateFunc( i, resolveContexts, resolveValues ) )\n            .fail( deferred.reject )\n            .progress( updateFunc( i, progressContexts, progressValues ) );\n        } else {\n          --remaining;\n        }\n      }\n    }\n\n    // if we're not waiting on anything, resolve the master\n    if ( !remaining ) {\n      deferred.resolveWith( resolveContexts, resolveValues );\n    }\n\n    return deferred.promise();\n  }\n});\njQuery.support = (function() {\n\n  var support,\n    all,\n    a,\n    select,\n    opt,\n    input,\n    fragment,\n    eventName,\n    i,\n    isSupported,\n    clickFn,\n    div = document.createElement(\"div\");\n\n  // Setup\n  div.setAttribute( \"className\", \"t\" );\n  div.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n  // Support tests won't run in some limited or non-browser environments\n  all = div.getElementsByTagName(\"*\");\n  a = div.getElementsByTagName(\"a\")[ 0 ];\n  if ( !all || !a || !all.length ) {\n    return {};\n  }\n\n  // First batch of tests\n  select = document.createElement(\"select\");\n  opt = select.appendChild( document.createElement(\"option\") );\n  input = div.getElementsByTagName(\"input\")[ 0 ];\n\n  a.style.cssText = \"top:1px;float:left;opacity:.5\";\n  support = {\n    // IE strips leading whitespace when .innerHTML is used\n    leadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n    // Make sure that tbody elements aren't automatically inserted\n    // IE will insert them into empty tables\n    tbody: !div.getElementsByTagName(\"tbody\").length,\n\n    // Make sure that link elements get serialized correctly by innerHTML\n    // This requires a wrapper element in IE\n    htmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n    // Get the style information from getAttribute\n    // (IE uses .cssText instead)\n    style: /top/.test( a.getAttribute(\"style\") ),\n\n    // Make sure that URLs aren't manipulated\n    // (IE normalizes it by default)\n    hrefNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n    // Make sure that element opacity exists\n    // (IE uses filter instead)\n    // Use a regex to work around a WebKit issue. See #5145\n    opacity: /^0.5/.test( a.style.opacity ),\n\n    // Verify style float existence\n    // (IE uses styleFloat instead of cssFloat)\n    cssFloat: !!a.style.cssFloat,\n\n    // Make sure that if no value is specified for a checkbox\n    // that it defaults to \"on\".\n    // (WebKit defaults to \"\" instead)\n    checkOn: ( input.value === \"on\" ),\n\n    // Make sure that a selected-by-default option has a working selected property.\n    // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n    optSelected: opt.selected,\n\n    // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n    getSetAttribute: div.className !== \"t\",\n\n    // Tests for enctype support on a form (#6743)\n    enctype: !!document.createElement(\"form\").enctype,\n\n    // Makes sure cloning an html5 element does not cause problems\n    // Where outerHTML is undefined, this still works\n    html5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n    // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode\n    boxModel: ( document.compatMode === \"CSS1Compat\" ),\n\n    // Will be defined later\n    submitBubbles: true,\n    changeBubbles: true,\n    focusinBubbles: false,\n    deleteExpando: true,\n    noCloneEvent: true,\n    inlineBlockNeedsLayout: false,\n    shrinkWrapBlocks: false,\n    reliableMarginRight: true,\n    boxSizingReliable: true,\n    pixelPosition: false\n  };\n\n  // Make sure checked status is properly cloned\n  input.checked = true;\n  support.noCloneChecked = input.cloneNode( true ).checked;\n\n  // Make sure that the options inside disabled selects aren't marked as disabled\n  // (WebKit marks them as disabled)\n  select.disabled = true;\n  support.optDisabled = !opt.disabled;\n\n  // Test to see if it's possible to delete an expando from an element\n  // Fails in Internet Explorer\n  try {\n    delete div.test;\n  } catch( e ) {\n    support.deleteExpando = false;\n  }\n\n  if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n    div.attachEvent( \"onclick\", clickFn = function() {\n      // Cloning a node shouldn't copy over any\n      // bound event handlers (IE does this)\n      support.noCloneEvent = false;\n    });\n    div.cloneNode( true ).fireEvent(\"onclick\");\n    div.detachEvent( \"onclick\", clickFn );\n  }\n\n  // Check if a radio maintains its value\n  // after being appended to the DOM\n  input = document.createElement(\"input\");\n  input.value = \"t\";\n  input.setAttribute( \"type\", \"radio\" );\n  support.radioValue = input.value === \"t\";\n\n  input.setAttribute( \"checked\", \"checked\" );\n\n  // #11217 - WebKit loses check when the name is after the checked attribute\n  input.setAttribute( \"name\", \"t\" );\n\n  div.appendChild( input );\n  fragment = document.createDocumentFragment();\n  fragment.appendChild( div.lastChild );\n\n  // WebKit doesn't clone checked state correctly in fragments\n  support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n  // Check if a disconnected checkbox will retain its checked\n  // value of true after appended to the DOM (IE6/7)\n  support.appendChecked = input.checked;\n\n  fragment.removeChild( input );\n  fragment.appendChild( div );\n\n  // Technique from Juriy Zaytsev\n  // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n  // We only care about the case where non-standard event systems\n  // are used, namely in IE. Short-circuiting here helps us to\n  // avoid an eval call (in setAttribute) which can cause CSP\n  // to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n  if ( div.attachEvent ) {\n    for ( i in {\n      submit: true,\n      change: true,\n      focusin: true\n    }) {\n      eventName = \"on\" + i;\n      isSupported = ( eventName in div );\n      if ( !isSupported ) {\n        div.setAttribute( eventName, \"return;\" );\n        isSupported = ( typeof div[ eventName ] === \"function\" );\n      }\n      support[ i + \"Bubbles\" ] = isSupported;\n    }\n  }\n\n  // Run tests that need a body at doc ready\n  jQuery(function() {\n    var container, div, tds, marginDiv,\n      divReset = \"padding:0;margin:0;border:0;display:block;overflow:hidden;\",\n      body = document.getElementsByTagName(\"body\")[0];\n\n    if ( !body ) {\n      // Return for frameset docs that don't have a body\n      return;\n    }\n\n    container = document.createElement(\"div\");\n    container.style.cssText = \"visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px\";\n    body.insertBefore( container, body.firstChild );\n\n    // Construct the test element\n    div = document.createElement(\"div\");\n    container.appendChild( div );\n\n    // Check if table cells still have offsetWidth/Height when they are set\n    // to display:none and there are still other visible table cells in a\n    // table row; if so, offsetWidth/Height are not reliable for use when\n    // determining if an element has been hidden directly using\n    // display:none (it is still safe to use offsets if a parent element is\n    // hidden; don safety goggles and see bug #4512 for more information).\n    // (only IE 8 fails this test)\n    div.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n    tds = div.getElementsByTagName(\"td\");\n    tds[ 0 ].style.cssText = \"padding:0;margin:0;border:0;display:none\";\n    isSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n    tds[ 0 ].style.display = \"\";\n    tds[ 1 ].style.display = \"none\";\n\n    // Check if empty table cells still have offsetWidth/Height\n    // (IE <= 8 fail this test)\n    support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n    // Check box-sizing and margin behavior\n    div.innerHTML = \"\";\n    div.style.cssText = \"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\";\n    support.boxSizing = ( div.offsetWidth === 4 );\n    support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );\n\n    // NOTE: To any future maintainer, we've window.getComputedStyle\n    // because jsdom on node.js will break without it.\n    if ( window.getComputedStyle ) {\n      support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n      support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\n      // Check if div with explicit width and no margin-right incorrectly\n      // gets computed margin-right based on width of container. For more\n      // info see bug #3333\n      // Fails in WebKit before Feb 2011 nightlies\n      // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n      marginDiv = document.createElement(\"div\");\n      marginDiv.style.cssText = div.style.cssText = divReset;\n      marginDiv.style.marginRight = marginDiv.style.width = \"0\";\n      div.style.width = \"1px\";\n      div.appendChild( marginDiv );\n      support.reliableMarginRight =\n        !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );\n    }\n\n    if ( typeof div.style.zoom !== \"undefined\" ) {\n      // Check if natively block-level elements act like inline-block\n      // elements when setting their display to 'inline' and giving\n      // them layout\n      // (IE < 8 does this)\n      div.innerHTML = \"\";\n      div.style.cssText = divReset + \"width:1px;padding:1px;display:inline;zoom:1\";\n      support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n      // Check if elements with layout shrink-wrap their children\n      // (IE 6 does this)\n      div.style.display = \"block\";\n      div.style.overflow = \"visible\";\n      div.innerHTML = \"<div></div>\";\n      div.firstChild.style.width = \"5px\";\n      support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\n      container.style.zoom = 1;\n    }\n\n    // Null elements to avoid leaks in IE\n    body.removeChild( container );\n    container = div = tds = marginDiv = null;\n  });\n\n  // Null elements to avoid leaks in IE\n  fragment.removeChild( div );\n  all = a = select = opt = input = fragment = div = null;\n\n  return support;\n})();\nvar rbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n  rmultiDash = /([A-Z])/g;\n\njQuery.extend({\n  cache: {},\n\n  deletedIds: [],\n\n  // Remove at next major release (1.9/2.0)\n  uuid: 0,\n\n  // Unique for each copy of jQuery on the page\n  // Non-digits removed to match rinlinejQuery\n  expando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n  // The following elements throw uncatchable exceptions if you\n  // attempt to add expando properties to them.\n  noData: {\n    \"embed\": true,\n    // Ban all objects except for Flash (which handle expandos)\n    \"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n    \"applet\": true\n  },\n\n  hasData: function( elem ) {\n    elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n    return !!elem && !isEmptyDataObject( elem );\n  },\n\n  data: function( elem, name, data, pvt /* Internal Use Only */ ) {\n    if ( !jQuery.acceptData( elem ) ) {\n      return;\n    }\n\n    var thisCache, ret,\n      internalKey = jQuery.expando,\n      getByName = typeof name === \"string\",\n\n      // We have to handle DOM nodes and JS objects differently because IE6-7\n      // can't GC object references properly across the DOM-JS boundary\n      isNode = elem.nodeType,\n\n      // Only DOM nodes need the global jQuery cache; JS object data is\n      // attached directly to the object so GC can occur automatically\n      cache = isNode ? jQuery.cache : elem,\n\n      // Only defining an ID for JS objects if its cache already exists allows\n      // the code to shortcut on the same path as a DOM node with no cache\n      id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n    // Avoid doing any more work than we need to when trying to get data on an\n    // object that has no data at all\n    if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {\n      return;\n    }\n\n    if ( !id ) {\n      // Only DOM nodes need a new unique ID for each element since their data\n      // ends up in the global cache\n      if ( isNode ) {\n        elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;\n      } else {\n        id = internalKey;\n      }\n    }\n\n    if ( !cache[ id ] ) {\n      cache[ id ] = {};\n\n      // Avoids exposing jQuery metadata on plain JS objects when the object\n      // is serialized using JSON.stringify\n      if ( !isNode ) {\n        cache[ id ].toJSON = jQuery.noop;\n      }\n    }\n\n    // An object can be passed to jQuery.data instead of a key/value pair; this gets\n    // shallow copied over onto the existing cache\n    if ( typeof name === \"object\" || typeof name === \"function\" ) {\n      if ( pvt ) {\n        cache[ id ] = jQuery.extend( cache[ id ], name );\n      } else {\n        cache[ id ].data = jQuery.extend( cache[ id ].data, name );\n      }\n    }\n\n    thisCache = cache[ id ];\n\n    // jQuery data() is stored in a separate object inside the object's internal data\n    // cache in order to avoid key collisions between internal data and user-defined\n    // data.\n    if ( !pvt ) {\n      if ( !thisCache.data ) {\n        thisCache.data = {};\n      }\n\n      thisCache = thisCache.data;\n    }\n\n    if ( data !== undefined ) {\n      thisCache[ jQuery.camelCase( name ) ] = data;\n    }\n\n    // Check for both converted-to-camel and non-converted data property names\n    // If a data property was specified\n    if ( getByName ) {\n\n      // First Try to find as-is property data\n      ret = thisCache[ name ];\n\n      // Test for null|undefined property data\n      if ( ret == null ) {\n\n        // Try to find the camelCased property\n        ret = thisCache[ jQuery.camelCase( name ) ];\n      }\n    } else {\n      ret = thisCache;\n    }\n\n    return ret;\n  },\n\n  removeData: function( elem, name, pvt /* Internal Use Only */ ) {\n    if ( !jQuery.acceptData( elem ) ) {\n      return;\n    }\n\n    var thisCache, i, l,\n\n      isNode = elem.nodeType,\n\n      // See jQuery.data for more information\n      cache = isNode ? jQuery.cache : elem,\n      id = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n    // If there is already no cache entry for this object, there is no\n    // purpose in continuing\n    if ( !cache[ id ] ) {\n      return;\n    }\n\n    if ( name ) {\n\n      thisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n      if ( thisCache ) {\n\n        // Support array or space separated string names for data keys\n        if ( !jQuery.isArray( name ) ) {\n\n          // try the string as a key before any manipulation\n          if ( name in thisCache ) {\n            name = [ name ];\n          } else {\n\n            // split the camel cased version by spaces unless a key with the spaces exists\n            name = jQuery.camelCase( name );\n            if ( name in thisCache ) {\n              name = [ name ];\n            } else {\n              name = name.split(\" \");\n            }\n          }\n        }\n\n        for ( i = 0, l = name.length; i < l; i++ ) {\n          delete thisCache[ name[i] ];\n        }\n\n        // If there is no data left in the cache, we want to continue\n        // and let the cache object itself get destroyed\n        if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n          return;\n        }\n      }\n    }\n\n    // See jQuery.data for more information\n    if ( !pvt ) {\n      delete cache[ id ].data;\n\n      // Don't destroy the parent cache unless the internal data object\n      // had been the only thing left in it\n      if ( !isEmptyDataObject( cache[ id ] ) ) {\n        return;\n      }\n    }\n\n    // Destroy the cache\n    if ( isNode ) {\n      jQuery.cleanData( [ elem ], true );\n\n    // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n    } else if ( jQuery.support.deleteExpando || cache != cache.window ) {\n      delete cache[ id ];\n\n    // When all else fails, null\n    } else {\n      cache[ id ] = null;\n    }\n  },\n\n  // For internal use only.\n  _data: function( elem, name, data ) {\n    return jQuery.data( elem, name, data, true );\n  },\n\n  // A method for determining if a DOM node can handle the data expando\n  acceptData: function( elem ) {\n    var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n    // nodes accept data unless otherwise specified; rejection can be conditional\n    return !noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n  }\n});\n\njQuery.fn.extend({\n  data: function( key, value ) {\n    var parts, part, attr, name, l,\n      elem = this[0],\n      i = 0,\n      data = null;\n\n    // Gets all values\n    if ( key === undefined ) {\n      if ( this.length ) {\n        data = jQuery.data( elem );\n\n        if ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n          attr = elem.attributes;\n          for ( l = attr.length; i < l; i++ ) {\n            name = attr[i].name;\n\n            if ( !name.indexOf( \"data-\" ) ) {\n              name = jQuery.camelCase( name.substring(5) );\n\n              dataAttr( elem, name, data[ name ] );\n            }\n          }\n          jQuery._data( elem, \"parsedAttrs\", true );\n        }\n      }\n\n      return data;\n    }\n\n    // Sets multiple values\n    if ( typeof key === \"object\" ) {\n      return this.each(function() {\n        jQuery.data( this, key );\n      });\n    }\n\n    parts = key.split( \".\", 2 );\n    parts[1] = parts[1] ? \".\" + parts[1] : \"\";\n    part = parts[1] + \"!\";\n\n    return jQuery.access( this, function( value ) {\n\n      if ( value === undefined ) {\n        data = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n        // Try to fetch any internally stored data first\n        if ( data === undefined && elem ) {\n          data = jQuery.data( elem, key );\n          data = dataAttr( elem, key, data );\n        }\n\n        return data === undefined && parts[1] ?\n          this.data( parts[0] ) :\n          data;\n      }\n\n      parts[1] = value;\n      this.each(function() {\n        var self = jQuery( this );\n\n        self.triggerHandler( \"setData\" + part, parts );\n        jQuery.data( this, key, value );\n        self.triggerHandler( \"changeData\" + part, parts );\n      });\n    }, null, value, arguments.length > 1, null, false );\n  },\n\n  removeData: function( key ) {\n    return this.each(function() {\n      jQuery.removeData( this, key );\n    });\n  }\n});\n\nfunction dataAttr( elem, key, data ) {\n  // If nothing was found internally, try to fetch any\n  // data from the HTML5 data-* attribute\n  if ( data === undefined && elem.nodeType === 1 ) {\n\n    var name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n    data = elem.getAttribute( name );\n\n    if ( typeof data === \"string\" ) {\n      try {\n        data = data === \"true\" ? true :\n        data === \"false\" ? false :\n        data === \"null\" ? null :\n        // Only convert to a number if it doesn't change the string\n        +data + \"\" === data ? +data :\n        rbrace.test( data ) ? jQuery.parseJSON( data ) :\n          data;\n      } catch( e ) {}\n\n      // Make sure we set the data so it isn't changed later\n      jQuery.data( elem, key, data );\n\n    } else {\n      data = undefined;\n    }\n  }\n\n  return data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n  var name;\n  for ( name in obj ) {\n\n    // if the public data object is empty, the private is still empty\n    if ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n      continue;\n    }\n    if ( name !== \"toJSON\" ) {\n      return false;\n    }\n  }\n\n  return true;\n}\njQuery.extend({\n  queue: function( elem, type, data ) {\n    var queue;\n\n    if ( elem ) {\n      type = ( type || \"fx\" ) + \"queue\";\n      queue = jQuery._data( elem, type );\n\n      // Speed up dequeue by getting out quickly if this is just a lookup\n      if ( data ) {\n        if ( !queue || jQuery.isArray(data) ) {\n          queue = jQuery._data( elem, type, jQuery.makeArray(data) );\n        } else {\n          queue.push( data );\n        }\n      }\n      return queue || [];\n    }\n  },\n\n  dequeue: function( elem, type ) {\n    type = type || \"fx\";\n\n    var queue = jQuery.queue( elem, type ),\n      startLength = queue.length,\n      fn = queue.shift(),\n      hooks = jQuery._queueHooks( elem, type ),\n      next = function() {\n        jQuery.dequeue( elem, type );\n      };\n\n    // If the fx queue is dequeued, always remove the progress sentinel\n    if ( fn === \"inprogress\" ) {\n      fn = queue.shift();\n      startLength--;\n    }\n\n    if ( fn ) {\n\n      // Add a progress sentinel to prevent the fx queue from being\n      // automatically dequeued\n      if ( type === \"fx\" ) {\n        queue.unshift( \"inprogress\" );\n      }\n\n      // clear up the last queue stop function\n      delete hooks.stop;\n      fn.call( elem, next, hooks );\n    }\n\n    if ( !startLength && hooks ) {\n      hooks.empty.fire();\n    }\n  },\n\n  // not intended for public consumption - generates a queueHooks object, or returns the current one\n  _queueHooks: function( elem, type ) {\n    var key = type + \"queueHooks\";\n    return jQuery._data( elem, key ) || jQuery._data( elem, key, {\n      empty: jQuery.Callbacks(\"once memory\").add(function() {\n        jQuery.removeData( elem, type + \"queue\", true );\n        jQuery.removeData( elem, key, true );\n      })\n    });\n  }\n});\n\njQuery.fn.extend({\n  queue: function( type, data ) {\n    var setter = 2;\n\n    if ( typeof type !== \"string\" ) {\n      data = type;\n      type = \"fx\";\n      setter--;\n    }\n\n    if ( arguments.length < setter ) {\n      return jQuery.queue( this[0], type );\n    }\n\n    return data === undefined ?\n      this :\n      this.each(function() {\n        var queue = jQuery.queue( this, type, data );\n\n        // ensure a hooks for this queue\n        jQuery._queueHooks( this, type );\n\n        if ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n          jQuery.dequeue( this, type );\n        }\n      });\n  },\n  dequeue: function( type ) {\n    return this.each(function() {\n      jQuery.dequeue( this, type );\n    });\n  },\n  // Based off of the plugin by Clint Helfers, with permission.\n  // http://blindsignals.com/index.php/2009/07/jquery-delay/\n  delay: function( time, type ) {\n    time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n    type = type || \"fx\";\n\n    return this.queue( type, function( next, hooks ) {\n      var timeout = setTimeout( next, time );\n      hooks.stop = function() {\n        clearTimeout( timeout );\n      };\n    });\n  },\n  clearQueue: function( type ) {\n    return this.queue( type || \"fx\", [] );\n  },\n  // Get a promise resolved when queues of a certain type\n  // are emptied (fx is the type by default)\n  promise: function( type, obj ) {\n    var tmp,\n      count = 1,\n      defer = jQuery.Deferred(),\n      elements = this,\n      i = this.length,\n      resolve = function() {\n        if ( !( --count ) ) {\n          defer.resolveWith( elements, [ elements ] );\n        }\n      };\n\n    if ( typeof type !== \"string\" ) {\n      obj = type;\n      type = undefined;\n    }\n    type = type || \"fx\";\n\n    while( i-- ) {\n      tmp = jQuery._data( elements[ i ], type + \"queueHooks\" );\n      if ( tmp && tmp.empty ) {\n        count++;\n        tmp.empty.add( resolve );\n      }\n    }\n    resolve();\n    return defer.promise( obj );\n  }\n});\nvar nodeHook, boolHook, fixSpecified,\n  rclass = /[\\t\\r\\n]/g,\n  rreturn = /\\r/g,\n  rtype = /^(?:button|input)$/i,\n  rfocusable = /^(?:button|input|object|select|textarea)$/i,\n  rclickable = /^a(?:rea|)$/i,\n  rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n  getSetAttribute = jQuery.support.getSetAttribute;\n\njQuery.fn.extend({\n  attr: function( name, value ) {\n    return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n  },\n\n  removeAttr: function( name ) {\n    return this.each(function() {\n      jQuery.removeAttr( this, name );\n    });\n  },\n\n  prop: function( name, value ) {\n    return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n  },\n\n  removeProp: function( name ) {\n    name = jQuery.propFix[ name ] || name;\n    return this.each(function() {\n      // try/catch handles cases where IE balks (such as removing a property on window)\n      try {\n        this[ name ] = undefined;\n        delete this[ name ];\n      } catch( e ) {}\n    });\n  },\n\n  addClass: function( value ) {\n    var classNames, i, l, elem,\n      setClass, c, cl;\n\n    if ( jQuery.isFunction( value ) ) {\n      return this.each(function( j ) {\n        jQuery( this ).addClass( value.call(this, j, this.className) );\n      });\n    }\n\n    if ( value && typeof value === \"string\" ) {\n      classNames = value.split( core_rspace );\n\n      for ( i = 0, l = this.length; i < l; i++ ) {\n        elem = this[ i ];\n\n        if ( elem.nodeType === 1 ) {\n          if ( !elem.className && classNames.length === 1 ) {\n            elem.className = value;\n\n          } else {\n            setClass = \" \" + elem.className + \" \";\n\n            for ( c = 0, cl = classNames.length; c < cl; c++ ) {\n              if ( setClass.indexOf( \" \" + classNames[ c ] + \" \" ) < 0 ) {\n                setClass += classNames[ c ] + \" \";\n              }\n            }\n            elem.className = jQuery.trim( setClass );\n          }\n        }\n      }\n    }\n\n    return this;\n  },\n\n  removeClass: function( value ) {\n    var removes, className, elem, c, cl, i, l;\n\n    if ( jQuery.isFunction( value ) ) {\n      return this.each(function( j ) {\n        jQuery( this ).removeClass( value.call(this, j, this.className) );\n      });\n    }\n    if ( (value && typeof value === \"string\") || value === undefined ) {\n      removes = ( value || \"\" ).split( core_rspace );\n\n      for ( i = 0, l = this.length; i < l; i++ ) {\n        elem = this[ i ];\n        if ( elem.nodeType === 1 && elem.className ) {\n\n          className = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\n          // loop over each item in the removal list\n          for ( c = 0, cl = removes.length; c < cl; c++ ) {\n            // Remove until there is nothing to remove,\n            while ( className.indexOf(\" \" + removes[ c ] + \" \") >= 0 ) {\n              className = className.replace( \" \" + removes[ c ] + \" \" , \" \" );\n            }\n          }\n          elem.className = value ? jQuery.trim( className ) : \"\";\n        }\n      }\n    }\n\n    return this;\n  },\n\n  toggleClass: function( value, stateVal ) {\n    var type = typeof value,\n      isBool = typeof stateVal === \"boolean\";\n\n    if ( jQuery.isFunction( value ) ) {\n      return this.each(function( i ) {\n        jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n      });\n    }\n\n    return this.each(function() {\n      if ( type === \"string\" ) {\n        // toggle individual class names\n        var className,\n          i = 0,\n          self = jQuery( this ),\n          state = stateVal,\n          classNames = value.split( core_rspace );\n\n        while ( (className = classNames[ i++ ]) ) {\n          // check each className given, space separated list\n          state = isBool ? state : !self.hasClass( className );\n          self[ state ? \"addClass\" : \"removeClass\" ]( className );\n        }\n\n      } else if ( type === \"undefined\" || type === \"boolean\" ) {\n        if ( this.className ) {\n          // store className if set\n          jQuery._data( this, \"__className__\", this.className );\n        }\n\n        // toggle whole className\n        this.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n      }\n    });\n  },\n\n  hasClass: function( selector ) {\n    var className = \" \" + selector + \" \",\n      i = 0,\n      l = this.length;\n    for ( ; i < l; i++ ) {\n      if ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n        return true;\n      }\n    }\n\n    return false;\n  },\n\n  val: function( value ) {\n    var hooks, ret, isFunction,\n      elem = this[0];\n\n    if ( !arguments.length ) {\n      if ( elem ) {\n        hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n        if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n          return ret;\n        }\n\n        ret = elem.value;\n\n        return typeof ret === \"string\" ?\n          // handle most common string cases\n          ret.replace(rreturn, \"\") :\n          // handle cases where value is null/undef or number\n          ret == null ? \"\" : ret;\n      }\n\n      return;\n    }\n\n    isFunction = jQuery.isFunction( value );\n\n    return this.each(function( i ) {\n      var val,\n        self = jQuery(this);\n\n      if ( this.nodeType !== 1 ) {\n        return;\n      }\n\n      if ( isFunction ) {\n        val = value.call( this, i, self.val() );\n      } else {\n        val = value;\n      }\n\n      // Treat null/undefined as \"\"; convert numbers to string\n      if ( val == null ) {\n        val = \"\";\n      } else if ( typeof val === \"number\" ) {\n        val += \"\";\n      } else if ( jQuery.isArray( val ) ) {\n        val = jQuery.map(val, function ( value ) {\n          return value == null ? \"\" : value + \"\";\n        });\n      }\n\n      hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n      // If set returns undefined, fall back to normal setting\n      if ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n        this.value = val;\n      }\n    });\n  }\n});\n\njQuery.extend({\n  valHooks: {\n    option: {\n      get: function( elem ) {\n        // attributes.value is undefined in Blackberry 4.7 but\n        // uses .value. See #6932\n        var val = elem.attributes.value;\n        return !val || val.specified ? elem.value : elem.text;\n      }\n    },\n    select: {\n      get: function( elem ) {\n        var value, option,\n          options = elem.options,\n          index = elem.selectedIndex,\n          one = elem.type === \"select-one\" || index < 0,\n          values = one ? null : [],\n          max = one ? index + 1 : options.length,\n          i = index < 0 ?\n            max :\n            one ? index : 0;\n\n        // Loop through all the selected options\n        for ( ; i < max; i++ ) {\n          option = options[ i ];\n\n          // oldIE doesn't update selected after form reset (#2551)\n          if ( ( option.selected || i === index ) &&\n              // Don't return options that are disabled or in a disabled optgroup\n              ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null ) &&\n              ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n            // Get the specific value for the option\n            value = jQuery( option ).val();\n\n            // We don't need an array for one selects\n            if ( one ) {\n              return value;\n            }\n\n            // Multi-Selects return an array\n            values.push( value );\n          }\n        }\n\n        return values;\n      },\n\n      set: function( elem, value ) {\n        var values = jQuery.makeArray( value );\n\n        jQuery(elem).find(\"option\").each(function() {\n          this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n        });\n\n        if ( !values.length ) {\n          elem.selectedIndex = -1;\n        }\n        return values;\n      }\n    }\n  },\n\n  // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9\n  attrFn: {},\n\n  attr: function( elem, name, value, pass ) {\n    var ret, hooks, notxml,\n      nType = elem.nodeType;\n\n    // don't get/set attributes on text, comment and attribute nodes\n    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n      return;\n    }\n\n    if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {\n      return jQuery( elem )[ name ]( value );\n    }\n\n    // Fallback to prop when attributes are not supported\n    if ( typeof elem.getAttribute === \"undefined\" ) {\n      return jQuery.prop( elem, name, value );\n    }\n\n    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n    // All attributes are lowercase\n    // Grab necessary hook if one is defined\n    if ( notxml ) {\n      name = name.toLowerCase();\n      hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n    }\n\n    if ( value !== undefined ) {\n\n      if ( value === null ) {\n        jQuery.removeAttr( elem, name );\n        return;\n\n      } else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n        return ret;\n\n      } else {\n        elem.setAttribute( name, value + \"\" );\n        return value;\n      }\n\n    } else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n      return ret;\n\n    } else {\n\n      ret = elem.getAttribute( name );\n\n      // Non-existent attributes return null, we normalize to undefined\n      return ret === null ?\n        undefined :\n        ret;\n    }\n  },\n\n  removeAttr: function( elem, value ) {\n    var propName, attrNames, name, isBool,\n      i = 0;\n\n    if ( value && elem.nodeType === 1 ) {\n\n      attrNames = value.split( core_rspace );\n\n      for ( ; i < attrNames.length; i++ ) {\n        name = attrNames[ i ];\n\n        if ( name ) {\n          propName = jQuery.propFix[ name ] || name;\n          isBool = rboolean.test( name );\n\n          // See #9699 for explanation of this approach (setting first, then removal)\n          // Do not do this for boolean attributes (see #10870)\n          if ( !isBool ) {\n            jQuery.attr( elem, name, \"\" );\n          }\n          elem.removeAttribute( getSetAttribute ? name : propName );\n\n          // Set corresponding property to false for boolean attributes\n          if ( isBool && propName in elem ) {\n            elem[ propName ] = false;\n          }\n        }\n      }\n    }\n  },\n\n  attrHooks: {\n    type: {\n      set: function( elem, value ) {\n        // We can't allow the type property to be changed (since it causes problems in IE)\n        if ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n          jQuery.error( \"type property can't be changed\" );\n        } else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n          // Setting the type on a radio button after the value resets the value in IE6-9\n          // Reset value to it's default in case type is set after value\n          // This is for element creation\n          var val = elem.value;\n          elem.setAttribute( \"type\", value );\n          if ( val ) {\n            elem.value = val;\n          }\n          return value;\n        }\n      }\n    },\n    // Use the value property for back compat\n    // Use the nodeHook for button elements in IE6/7 (#1954)\n    value: {\n      get: function( elem, name ) {\n        if ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n          return nodeHook.get( elem, name );\n        }\n        return name in elem ?\n          elem.value :\n          null;\n      },\n      set: function( elem, value, name ) {\n        if ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n          return nodeHook.set( elem, value, name );\n        }\n        // Does not return so that setAttribute is also used\n        elem.value = value;\n      }\n    }\n  },\n\n  propFix: {\n    tabindex: \"tabIndex\",\n    readonly: \"readOnly\",\n    \"for\": \"htmlFor\",\n    \"class\": \"className\",\n    maxlength: \"maxLength\",\n    cellspacing: \"cellSpacing\",\n    cellpadding: \"cellPadding\",\n    rowspan: \"rowSpan\",\n    colspan: \"colSpan\",\n    usemap: \"useMap\",\n    frameborder: \"frameBorder\",\n    contenteditable: \"contentEditable\"\n  },\n\n  prop: function( elem, name, value ) {\n    var ret, hooks, notxml,\n      nType = elem.nodeType;\n\n    // don't get/set properties on text, comment and attribute nodes\n    if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n      return;\n    }\n\n    notxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n    if ( notxml ) {\n      // Fix name and attach hooks\n      name = jQuery.propFix[ name ] || name;\n      hooks = jQuery.propHooks[ name ];\n    }\n\n    if ( value !== undefined ) {\n      if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n        return ret;\n\n      } else {\n        return ( elem[ name ] = value );\n      }\n\n    } else {\n      if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n        return ret;\n\n      } else {\n        return elem[ name ];\n      }\n    }\n  },\n\n  propHooks: {\n    tabIndex: {\n      get: function( elem ) {\n        // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n        // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n        var attributeNode = elem.getAttributeNode(\"tabindex\");\n\n        return attributeNode && attributeNode.specified ?\n          parseInt( attributeNode.value, 10 ) :\n          rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n            0 :\n            undefined;\n      }\n    }\n  }\n});\n\n// Hook for boolean attributes\nboolHook = {\n  get: function( elem, name ) {\n    // Align boolean attributes with corresponding properties\n    // Fall back to attribute presence where some booleans are not supported\n    var attrNode,\n      property = jQuery.prop( elem, name );\n    return property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n      name.toLowerCase() :\n      undefined;\n  },\n  set: function( elem, value, name ) {\n    var propName;\n    if ( value === false ) {\n      // Remove boolean attributes when set to false\n      jQuery.removeAttr( elem, name );\n    } else {\n      // value is true since we know at this point it's type boolean and not false\n      // Set boolean attributes to the same name and set the DOM property\n      propName = jQuery.propFix[ name ] || name;\n      if ( propName in elem ) {\n        // Only set the IDL specifically if it already exists on the element\n        elem[ propName ] = true;\n      }\n\n      elem.setAttribute( name, name.toLowerCase() );\n    }\n    return name;\n  }\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n  fixSpecified = {\n    name: true,\n    id: true,\n    coords: true\n  };\n\n  // Use this for any attribute in IE6/7\n  // This fixes almost every IE6/7 issue\n  nodeHook = jQuery.valHooks.button = {\n    get: function( elem, name ) {\n      var ret;\n      ret = elem.getAttributeNode( name );\n      return ret && ( fixSpecified[ name ] ? ret.value !== \"\" : ret.specified ) ?\n        ret.value :\n        undefined;\n    },\n    set: function( elem, value, name ) {\n      // Set the existing or create a new attribute node\n      var ret = elem.getAttributeNode( name );\n      if ( !ret ) {\n        ret = document.createAttribute( name );\n        elem.setAttributeNode( ret );\n      }\n      return ( ret.value = value + \"\" );\n    }\n  };\n\n  // Set width and height to auto instead of 0 on empty string( Bug #8150 )\n  // This is for removals\n  jQuery.each([ \"width\", \"height\" ], function( i, name ) {\n    jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n      set: function( elem, value ) {\n        if ( value === \"\" ) {\n          elem.setAttribute( name, \"auto\" );\n          return value;\n        }\n      }\n    });\n  });\n\n  // Set contenteditable to false on removals(#10429)\n  // Setting to empty string throws an error as an invalid value\n  jQuery.attrHooks.contenteditable = {\n    get: nodeHook.get,\n    set: function( elem, value, name ) {\n      if ( value === \"\" ) {\n        value = \"false\";\n      }\n      nodeHook.set( elem, value, name );\n    }\n  };\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n  jQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n    jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n      get: function( elem ) {\n        var ret = elem.getAttribute( name, 2 );\n        return ret === null ? undefined : ret;\n      }\n    });\n  });\n}\n\nif ( !jQuery.support.style ) {\n  jQuery.attrHooks.style = {\n    get: function( elem ) {\n      // Return undefined in the case of empty string\n      // Normalize to lowercase since IE uppercases css property names\n      return elem.style.cssText.toLowerCase() || undefined;\n    },\n    set: function( elem, value ) {\n      return ( elem.style.cssText = value + \"\" );\n    }\n  };\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n  jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n    get: function( elem ) {\n      var parent = elem.parentNode;\n\n      if ( parent ) {\n        parent.selectedIndex;\n\n        // Make sure that it also works with optgroups, see #5701\n        if ( parent.parentNode ) {\n          parent.parentNode.selectedIndex;\n        }\n      }\n      return null;\n    }\n  });\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n  jQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n  jQuery.each([ \"radio\", \"checkbox\" ], function() {\n    jQuery.valHooks[ this ] = {\n      get: function( elem ) {\n        // Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n        return elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n      }\n    };\n  });\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n  jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n    set: function( elem, value ) {\n      if ( jQuery.isArray( value ) ) {\n        return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n      }\n    }\n  });\n});\nvar rformElems = /^(?:textarea|input|select)$/i,\n  rtypenamespace = /^([^\\.]*|)(?:\\.(.+)|)$/,\n  rhoverHack = /(?:^|\\s)hover(\\.\\S+|)\\b/,\n  rkeyEvent = /^key/,\n  rmouseEvent = /^(?:mouse|contextmenu)|click/,\n  rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n  hoverHack = function( events ) {\n    return jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n  };\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n  add: function( elem, types, handler, data, selector ) {\n\n    var elemData, eventHandle, events,\n      t, tns, type, namespaces, handleObj,\n      handleObjIn, handlers, special;\n\n    // Don't attach events to noData or text/comment nodes (allow plain objects tho)\n    if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n      return;\n    }\n\n    // Caller can pass in an object of custom data in lieu of the handler\n    if ( handler.handler ) {\n      handleObjIn = handler;\n      handler = handleObjIn.handler;\n      selector = handleObjIn.selector;\n    }\n\n    // Make sure that the handler has a unique ID, used to find/remove it later\n    if ( !handler.guid ) {\n      handler.guid = jQuery.guid++;\n    }\n\n    // Init the element's event structure and main handler, if this is the first\n    events = elemData.events;\n    if ( !events ) {\n      elemData.events = events = {};\n    }\n    eventHandle = elemData.handle;\n    if ( !eventHandle ) {\n      elemData.handle = eventHandle = function( e ) {\n        // Discard the second event of a jQuery.event.trigger() and\n        // when an event is called after a page has unloaded\n        return typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n          jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n          undefined;\n      };\n      // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n      eventHandle.elem = elem;\n    }\n\n    // Handle multiple events separated by a space\n    // jQuery(...).bind(\"mouseover mouseout\", fn);\n    types = jQuery.trim( hoverHack(types) ).split( \" \" );\n    for ( t = 0; t < types.length; t++ ) {\n\n      tns = rtypenamespace.exec( types[t] ) || [];\n      type = tns[1];\n      namespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n      // If event changes its type, use the special event handlers for the changed type\n      special = jQuery.event.special[ type ] || {};\n\n      // If selector defined, determine special event api type, otherwise given type\n      type = ( selector ? special.delegateType : special.bindType ) || type;\n\n      // Update special based on newly reset type\n      special = jQuery.event.special[ type ] || {};\n\n      // handleObj is passed to all event handlers\n      handleObj = jQuery.extend({\n        type: type,\n        origType: tns[1],\n        data: data,\n        handler: handler,\n        guid: handler.guid,\n        selector: selector,\n        needsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n        namespace: namespaces.join(\".\")\n      }, handleObjIn );\n\n      // Init the event handler queue if we're the first\n      handlers = events[ type ];\n      if ( !handlers ) {\n        handlers = events[ type ] = [];\n        handlers.delegateCount = 0;\n\n        // Only use addEventListener/attachEvent if the special events handler returns false\n        if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n          // Bind the global event handler to the element\n          if ( elem.addEventListener ) {\n            elem.addEventListener( type, eventHandle, false );\n\n          } else if ( elem.attachEvent ) {\n            elem.attachEvent( \"on\" + type, eventHandle );\n          }\n        }\n      }\n\n      if ( special.add ) {\n        special.add.call( elem, handleObj );\n\n        if ( !handleObj.handler.guid ) {\n          handleObj.handler.guid = handler.guid;\n        }\n      }\n\n      // Add to the element's handler list, delegates in front\n      if ( selector ) {\n        handlers.splice( handlers.delegateCount++, 0, handleObj );\n      } else {\n        handlers.push( handleObj );\n      }\n\n      // Keep track of which events have ever been used, for event optimization\n      jQuery.event.global[ type ] = true;\n    }\n\n    // Nullify elem to prevent memory leaks in IE\n    elem = null;\n  },\n\n  global: {},\n\n  // Detach an event or set of events from an element\n  remove: function( elem, types, handler, selector, mappedTypes ) {\n\n    var t, tns, type, origType, namespaces, origCount,\n      j, events, special, eventType, handleObj,\n      elemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n    if ( !elemData || !(events = elemData.events) ) {\n      return;\n    }\n\n    // Once for each type.namespace in types; type may be omitted\n    types = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n    for ( t = 0; t < types.length; t++ ) {\n      tns = rtypenamespace.exec( types[t] ) || [];\n      type = origType = tns[1];\n      namespaces = tns[2];\n\n      // Unbind all events (on this namespace, if provided) for the element\n      if ( !type ) {\n        for ( type in events ) {\n          jQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n        }\n        continue;\n      }\n\n      special = jQuery.event.special[ type ] || {};\n      type = ( selector? special.delegateType : special.bindType ) || type;\n      eventType = events[ type ] || [];\n      origCount = eventType.length;\n      namespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\") : null;\n\n      // Remove matching events\n      for ( j = 0; j < eventType.length; j++ ) {\n        handleObj = eventType[ j ];\n\n        if ( ( mappedTypes || origType === handleObj.origType ) &&\n           ( !handler || handler.guid === handleObj.guid ) &&\n           ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n           ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n          eventType.splice( j--, 1 );\n\n          if ( handleObj.selector ) {\n            eventType.delegateCount--;\n          }\n          if ( special.remove ) {\n            special.remove.call( elem, handleObj );\n          }\n        }\n      }\n\n      // Remove generic event handler if we removed something and no more handlers exist\n      // (avoids potential for endless recursion during removal of special event handlers)\n      if ( eventType.length === 0 && origCount !== eventType.length ) {\n        if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n          jQuery.removeEvent( elem, type, elemData.handle );\n        }\n\n        delete events[ type ];\n      }\n    }\n\n    // Remove the expando if it's no longer used\n    if ( jQuery.isEmptyObject( events ) ) {\n      delete elemData.handle;\n\n      // removeData also checks for emptiness and clears the expando if empty\n      // so use it instead of delete\n      jQuery.removeData( elem, \"events\", true );\n    }\n  },\n\n  // Events that are safe to short-circuit if no handlers are attached.\n  // Native DOM events should not be added, they may have inline handlers.\n  customEvent: {\n    \"getData\": true,\n    \"setData\": true,\n    \"changeData\": true\n  },\n\n  trigger: function( event, data, elem, onlyHandlers ) {\n    // Don't do events on text and comment nodes\n    if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n      return;\n    }\n\n    // Event object or event type\n    var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,\n      type = event.type || event,\n      namespaces = [];\n\n    // focus/blur morphs to focusin/out; ensure we're not firing them right now\n    if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n      return;\n    }\n\n    if ( type.indexOf( \"!\" ) >= 0 ) {\n      // Exclusive events trigger only for the exact event (no namespaces)\n      type = type.slice(0, -1);\n      exclusive = true;\n    }\n\n    if ( type.indexOf( \".\" ) >= 0 ) {\n      // Namespaced trigger; create a regexp to match event type in handle()\n      namespaces = type.split(\".\");\n      type = namespaces.shift();\n      namespaces.sort();\n    }\n\n    if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n      // No jQuery handlers for this event type, and it can't have inline handlers\n      return;\n    }\n\n    // Caller can pass in an Event, Object, or just an event type string\n    event = typeof event === \"object\" ?\n      // jQuery.Event object\n      event[ jQuery.expando ] ? event :\n      // Object literal\n      new jQuery.Event( type, event ) :\n      // Just the event type (string)\n      new jQuery.Event( type );\n\n    event.type = type;\n    event.isTrigger = true;\n    event.exclusive = exclusive;\n    event.namespace = namespaces.join( \".\" );\n    event.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\") : null;\n    ontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n    // Handle a global trigger\n    if ( !elem ) {\n\n      // TODO: Stop taunting the data cache; remove global events and always attach to document\n      cache = jQuery.cache;\n      for ( i in cache ) {\n        if ( cache[ i ].events && cache[ i ].events[ type ] ) {\n          jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n        }\n      }\n      return;\n    }\n\n    // Clean up the event in case it is being reused\n    event.result = undefined;\n    if ( !event.target ) {\n      event.target = elem;\n    }\n\n    // Clone any incoming data and prepend the event, creating the handler arg list\n    data = data != null ? jQuery.makeArray( data ) : [];\n    data.unshift( event );\n\n    // Allow special events to draw outside the lines\n    special = jQuery.event.special[ type ] || {};\n    if ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n      return;\n    }\n\n    // Determine event propagation path in advance, per W3C events spec (#9951)\n    // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n    eventPath = [[ elem, special.bindType || type ]];\n    if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n      bubbleType = special.delegateType || type;\n      cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n      for ( old = elem; cur; cur = cur.parentNode ) {\n        eventPath.push([ cur, bubbleType ]);\n        old = cur;\n      }\n\n      // Only add window if we got to document (e.g., not plain obj or detached DOM)\n      if ( old === (elem.ownerDocument || document) ) {\n        eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n      }\n    }\n\n    // Fire handlers on the event path\n    for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n      cur = eventPath[i][0];\n      event.type = eventPath[i][1];\n\n      handle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n      if ( handle ) {\n        handle.apply( cur, data );\n      }\n      // Note that this is a bare JS function and not a jQuery handler\n      handle = ontype && cur[ ontype ];\n      if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {\n        event.preventDefault();\n      }\n    }\n    event.type = type;\n\n    // If nobody prevented the default action, do it now\n    if ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n      if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n        !(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n        // Call a native DOM method on the target with the same name name as the event.\n        // Can't use an .isFunction() check here because IE6/7 fails that test.\n        // Don't do default actions on window, that's where global variables be (#6170)\n        // IE<9 dies on focus/blur to hidden element (#1486)\n        if ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n          // Don't re-trigger an onFOO event when we call its FOO() method\n          old = elem[ ontype ];\n\n          if ( old ) {\n            elem[ ontype ] = null;\n          }\n\n          // Prevent re-triggering of the same event, since we already bubbled it above\n          jQuery.event.triggered = type;\n          elem[ type ]();\n          jQuery.event.triggered = undefined;\n\n          if ( old ) {\n            elem[ ontype ] = old;\n          }\n        }\n      }\n    }\n\n    return event.result;\n  },\n\n  dispatch: function( event ) {\n\n    // Make a writable jQuery.Event from the native event object\n    event = jQuery.event.fix( event || window.event );\n\n    var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related,\n      handlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n      delegateCount = handlers.delegateCount,\n      args = core_slice.call( arguments ),\n      run_all = !event.exclusive && !event.namespace,\n      special = jQuery.event.special[ event.type ] || {},\n      handlerQueue = [];\n\n    // Use the fix-ed jQuery.Event rather than the (read-only) native event\n    args[0] = event;\n    event.delegateTarget = this;\n\n    // Call the preDispatch hook for the mapped type, and let it bail if desired\n    if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n      return;\n    }\n\n    // Determine handlers that should run if there are delegated events\n    // Avoid non-left-click bubbling in Firefox (#3861)\n    if ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n      for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n        // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)\n        if ( cur.disabled !== true || event.type !== \"click\" ) {\n          selMatch = {};\n          matches = [];\n          for ( i = 0; i < delegateCount; i++ ) {\n            handleObj = handlers[ i ];\n            sel = handleObj.selector;\n\n            if ( selMatch[ sel ] === undefined ) {\n              selMatch[ sel ] = handleObj.needsContext ?\n                jQuery( sel, this ).index( cur ) >= 0 :\n                jQuery.find( sel, this, null, [ cur ] ).length;\n            }\n            if ( selMatch[ sel ] ) {\n              matches.push( handleObj );\n            }\n          }\n          if ( matches.length ) {\n            handlerQueue.push({ elem: cur, matches: matches });\n          }\n        }\n      }\n    }\n\n    // Add the remaining (directly-bound) handlers\n    if ( handlers.length > delegateCount ) {\n      handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n    }\n\n    // Run delegates first; they may want to stop propagation beneath us\n    for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n      matched = handlerQueue[ i ];\n      event.currentTarget = matched.elem;\n\n      for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n        handleObj = matched.matches[ j ];\n\n        // Triggered event must either 1) be non-exclusive and have no namespace, or\n        // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n        if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n          event.data = handleObj.data;\n          event.handleObj = handleObj;\n\n          ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n              .apply( matched.elem, args );\n\n          if ( ret !== undefined ) {\n            event.result = ret;\n            if ( ret === false ) {\n              event.preventDefault();\n              event.stopPropagation();\n            }\n          }\n        }\n      }\n    }\n\n    // Call the postDispatch hook for the mapped type\n    if ( special.postDispatch ) {\n      special.postDispatch.call( this, event );\n    }\n\n    return event.result;\n  },\n\n  // Includes some event props shared by KeyEvent and MouseEvent\n  // *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n  props: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n  fixHooks: {},\n\n  keyHooks: {\n    props: \"char charCode key keyCode\".split(\" \"),\n    filter: function( event, original ) {\n\n      // Add which for key events\n      if ( event.which == null ) {\n        event.which = original.charCode != null ? original.charCode : original.keyCode;\n      }\n\n      return event;\n    }\n  },\n\n  mouseHooks: {\n    props: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n    filter: function( event, original ) {\n      var eventDoc, doc, body,\n        button = original.button,\n        fromElement = original.fromElement;\n\n      // Calculate pageX/Y if missing and clientX/Y available\n      if ( event.pageX == null && original.clientX != null ) {\n        eventDoc = event.target.ownerDocument || document;\n        doc = eventDoc.documentElement;\n        body = eventDoc.body;\n\n        event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n        event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n      }\n\n      // Add relatedTarget, if necessary\n      if ( !event.relatedTarget && fromElement ) {\n        event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n      }\n\n      // Add which for click: 1 === left; 2 === middle; 3 === right\n      // Note: button is not normalized, so don't use it\n      if ( !event.which && button !== undefined ) {\n        event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n      }\n\n      return event;\n    }\n  },\n\n  fix: function( event ) {\n    if ( event[ jQuery.expando ] ) {\n      return event;\n    }\n\n    // Create a writable copy of the event object and normalize some properties\n    var i, prop,\n      originalEvent = event,\n      fixHook = jQuery.event.fixHooks[ event.type ] || {},\n      copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n    event = jQuery.Event( originalEvent );\n\n    for ( i = copy.length; i; ) {\n      prop = copy[ --i ];\n      event[ prop ] = originalEvent[ prop ];\n    }\n\n    // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n    if ( !event.target ) {\n      event.target = originalEvent.srcElement || document;\n    }\n\n    // Target should not be a text node (#504, Safari)\n    if ( event.target.nodeType === 3 ) {\n      event.target = event.target.parentNode;\n    }\n\n    // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)\n    event.metaKey = !!event.metaKey;\n\n    return fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n  },\n\n  special: {\n    load: {\n      // Prevent triggered image.load events from bubbling to window.load\n      noBubble: true\n    },\n\n    focus: {\n      delegateType: \"focusin\"\n    },\n    blur: {\n      delegateType: \"focusout\"\n    },\n\n    beforeunload: {\n      setup: function( data, namespaces, eventHandle ) {\n        // We only want to do this special case on windows\n        if ( jQuery.isWindow( this ) ) {\n          this.onbeforeunload = eventHandle;\n        }\n      },\n\n      teardown: function( namespaces, eventHandle ) {\n        if ( this.onbeforeunload === eventHandle ) {\n          this.onbeforeunload = null;\n        }\n      }\n    }\n  },\n\n  simulate: function( type, elem, event, bubble ) {\n    // Piggyback on a donor event to simulate a different one.\n    // Fake originalEvent to avoid donor's stopPropagation, but if the\n    // simulated event prevents default then we do the same on the donor.\n    var e = jQuery.extend(\n      new jQuery.Event(),\n      event,\n      { type: type,\n        isSimulated: true,\n        originalEvent: {}\n      }\n    );\n    if ( bubble ) {\n      jQuery.event.trigger( e, null, elem );\n    } else {\n      jQuery.event.dispatch.call( elem, e );\n    }\n    if ( e.isDefaultPrevented() ) {\n      event.preventDefault();\n    }\n  }\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n  function( elem, type, handle ) {\n    if ( elem.removeEventListener ) {\n      elem.removeEventListener( type, handle, false );\n    }\n  } :\n  function( elem, type, handle ) {\n    var name = \"on\" + type;\n\n    if ( elem.detachEvent ) {\n\n      // #8545, #7054, preventing memory leaks for custom events in IE6-8\n      // detachEvent needed property on element, by name of that event, to properly expose it to GC\n      if ( typeof elem[ name ] === \"undefined\" ) {\n        elem[ name ] = null;\n      }\n\n      elem.detachEvent( name, handle );\n    }\n  };\n\njQuery.Event = function( src, props ) {\n  // Allow instantiation without the 'new' keyword\n  if ( !(this instanceof jQuery.Event) ) {\n    return new jQuery.Event( src, props );\n  }\n\n  // Event object\n  if ( src && src.type ) {\n    this.originalEvent = src;\n    this.type = src.type;\n\n    // Events bubbling up the document may have been marked as prevented\n    // by a handler lower down the tree; reflect the correct value.\n    this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n      src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n  // Event type\n  } else {\n    this.type = src;\n  }\n\n  // Put explicitly provided properties onto the event object\n  if ( props ) {\n    jQuery.extend( this, props );\n  }\n\n  // Create a timestamp if incoming event doesn't have one\n  this.timeStamp = src && src.timeStamp || jQuery.now();\n\n  // Mark it as fixed\n  this[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n  return false;\n}\nfunction returnTrue() {\n  return true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n  preventDefault: function() {\n    this.isDefaultPrevented = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n\n    // if preventDefault exists run it on the original event\n    if ( e.preventDefault ) {\n      e.preventDefault();\n\n    // otherwise set the returnValue property of the original event to false (IE)\n    } else {\n      e.returnValue = false;\n    }\n  },\n  stopPropagation: function() {\n    this.isPropagationStopped = returnTrue;\n\n    var e = this.originalEvent;\n    if ( !e ) {\n      return;\n    }\n    // if stopPropagation exists run it on the original event\n    if ( e.stopPropagation ) {\n      e.stopPropagation();\n    }\n    // otherwise set the cancelBubble property of the original event to true (IE)\n    e.cancelBubble = true;\n  },\n  stopImmediatePropagation: function() {\n    this.isImmediatePropagationStopped = returnTrue;\n    this.stopPropagation();\n  },\n  isDefaultPrevented: returnFalse,\n  isPropagationStopped: returnFalse,\n  isImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n  mouseenter: \"mouseover\",\n  mouseleave: \"mouseout\"\n}, function( orig, fix ) {\n  jQuery.event.special[ orig ] = {\n    delegateType: fix,\n    bindType: fix,\n\n    handle: function( event ) {\n      var ret,\n        target = this,\n        related = event.relatedTarget,\n        handleObj = event.handleObj,\n        selector = handleObj.selector;\n\n      // For mousenter/leave call the handler if related is outside the target.\n      // NB: No relatedTarget if the mouse left/entered the browser window\n      if ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n        event.type = handleObj.origType;\n        ret = handleObj.handler.apply( this, arguments );\n        event.type = fix;\n      }\n      return ret;\n    }\n  };\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n  jQuery.event.special.submit = {\n    setup: function() {\n      // Only need this for delegated form submit events\n      if ( jQuery.nodeName( this, \"form\" ) ) {\n        return false;\n      }\n\n      // Lazy-add a submit handler when a descendant form may potentially be submitted\n      jQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n        // Node name check avoids a VML-related crash in IE (#9807)\n        var elem = e.target,\n          form = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n        if ( form && !jQuery._data( form, \"_submit_attached\" ) ) {\n          jQuery.event.add( form, \"submit._submit\", function( event ) {\n            event._submit_bubble = true;\n          });\n          jQuery._data( form, \"_submit_attached\", true );\n        }\n      });\n      // return undefined since we don't need an event listener\n    },\n\n    postDispatch: function( event ) {\n      // If form was submitted by the user, bubble the event up the tree\n      if ( event._submit_bubble ) {\n        delete event._submit_bubble;\n        if ( this.parentNode && !event.isTrigger ) {\n          jQuery.event.simulate( \"submit\", this.parentNode, event, true );\n        }\n      }\n    },\n\n    teardown: function() {\n      // Only need this for delegated form submit events\n      if ( jQuery.nodeName( this, \"form\" ) ) {\n        return false;\n      }\n\n      // Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n      jQuery.event.remove( this, \"._submit\" );\n    }\n  };\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n  jQuery.event.special.change = {\n\n    setup: function() {\n\n      if ( rformElems.test( this.nodeName ) ) {\n        // IE doesn't fire change on a check/radio until blur; trigger it on click\n        // after a propertychange. Eat the blur-change in special.change.handle.\n        // This still fires onchange a second time for check/radio after blur.\n        if ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n          jQuery.event.add( this, \"propertychange._change\", function( event ) {\n            if ( event.originalEvent.propertyName === \"checked\" ) {\n              this._just_changed = true;\n            }\n          });\n          jQuery.event.add( this, \"click._change\", function( event ) {\n            if ( this._just_changed && !event.isTrigger ) {\n              this._just_changed = false;\n            }\n            // Allow triggered, simulated change events (#11500)\n            jQuery.event.simulate( \"change\", this, event, true );\n          });\n        }\n        return false;\n      }\n      // Delegated event; lazy-add a change handler on descendant inputs\n      jQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n        var elem = e.target;\n\n        if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"_change_attached\" ) ) {\n          jQuery.event.add( elem, \"change._change\", function( event ) {\n            if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n              jQuery.event.simulate( \"change\", this.parentNode, event, true );\n            }\n          });\n          jQuery._data( elem, \"_change_attached\", true );\n        }\n      });\n    },\n\n    handle: function( event ) {\n      var elem = event.target;\n\n      // Swallow native change events from checkbox/radio, we already triggered them above\n      if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n        return event.handleObj.handler.apply( this, arguments );\n      }\n    },\n\n    teardown: function() {\n      jQuery.event.remove( this, \"._change\" );\n\n      return !rformElems.test( this.nodeName );\n    }\n  };\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n  jQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n    // Attach a single capturing handler while someone wants focusin/focusout\n    var attaches = 0,\n      handler = function( event ) {\n        jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n      };\n\n    jQuery.event.special[ fix ] = {\n      setup: function() {\n        if ( attaches++ === 0 ) {\n          document.addEventListener( orig, handler, true );\n        }\n      },\n      teardown: function() {\n        if ( --attaches === 0 ) {\n          document.removeEventListener( orig, handler, true );\n        }\n      }\n    };\n  });\n}\n\njQuery.fn.extend({\n\n  on: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n    var origFn, type;\n\n    // Types can be a map of types/handlers\n    if ( typeof types === \"object\" ) {\n      // ( types-Object, selector, data )\n      if ( typeof selector !== \"string\" ) { // && selector != null\n        // ( types-Object, data )\n        data = data || selector;\n        selector = undefined;\n      }\n      for ( type in types ) {\n        this.on( type, selector, data, types[ type ], one );\n      }\n      return this;\n    }\n\n    if ( data == null && fn == null ) {\n      // ( types, fn )\n      fn = selector;\n      data = selector = undefined;\n    } else if ( fn == null ) {\n      if ( typeof selector === \"string\" ) {\n        // ( types, selector, fn )\n        fn = data;\n        data = undefined;\n      } else {\n        // ( types, data, fn )\n        fn = data;\n        data = selector;\n        selector = undefined;\n      }\n    }\n    if ( fn === false ) {\n      fn = returnFalse;\n    } else if ( !fn ) {\n      return this;\n    }\n\n    if ( one === 1 ) {\n      origFn = fn;\n      fn = function( event ) {\n        // Can use an empty set, since event contains the info\n        jQuery().off( event );\n        return origFn.apply( this, arguments );\n      };\n      // Use same guid so caller can remove using origFn\n      fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n    }\n    return this.each( function() {\n      jQuery.event.add( this, types, fn, data, selector );\n    });\n  },\n  one: function( types, selector, data, fn ) {\n    return this.on( types, selector, data, fn, 1 );\n  },\n  off: function( types, selector, fn ) {\n    var handleObj, type;\n    if ( types && types.preventDefault && types.handleObj ) {\n      // ( event )  dispatched jQuery.Event\n      handleObj = types.handleObj;\n      jQuery( types.delegateTarget ).off(\n        handleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n        handleObj.selector,\n        handleObj.handler\n      );\n      return this;\n    }\n    if ( typeof types === \"object\" ) {\n      // ( types-object [, selector] )\n      for ( type in types ) {\n        this.off( type, selector, types[ type ] );\n      }\n      return this;\n    }\n    if ( selector === false || typeof selector === \"function\" ) {\n      // ( types [, fn] )\n      fn = selector;\n      selector = undefined;\n    }\n    if ( fn === false ) {\n      fn = returnFalse;\n    }\n    return this.each(function() {\n      jQuery.event.remove( this, types, fn, selector );\n    });\n  },\n\n  bind: function( types, data, fn ) {\n    return this.on( types, null, data, fn );\n  },\n  unbind: function( types, fn ) {\n    return this.off( types, null, fn );\n  },\n\n  live: function( types, data, fn ) {\n    jQuery( this.context ).on( types, this.selector, data, fn );\n    return this;\n  },\n  die: function( types, fn ) {\n    jQuery( this.context ).off( types, this.selector || \"**\", fn );\n    return this;\n  },\n\n  delegate: function( selector, types, data, fn ) {\n    return this.on( types, selector, data, fn );\n  },\n  undelegate: function( selector, types, fn ) {\n    // ( namespace ) or ( selector, types [, fn] )\n    return arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n  },\n\n  trigger: function( type, data ) {\n    return this.each(function() {\n      jQuery.event.trigger( type, data, this );\n    });\n  },\n  triggerHandler: function( type, data ) {\n    if ( this[0] ) {\n      return jQuery.event.trigger( type, data, this[0], true );\n    }\n  },\n\n  toggle: function( fn ) {\n    // Save reference to arguments for access in closure\n    var args = arguments,\n      guid = fn.guid || jQuery.guid++,\n      i = 0,\n      toggler = function( event ) {\n        // Figure out which function to execute\n        var lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n        jQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n        // Make sure that clicks stop\n        event.preventDefault();\n\n        // and execute the function\n        return args[ lastToggle ].apply( this, arguments ) || false;\n      };\n\n    // link all the functions, so any of them can unbind this click handler\n    toggler.guid = guid;\n    while ( i < args.length ) {\n      args[ i++ ].guid = guid;\n    }\n\n    return this.click( toggler );\n  },\n\n  hover: function( fnOver, fnOut ) {\n    return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n  }\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n  \"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n  \"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n  // Handle event binding\n  jQuery.fn[ name ] = function( data, fn ) {\n    if ( fn == null ) {\n      fn = data;\n      data = null;\n    }\n\n    return arguments.length > 0 ?\n      this.on( name, null, data, fn ) :\n      this.trigger( name );\n  };\n\n  if ( rkeyEvent.test( name ) ) {\n    jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n  }\n\n  if ( rmouseEvent.test( name ) ) {\n    jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n  }\n});\n/*!\n * Sizzle CSS Selector Engine\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license\n * http://sizzlejs.com/\n */\n(function( window, undefined ) {\n\nvar cachedruns,\n  assertGetIdNotName,\n  Expr,\n  getText,\n  isXML,\n  contains,\n  compile,\n  sortOrder,\n  hasDuplicate,\n  outermostContext,\n\n  baseHasDuplicate = true,\n  strundefined = \"undefined\",\n\n  expando = ( \"sizcache\" + Math.random() ).replace( \".\", \"\" ),\n\n  Token = String,\n  document = window.document,\n  docElem = document.documentElement,\n  dirruns = 0,\n  done = 0,\n  pop = [].pop,\n  push = [].push,\n  slice = [].slice,\n  // Use a stripped-down indexOf if a native one is unavailable\n  indexOf = [].indexOf || function( elem ) {\n    var i = 0,\n      len = this.length;\n    for ( ; i < len; i++ ) {\n      if ( this[i] === elem ) {\n        return i;\n      }\n    }\n    return -1;\n  },\n\n  // Augment a function for special use by Sizzle\n  markFunction = function( fn, value ) {\n    fn[ expando ] = value == null || value;\n    return fn;\n  },\n\n  createCache = function() {\n    var cache = {},\n      keys = [];\n\n    return markFunction(function( key, value ) {\n      // Only keep the most recent entries\n      if ( keys.push( key ) > Expr.cacheLength ) {\n        delete cache[ keys.shift() ];\n      }\n\n      // Retrieve with (key + \" \") to avoid collision with native Object.prototype properties (see Issue #157)\n      return (cache[ key + \" \" ] = value);\n    }, cache );\n  },\n\n  classCache = createCache(),\n  tokenCache = createCache(),\n  compilerCache = createCache(),\n\n  // Regex\n\n  // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n  whitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n  // http://www.w3.org/TR/css3-syntax/#characters\n  characterEncoding = \"(?:\\\\\\\\.|[-\\\\w]|[^\\\\x00-\\\\xa0])+\",\n\n  // Loosely modeled on CSS identifier characters\n  // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)\n  // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n  identifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n  // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n  operators = \"([*^$|!~]?=)\",\n  attributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n    \"*(?:\" + operators + whitespace + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + identifier + \")|)|)\" + whitespace + \"*\\\\]\",\n\n  // Prefer arguments not in parens/brackets,\n  //   then attribute selectors and non-pseudos (denoted by :),\n  //   then anything else\n  // These preferences are here to reduce the number of selectors\n  //   needing tokenize in the PSEUDO preFilter\n  pseudos = \":(\" + characterEncoding + \")(?:\\\\((?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\2|([^()[\\\\]]*|(?:(?:\" + attributes + \")|[^:]|\\\\\\\\.)*|.*))\\\\)|)\",\n\n  // For matchExpr.POS and matchExpr.needsContext\n  pos = \":(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" + whitespace +\n    \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\",\n\n  // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n  rtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n  rcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n  rcombinators = new RegExp( \"^\" + whitespace + \"*([\\\\x20\\\\t\\\\r\\\\n\\\\f>+~])\" + whitespace + \"*\" ),\n  rpseudo = new RegExp( pseudos ),\n\n  // Easily-parseable/retrievable ID or TAG or CLASS selectors\n  rquickExpr = /^(?:#([\\w\\-]+)|(\\w+)|\\.([\\w\\-]+))$/,\n\n  rnot = /^:not/,\n  rsibling = /[\\x20\\t\\r\\n\\f]*[+~]/,\n  rendsWithNot = /:not\\($/,\n\n  rheader = /h\\d/i,\n  rinputs = /input|select|textarea|button/i,\n\n  rbackslash = /\\\\(?!\\\\)/g,\n\n  matchExpr = {\n    \"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n    \"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n    \"NAME\": new RegExp( \"^\\\\[name=['\\\"]?(\" + characterEncoding + \")['\\\"]?\\\\]\" ),\n    \"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n    \"ATTR\": new RegExp( \"^\" + attributes ),\n    \"PSEUDO\": new RegExp( \"^\" + pseudos ),\n    \"POS\": new RegExp( pos, \"i\" ),\n    \"CHILD\": new RegExp( \"^:(only|nth|first|last)-child(?:\\\\(\" + whitespace +\n      \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n      \"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n    // For use in libraries implementing .is()\n    \"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|\" + pos, \"i\" )\n  },\n\n  // Support\n\n  // Used for testing something on an element\n  assert = function( fn ) {\n    var div = document.createElement(\"div\");\n\n    try {\n      return fn( div );\n    } catch (e) {\n      return false;\n    } finally {\n      // release memory in IE\n      div = null;\n    }\n  },\n\n  // Check if getElementsByTagName(\"*\") returns only elements\n  assertTagNameNoComments = assert(function( div ) {\n    div.appendChild( document.createComment(\"\") );\n    return !div.getElementsByTagName(\"*\").length;\n  }),\n\n  // Check if getAttribute returns normalized href attributes\n  assertHrefNotNormalized = assert(function( div ) {\n    div.innerHTML = \"<a href='#'></a>\";\n    return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\n      div.firstChild.getAttribute(\"href\") === \"#\";\n  }),\n\n  // Check if attributes should be retrieved by attribute nodes\n  assertAttributes = assert(function( div ) {\n    div.innerHTML = \"<select></select>\";\n    var type = typeof div.lastChild.getAttribute(\"multiple\");\n    // IE8 returns a string for some attributes even when not present\n    return type !== \"boolean\" && type !== \"string\";\n  }),\n\n  // Check if getElementsByClassName can be trusted\n  assertUsableClassName = assert(function( div ) {\n    // Opera can't find a second classname (in 9.6)\n    div.innerHTML = \"<div class='hidden e'></div><div class='hidden'></div>\";\n    if ( !div.getElementsByClassName || !div.getElementsByClassName(\"e\").length ) {\n      return false;\n    }\n\n    // Safari 3.2 caches class attributes and doesn't catch changes\n    div.lastChild.className = \"e\";\n    return div.getElementsByClassName(\"e\").length === 2;\n  }),\n\n  // Check if getElementById returns elements by name\n  // Check if getElementsByName privileges form controls or returns elements by ID\n  assertUsableName = assert(function( div ) {\n    // Inject content\n    div.id = expando + 0;\n    div.innerHTML = \"<a name='\" + expando + \"'></a><div name='\" + expando + \"'></div>\";\n    docElem.insertBefore( div, docElem.firstChild );\n\n    // Test\n    var pass = document.getElementsByName &&\n      // buggy browsers will return fewer than the correct 2\n      document.getElementsByName( expando ).length === 2 +\n      // buggy browsers will return more than the correct 0\n      document.getElementsByName( expando + 0 ).length;\n    assertGetIdNotName = !document.getElementById( expando );\n\n    // Cleanup\n    docElem.removeChild( div );\n\n    return pass;\n  });\n\n// If slice is not available, provide a backup\ntry {\n  slice.call( docElem.childNodes, 0 )[0].nodeType;\n} catch ( e ) {\n  slice = function( i ) {\n    var elem,\n      results = [];\n    for ( ; (elem = this[i]); i++ ) {\n      results.push( elem );\n    }\n    return results;\n  };\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n  results = results || [];\n  context = context || document;\n  var match, elem, xml, m,\n    nodeType = context.nodeType;\n\n  if ( !selector || typeof selector !== \"string\" ) {\n    return results;\n  }\n\n  if ( nodeType !== 1 && nodeType !== 9 ) {\n    return [];\n  }\n\n  xml = isXML( context );\n\n  if ( !xml && !seed ) {\n    if ( (match = rquickExpr.exec( selector )) ) {\n      // Speed-up: Sizzle(\"#ID\")\n      if ( (m = match[1]) ) {\n        if ( nodeType === 9 ) {\n          elem = context.getElementById( m );\n          // Check parentNode to catch when Blackberry 4.6 returns\n          // nodes that are no longer in the document #6963\n          if ( elem && elem.parentNode ) {\n            // Handle the case where IE, Opera, and Webkit return items\n            // by name instead of ID\n            if ( elem.id === m ) {\n              results.push( elem );\n              return results;\n            }\n          } else {\n            return results;\n          }\n        } else {\n          // Context is not a document\n          if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n            contains( context, elem ) && elem.id === m ) {\n            results.push( elem );\n            return results;\n          }\n        }\n\n      // Speed-up: Sizzle(\"TAG\")\n      } else if ( match[2] ) {\n        push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\n        return results;\n\n      // Speed-up: Sizzle(\".CLASS\")\n      } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {\n        push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\n        return results;\n      }\n    }\n  }\n\n  // All others\n  return select( selector.replace( rtrim, \"$1\" ), context, results, seed, xml );\n}\n\nSizzle.matches = function( expr, elements ) {\n  return Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n  return Sizzle( expr, null, null, [ elem ] ).length > 0;\n};\n\n// Returns a function to use in pseudos for input types\nfunction createInputPseudo( type ) {\n  return function( elem ) {\n    var name = elem.nodeName.toLowerCase();\n    return name === \"input\" && elem.type === type;\n  };\n}\n\n// Returns a function to use in pseudos for buttons\nfunction createButtonPseudo( type ) {\n  return function( elem ) {\n    var name = elem.nodeName.toLowerCase();\n    return (name === \"input\" || name === \"button\") && elem.type === type;\n  };\n}\n\n// Returns a function to use in pseudos for positionals\nfunction createPositionalPseudo( fn ) {\n  return markFunction(function( argument ) {\n    argument = +argument;\n    return markFunction(function( seed, matches ) {\n      var j,\n        matchIndexes = fn( [], seed.length, argument ),\n        i = matchIndexes.length;\n\n      // Match elements found at the specified indexes\n      while ( i-- ) {\n        if ( seed[ (j = matchIndexes[i]) ] ) {\n          seed[j] = !(matches[j] = seed[j]);\n        }\n      }\n    });\n  });\n}\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n  var node,\n    ret = \"\",\n    i = 0,\n    nodeType = elem.nodeType;\n\n  if ( nodeType ) {\n    if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n      // Use textContent for elements\n      // innerText usage removed for consistency of new lines (see #11153)\n      if ( typeof elem.textContent === \"string\" ) {\n        return elem.textContent;\n      } else {\n        // Traverse its children\n        for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n          ret += getText( elem );\n        }\n      }\n    } else if ( nodeType === 3 || nodeType === 4 ) {\n      return elem.nodeValue;\n    }\n    // Do not include comment or processing instruction nodes\n  } else {\n\n    // If no nodeType, this is expected to be an array\n    for ( ; (node = elem[i]); i++ ) {\n      // Do not traverse comment nodes\n      ret += getText( node );\n    }\n  }\n  return ret;\n};\n\nisXML = Sizzle.isXML = function( elem ) {\n  // documentElement is verified for cases where it doesn't yet exist\n  // (such as loading iframes in IE - #4833)\n  var documentElement = elem && (elem.ownerDocument || elem).documentElement;\n  return documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n// Element contains another\ncontains = Sizzle.contains = docElem.contains ?\n  function( a, b ) {\n    var adown = a.nodeType === 9 ? a.documentElement : a,\n      bup = b && b.parentNode;\n    return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );\n  } :\n  docElem.compareDocumentPosition ?\n  function( a, b ) {\n    return b && !!( a.compareDocumentPosition( b ) & 16 );\n  } :\n  function( a, b ) {\n    while ( (b = b.parentNode) ) {\n      if ( b === a ) {\n        return true;\n      }\n    }\n    return false;\n  };\n\nSizzle.attr = function( elem, name ) {\n  var val,\n    xml = isXML( elem );\n\n  if ( !xml ) {\n    name = name.toLowerCase();\n  }\n  if ( (val = Expr.attrHandle[ name ]) ) {\n    return val( elem );\n  }\n  if ( xml || assertAttributes ) {\n    return elem.getAttribute( name );\n  }\n  val = elem.getAttributeNode( name );\n  return val ?\n    typeof elem[ name ] === \"boolean\" ?\n      elem[ name ] ? name : null :\n      val.specified ? val.value : null :\n    null;\n};\n\nExpr = Sizzle.selectors = {\n\n  // Can be adjusted by the user\n  cacheLength: 50,\n\n  createPseudo: markFunction,\n\n  match: matchExpr,\n\n  // IE6/7 return a modified href\n  attrHandle: assertHrefNotNormalized ?\n    {} :\n    {\n      \"href\": function( elem ) {\n        return elem.getAttribute( \"href\", 2 );\n      },\n      \"type\": function( elem ) {\n        return elem.getAttribute(\"type\");\n      }\n    },\n\n  find: {\n    \"ID\": assertGetIdNotName ?\n      function( id, context, xml ) {\n        if ( typeof context.getElementById !== strundefined && !xml ) {\n          var m = context.getElementById( id );\n          // Check parentNode to catch when Blackberry 4.6 returns\n          // nodes that are no longer in the document #6963\n          return m && m.parentNode ? [m] : [];\n        }\n      } :\n      function( id, context, xml ) {\n        if ( typeof context.getElementById !== strundefined && !xml ) {\n          var m = context.getElementById( id );\n\n          return m ?\n            m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode(\"id\").value === id ?\n              [m] :\n              undefined :\n            [];\n        }\n      },\n\n    \"TAG\": assertTagNameNoComments ?\n      function( tag, context ) {\n        if ( typeof context.getElementsByTagName !== strundefined ) {\n          return context.getElementsByTagName( tag );\n        }\n      } :\n      function( tag, context ) {\n        var results = context.getElementsByTagName( tag );\n\n        // Filter out possible comments\n        if ( tag === \"*\" ) {\n          var elem,\n            tmp = [],\n            i = 0;\n\n          for ( ; (elem = results[i]); i++ ) {\n            if ( elem.nodeType === 1 ) {\n              tmp.push( elem );\n            }\n          }\n\n          return tmp;\n        }\n        return results;\n      },\n\n    \"NAME\": assertUsableName && function( tag, context ) {\n      if ( typeof context.getElementsByName !== strundefined ) {\n        return context.getElementsByName( name );\n      }\n    },\n\n    \"CLASS\": assertUsableClassName && function( className, context, xml ) {\n      if ( typeof context.getElementsByClassName !== strundefined && !xml ) {\n        return context.getElementsByClassName( className );\n      }\n    }\n  },\n\n  relative: {\n    \">\": { dir: \"parentNode\", first: true },\n    \" \": { dir: \"parentNode\" },\n    \"+\": { dir: \"previousSibling\", first: true },\n    \"~\": { dir: \"previousSibling\" }\n  },\n\n  preFilter: {\n    \"ATTR\": function( match ) {\n      match[1] = match[1].replace( rbackslash, \"\" );\n\n      // Move the given value to match[3] whether quoted or unquoted\n      match[3] = ( match[4] || match[5] || \"\" ).replace( rbackslash, \"\" );\n\n      if ( match[2] === \"~=\" ) {\n        match[3] = \" \" + match[3] + \" \";\n      }\n\n      return match.slice( 0, 4 );\n    },\n\n    \"CHILD\": function( match ) {\n      /* matches from matchExpr[\"CHILD\"]\n        1 type (only|nth|...)\n        2 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n        3 xn-component of xn+y argument ([+-]?\\d*n|)\n        4 sign of xn-component\n        5 x of xn-component\n        6 sign of y-component\n        7 y of y-component\n      */\n      match[1] = match[1].toLowerCase();\n\n      if ( match[1] === \"nth\" ) {\n        // nth-child requires argument\n        if ( !match[2] ) {\n          Sizzle.error( match[0] );\n        }\n\n        // numeric x and y parameters for Expr.filter.CHILD\n        // remember that false/true cast respectively to 0/1\n        match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === \"even\" || match[2] === \"odd\" ) );\n        match[4] = +( ( match[6] + match[7] ) || match[2] === \"odd\" );\n\n      // other types prohibit arguments\n      } else if ( match[2] ) {\n        Sizzle.error( match[0] );\n      }\n\n      return match;\n    },\n\n    \"PSEUDO\": function( match ) {\n      var unquoted, excess;\n      if ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n        return null;\n      }\n\n      if ( match[3] ) {\n        match[2] = match[3];\n      } else if ( (unquoted = match[4]) ) {\n        // Only check arguments that contain a pseudo\n        if ( rpseudo.test(unquoted) &&\n          // Get excess from tokenize (recursively)\n          (excess = tokenize( unquoted, true )) &&\n          // advance to the next closing parenthesis\n          (excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n          // excess is a negative index\n          unquoted = unquoted.slice( 0, excess );\n          match[0] = match[0].slice( 0, excess );\n        }\n        match[2] = unquoted;\n      }\n\n      // Return only captures needed by the pseudo filter method (type and argument)\n      return match.slice( 0, 3 );\n    }\n  },\n\n  filter: {\n    \"ID\": assertGetIdNotName ?\n      function( id ) {\n        id = id.replace( rbackslash, \"\" );\n        return function( elem ) {\n          return elem.getAttribute(\"id\") === id;\n        };\n      } :\n      function( id ) {\n        id = id.replace( rbackslash, \"\" );\n        return function( elem ) {\n          var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode(\"id\");\n          return node && node.value === id;\n        };\n      },\n\n    \"TAG\": function( nodeName ) {\n      if ( nodeName === \"*\" ) {\n        return function() { return true; };\n      }\n      nodeName = nodeName.replace( rbackslash, \"\" ).toLowerCase();\n\n      return function( elem ) {\n        return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n      };\n    },\n\n    \"CLASS\": function( className ) {\n      var pattern = classCache[ expando ][ className + \" \" ];\n\n      return pattern ||\n        (pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n        classCache( className, function( elem ) {\n          return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute(\"class\")) || \"\" );\n        });\n    },\n\n    \"ATTR\": function( name, operator, check ) {\n      return function( elem, context ) {\n        var result = Sizzle.attr( elem, name );\n\n        if ( result == null ) {\n          return operator === \"!=\";\n        }\n        if ( !operator ) {\n          return true;\n        }\n\n        result += \"\";\n\n        return operator === \"=\" ? result === check :\n          operator === \"!=\" ? result !== check :\n          operator === \"^=\" ? check && result.indexOf( check ) === 0 :\n          operator === \"*=\" ? check && result.indexOf( check ) > -1 :\n          operator === \"$=\" ? check && result.substr( result.length - check.length ) === check :\n          operator === \"~=\" ? ( \" \" + result + \" \" ).indexOf( check ) > -1 :\n          operator === \"|=\" ? result === check || result.substr( 0, check.length + 1 ) === check + \"-\" :\n          false;\n      };\n    },\n\n    \"CHILD\": function( type, argument, first, last ) {\n\n      if ( type === \"nth\" ) {\n        return function( elem ) {\n          var node, diff,\n            parent = elem.parentNode;\n\n          if ( first === 1 && last === 0 ) {\n            return true;\n          }\n\n          if ( parent ) {\n            diff = 0;\n            for ( node = parent.firstChild; node; node = node.nextSibling ) {\n              if ( node.nodeType === 1 ) {\n                diff++;\n                if ( elem === node ) {\n                  break;\n                }\n              }\n            }\n          }\n\n          // Incorporate the offset (or cast to NaN), then check against cycle size\n          diff -= last;\n          return diff === first || ( diff % first === 0 && diff / first >= 0 );\n        };\n      }\n\n      return function( elem ) {\n        var node = elem;\n\n        switch ( type ) {\n          case \"only\":\n          case \"first\":\n            while ( (node = node.previousSibling) ) {\n              if ( node.nodeType === 1 ) {\n                return false;\n              }\n            }\n\n            if ( type === \"first\" ) {\n              return true;\n            }\n\n            node = elem;\n\n            /* falls through */\n          case \"last\":\n            while ( (node = node.nextSibling) ) {\n              if ( node.nodeType === 1 ) {\n                return false;\n              }\n            }\n\n            return true;\n        }\n      };\n    },\n\n    \"PSEUDO\": function( pseudo, argument ) {\n      // pseudo-class names are case-insensitive\n      // http://www.w3.org/TR/selectors/#pseudo-classes\n      // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n      // Remember that setFilters inherits from pseudos\n      var args,\n        fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n          Sizzle.error( \"unsupported pseudo: \" + pseudo );\n\n      // The user may use createPseudo to indicate that\n      // arguments are needed to create the filter function\n      // just as Sizzle does\n      if ( fn[ expando ] ) {\n        return fn( argument );\n      }\n\n      // But maintain support for old signatures\n      if ( fn.length > 1 ) {\n        args = [ pseudo, pseudo, \"\", argument ];\n        return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n          markFunction(function( seed, matches ) {\n            var idx,\n              matched = fn( seed, argument ),\n              i = matched.length;\n            while ( i-- ) {\n              idx = indexOf.call( seed, matched[i] );\n              seed[ idx ] = !( matches[ idx ] = matched[i] );\n            }\n          }) :\n          function( elem ) {\n            return fn( elem, 0, args );\n          };\n      }\n\n      return fn;\n    }\n  },\n\n  pseudos: {\n    \"not\": markFunction(function( selector ) {\n      // Trim the selector passed to compile\n      // to avoid treating leading and trailing\n      // spaces as combinators\n      var input = [],\n        results = [],\n        matcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n      return matcher[ expando ] ?\n        markFunction(function( seed, matches, context, xml ) {\n          var elem,\n            unmatched = matcher( seed, null, xml, [] ),\n            i = seed.length;\n\n          // Match elements unmatched by `matcher`\n          while ( i-- ) {\n            if ( (elem = unmatched[i]) ) {\n              seed[i] = !(matches[i] = elem);\n            }\n          }\n        }) :\n        function( elem, context, xml ) {\n          input[0] = elem;\n          matcher( input, null, xml, results );\n          return !results.pop();\n        };\n    }),\n\n    \"has\": markFunction(function( selector ) {\n      return function( elem ) {\n        return Sizzle( selector, elem ).length > 0;\n      };\n    }),\n\n    \"contains\": markFunction(function( text ) {\n      return function( elem ) {\n        return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n      };\n    }),\n\n    \"enabled\": function( elem ) {\n      return elem.disabled === false;\n    },\n\n    \"disabled\": function( elem ) {\n      return elem.disabled === true;\n    },\n\n    \"checked\": function( elem ) {\n      // In CSS3, :checked should return both checked and selected elements\n      // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n      var nodeName = elem.nodeName.toLowerCase();\n      return (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n    },\n\n    \"selected\": function( elem ) {\n      // Accessing this property makes selected-by-default\n      // options in Safari work properly\n      if ( elem.parentNode ) {\n        elem.parentNode.selectedIndex;\n      }\n\n      return elem.selected === true;\n    },\n\n    \"parent\": function( elem ) {\n      return !Expr.pseudos[\"empty\"]( elem );\n    },\n\n    \"empty\": function( elem ) {\n      // http://www.w3.org/TR/selectors/#empty-pseudo\n      // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\n      //   not comment, processing instructions, or others\n      // Thanks to Diego Perini for the nodeName shortcut\n      //   Greater than \"@\" means alpha characters (specifically not starting with \"#\" or \"?\")\n      var nodeType;\n      elem = elem.firstChild;\n      while ( elem ) {\n        if ( elem.nodeName > \"@\" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {\n          return false;\n        }\n        elem = elem.nextSibling;\n      }\n      return true;\n    },\n\n    \"header\": function( elem ) {\n      return rheader.test( elem.nodeName );\n    },\n\n    \"text\": function( elem ) {\n      var type, attr;\n      // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n      // use getAttribute instead to test this case\n      return elem.nodeName.toLowerCase() === \"input\" &&\n        (type = elem.type) === \"text\" &&\n        ( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === type );\n    },\n\n    // Input types\n    \"radio\": createInputPseudo(\"radio\"),\n    \"checkbox\": createInputPseudo(\"checkbox\"),\n    \"file\": createInputPseudo(\"file\"),\n    \"password\": createInputPseudo(\"password\"),\n    \"image\": createInputPseudo(\"image\"),\n\n    \"submit\": createButtonPseudo(\"submit\"),\n    \"reset\": createButtonPseudo(\"reset\"),\n\n    \"button\": function( elem ) {\n      var name = elem.nodeName.toLowerCase();\n      return name === \"input\" && elem.type === \"button\" || name === \"button\";\n    },\n\n    \"input\": function( elem ) {\n      return rinputs.test( elem.nodeName );\n    },\n\n    \"focus\": function( elem ) {\n      var doc = elem.ownerDocument;\n      return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n    },\n\n    \"active\": function( elem ) {\n      return elem === elem.ownerDocument.activeElement;\n    },\n\n    // Positional types\n    \"first\": createPositionalPseudo(function() {\n      return [ 0 ];\n    }),\n\n    \"last\": createPositionalPseudo(function( matchIndexes, length ) {\n      return [ length - 1 ];\n    }),\n\n    \"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n      return [ argument < 0 ? argument + length : argument ];\n    }),\n\n    \"even\": createPositionalPseudo(function( matchIndexes, length ) {\n      for ( var i = 0; i < length; i += 2 ) {\n        matchIndexes.push( i );\n      }\n      return matchIndexes;\n    }),\n\n    \"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n      for ( var i = 1; i < length; i += 2 ) {\n        matchIndexes.push( i );\n      }\n      return matchIndexes;\n    }),\n\n    \"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n      for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) {\n        matchIndexes.push( i );\n      }\n      return matchIndexes;\n    }),\n\n    \"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n      for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) {\n        matchIndexes.push( i );\n      }\n      return matchIndexes;\n    })\n  }\n};\n\nfunction siblingCheck( a, b, ret ) {\n  if ( a === b ) {\n    return ret;\n  }\n\n  var cur = a.nextSibling;\n\n  while ( cur ) {\n    if ( cur === b ) {\n      return -1;\n    }\n\n    cur = cur.nextSibling;\n  }\n\n  return 1;\n}\n\nsortOrder = docElem.compareDocumentPosition ?\n  function( a, b ) {\n    if ( a === b ) {\n      hasDuplicate = true;\n      return 0;\n    }\n\n    return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?\n      a.compareDocumentPosition :\n      a.compareDocumentPosition(b) & 4\n    ) ? -1 : 1;\n  } :\n  function( a, b ) {\n    // The nodes are identical, we can exit early\n    if ( a === b ) {\n      hasDuplicate = true;\n      return 0;\n\n    // Fallback to using sourceIndex (in IE) if it's available on both nodes\n    } else if ( a.sourceIndex && b.sourceIndex ) {\n      return a.sourceIndex - b.sourceIndex;\n    }\n\n    var al, bl,\n      ap = [],\n      bp = [],\n      aup = a.parentNode,\n      bup = b.parentNode,\n      cur = aup;\n\n    // If the nodes are siblings (or identical) we can do a quick check\n    if ( aup === bup ) {\n      return siblingCheck( a, b );\n\n    // If no parents were found then the nodes are disconnected\n    } else if ( !aup ) {\n      return -1;\n\n    } else if ( !bup ) {\n      return 1;\n    }\n\n    // Otherwise they're somewhere else in the tree so we need\n    // to build up a full list of the parentNodes for comparison\n    while ( cur ) {\n      ap.unshift( cur );\n      cur = cur.parentNode;\n    }\n\n    cur = bup;\n\n    while ( cur ) {\n      bp.unshift( cur );\n      cur = cur.parentNode;\n    }\n\n    al = ap.length;\n    bl = bp.length;\n\n    // Start walking down the tree looking for a discrepancy\n    for ( var i = 0; i < al && i < bl; i++ ) {\n      if ( ap[i] !== bp[i] ) {\n        return siblingCheck( ap[i], bp[i] );\n      }\n    }\n\n    // We ended someplace up the tree so do a sibling check\n    return i === al ?\n      siblingCheck( a, bp[i], -1 ) :\n      siblingCheck( ap[i], b, 1 );\n  };\n\n// Always assume the presence of duplicates if sort doesn't\n// pass them to our comparison function (as in Google Chrome).\n[0, 0].sort( sortOrder );\nbaseHasDuplicate = !hasDuplicate;\n\n// Document sorting and removing duplicates\nSizzle.uniqueSort = function( results ) {\n  var elem,\n    duplicates = [],\n    i = 1,\n    j = 0;\n\n  hasDuplicate = baseHasDuplicate;\n  results.sort( sortOrder );\n\n  if ( hasDuplicate ) {\n    for ( ; (elem = results[i]); i++ ) {\n      if ( elem === results[ i - 1 ] ) {\n        j = duplicates.push( i );\n      }\n    }\n    while ( j-- ) {\n      results.splice( duplicates[ j ], 1 );\n    }\n  }\n\n  return results;\n};\n\nSizzle.error = function( msg ) {\n  throw new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\nfunction tokenize( selector, parseOnly ) {\n  var matched, match, tokens, type,\n    soFar, groups, preFilters,\n    cached = tokenCache[ expando ][ selector + \" \" ];\n\n  if ( cached ) {\n    return parseOnly ? 0 : cached.slice( 0 );\n  }\n\n  soFar = selector;\n  groups = [];\n  preFilters = Expr.preFilter;\n\n  while ( soFar ) {\n\n    // Comma and first run\n    if ( !matched || (match = rcomma.exec( soFar )) ) {\n      if ( match ) {\n        // Don't consume trailing commas as valid\n        soFar = soFar.slice( match[0].length ) || soFar;\n      }\n      groups.push( tokens = [] );\n    }\n\n    matched = false;\n\n    // Combinators\n    if ( (match = rcombinators.exec( soFar )) ) {\n      tokens.push( matched = new Token( match.shift() ) );\n      soFar = soFar.slice( matched.length );\n\n      // Cast descendant combinators to space\n      matched.type = match[0].replace( rtrim, \" \" );\n    }\n\n    // Filters\n    for ( type in Expr.filter ) {\n      if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n        (match = preFilters[ type ]( match ))) ) {\n\n        tokens.push( matched = new Token( match.shift() ) );\n        soFar = soFar.slice( matched.length );\n        matched.type = type;\n        matched.matches = match;\n      }\n    }\n\n    if ( !matched ) {\n      break;\n    }\n  }\n\n  // Return the length of the invalid excess\n  // if we're just parsing\n  // Otherwise, throw an error or return tokens\n  return parseOnly ?\n    soFar.length :\n    soFar ?\n      Sizzle.error( selector ) :\n      // Cache the tokens\n      tokenCache( selector, groups ).slice( 0 );\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n  var dir = combinator.dir,\n    checkNonElements = base && combinator.dir === \"parentNode\",\n    doneName = done++;\n\n  return combinator.first ?\n    // Check against closest ancestor/preceding element\n    function( elem, context, xml ) {\n      while ( (elem = elem[ dir ]) ) {\n        if ( checkNonElements || elem.nodeType === 1  ) {\n          return matcher( elem, context, xml );\n        }\n      }\n    } :\n\n    // Check against all ancestor/preceding elements\n    function( elem, context, xml ) {\n      // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n      if ( !xml ) {\n        var cache,\n          dirkey = dirruns + \" \" + doneName + \" \",\n          cachedkey = dirkey + cachedruns;\n        while ( (elem = elem[ dir ]) ) {\n          if ( checkNonElements || elem.nodeType === 1 ) {\n            if ( (cache = elem[ expando ]) === cachedkey ) {\n              return elem.sizset;\n            } else if ( typeof cache === \"string\" && cache.indexOf(dirkey) === 0 ) {\n              if ( elem.sizset ) {\n                return elem;\n              }\n            } else {\n              elem[ expando ] = cachedkey;\n              if ( matcher( elem, context, xml ) ) {\n                elem.sizset = true;\n                return elem;\n              }\n              elem.sizset = false;\n            }\n          }\n        }\n      } else {\n        while ( (elem = elem[ dir ]) ) {\n          if ( checkNonElements || elem.nodeType === 1 ) {\n            if ( matcher( elem, context, xml ) ) {\n              return elem;\n            }\n          }\n        }\n      }\n    };\n}\n\nfunction elementMatcher( matchers ) {\n  return matchers.length > 1 ?\n    function( elem, context, xml ) {\n      var i = matchers.length;\n      while ( i-- ) {\n        if ( !matchers[i]( elem, context, xml ) ) {\n          return false;\n        }\n      }\n      return true;\n    } :\n    matchers[0];\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n  var elem,\n    newUnmatched = [],\n    i = 0,\n    len = unmatched.length,\n    mapped = map != null;\n\n  for ( ; i < len; i++ ) {\n    if ( (elem = unmatched[i]) ) {\n      if ( !filter || filter( elem, context, xml ) ) {\n        newUnmatched.push( elem );\n        if ( mapped ) {\n          map.push( i );\n        }\n      }\n    }\n  }\n\n  return newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n  if ( postFilter && !postFilter[ expando ] ) {\n    postFilter = setMatcher( postFilter );\n  }\n  if ( postFinder && !postFinder[ expando ] ) {\n    postFinder = setMatcher( postFinder, postSelector );\n  }\n  return markFunction(function( seed, results, context, xml ) {\n    var temp, i, elem,\n      preMap = [],\n      postMap = [],\n      preexisting = results.length,\n\n      // Get initial elements from seed or context\n      elems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n      // Prefilter to get matcher input, preserving a map for seed-results synchronization\n      matcherIn = preFilter && ( seed || !selector ) ?\n        condense( elems, preMap, preFilter, context, xml ) :\n        elems,\n\n      matcherOut = matcher ?\n        // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n        postFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n          // ...intermediate processing is necessary\n          [] :\n\n          // ...otherwise use results directly\n          results :\n        matcherIn;\n\n    // Find primary matches\n    if ( matcher ) {\n      matcher( matcherIn, matcherOut, context, xml );\n    }\n\n    // Apply postFilter\n    if ( postFilter ) {\n      temp = condense( matcherOut, postMap );\n      postFilter( temp, [], context, xml );\n\n      // Un-match failing elements by moving them back to matcherIn\n      i = temp.length;\n      while ( i-- ) {\n        if ( (elem = temp[i]) ) {\n          matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n        }\n      }\n    }\n\n    if ( seed ) {\n      if ( postFinder || preFilter ) {\n        if ( postFinder ) {\n          // Get the final matcherOut by condensing this intermediate into postFinder contexts\n          temp = [];\n          i = matcherOut.length;\n          while ( i-- ) {\n            if ( (elem = matcherOut[i]) ) {\n              // Restore matcherIn since elem is not yet a final match\n              temp.push( (matcherIn[i] = elem) );\n            }\n          }\n          postFinder( null, (matcherOut = []), temp, xml );\n        }\n\n        // Move matched elements from seed to results to keep them synchronized\n        i = matcherOut.length;\n        while ( i-- ) {\n          if ( (elem = matcherOut[i]) &&\n            (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\n\n            seed[temp] = !(results[temp] = elem);\n          }\n        }\n      }\n\n    // Add elements to results, through postFinder if defined\n    } else {\n      matcherOut = condense(\n        matcherOut === results ?\n          matcherOut.splice( preexisting, matcherOut.length ) :\n          matcherOut\n      );\n      if ( postFinder ) {\n        postFinder( null, results, matcherOut, xml );\n      } else {\n        push.apply( results, matcherOut );\n      }\n    }\n  });\n}\n\nfunction matcherFromTokens( tokens ) {\n  var checkContext, matcher, j,\n    len = tokens.length,\n    leadingRelative = Expr.relative[ tokens[0].type ],\n    implicitRelative = leadingRelative || Expr.relative[\" \"],\n    i = leadingRelative ? 1 : 0,\n\n    // The foundational matcher ensures that elements are reachable from top-level context(s)\n    matchContext = addCombinator( function( elem ) {\n      return elem === checkContext;\n    }, implicitRelative, true ),\n    matchAnyContext = addCombinator( function( elem ) {\n      return indexOf.call( checkContext, elem ) > -1;\n    }, implicitRelative, true ),\n    matchers = [ function( elem, context, xml ) {\n      return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n        (checkContext = context).nodeType ?\n          matchContext( elem, context, xml ) :\n          matchAnyContext( elem, context, xml ) );\n    } ];\n\n  for ( ; i < len; i++ ) {\n    if ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n      matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];\n    } else {\n      matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n      // Return special upon seeing a positional matcher\n      if ( matcher[ expando ] ) {\n        // Find the next relative operator (if any) for proper handling\n        j = ++i;\n        for ( ; j < len; j++ ) {\n          if ( Expr.relative[ tokens[j].type ] ) {\n            break;\n          }\n        }\n        return setMatcher(\n          i > 1 && elementMatcher( matchers ),\n          i > 1 && tokens.slice( 0, i - 1 ).join(\"\").replace( rtrim, \"$1\" ),\n          matcher,\n          i < j && matcherFromTokens( tokens.slice( i, j ) ),\n          j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n          j < len && tokens.join(\"\")\n        );\n      }\n      matchers.push( matcher );\n    }\n  }\n\n  return elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n  var bySet = setMatchers.length > 0,\n    byElement = elementMatchers.length > 0,\n    superMatcher = function( seed, context, xml, results, expandContext ) {\n      var elem, j, matcher,\n        setMatched = [],\n        matchedCount = 0,\n        i = \"0\",\n        unmatched = seed && [],\n        outermost = expandContext != null,\n        contextBackup = outermostContext,\n        // We must always have either seed elements or context\n        elems = seed || byElement && Expr.find[\"TAG\"]( \"*\", expandContext && context.parentNode || context ),\n        // Nested matchers should use non-integer dirruns\n        dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);\n\n      if ( outermost ) {\n        outermostContext = context !== document && context;\n        cachedruns = superMatcher.el;\n      }\n\n      // Add elements passing elementMatchers directly to results\n      for ( ; (elem = elems[i]) != null; i++ ) {\n        if ( byElement && elem ) {\n          for ( j = 0; (matcher = elementMatchers[j]); j++ ) {\n            if ( matcher( elem, context, xml ) ) {\n              results.push( elem );\n              break;\n            }\n          }\n          if ( outermost ) {\n            dirruns = dirrunsUnique;\n            cachedruns = ++superMatcher.el;\n          }\n        }\n\n        // Track unmatched elements for set filters\n        if ( bySet ) {\n          // They will have gone through all possible matchers\n          if ( (elem = !matcher && elem) ) {\n            matchedCount--;\n          }\n\n          // Lengthen the array for every element, matched or not\n          if ( seed ) {\n            unmatched.push( elem );\n          }\n        }\n      }\n\n      // Apply set filters to unmatched elements\n      matchedCount += i;\n      if ( bySet && i !== matchedCount ) {\n        for ( j = 0; (matcher = setMatchers[j]); j++ ) {\n          matcher( unmatched, setMatched, context, xml );\n        }\n\n        if ( seed ) {\n          // Reintegrate element matches to eliminate the need for sorting\n          if ( matchedCount > 0 ) {\n            while ( i-- ) {\n              if ( !(unmatched[i] || setMatched[i]) ) {\n                setMatched[i] = pop.call( results );\n              }\n            }\n          }\n\n          // Discard index placeholder values to get only actual matches\n          setMatched = condense( setMatched );\n        }\n\n        // Add matches to results\n        push.apply( results, setMatched );\n\n        // Seedless set matches succeeding multiple successful matchers stipulate sorting\n        if ( outermost && !seed && setMatched.length > 0 &&\n          ( matchedCount + setMatchers.length ) > 1 ) {\n\n          Sizzle.uniqueSort( results );\n        }\n      }\n\n      // Override manipulation of globals by nested matchers\n      if ( outermost ) {\n        dirruns = dirrunsUnique;\n        outermostContext = contextBackup;\n      }\n\n      return unmatched;\n    };\n\n  superMatcher.el = 0;\n  return bySet ?\n    markFunction( superMatcher ) :\n    superMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\n  var i,\n    setMatchers = [],\n    elementMatchers = [],\n    cached = compilerCache[ expando ][ selector + \" \" ];\n\n  if ( !cached ) {\n    // Generate a function of recursive functions that can be used to check each element\n    if ( !group ) {\n      group = tokenize( selector );\n    }\n    i = group.length;\n    while ( i-- ) {\n      cached = matcherFromTokens( group[i] );\n      if ( cached[ expando ] ) {\n        setMatchers.push( cached );\n      } else {\n        elementMatchers.push( cached );\n      }\n    }\n\n    // Cache the compiled function\n    cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n  }\n  return cached;\n};\n\nfunction multipleContexts( selector, contexts, results ) {\n  var i = 0,\n    len = contexts.length;\n  for ( ; i < len; i++ ) {\n    Sizzle( selector, contexts[i], results );\n  }\n  return results;\n}\n\nfunction select( selector, context, results, seed, xml ) {\n  var i, tokens, token, type, find,\n    match = tokenize( selector ),\n    j = match.length;\n\n  if ( !seed ) {\n    // Try to minimize operations if there is only one group\n    if ( match.length === 1 ) {\n\n      // Take a shortcut and set the context if the root selector is an ID\n      tokens = match[0] = match[0].slice( 0 );\n      if ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n          context.nodeType === 9 && !xml &&\n          Expr.relative[ tokens[1].type ] ) {\n\n        context = Expr.find[\"ID\"]( token.matches[0].replace( rbackslash, \"\" ), context, xml )[0];\n        if ( !context ) {\n          return results;\n        }\n\n        selector = selector.slice( tokens.shift().length );\n      }\n\n      // Fetch a seed set for right-to-left matching\n      for ( i = matchExpr[\"POS\"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) {\n        token = tokens[i];\n\n        // Abort if we hit a combinator\n        if ( Expr.relative[ (type = token.type) ] ) {\n          break;\n        }\n        if ( (find = Expr.find[ type ]) ) {\n          // Search, expanding context for leading sibling combinators\n          if ( (seed = find(\n            token.matches[0].replace( rbackslash, \"\" ),\n            rsibling.test( tokens[0].type ) && context.parentNode || context,\n            xml\n          )) ) {\n\n            // If seed is empty or no tokens remain, we can return early\n            tokens.splice( i, 1 );\n            selector = seed.length && tokens.join(\"\");\n            if ( !selector ) {\n              push.apply( results, slice.call( seed, 0 ) );\n              return results;\n            }\n\n            break;\n          }\n        }\n      }\n    }\n  }\n\n  // Compile and execute a filtering function\n  // Provide `match` to avoid retokenization if we modified the selector above\n  compile( selector, match )(\n    seed,\n    context,\n    xml,\n    results,\n    rsibling.test( selector )\n  );\n  return results;\n}\n\nif ( document.querySelectorAll ) {\n  (function() {\n    var disconnectedMatch,\n      oldSelect = select,\n      rescape = /'|\\\\/g,\n      rattributeQuotes = /\\=[\\x20\\t\\r\\n\\f]*([^'\"\\]]*)[\\x20\\t\\r\\n\\f]*\\]/g,\n\n      // qSa(:focus) reports false when true (Chrome 21), no need to also add to buggyMatches since matches checks buggyQSA\n      // A support test would require too much code (would include document ready)\n      rbuggyQSA = [ \":focus\" ],\n\n      // matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n      // A support test would require too much code (would include document ready)\n      // just skip matchesSelector for :active\n      rbuggyMatches = [ \":active\" ],\n      matches = docElem.matchesSelector ||\n        docElem.mozMatchesSelector ||\n        docElem.webkitMatchesSelector ||\n        docElem.oMatchesSelector ||\n        docElem.msMatchesSelector;\n\n    // Build QSA regex\n    // Regex strategy adopted from Diego Perini\n    assert(function( div ) {\n      // Select is set to empty string on purpose\n      // This is to test IE's treatment of not explictly\n      // setting a boolean content attribute,\n      // since its presence should be enough\n      // http://bugs.jquery.com/ticket/12359\n      div.innerHTML = \"<select><option selected=''></option></select>\";\n\n      // IE8 - Some boolean attributes are not treated correctly\n      if ( !div.querySelectorAll(\"[selected]\").length ) {\n        rbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:checked|disabled|ismap|multiple|readonly|selected|value)\" );\n      }\n\n      // Webkit/Opera - :checked should return selected option elements\n      // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n      // IE8 throws error here (do not put tests after this one)\n      if ( !div.querySelectorAll(\":checked\").length ) {\n        rbuggyQSA.push(\":checked\");\n      }\n    });\n\n    assert(function( div ) {\n\n      // Opera 10-12/IE9 - ^= $= *= and empty values\n      // Should not select anything\n      div.innerHTML = \"<p test=''></p>\";\n      if ( div.querySelectorAll(\"[test^='']\").length ) {\n        rbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:\\\"\\\"|'')\" );\n      }\n\n      // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n      // IE8 throws error here (do not put tests after this one)\n      div.innerHTML = \"<input type='hidden'/>\";\n      if ( !div.querySelectorAll(\":enabled\").length ) {\n        rbuggyQSA.push(\":enabled\", \":disabled\");\n      }\n    });\n\n    // rbuggyQSA always contains :focus, so no need for a length check\n    rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join(\"|\") );\n\n    select = function( selector, context, results, seed, xml ) {\n      // Only use querySelectorAll when not filtering,\n      // when this is not xml,\n      // and when no QSA bugs apply\n      if ( !seed && !xml && !rbuggyQSA.test( selector ) ) {\n        var groups, i,\n          old = true,\n          nid = expando,\n          newContext = context,\n          newSelector = context.nodeType === 9 && selector;\n\n        // qSA works strangely on Element-rooted queries\n        // We can work around this by specifying an extra ID on the root\n        // and working up from there (Thanks to Andrew Dupont for the technique)\n        // IE 8 doesn't work on object elements\n        if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n          groups = tokenize( selector );\n\n          if ( (old = context.getAttribute(\"id\")) ) {\n            nid = old.replace( rescape, \"\\\\$&\" );\n          } else {\n            context.setAttribute( \"id\", nid );\n          }\n          nid = \"[id='\" + nid + \"'] \";\n\n          i = groups.length;\n          while ( i-- ) {\n            groups[i] = nid + groups[i].join(\"\");\n          }\n          newContext = rsibling.test( selector ) && context.parentNode || context;\n          newSelector = groups.join(\",\");\n        }\n\n        if ( newSelector ) {\n          try {\n            push.apply( results, slice.call( newContext.querySelectorAll(\n              newSelector\n            ), 0 ) );\n            return results;\n          } catch(qsaError) {\n          } finally {\n            if ( !old ) {\n              context.removeAttribute(\"id\");\n            }\n          }\n        }\n      }\n\n      return oldSelect( selector, context, results, seed, xml );\n    };\n\n    if ( matches ) {\n      assert(function( div ) {\n        // Check to see if it's possible to do matchesSelector\n        // on a disconnected node (IE 9)\n        disconnectedMatch = matches.call( div, \"div\" );\n\n        // This should fail with an exception\n        // Gecko does not error, returns false instead\n        try {\n          matches.call( div, \"[test!='']:sizzle\" );\n          rbuggyMatches.push( \"!=\", pseudos );\n        } catch ( e ) {}\n      });\n\n      // rbuggyMatches always contains :active and :focus, so no need for a length check\n      rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join(\"|\") );\n\n      Sizzle.matchesSelector = function( elem, expr ) {\n        // Make sure that attribute selectors are quoted\n        expr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n        // rbuggyMatches always contains :active, so no need for an existence check\n        if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && !rbuggyQSA.test( expr ) ) {\n          try {\n            var ret = matches.call( elem, expr );\n\n            // IE 9's matchesSelector returns false on disconnected nodes\n            if ( ret || disconnectedMatch ||\n                // As well, disconnected nodes are said to be in a document\n                // fragment in IE 9\n                elem.document && elem.document.nodeType !== 11 ) {\n              return ret;\n            }\n          } catch(e) {}\n        }\n\n        return Sizzle( expr, null, null, [ elem ] ).length > 0;\n      };\n    }\n  })();\n}\n\n// Deprecated\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Back-compat\nfunction setFilters() {}\nExpr.filters = setFilters.prototype = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})( window );\nvar runtil = /Until$/,\n  rparentsprev = /^(?:parents|prev(?:Until|All))/,\n  isSimple = /^.[^:#\\[\\.,]*$/,\n  rneedsContext = jQuery.expr.match.needsContext,\n  // methods guaranteed to produce a unique set when starting from a unique set\n  guaranteedUnique = {\n    children: true,\n    contents: true,\n    next: true,\n    prev: true\n  };\n\njQuery.fn.extend({\n  find: function( selector ) {\n    var i, l, length, n, r, ret,\n      self = this;\n\n    if ( typeof selector !== \"string\" ) {\n      return jQuery( selector ).filter(function() {\n        for ( i = 0, l = self.length; i < l; i++ ) {\n          if ( jQuery.contains( self[ i ], this ) ) {\n            return true;\n          }\n        }\n      });\n    }\n\n    ret = this.pushStack( \"\", \"find\", selector );\n\n    for ( i = 0, l = this.length; i < l; i++ ) {\n      length = ret.length;\n      jQuery.find( selector, this[i], ret );\n\n      if ( i > 0 ) {\n        // Make sure that the results are unique\n        for ( n = length; n < ret.length; n++ ) {\n          for ( r = 0; r < length; r++ ) {\n            if ( ret[r] === ret[n] ) {\n              ret.splice(n--, 1);\n              break;\n            }\n          }\n        }\n      }\n    }\n\n    return ret;\n  },\n\n  has: function( target ) {\n    var i,\n      targets = jQuery( target, this ),\n      len = targets.length;\n\n    return this.filter(function() {\n      for ( i = 0; i < len; i++ ) {\n        if ( jQuery.contains( this, targets[i] ) ) {\n          return true;\n        }\n      }\n    });\n  },\n\n  not: function( selector ) {\n    return this.pushStack( winnow(this, selector, false), \"not\", selector);\n  },\n\n  filter: function( selector ) {\n    return this.pushStack( winnow(this, selector, true), \"filter\", selector );\n  },\n\n  is: function( selector ) {\n    return !!selector && (\n      typeof selector === \"string\" ?\n        // If this is a positional/relative selector, check membership in the returned set\n        // so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n        rneedsContext.test( selector ) ?\n          jQuery( selector, this.context ).index( this[0] ) >= 0 :\n          jQuery.filter( selector, this ).length > 0 :\n        this.filter( selector ).length > 0 );\n  },\n\n  closest: function( selectors, context ) {\n    var cur,\n      i = 0,\n      l = this.length,\n      ret = [],\n      pos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n        jQuery( selectors, context || this.context ) :\n        0;\n\n    for ( ; i < l; i++ ) {\n      cur = this[i];\n\n      while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {\n        if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n          ret.push( cur );\n          break;\n        }\n        cur = cur.parentNode;\n      }\n    }\n\n    ret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n    return this.pushStack( ret, \"closest\", selectors );\n  },\n\n  // Determine the position of an element within\n  // the matched set of elements\n  index: function( elem ) {\n\n    // No argument, return index in parent\n    if ( !elem ) {\n      return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n    }\n\n    // index in selector\n    if ( typeof elem === \"string\" ) {\n      return jQuery.inArray( this[0], jQuery( elem ) );\n    }\n\n    // Locate the position of the desired element\n    return jQuery.inArray(\n      // If it receives a jQuery object, the first element is used\n      elem.jquery ? elem[0] : elem, this );\n  },\n\n  add: function( selector, context ) {\n    var set = typeof selector === \"string\" ?\n        jQuery( selector, context ) :\n        jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n      all = jQuery.merge( this.get(), set );\n\n    return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n      all :\n      jQuery.unique( all ) );\n  },\n\n  addBack: function( selector ) {\n    return this.add( selector == null ?\n      this.prevObject : this.prevObject.filter(selector)\n    );\n  }\n});\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n  return !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\nfunction sibling( cur, dir ) {\n  do {\n    cur = cur[ dir ];\n  } while ( cur && cur.nodeType !== 1 );\n\n  return cur;\n}\n\njQuery.each({\n  parent: function( elem ) {\n    var parent = elem.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n  parents: function( elem ) {\n    return jQuery.dir( elem, \"parentNode\" );\n  },\n  parentsUntil: function( elem, i, until ) {\n    return jQuery.dir( elem, \"parentNode\", until );\n  },\n  next: function( elem ) {\n    return sibling( elem, \"nextSibling\" );\n  },\n  prev: function( elem ) {\n    return sibling( elem, \"previousSibling\" );\n  },\n  nextAll: function( elem ) {\n    return jQuery.dir( elem, \"nextSibling\" );\n  },\n  prevAll: function( elem ) {\n    return jQuery.dir( elem, \"previousSibling\" );\n  },\n  nextUntil: function( elem, i, until ) {\n    return jQuery.dir( elem, \"nextSibling\", until );\n  },\n  prevUntil: function( elem, i, until ) {\n    return jQuery.dir( elem, \"previousSibling\", until );\n  },\n  siblings: function( elem ) {\n    return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n  },\n  children: function( elem ) {\n    return jQuery.sibling( elem.firstChild );\n  },\n  contents: function( elem ) {\n    return jQuery.nodeName( elem, \"iframe\" ) ?\n      elem.contentDocument || elem.contentWindow.document :\n      jQuery.merge( [], elem.childNodes );\n  }\n}, function( name, fn ) {\n  jQuery.fn[ name ] = function( until, selector ) {\n    var ret = jQuery.map( this, fn, until );\n\n    if ( !runtil.test( name ) ) {\n      selector = until;\n    }\n\n    if ( selector && typeof selector === \"string\" ) {\n      ret = jQuery.filter( selector, ret );\n    }\n\n    ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n    if ( this.length > 1 && rparentsprev.test( name ) ) {\n      ret = ret.reverse();\n    }\n\n    return this.pushStack( ret, name, core_slice.call( arguments ).join(\",\") );\n  };\n});\n\njQuery.extend({\n  filter: function( expr, elems, not ) {\n    if ( not ) {\n      expr = \":not(\" + expr + \")\";\n    }\n\n    return elems.length === 1 ?\n      jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n      jQuery.find.matches(expr, elems);\n  },\n\n  dir: function( elem, dir, until ) {\n    var matched = [],\n      cur = elem[ dir ];\n\n    while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n      if ( cur.nodeType === 1 ) {\n        matched.push( cur );\n      }\n      cur = cur[dir];\n    }\n    return matched;\n  },\n\n  sibling: function( n, elem ) {\n    var r = [];\n\n    for ( ; n; n = n.nextSibling ) {\n      if ( n.nodeType === 1 && n !== elem ) {\n        r.push( n );\n      }\n    }\n\n    return r;\n  }\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n  // Can't pass null or undefined to indexOf in Firefox 4\n  // Set to 0 to skip string check\n  qualifier = qualifier || 0;\n\n  if ( jQuery.isFunction( qualifier ) ) {\n    return jQuery.grep(elements, function( elem, i ) {\n      var retVal = !!qualifier.call( elem, i, elem );\n      return retVal === keep;\n    });\n\n  } else if ( qualifier.nodeType ) {\n    return jQuery.grep(elements, function( elem, i ) {\n      return ( elem === qualifier ) === keep;\n    });\n\n  } else if ( typeof qualifier === \"string\" ) {\n    var filtered = jQuery.grep(elements, function( elem ) {\n      return elem.nodeType === 1;\n    });\n\n    if ( isSimple.test( qualifier ) ) {\n      return jQuery.filter(qualifier, filtered, !keep);\n    } else {\n      qualifier = jQuery.filter( qualifier, filtered );\n    }\n  }\n\n  return jQuery.grep(elements, function( elem, i ) {\n    return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n  });\n}\nfunction createSafeFragment( document ) {\n  var list = nodeNames.split( \"|\" ),\n  safeFrag = document.createDocumentFragment();\n\n  if ( safeFrag.createElement ) {\n    while ( list.length ) {\n      safeFrag.createElement(\n        list.pop()\n      );\n    }\n  }\n  return safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n    \"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n  rinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n  rleadingWhitespace = /^\\s+/,\n  rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n  rtagName = /<([\\w:]+)/,\n  rtbody = /<tbody/i,\n  rhtml = /<|&#?\\w+;/,\n  rnoInnerhtml = /<(?:script|style|link)/i,\n  rnocache = /<(?:script|object|embed|option|style)/i,\n  rnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n  rcheckableType = /^(?:checkbox|radio)$/,\n  // checked=\"checked\" or checked\n  rchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n  rscriptType = /\\/(java|ecma)script/i,\n  rcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)|[\\]\\-]{2}>\\s*$/g,\n  wrapMap = {\n    option: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n    legend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n    thead: [ 1, \"<table>\", \"</table>\" ],\n    tr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n    td: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n    col: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n    area: [ 1, \"<map>\", \"</map>\" ],\n    _default: [ 0, \"\", \"\" ]\n  },\n  safeFragment = createSafeFragment( document ),\n  fragmentDiv = safeFragment.appendChild( document.createElement(\"div\") );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n// unless wrapped in a div with non-breaking characters in front of it.\nif ( !jQuery.support.htmlSerialize ) {\n  wrapMap._default = [ 1, \"X<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n  text: function( value ) {\n    return jQuery.access( this, function( value ) {\n      return value === undefined ?\n        jQuery.text( this ) :\n        this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n    }, null, value, arguments.length );\n  },\n\n  wrapAll: function( html ) {\n    if ( jQuery.isFunction( html ) ) {\n      return this.each(function(i) {\n        jQuery(this).wrapAll( html.call(this, i) );\n      });\n    }\n\n    if ( this[0] ) {\n      // The elements to wrap the target around\n      var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n      if ( this[0].parentNode ) {\n        wrap.insertBefore( this[0] );\n      }\n\n      wrap.map(function() {\n        var elem = this;\n\n        while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n          elem = elem.firstChild;\n        }\n\n        return elem;\n      }).append( this );\n    }\n\n    return this;\n  },\n\n  wrapInner: function( html ) {\n    if ( jQuery.isFunction( html ) ) {\n      return this.each(function(i) {\n        jQuery(this).wrapInner( html.call(this, i) );\n      });\n    }\n\n    return this.each(function() {\n      var self = jQuery( this ),\n        contents = self.contents();\n\n      if ( contents.length ) {\n        contents.wrapAll( html );\n\n      } else {\n        self.append( html );\n      }\n    });\n  },\n\n  wrap: function( html ) {\n    var isFunction = jQuery.isFunction( html );\n\n    return this.each(function(i) {\n      jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n    });\n  },\n\n  unwrap: function() {\n    return this.parent().each(function() {\n      if ( !jQuery.nodeName( this, \"body\" ) ) {\n        jQuery( this ).replaceWith( this.childNodes );\n      }\n    }).end();\n  },\n\n  append: function() {\n    return this.domManip(arguments, true, function( elem ) {\n      if ( this.nodeType === 1 || this.nodeType === 11 ) {\n        this.appendChild( elem );\n      }\n    });\n  },\n\n  prepend: function() {\n    return this.domManip(arguments, true, function( elem ) {\n      if ( this.nodeType === 1 || this.nodeType === 11 ) {\n        this.insertBefore( elem, this.firstChild );\n      }\n    });\n  },\n\n  before: function() {\n    if ( !isDisconnected( this[0] ) ) {\n      return this.domManip(arguments, false, function( elem ) {\n        this.parentNode.insertBefore( elem, this );\n      });\n    }\n\n    if ( arguments.length ) {\n      var set = jQuery.clean( arguments );\n      return this.pushStack( jQuery.merge( set, this ), \"before\", this.selector );\n    }\n  },\n\n  after: function() {\n    if ( !isDisconnected( this[0] ) ) {\n      return this.domManip(arguments, false, function( elem ) {\n        this.parentNode.insertBefore( elem, this.nextSibling );\n      });\n    }\n\n    if ( arguments.length ) {\n      var set = jQuery.clean( arguments );\n      return this.pushStack( jQuery.merge( this, set ), \"after\", this.selector );\n    }\n  },\n\n  // keepData is for internal use only--do not document\n  remove: function( selector, keepData ) {\n    var elem,\n      i = 0;\n\n    for ( ; (elem = this[i]) != null; i++ ) {\n      if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n        if ( !keepData && elem.nodeType === 1 ) {\n          jQuery.cleanData( elem.getElementsByTagName(\"*\") );\n          jQuery.cleanData( [ elem ] );\n        }\n\n        if ( elem.parentNode ) {\n          elem.parentNode.removeChild( elem );\n        }\n      }\n    }\n\n    return this;\n  },\n\n  empty: function() {\n    var elem,\n      i = 0;\n\n    for ( ; (elem = this[i]) != null; i++ ) {\n      // Remove element nodes and prevent memory leaks\n      if ( elem.nodeType === 1 ) {\n        jQuery.cleanData( elem.getElementsByTagName(\"*\") );\n      }\n\n      // Remove any remaining nodes\n      while ( elem.firstChild ) {\n        elem.removeChild( elem.firstChild );\n      }\n    }\n\n    return this;\n  },\n\n  clone: function( dataAndEvents, deepDataAndEvents ) {\n    dataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n    deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n    return this.map( function () {\n      return jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n    });\n  },\n\n  html: function( value ) {\n    return jQuery.access( this, function( value ) {\n      var elem = this[0] || {},\n        i = 0,\n        l = this.length;\n\n      if ( value === undefined ) {\n        return elem.nodeType === 1 ?\n          elem.innerHTML.replace( rinlinejQuery, \"\" ) :\n          undefined;\n      }\n\n      // See if we can take a shortcut and just use innerHTML\n      if ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n        ( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n        ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n        !wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n        value = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n        try {\n          for (; i < l; i++ ) {\n            // Remove element nodes and prevent memory leaks\n            elem = this[i] || {};\n            if ( elem.nodeType === 1 ) {\n              jQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n              elem.innerHTML = value;\n            }\n          }\n\n          elem = 0;\n\n        // If using innerHTML throws an exception, use the fallback method\n        } catch(e) {}\n      }\n\n      if ( elem ) {\n        this.empty().append( value );\n      }\n    }, null, value, arguments.length );\n  },\n\n  replaceWith: function( value ) {\n    if ( !isDisconnected( this[0] ) ) {\n      // Make sure that the elements are removed from the DOM before they are inserted\n      // this can help fix replacing a parent with child elements\n      if ( jQuery.isFunction( value ) ) {\n        return this.each(function(i) {\n          var self = jQuery(this), old = self.html();\n          self.replaceWith( value.call( this, i, old ) );\n        });\n      }\n\n      if ( typeof value !== \"string\" ) {\n        value = jQuery( value ).detach();\n      }\n\n      return this.each(function() {\n        var next = this.nextSibling,\n          parent = this.parentNode;\n\n        jQuery( this ).remove();\n\n        if ( next ) {\n          jQuery(next).before( value );\n        } else {\n          jQuery(parent).append( value );\n        }\n      });\n    }\n\n    return this.length ?\n      this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n      this;\n  },\n\n  detach: function( selector ) {\n    return this.remove( selector, true );\n  },\n\n  domManip: function( args, table, callback ) {\n\n    // Flatten any nested arrays\n    args = [].concat.apply( [], args );\n\n    var results, first, fragment, iNoClone,\n      i = 0,\n      value = args[0],\n      scripts = [],\n      l = this.length;\n\n    // We can't cloneNode fragments that contain checked, in WebKit\n    if ( !jQuery.support.checkClone && l > 1 && typeof value === \"string\" && rchecked.test( value ) ) {\n      return this.each(function() {\n        jQuery(this).domManip( args, table, callback );\n      });\n    }\n\n    if ( jQuery.isFunction(value) ) {\n      return this.each(function(i) {\n        var self = jQuery(this);\n        args[0] = value.call( this, i, table ? self.html() : undefined );\n        self.domManip( args, table, callback );\n      });\n    }\n\n    if ( this[0] ) {\n      results = jQuery.buildFragment( args, this, scripts );\n      fragment = results.fragment;\n      first = fragment.firstChild;\n\n      if ( fragment.childNodes.length === 1 ) {\n        fragment = first;\n      }\n\n      if ( first ) {\n        table = table && jQuery.nodeName( first, \"tr\" );\n\n        // Use the original fragment for the last item instead of the first because it can end up\n        // being emptied incorrectly in certain situations (#8070).\n        // Fragments from the fragment cache must always be cloned and never used in place.\n        for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {\n          callback.call(\n            table && jQuery.nodeName( this[i], \"table\" ) ?\n              findOrAppend( this[i], \"tbody\" ) :\n              this[i],\n            i === iNoClone ?\n              fragment :\n              jQuery.clone( fragment, true, true )\n          );\n        }\n      }\n\n      // Fix #11809: Avoid leaking memory\n      fragment = first = null;\n\n      if ( scripts.length ) {\n        jQuery.each( scripts, function( i, elem ) {\n          if ( elem.src ) {\n            if ( jQuery.ajax ) {\n              jQuery.ajax({\n                url: elem.src,\n                type: \"GET\",\n                dataType: \"script\",\n                async: false,\n                global: false,\n                \"throws\": true\n              });\n            } else {\n              jQuery.error(\"no ajax\");\n            }\n          } else {\n            jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"\" ) );\n          }\n\n          if ( elem.parentNode ) {\n            elem.parentNode.removeChild( elem );\n          }\n        });\n      }\n    }\n\n    return this;\n  }\n});\n\nfunction findOrAppend( elem, tag ) {\n  return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n  if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n    return;\n  }\n\n  var type, i, l,\n    oldData = jQuery._data( src ),\n    curData = jQuery._data( dest, oldData ),\n    events = oldData.events;\n\n  if ( events ) {\n    delete curData.handle;\n    curData.events = {};\n\n    for ( type in events ) {\n      for ( i = 0, l = events[ type ].length; i < l; i++ ) {\n        jQuery.event.add( dest, type, events[ type ][ i ] );\n      }\n    }\n  }\n\n  // make the cloned public data object a copy from the original\n  if ( curData.data ) {\n    curData.data = jQuery.extend( {}, curData.data );\n  }\n}\n\nfunction cloneFixAttributes( src, dest ) {\n  var nodeName;\n\n  // We do not need to do anything for non-Elements\n  if ( dest.nodeType !== 1 ) {\n    return;\n  }\n\n  // clearAttributes removes the attributes, which we don't want,\n  // but also removes the attachEvent events, which we *do* want\n  if ( dest.clearAttributes ) {\n    dest.clearAttributes();\n  }\n\n  // mergeAttributes, in contrast, only merges back on the\n  // original attributes, not the events\n  if ( dest.mergeAttributes ) {\n    dest.mergeAttributes( src );\n  }\n\n  nodeName = dest.nodeName.toLowerCase();\n\n  if ( nodeName === \"object\" ) {\n    // IE6-10 improperly clones children of object elements using classid.\n    // IE10 throws NoModificationAllowedError if parent is null, #12132.\n    if ( dest.parentNode ) {\n      dest.outerHTML = src.outerHTML;\n    }\n\n    // This path appears unavoidable for IE9. When cloning an object\n    // element in IE9, the outerHTML strategy above is not sufficient.\n    // If the src has innerHTML and the destination does not,\n    // copy the src.innerHTML into the dest.innerHTML. #10324\n    if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {\n      dest.innerHTML = src.innerHTML;\n    }\n\n  } else if ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n    // IE6-8 fails to persist the checked state of a cloned checkbox\n    // or radio button. Worse, IE6-7 fail to give the cloned element\n    // a checked appearance if the defaultChecked value isn't also set\n\n    dest.defaultChecked = dest.checked = src.checked;\n\n    // IE6-7 get confused and end up setting the value of a cloned\n    // checkbox/radio button to an empty string instead of \"on\"\n    if ( dest.value !== src.value ) {\n      dest.value = src.value;\n    }\n\n  // IE6-8 fails to return the selected option to the default selected\n  // state when cloning options\n  } else if ( nodeName === \"option\" ) {\n    dest.selected = src.defaultSelected;\n\n  // IE6-8 fails to set the defaultValue to the correct value when\n  // cloning other types of input fields\n  } else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n    dest.defaultValue = src.defaultValue;\n\n  // IE blanks contents when cloning scripts\n  } else if ( nodeName === \"script\" && dest.text !== src.text ) {\n    dest.text = src.text;\n  }\n\n  // Event data gets referenced instead of copied if the expando\n  // gets copied too\n  dest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, context, scripts ) {\n  var fragment, cacheable, cachehit,\n    first = args[ 0 ];\n\n  // Set context from what may come in as undefined or a jQuery collection or a node\n  // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 &\n  // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception\n  context = context || document;\n  context = !context.nodeType && context[0] || context;\n  context = context.ownerDocument || context;\n\n  // Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n  // Cloning options loses the selected state, so don't cache them\n  // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n  // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n  // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n  if ( args.length === 1 && typeof first === \"string\" && first.length < 512 && context === document &&\n    first.charAt(0) === \"<\" && !rnocache.test( first ) &&\n    (jQuery.support.checkClone || !rchecked.test( first )) &&\n    (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n    // Mark cacheable and look for a hit\n    cacheable = true;\n    fragment = jQuery.fragments[ first ];\n    cachehit = fragment !== undefined;\n  }\n\n  if ( !fragment ) {\n    fragment = context.createDocumentFragment();\n    jQuery.clean( args, context, fragment, scripts );\n\n    // Update the cache, but only store false\n    // unless this is a second parsing of the same content\n    if ( cacheable ) {\n      jQuery.fragments[ first ] = cachehit && fragment;\n    }\n  }\n\n  return { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n  appendTo: \"append\",\n  prependTo: \"prepend\",\n  insertBefore: \"before\",\n  insertAfter: \"after\",\n  replaceAll: \"replaceWith\"\n}, function( name, original ) {\n  jQuery.fn[ name ] = function( selector ) {\n    var elems,\n      i = 0,\n      ret = [],\n      insert = jQuery( selector ),\n      l = insert.length,\n      parent = this.length === 1 && this[0].parentNode;\n\n    if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {\n      insert[ original ]( this[0] );\n      return this;\n    } else {\n      for ( ; i < l; i++ ) {\n        elems = ( i > 0 ? this.clone(true) : this ).get();\n        jQuery( insert[i] )[ original ]( elems );\n        ret = ret.concat( elems );\n      }\n\n      return this.pushStack( ret, name, insert.selector );\n    }\n  };\n});\n\nfunction getAll( elem ) {\n  if ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n    return elem.getElementsByTagName( \"*\" );\n\n  } else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n    return elem.querySelectorAll( \"*\" );\n\n  } else {\n    return [];\n  }\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n  if ( rcheckableType.test( elem.type ) ) {\n    elem.defaultChecked = elem.checked;\n  }\n}\n\njQuery.extend({\n  clone: function( elem, dataAndEvents, deepDataAndEvents ) {\n    var srcElements,\n      destElements,\n      i,\n      clone;\n\n    if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n      clone = elem.cloneNode( true );\n\n    // IE<=8 does not properly clone detached, unknown element nodes\n    } else {\n      fragmentDiv.innerHTML = elem.outerHTML;\n      fragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n    }\n\n    if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n        (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n      // IE copies events bound via attachEvent when using cloneNode.\n      // Calling detachEvent on the clone will also remove the events\n      // from the original. In order to get around this, we use some\n      // proprietary methods to clear the events. Thanks to MooTools\n      // guys for this hotness.\n\n      cloneFixAttributes( elem, clone );\n\n      // Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n      srcElements = getAll( elem );\n      destElements = getAll( clone );\n\n      // Weird iteration because IE will replace the length property\n      // with an element if you are cloning the body and one of the\n      // elements on the page has a name or id of \"length\"\n      for ( i = 0; srcElements[i]; ++i ) {\n        // Ensure that the destination node is not null; Fixes #9587\n        if ( destElements[i] ) {\n          cloneFixAttributes( srcElements[i], destElements[i] );\n        }\n      }\n    }\n\n    // Copy the events from the original to the clone\n    if ( dataAndEvents ) {\n      cloneCopyEvent( elem, clone );\n\n      if ( deepDataAndEvents ) {\n        srcElements = getAll( elem );\n        destElements = getAll( clone );\n\n        for ( i = 0; srcElements[i]; ++i ) {\n          cloneCopyEvent( srcElements[i], destElements[i] );\n        }\n      }\n    }\n\n    srcElements = destElements = null;\n\n    // Return the cloned set\n    return clone;\n  },\n\n  clean: function( elems, context, fragment, scripts ) {\n    var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,\n      safe = context === document && safeFragment,\n      ret = [];\n\n    // Ensure that context is a document\n    if ( !context || typeof context.createDocumentFragment === \"undefined\" ) {\n      context = document;\n    }\n\n    // Use the already-created safe fragment if context permits\n    for ( i = 0; (elem = elems[i]) != null; i++ ) {\n      if ( typeof elem === \"number\" ) {\n        elem += \"\";\n      }\n\n      if ( !elem ) {\n        continue;\n      }\n\n      // Convert html string into DOM nodes\n      if ( typeof elem === \"string\" ) {\n        if ( !rhtml.test( elem ) ) {\n          elem = context.createTextNode( elem );\n        } else {\n          // Ensure a safe container in which to render the html\n          safe = safe || createSafeFragment( context );\n          div = context.createElement(\"div\");\n          safe.appendChild( div );\n\n          // Fix \"XHTML\"-style tags in all browsers\n          elem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n          // Go to html and back, then peel off extra wrappers\n          tag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase();\n          wrap = wrapMap[ tag ] || wrapMap._default;\n          depth = wrap[0];\n          div.innerHTML = wrap[1] + elem + wrap[2];\n\n          // Move to the right depth\n          while ( depth-- ) {\n            div = div.lastChild;\n          }\n\n          // Remove IE's autoinserted <tbody> from table fragments\n          if ( !jQuery.support.tbody ) {\n\n            // String was a <table>, *may* have spurious <tbody>\n            hasBody = rtbody.test(elem);\n              tbody = tag === \"table\" && !hasBody ?\n                div.firstChild && div.firstChild.childNodes :\n\n                // String was a bare <thead> or <tfoot>\n                wrap[1] === \"<table>\" && !hasBody ?\n                  div.childNodes :\n                  [];\n\n            for ( j = tbody.length - 1; j >= 0 ; --j ) {\n              if ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n                tbody[ j ].parentNode.removeChild( tbody[ j ] );\n              }\n            }\n          }\n\n          // IE completely kills leading whitespace when innerHTML is used\n          if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n            div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n          }\n\n          elem = div.childNodes;\n\n          // Take out of fragment container (we need a fresh div each time)\n          div.parentNode.removeChild( div );\n        }\n      }\n\n      if ( elem.nodeType ) {\n        ret.push( elem );\n      } else {\n        jQuery.merge( ret, elem );\n      }\n    }\n\n    // Fix #11356: Clear elements from safeFragment\n    if ( div ) {\n      elem = div = safe = null;\n    }\n\n    // Reset defaultChecked for any radios and checkboxes\n    // about to be appended to the DOM in IE 6/7 (#8060)\n    if ( !jQuery.support.appendChecked ) {\n      for ( i = 0; (elem = ret[i]) != null; i++ ) {\n        if ( jQuery.nodeName( elem, \"input\" ) ) {\n          fixDefaultChecked( elem );\n        } else if ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n          jQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n        }\n      }\n    }\n\n    // Append elements to a provided document fragment\n    if ( fragment ) {\n      // Special handling of each script element\n      handleScript = function( elem ) {\n        // Check if we consider it executable\n        if ( !elem.type || rscriptType.test( elem.type ) ) {\n          // Detach the script and store it in the scripts array (if provided) or the fragment\n          // Return truthy to indicate that it has been handled\n          return scripts ?\n            scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :\n            fragment.appendChild( elem );\n        }\n      };\n\n      for ( i = 0; (elem = ret[i]) != null; i++ ) {\n        // Check if we're done after handling an executable script\n        if ( !( jQuery.nodeName( elem, \"script\" ) && handleScript( elem ) ) ) {\n          // Append to fragment and handle embedded scripts\n          fragment.appendChild( elem );\n          if ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n            // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration\n            jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName(\"script\") ), handleScript );\n\n            // Splice the scripts into ret after their former ancestor and advance our index beyond them\n            ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n            i += jsTags.length;\n          }\n        }\n      }\n    }\n\n    return ret;\n  },\n\n  cleanData: function( elems, /* internal */ acceptData ) {\n    var data, id, elem, type,\n      i = 0,\n      internalKey = jQuery.expando,\n      cache = jQuery.cache,\n      deleteExpando = jQuery.support.deleteExpando,\n      special = jQuery.event.special;\n\n    for ( ; (elem = elems[i]) != null; i++ ) {\n\n      if ( acceptData || jQuery.acceptData( elem ) ) {\n\n        id = elem[ internalKey ];\n        data = id && cache[ id ];\n\n        if ( data ) {\n          if ( data.events ) {\n            for ( type in data.events ) {\n              if ( special[ type ] ) {\n                jQuery.event.remove( elem, type );\n\n              // This is a shortcut to avoid jQuery.event.remove's overhead\n              } else {\n                jQuery.removeEvent( elem, type, data.handle );\n              }\n            }\n          }\n\n          // Remove cache only if it was not already removed by jQuery.event.remove\n          if ( cache[ id ] ) {\n\n            delete cache[ id ];\n\n            // IE does not allow us to delete expando properties from nodes,\n            // nor does it have a removeAttribute function on Document nodes;\n            // we must handle all of these cases\n            if ( deleteExpando ) {\n              delete elem[ internalKey ];\n\n            } else if ( elem.removeAttribute ) {\n              elem.removeAttribute( internalKey );\n\n            } else {\n              elem[ internalKey ] = null;\n            }\n\n            jQuery.deletedIds.push( id );\n          }\n        }\n      }\n    }\n  }\n});\n// Limit scope pollution from any deprecated API\n(function() {\n\nvar matched, browser;\n\n// Use of jQuery.browser is frowned upon.\n// More details: http://api.jquery.com/jQuery.browser\n// jQuery.uaMatch maintained for back-compat\njQuery.uaMatch = function( ua ) {\n  ua = ua.toLowerCase();\n\n  var match = /(chrome)[ \\/]([\\w.]+)/.exec( ua ) ||\n    /(webkit)[ \\/]([\\w.]+)/.exec( ua ) ||\n    /(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec( ua ) ||\n    /(msie) ([\\w.]+)/.exec( ua ) ||\n    ua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec( ua ) ||\n    [];\n\n  return {\n    browser: match[ 1 ] || \"\",\n    version: match[ 2 ] || \"0\"\n  };\n};\n\nmatched = jQuery.uaMatch( navigator.userAgent );\nbrowser = {};\n\nif ( matched.browser ) {\n  browser[ matched.browser ] = true;\n  browser.version = matched.version;\n}\n\n// Chrome is Webkit, but Webkit is also Safari.\nif ( browser.chrome ) {\n  browser.webkit = true;\n} else if ( browser.webkit ) {\n  browser.safari = true;\n}\n\njQuery.browser = browser;\n\njQuery.sub = function() {\n  function jQuerySub( selector, context ) {\n    return new jQuerySub.fn.init( selector, context );\n  }\n  jQuery.extend( true, jQuerySub, this );\n  jQuerySub.superclass = this;\n  jQuerySub.fn = jQuerySub.prototype = this();\n  jQuerySub.fn.constructor = jQuerySub;\n  jQuerySub.sub = this.sub;\n  jQuerySub.fn.init = function init( selector, context ) {\n    if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n      context = jQuerySub( context );\n    }\n\n    return jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n  };\n  jQuerySub.fn.init.prototype = jQuerySub.fn;\n  var rootjQuerySub = jQuerySub(document);\n  return jQuerySub;\n};\n\n})();\nvar curCSS, iframe, iframeDoc,\n  ralpha = /alpha\\([^)]*\\)/i,\n  ropacity = /opacity=([^)]*)/,\n  rposition = /^(top|right|bottom|left)$/,\n  // swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n  // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n  rdisplayswap = /^(none|table(?!-c[ea]).+)/,\n  rmargin = /^margin/,\n  rnumsplit = new RegExp( \"^(\" + core_pnum + \")(.*)$\", \"i\" ),\n  rnumnonpx = new RegExp( \"^(\" + core_pnum + \")(?!px)[a-z%]+$\", \"i\" ),\n  rrelNum = new RegExp( \"^([-+])=(\" + core_pnum + \")\", \"i\" ),\n  elemdisplay = { BODY: \"block\" },\n\n  cssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n  cssNormalTransform = {\n    letterSpacing: 0,\n    fontWeight: 400\n  },\n\n  cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n  cssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ],\n\n  eventsToggle = jQuery.fn.toggle;\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n  // shortcut for names that are not vendor prefixed\n  if ( name in style ) {\n    return name;\n  }\n\n  // check for vendor prefixed names\n  var capName = name.charAt(0).toUpperCase() + name.slice(1),\n    origName = name,\n    i = cssPrefixes.length;\n\n  while ( i-- ) {\n    name = cssPrefixes[ i ] + capName;\n    if ( name in style ) {\n      return name;\n    }\n  }\n\n  return origName;\n}\n\nfunction isHidden( elem, el ) {\n  elem = el || elem;\n  return jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n}\n\nfunction showHide( elements, show ) {\n  var elem, display,\n    values = [],\n    index = 0,\n    length = elements.length;\n\n  for ( ; index < length; index++ ) {\n    elem = elements[ index ];\n    if ( !elem.style ) {\n      continue;\n    }\n    values[ index ] = jQuery._data( elem, \"olddisplay\" );\n    if ( show ) {\n      // Reset the inline display of this element to learn if it is\n      // being hidden by cascaded rules or not\n      if ( !values[ index ] && elem.style.display === \"none\" ) {\n        elem.style.display = \"\";\n      }\n\n      // Set elements which have been overridden with display: none\n      // in a stylesheet to whatever the default browser style is\n      // for such an element\n      if ( elem.style.display === \"\" && isHidden( elem ) ) {\n        values[ index ] = jQuery._data( elem, \"olddisplay\", css_defaultDisplay(elem.nodeName) );\n      }\n    } else {\n      display = curCSS( elem, \"display\" );\n\n      if ( !values[ index ] && display !== \"none\" ) {\n        jQuery._data( elem, \"olddisplay\", display );\n      }\n    }\n  }\n\n  // Set the display of most of the elements in a second loop\n  // to avoid the constant reflow\n  for ( index = 0; index < length; index++ ) {\n    elem = elements[ index ];\n    if ( !elem.style ) {\n      continue;\n    }\n    if ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n      elem.style.display = show ? values[ index ] || \"\" : \"none\";\n    }\n  }\n\n  return elements;\n}\n\njQuery.fn.extend({\n  css: function( name, value ) {\n    return jQuery.access( this, function( elem, name, value ) {\n      return value !== undefined ?\n        jQuery.style( elem, name, value ) :\n        jQuery.css( elem, name );\n    }, name, value, arguments.length > 1 );\n  },\n  show: function() {\n    return showHide( this, true );\n  },\n  hide: function() {\n    return showHide( this );\n  },\n  toggle: function( state, fn2 ) {\n    var bool = typeof state === \"boolean\";\n\n    if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {\n      return eventsToggle.apply( this, arguments );\n    }\n\n    return this.each(function() {\n      if ( bool ? state : isHidden( this ) ) {\n        jQuery( this ).show();\n      } else {\n        jQuery( this ).hide();\n      }\n    });\n  }\n});\n\njQuery.extend({\n  // Add in style property hooks for overriding the default\n  // behavior of getting and setting a style property\n  cssHooks: {\n    opacity: {\n      get: function( elem, computed ) {\n        if ( computed ) {\n          // We should always get a number back from opacity\n          var ret = curCSS( elem, \"opacity\" );\n          return ret === \"\" ? \"1\" : ret;\n\n        }\n      }\n    }\n  },\n\n  // Exclude the following css properties to add px\n  cssNumber: {\n    \"fillOpacity\": true,\n    \"fontWeight\": true,\n    \"lineHeight\": true,\n    \"opacity\": true,\n    \"orphans\": true,\n    \"widows\": true,\n    \"zIndex\": true,\n    \"zoom\": true\n  },\n\n  // Add in properties whose names you wish to fix before\n  // setting or getting the value\n  cssProps: {\n    // normalize float css property\n    \"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n  },\n\n  // Get and set the style property on a DOM Node\n  style: function( elem, name, value, extra ) {\n    // Don't set styles on text and comment nodes\n    if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n      return;\n    }\n\n    // Make sure that we're working with the right name\n    var ret, type, hooks,\n      origName = jQuery.camelCase( name ),\n      style = elem.style;\n\n    name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n    // gets hook for the prefixed version\n    // followed by the unprefixed version\n    hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n    // Check if we're setting a value\n    if ( value !== undefined ) {\n      type = typeof value;\n\n      // convert relative number strings (+= or -=) to relative numbers. #7345\n      if ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n        value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n        // Fixes bug #9237\n        type = \"number\";\n      }\n\n      // Make sure that NaN and null values aren't set. See: #7116\n      if ( value == null || type === \"number\" && isNaN( value ) ) {\n        return;\n      }\n\n      // If a number was passed in, add 'px' to the (except for certain CSS properties)\n      if ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n        value += \"px\";\n      }\n\n      // If a hook was provided, use that value, otherwise just set the specified value\n      if ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n        // Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n        // Fixes bug #5509\n        try {\n          style[ name ] = value;\n        } catch(e) {}\n      }\n\n    } else {\n      // If a hook was provided get the non-computed value from there\n      if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n        return ret;\n      }\n\n      // Otherwise just get the value from the style object\n      return style[ name ];\n    }\n  },\n\n  css: function( elem, name, numeric, extra ) {\n    var val, num, hooks,\n      origName = jQuery.camelCase( name );\n\n    // Make sure that we're working with the right name\n    name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n    // gets hook for the prefixed version\n    // followed by the unprefixed version\n    hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n    // If a hook was provided get the computed value from there\n    if ( hooks && \"get\" in hooks ) {\n      val = hooks.get( elem, true, extra );\n    }\n\n    // Otherwise, if a way to get the computed value exists, use that\n    if ( val === undefined ) {\n      val = curCSS( elem, name );\n    }\n\n    //convert \"normal\" to computed value\n    if ( val === \"normal\" && name in cssNormalTransform ) {\n      val = cssNormalTransform[ name ];\n    }\n\n    // Return, converting to number if forced or a qualifier was provided and val looks numeric\n    if ( numeric || extra !== undefined ) {\n      num = parseFloat( val );\n      return numeric || jQuery.isNumeric( num ) ? num || 0 : val;\n    }\n    return val;\n  },\n\n  // A method for quickly swapping in/out CSS properties to get correct calculations\n  swap: function( elem, options, callback ) {\n    var ret, name,\n      old = {};\n\n    // Remember the old values, and insert the new ones\n    for ( name in options ) {\n      old[ name ] = elem.style[ name ];\n      elem.style[ name ] = options[ name ];\n    }\n\n    ret = callback.call( elem );\n\n    // Revert the old values\n    for ( name in options ) {\n      elem.style[ name ] = old[ name ];\n    }\n\n    return ret;\n  }\n});\n\n// NOTE: To any future maintainer, we've window.getComputedStyle\n// because jsdom on node.js will break without it.\nif ( window.getComputedStyle ) {\n  curCSS = function( elem, name ) {\n    var ret, width, minWidth, maxWidth,\n      computed = window.getComputedStyle( elem, null ),\n      style = elem.style;\n\n    if ( computed ) {\n\n      // getPropertyValue is only needed for .css('filter') in IE9, see #12537\n      ret = computed.getPropertyValue( name ) || computed[ name ];\n\n      if ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n        ret = jQuery.style( elem, name );\n      }\n\n      // A tribute to the \"awesome hack by Dean Edwards\"\n      // Chrome < 17 and Safari 5.0 uses \"computed value\" instead of \"used value\" for margin-right\n      // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n      // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n      if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n        width = style.width;\n        minWidth = style.minWidth;\n        maxWidth = style.maxWidth;\n\n        style.minWidth = style.maxWidth = style.width = ret;\n        ret = computed.width;\n\n        style.width = width;\n        style.minWidth = minWidth;\n        style.maxWidth = maxWidth;\n      }\n    }\n\n    return ret;\n  };\n} else if ( document.documentElement.currentStyle ) {\n  curCSS = function( elem, name ) {\n    var left, rsLeft,\n      ret = elem.currentStyle && elem.currentStyle[ name ],\n      style = elem.style;\n\n    // Avoid setting ret to empty string here\n    // so we don't default to auto\n    if ( ret == null && style && style[ name ] ) {\n      ret = style[ name ];\n    }\n\n    // From the awesome hack by Dean Edwards\n    // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n    // If we're not dealing with a regular pixel number\n    // but a number that has a weird ending, we need to convert it to pixels\n    // but not position css attributes, as those are proportional to the parent element instead\n    // and we can't measure the parent instead because it might trigger a \"stacking dolls\" problem\n    if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n      // Remember the original values\n      left = style.left;\n      rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n      // Put in the new values to get a computed value out\n      if ( rsLeft ) {\n        elem.runtimeStyle.left = elem.currentStyle.left;\n      }\n      style.left = name === \"fontSize\" ? \"1em\" : ret;\n      ret = style.pixelLeft + \"px\";\n\n      // Revert the changed values\n      style.left = left;\n      if ( rsLeft ) {\n        elem.runtimeStyle.left = rsLeft;\n      }\n    }\n\n    return ret === \"\" ? \"auto\" : ret;\n  };\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n  var matches = rnumsplit.exec( value );\n  return matches ?\n      Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n      value;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox ) {\n  var i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n    // If we already have the right measurement, avoid augmentation\n    4 :\n    // Otherwise initialize for horizontal or vertical properties\n    name === \"width\" ? 1 : 0,\n\n    val = 0;\n\n  for ( ; i < 4; i += 2 ) {\n    // both box models exclude margin, so add it if we want it\n    if ( extra === \"margin\" ) {\n      // we use jQuery.css instead of curCSS here\n      // because of the reliableMarginRight CSS hook!\n      val += jQuery.css( elem, extra + cssExpand[ i ], true );\n    }\n\n    // From this point on we use curCSS for maximum performance (relevant in animations)\n    if ( isBorderBox ) {\n      // border-box includes padding, so remove it if we want content\n      if ( extra === \"content\" ) {\n        val -= parseFloat( curCSS( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n      }\n\n      // at this point, extra isn't border nor margin, so remove border\n      if ( extra !== \"margin\" ) {\n        val -= parseFloat( curCSS( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n      }\n    } else {\n      // at this point, extra isn't content, so add padding\n      val += parseFloat( curCSS( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\n      // at this point, extra isn't content nor padding, so add border\n      if ( extra !== \"padding\" ) {\n        val += parseFloat( curCSS( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n      }\n    }\n  }\n\n  return val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n  // Start with offset property, which is equivalent to the border-box value\n  var val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n    valueIsBorderBox = true,\n    isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\" ) === \"border-box\";\n\n  // some non-html elements return undefined for offsetWidth, so check for null/undefined\n  // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n  // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n  if ( val <= 0 || val == null ) {\n    // Fall back to computed then uncomputed css if necessary\n    val = curCSS( elem, name );\n    if ( val < 0 || val == null ) {\n      val = elem.style[ name ];\n    }\n\n    // Computed unit is not pixels. Stop here and return.\n    if ( rnumnonpx.test(val) ) {\n      return val;\n    }\n\n    // we need the check for style in case a browser which returns unreliable values\n    // for getComputedStyle silently falls back to the reliable elem.style\n    valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );\n\n    // Normalize \"\", auto, and prepare for extra\n    val = parseFloat( val ) || 0;\n  }\n\n  // use the active box-sizing model to add/subtract irrelevant styles\n  return ( val +\n    augmentWidthOrHeight(\n      elem,\n      name,\n      extra || ( isBorderBox ? \"border\" : \"content\" ),\n      valueIsBorderBox\n    )\n  ) + \"px\";\n}\n\n\n// Try to determine the default display value of an element\nfunction css_defaultDisplay( nodeName ) {\n  if ( elemdisplay[ nodeName ] ) {\n    return elemdisplay[ nodeName ];\n  }\n\n  var elem = jQuery( \"<\" + nodeName + \">\" ).appendTo( document.body ),\n    display = elem.css(\"display\");\n  elem.remove();\n\n  // If the simple way fails,\n  // get element's real default display by attaching it to a temp iframe\n  if ( display === \"none\" || display === \"\" ) {\n    // Use the already-created iframe if possible\n    iframe = document.body.appendChild(\n      iframe || jQuery.extend( document.createElement(\"iframe\"), {\n        frameBorder: 0,\n        width: 0,\n        height: 0\n      })\n    );\n\n    // Create a cacheable copy of the iframe document on first call.\n    // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n    // document to it; WebKit & Firefox won't allow reusing the iframe document.\n    if ( !iframeDoc || !iframe.createElement ) {\n      iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n      iframeDoc.write(\"<!doctype html><html><body>\");\n      iframeDoc.close();\n    }\n\n    elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );\n\n    display = curCSS( elem, \"display\" );\n    document.body.removeChild( iframe );\n  }\n\n  // Store the correct default display\n  elemdisplay[ nodeName ] = display;\n\n  return display;\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n  jQuery.cssHooks[ name ] = {\n    get: function( elem, computed, extra ) {\n      if ( computed ) {\n        // certain elements can have dimension info if we invisibly show them\n        // however, it must have a current display style that would benefit from this\n        if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, \"display\" ) ) ) {\n          return jQuery.swap( elem, cssShow, function() {\n            return getWidthOrHeight( elem, name, extra );\n          });\n        } else {\n          return getWidthOrHeight( elem, name, extra );\n        }\n      }\n    },\n\n    set: function( elem, value, extra ) {\n      return setPositiveNumber( elem, value, extra ?\n        augmentWidthOrHeight(\n          elem,\n          name,\n          extra,\n          jQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\" ) === \"border-box\"\n        ) : 0\n      );\n    }\n  };\n});\n\nif ( !jQuery.support.opacity ) {\n  jQuery.cssHooks.opacity = {\n    get: function( elem, computed ) {\n      // IE uses filters for opacity\n      return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n        ( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n        computed ? \"1\" : \"\";\n    },\n\n    set: function( elem, value ) {\n      var style = elem.style,\n        currentStyle = elem.currentStyle,\n        opacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n        filter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n      // IE has trouble with opacity if it does not have layout\n      // Force it by setting the zoom level\n      style.zoom = 1;\n\n      // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n      if ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n        style.removeAttribute ) {\n\n        // Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n        // if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n        // style.removeAttribute is IE Only, but so apparently is this code path...\n        style.removeAttribute( \"filter\" );\n\n        // if there there is no filter style applied in a css rule, we are done\n        if ( currentStyle && !currentStyle.filter ) {\n          return;\n        }\n      }\n\n      // otherwise, set new filter values\n      style.filter = ralpha.test( filter ) ?\n        filter.replace( ralpha, opacity ) :\n        filter + \" \" + opacity;\n    }\n  };\n}\n\n// These hooks cannot be added until DOM ready because the support test\n// for it is not run until after DOM ready\njQuery(function() {\n  if ( !jQuery.support.reliableMarginRight ) {\n    jQuery.cssHooks.marginRight = {\n      get: function( elem, computed ) {\n        // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n        // Work around by temporarily setting element display to inline-block\n        return jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n          if ( computed ) {\n            return curCSS( elem, \"marginRight\" );\n          }\n        });\n      }\n    };\n  }\n\n  // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n  // getComputedStyle returns percent when specified for top/left/bottom/right\n  // rather than make the css module depend on the offset module, we just check for it here\n  if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {\n    jQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n      jQuery.cssHooks[ prop ] = {\n        get: function( elem, computed ) {\n          if ( computed ) {\n            var ret = curCSS( elem, prop );\n            // if curCSS returns percentage, fallback to offset\n            return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + \"px\" : ret;\n          }\n        }\n      };\n    });\n  }\n\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n  jQuery.expr.filters.hidden = function( elem ) {\n    return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, \"display\" )) === \"none\");\n  };\n\n  jQuery.expr.filters.visible = function( elem ) {\n    return !jQuery.expr.filters.hidden( elem );\n  };\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n  margin: \"\",\n  padding: \"\",\n  border: \"Width\"\n}, function( prefix, suffix ) {\n  jQuery.cssHooks[ prefix + suffix ] = {\n    expand: function( value ) {\n      var i,\n\n        // assumes a single number if not a string\n        parts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n        expanded = {};\n\n      for ( i = 0; i < 4; i++ ) {\n        expanded[ prefix + cssExpand[ i ] + suffix ] =\n          parts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n      }\n\n      return expanded;\n    }\n  };\n\n  if ( !rmargin.test( prefix ) ) {\n    jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n  }\n});\nvar r20 = /%20/g,\n  rbracket = /\\[\\]$/,\n  rCRLF = /\\r?\\n/g,\n  rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n  rselectTextarea = /^(?:select|textarea)/i;\n\njQuery.fn.extend({\n  serialize: function() {\n    return jQuery.param( this.serializeArray() );\n  },\n  serializeArray: function() {\n    return this.map(function(){\n      return this.elements ? jQuery.makeArray( this.elements ) : this;\n    })\n    .filter(function(){\n      return this.name && !this.disabled &&\n        ( this.checked || rselectTextarea.test( this.nodeName ) ||\n          rinput.test( this.type ) );\n    })\n    .map(function( i, elem ){\n      var val = jQuery( this ).val();\n\n      return val == null ?\n        null :\n        jQuery.isArray( val ) ?\n          jQuery.map( val, function( val, i ){\n            return { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n          }) :\n          { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n    }).get();\n  }\n});\n\n//Serialize an array of form elements or a set of\n//key/values into a query string\njQuery.param = function( a, traditional ) {\n  var prefix,\n    s = [],\n    add = function( key, value ) {\n      // If value is a function, invoke it and return its value\n      value = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n      s[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n    };\n\n  // Set traditional to true for jQuery <= 1.3.2 behavior.\n  if ( traditional === undefined ) {\n    traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n  }\n\n  // If an array was passed in, assume that it is an array of form elements.\n  if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n    // Serialize the form elements\n    jQuery.each( a, function() {\n      add( this.name, this.value );\n    });\n\n  } else {\n    // If traditional, encode the \"old\" way (the way 1.3.2 or older\n    // did it), otherwise encode params recursively.\n    for ( prefix in a ) {\n      buildParams( prefix, a[ prefix ], traditional, add );\n    }\n  }\n\n  // Return the resulting serialization\n  return s.join( \"&\" ).replace( r20, \"+\" );\n};\n\nfunction buildParams( prefix, obj, traditional, add ) {\n  var name;\n\n  if ( jQuery.isArray( obj ) ) {\n    // Serialize array item.\n    jQuery.each( obj, function( i, v ) {\n      if ( traditional || rbracket.test( prefix ) ) {\n        // Treat each array item as a scalar.\n        add( prefix, v );\n\n      } else {\n        // If array item is non-scalar (array or object), encode its\n        // numeric index to resolve deserialization ambiguity issues.\n        // Note that rack (as of 1.0.0) can't currently deserialize\n        // nested arrays properly, and attempting to do so may cause\n        // a server error. Possible fixes are to modify rack's\n        // deserialization algorithm or to provide an option or flag\n        // to force array serialization to be shallow.\n        buildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n      }\n    });\n\n  } else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n    // Serialize object item.\n    for ( name in obj ) {\n      buildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n    }\n\n  } else {\n    // Serialize scalar item.\n    add( prefix, obj );\n  }\n}\nvar\n  // Document location\n  ajaxLocParts,\n  ajaxLocation,\n\n  rhash = /#.*$/,\n  rheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n  // #7653, #8125, #8152: local protocol detection\n  rlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n  rnoContent = /^(?:GET|HEAD)$/,\n  rprotocol = /^\\/\\//,\n  rquery = /\\?/,\n  rscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n  rts = /([?&])_=[^&]*/,\n  rurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n  // Keep a copy of the old load method\n  _load = jQuery.fn.load,\n\n  /* Prefilters\n   * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n   * 2) These are called:\n   *    - BEFORE asking for a transport\n   *    - AFTER param serialization (s.data is a string if s.processData is true)\n   * 3) key is the dataType\n   * 4) the catchall symbol \"*\" can be used\n   * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n   */\n  prefilters = {},\n\n  /* Transports bindings\n   * 1) key is the dataType\n   * 2) the catchall symbol \"*\" can be used\n   * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n   */\n  transports = {},\n\n  // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n  allTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n  ajaxLocation = location.href;\n} catch( e ) {\n  // Use the href attribute of an A element\n  // since IE will modify it given document.location\n  ajaxLocation = document.createElement( \"a\" );\n  ajaxLocation.href = \"\";\n  ajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n  // dataTypeExpression is optional and defaults to \"*\"\n  return function( dataTypeExpression, func ) {\n\n    if ( typeof dataTypeExpression !== \"string\" ) {\n      func = dataTypeExpression;\n      dataTypeExpression = \"*\";\n    }\n\n    var dataType, list, placeBefore,\n      dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),\n      i = 0,\n      length = dataTypes.length;\n\n    if ( jQuery.isFunction( func ) ) {\n      // For each dataType in the dataTypeExpression\n      for ( ; i < length; i++ ) {\n        dataType = dataTypes[ i ];\n        // We control if we're asked to add before\n        // any existing element\n        placeBefore = /^\\+/.test( dataType );\n        if ( placeBefore ) {\n          dataType = dataType.substr( 1 ) || \"*\";\n        }\n        list = structure[ dataType ] = structure[ dataType ] || [];\n        // then we add to the structure accordingly\n        list[ placeBefore ? \"unshift\" : \"push\" ]( func );\n      }\n    }\n  };\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n    dataType /* internal */, inspected /* internal */ ) {\n\n  dataType = dataType || options.dataTypes[ 0 ];\n  inspected = inspected || {};\n\n  inspected[ dataType ] = true;\n\n  var selection,\n    list = structure[ dataType ],\n    i = 0,\n    length = list ? list.length : 0,\n    executeOnly = ( structure === prefilters );\n\n  for ( ; i < length && ( executeOnly || !selection ); i++ ) {\n    selection = list[ i ]( options, originalOptions, jqXHR );\n    // If we got redirected to another dataType\n    // we try there if executing only and not done already\n    if ( typeof selection === \"string\" ) {\n      if ( !executeOnly || inspected[ selection ] ) {\n        selection = undefined;\n      } else {\n        options.dataTypes.unshift( selection );\n        selection = inspectPrefiltersOrTransports(\n            structure, options, originalOptions, jqXHR, selection, inspected );\n      }\n    }\n  }\n  // If we're only executing or nothing was selected\n  // we try the catchall dataType if not done already\n  if ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n    selection = inspectPrefiltersOrTransports(\n        structure, options, originalOptions, jqXHR, \"*\", inspected );\n  }\n  // unnecessary when only executing (prefilters)\n  // but it'll be ignored by the caller in that case\n  return selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n  var key, deep,\n    flatOptions = jQuery.ajaxSettings.flatOptions || {};\n  for ( key in src ) {\n    if ( src[ key ] !== undefined ) {\n      ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n    }\n  }\n  if ( deep ) {\n    jQuery.extend( true, target, deep );\n  }\n}\n\njQuery.fn.load = function( url, params, callback ) {\n  if ( typeof url !== \"string\" && _load ) {\n    return _load.apply( this, arguments );\n  }\n\n  // Don't do a request if no elements are being requested\n  if ( !this.length ) {\n    return this;\n  }\n\n  var selector, type, response,\n    self = this,\n    off = url.indexOf(\" \");\n\n  if ( off >= 0 ) {\n    selector = url.slice( off, url.length );\n    url = url.slice( 0, off );\n  }\n\n  // If it's a function\n  if ( jQuery.isFunction( params ) ) {\n\n    // We assume that it's the callback\n    callback = params;\n    params = undefined;\n\n  // Otherwise, build a param string\n  } else if ( params && typeof params === \"object\" ) {\n    type = \"POST\";\n  }\n\n  // Request the remote document\n  jQuery.ajax({\n    url: url,\n\n    // if \"type\" variable is undefined, then \"GET\" method will be used\n    type: type,\n    dataType: \"html\",\n    data: params,\n    complete: function( jqXHR, status ) {\n      if ( callback ) {\n        self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n      }\n    }\n  }).done(function( responseText ) {\n\n    // Save response for use in complete callback\n    response = arguments;\n\n    // See if a selector was specified\n    self.html( selector ?\n\n      // Create a dummy div to hold the results\n      jQuery(\"<div>\")\n\n        // inject the contents of the document in, removing the scripts\n        // to avoid any 'Permission Denied' errors in IE\n        .append( responseText.replace( rscript, \"\" ) )\n\n        // Locate the specified elements\n        .find( selector ) :\n\n      // If not, just inject the full result\n      responseText );\n\n  });\n\n  return this;\n};\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n  jQuery.fn[ o ] = function( f ){\n    return this.on( o, f );\n  };\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n  jQuery[ method ] = function( url, data, callback, type ) {\n    // shift arguments if data argument was omitted\n    if ( jQuery.isFunction( data ) ) {\n      type = type || callback;\n      callback = data;\n      data = undefined;\n    }\n\n    return jQuery.ajax({\n      type: method,\n      url: url,\n      data: data,\n      success: callback,\n      dataType: type\n    });\n  };\n});\n\njQuery.extend({\n\n  getScript: function( url, callback ) {\n    return jQuery.get( url, undefined, callback, \"script\" );\n  },\n\n  getJSON: function( url, data, callback ) {\n    return jQuery.get( url, data, callback, \"json\" );\n  },\n\n  // Creates a full fledged settings object into target\n  // with both ajaxSettings and settings fields.\n  // If target is omitted, writes into ajaxSettings.\n  ajaxSetup: function( target, settings ) {\n    if ( settings ) {\n      // Building a settings object\n      ajaxExtend( target, jQuery.ajaxSettings );\n    } else {\n      // Extending ajaxSettings\n      settings = target;\n      target = jQuery.ajaxSettings;\n    }\n    ajaxExtend( target, settings );\n    return target;\n  },\n\n  ajaxSettings: {\n    url: ajaxLocation,\n    isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n    global: true,\n    type: \"GET\",\n    contentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n    processData: true,\n    async: true,\n    /*\n    timeout: 0,\n    data: null,\n    dataType: null,\n    username: null,\n    password: null,\n    cache: null,\n    throws: false,\n    traditional: false,\n    headers: {},\n    */\n\n    accepts: {\n      xml: \"application/xml, text/xml\",\n      html: \"text/html\",\n      text: \"text/plain\",\n      json: \"application/json, text/javascript\",\n      \"*\": allTypes\n    },\n\n    contents: {\n      xml: /xml/,\n      html: /html/,\n      json: /json/\n    },\n\n    responseFields: {\n      xml: \"responseXML\",\n      text: \"responseText\"\n    },\n\n    // List of data converters\n    // 1) key format is \"source_type destination_type\" (a single space in-between)\n    // 2) the catchall symbol \"*\" can be used for source_type\n    converters: {\n\n      // Convert anything to text\n      \"* text\": window.String,\n\n      // Text to html (true = no transformation)\n      \"text html\": true,\n\n      // Evaluate text as a json expression\n      \"text json\": jQuery.parseJSON,\n\n      // Parse text as xml\n      \"text xml\": jQuery.parseXML\n    },\n\n    // For options that shouldn't be deep extended:\n    // you can add your own custom options here if\n    // and when you create one that shouldn't be\n    // deep extended (see ajaxExtend)\n    flatOptions: {\n      context: true,\n      url: true\n    }\n  },\n\n  ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n  ajaxTransport: addToPrefiltersOrTransports( transports ),\n\n  // Main method\n  ajax: function( url, options ) {\n\n    // If url is an object, simulate pre-1.5 signature\n    if ( typeof url === \"object\" ) {\n      options = url;\n      url = undefined;\n    }\n\n    // Force options to be an object\n    options = options || {};\n\n    var // ifModified key\n      ifModifiedKey,\n      // Response headers\n      responseHeadersString,\n      responseHeaders,\n      // transport\n      transport,\n      // timeout handle\n      timeoutTimer,\n      // Cross-domain detection vars\n      parts,\n      // To know if global events are to be dispatched\n      fireGlobals,\n      // Loop variable\n      i,\n      // Create the final options object\n      s = jQuery.ajaxSetup( {}, options ),\n      // Callbacks context\n      callbackContext = s.context || s,\n      // Context for global events\n      // It's the callbackContext if one was provided in the options\n      // and if it's a DOM node or a jQuery collection\n      globalEventContext = callbackContext !== s &&\n        ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n            jQuery( callbackContext ) : jQuery.event,\n      // Deferreds\n      deferred = jQuery.Deferred(),\n      completeDeferred = jQuery.Callbacks( \"once memory\" ),\n      // Status-dependent callbacks\n      statusCode = s.statusCode || {},\n      // Headers (they are sent all at once)\n      requestHeaders = {},\n      requestHeadersNames = {},\n      // The jqXHR state\n      state = 0,\n      // Default abort message\n      strAbort = \"canceled\",\n      // Fake xhr\n      jqXHR = {\n\n        readyState: 0,\n\n        // Caches the header\n        setRequestHeader: function( name, value ) {\n          if ( !state ) {\n            var lname = name.toLowerCase();\n            name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n            requestHeaders[ name ] = value;\n          }\n          return this;\n        },\n\n        // Raw string\n        getAllResponseHeaders: function() {\n          return state === 2 ? responseHeadersString : null;\n        },\n\n        // Builds headers hashtable if needed\n        getResponseHeader: function( key ) {\n          var match;\n          if ( state === 2 ) {\n            if ( !responseHeaders ) {\n              responseHeaders = {};\n              while( ( match = rheaders.exec( responseHeadersString ) ) ) {\n                responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n              }\n            }\n            match = responseHeaders[ key.toLowerCase() ];\n          }\n          return match === undefined ? null : match;\n        },\n\n        // Overrides response content-type header\n        overrideMimeType: function( type ) {\n          if ( !state ) {\n            s.mimeType = type;\n          }\n          return this;\n        },\n\n        // Cancel the request\n        abort: function( statusText ) {\n          statusText = statusText || strAbort;\n          if ( transport ) {\n            transport.abort( statusText );\n          }\n          done( 0, statusText );\n          return this;\n        }\n      };\n\n    // Callback for when everything is done\n    // It is defined here because jslint complains if it is declared\n    // at the end of the function (which would be more logical and readable)\n    function done( status, nativeStatusText, responses, headers ) {\n      var isSuccess, success, error, response, modified,\n        statusText = nativeStatusText;\n\n      // Called once\n      if ( state === 2 ) {\n        return;\n      }\n\n      // State is \"done\" now\n      state = 2;\n\n      // Clear timeout if it exists\n      if ( timeoutTimer ) {\n        clearTimeout( timeoutTimer );\n      }\n\n      // Dereference transport for early garbage collection\n      // (no matter how long the jqXHR object will be used)\n      transport = undefined;\n\n      // Cache response headers\n      responseHeadersString = headers || \"\";\n\n      // Set readyState\n      jqXHR.readyState = status > 0 ? 4 : 0;\n\n      // Get response data\n      if ( responses ) {\n        response = ajaxHandleResponses( s, jqXHR, responses );\n      }\n\n      // If successful, handle type chaining\n      if ( status >= 200 && status < 300 || status === 304 ) {\n\n        // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n        if ( s.ifModified ) {\n\n          modified = jqXHR.getResponseHeader(\"Last-Modified\");\n          if ( modified ) {\n            jQuery.lastModified[ ifModifiedKey ] = modified;\n          }\n          modified = jqXHR.getResponseHeader(\"Etag\");\n          if ( modified ) {\n            jQuery.etag[ ifModifiedKey ] = modified;\n          }\n        }\n\n        // If not modified\n        if ( status === 304 ) {\n\n          statusText = \"notmodified\";\n          isSuccess = true;\n\n        // If we have data\n        } else {\n\n          isSuccess = ajaxConvert( s, response );\n          statusText = isSuccess.state;\n          success = isSuccess.data;\n          error = isSuccess.error;\n          isSuccess = !error;\n        }\n      } else {\n        // We extract error from statusText\n        // then normalize statusText and status for non-aborts\n        error = statusText;\n        if ( !statusText || status ) {\n          statusText = \"error\";\n          if ( status < 0 ) {\n            status = 0;\n          }\n        }\n      }\n\n      // Set data for the fake xhr object\n      jqXHR.status = status;\n      jqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n      // Success/Error\n      if ( isSuccess ) {\n        deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n      } else {\n        deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n      }\n\n      // Status-dependent callbacks\n      jqXHR.statusCode( statusCode );\n      statusCode = undefined;\n\n      if ( fireGlobals ) {\n        globalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n            [ jqXHR, s, isSuccess ? success : error ] );\n      }\n\n      // Complete\n      completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n      if ( fireGlobals ) {\n        globalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n        // Handle the global AJAX counter\n        if ( !( --jQuery.active ) ) {\n          jQuery.event.trigger( \"ajaxStop\" );\n        }\n      }\n    }\n\n    // Attach deferreds\n    deferred.promise( jqXHR );\n    jqXHR.success = jqXHR.done;\n    jqXHR.error = jqXHR.fail;\n    jqXHR.complete = completeDeferred.add;\n\n    // Status-dependent callbacks\n    jqXHR.statusCode = function( map ) {\n      if ( map ) {\n        var tmp;\n        if ( state < 2 ) {\n          for ( tmp in map ) {\n            statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n          }\n        } else {\n          tmp = map[ jqXHR.status ];\n          jqXHR.always( tmp );\n        }\n      }\n      return this;\n    };\n\n    // Remove hash character (#7531: and string promotion)\n    // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n    // We also use the url parameter if available\n    s.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n    // Extract dataTypes list\n    s.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( core_rspace );\n\n    // A cross-domain request is in order when we have a protocol:host:port mismatch\n    if ( s.crossDomain == null ) {\n      parts = rurl.exec( s.url.toLowerCase() );\n      s.crossDomain = !!( parts &&\n        ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n          ( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n            ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n      );\n    }\n\n    // Convert data if not already a string\n    if ( s.data && s.processData && typeof s.data !== \"string\" ) {\n      s.data = jQuery.param( s.data, s.traditional );\n    }\n\n    // Apply prefilters\n    inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n    // If request was aborted inside a prefilter, stop there\n    if ( state === 2 ) {\n      return jqXHR;\n    }\n\n    // We can fire global events as of now if asked to\n    fireGlobals = s.global;\n\n    // Uppercase the type\n    s.type = s.type.toUpperCase();\n\n    // Determine if request has content\n    s.hasContent = !rnoContent.test( s.type );\n\n    // Watch for a new set of requests\n    if ( fireGlobals && jQuery.active++ === 0 ) {\n      jQuery.event.trigger( \"ajaxStart\" );\n    }\n\n    // More options handling for requests with no content\n    if ( !s.hasContent ) {\n\n      // If data is available, append data to url\n      if ( s.data ) {\n        s.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n        // #9682: remove data so that it's not used in an eventual retry\n        delete s.data;\n      }\n\n      // Get ifModifiedKey before adding the anti-cache parameter\n      ifModifiedKey = s.url;\n\n      // Add anti-cache in url if needed\n      if ( s.cache === false ) {\n\n        var ts = jQuery.now(),\n          // try replacing _= if it is there\n          ret = s.url.replace( rts, \"$1_=\" + ts );\n\n        // if nothing was replaced, add timestamp to the end\n        s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n      }\n    }\n\n    // Set the correct header, if data is being sent\n    if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n      jqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n    }\n\n    // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n    if ( s.ifModified ) {\n      ifModifiedKey = ifModifiedKey || s.url;\n      if ( jQuery.lastModified[ ifModifiedKey ] ) {\n        jqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n      }\n      if ( jQuery.etag[ ifModifiedKey ] ) {\n        jqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n      }\n    }\n\n    // Set the Accepts header for the server, depending on the dataType\n    jqXHR.setRequestHeader(\n      \"Accept\",\n      s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n        s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n        s.accepts[ \"*\" ]\n    );\n\n    // Check for headers option\n    for ( i in s.headers ) {\n      jqXHR.setRequestHeader( i, s.headers[ i ] );\n    }\n\n    // Allow custom headers/mimetypes and early abort\n    if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n        // Abort if not done already and return\n        return jqXHR.abort();\n\n    }\n\n    // aborting is no longer a cancellation\n    strAbort = \"abort\";\n\n    // Install callbacks on deferreds\n    for ( i in { success: 1, error: 1, complete: 1 } ) {\n      jqXHR[ i ]( s[ i ] );\n    }\n\n    // Get transport\n    transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n    // If no transport, we auto-abort\n    if ( !transport ) {\n      done( -1, \"No Transport\" );\n    } else {\n      jqXHR.readyState = 1;\n      // Send global event\n      if ( fireGlobals ) {\n        globalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n      }\n      // Timeout\n      if ( s.async && s.timeout > 0 ) {\n        timeoutTimer = setTimeout( function(){\n          jqXHR.abort( \"timeout\" );\n        }, s.timeout );\n      }\n\n      try {\n        state = 1;\n        transport.send( requestHeaders, done );\n      } catch (e) {\n        // Propagate exception as error if not done\n        if ( state < 2 ) {\n          done( -1, e );\n        // Simply rethrow otherwise\n        } else {\n          throw e;\n        }\n      }\n    }\n\n    return jqXHR;\n  },\n\n  // Counter for holding the number of active queries\n  active: 0,\n\n  // Last-Modified header cache for next request\n  lastModified: {},\n  etag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n  var ct, type, finalDataType, firstDataType,\n    contents = s.contents,\n    dataTypes = s.dataTypes,\n    responseFields = s.responseFields;\n\n  // Fill responseXXX fields\n  for ( type in responseFields ) {\n    if ( type in responses ) {\n      jqXHR[ responseFields[type] ] = responses[ type ];\n    }\n  }\n\n  // Remove auto dataType and get content-type in the process\n  while( dataTypes[ 0 ] === \"*\" ) {\n    dataTypes.shift();\n    if ( ct === undefined ) {\n      ct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n    }\n  }\n\n  // Check if we're dealing with a known content-type\n  if ( ct ) {\n    for ( type in contents ) {\n      if ( contents[ type ] && contents[ type ].test( ct ) ) {\n        dataTypes.unshift( type );\n        break;\n      }\n    }\n  }\n\n  // Check to see if we have a response for the expected dataType\n  if ( dataTypes[ 0 ] in responses ) {\n    finalDataType = dataTypes[ 0 ];\n  } else {\n    // Try convertible dataTypes\n    for ( type in responses ) {\n      if ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n        finalDataType = type;\n        break;\n      }\n      if ( !firstDataType ) {\n        firstDataType = type;\n      }\n    }\n    // Or just use first one\n    finalDataType = finalDataType || firstDataType;\n  }\n\n  // If we found a dataType\n  // We add the dataType to the list if needed\n  // and return the corresponding response\n  if ( finalDataType ) {\n    if ( finalDataType !== dataTypes[ 0 ] ) {\n      dataTypes.unshift( finalDataType );\n    }\n    return responses[ finalDataType ];\n  }\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n  var conv, conv2, current, tmp,\n    // Work with a copy of dataTypes in case we need to modify it for conversion\n    dataTypes = s.dataTypes.slice(),\n    prev = dataTypes[ 0 ],\n    converters = {},\n    i = 0;\n\n  // Apply the dataFilter if provided\n  if ( s.dataFilter ) {\n    response = s.dataFilter( response, s.dataType );\n  }\n\n  // Create converters map with lowercased keys\n  if ( dataTypes[ 1 ] ) {\n    for ( conv in s.converters ) {\n      converters[ conv.toLowerCase() ] = s.converters[ conv ];\n    }\n  }\n\n  // Convert to each sequential dataType, tolerating list modification\n  for ( ; (current = dataTypes[++i]); ) {\n\n    // There's only work to do if current dataType is non-auto\n    if ( current !== \"*\" ) {\n\n      // Convert response if prev dataType is non-auto and differs from current\n      if ( prev !== \"*\" && prev !== current ) {\n\n        // Seek a direct converter\n        conv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n        // If none found, seek a pair\n        if ( !conv ) {\n          for ( conv2 in converters ) {\n\n            // If conv2 outputs current\n            tmp = conv2.split(\" \");\n            if ( tmp[ 1 ] === current ) {\n\n              // If prev can be converted to accepted input\n              conv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n                converters[ \"* \" + tmp[ 0 ] ];\n              if ( conv ) {\n                // Condense equivalence converters\n                if ( conv === true ) {\n                  conv = converters[ conv2 ];\n\n                // Otherwise, insert the intermediate dataType\n                } else if ( converters[ conv2 ] !== true ) {\n                  current = tmp[ 0 ];\n                  dataTypes.splice( i--, 0, current );\n                }\n\n                break;\n              }\n            }\n          }\n        }\n\n        // Apply converter (if not an equivalence)\n        if ( conv !== true ) {\n\n          // Unless errors are allowed to bubble, catch and return them\n          if ( conv && s[\"throws\"] ) {\n            response = conv( response );\n          } else {\n            try {\n              response = conv( response );\n            } catch ( e ) {\n              return { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n            }\n          }\n        }\n      }\n\n      // Update prev for next iteration\n      prev = current;\n    }\n  }\n\n  return { state: \"success\", data: response };\n}\nvar oldCallbacks = [],\n  rquestion = /\\?/,\n  rjsonp = /(=)\\?(?=&|$)|\\?\\?/,\n  nonce = jQuery.now();\n\n// Default jsonp settings\njQuery.ajaxSetup({\n  jsonp: \"callback\",\n  jsonpCallback: function() {\n    var callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n    this[ callback ] = true;\n    return callback;\n  }\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n  var callbackName, overwritten, responseContainer,\n    data = s.data,\n    url = s.url,\n    hasCallback = s.jsonp !== false,\n    replaceInUrl = hasCallback && rjsonp.test( url ),\n    replaceInData = hasCallback && !replaceInUrl && typeof data === \"string\" &&\n      !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") &&\n      rjsonp.test( data );\n\n  // Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n  if ( s.dataTypes[ 0 ] === \"jsonp\" || replaceInUrl || replaceInData ) {\n\n    // Get callback name, remembering preexisting value associated with it\n    callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n      s.jsonpCallback() :\n      s.jsonpCallback;\n    overwritten = window[ callbackName ];\n\n    // Insert callback into url or form data\n    if ( replaceInUrl ) {\n      s.url = url.replace( rjsonp, \"$1\" + callbackName );\n    } else if ( replaceInData ) {\n      s.data = data.replace( rjsonp, \"$1\" + callbackName );\n    } else if ( hasCallback ) {\n      s.url += ( rquestion.test( url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n    }\n\n    // Use data converter to retrieve json after script execution\n    s.converters[\"script json\"] = function() {\n      if ( !responseContainer ) {\n        jQuery.error( callbackName + \" was not called\" );\n      }\n      return responseContainer[ 0 ];\n    };\n\n    // force json dataType\n    s.dataTypes[ 0 ] = \"json\";\n\n    // Install callback\n    window[ callbackName ] = function() {\n      responseContainer = arguments;\n    };\n\n    // Clean-up function (fires after converters)\n    jqXHR.always(function() {\n      // Restore preexisting value\n      window[ callbackName ] = overwritten;\n\n      // Save back as free\n      if ( s[ callbackName ] ) {\n        // make sure that re-using the options doesn't screw things around\n        s.jsonpCallback = originalSettings.jsonpCallback;\n\n        // save the callback name for future use\n        oldCallbacks.push( callbackName );\n      }\n\n      // Call if it was a function and we have a response\n      if ( responseContainer && jQuery.isFunction( overwritten ) ) {\n        overwritten( responseContainer[ 0 ] );\n      }\n\n      responseContainer = overwritten = undefined;\n    });\n\n    // Delegate to script\n    return \"script\";\n  }\n});\n// Install script dataType\njQuery.ajaxSetup({\n  accepts: {\n    script: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n  },\n  contents: {\n    script: /javascript|ecmascript/\n  },\n  converters: {\n    \"text script\": function( text ) {\n      jQuery.globalEval( text );\n      return text;\n    }\n  }\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n  if ( s.cache === undefined ) {\n    s.cache = false;\n  }\n  if ( s.crossDomain ) {\n    s.type = \"GET\";\n    s.global = false;\n  }\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n  // This transport only deals with cross domain requests\n  if ( s.crossDomain ) {\n\n    var script,\n      head = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n    return {\n\n      send: function( _, callback ) {\n\n        script = document.createElement( \"script\" );\n\n        script.async = \"async\";\n\n        if ( s.scriptCharset ) {\n          script.charset = s.scriptCharset;\n        }\n\n        script.src = s.url;\n\n        // Attach handlers for all browsers\n        script.onload = script.onreadystatechange = function( _, isAbort ) {\n\n          if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n            // Handle memory leak in IE\n            script.onload = script.onreadystatechange = null;\n\n            // Remove the script\n            if ( head && script.parentNode ) {\n              head.removeChild( script );\n            }\n\n            // Dereference the script\n            script = undefined;\n\n            // Callback if not abort\n            if ( !isAbort ) {\n              callback( 200, \"success\" );\n            }\n          }\n        };\n        // Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n        // This arises when a base node is used (#2709 and #4378).\n        head.insertBefore( script, head.firstChild );\n      },\n\n      abort: function() {\n        if ( script ) {\n          script.onload( 0, 1 );\n        }\n      }\n    };\n  }\n});\nvar xhrCallbacks,\n  // #5280: Internet Explorer will keep connections alive if we don't abort on unload\n  xhrOnUnloadAbort = window.ActiveXObject ? function() {\n    // Abort all pending requests\n    for ( var key in xhrCallbacks ) {\n      xhrCallbacks[ key ]( 0, 1 );\n    }\n  } : false,\n  xhrId = 0;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n  try {\n    return new window.XMLHttpRequest();\n  } catch( e ) {}\n}\n\nfunction createActiveXHR() {\n  try {\n    return new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n  } catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n  /* Microsoft failed to properly\n   * implement the XMLHttpRequest in IE7 (can't request local files),\n   * so we use the ActiveXObject when it is available\n   * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n   * we need a fallback.\n   */\n  function() {\n    return !this.isLocal && createStandardXHR() || createActiveXHR();\n  } :\n  // For all other browsers, use the standard XMLHttpRequest object\n  createStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n  jQuery.extend( jQuery.support, {\n    ajax: !!xhr,\n    cors: !!xhr && ( \"withCredentials\" in xhr )\n  });\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n  jQuery.ajaxTransport(function( s ) {\n    // Cross domain only allowed if supported through XMLHttpRequest\n    if ( !s.crossDomain || jQuery.support.cors ) {\n\n      var callback;\n\n      return {\n        send: function( headers, complete ) {\n\n          // Get a new xhr\n          var handle, i,\n            xhr = s.xhr();\n\n          // Open the socket\n          // Passing null username, generates a login popup on Opera (#2865)\n          if ( s.username ) {\n            xhr.open( s.type, s.url, s.async, s.username, s.password );\n          } else {\n            xhr.open( s.type, s.url, s.async );\n          }\n\n          // Apply custom fields if provided\n          if ( s.xhrFields ) {\n            for ( i in s.xhrFields ) {\n              xhr[ i ] = s.xhrFields[ i ];\n            }\n          }\n\n          // Override mime type if needed\n          if ( s.mimeType && xhr.overrideMimeType ) {\n            xhr.overrideMimeType( s.mimeType );\n          }\n\n          // X-Requested-With header\n          // For cross-domain requests, seeing as conditions for a preflight are\n          // akin to a jigsaw puzzle, we simply never set it to be sure.\n          // (it can always be set on a per-request basis or even using ajaxSetup)\n          // For same-domain requests, won't change header if already provided.\n          if ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n            headers[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n          }\n\n          // Need an extra try/catch for cross domain requests in Firefox 3\n          try {\n            for ( i in headers ) {\n              xhr.setRequestHeader( i, headers[ i ] );\n            }\n          } catch( _ ) {}\n\n          // Do send the request\n          // This may raise an exception which is actually\n          // handled in jQuery.ajax (so no try/catch here)\n          xhr.send( ( s.hasContent && s.data ) || null );\n\n          // Listener\n          callback = function( _, isAbort ) {\n\n            var status,\n              statusText,\n              responseHeaders,\n              responses,\n              xml;\n\n            // Firefox throws exceptions when accessing properties\n            // of an xhr when a network error occurred\n            // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n            try {\n\n              // Was never called and is aborted or complete\n              if ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n                // Only called once\n                callback = undefined;\n\n                // Do not keep as active anymore\n                if ( handle ) {\n                  xhr.onreadystatechange = jQuery.noop;\n                  if ( xhrOnUnloadAbort ) {\n                    delete xhrCallbacks[ handle ];\n                  }\n                }\n\n                // If it's an abort\n                if ( isAbort ) {\n                  // Abort it manually if needed\n                  if ( xhr.readyState !== 4 ) {\n                    xhr.abort();\n                  }\n                } else {\n                  status = xhr.status;\n                  responseHeaders = xhr.getAllResponseHeaders();\n                  responses = {};\n                  xml = xhr.responseXML;\n\n                  // Construct response list\n                  if ( xml && xml.documentElement /* #4958 */ ) {\n                    responses.xml = xml;\n                  }\n\n                  // When requesting binary data, IE6-9 will throw an exception\n                  // on any attempt to access responseText (#11426)\n                  try {\n                    responses.text = xhr.responseText;\n                  } catch( e ) {\n                  }\n\n                  // Firefox throws an exception when accessing\n                  // statusText for faulty cross-domain requests\n                  try {\n                    statusText = xhr.statusText;\n                  } catch( e ) {\n                    // We normalize with Webkit giving an empty statusText\n                    statusText = \"\";\n                  }\n\n                  // Filter status for non standard behaviors\n\n                  // If the request is local and we have data: assume a success\n                  // (success with no data won't get notified, that's the best we\n                  // can do given current implementations)\n                  if ( !status && s.isLocal && !s.crossDomain ) {\n                    status = responses.text ? 200 : 404;\n                  // IE - #1450: sometimes returns 1223 when it should be 204\n                  } else if ( status === 1223 ) {\n                    status = 204;\n                  }\n                }\n              }\n            } catch( firefoxAccessException ) {\n              if ( !isAbort ) {\n                complete( -1, firefoxAccessException );\n              }\n            }\n\n            // Call complete if needed\n            if ( responses ) {\n              complete( status, statusText, responses, responseHeaders );\n            }\n          };\n\n          if ( !s.async ) {\n            // if we're in sync mode we fire the callback\n            callback();\n          } else if ( xhr.readyState === 4 ) {\n            // (IE6 & IE7) if it's in cache and has been\n            // retrieved directly we need to fire the callback\n            setTimeout( callback, 0 );\n          } else {\n            handle = ++xhrId;\n            if ( xhrOnUnloadAbort ) {\n              // Create the active xhrs callbacks list if needed\n              // and attach the unload handler\n              if ( !xhrCallbacks ) {\n                xhrCallbacks = {};\n                jQuery( window ).unload( xhrOnUnloadAbort );\n              }\n              // Add to list of active xhrs callbacks\n              xhrCallbacks[ handle ] = callback;\n            }\n            xhr.onreadystatechange = callback;\n          }\n        },\n\n        abort: function() {\n          if ( callback ) {\n            callback(0,1);\n          }\n        }\n      };\n    }\n  });\n}\nvar fxNow, timerId,\n  rfxtypes = /^(?:toggle|show|hide)$/,\n  rfxnum = new RegExp( \"^(?:([-+])=|)(\" + core_pnum + \")([a-z%]*)$\", \"i\" ),\n  rrun = /queueHooks$/,\n  animationPrefilters = [ defaultPrefilter ],\n  tweeners = {\n    \"*\": [function( prop, value ) {\n      var end, unit,\n        tween = this.createTween( prop, value ),\n        parts = rfxnum.exec( value ),\n        target = tween.cur(),\n        start = +target || 0,\n        scale = 1,\n        maxIterations = 20;\n\n      if ( parts ) {\n        end = +parts[2];\n        unit = parts[3] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\n        // We need to compute starting value\n        if ( unit !== \"px\" && start ) {\n          // Iteratively approximate from a nonzero starting point\n          // Prefer the current property, because this process will be trivial if it uses the same units\n          // Fallback to end or a simple constant\n          start = jQuery.css( tween.elem, prop, true ) || end || 1;\n\n          do {\n            // If previous iteration zeroed out, double until we get *something*\n            // Use a string for doubling factor so we don't accidentally see scale as unchanged below\n            scale = scale || \".5\";\n\n            // Adjust and apply\n            start = start / scale;\n            jQuery.style( tween.elem, prop, start + unit );\n\n          // Update scale, tolerating zero or NaN from tween.cur()\n          // And breaking the loop if scale is unchanged or perfect, or if we've just had enough\n          } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n        }\n\n        tween.unit = unit;\n        tween.start = start;\n        // If a +=/-= token was provided, we're doing a relative animation\n        tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;\n      }\n      return tween;\n    }]\n  };\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n  setTimeout(function() {\n    fxNow = undefined;\n  }, 0 );\n  return ( fxNow = jQuery.now() );\n}\n\nfunction createTweens( animation, props ) {\n  jQuery.each( props, function( prop, value ) {\n    var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n      index = 0,\n      length = collection.length;\n    for ( ; index < length; index++ ) {\n      if ( collection[ index ].call( animation, prop, value ) ) {\n\n        // we're done with this property\n        return;\n      }\n    }\n  });\n}\n\nfunction Animation( elem, properties, options ) {\n  var result,\n    index = 0,\n    tweenerIndex = 0,\n    length = animationPrefilters.length,\n    deferred = jQuery.Deferred().always( function() {\n      // don't match elem in the :animated selector\n      delete tick.elem;\n    }),\n    tick = function() {\n      var currentTime = fxNow || createFxNow(),\n        remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n        // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)\n        temp = remaining / animation.duration || 0,\n        percent = 1 - temp,\n        index = 0,\n        length = animation.tweens.length;\n\n      for ( ; index < length ; index++ ) {\n        animation.tweens[ index ].run( percent );\n      }\n\n      deferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n      if ( percent < 1 && length ) {\n        return remaining;\n      } else {\n        deferred.resolveWith( elem, [ animation ] );\n        return false;\n      }\n    },\n    animation = deferred.promise({\n      elem: elem,\n      props: jQuery.extend( {}, properties ),\n      opts: jQuery.extend( true, { specialEasing: {} }, options ),\n      originalProperties: properties,\n      originalOptions: options,\n      startTime: fxNow || createFxNow(),\n      duration: options.duration,\n      tweens: [],\n      createTween: function( prop, end, easing ) {\n        var tween = jQuery.Tween( elem, animation.opts, prop, end,\n            animation.opts.specialEasing[ prop ] || animation.opts.easing );\n        animation.tweens.push( tween );\n        return tween;\n      },\n      stop: function( gotoEnd ) {\n        var index = 0,\n          // if we are going to the end, we want to run all the tweens\n          // otherwise we skip this part\n          length = gotoEnd ? animation.tweens.length : 0;\n\n        for ( ; index < length ; index++ ) {\n          animation.tweens[ index ].run( 1 );\n        }\n\n        // resolve when we played the last frame\n        // otherwise, reject\n        if ( gotoEnd ) {\n          deferred.resolveWith( elem, [ animation, gotoEnd ] );\n        } else {\n          deferred.rejectWith( elem, [ animation, gotoEnd ] );\n        }\n        return this;\n      }\n    }),\n    props = animation.props;\n\n  propFilter( props, animation.opts.specialEasing );\n\n  for ( ; index < length ; index++ ) {\n    result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n    if ( result ) {\n      return result;\n    }\n  }\n\n  createTweens( animation, props );\n\n  if ( jQuery.isFunction( animation.opts.start ) ) {\n    animation.opts.start.call( elem, animation );\n  }\n\n  jQuery.fx.timer(\n    jQuery.extend( tick, {\n      anim: animation,\n      queue: animation.opts.queue,\n      elem: elem\n    })\n  );\n\n  // attach callbacks from options\n  return animation.progress( animation.opts.progress )\n    .done( animation.opts.done, animation.opts.complete )\n    .fail( animation.opts.fail )\n    .always( animation.opts.always );\n}\n\nfunction propFilter( props, specialEasing ) {\n  var index, name, easing, value, hooks;\n\n  // camelCase, specialEasing and expand cssHook pass\n  for ( index in props ) {\n    name = jQuery.camelCase( index );\n    easing = specialEasing[ name ];\n    value = props[ index ];\n    if ( jQuery.isArray( value ) ) {\n      easing = value[ 1 ];\n      value = props[ index ] = value[ 0 ];\n    }\n\n    if ( index !== name ) {\n      props[ name ] = value;\n      delete props[ index ];\n    }\n\n    hooks = jQuery.cssHooks[ name ];\n    if ( hooks && \"expand\" in hooks ) {\n      value = hooks.expand( value );\n      delete props[ name ];\n\n      // not quite $.extend, this wont overwrite keys already present.\n      // also - reusing 'index' from above because we have the correct \"name\"\n      for ( index in value ) {\n        if ( !( index in props ) ) {\n          props[ index ] = value[ index ];\n          specialEasing[ index ] = easing;\n        }\n      }\n    } else {\n      specialEasing[ name ] = easing;\n    }\n  }\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n  tweener: function( props, callback ) {\n    if ( jQuery.isFunction( props ) ) {\n      callback = props;\n      props = [ \"*\" ];\n    } else {\n      props = props.split(\" \");\n    }\n\n    var prop,\n      index = 0,\n      length = props.length;\n\n    for ( ; index < length ; index++ ) {\n      prop = props[ index ];\n      tweeners[ prop ] = tweeners[ prop ] || [];\n      tweeners[ prop ].unshift( callback );\n    }\n  },\n\n  prefilter: function( callback, prepend ) {\n    if ( prepend ) {\n      animationPrefilters.unshift( callback );\n    } else {\n      animationPrefilters.push( callback );\n    }\n  }\n});\n\nfunction defaultPrefilter( elem, props, opts ) {\n  var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire,\n    anim = this,\n    style = elem.style,\n    orig = {},\n    handled = [],\n    hidden = elem.nodeType && isHidden( elem );\n\n  // handle queue: false promises\n  if ( !opts.queue ) {\n    hooks = jQuery._queueHooks( elem, \"fx\" );\n    if ( hooks.unqueued == null ) {\n      hooks.unqueued = 0;\n      oldfire = hooks.empty.fire;\n      hooks.empty.fire = function() {\n        if ( !hooks.unqueued ) {\n          oldfire();\n        }\n      };\n    }\n    hooks.unqueued++;\n\n    anim.always(function() {\n      // doing this makes sure that the complete handler will be called\n      // before this completes\n      anim.always(function() {\n        hooks.unqueued--;\n        if ( !jQuery.queue( elem, \"fx\" ).length ) {\n          hooks.empty.fire();\n        }\n      });\n    });\n  }\n\n  // height/width overflow pass\n  if ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n    // Make sure that nothing sneaks out\n    // Record all 3 overflow attributes because IE does not\n    // change the overflow attribute when overflowX and\n    // overflowY are set to the same value\n    opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n    // Set display property to inline-block for height/width\n    // animations on inline elements that are having width/height animated\n    if ( jQuery.css( elem, \"display\" ) === \"inline\" &&\n        jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n      // inline-level elements accept inline-block;\n      // block-level elements need to be inline with layout\n      if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === \"inline\" ) {\n        style.display = \"inline-block\";\n\n      } else {\n        style.zoom = 1;\n      }\n    }\n  }\n\n  if ( opts.overflow ) {\n    style.overflow = \"hidden\";\n    if ( !jQuery.support.shrinkWrapBlocks ) {\n      anim.done(function() {\n        style.overflow = opts.overflow[ 0 ];\n        style.overflowX = opts.overflow[ 1 ];\n        style.overflowY = opts.overflow[ 2 ];\n      });\n    }\n  }\n\n\n  // show/hide pass\n  for ( index in props ) {\n    value = props[ index ];\n    if ( rfxtypes.exec( value ) ) {\n      delete props[ index ];\n      toggle = toggle || value === \"toggle\";\n      if ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n        continue;\n      }\n      handled.push( index );\n    }\n  }\n\n  length = handled.length;\n  if ( length ) {\n    dataShow = jQuery._data( elem, \"fxshow\" ) || jQuery._data( elem, \"fxshow\", {} );\n    if ( \"hidden\" in dataShow ) {\n      hidden = dataShow.hidden;\n    }\n\n    // store state if its toggle - enables .stop().toggle() to \"reverse\"\n    if ( toggle ) {\n      dataShow.hidden = !hidden;\n    }\n    if ( hidden ) {\n      jQuery( elem ).show();\n    } else {\n      anim.done(function() {\n        jQuery( elem ).hide();\n      });\n    }\n    anim.done(function() {\n      var prop;\n      jQuery.removeData( elem, \"fxshow\", true );\n      for ( prop in orig ) {\n        jQuery.style( elem, prop, orig[ prop ] );\n      }\n    });\n    for ( index = 0 ; index < length ; index++ ) {\n      prop = handled[ index ];\n      tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );\n      orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );\n\n      if ( !( prop in dataShow ) ) {\n        dataShow[ prop ] = tween.start;\n        if ( hidden ) {\n          tween.end = tween.start;\n          tween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n        }\n      }\n    }\n  }\n}\n\nfunction Tween( elem, options, prop, end, easing ) {\n  return new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n  constructor: Tween,\n  init: function( elem, options, prop, end, easing, unit ) {\n    this.elem = elem;\n    this.prop = prop;\n    this.easing = easing || \"swing\";\n    this.options = options;\n    this.start = this.now = this.cur();\n    this.end = end;\n    this.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n  },\n  cur: function() {\n    var hooks = Tween.propHooks[ this.prop ];\n\n    return hooks && hooks.get ?\n      hooks.get( this ) :\n      Tween.propHooks._default.get( this );\n  },\n  run: function( percent ) {\n    var eased,\n      hooks = Tween.propHooks[ this.prop ];\n\n    if ( this.options.duration ) {\n      this.pos = eased = jQuery.easing[ this.easing ](\n        percent, this.options.duration * percent, 0, 1, this.options.duration\n      );\n    } else {\n      this.pos = eased = percent;\n    }\n    this.now = ( this.end - this.start ) * eased + this.start;\n\n    if ( this.options.step ) {\n      this.options.step.call( this.elem, this.now, this );\n    }\n\n    if ( hooks && hooks.set ) {\n      hooks.set( this );\n    } else {\n      Tween.propHooks._default.set( this );\n    }\n    return this;\n  }\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n  _default: {\n    get: function( tween ) {\n      var result;\n\n      if ( tween.elem[ tween.prop ] != null &&\n        (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n        return tween.elem[ tween.prop ];\n      }\n\n      // passing any value as a 4th parameter to .css will automatically\n      // attempt a parseFloat and fallback to a string if the parse fails\n      // so, simple values such as \"10px\" are parsed to Float.\n      // complex values such as \"rotate(1rad)\" are returned as is.\n      result = jQuery.css( tween.elem, tween.prop, false, \"\" );\n      // Empty strings, null, undefined and \"auto\" are converted to 0.\n      return !result || result === \"auto\" ? 0 : result;\n    },\n    set: function( tween ) {\n      // use step hook for back compat - use cssHook if its there - use .style if its\n      // available and use plain properties where available\n      if ( jQuery.fx.step[ tween.prop ] ) {\n        jQuery.fx.step[ tween.prop ]( tween );\n      } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n        jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n      } else {\n        tween.elem[ tween.prop ] = tween.now;\n      }\n    }\n  }\n};\n\n// Remove in 2.0 - this supports IE8's panic based approach\n// to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n  set: function( tween ) {\n    if ( tween.elem.nodeType && tween.elem.parentNode ) {\n      tween.elem[ tween.prop ] = tween.now;\n    }\n  }\n};\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n  var cssFn = jQuery.fn[ name ];\n  jQuery.fn[ name ] = function( speed, easing, callback ) {\n    return speed == null || typeof speed === \"boolean\" ||\n      // special check for .toggle( handler, handler, ... )\n      ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ?\n      cssFn.apply( this, arguments ) :\n      this.animate( genFx( name, true ), speed, easing, callback );\n  };\n});\n\njQuery.fn.extend({\n  fadeTo: function( speed, to, easing, callback ) {\n\n    // show any hidden elements after setting opacity to 0\n    return this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n      // animate to the value specified\n      .end().animate({ opacity: to }, speed, easing, callback );\n  },\n  animate: function( prop, speed, easing, callback ) {\n    var empty = jQuery.isEmptyObject( prop ),\n      optall = jQuery.speed( speed, easing, callback ),\n      doAnimation = function() {\n        // Operate on a copy of prop so per-property easing won't be lost\n        var anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n        // Empty animations resolve immediately\n        if ( empty ) {\n          anim.stop( true );\n        }\n      };\n\n    return empty || optall.queue === false ?\n      this.each( doAnimation ) :\n      this.queue( optall.queue, doAnimation );\n  },\n  stop: function( type, clearQueue, gotoEnd ) {\n    var stopQueue = function( hooks ) {\n      var stop = hooks.stop;\n      delete hooks.stop;\n      stop( gotoEnd );\n    };\n\n    if ( typeof type !== \"string\" ) {\n      gotoEnd = clearQueue;\n      clearQueue = type;\n      type = undefined;\n    }\n    if ( clearQueue && type !== false ) {\n      this.queue( type || \"fx\", [] );\n    }\n\n    return this.each(function() {\n      var dequeue = true,\n        index = type != null && type + \"queueHooks\",\n        timers = jQuery.timers,\n        data = jQuery._data( this );\n\n      if ( index ) {\n        if ( data[ index ] && data[ index ].stop ) {\n          stopQueue( data[ index ] );\n        }\n      } else {\n        for ( index in data ) {\n          if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n            stopQueue( data[ index ] );\n          }\n        }\n      }\n\n      for ( index = timers.length; index--; ) {\n        if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n          timers[ index ].anim.stop( gotoEnd );\n          dequeue = false;\n          timers.splice( index, 1 );\n        }\n      }\n\n      // start the next in the queue if the last step wasn't forced\n      // timers currently will call their complete callbacks, which will dequeue\n      // but only if they were gotoEnd\n      if ( dequeue || !gotoEnd ) {\n        jQuery.dequeue( this, type );\n      }\n    });\n  }\n});\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n  var which,\n    attrs = { height: type },\n    i = 0;\n\n  // if we include width, step value is 1 to do all cssExpand values,\n  // if we don't include width, step value is 2 to skip over Left and Right\n  includeWidth = includeWidth? 1 : 0;\n  for( ; i < 4 ; i += 2 - includeWidth ) {\n    which = cssExpand[ i ];\n    attrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n  }\n\n  if ( includeWidth ) {\n    attrs.opacity = attrs.width = type;\n  }\n\n  return attrs;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n  slideDown: genFx(\"show\"),\n  slideUp: genFx(\"hide\"),\n  slideToggle: genFx(\"toggle\"),\n  fadeIn: { opacity: \"show\" },\n  fadeOut: { opacity: \"hide\" },\n  fadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n  jQuery.fn[ name ] = function( speed, easing, callback ) {\n    return this.animate( props, speed, easing, callback );\n  };\n});\n\njQuery.speed = function( speed, easing, fn ) {\n  var opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n    complete: fn || !fn && easing ||\n      jQuery.isFunction( speed ) && speed,\n    duration: speed,\n    easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n  };\n\n  opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n    opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n  // normalize opt.queue - true/undefined/null -> \"fx\"\n  if ( opt.queue == null || opt.queue === true ) {\n    opt.queue = \"fx\";\n  }\n\n  // Queueing\n  opt.old = opt.complete;\n\n  opt.complete = function() {\n    if ( jQuery.isFunction( opt.old ) ) {\n      opt.old.call( this );\n    }\n\n    if ( opt.queue ) {\n      jQuery.dequeue( this, opt.queue );\n    }\n  };\n\n  return opt;\n};\n\njQuery.easing = {\n  linear: function( p ) {\n    return p;\n  },\n  swing: function( p ) {\n    return 0.5 - Math.cos( p*Math.PI ) / 2;\n  }\n};\n\njQuery.timers = [];\njQuery.fx = Tween.prototype.init;\njQuery.fx.tick = function() {\n  var timer,\n    timers = jQuery.timers,\n    i = 0;\n\n  fxNow = jQuery.now();\n\n  for ( ; i < timers.length; i++ ) {\n    timer = timers[ i ];\n    // Checks the timer has not already been removed\n    if ( !timer() && timers[ i ] === timer ) {\n      timers.splice( i--, 1 );\n    }\n  }\n\n  if ( !timers.length ) {\n    jQuery.fx.stop();\n  }\n  fxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n  if ( timer() && jQuery.timers.push( timer ) && !timerId ) {\n    timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n  }\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.stop = function() {\n  clearInterval( timerId );\n  timerId = null;\n};\n\njQuery.fx.speeds = {\n  slow: 600,\n  fast: 200,\n  // Default speed\n  _default: 400\n};\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n  jQuery.expr.filters.animated = function( elem ) {\n    return jQuery.grep(jQuery.timers, function( fn ) {\n      return elem === fn.elem;\n    }).length;\n  };\n}\nvar rroot = /^(?:body|html)$/i;\n\njQuery.fn.offset = function( options ) {\n  if ( arguments.length ) {\n    return options === undefined ?\n      this :\n      this.each(function( i ) {\n        jQuery.offset.setOffset( this, options, i );\n      });\n  }\n\n  var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft,\n    box = { top: 0, left: 0 },\n    elem = this[ 0 ],\n    doc = elem && elem.ownerDocument;\n\n  if ( !doc ) {\n    return;\n  }\n\n  if ( (body = doc.body) === elem ) {\n    return jQuery.offset.bodyOffset( elem );\n  }\n\n  docElem = doc.documentElement;\n\n  // Make sure it's not a disconnected DOM node\n  if ( !jQuery.contains( docElem, elem ) ) {\n    return box;\n  }\n\n  // If we don't have gBCR, just use 0,0 rather than error\n  // BlackBerry 5, iOS 3 (original iPhone)\n  if ( typeof elem.getBoundingClientRect !== \"undefined\" ) {\n    box = elem.getBoundingClientRect();\n  }\n  win = getWindow( doc );\n  clientTop  = docElem.clientTop  || body.clientTop  || 0;\n  clientLeft = docElem.clientLeft || body.clientLeft || 0;\n  scrollTop  = win.pageYOffset || docElem.scrollTop;\n  scrollLeft = win.pageXOffset || docElem.scrollLeft;\n  return {\n    top: box.top  + scrollTop  - clientTop,\n    left: box.left + scrollLeft - clientLeft\n  };\n};\n\njQuery.offset = {\n\n  bodyOffset: function( body ) {\n    var top = body.offsetTop,\n      left = body.offsetLeft;\n\n    if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n      top  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n      left += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n    }\n\n    return { top: top, left: left };\n  },\n\n  setOffset: function( elem, options, i ) {\n    var position = jQuery.css( elem, \"position\" );\n\n    // set position first, in-case top/left are set even on static elem\n    if ( position === \"static\" ) {\n      elem.style.position = \"relative\";\n    }\n\n    var curElem = jQuery( elem ),\n      curOffset = curElem.offset(),\n      curCSSTop = jQuery.css( elem, \"top\" ),\n      curCSSLeft = jQuery.css( elem, \"left\" ),\n      calculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n      props = {}, curPosition = {}, curTop, curLeft;\n\n    // need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n    if ( calculatePosition ) {\n      curPosition = curElem.position();\n      curTop = curPosition.top;\n      curLeft = curPosition.left;\n    } else {\n      curTop = parseFloat( curCSSTop ) || 0;\n      curLeft = parseFloat( curCSSLeft ) || 0;\n    }\n\n    if ( jQuery.isFunction( options ) ) {\n      options = options.call( elem, i, curOffset );\n    }\n\n    if ( options.top != null ) {\n      props.top = ( options.top - curOffset.top ) + curTop;\n    }\n    if ( options.left != null ) {\n      props.left = ( options.left - curOffset.left ) + curLeft;\n    }\n\n    if ( \"using\" in options ) {\n      options.using.call( elem, props );\n    } else {\n      curElem.css( props );\n    }\n  }\n};\n\n\njQuery.fn.extend({\n\n  position: function() {\n    if ( !this[0] ) {\n      return;\n    }\n\n    var elem = this[0],\n\n    // Get *real* offsetParent\n    offsetParent = this.offsetParent(),\n\n    // Get correct offsets\n    offset       = this.offset(),\n    parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n    // Subtract element margins\n    // note: when an element has margin: auto the offsetLeft and marginLeft\n    // are the same in Safari causing offset.left to incorrectly be 0\n    offset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n    offset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n    // Add offsetParent borders\n    parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n    parentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n    // Subtract the two offsets\n    return {\n      top:  offset.top  - parentOffset.top,\n      left: offset.left - parentOffset.left\n    };\n  },\n\n  offsetParent: function() {\n    return this.map(function() {\n      var offsetParent = this.offsetParent || document.body;\n      while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n        offsetParent = offsetParent.offsetParent;\n      }\n      return offsetParent || document.body;\n    });\n  }\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n  var top = /Y/.test( prop );\n\n  jQuery.fn[ method ] = function( val ) {\n    return jQuery.access( this, function( elem, method, val ) {\n      var win = getWindow( elem );\n\n      if ( val === undefined ) {\n        return win ? (prop in win) ? win[ prop ] :\n          win.document.documentElement[ method ] :\n          elem[ method ];\n      }\n\n      if ( win ) {\n        win.scrollTo(\n          !top ? val : jQuery( win ).scrollLeft(),\n           top ? val : jQuery( win ).scrollTop()\n        );\n\n      } else {\n        elem[ method ] = val;\n      }\n    }, method, val, arguments.length, null );\n  };\n});\n\nfunction getWindow( elem ) {\n  return jQuery.isWindow( elem ) ?\n    elem :\n    elem.nodeType === 9 ?\n      elem.defaultView || elem.parentWindow :\n      false;\n}\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n  jQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n    // margin is only for outerHeight, outerWidth\n    jQuery.fn[ funcName ] = function( margin, value ) {\n      var chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n        extra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n      return jQuery.access( this, function( elem, type, value ) {\n        var doc;\n\n        if ( jQuery.isWindow( elem ) ) {\n          // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n          // isn't a whole lot we can do. See pull request at this URL for discussion:\n          // https://github.com/jquery/jquery/pull/764\n          return elem.document.documentElement[ \"client\" + name ];\n        }\n\n        // Get document width or height\n        if ( elem.nodeType === 9 ) {\n          doc = elem.documentElement;\n\n          // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest\n          // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.\n          return Math.max(\n            elem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n            elem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n            doc[ \"client\" + name ]\n          );\n        }\n\n        return value === undefined ?\n          // Get width or height on the element, requesting but not forcing parseFloat\n          jQuery.css( elem, type, value, extra ) :\n\n          // Set width or height on the element\n          jQuery.style( elem, type, value, extra );\n      }, type, chainable ? margin : undefined, chainable, null );\n    };\n  });\n});\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n  define( \"jquery\", [], function () { return jQuery; } );\n}\n\n})( window );",
+			"settings":
+			{
+				"buffer_size": 287804,
+				"line_ending": "Unix",
+				"name": "/*!"
+			}
+		},
+		{
+			"file": "test/integration/test-submit.js",
+			"settings":
+			{
+				"buffer_size": 3638,
+				"line_ending": "Unix"
+			}
+		},
+		{
+			"file": "test/integration/test-submit-custom.js",
+			"settings":
+			{
+				"buffer_size": 3684,
+				"line_ending": "Unix"
+			}
+		},
+		{
+			"file": "test/integration/test-http-response.js",
+			"settings":
+			{
+				"buffer_size": 3109,
+				"line_ending": "Unix"
+			}
+		},
+		{
+			"file": "Readme.md",
+			"settings":
+			{
+				"buffer_size": 2774,
+				"line_ending": "Unix"
+			}
+		},
+		{
+			"contents": "var CRLF = '\\r\\n';\nvar form = new FormData();\n\nvar options = {\n  header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,\n  knownLength: 1\n};\n\nform.append('my_buffer', buffer, options);\n\nform.submit('http://example.com/', function(err, res) {\n  if (err) throw err;\n  console.log('Done');\n});",
+			"settings":
+			{
+				"buffer_size": 322,
+				"line_ending": "Unix"
+			}
+		},
+		{
+			"file": "test/run.js",
+			"settings":
+			{
+				"buffer_size": 121,
+				"line_ending": "Unix"
+			}
+		}
+	],
+	"build_system": "",
+	"command_palette":
+	{
+		"height": 87.0,
+		"selected_items":
+		[
+			[
+				"Package Control: in",
+				"Package Control: Install Package"
+			],
+			[
+				"Package Control: ins",
+				"Package Control: Install Package"
+			],
+			[
+				"ins",
+				"Package Control: Install Package"
+			],
+			[
+				"insta",
+				"Package Control: Install Package"
+			]
+		],
+		"width": 467.0
+	},
+	"console":
+	{
+		"height": 125.0
+	},
+	"distraction_free":
+	{
+		"menu_visible": true,
+		"show_minimap": false,
+		"show_open_files": false,
+		"show_tabs": false,
+		"side_bar_visible": false,
+		"status_bar_visible": false
+	},
+	"file_history":
+	[
+		"/Users/alexi/Dropbox/Projects/node-form-data/test/integration/test-http-respone.js",
+		"/Users/alexi/Dropbox/Projects/node-form-data/test/run.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/sftp-config-alt.json",
+		"/Users/alexi/Desktop/test/file.txt",
+		"/Users/alexi/Desktop/stuff/kodak/web.js",
+		"/Users/alexi/Desktop/test/test1.js",
+		"/Users/alexi/Desktop/test/spdy.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/bin/echo.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/static/test.html",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/bin/passthrough_stream.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/node_modules/request/main.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/node_modules/request/tests/test-pipes.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/static/a/main.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/node_modules/flickr/lib/flickr.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/node_modules/socket.io/lib/socket.io.js",
+		"/var/folders/xn/475pdrpd72n4s6gdh4y_c2dm0000gn/T/sublime-sftp-browse-1342313240/mapped/var/www/libereco.ia.gs/node_modules/oauth/lib/oauth.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/node_modules/flickr/node_modules/oauth/lib/oauth.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/node_modules/flickr/index.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/node_modules/socket.io/index.js",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/sftp-config.json",
+		"/Users/alexi/Dropbox/Projects/libereco.ia.gs/public/index.html",
+		"/Users/alexi/Desktop/kodak/dns.js",
+		"/Users/alexi/Dropbox/Projects/500.ia.gs/htdocs/s/fonts.css",
+		"/Users/alexi/Dropbox/Projects/ia.gs/sftp-config.json",
+		"/Users/alexi/Downloads/fabric_plaid.png",
+		"/Users/alexi/Library/Application Support/Sublime Text 2/Packages/Default/Global.sublime-settings",
+		"/Users/alexi/Dropbox/Projects/ia.gs/node_modules/director/lib/director/router.js",
+		"/Users/alexi/Dropbox/Projects/ia.gs/web/e/404.html",
+		"/Users/alexi/Dropbox/Projects/ia.gs/web/e/500.html",
+		"/Users/alexi/Dropbox/Projects/ia.gs/node_modules/director/lib/director/http/index.js",
+		"/Users/alexi/Library/Application Support/Sublime Text 2/Packages/SFTP/SFTP.sublime-settings",
+		"/Users/alexi/Library/Application Support/Sublime Text 2/Packages/SFTP/Default (OSX).sublime-keymap",
+		"/Users/alexi/Sites/new/sftp-config.json",
+		"/Users/alexi/Sites/new/polarbear.css",
+		"/Users/alexi/Library/Application Support/Sublime Text 2/Packages/User/Base File.sublime-settings",
+		"/Users/alexi/Library/Application Support/Sublime Text 2/Packages/Default/Base File.sublime-settings",
+		"/Users/alexi/Sites/new/include/Controllers/Home/HomepageController.php"
+	],
+	"find":
+	{
+		"height": 35.0
+	},
+	"find_in_files":
+	{
+		"height": 0.0,
+		"where_history":
+		[
+			""
+		]
+	},
+	"find_state":
+	{
+		"case_sensitive": false,
+		"find_history":
+		[
+			"readable",
+			"argument",
+			"mikeal",
+			"return;",
+			"throw arguments[1]",
+			"arguments[1]",
+			"throw arguments",
+			"throw arguments[1]",
+			"path",
+			"conso",
+			"isStreamLike",
+			"parseUrl",
+			"stream",
+			"node.js",
+			"stream",
+			"http://libereco.ia.gs/",
+			"flickr_message_nopro",
+			"auth:done",
+			"con",
+			"console",
+			"photos",
+			"isReadStream",
+			"Buffer",
+			"Bufer",
+			"multipart",
+			"sig",
+			"api",
+			"api_",
+			"api_sig",
+			"writeFile",
+			"googledoodle.png",
+			"attachment",
+			"_write",
+			"fs",
+			"mime",
+			"_putOrPost",
+			"_performSecureRequest",
+			"8034",
+			"try",
+			"paramsToQueryString",
+			"_executeOAuthAPIRequest",
+			"oauth_client",
+			"_createClient",
+			"authorization",
+			"body",
+			"_performSecureRequest",
+			"query",
+			"io.",
+			".listen",
+			"io",
+			"config",
+			"set",
+			"console",
+			"'next'",
+			"console",
+			"_asyncEverySeries",
+			"runlist",
+			"function",
+			"async",
+			"local",
+			"Find schools",
+			"What's up"
+		],
+		"highlight": true,
+		"in_selection": false,
+		"preserve_case": false,
+		"regex": false,
+		"replace_history":
+		[
+		],
+		"reverse": false,
+		"show_context": true,
+		"use_buffer2": true,
+		"whole_word": false,
+		"wrap": true
+	},
+	"groups":
+	[
+		{
+			"selected": 1,
+			"sheets":
+			[
+				{
+					"buffer": 0,
+					"file": "test/integration/test-pipe.js",
+					"settings":
+					{
+						"buffer_size": 3625,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								654,
+								673
+							]
+						],
+						"settings":
+						{
+							"function_name_status_row": 18,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/JavaScript/JavaScript.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 238.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				},
+				{
+					"buffer": 1,
+					"file": "package.json",
+					"settings":
+					{
+						"buffer_size": 673,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								282,
+								282
+							]
+						],
+						"settings":
+						{
+							"function_name_status_row": 4,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/JavaScript/JSON.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 0.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				},
+				{
+					"buffer": 2,
+					"file": "lib/form_data.js",
+					"settings":
+					{
+						"buffer_size": 7510,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								1940,
+								1940
+							]
+						],
+						"settings":
+						{
+							"function_name_status_row": 65,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/JavaScript/JavaScript.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 658.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				},
+				{
+					"buffer": 3,
+					"settings":
+					{
+						"buffer_size": 287804,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								8273,
+								8279
+							]
+						],
+						"settings":
+						{
+							"auto_name": "/*!",
+							"function_name_status_row": 290,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/JavaScript/JavaScript.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 5683.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				},
+				{
+					"buffer": 4,
+					"file": "test/integration/test-submit.js",
+					"settings":
+					{
+						"buffer_size": 3638,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								3556,
+								3556
+							]
+						],
+						"settings":
+						{
+							"function_name_status_row": 111,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/JavaScript/JavaScript.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 1200.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				},
+				{
+					"buffer": 5,
+					"file": "test/integration/test-submit-custom.js",
+					"settings":
+					{
+						"buffer_size": 3684,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								3449,
+								3449
+							]
+						],
+						"settings":
+						{
+							"function_name_status_row": 104,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/JavaScript/JavaScript.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 1268.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				},
+				{
+					"buffer": 6,
+					"file": "test/integration/test-http-response.js",
+					"settings":
+					{
+						"buffer_size": 3109,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								2156,
+								2156
+							]
+						],
+						"settings":
+						{
+							"function_name_status_row": 88,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/JavaScript/JavaScript.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 59.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				},
+				{
+					"buffer": 7,
+					"file": "Readme.md",
+					"settings":
+					{
+						"buffer_size": 2774,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								0,
+								0
+							]
+						],
+						"settings":
+						{
+							"function_name_status_row": 0,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/Markdown/Markdown.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 996.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				},
+				{
+					"buffer": 8,
+					"settings":
+					{
+						"buffer_size": 322,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								0,
+								322
+							]
+						],
+						"settings":
+						{
+							"function_name_status_row": 0,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/JavaScript/JavaScript.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 0.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				},
+				{
+					"buffer": 9,
+					"file": "test/run.js",
+					"settings":
+					{
+						"buffer_size": 121,
+						"regions":
+						{
+						},
+						"selection":
+						[
+							[
+								76,
+								76
+							]
+						],
+						"settings":
+						{
+							"function_name_status_row": 4,
+							"incomplete_sync": null,
+							"remote_loading": false,
+							"synced": false,
+							"syntax": "Packages/JavaScript/JavaScript.tmLanguage"
+						},
+						"translation.x": 0.0,
+						"translation.y": 0.0,
+						"zoom_level": 1.0
+					},
+					"type": "text"
+				}
+			]
+		}
+	],
+	"incremental_find":
+	{
+		"height": 0.0
+	},
+	"input":
+	{
+		"height": 31.0
+	},
+	"layout":
+	{
+		"cells":
+		[
+			[
+				0,
+				0,
+				1,
+				1
+			]
+		],
+		"cols":
+		[
+			0.0,
+			1.0
+		],
+		"rows":
+		[
+			0.0,
+			1.0
+		]
+	},
+	"menu_visible": true,
+	"output.sftp":
+	{
+		"height": 108.0
+	},
+	"replace":
+	{
+		"height": 0.0
+	},
+	"save_all_on_build": true,
+	"select_file":
+	{
+		"height": 0.0,
+		"selected_items":
+		[
+			[
+				"homepagecon",
+				"include/Controllers/Home/HomepageController.php"
+			],
+			[
+				"polar",
+				"polarbear.css"
+			],
+			[
+				"homepageco",
+				"include/Controllers/Home/HomepageController.php"
+			],
+			[
+				"homepage.js",
+				"include/js/application/homepage/homepage.js"
+			]
+		],
+		"width": 0.0
+	},
+	"select_project":
+	{
+		"height": 0.0,
+		"selected_items":
+		[
+		],
+		"width": 0.0
+	},
+	"show_minimap": true,
+	"show_open_files": true,
+	"show_tabs": true,
+	"side_bar_visible": true,
+	"side_bar_width": 250.0,
+	"status_bar_visible": true
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/LICENSE	(revision 484)
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Caolan McMahon
+
+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.
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/README.md	(revision 484)
@@ -0,0 +1,1414 @@
+# Async.js
+
+Async is a utility module which provides straight-forward, powerful functions
+for working with asynchronous JavaScript. Although originally designed for
+use with [node.js](http://nodejs.org), it can also be used directly in the
+browser. Also supports [component](https://github.com/component/component).
+
+Async provides around 20 functions that include the usual 'functional'
+suspects (map, reduce, filter, eachâŠ) as well as some common patterns
+for asynchronous control flow (parallel, series, waterfallâŠ). All these
+functions assume you follow the node.js convention of providing a single
+callback as the last argument of your async function.
+
+
+## Quick Examples
+
+```javascript
+async.map(['file1','file2','file3'], fs.stat, function(err, results){
+    // results is now an array of stats for each file
+});
+
+async.filter(['file1','file2','file3'], fs.exists, function(results){
+    // results now equals an array of the existing files
+});
+
+async.parallel([
+    function(){ ... },
+    function(){ ... }
+], callback);
+
+async.series([
+    function(){ ... },
+    function(){ ... }
+]);
+```
+
+There are many more functions available so take a look at the docs below for a
+full list. This module aims to be comprehensive, so if you feel anything is
+missing please create a GitHub issue for it.
+
+## Common Pitfalls
+
+### Binding a context to an iterator
+
+This section is really about bind, not about async. If you are wondering how to
+make async execute your iterators in a given context, or are confused as to why
+a method of another library isn't working as an iterator, study this example:
+
+```js
+// Here is a simple object with an (unnecessarily roundabout) squaring method
+var AsyncSquaringLibrary = {
+  squareExponent: 2,
+  square: function(number, callback){ 
+    var result = Math.pow(number, this.squareExponent);
+    setTimeout(function(){
+      callback(null, result);
+    }, 200);
+  }
+};
+
+async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){
+  // result is [NaN, NaN, NaN]
+  // This fails because the `this.squareExponent` expression in the square
+  // function is not evaluated in the context of AsyncSquaringLibrary, and is
+  // therefore undefined.
+});
+
+async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){
+  // result is [1, 4, 9]
+  // With the help of bind we can attach a context to the iterator before
+  // passing it to async. Now the square function will be executed in its 
+  // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`
+  // will be as expected.
+});
+```
+
+## Download
+
+The source is available for download from
+[GitHub](http://github.com/caolan/async).
+Alternatively, you can install using Node Package Manager (npm):
+
+    npm install async
+
+__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed
+
+## In the Browser
+
+So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:
+
+```html
+<script type="text/javascript" src="async.js"></script>
+<script type="text/javascript">
+
+    async.map(data, asyncProcess, function(err, results){
+        alert(results);
+    });
+
+</script>
+```
+
+## Documentation
+
+### Collections
+
+* [each](#each)
+* [map](#map)
+* [filter](#filter)
+* [reject](#reject)
+* [reduce](#reduce)
+* [detect](#detect)
+* [sortBy](#sortBy)
+* [some](#some)
+* [every](#every)
+* [concat](#concat)
+
+### Control Flow
+
+* [series](#series)
+* [parallel](#parallel)
+* [whilst](#whilst)
+* [doWhilst](#doWhilst)
+* [until](#until)
+* [doUntil](#doUntil)
+* [forever](#forever)
+* [waterfall](#waterfall)
+* [compose](#compose)
+* [applyEach](#applyEach)
+* [queue](#queue)
+* [cargo](#cargo)
+* [auto](#auto)
+* [iterator](#iterator)
+* [apply](#apply)
+* [nextTick](#nextTick)
+* [times](#times)
+* [timesSeries](#timesSeries)
+
+### Utils
+
+* [memoize](#memoize)
+* [unmemoize](#unmemoize)
+* [log](#log)
+* [dir](#dir)
+* [noConflict](#noConflict)
+
+
+## Collections
+
+<a name="forEach" />
+<a name="each" />
+### each(arr, iterator, callback)
+
+Applies an iterator function to each item in an array, in parallel.
+The iterator is called with an item from the list and a callback for when it
+has finished. If the iterator passes an error to this callback, the main
+callback for the each function is immediately called with the error.
+
+Note, that since this function applies the iterator to each item in parallel
+there is no guarantee that the iterator functions will complete in order.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err) which must be called once it has 
+  completed. If no error has occured, the callback should be run without 
+  arguments or with an explicit null argument.
+* callback(err) - A callback which is called after all the iterator functions
+  have finished, or an error has occurred.
+
+__Example__
+
+```js
+// assuming openFiles is an array of file names and saveFile is a function
+// to save the modified contents of that file:
+
+async.each(openFiles, saveFile, function(err){
+    // if any of the saves produced an error, err would equal that error
+});
+```
+
+---------------------------------------
+
+<a name="forEachSeries" />
+<a name="eachSeries" />
+### eachSeries(arr, iterator, callback)
+
+The same as each only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. This means the iterator functions will complete in order.
+
+
+---------------------------------------
+
+<a name="forEachLimit" />
+<a name="eachLimit" />
+### eachLimit(arr, limit, iterator, callback)
+
+The same as each only no more than "limit" iterators will be simultaneously 
+running at any time.
+
+Note that the items are not processed in batches, so there is no guarantee that
+ the first "limit" iterator functions will complete before any others are 
+started.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* limit - The maximum number of iterators to run at any time.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err) which must be called once it has 
+  completed. If no error has occured, the callback should be run without 
+  arguments or with an explicit null argument.
+* callback(err) - A callback which is called after all the iterator functions
+  have finished, or an error has occurred.
+
+__Example__
+
+```js
+// Assume documents is an array of JSON objects and requestApi is a
+// function that interacts with a rate-limited REST api.
+
+async.eachLimit(documents, 20, requestApi, function(err){
+    // if any of the saves produced an error, err would equal that error
+});
+```
+
+---------------------------------------
+
+<a name="map" />
+### map(arr, iterator, callback)
+
+Produces a new array of values by mapping each value in the given array through
+the iterator function. The iterator is called with an item from the array and a
+callback for when it has finished processing. The callback takes 2 arguments, 
+an error and the transformed item from the array. If the iterator passes an
+error to this callback, the main callback for the map function is immediately
+called with the error.
+
+Note, that since this function applies the iterator to each item in parallel
+there is no guarantee that the iterator functions will complete in order, however
+the results array will be in the same order as the original array.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err, transformed) which must be called once 
+  it has completed with an error (which can be null) and a transformed item.
+* callback(err, results) - A callback which is called after all the iterator
+  functions have finished, or an error has occurred. Results is an array of the
+  transformed items from the original array.
+
+__Example__
+
+```js
+async.map(['file1','file2','file3'], fs.stat, function(err, results){
+    // results is now an array of stats for each file
+});
+```
+
+---------------------------------------
+
+<a name="mapSeries" />
+### mapSeries(arr, iterator, callback)
+
+The same as map only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+
+---------------------------------------
+
+<a name="mapLimit" />
+### mapLimit(arr, limit, iterator, callback)
+
+The same as map only no more than "limit" iterators will be simultaneously 
+running at any time.
+
+Note that the items are not processed in batches, so there is no guarantee that
+ the first "limit" iterator functions will complete before any others are 
+started.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* limit - The maximum number of iterators to run at any time.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err, transformed) which must be called once 
+  it has completed with an error (which can be null) and a transformed item.
+* callback(err, results) - A callback which is called after all the iterator
+  functions have finished, or an error has occurred. Results is an array of the
+  transformed items from the original array.
+
+__Example__
+
+```js
+async.map(['file1','file2','file3'], 1, fs.stat, function(err, results){
+    // results is now an array of stats for each file
+});
+```
+
+---------------------------------------
+
+<a name="filter" />
+### filter(arr, iterator, callback)
+
+__Alias:__ select
+
+Returns a new array of all the values which pass an async truth test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like fs.exists. This operation is
+performed in parallel, but the results array will be in the same order as the
+original.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+  The iterator is passed a callback(truthValue) which must be called with a 
+  boolean argument once it has completed.
+* callback(results) - A callback which is called after all the iterator
+  functions have finished.
+
+__Example__
+
+```js
+async.filter(['file1','file2','file3'], fs.exists, function(results){
+    // results now equals an array of the existing files
+});
+```
+
+---------------------------------------
+
+<a name="filterSeries" />
+### filterSeries(arr, iterator, callback)
+
+__alias:__ selectSeries
+
+The same as filter only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+---------------------------------------
+
+<a name="reject" />
+### reject(arr, iterator, callback)
+
+The opposite of filter. Removes values that pass an async truth test.
+
+---------------------------------------
+
+<a name="rejectSeries" />
+### rejectSeries(arr, iterator, callback)
+
+The same as reject, only the iterator is applied to each item in the array
+in series.
+
+
+---------------------------------------
+
+<a name="reduce" />
+### reduce(arr, memo, iterator, callback)
+
+__aliases:__ inject, foldl
+
+Reduces a list of values into a single value using an async iterator to return
+each successive step. Memo is the initial state of the reduction. This
+function only operates in series. For performance reasons, it may make sense to
+split a call to this function into a parallel map, then use the normal
+Array.prototype.reduce on the results. This function is for situations where
+each step in the reduction needs to be async, if you can get the data before
+reducing it then it's probably a good idea to do so.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* memo - The initial state of the reduction.
+* iterator(memo, item, callback) - A function applied to each item in the
+  array to produce the next step in the reduction. The iterator is passed a
+  callback(err, reduction) which accepts an optional error as its first 
+  argument, and the state of the reduction as the second. If an error is 
+  passed to the callback, the reduction is stopped and the main callback is 
+  immediately called with the error.
+* callback(err, result) - A callback which is called after all the iterator
+  functions have finished. Result is the reduced value.
+
+__Example__
+
+```js
+async.reduce([1,2,3], 0, function(memo, item, callback){
+    // pointless async:
+    process.nextTick(function(){
+        callback(null, memo + item)
+    });
+}, function(err, result){
+    // result is now equal to the last value of memo, which is 6
+});
+```
+
+---------------------------------------
+
+<a name="reduceRight" />
+### reduceRight(arr, memo, iterator, callback)
+
+__Alias:__ foldr
+
+Same as reduce, only operates on the items in the array in reverse order.
+
+
+---------------------------------------
+
+<a name="detect" />
+### detect(arr, iterator, callback)
+
+Returns the first value in a list that passes an async truth test. The
+iterator is applied in parallel, meaning the first iterator to return true will
+fire the detect callback with that result. That means the result might not be
+the first item in the original array (in terms of order) that passes the test.
+
+If order within the original array is important then look at detectSeries.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+  The iterator is passed a callback(truthValue) which must be called with a 
+  boolean argument once it has completed.
+* callback(result) - A callback which is called as soon as any iterator returns
+  true, or after all the iterator functions have finished. Result will be
+  the first item in the array that passes the truth test (iterator) or the
+  value undefined if none passed.
+
+__Example__
+
+```js
+async.detect(['file1','file2','file3'], fs.exists, function(result){
+    // result now equals the first file in the list that exists
+});
+```
+
+---------------------------------------
+
+<a name="detectSeries" />
+### detectSeries(arr, iterator, callback)
+
+The same as detect, only the iterator is applied to each item in the array
+in series. This means the result is always the first in the original array (in
+terms of array order) that passes the truth test.
+
+
+---------------------------------------
+
+<a name="sortBy" />
+### sortBy(arr, iterator, callback)
+
+Sorts a list by the results of running each value through an async iterator.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err, sortValue) which must be called once it
+  has completed with an error (which can be null) and a value to use as the sort
+  criteria.
+* callback(err, results) - A callback which is called after all the iterator
+  functions have finished, or an error has occurred. Results is the items from
+  the original array sorted by the values returned by the iterator calls.
+
+__Example__
+
+```js
+async.sortBy(['file1','file2','file3'], function(file, callback){
+    fs.stat(file, function(err, stats){
+        callback(err, stats.mtime);
+    });
+}, function(err, results){
+    // results is now the original array of files sorted by
+    // modified date
+});
+```
+
+---------------------------------------
+
+<a name="some" />
+### some(arr, iterator, callback)
+
+__Alias:__ any
+
+Returns true if at least one element in the array satisfies an async test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like fs.exists. Once any iterator
+call returns true, the main callback is immediately called.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+  The iterator is passed a callback(truthValue) which must be called with a 
+  boolean argument once it has completed.
+* callback(result) - A callback which is called as soon as any iterator returns
+  true, or after all the iterator functions have finished. Result will be
+  either true or false depending on the values of the async tests.
+
+__Example__
+
+```js
+async.some(['file1','file2','file3'], fs.exists, function(result){
+    // if result is true then at least one of the files exists
+});
+```
+
+---------------------------------------
+
+<a name="every" />
+### every(arr, iterator, callback)
+
+__Alias:__ all
+
+Returns true if every element in the array satisfies an async test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like fs.exists.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+  The iterator is passed a callback(truthValue) which must be called with a 
+  boolean argument once it has completed.
+* callback(result) - A callback which is called after all the iterator
+  functions have finished. Result will be either true or false depending on
+  the values of the async tests.
+
+__Example__
+
+```js
+async.every(['file1','file2','file3'], fs.exists, function(result){
+    // if result is true then every file exists
+});
+```
+
+---------------------------------------
+
+<a name="concat" />
+### concat(arr, iterator, callback)
+
+Applies an iterator to each item in a list, concatenating the results. Returns the
+concatenated list. The iterators are called in parallel, and the results are
+concatenated as they return. There is no guarantee that the results array will
+be returned in the original order of the arguments passed to the iterator function.
+
+__Arguments__
+
+* arr - An array to iterate over
+* iterator(item, callback) - A function to apply to each item in the array.
+  The iterator is passed a callback(err, results) which must be called once it 
+  has completed with an error (which can be null) and an array of results.
+* callback(err, results) - A callback which is called after all the iterator
+  functions have finished, or an error has occurred. Results is an array containing
+  the concatenated results of the iterator function.
+
+__Example__
+
+```js
+async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){
+    // files is now a list of filenames that exist in the 3 directories
+});
+```
+
+---------------------------------------
+
+<a name="concatSeries" />
+### concatSeries(arr, iterator, callback)
+
+Same as async.concat, but executes in series instead of parallel.
+
+
+## Control Flow
+
+<a name="series" />
+### series(tasks, [callback])
+
+Run an array of functions in series, each one running once the previous
+function has completed. If any functions in the series pass an error to its
+callback, no more functions are run and the callback for the series is
+immediately called with the value of the error. Once the tasks have completed,
+the results are passed to the final callback as an array.
+
+It is also possible to use an object instead of an array. Each property will be
+run as a function and the results will be passed to the final callback as an object
+instead of an array. This can be a more readable way of handling results from
+async.series.
+
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed
+  a callback(err, result) it must call on completion with an error (which can
+  be null) and an optional result value.
+* callback(err, results) - An optional callback to run once all the functions
+  have completed. This function gets a results array (or object) containing all 
+  the result arguments passed to the task callbacks.
+
+__Example__
+
+```js
+async.series([
+    function(callback){
+        // do some stuff ...
+        callback(null, 'one');
+    },
+    function(callback){
+        // do some more stuff ...
+        callback(null, 'two');
+    }
+],
+// optional callback
+function(err, results){
+    // results is now equal to ['one', 'two']
+});
+
+
+// an example using an object instead of an array
+async.series({
+    one: function(callback){
+        setTimeout(function(){
+            callback(null, 1);
+        }, 200);
+    },
+    two: function(callback){
+        setTimeout(function(){
+            callback(null, 2);
+        }, 100);
+    }
+},
+function(err, results) {
+    // results is now equal to: {one: 1, two: 2}
+});
+```
+
+---------------------------------------
+
+<a name="parallel" />
+### parallel(tasks, [callback])
+
+Run an array of functions in parallel, without waiting until the previous
+function has completed. If any of the functions pass an error to its
+callback, the main callback is immediately called with the value of the error.
+Once the tasks have completed, the results are passed to the final callback as an
+array.
+
+It is also possible to use an object instead of an array. Each property will be
+run as a function and the results will be passed to the final callback as an object
+instead of an array. This can be a more readable way of handling results from
+async.parallel.
+
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed 
+  a callback(err, result) it must call on completion with an error (which can
+  be null) and an optional result value.
+* callback(err, results) - An optional callback to run once all the functions
+  have completed. This function gets a results array (or object) containing all 
+  the result arguments passed to the task callbacks.
+
+__Example__
+
+```js
+async.parallel([
+    function(callback){
+        setTimeout(function(){
+            callback(null, 'one');
+        }, 200);
+    },
+    function(callback){
+        setTimeout(function(){
+            callback(null, 'two');
+        }, 100);
+    }
+],
+// optional callback
+function(err, results){
+    // the results array will equal ['one','two'] even though
+    // the second function had a shorter timeout.
+});
+
+
+// an example using an object instead of an array
+async.parallel({
+    one: function(callback){
+        setTimeout(function(){
+            callback(null, 1);
+        }, 200);
+    },
+    two: function(callback){
+        setTimeout(function(){
+            callback(null, 2);
+        }, 100);
+    }
+},
+function(err, results) {
+    // results is now equals to: {one: 1, two: 2}
+});
+```
+
+---------------------------------------
+
+<a name="parallel" />
+### parallelLimit(tasks, limit, [callback])
+
+The same as parallel only the tasks are executed in parallel with a maximum of "limit" 
+tasks executing at any time.
+
+Note that the tasks are not executed in batches, so there is no guarantee that 
+the first "limit" tasks will complete before any others are started.
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed 
+  a callback(err, result) it must call on completion with an error (which can
+  be null) and an optional result value.
+* limit - The maximum number of tasks to run at any time.
+* callback(err, results) - An optional callback to run once all the functions
+  have completed. This function gets a results array (or object) containing all 
+  the result arguments passed to the task callbacks.
+
+---------------------------------------
+
+<a name="whilst" />
+### whilst(test, fn, callback)
+
+Repeatedly call fn, while test returns true. Calls the callback when stopped,
+or an error occurs.
+
+__Arguments__
+
+* test() - synchronous truth test to perform before each execution of fn.
+* fn(callback) - A function to call each time the test passes. The function is
+  passed a callback(err) which must be called once it has completed with an 
+  optional error argument.
+* callback(err) - A callback which is called after the test fails and repeated
+  execution of fn has stopped.
+
+__Example__
+
+```js
+var count = 0;
+
+async.whilst(
+    function () { return count < 5; },
+    function (callback) {
+        count++;
+        setTimeout(callback, 1000);
+    },
+    function (err) {
+        // 5 seconds have passed
+    }
+);
+```
+
+---------------------------------------
+
+<a name="doWhilst" />
+### doWhilst(fn, test, callback)
+
+The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
+
+---------------------------------------
+
+<a name="until" />
+### until(test, fn, callback)
+
+Repeatedly call fn, until test returns true. Calls the callback when stopped,
+or an error occurs.
+
+The inverse of async.whilst.
+
+---------------------------------------
+
+<a name="doUntil" />
+### doUntil(fn, test, callback)
+
+Like doWhilst except the test is inverted. Note the argument ordering differs from `until`.
+
+---------------------------------------
+
+<a name="forever" />
+### forever(fn, callback)
+
+Calls the asynchronous function 'fn' repeatedly, in series, indefinitely.
+If an error is passed to fn's callback then 'callback' is called with the
+error, otherwise it will never be called.
+
+---------------------------------------
+
+<a name="waterfall" />
+### waterfall(tasks, [callback])
+
+Runs an array of functions in series, each passing their results to the next in
+the array. However, if any of the functions pass an error to the callback, the
+next function is not executed and the main callback is immediately called with
+the error.
+
+__Arguments__
+
+* tasks - An array of functions to run, each function is passed a 
+  callback(err, result1, result2, ...) it must call on completion. The first
+  argument is an error (which can be null) and any further arguments will be 
+  passed as arguments in order to the next task.
+* callback(err, [results]) - An optional callback to run once all the functions
+  have completed. This will be passed the results of the last task's callback.
+
+
+
+__Example__
+
+```js
+async.waterfall([
+    function(callback){
+        callback(null, 'one', 'two');
+    },
+    function(arg1, arg2, callback){
+        callback(null, 'three');
+    },
+    function(arg1, callback){
+        // arg1 now equals 'three'
+        callback(null, 'done');
+    }
+], function (err, result) {
+   // result now equals 'done'    
+});
+```
+
+---------------------------------------
+<a name="compose" />
+### compose(fn1, fn2...)
+
+Creates a function which is a composition of the passed asynchronous
+functions. Each function consumes the return value of the function that
+follows. Composing functions f(), g() and h() would produce the result of
+f(g(h())), only this version uses callbacks to obtain the return values.
+
+Each function is executed with the `this` binding of the composed function.
+
+__Arguments__
+
+* functions... - the asynchronous functions to compose
+
+
+__Example__
+
+```js
+function add1(n, callback) {
+    setTimeout(function () {
+        callback(null, n + 1);
+    }, 10);
+}
+
+function mul3(n, callback) {
+    setTimeout(function () {
+        callback(null, n * 3);
+    }, 10);
+}
+
+var add1mul3 = async.compose(mul3, add1);
+
+add1mul3(4, function (err, result) {
+   // result now equals 15
+});
+```
+
+---------------------------------------
+<a name="applyEach" />
+### applyEach(fns, args..., callback)
+
+Applies the provided arguments to each function in the array, calling the
+callback after all functions have completed. If you only provide the first
+argument then it will return a function which lets you pass in the
+arguments as if it were a single function call.
+
+__Arguments__
+
+* fns - the asynchronous functions to all call with the same arguments
+* args... - any number of separate arguments to pass to the function
+* callback - the final argument should be the callback, called when all
+  functions have completed processing
+
+
+__Example__
+
+```js
+async.applyEach([enableSearch, updateSchema], 'bucket', callback);
+
+// partial application example:
+async.each(
+    buckets,
+    async.applyEach([enableSearch, updateSchema]),
+    callback
+);
+```
+
+---------------------------------------
+
+<a name="applyEachSeries" />
+### applyEachSeries(arr, iterator, callback)
+
+The same as applyEach only the functions are applied in series.
+
+---------------------------------------
+
+<a name="queue" />
+### queue(worker, concurrency)
+
+Creates a queue object with the specified concurrency. Tasks added to the
+queue will be processed in parallel (up to the concurrency limit). If all
+workers are in progress, the task is queued until one is available. Once
+a worker has completed a task, the task's callback is called.
+
+__Arguments__
+
+* worker(task, callback) - An asynchronous function for processing a queued
+  task, which must call its callback(err) argument when finished, with an 
+  optional error as an argument.
+* concurrency - An integer for determining how many worker functions should be
+  run in parallel.
+
+__Queue objects__
+
+The queue object returned by this function has the following properties and
+methods:
+
+* length() - a function returning the number of items waiting to be processed.
+* concurrency - an integer for determining how many worker functions should be
+  run in parallel. This property can be changed after a queue is created to
+  alter the concurrency on-the-fly.
+* push(task, [callback]) - add a new task to the queue, the callback is called
+  once the worker has finished processing the task.
+  instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.
+* unshift(task, [callback]) - add a new task to the front of the queue.
+* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued
+* empty - a callback that is called when the last item from the queue is given to a worker
+* drain - a callback that is called when the last item from the queue has returned from the worker
+
+__Example__
+
+```js
+// create a queue object with concurrency 2
+
+var q = async.queue(function (task, callback) {
+    console.log('hello ' + task.name);
+    callback();
+}, 2);
+
+
+// assign a callback
+q.drain = function() {
+    console.log('all items have been processed');
+}
+
+// add some items to the queue
+
+q.push({name: 'foo'}, function (err) {
+    console.log('finished processing foo');
+});
+q.push({name: 'bar'}, function (err) {
+    console.log('finished processing bar');
+});
+
+// add some items to the queue (batch-wise)
+
+q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {
+    console.log('finished processing bar');
+});
+
+// add some items to the front of the queue
+
+q.unshift({name: 'bar'}, function (err) {
+    console.log('finished processing bar');
+});
+```
+
+---------------------------------------
+
+<a name="cargo" />
+### cargo(worker, [payload])
+
+Creates a cargo object with the specified payload. Tasks added to the
+cargo will be processed altogether (up to the payload limit). If the
+worker is in progress, the task is queued until it is available. Once
+the worker has completed some tasks, each callback of those tasks is called.
+
+__Arguments__
+
+* worker(tasks, callback) - An asynchronous function for processing an array of
+  queued tasks, which must call its callback(err) argument when finished, with 
+  an optional error as an argument.
+* payload - An optional integer for determining how many tasks should be
+  processed per round; if omitted, the default is unlimited.
+
+__Cargo objects__
+
+The cargo object returned by this function has the following properties and
+methods:
+
+* length() - a function returning the number of items waiting to be processed.
+* payload - an integer for determining how many tasks should be
+  process per round. This property can be changed after a cargo is created to
+  alter the payload on-the-fly.
+* push(task, [callback]) - add a new task to the queue, the callback is called
+  once the worker has finished processing the task.
+  instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.
+* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued
+* empty - a callback that is called when the last item from the queue is given to a worker
+* drain - a callback that is called when the last item from the queue has returned from the worker
+
+__Example__
+
+```js
+// create a cargo object with payload 2
+
+var cargo = async.cargo(function (tasks, callback) {
+    for(var i=0; i<tasks.length; i++){
+      console.log('hello ' + tasks[i].name);
+    }
+    callback();
+}, 2);
+
+
+// add some items
+
+cargo.push({name: 'foo'}, function (err) {
+    console.log('finished processing foo');
+});
+cargo.push({name: 'bar'}, function (err) {
+    console.log('finished processing bar');
+});
+cargo.push({name: 'baz'}, function (err) {
+    console.log('finished processing baz');
+});
+```
+
+---------------------------------------
+
+<a name="auto" />
+### auto(tasks, [callback])
+
+Determines the best order for running functions based on their requirements.
+Each function can optionally depend on other functions being completed first,
+and each function is run as soon as its requirements are satisfied. If any of
+the functions pass an error to their callback, that function will not complete
+(so any other functions depending on it will not run) and the main callback
+will be called immediately with the error. Functions also receive an object
+containing the results of functions which have completed so far.
+
+Note, all functions are called with a results object as a second argument, 
+so it is unsafe to pass functions in the tasks object which cannot handle the
+extra argument. For example, this snippet of code:
+
+```js
+async.auto({
+  readData: async.apply(fs.readFile, 'data.txt', 'utf-8');
+}, callback);
+```
+
+will have the effect of calling readFile with the results object as the last
+argument, which will fail:
+
+```js
+fs.readFile('data.txt', 'utf-8', cb, {});
+```
+
+Instead, wrap the call to readFile in a function which does not forward the 
+results object:
+
+```js
+async.auto({
+  readData: function(cb, results){
+    fs.readFile('data.txt', 'utf-8', cb);
+  }
+}, callback);
+```
+
+__Arguments__
+
+* tasks - An object literal containing named functions or an array of
+  requirements, with the function itself the last item in the array. The key
+  used for each function or array is used when specifying requirements. The 
+  function receives two arguments: (1) a callback(err, result) which must be 
+  called when finished, passing an error (which can be null) and the result of 
+  the function's execution, and (2) a results object, containing the results of
+  the previously executed functions.
+* callback(err, results) - An optional callback which is called when all the
+  tasks have been completed. The callback will receive an error as an argument
+  if any tasks pass an error to their callback. Results will always be passed
+	but if an error occurred, no other tasks will be performed, and the results
+	object will only contain partial results.
+  
+
+__Example__
+
+```js
+async.auto({
+    get_data: function(callback){
+        // async code to get some data
+    },
+    make_folder: function(callback){
+        // async code to create a directory to store a file in
+        // this is run at the same time as getting the data
+    },
+    write_file: ['get_data', 'make_folder', function(callback){
+        // once there is some data and the directory exists,
+        // write the data to a file in the directory
+        callback(null, filename);
+    }],
+    email_link: ['write_file', function(callback, results){
+        // once the file is written let's email a link to it...
+        // results.write_file contains the filename returned by write_file.
+    }]
+});
+```
+
+This is a fairly trivial example, but to do this using the basic parallel and
+series functions would look like this:
+
+```js
+async.parallel([
+    function(callback){
+        // async code to get some data
+    },
+    function(callback){
+        // async code to create a directory to store a file in
+        // this is run at the same time as getting the data
+    }
+],
+function(err, results){
+    async.series([
+        function(callback){
+            // once there is some data and the directory exists,
+            // write the data to a file in the directory
+        },
+        function(callback){
+            // once the file is written let's email a link to it...
+        }
+    ]);
+});
+```
+
+For a complicated series of async tasks using the auto function makes adding
+new tasks much easier and makes the code more readable.
+
+
+---------------------------------------
+
+<a name="iterator" />
+### iterator(tasks)
+
+Creates an iterator function which calls the next function in the array,
+returning a continuation to call the next one after that. It's also possible to
+'peek' the next iterator by doing iterator.next().
+
+This function is used internally by the async module but can be useful when
+you want to manually control the flow of functions in series.
+
+__Arguments__
+
+* tasks - An array of functions to run.
+
+__Example__
+
+```js
+var iterator = async.iterator([
+    function(){ sys.p('one'); },
+    function(){ sys.p('two'); },
+    function(){ sys.p('three'); }
+]);
+
+node> var iterator2 = iterator();
+'one'
+node> var iterator3 = iterator2();
+'two'
+node> iterator3();
+'three'
+node> var nextfn = iterator2.next();
+node> nextfn();
+'three'
+```
+
+---------------------------------------
+
+<a name="apply" />
+### apply(function, arguments..)
+
+Creates a continuation function with some arguments already applied, a useful
+shorthand when combined with other control flow functions. Any arguments
+passed to the returned function are added to the arguments originally passed
+to apply.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to automatically apply when the
+  continuation is called.
+
+__Example__
+
+```js
+// using apply
+
+async.parallel([
+    async.apply(fs.writeFile, 'testfile1', 'test1'),
+    async.apply(fs.writeFile, 'testfile2', 'test2'),
+]);
+
+
+// the same process without using apply
+
+async.parallel([
+    function(callback){
+        fs.writeFile('testfile1', 'test1', callback);
+    },
+    function(callback){
+        fs.writeFile('testfile2', 'test2', callback);
+    }
+]);
+```
+
+It's possible to pass any number of additional arguments when calling the
+continuation:
+
+```js
+node> var fn = async.apply(sys.puts, 'one');
+node> fn('two', 'three');
+one
+two
+three
+```
+
+---------------------------------------
+
+<a name="nextTick" />
+### nextTick(callback)
+
+Calls the callback on a later loop around the event loop. In node.js this just
+calls process.nextTick, in the browser it falls back to setImmediate(callback)
+if available, otherwise setTimeout(callback, 0), which means other higher priority
+events may precede the execution of the callback.
+
+This is used internally for browser-compatibility purposes.
+
+__Arguments__
+
+* callback - The function to call on a later loop around the event loop.
+
+__Example__
+
+```js
+var call_order = [];
+async.nextTick(function(){
+    call_order.push('two');
+    // call_order now equals ['one','two']
+});
+call_order.push('one')
+```
+
+<a name="times" />
+### times(n, callback)
+
+Calls the callback n times and accumulates results in the same manner
+you would use with async.map.
+
+__Arguments__
+
+* n - The number of times to run the function.
+* callback - The function to call n times.
+
+__Example__
+
+```js
+// Pretend this is some complicated async factory
+var createUser = function(id, callback) {
+  callback(null, {
+    id: 'user' + id
+  })
+}
+// generate 5 users
+async.times(5, function(n, next){
+    createUser(n, function(err, user) {
+      next(err, user)
+    })
+}, function(err, users) {
+  // we should now have 5 users
+});
+```
+
+<a name="timesSeries" />
+### timesSeries(n, callback)
+
+The same as times only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+
+## Utils
+
+<a name="memoize" />
+### memoize(fn, [hasher])
+
+Caches the results of an async function. When creating a hash to store function
+results against, the callback is omitted from the hash and an optional hash
+function can be used.
+
+The cache of results is exposed as the `memo` property of the function returned
+by `memoize`.
+
+__Arguments__
+
+* fn - the function you to proxy and cache results from.
+* hasher - an optional function for generating a custom hash for storing
+  results, it has all the arguments applied to it apart from the callback, and
+  must be synchronous.
+
+__Example__
+
+```js
+var slow_fn = function (name, callback) {
+    // do something
+    callback(null, result);
+};
+var fn = async.memoize(slow_fn);
+
+// fn can now be used as if it were slow_fn
+fn('some name', function () {
+    // callback
+});
+```
+
+<a name="unmemoize" />
+### unmemoize(fn)
+
+Undoes a memoized function, reverting it to the original, unmemoized
+form. Comes handy in tests.
+
+__Arguments__
+
+* fn - the memoized function
+
+<a name="log" />
+### log(function, arguments)
+
+Logs the result of an async function to the console. Only works in node.js or
+in browsers that support console.log and console.error (such as FF and Chrome).
+If multiple arguments are returned from the async function, console.log is
+called on each argument in order.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to apply to the function.
+
+__Example__
+
+```js
+var hello = function(name, callback){
+    setTimeout(function(){
+        callback(null, 'hello ' + name);
+    }, 1000);
+};
+```
+```js
+node> async.log(hello, 'world');
+'hello world'
+```
+
+---------------------------------------
+
+<a name="dir" />
+### dir(function, arguments)
+
+Logs the result of an async function to the console using console.dir to
+display the properties of the resulting object. Only works in node.js or
+in browsers that support console.dir and console.error (such as FF and Chrome).
+If multiple arguments are returned from the async function, console.dir is
+called on each argument in order.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to apply to the function.
+
+__Example__
+
+```js
+var hello = function(name, callback){
+    setTimeout(function(){
+        callback(null, {hello: name});
+    }, 1000);
+};
+```
+```js
+node> async.dir(hello, 'world');
+{hello: 'world'}
+```
+
+---------------------------------------
+
+<a name="noConflict" />
+### noConflict()
+
+Changes the value of async back to its original value, returning a reference to the
+async object.
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/component.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/component.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/component.json	(revision 484)
@@ -0,0 +1,11 @@
+{
+  "name": "async",
+  "repo": "caolan/async",
+  "description": "Higher-order functions and common patterns for asynchronous code",
+  "version": "0.1.23",
+  "keywords": [],
+  "dependencies": {},
+  "development": {},
+  "main": "lib/async.js",
+  "scripts": [ "lib/async.js" ]
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/lib/async.js	(revision 484)
@@ -0,0 +1,955 @@
+/*global setImmediate: false, setTimeout: false, console: false */
+(function () {
+
+    var async = {};
+
+    // global on the server, window in the browser
+    var root, previous_async;
+
+    root = this;
+    if (root != null) {
+      previous_async = root.async;
+    }
+
+    async.noConflict = function () {
+        root.async = previous_async;
+        return async;
+    };
+
+    function only_once(fn) {
+        var called = false;
+        return function() {
+            if (called) throw new Error("Callback was already called.");
+            called = true;
+            fn.apply(root, arguments);
+        }
+    }
+
+    //// cross-browser compatiblity functions ////
+
+    var _each = function (arr, iterator) {
+        if (arr.forEach) {
+            return arr.forEach(iterator);
+        }
+        for (var i = 0; i < arr.length; i += 1) {
+            iterator(arr[i], i, arr);
+        }
+    };
+
+    var _map = function (arr, iterator) {
+        if (arr.map) {
+            return arr.map(iterator);
+        }
+        var results = [];
+        _each(arr, function (x, i, a) {
+            results.push(iterator(x, i, a));
+        });
+        return results;
+    };
+
+    var _reduce = function (arr, iterator, memo) {
+        if (arr.reduce) {
+            return arr.reduce(iterator, memo);
+        }
+        _each(arr, function (x, i, a) {
+            memo = iterator(memo, x, i, a);
+        });
+        return memo;
+    };
+
+    var _keys = function (obj) {
+        if (Object.keys) {
+            return Object.keys(obj);
+        }
+        var keys = [];
+        for (var k in obj) {
+            if (obj.hasOwnProperty(k)) {
+                keys.push(k);
+            }
+        }
+        return keys;
+    };
+
+    //// exported async module functions ////
+
+    //// nextTick implementation with browser-compatible fallback ////
+    if (typeof process === 'undefined' || !(process.nextTick)) {
+        if (typeof setImmediate === 'function') {
+            async.nextTick = function (fn) {
+                // not a direct alias for IE10 compatibility
+                setImmediate(fn);
+            };
+            async.setImmediate = async.nextTick;
+        }
+        else {
+            async.nextTick = function (fn) {
+                setTimeout(fn, 0);
+            };
+            async.setImmediate = async.nextTick;
+        }
+    }
+    else {
+        async.nextTick = process.nextTick;
+        if (typeof setImmediate !== 'undefined') {
+            async.setImmediate = setImmediate;
+        }
+        else {
+            async.setImmediate = async.nextTick;
+        }
+    }
+
+    async.each = function (arr, iterator, callback) {
+        callback = callback || function () {};
+        if (!arr.length) {
+            return callback();
+        }
+        var completed = 0;
+        _each(arr, function (x) {
+            iterator(x, only_once(function (err) {
+                if (err) {
+                    callback(err);
+                    callback = function () {};
+                }
+                else {
+                    completed += 1;
+                    if (completed >= arr.length) {
+                        callback(null);
+                    }
+                }
+            }));
+        });
+    };
+    async.forEach = async.each;
+
+    async.eachSeries = function (arr, iterator, callback) {
+        callback = callback || function () {};
+        if (!arr.length) {
+            return callback();
+        }
+        var completed = 0;
+        var iterate = function () {
+            iterator(arr[completed], function (err) {
+                if (err) {
+                    callback(err);
+                    callback = function () {};
+                }
+                else {
+                    completed += 1;
+                    if (completed >= arr.length) {
+                        callback(null);
+                    }
+                    else {
+                        iterate();
+                    }
+                }
+            });
+        };
+        iterate();
+    };
+    async.forEachSeries = async.eachSeries;
+
+    async.eachLimit = function (arr, limit, iterator, callback) {
+        var fn = _eachLimit(limit);
+        fn.apply(null, [arr, iterator, callback]);
+    };
+    async.forEachLimit = async.eachLimit;
+
+    var _eachLimit = function (limit) {
+
+        return function (arr, iterator, callback) {
+            callback = callback || function () {};
+            if (!arr.length || limit <= 0) {
+                return callback();
+            }
+            var completed = 0;
+            var started = 0;
+            var running = 0;
+
+            (function replenish () {
+                if (completed >= arr.length) {
+                    return callback();
+                }
+
+                while (running < limit && started < arr.length) {
+                    started += 1;
+                    running += 1;
+                    iterator(arr[started - 1], function (err) {
+                        if (err) {
+                            callback(err);
+                            callback = function () {};
+                        }
+                        else {
+                            completed += 1;
+                            running -= 1;
+                            if (completed >= arr.length) {
+                                callback();
+                            }
+                            else {
+                                replenish();
+                            }
+                        }
+                    });
+                }
+            })();
+        };
+    };
+
+
+    var doParallel = function (fn) {
+        return function () {
+            var args = Array.prototype.slice.call(arguments);
+            return fn.apply(null, [async.each].concat(args));
+        };
+    };
+    var doParallelLimit = function(limit, fn) {
+        return function () {
+            var args = Array.prototype.slice.call(arguments);
+            return fn.apply(null, [_eachLimit(limit)].concat(args));
+        };
+    };
+    var doSeries = function (fn) {
+        return function () {
+            var args = Array.prototype.slice.call(arguments);
+            return fn.apply(null, [async.eachSeries].concat(args));
+        };
+    };
+
+
+    var _asyncMap = function (eachfn, arr, iterator, callback) {
+        var results = [];
+        arr = _map(arr, function (x, i) {
+            return {index: i, value: x};
+        });
+        eachfn(arr, function (x, callback) {
+            iterator(x.value, function (err, v) {
+                results[x.index] = v;
+                callback(err);
+            });
+        }, function (err) {
+            callback(err, results);
+        });
+    };
+    async.map = doParallel(_asyncMap);
+    async.mapSeries = doSeries(_asyncMap);
+    async.mapLimit = function (arr, limit, iterator, callback) {
+        return _mapLimit(limit)(arr, iterator, callback);
+    };
+
+    var _mapLimit = function(limit) {
+        return doParallelLimit(limit, _asyncMap);
+    };
+
+    // reduce only has a series version, as doing reduce in parallel won't
+    // work in many situations.
+    async.reduce = function (arr, memo, iterator, callback) {
+        async.eachSeries(arr, function (x, callback) {
+            iterator(memo, x, function (err, v) {
+                memo = v;
+                callback(err);
+            });
+        }, function (err) {
+            callback(err, memo);
+        });
+    };
+    // inject alias
+    async.inject = async.reduce;
+    // foldl alias
+    async.foldl = async.reduce;
+
+    async.reduceRight = function (arr, memo, iterator, callback) {
+        var reversed = _map(arr, function (x) {
+            return x;
+        }).reverse();
+        async.reduce(reversed, memo, iterator, callback);
+    };
+    // foldr alias
+    async.foldr = async.reduceRight;
+
+    var _filter = function (eachfn, arr, iterator, callback) {
+        var results = [];
+        arr = _map(arr, function (x, i) {
+            return {index: i, value: x};
+        });
+        eachfn(arr, function (x, callback) {
+            iterator(x.value, function (v) {
+                if (v) {
+                    results.push(x);
+                }
+                callback();
+            });
+        }, function (err) {
+            callback(_map(results.sort(function (a, b) {
+                return a.index - b.index;
+            }), function (x) {
+                return x.value;
+            }));
+        });
+    };
+    async.filter = doParallel(_filter);
+    async.filterSeries = doSeries(_filter);
+    // select alias
+    async.select = async.filter;
+    async.selectSeries = async.filterSeries;
+
+    var _reject = function (eachfn, arr, iterator, callback) {
+        var results = [];
+        arr = _map(arr, function (x, i) {
+            return {index: i, value: x};
+        });
+        eachfn(arr, function (x, callback) {
+            iterator(x.value, function (v) {
+                if (!v) {
+                    results.push(x);
+                }
+                callback();
+            });
+        }, function (err) {
+            callback(_map(results.sort(function (a, b) {
+                return a.index - b.index;
+            }), function (x) {
+                return x.value;
+            }));
+        });
+    };
+    async.reject = doParallel(_reject);
+    async.rejectSeries = doSeries(_reject);
+
+    var _detect = function (eachfn, arr, iterator, main_callback) {
+        eachfn(arr, function (x, callback) {
+            iterator(x, function (result) {
+                if (result) {
+                    main_callback(x);
+                    main_callback = function () {};
+                }
+                else {
+                    callback();
+                }
+            });
+        }, function (err) {
+            main_callback();
+        });
+    };
+    async.detect = doParallel(_detect);
+    async.detectSeries = doSeries(_detect);
+
+    async.some = function (arr, iterator, main_callback) {
+        async.each(arr, function (x, callback) {
+            iterator(x, function (v) {
+                if (v) {
+                    main_callback(true);
+                    main_callback = function () {};
+                }
+                callback();
+            });
+        }, function (err) {
+            main_callback(false);
+        });
+    };
+    // any alias
+    async.any = async.some;
+
+    async.every = function (arr, iterator, main_callback) {
+        async.each(arr, function (x, callback) {
+            iterator(x, function (v) {
+                if (!v) {
+                    main_callback(false);
+                    main_callback = function () {};
+                }
+                callback();
+            });
+        }, function (err) {
+            main_callback(true);
+        });
+    };
+    // all alias
+    async.all = async.every;
+
+    async.sortBy = function (arr, iterator, callback) {
+        async.map(arr, function (x, callback) {
+            iterator(x, function (err, criteria) {
+                if (err) {
+                    callback(err);
+                }
+                else {
+                    callback(null, {value: x, criteria: criteria});
+                }
+            });
+        }, function (err, results) {
+            if (err) {
+                return callback(err);
+            }
+            else {
+                var fn = function (left, right) {
+                    var a = left.criteria, b = right.criteria;
+                    return a < b ? -1 : a > b ? 1 : 0;
+                };
+                callback(null, _map(results.sort(fn), function (x) {
+                    return x.value;
+                }));
+            }
+        });
+    };
+
+    async.auto = function (tasks, callback) {
+        callback = callback || function () {};
+        var keys = _keys(tasks);
+        if (!keys.length) {
+            return callback(null);
+        }
+
+        var results = {};
+
+        var listeners = [];
+        var addListener = function (fn) {
+            listeners.unshift(fn);
+        };
+        var removeListener = function (fn) {
+            for (var i = 0; i < listeners.length; i += 1) {
+                if (listeners[i] === fn) {
+                    listeners.splice(i, 1);
+                    return;
+                }
+            }
+        };
+        var taskComplete = function () {
+            _each(listeners.slice(0), function (fn) {
+                fn();
+            });
+        };
+
+        addListener(function () {
+            if (_keys(results).length === keys.length) {
+                callback(null, results);
+                callback = function () {};
+            }
+        });
+
+        _each(keys, function (k) {
+            var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
+            var taskCallback = function (err) {
+                var args = Array.prototype.slice.call(arguments, 1);
+                if (args.length <= 1) {
+                    args = args[0];
+                }
+                if (err) {
+                    var safeResults = {};
+                    _each(_keys(results), function(rkey) {
+                        safeResults[rkey] = results[rkey];
+                    });
+                    safeResults[k] = args;
+                    callback(err, safeResults);
+                    // stop subsequent errors hitting callback multiple times
+                    callback = function () {};
+                }
+                else {
+                    results[k] = args;
+                    async.setImmediate(taskComplete);
+                }
+            };
+            var requires = task.slice(0, Math.abs(task.length - 1)) || [];
+            var ready = function () {
+                return _reduce(requires, function (a, x) {
+                    return (a && results.hasOwnProperty(x));
+                }, true) && !results.hasOwnProperty(k);
+            };
+            if (ready()) {
+                task[task.length - 1](taskCallback, results);
+            }
+            else {
+                var listener = function () {
+                    if (ready()) {
+                        removeListener(listener);
+                        task[task.length - 1](taskCallback, results);
+                    }
+                };
+                addListener(listener);
+            }
+        });
+    };
+
+    async.waterfall = function (tasks, callback) {
+        callback = callback || function () {};
+        if (tasks.constructor !== Array) {
+          var err = new Error('First argument to waterfall must be an array of functions');
+          return callback(err);
+        }
+        if (!tasks.length) {
+            return callback();
+        }
+        var wrapIterator = function (iterator) {
+            return function (err) {
+                if (err) {
+                    callback.apply(null, arguments);
+                    callback = function () {};
+                }
+                else {
+                    var args = Array.prototype.slice.call(arguments, 1);
+                    var next = iterator.next();
+                    if (next) {
+                        args.push(wrapIterator(next));
+                    }
+                    else {
+                        args.push(callback);
+                    }
+                    async.setImmediate(function () {
+                        iterator.apply(null, args);
+                    });
+                }
+            };
+        };
+        wrapIterator(async.iterator(tasks))();
+    };
+
+    var _parallel = function(eachfn, tasks, callback) {
+        callback = callback || function () {};
+        if (tasks.constructor === Array) {
+            eachfn.map(tasks, function (fn, callback) {
+                if (fn) {
+                    fn(function (err) {
+                        var args = Array.prototype.slice.call(arguments, 1);
+                        if (args.length <= 1) {
+                            args = args[0];
+                        }
+                        callback.call(null, err, args);
+                    });
+                }
+            }, callback);
+        }
+        else {
+            var results = {};
+            eachfn.each(_keys(tasks), function (k, callback) {
+                tasks[k](function (err) {
+                    var args = Array.prototype.slice.call(arguments, 1);
+                    if (args.length <= 1) {
+                        args = args[0];
+                    }
+                    results[k] = args;
+                    callback(err);
+                });
+            }, function (err) {
+                callback(err, results);
+            });
+        }
+    };
+
+    async.parallel = function (tasks, callback) {
+        _parallel({ map: async.map, each: async.each }, tasks, callback);
+    };
+
+    async.parallelLimit = function(tasks, limit, callback) {
+        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
+    };
+
+    async.series = function (tasks, callback) {
+        callback = callback || function () {};
+        if (tasks.constructor === Array) {
+            async.mapSeries(tasks, function (fn, callback) {
+                if (fn) {
+                    fn(function (err) {
+                        var args = Array.prototype.slice.call(arguments, 1);
+                        if (args.length <= 1) {
+                            args = args[0];
+                        }
+                        callback.call(null, err, args);
+                    });
+                }
+            }, callback);
+        }
+        else {
+            var results = {};
+            async.eachSeries(_keys(tasks), function (k, callback) {
+                tasks[k](function (err) {
+                    var args = Array.prototype.slice.call(arguments, 1);
+                    if (args.length <= 1) {
+                        args = args[0];
+                    }
+                    results[k] = args;
+                    callback(err);
+                });
+            }, function (err) {
+                callback(err, results);
+            });
+        }
+    };
+
+    async.iterator = function (tasks) {
+        var makeCallback = function (index) {
+            var fn = function () {
+                if (tasks.length) {
+                    tasks[index].apply(null, arguments);
+                }
+                return fn.next();
+            };
+            fn.next = function () {
+                return (index < tasks.length - 1) ? makeCallback(index + 1): null;
+            };
+            return fn;
+        };
+        return makeCallback(0);
+    };
+
+    async.apply = function (fn) {
+        var args = Array.prototype.slice.call(arguments, 1);
+        return function () {
+            return fn.apply(
+                null, args.concat(Array.prototype.slice.call(arguments))
+            );
+        };
+    };
+
+    var _concat = function (eachfn, arr, fn, callback) {
+        var r = [];
+        eachfn(arr, function (x, cb) {
+            fn(x, function (err, y) {
+                r = r.concat(y || []);
+                cb(err);
+            });
+        }, function (err) {
+            callback(err, r);
+        });
+    };
+    async.concat = doParallel(_concat);
+    async.concatSeries = doSeries(_concat);
+
+    async.whilst = function (test, iterator, callback) {
+        if (test()) {
+            iterator(function (err) {
+                if (err) {
+                    return callback(err);
+                }
+                async.whilst(test, iterator, callback);
+            });
+        }
+        else {
+            callback();
+        }
+    };
+
+    async.doWhilst = function (iterator, test, callback) {
+        iterator(function (err) {
+            if (err) {
+                return callback(err);
+            }
+            if (test()) {
+                async.doWhilst(iterator, test, callback);
+            }
+            else {
+                callback();
+            }
+        });
+    };
+
+    async.until = function (test, iterator, callback) {
+        if (!test()) {
+            iterator(function (err) {
+                if (err) {
+                    return callback(err);
+                }
+                async.until(test, iterator, callback);
+            });
+        }
+        else {
+            callback();
+        }
+    };
+
+    async.doUntil = function (iterator, test, callback) {
+        iterator(function (err) {
+            if (err) {
+                return callback(err);
+            }
+            if (!test()) {
+                async.doUntil(iterator, test, callback);
+            }
+            else {
+                callback();
+            }
+        });
+    };
+
+    async.queue = function (worker, concurrency) {
+        if (concurrency === undefined) {
+            concurrency = 1;
+        }
+        function _insert(q, data, pos, callback) {
+          if(data.constructor !== Array) {
+              data = [data];
+          }
+          _each(data, function(task) {
+              var item = {
+                  data: task,
+                  callback: typeof callback === 'function' ? callback : null
+              };
+
+              if (pos) {
+                q.tasks.unshift(item);
+              } else {
+                q.tasks.push(item);
+              }
+
+              if (q.saturated && q.tasks.length === concurrency) {
+                  q.saturated();
+              }
+              async.setImmediate(q.process);
+          });
+        }
+
+        var workers = 0;
+        var q = {
+            tasks: [],
+            concurrency: concurrency,
+            saturated: null,
+            empty: null,
+            drain: null,
+            push: function (data, callback) {
+              _insert(q, data, false, callback);
+            },
+            unshift: function (data, callback) {
+              _insert(q, data, true, callback);
+            },
+            process: function () {
+                if (workers < q.concurrency && q.tasks.length) {
+                    var task = q.tasks.shift();
+                    if (q.empty && q.tasks.length === 0) {
+                        q.empty();
+                    }
+                    workers += 1;
+                    var next = function () {
+                        workers -= 1;
+                        if (task.callback) {
+                            task.callback.apply(task, arguments);
+                        }
+                        if (q.drain && q.tasks.length + workers === 0) {
+                            q.drain();
+                        }
+                        q.process();
+                    };
+                    var cb = only_once(next);
+                    worker(task.data, cb);
+                }
+            },
+            length: function () {
+                return q.tasks.length;
+            },
+            running: function () {
+                return workers;
+            }
+        };
+        return q;
+    };
+
+    async.cargo = function (worker, payload) {
+        var working     = false,
+            tasks       = [];
+
+        var cargo = {
+            tasks: tasks,
+            payload: payload,
+            saturated: null,
+            empty: null,
+            drain: null,
+            push: function (data, callback) {
+                if(data.constructor !== Array) {
+                    data = [data];
+                }
+                _each(data, function(task) {
+                    tasks.push({
+                        data: task,
+                        callback: typeof callback === 'function' ? callback : null
+                    });
+                    if (cargo.saturated && tasks.length === payload) {
+                        cargo.saturated();
+                    }
+                });
+                async.setImmediate(cargo.process);
+            },
+            process: function process() {
+                if (working) return;
+                if (tasks.length === 0) {
+                    if(cargo.drain) cargo.drain();
+                    return;
+                }
+
+                var ts = typeof payload === 'number'
+                            ? tasks.splice(0, payload)
+                            : tasks.splice(0);
+
+                var ds = _map(ts, function (task) {
+                    return task.data;
+                });
+
+                if(cargo.empty) cargo.empty();
+                working = true;
+                worker(ds, function () {
+                    working = false;
+
+                    var args = arguments;
+                    _each(ts, function (data) {
+                        if (data.callback) {
+                            data.callback.apply(null, args);
+                        }
+                    });
+
+                    process();
+                });
+            },
+            length: function () {
+                return tasks.length;
+            },
+            running: function () {
+                return working;
+            }
+        };
+        return cargo;
+    };
+
+    var _console_fn = function (name) {
+        return function (fn) {
+            var args = Array.prototype.slice.call(arguments, 1);
+            fn.apply(null, args.concat([function (err) {
+                var args = Array.prototype.slice.call(arguments, 1);
+                if (typeof console !== 'undefined') {
+                    if (err) {
+                        if (console.error) {
+                            console.error(err);
+                        }
+                    }
+                    else if (console[name]) {
+                        _each(args, function (x) {
+                            console[name](x);
+                        });
+                    }
+                }
+            }]));
+        };
+    };
+    async.log = _console_fn('log');
+    async.dir = _console_fn('dir');
+    /*async.info = _console_fn('info');
+    async.warn = _console_fn('warn');
+    async.error = _console_fn('error');*/
+
+    async.memoize = function (fn, hasher) {
+        var memo = {};
+        var queues = {};
+        hasher = hasher || function (x) {
+            return x;
+        };
+        var memoized = function () {
+            var args = Array.prototype.slice.call(arguments);
+            var callback = args.pop();
+            var key = hasher.apply(null, args);
+            if (key in memo) {
+                callback.apply(null, memo[key]);
+            }
+            else if (key in queues) {
+                queues[key].push(callback);
+            }
+            else {
+                queues[key] = [callback];
+                fn.apply(null, args.concat([function () {
+                    memo[key] = arguments;
+                    var q = queues[key];
+                    delete queues[key];
+                    for (var i = 0, l = q.length; i < l; i++) {
+                      q[i].apply(null, arguments);
+                    }
+                }]));
+            }
+        };
+        memoized.memo = memo;
+        memoized.unmemoized = fn;
+        return memoized;
+    };
+
+    async.unmemoize = function (fn) {
+      return function () {
+        return (fn.unmemoized || fn).apply(null, arguments);
+      };
+    };
+
+    async.times = function (count, iterator, callback) {
+        var counter = [];
+        for (var i = 0; i < count; i++) {
+            counter.push(i);
+        }
+        return async.map(counter, iterator, callback);
+    };
+
+    async.timesSeries = function (count, iterator, callback) {
+        var counter = [];
+        for (var i = 0; i < count; i++) {
+            counter.push(i);
+        }
+        return async.mapSeries(counter, iterator, callback);
+    };
+
+    async.compose = function (/* functions... */) {
+        var fns = Array.prototype.reverse.call(arguments);
+        return function () {
+            var that = this;
+            var args = Array.prototype.slice.call(arguments);
+            var callback = args.pop();
+            async.reduce(fns, args, function (newargs, fn, cb) {
+                fn.apply(that, newargs.concat([function () {
+                    var err = arguments[0];
+                    var nextargs = Array.prototype.slice.call(arguments, 1);
+                    cb(err, nextargs);
+                }]))
+            },
+            function (err, results) {
+                callback.apply(that, [err].concat(results));
+            });
+        };
+    };
+
+    var _applyEach = function (eachfn, fns /*args...*/) {
+        var go = function () {
+            var that = this;
+            var args = Array.prototype.slice.call(arguments);
+            var callback = args.pop();
+            return eachfn(fns, function (fn, cb) {
+                fn.apply(that, args.concat([cb]));
+            },
+            callback);
+        };
+        if (arguments.length > 2) {
+            var args = Array.prototype.slice.call(arguments, 2);
+            return go.apply(this, args);
+        }
+        else {
+            return go;
+        }
+    };
+    async.applyEach = doParallel(_applyEach);
+    async.applyEachSeries = doSeries(_applyEach);
+
+    async.forever = function (fn, callback) {
+        function next(err) {
+            if (err) {
+                if (callback) {
+                    return callback(err);
+                }
+                throw err;
+            }
+            fn(next);
+        }
+        next();
+    };
+
+    // AMD / RequireJS
+    if (typeof define !== 'undefined' && define.amd) {
+        define([], function () {
+            return async;
+        });
+    }
+    // Node.js
+    else if (typeof module !== 'undefined' && module.exports) {
+        module.exports = async;
+    }
+    // included directly via <script> tag
+    else {
+        root.async = async;
+    }
+
+}());
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/async/package.json	(revision 484)
@@ -0,0 +1,43 @@
+{
+  "name": "async",
+  "description": "Higher-order functions and common patterns for asynchronous code",
+  "main": "./lib/async",
+  "author": {
+    "name": "Caolan McMahon"
+  },
+  "version": "0.2.9",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/caolan/async.git"
+  },
+  "bugs": {
+    "url": "https://github.com/caolan/async/issues"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "https://github.com/caolan/async/raw/master/LICENSE"
+    }
+  ],
+  "devDependencies": {
+    "nodeunit": ">0.0.0",
+    "uglify-js": "1.2.x",
+    "nodelint": ">0.0.0"
+  },
+  "jam": {
+    "main": "lib/async.js",
+    "include": [
+      "lib/async.js",
+      "README.md",
+      "LICENSE"
+    ]
+  },
+  "scripts": {
+    "test": "nodeunit test/test-async.js"
+  },
+  "readme": "# Async.js\n\nAsync is a utility module which provides straight-forward, powerful functions\nfor working with asynchronous JavaScript. Although originally designed for\nuse with [node.js](http://nodejs.org), it can also be used directly in the\nbrowser. Also supports [component](https://github.com/component/component).\n\nAsync provides around 20 functions that include the usual 'functional'\nsuspects (map, reduce, filter, eachâŠ) as well as some common patterns\nfor asynchronous control flow (parallel, series, waterfallâŠ). All these\nfunctions assume you follow the node.js convention of providing a single\ncallback as the last argument of your async function.\n\n\n## Quick Examples\n\n```javascript\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n    // results is now an array of stats for each file\n});\n\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n    // results now equals an array of the existing files\n});\n\nasync.parallel([\n    function(){ ... },\n    function(){ ... }\n], callback);\n\nasync.series([\n    function(){ ... },\n    function(){ ... }\n]);\n```\n\nThere are many more functions available so take a look at the docs below for a\nfull list. This module aims to be comprehensive, so if you feel anything is\nmissing please create a GitHub issue for it.\n\n## Common Pitfalls\n\n### Binding a context to an iterator\n\nThis section is really about bind, not about async. If you are wondering how to\nmake async execute your iterators in a given context, or are confused as to why\na method of another library isn't working as an iterator, study this example:\n\n```js\n// Here is a simple object with an (unnecessarily roundabout) squaring method\nvar AsyncSquaringLibrary = {\n  squareExponent: 2,\n  square: function(number, callback){ \n    var result = Math.pow(number, this.squareExponent);\n    setTimeout(function(){\n      callback(null, result);\n    }, 200);\n  }\n};\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){\n  // result is [NaN, NaN, NaN]\n  // This fails because the `this.squareExponent` expression in the square\n  // function is not evaluated in the context of AsyncSquaringLibrary, and is\n  // therefore undefined.\n});\n\nasync.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){\n  // result is [1, 4, 9]\n  // With the help of bind we can attach a context to the iterator before\n  // passing it to async. Now the square function will be executed in its \n  // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`\n  // will be as expected.\n});\n```\n\n## Download\n\nThe source is available for download from\n[GitHub](http://github.com/caolan/async).\nAlternatively, you can install using Node Package Manager (npm):\n\n    npm install async\n\n__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed\n\n## In the Browser\n\nSo far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:\n\n```html\n<script type=\"text/javascript\" src=\"async.js\"></script>\n<script type=\"text/javascript\">\n\n    async.map(data, asyncProcess, function(err, results){\n        alert(results);\n    });\n\n</script>\n```\n\n## Documentation\n\n### Collections\n\n* [each](#each)\n* [map](#map)\n* [filter](#filter)\n* [reject](#reject)\n* [reduce](#reduce)\n* [detect](#detect)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [whilst](#whilst)\n* [doWhilst](#doWhilst)\n* [until](#until)\n* [doUntil](#doUntil)\n* [forever](#forever)\n* [waterfall](#waterfall)\n* [compose](#compose)\n* [applyEach](#applyEach)\n* [queue](#queue)\n* [cargo](#cargo)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n* [times](#times)\n* [timesSeries](#timesSeries)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n<a name=\"forEach\" />\n<a name=\"each\" />\n### each(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the each function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err) which must be called once it has \n  completed. If no error has occured, the callback should be run without \n  arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n  have finished, or an error has occurred.\n\n__Example__\n\n```js\n// assuming openFiles is an array of file names and saveFile is a function\n// to save the modified contents of that file:\n\nasync.each(openFiles, saveFile, function(err){\n    // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n<a name=\"forEachSeries\" />\n<a name=\"eachSeries\" />\n### eachSeries(arr, iterator, callback)\n\nThe same as each only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n<a name=\"forEachLimit\" />\n<a name=\"eachLimit\" />\n### eachLimit(arr, limit, iterator, callback)\n\nThe same as each only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err) which must be called once it has \n  completed. If no error has occured, the callback should be run without \n  arguments or with an explicit null argument.\n* callback(err) - A callback which is called after all the iterator functions\n  have finished, or an error has occurred.\n\n__Example__\n\n```js\n// Assume documents is an array of JSON objects and requestApi is a\n// function that interacts with a rate-limited REST api.\n\nasync.eachLimit(documents, 20, requestApi, function(err){\n    // if any of the saves produced an error, err would equal that error\n});\n```\n\n---------------------------------------\n\n<a name=\"map\" />\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err, transformed) which must be called once \n  it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n  functions have finished, or an error has occurred. Results is an array of the\n  transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], fs.stat, function(err, results){\n    // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n<a name=\"mapSeries\" />\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n<a name=\"mapLimit\" />\n### mapLimit(arr, limit, iterator, callback)\n\nThe same as map only no more than \"limit\" iterators will be simultaneously \nrunning at any time.\n\nNote that the items are not processed in batches, so there is no guarantee that\n the first \"limit\" iterator functions will complete before any others are \nstarted.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - The maximum number of iterators to run at any time.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err, transformed) which must be called once \n  it has completed with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n  functions have finished, or an error has occurred. Results is an array of the\n  transformed items from the original array.\n\n__Example__\n\n```js\nasync.map(['file1','file2','file3'], 1, fs.stat, function(err, results){\n    // results is now an array of stats for each file\n});\n```\n\n---------------------------------------\n\n<a name=\"filter\" />\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n  The iterator is passed a callback(truthValue) which must be called with a \n  boolean argument once it has completed.\n* callback(results) - A callback which is called after all the iterator\n  functions have finished.\n\n__Example__\n\n```js\nasync.filter(['file1','file2','file3'], fs.exists, function(results){\n    // results now equals an array of the existing files\n});\n```\n\n---------------------------------------\n\n<a name=\"filterSeries\" />\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n<a name=\"reject\" />\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n<a name=\"rejectSeries\" />\n### rejectSeries(arr, iterator, callback)\n\nThe same as reject, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n<a name=\"reduce\" />\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then it's probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n  array to produce the next step in the reduction. The iterator is passed a\n  callback(err, reduction) which accepts an optional error as its first \n  argument, and the state of the reduction as the second. If an error is \n  passed to the callback, the reduction is stopped and the main callback is \n  immediately called with the error.\n* callback(err, result) - A callback which is called after all the iterator\n  functions have finished. Result is the reduced value.\n\n__Example__\n\n```js\nasync.reduce([1,2,3], 0, function(memo, item, callback){\n    // pointless async:\n    process.nextTick(function(){\n        callback(null, memo + item)\n    });\n}, function(err, result){\n    // result is now equal to the last value of memo, which is 6\n});\n```\n\n---------------------------------------\n\n<a name=\"reduceRight\" />\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n<a name=\"detect\" />\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n  The iterator is passed a callback(truthValue) which must be called with a \n  boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n  true, or after all the iterator functions have finished. Result will be\n  the first item in the array that passes the truth test (iterator) or the\n  value undefined if none passed.\n\n__Example__\n\n```js\nasync.detect(['file1','file2','file3'], fs.exists, function(result){\n    // result now equals the first file in the list that exists\n});\n```\n\n---------------------------------------\n\n<a name=\"detectSeries\" />\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n<a name=\"sortBy\" />\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err, sortValue) which must be called once it\n  has completed with an error (which can be null) and a value to use as the sort\n  criteria.\n* callback(err, results) - A callback which is called after all the iterator\n  functions have finished, or an error has occurred. Results is the items from\n  the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n```js\nasync.sortBy(['file1','file2','file3'], function(file, callback){\n    fs.stat(file, function(err, stats){\n        callback(err, stats.mtime);\n    });\n}, function(err, results){\n    // results is now the original array of files sorted by\n    // modified date\n});\n```\n\n---------------------------------------\n\n<a name=\"some\" />\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n  The iterator is passed a callback(truthValue) which must be called with a \n  boolean argument once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n  true, or after all the iterator functions have finished. Result will be\n  either true or false depending on the values of the async tests.\n\n__Example__\n\n```js\nasync.some(['file1','file2','file3'], fs.exists, function(result){\n    // if result is true then at least one of the files exists\n});\n```\n\n---------------------------------------\n\n<a name=\"every\" />\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like fs.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n  The iterator is passed a callback(truthValue) which must be called with a \n  boolean argument once it has completed.\n* callback(result) - A callback which is called after all the iterator\n  functions have finished. Result will be either true or false depending on\n  the values of the async tests.\n\n__Example__\n\n```js\nasync.every(['file1','file2','file3'], fs.exists, function(result){\n    // if result is true then every file exists\n});\n```\n\n---------------------------------------\n\n<a name=\"concat\" />\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n  The iterator is passed a callback(err, results) which must be called once it \n  has completed with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n  functions have finished, or an error has occurred. Results is an array containing\n  the concatenated results of the iterator function.\n\n__Example__\n\n```js\nasync.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n    // files is now a list of filenames that exist in the 3 directories\n});\n```\n\n---------------------------------------\n\n<a name=\"concatSeries\" />\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n<a name=\"series\" />\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n  a callback(err, result) it must call on completion with an error (which can\n  be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n  have completed. This function gets a results array (or object) containing all \n  the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.series([\n    function(callback){\n        // do some stuff ...\n        callback(null, 'one');\n    },\n    function(callback){\n        // do some more stuff ...\n        callback(null, 'two');\n    }\n],\n// optional callback\nfunction(err, results){\n    // results is now equal to ['one', 'two']\n});\n\n\n// an example using an object instead of an array\nasync.series({\n    one: function(callback){\n        setTimeout(function(){\n            callback(null, 1);\n        }, 200);\n    },\n    two: function(callback){\n        setTimeout(function(){\n            callback(null, 2);\n        }, 100);\n    }\n},\nfunction(err, results) {\n    // results is now equal to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n<a name=\"parallel\" />\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n  a callback(err, result) it must call on completion with an error (which can\n  be null) and an optional result value.\n* callback(err, results) - An optional callback to run once all the functions\n  have completed. This function gets a results array (or object) containing all \n  the result arguments passed to the task callbacks.\n\n__Example__\n\n```js\nasync.parallel([\n    function(callback){\n        setTimeout(function(){\n            callback(null, 'one');\n        }, 200);\n    },\n    function(callback){\n        setTimeout(function(){\n            callback(null, 'two');\n        }, 100);\n    }\n],\n// optional callback\nfunction(err, results){\n    // the results array will equal ['one','two'] even though\n    // the second function had a shorter timeout.\n});\n\n\n// an example using an object instead of an array\nasync.parallel({\n    one: function(callback){\n        setTimeout(function(){\n            callback(null, 1);\n        }, 200);\n    },\n    two: function(callback){\n        setTimeout(function(){\n            callback(null, 2);\n        }, 100);\n    }\n},\nfunction(err, results) {\n    // results is now equals to: {one: 1, two: 2}\n});\n```\n\n---------------------------------------\n\n<a name=\"parallel\" />\n### parallelLimit(tasks, limit, [callback])\n\nThe same as parallel only the tasks are executed in parallel with a maximum of \"limit\" \ntasks executing at any time.\n\nNote that the tasks are not executed in batches, so there is no guarantee that \nthe first \"limit\" tasks will complete before any others are started.\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed \n  a callback(err, result) it must call on completion with an error (which can\n  be null) and an optional result value.\n* limit - The maximum number of tasks to run at any time.\n* callback(err, results) - An optional callback to run once all the functions\n  have completed. This function gets a results array (or object) containing all \n  the result arguments passed to the task callbacks.\n\n---------------------------------------\n\n<a name=\"whilst\" />\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n  passed a callback(err) which must be called once it has completed with an \n  optional error argument.\n* callback(err) - A callback which is called after the test fails and repeated\n  execution of fn has stopped.\n\n__Example__\n\n```js\nvar count = 0;\n\nasync.whilst(\n    function () { return count < 5; },\n    function (callback) {\n        count++;\n        setTimeout(callback, 1000);\n    },\n    function (err) {\n        // 5 seconds have passed\n    }\n);\n```\n\n---------------------------------------\n\n<a name=\"doWhilst\" />\n### doWhilst(fn, test, callback)\n\nThe post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.\n\n---------------------------------------\n\n<a name=\"until\" />\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n---------------------------------------\n\n<a name=\"doUntil\" />\n### doUntil(fn, test, callback)\n\nLike doWhilst except the test is inverted. Note the argument ordering differs from `until`.\n\n---------------------------------------\n\n<a name=\"forever\" />\n### forever(fn, callback)\n\nCalls the asynchronous function 'fn' repeatedly, in series, indefinitely.\nIf an error is passed to fn's callback then 'callback' is called with the\nerror, otherwise it will never be called.\n\n---------------------------------------\n\n<a name=\"waterfall\" />\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a \n  callback(err, result1, result2, ...) it must call on completion. The first\n  argument is an error (which can be null) and any further arguments will be \n  passed as arguments in order to the next task.\n* callback(err, [results]) - An optional callback to run once all the functions\n  have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n```js\nasync.waterfall([\n    function(callback){\n        callback(null, 'one', 'two');\n    },\n    function(arg1, arg2, callback){\n        callback(null, 'three');\n    },\n    function(arg1, callback){\n        // arg1 now equals 'three'\n        callback(null, 'done');\n    }\n], function (err, result) {\n   // result now equals 'done'    \n});\n```\n\n---------------------------------------\n<a name=\"compose\" />\n### compose(fn1, fn2...)\n\nCreates a function which is a composition of the passed asynchronous\nfunctions. Each function consumes the return value of the function that\nfollows. Composing functions f(), g() and h() would produce the result of\nf(g(h())), only this version uses callbacks to obtain the return values.\n\nEach function is executed with the `this` binding of the composed function.\n\n__Arguments__\n\n* functions... - the asynchronous functions to compose\n\n\n__Example__\n\n```js\nfunction add1(n, callback) {\n    setTimeout(function () {\n        callback(null, n + 1);\n    }, 10);\n}\n\nfunction mul3(n, callback) {\n    setTimeout(function () {\n        callback(null, n * 3);\n    }, 10);\n}\n\nvar add1mul3 = async.compose(mul3, add1);\n\nadd1mul3(4, function (err, result) {\n   // result now equals 15\n});\n```\n\n---------------------------------------\n<a name=\"applyEach\" />\n### applyEach(fns, args..., callback)\n\nApplies the provided arguments to each function in the array, calling the\ncallback after all functions have completed. If you only provide the first\nargument then it will return a function which lets you pass in the\narguments as if it were a single function call.\n\n__Arguments__\n\n* fns - the asynchronous functions to all call with the same arguments\n* args... - any number of separate arguments to pass to the function\n* callback - the final argument should be the callback, called when all\n  functions have completed processing\n\n\n__Example__\n\n```js\nasync.applyEach([enableSearch, updateSchema], 'bucket', callback);\n\n// partial application example:\nasync.each(\n    buckets,\n    async.applyEach([enableSearch, updateSchema]),\n    callback\n);\n```\n\n---------------------------------------\n\n<a name=\"applyEachSeries\" />\n### applyEachSeries(arr, iterator, callback)\n\nThe same as applyEach only the functions are applied in series.\n\n---------------------------------------\n\n<a name=\"queue\" />\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n  task, which must call its callback(err) argument when finished, with an \n  optional error as an argument.\n* concurrency - An integer for determining how many worker functions should be\n  run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n  run in parallel. This property can be changed after a queue is created to\n  alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n  once the worker has finished processing the task.\n  instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* unshift(task, [callback]) - add a new task to the front of the queue.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a queue object with concurrency 2\n\nvar q = async.queue(function (task, callback) {\n    console.log('hello ' + task.name);\n    callback();\n}, 2);\n\n\n// assign a callback\nq.drain = function() {\n    console.log('all items have been processed');\n}\n\n// add some items to the queue\n\nq.push({name: 'foo'}, function (err) {\n    console.log('finished processing foo');\n});\nq.push({name: 'bar'}, function (err) {\n    console.log('finished processing bar');\n});\n\n// add some items to the queue (batch-wise)\n\nq.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n    console.log('finished processing bar');\n});\n\n// add some items to the front of the queue\n\nq.unshift({name: 'bar'}, function (err) {\n    console.log('finished processing bar');\n});\n```\n\n---------------------------------------\n\n<a name=\"cargo\" />\n### cargo(worker, [payload])\n\nCreates a cargo object with the specified payload. Tasks added to the\ncargo will be processed altogether (up to the payload limit). If the\nworker is in progress, the task is queued until it is available. Once\nthe worker has completed some tasks, each callback of those tasks is called.\n\n__Arguments__\n\n* worker(tasks, callback) - An asynchronous function for processing an array of\n  queued tasks, which must call its callback(err) argument when finished, with \n  an optional error as an argument.\n* payload - An optional integer for determining how many tasks should be\n  processed per round; if omitted, the default is unlimited.\n\n__Cargo objects__\n\nThe cargo object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* payload - an integer for determining how many tasks should be\n  process per round. This property can be changed after a cargo is created to\n  alter the payload on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n  once the worker has finished processing the task.\n  instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n```js\n// create a cargo object with payload 2\n\nvar cargo = async.cargo(function (tasks, callback) {\n    for(var i=0; i<tasks.length; i++){\n      console.log('hello ' + tasks[i].name);\n    }\n    callback();\n}, 2);\n\n\n// add some items\n\ncargo.push({name: 'foo'}, function (err) {\n    console.log('finished processing foo');\n});\ncargo.push({name: 'bar'}, function (err) {\n    console.log('finished processing bar');\n});\ncargo.push({name: 'baz'}, function (err) {\n    console.log('finished processing baz');\n});\n```\n\n---------------------------------------\n\n<a name=\"auto\" />\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\nNote, all functions are called with a results object as a second argument, \nso it is unsafe to pass functions in the tasks object which cannot handle the\nextra argument. For example, this snippet of code:\n\n```js\nasync.auto({\n  readData: async.apply(fs.readFile, 'data.txt', 'utf-8');\n}, callback);\n```\n\nwill have the effect of calling readFile with the results object as the last\nargument, which will fail:\n\n```js\nfs.readFile('data.txt', 'utf-8', cb, {});\n```\n\nInstead, wrap the call to readFile in a function which does not forward the \nresults object:\n\n```js\nasync.auto({\n  readData: function(cb, results){\n    fs.readFile('data.txt', 'utf-8', cb);\n  }\n}, callback);\n```\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n  requirements, with the function itself the last item in the array. The key\n  used for each function or array is used when specifying requirements. The \n  function receives two arguments: (1) a callback(err, result) which must be \n  called when finished, passing an error (which can be null) and the result of \n  the function's execution, and (2) a results object, containing the results of\n  the previously executed functions.\n* callback(err, results) - An optional callback which is called when all the\n  tasks have been completed. The callback will receive an error as an argument\n  if any tasks pass an error to their callback. Results will always be passed\n\tbut if an error occurred, no other tasks will be performed, and the results\n\tobject will only contain partial results.\n  \n\n__Example__\n\n```js\nasync.auto({\n    get_data: function(callback){\n        // async code to get some data\n    },\n    make_folder: function(callback){\n        // async code to create a directory to store a file in\n        // this is run at the same time as getting the data\n    },\n    write_file: ['get_data', 'make_folder', function(callback){\n        // once there is some data and the directory exists,\n        // write the data to a file in the directory\n        callback(null, filename);\n    }],\n    email_link: ['write_file', function(callback, results){\n        // once the file is written let's email a link to it...\n        // results.write_file contains the filename returned by write_file.\n    }]\n});\n```\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n```js\nasync.parallel([\n    function(callback){\n        // async code to get some data\n    },\n    function(callback){\n        // async code to create a directory to store a file in\n        // this is run at the same time as getting the data\n    }\n],\nfunction(err, results){\n    async.series([\n        function(callback){\n            // once there is some data and the directory exists,\n            // write the data to a file in the directory\n        },\n        function(callback){\n            // once the file is written let's email a link to it...\n        }\n    ]);\n});\n```\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n<a name=\"iterator\" />\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. It's also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run.\n\n__Example__\n\n```js\nvar iterator = async.iterator([\n    function(){ sys.p('one'); },\n    function(){ sys.p('two'); },\n    function(){ sys.p('three'); }\n]);\n\nnode> var iterator2 = iterator();\n'one'\nnode> var iterator3 = iterator2();\n'two'\nnode> iterator3();\n'three'\nnode> var nextfn = iterator2.next();\nnode> nextfn();\n'three'\n```\n\n---------------------------------------\n\n<a name=\"apply\" />\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n  continuation is called.\n\n__Example__\n\n```js\n// using apply\n\nasync.parallel([\n    async.apply(fs.writeFile, 'testfile1', 'test1'),\n    async.apply(fs.writeFile, 'testfile2', 'test2'),\n]);\n\n\n// the same process without using apply\n\nasync.parallel([\n    function(callback){\n        fs.writeFile('testfile1', 'test1', callback);\n    },\n    function(callback){\n        fs.writeFile('testfile2', 'test2', callback);\n    }\n]);\n```\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n```js\nnode> var fn = async.apply(sys.puts, 'one');\nnode> fn('two', 'three');\none\ntwo\nthree\n```\n\n---------------------------------------\n\n<a name=\"nextTick\" />\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setImmediate(callback)\nif available, otherwise setTimeout(callback, 0), which means other higher priority\nevents may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n```js\nvar call_order = [];\nasync.nextTick(function(){\n    call_order.push('two');\n    // call_order now equals ['one','two']\n});\ncall_order.push('one')\n```\n\n<a name=\"times\" />\n### times(n, callback)\n\nCalls the callback n times and accumulates results in the same manner\nyou would use with async.map.\n\n__Arguments__\n\n* n - The number of times to run the function.\n* callback - The function to call n times.\n\n__Example__\n\n```js\n// Pretend this is some complicated async factory\nvar createUser = function(id, callback) {\n  callback(null, {\n    id: 'user' + id\n  })\n}\n// generate 5 users\nasync.times(5, function(n, next){\n    createUser(n, function(err, user) {\n      next(err, user)\n    })\n}, function(err, users) {\n  // we should now have 5 users\n});\n```\n\n<a name=\"timesSeries\" />\n### timesSeries(n, callback)\n\nThe same as times only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n## Utils\n\n<a name=\"memoize\" />\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\nThe cache of results is exposed as the `memo` property of the function returned\nby `memoize`.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n  results, it has all the arguments applied to it apart from the callback, and\n  must be synchronous.\n\n__Example__\n\n```js\nvar slow_fn = function (name, callback) {\n    // do something\n    callback(null, result);\n};\nvar fn = async.memoize(slow_fn);\n\n// fn can now be used as if it were slow_fn\nfn('some name', function () {\n    // callback\n});\n```\n\n<a name=\"unmemoize\" />\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n<a name=\"log\" />\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n    setTimeout(function(){\n        callback(null, 'hello ' + name);\n    }, 1000);\n};\n```\n```js\nnode> async.log(hello, 'world');\n'hello world'\n```\n\n---------------------------------------\n\n<a name=\"dir\" />\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n```js\nvar hello = function(name, callback){\n    setTimeout(function(){\n        callback(null, {hello: name});\n    }, 1000);\n};\n```\n```js\nnode> async.dir(hello, 'world');\n{hello: 'world'}\n```\n\n---------------------------------------\n\n<a name=\"noConflict\" />\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n",
+  "readmeFilename": "README.md",
+  "homepage": "https://github.com/caolan/async",
+  "_id": "async@0.2.9",
+  "_from": "async@~0.2.7"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/.npmignore	(revision 484)
@@ -0,0 +1,3 @@
+*.un~
+/node_modules
+/test/tmp
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/License
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/License	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/License	(revision 484)
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
+
+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.
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+SHELL := /bin/bash
+
+test:
+	@./test/run.js
+
+.PHONY: test
+
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/Readme.md	(revision 484)
@@ -0,0 +1,132 @@
+# combined-stream
+
+A stream that emits multiple other streams one after another.
+
+## Installation
+
+``` bash
+npm install combined-stream
+```
+
+## Usage
+
+Here is a simple example that shows how you can use combined-stream to combine
+two files into one:
+
+``` javascript
+var CombinedStream = require('combined-stream');
+var fs = require('fs');
+
+var combinedStream = CombinedStream.create();
+combinedStream.append(fs.createReadStream('file1.txt'));
+combinedStream.append(fs.createReadStream('file2.txt'));
+
+combinedStream.pipe(fs.createWriteStream('combined.txt'));
+```
+
+While the example above works great, it will pause all source streams until
+they are needed. If you don't want that to happen, you can set `pauseStreams`
+to `false`:
+
+``` javascript
+var CombinedStream = require('combined-stream');
+var fs = require('fs');
+
+var combinedStream = CombinedStream.create({pauseStreams: false});
+combinedStream.append(fs.createReadStream('file1.txt'));
+combinedStream.append(fs.createReadStream('file2.txt'));
+
+combinedStream.pipe(fs.createWriteStream('combined.txt'));
+```
+
+However, what if you don't have all the source streams yet, or you don't want
+to allocate the resources (file descriptors, memory, etc.) for them right away?
+Well, in that case you can simply provide a callback that supplies the stream
+by calling a `next()` function:
+
+``` javascript
+var CombinedStream = require('combined-stream');
+var fs = require('fs');
+
+var combinedStream = CombinedStream.create();
+combinedStream.append(function(next) {
+  next(fs.createReadStream('file1.txt'));
+});
+combinedStream.append(function(next) {
+  next(fs.createReadStream('file2.txt'));
+});
+
+combinedStream.pipe(fs.createWriteStream('combined.txt'));
+```
+
+## API
+
+### CombinedStream.create([options])
+
+Returns a new combined stream object. Available options are:
+
+* `maxDataSize`
+* `pauseStreams`
+
+The effect of those options is described below.
+
+### combinedStream.pauseStreams = true
+
+Whether to apply back pressure to the underlaying streams. If set to `false`,
+the underlaying streams will never be paused. If set to `true`, the
+underlaying streams will be paused right after being appended, as well as when
+`delayedStream.pipe()` wants to throttle.
+
+### combinedStream.maxDataSize = 2 * 1024 * 1024
+
+The maximum amount of bytes (or characters) to buffer for all source streams.
+If this value is exceeded, `combinedStream` emits an `'error'` event.
+
+### combinedStream.dataSize = 0
+
+The amount of bytes (or characters) currently buffered by `combinedStream`.
+
+### combinedStream.append(stream)
+
+Appends the given `stream` to the combinedStream object. If `pauseStreams` is
+set to `true, this stream will also be paused right away.
+
+`streams` can also be a function that takes one parameter called `next`. `next`
+is a function that must be invoked in order to provide the `next` stream, see
+example above.
+
+Regardless of how the `stream` is appended, combined-stream always attaches an
+`'error'` listener to it, so you don't have to do that manually.
+
+Special case: `stream` can also be a String or Buffer.
+
+### combinedStream.write(data)
+
+You should not call this, `combinedStream` takes care of piping the appended
+streams into itself for you.
+
+### combinedStream.resume()
+
+Causes `combinedStream` to start drain the streams it manages. The function is
+idempotent, and also emits a `'resume'` event each time which usually goes to
+the stream that is currently being drained.
+
+### combinedStream.pause();
+
+If `combinedStream.pauseStreams` is set to `false`, this does nothing.
+Otherwise a `'pause'` event is emitted, this goes to the stream that is
+currently being drained, so you can use it to apply back pressure.
+
+### combinedStream.end();
+
+Sets `combinedStream.writable` to false, emits an `'end'` event, and removes
+all streams from the queue.
+
+### combinedStream.destroy();
+
+Same as `combinedStream.end()`, except it emits a `'close'` event instead of
+`'end'`.
+
+## License
+
+combined-stream is licensed under the MIT license.
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js	(revision 484)
@@ -0,0 +1,185 @@
+var util = require('util');
+var Stream = require('stream').Stream;
+var DelayedStream = require('delayed-stream');
+
+module.exports = CombinedStream;
+function CombinedStream() {
+  this.writable = false;
+  this.readable = true;
+  this.dataSize = 0;
+  this.maxDataSize = 2 * 1024 * 1024;
+  this.pauseStreams = true;
+
+  this._released = false;
+  this._streams = [];
+  this._currentStream = null;
+}
+util.inherits(CombinedStream, Stream);
+
+CombinedStream.create = function(options) {
+  var combinedStream = new this();
+
+  options = options || {};
+  for (var option in options) {
+    combinedStream[option] = options[option];
+  }
+
+  return combinedStream;
+};
+
+CombinedStream.isStreamLike = function(stream) {
+  return (typeof stream !== 'function')
+    && (typeof stream !== 'string')
+    && (typeof stream !== 'boolean')    
+    && (typeof stream !== 'number')
+    && (!Buffer.isBuffer(stream));
+};
+
+CombinedStream.prototype.append = function(stream) {
+  var isStreamLike = CombinedStream.isStreamLike(stream);
+
+  if (isStreamLike) {
+    if (!(stream instanceof DelayedStream)) {
+      stream.on('data', this._checkDataSize.bind(this));
+
+      stream = DelayedStream.create(stream, {
+        maxDataSize: Infinity,
+        pauseStream: this.pauseStreams,
+      });
+    }
+
+    this._handleErrors(stream);
+
+    if (this.pauseStreams) {
+      stream.pause();
+    }
+  }
+
+  this._streams.push(stream);
+  return this;
+};
+
+CombinedStream.prototype.pipe = function(dest, options) {
+  Stream.prototype.pipe.call(this, dest, options);
+  this.resume();
+};
+
+CombinedStream.prototype._getNext = function() {
+  this._currentStream = null;
+  var stream = this._streams.shift();
+
+
+  if (typeof stream == 'undefined') {
+    this.end();
+    return;
+  }
+
+  if (typeof stream !== 'function') {
+    this._pipeNext(stream);
+    return;
+  }
+
+  var getStream = stream;
+  getStream(function(stream) {
+    var isStreamLike = CombinedStream.isStreamLike(stream);
+    if (isStreamLike) {
+      stream.on('data', this._checkDataSize.bind(this));
+      this._handleErrors(stream);
+    }
+
+    this._pipeNext(stream);
+  }.bind(this));
+};
+
+CombinedStream.prototype._pipeNext = function(stream) {
+  this._currentStream = stream;
+
+  var isStreamLike = CombinedStream.isStreamLike(stream);
+  if (isStreamLike) {
+    stream.on('end', this._getNext.bind(this))
+    stream.pipe(this, {end: false});
+    return;
+  }
+
+  var value = stream;
+  this.write(value);
+  this._getNext();
+};
+
+CombinedStream.prototype._handleErrors = function(stream) {
+  var self = this;
+  stream.on('error', function(err) {
+    self._emitError(err);
+  });
+};
+
+CombinedStream.prototype.write = function(data) {
+  this.emit('data', data);
+};
+
+CombinedStream.prototype.pause = function() {
+  if (!this.pauseStreams) {
+    return;
+  }
+
+  this.emit('pause');
+};
+
+CombinedStream.prototype.resume = function() {
+  if (!this._released) {
+    this._released = true;
+    this.writable = true;
+    this._getNext();
+  }
+
+  this.emit('resume');
+};
+
+CombinedStream.prototype.end = function() {
+  this._reset();
+  this.emit('end');
+};
+
+CombinedStream.prototype.destroy = function() {
+  this._reset();
+  this.emit('close');
+};
+
+CombinedStream.prototype._reset = function() {
+  this.writable = false;
+  this._streams = [];
+  this._currentStream = null;
+};
+
+CombinedStream.prototype._checkDataSize = function() {
+  this._updateDataSize();
+  if (this.dataSize <= this.maxDataSize) {
+    return;
+  }
+
+  var message =
+    'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'
+  this._emitError(new Error(message));
+};
+
+CombinedStream.prototype._updateDataSize = function() {
+  this.dataSize = 0;
+
+  var self = this;
+  this._streams.forEach(function(stream) {
+    if (!stream.dataSize) {
+      return;
+    }
+
+    self.dataSize += stream.dataSize;
+  });
+
+  if (this._currentStream && this._currentStream.dataSize) {
+    this.dataSize += this._currentStream.dataSize;
+  }
+};
+
+CombinedStream.prototype._emitError = function(err) {
+  this._reset();
+  this.emit('error', err);
+};
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore	(revision 484)
@@ -0,0 +1,2 @@
+*.un~
+/node_modules/*
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License	(revision 484)
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
+
+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.
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile	(revision 484)
@@ -0,0 +1,7 @@
+SHELL := /bin/bash
+
+test:
+	@./test/run.js
+
+.PHONY: test
+
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md	(revision 484)
@@ -0,0 +1,154 @@
+# delayed-stream
+
+Buffers events from a stream until you are ready to handle them.
+
+## Installation
+
+``` bash
+npm install delayed-stream
+```
+
+## Usage
+
+The following example shows how to write a http echo server that delays its
+response by 1000 ms.
+
+``` javascript
+var DelayedStream = require('delayed-stream');
+var http = require('http');
+
+http.createServer(function(req, res) {
+  var delayed = DelayedStream.create(req);
+
+  setTimeout(function() {
+    res.writeHead(200);
+    delayed.pipe(res);
+  }, 1000);
+});
+```
+
+If you are not using `Stream#pipe`, you can also manually release the buffered
+events by calling `delayedStream.resume()`:
+
+``` javascript
+var delayed = DelayedStream.create(req);
+
+setTimeout(function() {
+  // Emit all buffered events and resume underlaying source
+  delayed.resume();
+}, 1000);
+```
+
+## Implementation
+
+In order to use this meta stream properly, here are a few things you should
+know about the implementation.
+
+### Event Buffering / Proxying
+
+All events of the `source` stream are hijacked by overwriting the `source.emit`
+method. Until node implements a catch-all event listener, this is the only way.
+
+However, delayed-stream still continues to emit all events it captures on the
+`source`, regardless of whether you have released the delayed stream yet or
+not.
+
+Upon creation, delayed-stream captures all `source` events and stores them in
+an internal event buffer. Once `delayedStream.release()` is called, all
+buffered events are emitted on the `delayedStream`, and the event buffer is
+cleared. After that, delayed-stream merely acts as a proxy for the underlaying
+source.
+
+### Error handling
+
+Error events on `source` are buffered / proxied just like any other events.
+However, `delayedStream.create` attaches a no-op `'error'` listener to the
+`source`. This way you only have to handle errors on the `delayedStream`
+object, rather than in two places.
+
+### Buffer limits
+
+delayed-stream provides a `maxDataSize` property that can be used to limit
+the amount of data being buffered. In order to protect you from bad `source`
+streams that don't react to `source.pause()`, this feature is enabled by
+default.
+
+## API
+
+### DelayedStream.create(source, [options])
+
+Returns a new `delayedStream`. Available options are:
+
+* `pauseStream`
+* `maxDataSize`
+
+The description for those properties can be found below.
+
+### delayedStream.source
+
+The `source` stream managed by this object. This is useful if you are
+passing your `delayedStream` around, and you still want to access properties
+on the `source` object.
+
+### delayedStream.pauseStream = true
+
+Whether to pause the underlaying `source` when calling
+`DelayedStream.create()`. Modifying this property afterwards has no effect.
+
+### delayedStream.maxDataSize = 1024 * 1024
+
+The amount of data to buffer before emitting an `error`.
+
+If the underlaying source is emitting `Buffer` objects, the `maxDataSize`
+refers to bytes.
+
+If the underlaying source is emitting JavaScript strings, the size refers to
+characters.
+
+If you know what you are doing, you can set this property to `Infinity` to
+disable this feature. You can also modify this property during runtime.
+
+### delayedStream.maxDataSize = 1024 * 1024
+
+The amount of data to buffer before emitting an `error`.
+
+If the underlaying source is emitting `Buffer` objects, the `maxDataSize`
+refers to bytes.
+
+If the underlaying source is emitting JavaScript strings, the size refers to
+characters.
+
+If you know what you are doing, you can set this property to `Infinity` to
+disable this feature.
+
+### delayedStream.dataSize = 0
+
+The amount of data buffered so far.
+
+### delayedStream.readable
+
+An ECMA5 getter that returns the value of `source.readable`.
+
+### delayedStream.resume()
+
+If the `delayedStream` has not been released so far, `delayedStream.release()`
+is called.
+
+In either case, `source.resume()` is called.
+
+### delayedStream.pause()
+
+Calls `source.pause()`.
+
+### delayedStream.pipe(dest)
+
+Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`.
+
+### delayedStream.release()
+
+Emits and clears all events that have been buffered up so far. This does not
+resume the underlaying source, use `delayedStream.resume()` instead.
+
+## License
+
+delayed-stream is licensed under the MIT license.
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js	(revision 484)
@@ -0,0 +1,99 @@
+var Stream = require('stream').Stream;
+var util = require('util');
+
+module.exports = DelayedStream;
+function DelayedStream() {
+  this.source = null;
+  this.dataSize = 0;
+  this.maxDataSize = 1024 * 1024;
+  this.pauseStream = true;
+
+  this._maxDataSizeExceeded = false;
+  this._released = false;
+  this._bufferedEvents = [];
+}
+util.inherits(DelayedStream, Stream);
+
+DelayedStream.create = function(source, options) {
+  var delayedStream = new this();
+
+  options = options || {};
+  for (var option in options) {
+    delayedStream[option] = options[option];
+  }
+
+  delayedStream.source = source;
+
+  var realEmit = source.emit;
+  source.emit = function() {
+    delayedStream._handleEmit(arguments);
+    return realEmit.apply(source, arguments);
+  };
+
+  source.on('error', function() {});
+  if (delayedStream.pauseStream) {
+    source.pause();
+  }
+
+  return delayedStream;
+};
+
+DelayedStream.prototype.__defineGetter__('readable', function() {
+  return this.source.readable;
+});
+
+DelayedStream.prototype.resume = function() {
+  if (!this._released) {
+    this.release();
+  }
+
+  this.source.resume();
+};
+
+DelayedStream.prototype.pause = function() {
+  this.source.pause();
+};
+
+DelayedStream.prototype.release = function() {
+  this._released = true;
+
+  this._bufferedEvents.forEach(function(args) {
+    this.emit.apply(this, args);
+  }.bind(this));
+  this._bufferedEvents = [];
+};
+
+DelayedStream.prototype.pipe = function() {
+  var r = Stream.prototype.pipe.apply(this, arguments);
+  this.resume();
+  return r;
+};
+
+DelayedStream.prototype._handleEmit = function(args) {
+  if (this._released) {
+    this.emit.apply(this, args);
+    return;
+  }
+
+  if (args[0] === 'data') {
+    this.dataSize += args[1].length;
+    this._checkIfMaxDataSizeExceeded();
+  }
+
+  this._bufferedEvents.push(args);
+};
+
+DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() {
+  if (this._maxDataSizeExceeded) {
+    return;
+  }
+
+  if (this.dataSize <= this.maxDataSize) {
+    return;
+  }
+
+  this._maxDataSizeExceeded = true;
+  var message =
+    'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'
+  this.emit('error', new Error(message));
+};
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json	(revision 484)
@@ -0,0 +1,31 @@
+{
+  "author": {
+    "name": "Felix GeisendÃ¶rfer",
+    "email": "felix@debuggable.com",
+    "url": "http://debuggable.com/"
+  },
+  "name": "delayed-stream",
+  "description": "Buffers events from a stream until you are ready to handle them.",
+  "version": "0.0.5",
+  "homepage": "https://github.com/felixge/node-delayed-stream",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/felixge/node-delayed-stream.git"
+  },
+  "main": "./lib/delayed_stream",
+  "engines": {
+    "node": ">=0.4.0"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "fake": "0.2.0",
+    "far": "0.0.1"
+  },
+  "readme": "# delayed-stream\n\nBuffers events from a stream until you are ready to handle them.\n\n## Installation\n\n``` bash\nnpm install delayed-stream\n```\n\n## Usage\n\nThe following example shows how to write a http echo server that delays its\nresponse by 1000 ms.\n\n``` javascript\nvar DelayedStream = require('delayed-stream');\nvar http = require('http');\n\nhttp.createServer(function(req, res) {\n  var delayed = DelayedStream.create(req);\n\n  setTimeout(function() {\n    res.writeHead(200);\n    delayed.pipe(res);\n  }, 1000);\n});\n```\n\nIf you are not using `Stream#pipe`, you can also manually release the buffered\nevents by calling `delayedStream.resume()`:\n\n``` javascript\nvar delayed = DelayedStream.create(req);\n\nsetTimeout(function() {\n  // Emit all buffered events and resume underlaying source\n  delayed.resume();\n}, 1000);\n```\n\n## Implementation\n\nIn order to use this meta stream properly, here are a few things you should\nknow about the implementation.\n\n### Event Buffering / Proxying\n\nAll events of the `source` stream are hijacked by overwriting the `source.emit`\nmethod. Until node implements a catch-all event listener, this is the only way.\n\nHowever, delayed-stream still continues to emit all events it captures on the\n`source`, regardless of whether you have released the delayed stream yet or\nnot.\n\nUpon creation, delayed-stream captures all `source` events and stores them in\nan internal event buffer. Once `delayedStream.release()` is called, all\nbuffered events are emitted on the `delayedStream`, and the event buffer is\ncleared. After that, delayed-stream merely acts as a proxy for the underlaying\nsource.\n\n### Error handling\n\nError events on `source` are buffered / proxied just like any other events.\nHowever, `delayedStream.create` attaches a no-op `'error'` listener to the\n`source`. This way you only have to handle errors on the `delayedStream`\nobject, rather than in two places.\n\n### Buffer limits\n\ndelayed-stream provides a `maxDataSize` property that can be used to limit\nthe amount of data being buffered. In order to protect you from bad `source`\nstreams that don't react to `source.pause()`, this feature is enabled by\ndefault.\n\n## API\n\n### DelayedStream.create(source, [options])\n\nReturns a new `delayedStream`. Available options are:\n\n* `pauseStream`\n* `maxDataSize`\n\nThe description for those properties can be found below.\n\n### delayedStream.source\n\nThe `source` stream managed by this object. This is useful if you are\npassing your `delayedStream` around, and you still want to access properties\non the `source` object.\n\n### delayedStream.pauseStream = true\n\nWhether to pause the underlaying `source` when calling\n`DelayedStream.create()`. Modifying this property afterwards has no effect.\n\n### delayedStream.maxDataSize = 1024 * 1024\n\nThe amount of data to buffer before emitting an `error`.\n\nIf the underlaying source is emitting `Buffer` objects, the `maxDataSize`\nrefers to bytes.\n\nIf the underlaying source is emitting JavaScript strings, the size refers to\ncharacters.\n\nIf you know what you are doing, you can set this property to `Infinity` to\ndisable this feature. You can also modify this property during runtime.\n\n### delayedStream.maxDataSize = 1024 * 1024\n\nThe amount of data to buffer before emitting an `error`.\n\nIf the underlaying source is emitting `Buffer` objects, the `maxDataSize`\nrefers to bytes.\n\nIf the underlaying source is emitting JavaScript strings, the size refers to\ncharacters.\n\nIf you know what you are doing, you can set this property to `Infinity` to\ndisable this feature.\n\n### delayedStream.dataSize = 0\n\nThe amount of data buffered so far.\n\n### delayedStream.readable\n\nAn ECMA5 getter that returns the value of `source.readable`.\n\n### delayedStream.resume()\n\nIf the `delayedStream` has not been released so far, `delayedStream.release()`\nis called.\n\nIn either case, `source.resume()` is called.\n\n### delayedStream.pause()\n\nCalls `source.pause()`.\n\n### delayedStream.pipe(dest)\n\nCalls `delayedStream.resume()` and then proxies the arguments to `source.pipe`.\n\n### delayedStream.release()\n\nEmits and clears all events that have been buffered up so far. This does not\nresume the underlaying source, use `delayedStream.resume()` instead.\n\n## License\n\ndelayed-stream is licensed under the MIT license.\n",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/felixge/node-delayed-stream/issues"
+  },
+  "_id": "delayed-stream@0.0.5",
+  "_from": "delayed-stream@0.0.5"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/common.js	(revision 484)
@@ -0,0 +1,6 @@
+var common = module.exports;
+
+common.DelayedStream = require('..');
+common.assert = require('assert');
+common.fake = require('fake');
+common.PORT = 49252;
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-http-upload.js	(revision 484)
@@ -0,0 +1,38 @@
+var common = require('../common');
+var assert = common.assert;
+var DelayedStream = common.DelayedStream;
+var http = require('http');
+
+var UPLOAD = new Buffer(10 * 1024 * 1024);
+
+var server = http.createServer(function(req, res) {
+  var delayed = DelayedStream.create(req, {maxDataSize: UPLOAD.length});
+
+  setTimeout(function() {
+    res.writeHead(200);
+    delayed.pipe(res);
+  }, 10);
+});
+server.listen(common.PORT, function() {
+  var request = http.request({
+    method: 'POST',
+    port: common.PORT,
+  });
+
+  request.write(UPLOAD);
+  request.end();
+
+  request.on('response', function(res) {
+    var received = 0;
+    res
+      .on('data', function(chunk) {
+        received += chunk.length;
+      })
+      .on('end', function() {
+        assert.equal(received, UPLOAD.length);
+        server.close();
+      });
+  });
+});
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-auto-pause.js	(revision 484)
@@ -0,0 +1,21 @@
+var common = require('../common');
+var assert = common.assert;
+var fake = common.fake.create();
+var DelayedStream = common.DelayedStream;
+var Stream = require('stream').Stream;
+
+(function testAutoPause() {
+  var source = new Stream();
+
+  fake.expect(source, 'pause', 1);
+  var delayedStream = DelayedStream.create(source);
+  fake.verify();
+})();
+
+(function testDisableAutoPause() {
+  var source = new Stream();
+  fake.expect(source, 'pause', 0);
+
+  var delayedStream = DelayedStream.create(source, {pauseStream: false});
+  fake.verify();
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream-pause.js	(revision 484)
@@ -0,0 +1,14 @@
+var common = require('../common');
+var assert = common.assert;
+var fake = common.fake.create();
+var DelayedStream = common.DelayedStream;
+var Stream = require('stream').Stream;
+
+(function testDelayEventsUntilResume() {
+  var source = new Stream();
+  var delayedStream = DelayedStream.create(source, {pauseStream: false});
+
+  fake.expect(source, 'pause');
+  delayedStream.pause();
+  fake.verify();
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-delayed-stream.js	(revision 484)
@@ -0,0 +1,48 @@
+var common = require('../common');
+var assert = common.assert;
+var fake = common.fake.create();
+var DelayedStream = common.DelayedStream;
+var Stream = require('stream').Stream;
+
+(function testDelayEventsUntilResume() {
+  var source = new Stream();
+  var delayedStream = DelayedStream.create(source, {pauseStream: false});
+
+  // delayedStream must not emit until we resume
+  fake.expect(delayedStream, 'emit', 0);
+
+  // but our original source must emit
+  var params = [];
+  source.on('foo', function(param) {
+    params.push(param);
+  });
+
+  source.emit('foo', 1);
+  source.emit('foo', 2);
+
+  // Make sure delayedStream did not emit, and source did
+  assert.deepEqual(params, [1, 2]);
+  fake.verify();
+
+  // After resume, delayedStream must playback all events
+  fake
+    .stub(delayedStream, 'emit')
+    .times(Infinity)
+    .withArg(1, 'newListener');
+  fake.expect(delayedStream, 'emit', ['foo', 1]);
+  fake.expect(delayedStream, 'emit', ['foo', 2]);
+  fake.expect(source, 'resume');
+
+  delayedStream.resume();
+  fake.verify();
+
+  // Calling resume again will delegate to source
+  fake.expect(source, 'resume');
+  delayedStream.resume();
+  fake.verify();
+
+  // Emitting more events directly leads to them being emitted
+  fake.expect(delayedStream, 'emit', ['foo', 3]);
+  source.emit('foo', 3);
+  fake.verify();
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-handle-source-errors.js	(revision 484)
@@ -0,0 +1,15 @@
+var common = require('../common');
+var assert = common.assert;
+var fake = common.fake.create();
+var DelayedStream = common.DelayedStream;
+var Stream = require('stream').Stream;
+
+(function testHandleSourceErrors() {
+  var source = new Stream();
+  var delayedStream = DelayedStream.create(source, {pauseStream: false});
+
+  // We deal with this by attaching a no-op listener to 'error' on the source
+  // when creating a new DelayedStream. This way error events on the source
+  // won't throw.
+  source.emit('error', new Error('something went wrong'));
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-max-data-size.js	(revision 484)
@@ -0,0 +1,18 @@
+var common = require('../common');
+var assert = common.assert;
+var fake = common.fake.create();
+var DelayedStream = common.DelayedStream;
+var Stream = require('stream').Stream;
+
+(function testMaxDataSize() {
+  var source = new Stream();
+  var delayedStream = DelayedStream.create(source, {maxDataSize: 1024, pauseStream: false});
+
+  source.emit('data', new Buffer(1024));
+
+  fake
+    .expect(delayedStream, 'emit')
+    .withArg(1, 'error');
+  source.emit('data', new Buffer(1));
+  fake.verify();
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-pipe-resumes.js	(revision 484)
@@ -0,0 +1,13 @@
+var common = require('../common');
+var assert = common.assert;
+var fake = common.fake.create();
+var DelayedStream = common.DelayedStream;
+var Stream = require('stream').Stream;
+
+(function testPipeReleases() {
+  var source = new Stream();
+  var delayedStream = DelayedStream.create(source, {pauseStream: false});
+
+  fake.expect(delayedStream, 'resume');
+  delayedStream.pipe(new Stream());
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/integration/test-proxy-readable.js	(revision 484)
@@ -0,0 +1,13 @@
+var common = require('../common');
+var assert = common.assert;
+var fake = common.fake.create();
+var DelayedStream = common.DelayedStream;
+var Stream = require('stream').Stream;
+
+(function testProxyReadableProperty() {
+  var source = new Stream();
+  var delayedStream = DelayedStream.create(source, {pauseStream: false});
+
+  source.readable = fake.value('source.readable');
+  assert.strictEqual(delayedStream.readable, source.readable);
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/test/run.js	(revision 484)
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+var far = require('far').create();
+
+far.add(__dirname);
+far.include(/test-.*\.js$/);
+
+far.execute();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/package.json	(revision 484)
@@ -0,0 +1,32 @@
+{
+  "author": {
+    "name": "Felix GeisendÃ¶rfer",
+    "email": "felix@debuggable.com",
+    "url": "http://debuggable.com/"
+  },
+  "name": "combined-stream",
+  "description": "A stream that emits multiple other streams one after another.",
+  "version": "0.0.4",
+  "homepage": "https://github.com/felixge/node-combined-stream",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/felixge/node-combined-stream.git"
+  },
+  "main": "./lib/combined_stream",
+  "engines": {
+    "node": "*"
+  },
+  "dependencies": {
+    "delayed-stream": "0.0.5"
+  },
+  "devDependencies": {
+    "far": "0.0.1"
+  },
+  "readme": "# combined-stream\n\nA stream that emits multiple other streams one after another.\n\n## Installation\n\n``` bash\nnpm install combined-stream\n```\n\n## Usage\n\nHere is a simple example that shows how you can use combined-stream to combine\ntwo files into one:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create();\ncombinedStream.append(fs.createReadStream('file1.txt'));\ncombinedStream.append(fs.createReadStream('file2.txt'));\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\nWhile the example above works great, it will pause all source streams until\nthey are needed. If you don't want that to happen, you can set `pauseStreams`\nto `false`:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create({pauseStreams: false});\ncombinedStream.append(fs.createReadStream('file1.txt'));\ncombinedStream.append(fs.createReadStream('file2.txt'));\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\nHowever, what if you don't have all the source streams yet, or you don't want\nto allocate the resources (file descriptors, memory, etc.) for them right away?\nWell, in that case you can simply provide a callback that supplies the stream\nby calling a `next()` function:\n\n``` javascript\nvar CombinedStream = require('combined-stream');\nvar fs = require('fs');\n\nvar combinedStream = CombinedStream.create();\ncombinedStream.append(function(next) {\n  next(fs.createReadStream('file1.txt'));\n});\ncombinedStream.append(function(next) {\n  next(fs.createReadStream('file2.txt'));\n});\n\ncombinedStream.pipe(fs.createWriteStream('combined.txt'));\n```\n\n## API\n\n### CombinedStream.create([options])\n\nReturns a new combined stream object. Available options are:\n\n* `maxDataSize`\n* `pauseStreams`\n\nThe effect of those options is described below.\n\n### combinedStream.pauseStreams = true\n\nWhether to apply back pressure to the underlaying streams. If set to `false`,\nthe underlaying streams will never be paused. If set to `true`, the\nunderlaying streams will be paused right after being appended, as well as when\n`delayedStream.pipe()` wants to throttle.\n\n### combinedStream.maxDataSize = 2 * 1024 * 1024\n\nThe maximum amount of bytes (or characters) to buffer for all source streams.\nIf this value is exceeded, `combinedStream` emits an `'error'` event.\n\n### combinedStream.dataSize = 0\n\nThe amount of bytes (or characters) currently buffered by `combinedStream`.\n\n### combinedStream.append(stream)\n\nAppends the given `stream` to the combinedStream object. If `pauseStreams` is\nset to `true, this stream will also be paused right away.\n\n`streams` can also be a function that takes one parameter called `next`. `next`\nis a function that must be invoked in order to provide the `next` stream, see\nexample above.\n\nRegardless of how the `stream` is appended, combined-stream always attaches an\n`'error'` listener to it, so you don't have to do that manually.\n\nSpecial case: `stream` can also be a String or Buffer.\n\n### combinedStream.write(data)\n\nYou should not call this, `combinedStream` takes care of piping the appended\nstreams into itself for you.\n\n### combinedStream.resume()\n\nCauses `combinedStream` to start drain the streams it manages. The function is\nidempotent, and also emits a `'resume'` event each time which usually goes to\nthe stream that is currently being drained.\n\n### combinedStream.pause();\n\nIf `combinedStream.pauseStreams` is set to `false`, this does nothing.\nOtherwise a `'pause'` event is emitted, this goes to the stream that is\ncurrently being drained, so you can use it to apply back pressure.\n\n### combinedStream.end();\n\nSets `combinedStream.writable` to false, emits an `'end'` event, and removes\nall streams from the queue.\n\n### combinedStream.destroy();\n\nSame as `combinedStream.end()`, except it emits a `'close'` event instead of\n`'end'`.\n\n## License\n\ncombined-stream is licensed under the MIT license.\n",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/felixge/node-combined-stream/issues"
+  },
+  "_id": "combined-stream@0.0.4",
+  "_from": "combined-stream@~0.0.4"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/common.js	(revision 484)
@@ -0,0 +1,23 @@
+var common = module.exports;
+
+var path = require('path');
+var fs = require('fs');
+var root = path.join(__dirname, '..');
+
+common.dir = {
+  fixture: root + '/test/fixture',
+  tmp: root + '/test/tmp',
+};
+
+// Create tmp directory if it does not exist
+// Not using fs.exists so as to be node 0.6.x compatible
+try {
+  fs.statSync(common.dir.tmp);
+}
+catch (e) {
+  // Dir does not exist
+  fs.mkdirSync(common.dir.tmp);
+}
+
+common.CombinedStream = require(root);
+common.assert = require('assert');
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file1.txt	(revision 484)
@@ -0,0 +1,256 @@
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
+10101010101010101010101010101010101010101010101010101010101010101010101010101010
+01010101010101010101010101010101010101010101010101010101010101010101010101010101
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/fixture/file2.txt	(revision 484)
@@ -0,0 +1,256 @@
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
+20202020202020202020202020202020202020202020202020202020202020202020202020202020
+02020202020202020202020202020202020202020202020202020202020202020202020202020202
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-callback-streams.js	(revision 484)
@@ -0,0 +1,27 @@
+var common = require('../common');
+var assert = common.assert;
+var CombinedStream = common.CombinedStream;
+var fs = require('fs');
+
+var FILE1 = common.dir.fixture + '/file1.txt';
+var FILE2 = common.dir.fixture + '/file2.txt';
+var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
+
+(function testDelayedStreams() {
+  var combinedStream = CombinedStream.create();
+  combinedStream.append(function(next) {
+    next(fs.createReadStream(FILE1));
+  });
+  combinedStream.append(function(next) {
+    next(fs.createReadStream(FILE2));
+  });
+
+  var tmpFile = common.dir.tmp + '/combined.txt';
+  var dest = fs.createWriteStream(tmpFile);
+  combinedStream.pipe(dest);
+
+  dest.on('end', function() {
+    var written = fs.readFileSync(tmpFile, 'utf8');
+    assert.strictEqual(written, EXPECTED);
+  });
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-data-size.js	(revision 484)
@@ -0,0 +1,34 @@
+var common = require('../common');
+var assert = common.assert;
+var CombinedStream = common.CombinedStream;
+
+(function testDataSizeGetter() {
+  var combinedStream = CombinedStream.create();
+
+  assert.strictEqual(combinedStream.dataSize, 0);
+
+  // Test one stream
+  combinedStream._streams.push({dataSize: 10});
+  combinedStream._updateDataSize();
+  assert.strictEqual(combinedStream.dataSize, 10);
+
+  // Test two streams
+  combinedStream._streams.push({dataSize: 23});
+  combinedStream._updateDataSize();
+  assert.strictEqual(combinedStream.dataSize, 33);
+
+  // Test currentStream
+  combinedStream._currentStream = {dataSize: 20};
+  combinedStream._updateDataSize();
+  assert.strictEqual(combinedStream.dataSize, 53);
+
+  // Test currentStream without dataSize
+  combinedStream._currentStream = {};
+  combinedStream._updateDataSize();
+  assert.strictEqual(combinedStream.dataSize, 33);
+
+  // Test stream function
+  combinedStream._streams.push(function() {});
+  combinedStream._updateDataSize();
+  assert.strictEqual(combinedStream.dataSize, 33);
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams-and-buffers-and-strings.js	(revision 484)
@@ -0,0 +1,38 @@
+var common = require('../common');
+var assert = common.assert;
+var CombinedStream = common.CombinedStream;
+var fs = require('fs');
+
+var FILE1 = common.dir.fixture + '/file1.txt';
+var BUFFER = new Buffer('Bacon is delicious');
+var FILE2 = common.dir.fixture + '/file2.txt';
+var STRING = 'The â¬ kicks the $\'s ass!';
+
+var EXPECTED =
+  fs.readFileSync(FILE1)
+  + BUFFER
+  + fs.readFileSync(FILE2)
+  + STRING;
+var GOT;
+
+(function testDelayedStreams() {
+  var combinedStream = CombinedStream.create();
+  combinedStream.append(fs.createReadStream(FILE1));
+  combinedStream.append(BUFFER);
+  combinedStream.append(fs.createReadStream(FILE2));
+  combinedStream.append(function(next) {
+    next(STRING);
+  });
+
+  var tmpFile = common.dir.tmp + '/combined-file1-buffer-file2-string.txt';
+  var dest = fs.createWriteStream(tmpFile);
+  combinedStream.pipe(dest);
+
+  dest.on('close', function() {
+    GOT = fs.readFileSync(tmpFile, 'utf8');
+  });
+})();
+
+process.on('exit', function() {
+  assert.strictEqual(GOT, EXPECTED);
+});
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-delayed-streams.js	(revision 484)
@@ -0,0 +1,35 @@
+var common = require('../common');
+var assert = common.assert;
+var CombinedStream = common.CombinedStream;
+var fs = require('fs');
+
+var FILE1 = common.dir.fixture + '/file1.txt';
+var FILE2 = common.dir.fixture + '/file2.txt';
+var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
+var GOT;
+
+(function testDelayedStreams() {
+  var combinedStream = CombinedStream.create();
+  combinedStream.append(fs.createReadStream(FILE1));
+  combinedStream.append(fs.createReadStream(FILE2));
+
+  var stream1 = combinedStream._streams[0];
+  var stream2 = combinedStream._streams[1];
+
+  stream1.on('end', function() {
+    assert.equal(stream2.dataSize, 0);
+  });
+
+  var tmpFile = common.dir.tmp + '/combined.txt';
+  var dest = fs.createWriteStream(tmpFile);
+  combinedStream.pipe(dest);
+
+  dest.on('close', function() {
+    GOT = fs.readFileSync(tmpFile, 'utf8');
+  });
+})();
+
+process.on('exit', function() {
+  console.error(GOT.length, EXPECTED.length);
+  assert.strictEqual(GOT, EXPECTED);
+});
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-empty-string.js	(revision 484)
@@ -0,0 +1,39 @@
+var common = require('../common');
+var assert = common.assert;
+var CombinedStream = common.CombinedStream;
+var util = require('util');
+var Stream = require('stream').Stream;
+
+var s = CombinedStream.create();
+
+
+function StringStream(){
+  this.writable=true;
+  this.str=""
+}
+util.inherits(StringStream,Stream);
+
+StringStream.prototype.write=function(chunk,encoding){
+  this.str+=chunk.toString();
+  this.emit('data',chunk);
+}
+
+StringStream.prototype.end=function(chunk,encoding){
+  this.emit('end');
+}
+
+StringStream.prototype.toString=function(){
+  return this.str;
+}
+
+
+s.append("foo.");
+s.append("");
+s.append("bar");
+
+var ss = new StringStream();
+
+s.pipe(ss);
+s.resume();
+
+assert.equal(ss.toString(),"foo.bar");
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-is-stream-like.js	(revision 484)
@@ -0,0 +1,17 @@
+var fs = require('fs');
+var common = require('../common');
+var assert = common.assert;
+var CombinedStream = common.CombinedStream;
+var FILE1 = common.dir.fixture + '/file1.txt';
+var fileStream = fs.createReadStream(FILE1);
+
+var foo = function(){};
+
+(function testIsStreamLike() {
+  assert(! CombinedStream.isStreamLike(true));
+  assert(! CombinedStream.isStreamLike("I am a string"));
+  assert(! CombinedStream.isStreamLike(7));
+  assert(! CombinedStream.isStreamLike(foo));
+
+  assert(CombinedStream.isStreamLike(fileStream));
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-max-data-size.js	(revision 484)
@@ -0,0 +1,24 @@
+var common = require('../common');
+var assert = common.assert;
+var CombinedStream = common.CombinedStream;
+var fs = require('fs');
+
+var FILE1 = common.dir.fixture + '/file1.txt';
+var FILE2 = common.dir.fixture + '/file2.txt';
+var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
+
+(function testDelayedStreams() {
+  var combinedStream = CombinedStream.create({pauseStreams: false, maxDataSize: 20736});
+  combinedStream.append(fs.createReadStream(FILE1));
+  combinedStream.append(fs.createReadStream(FILE2));
+
+  var gotErr = null;
+  combinedStream.on('error', function(err) {
+    gotErr = err;
+  });
+
+  process.on('exit', function() {
+    assert.ok(gotErr);
+    assert.ok(gotErr.message.match(/bytes/));
+  });
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/integration/test-unpaused-streams.js	(revision 484)
@@ -0,0 +1,30 @@
+var common = require('../common');
+var assert = common.assert;
+var CombinedStream = common.CombinedStream;
+var fs = require('fs');
+
+var FILE1 = common.dir.fixture + '/file1.txt';
+var FILE2 = common.dir.fixture + '/file2.txt';
+var EXPECTED = fs.readFileSync(FILE1) + fs.readFileSync(FILE2);
+
+(function testDelayedStreams() {
+  var combinedStream = CombinedStream.create({pauseStreams: false});
+  combinedStream.append(fs.createReadStream(FILE1));
+  combinedStream.append(fs.createReadStream(FILE2));
+
+  var stream1 = combinedStream._streams[0];
+  var stream2 = combinedStream._streams[1];
+
+  stream1.on('end', function() {
+    assert.ok(stream2.dataSize > 0);
+  });
+
+  var tmpFile = common.dir.tmp + '/combined.txt';
+  var dest = fs.createWriteStream(tmpFile);
+  combinedStream.pipe(dest);
+
+  dest.on('end', function() {
+    var written = fs.readFileSync(tmpFile, 'utf8');
+    assert.strictEqual(written, EXPECTED);
+  });
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/node_modules/combined-stream/test/run.js	(revision 484)
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+var far = require('far').create();
+
+far.add(__dirname);
+far.include(/test-.*\.js$/);
+
+far.execute();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/package.json	(revision 484)
@@ -0,0 +1,40 @@
+{
+  "author": {
+    "name": "Felix GeisendÃ¶rfer",
+    "email": "felix@debuggable.com",
+    "url": "http://debuggable.com/"
+  },
+  "name": "form-data",
+  "description": "A module to create readable `\"multipart/form-data\"` streams.  Can be used to submit forms and file uploads to other web applications.",
+  "version": "0.0.8",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/felixge/node-form-data.git"
+  },
+  "main": "./lib/form_data",
+  "scripts": {
+    "test": "node test/run.js"
+  },
+  "engines": {
+    "node": ">= 0.6"
+  },
+  "dependencies": {
+    "combined-stream": "~0.0.4",
+    "mime": "~1.2.2",
+    "async": "~0.2.7"
+  },
+  "devDependencies": {
+    "fake": "~0.2.1",
+    "far": "~0.0.7",
+    "formidable": "~1.0.13",
+    "request": "~2.16.6"
+  },
+  "readme": "# Form-Data [![Build Status](https://travis-ci.org/alexindigo/node-form-data.png?branch=master)](https://travis-ci.org/alexindigo/node-form-data)\n\nA module to create readable `\"multipart/form-data\"` streams.  Can be used to\nsubmit forms and file uploads to other web applications.\n\nThe API of this module is inspired by the\n[XMLHttpRequest-2 FormData Interface][xhr2-fd].\n\n[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface\n\n## Install\n\n```\nnpm install form-data\n```\n\n## Usage\n\nIn this example we are constructing a form with 3 fields that contain a string,\na buffer and a file stream.\n\n``` javascript\nvar FormData = require('form-data');\nvar fs = require('fs');\n\nvar form = new FormData();\nform.append('my_field', 'my value');\nform.append('my_buffer', new Buffer(10));\nform.append('my_file', fs.createReadStream('/foo/bar.jpg'));\n```\n\nAlso you can use http-response stream:\n\n``` javascript\nvar FormData = require('form-data');\nvar http = require('http');\n\nvar form = new FormData();\n\nhttp.request('http://nodejs.org/images/logo.png', function(response) {\n  form.append('my_field', 'my value');\n  form.append('my_buffer', new Buffer(10));\n  form.append('my_logo', response);\n});\n```\n\nOr @mikeal's request stream:\n\n``` javascript\nvar FormData = require('form-data');\nvar request = require('request');\n\nvar form = new FormData();\n\nform.append('my_field', 'my value');\nform.append('my_buffer', new Buffer(10));\nform.append('my_logo', request('http://nodejs.org/images/logo.png'));\n```\n\nIn order to submit this form to a web application, you can use node's http\nclient interface:\n\n``` javascript\nvar http = require('http');\n\nvar request = http.request({\n  method: 'post',\n  host: 'example.org',\n  path: '/upload',\n  headers: form.getHeaders()\n});\n\nform.pipe(request);\n\nrequest.on('response', function(res) {\n  console.log(res.statusCode);\n});\n```\n\nOr if you would prefer the `'Content-Length'` header to be set for you:\n\n``` javascript\nform.submit('example.org/upload', function(err, res) {\n  console.log(res.statusCode);\n});\n```\n\nTo use custom headers and pre-known length in parts:\n\n``` javascript\nvar CRLF = '\\r\\n';\nvar form = new FormData();\n\nvar options = {\n  header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,\n  knownLength: 1\n};\n\nform.append('my_buffer', buffer, options);\n\nform.submit('http://example.com/', function(err, res) {\n  if (err) throw err;\n  console.log('Done');\n});\n```\n\nForm-Data can recognize and fetch all the required information from common types of streams (fs.readStream, http.response and mikeal's request), for some other types of streams you'd need to provide \"file\"-related information manually:\n\n``` javascript\nsomeModule.stream(function(err, stdout, stderr) {\n  if (err) throw err;\n\n  var form = new FormData();\n\n  form.append('file', stdout, {\n    filename: 'unicycle.jpg',\n    contentType: 'image/jpg',\n    knownLength: 19806\n  });\n\n  form.submit('http://example.com/', function(err, res) {\n    if (err) throw err;\n    console.log('Done');\n  });\n});\n```\n\nFor edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter:\n\n``` javascript\nform.submit({\n  host: 'example.com',\n  path: '/probably.php?extra=params',\n  auth: 'username:password'\n}, function(err, res) {\n  console.log(res.statusCode);\n});\n```\n\n## TODO\n\n- Add new streams (0.10) support and try really hard not to break it for 0.8.x.\n\n## License\n\nForm-Data is licensed under the MIT license.\n",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/felixge/node-form-data/issues"
+  },
+  "homepage": "https://github.com/felixge/node-form-data",
+  "_id": "form-data@0.0.8",
+  "_from": "form-data@0.0.8"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/sftp-config.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/sftp-config.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/sftp-config.json	(revision 484)
@@ -0,0 +1,43 @@
+{
+    // The tab key will cycle through the settings when first created
+    // Visit http://wbond.net/sublime_packages/sftp/settings for help
+
+    // sftp, ftp or ftps
+    "type": "sftp",
+
+    "save_before_upload": true,
+    "upload_on_save": true,
+    "sync_down_on_open": false,
+    "sync_skip_deletes": false,
+    "confirm_downloads": false,
+    "confirm_sync": true,
+    "confirm_overwrite_newer": false,
+
+    "host": "amber.exposeapp.com",
+    "user": "alex",
+    //"password": "password",
+    //"port": "22",
+
+    "remote_path": "/var/www/_playground/form-data/",
+    "ignore_regexes": [
+        "node_modules",
+        "\\.sublime-(project|workspace)", "sftp-config(-alt\\d?)?\\.json",
+        "sftp-settings\\.json", "/venv/", "\\.svn", "\\.hg", "\\.git",
+        "\\.bzr", "_darcs", "CVS", "\\.DS_Store", "Thumbs\\.db", "desktop\\.ini"
+    ],
+    //"file_permissions": "664",
+    //"dir_permissions": "775",
+
+    //"extra_list_connections": 0,
+
+    "connect_timeout": 30,
+    //"keepalive": 120,
+    //"ftp_passive_mode": true,
+    //"ssh_key_file": "~/.ssh/id_rsa",
+    //"sftp_flags": ["-F", "/path/to/ssh_config"],
+
+    //"preserve_modification_times": false,
+    //"remote_time_offset_in_hours": 0,
+    //"remote_encoding": "utf-8",
+    //"remote_locale": "C",
+}
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/common.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/common.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/common.js	(revision 484)
@@ -0,0 +1,14 @@
+var common = module.exports;
+var path = require('path');
+
+var rootDir = path.join(__dirname, '..');
+common.dir = {
+  lib: rootDir + '/lib',
+  fixture: rootDir + '/test/fixture',
+  tmp: rootDir + '/test/tmp',
+};
+
+common.assert = require('assert');
+common.fake = require('fake');
+
+common.port = 8432;
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/fixture/bacon.txt
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/fixture/bacon.txt	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/fixture/bacon.txt	(revision 484)
@@ -0,0 +1,1 @@
+Bacon is delicious.
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-custom-filename.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-custom-filename.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-custom-filename.js	(revision 484)
@@ -0,0 +1,52 @@
+/*
+test custom filename and content-type:
+re: https://github.com/felixge/node-form-data/issues/29
+*/
+
+var common       = require('../common');
+var assert       = common.assert;
+var http         = require('http');
+var fs           = require('fs');
+
+var FormData     = require(common.dir.lib + '/form_data');
+var IncomingForm = require('formidable').IncomingForm;
+
+var options = {
+  filename: 'test.png',
+  contentType: 'image/gif'
+};
+
+var server = http.createServer(function(req, res) {
+
+  var form = new IncomingForm({uploadDir: common.dir.tmp});
+
+  form.parse(req);
+
+  form
+    .on('file', function(name, file) {
+      assert.strictEqual(name, 'my_file');
+      assert.strictEqual(file.name, options.filename);
+      assert.strictEqual(file.type, options.contentType);
+    })
+    .on('end', function() {
+      res.writeHead(200);
+      res.end('done');
+    });
+});
+
+
+server.listen(common.port, function() {
+  var form = new FormData();
+
+  form.append('my_file', fs.createReadStream(common.dir.fixture + '/unicycle.jpg'), options);
+
+  form.submit('http://localhost:' + common.port + '/', function(err, res) {
+    if (err) {
+      throw err;
+    }
+
+    assert.strictEqual(res.statusCode, 200);
+    server.close();
+  });
+
+});
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-custom-headers.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-custom-headers.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-custom-headers.js	(revision 484)
@@ -0,0 +1,75 @@
+/*
+test custom headers, added in pull request:
+https://github.com/felixge/node-form-data/pull/17
+*/
+
+var common = require('../common');
+var assert = common.assert;
+var http = require('http');
+
+var FormData = require(common.dir.lib + '/form_data');
+
+var CRLF = '\r\n';
+
+var testHeader = 'X-Test-Fake: 123';
+
+var expectedLength;
+
+
+var server = http.createServer(function(req, res) {
+  var data = '';
+  req.setEncoding('utf8');
+
+  req.on('data', function(d) {
+    data += d;
+  });
+
+  req.on('end', function() {
+    assert.ok( data.indexOf( testHeader ) != -1 );
+
+    // content-length would be 1000+ w/actual buffer size,
+    // but smaller w/overridden size.
+    assert.ok( typeof req.headers['content-length'] !== 'undefined' );
+    assert.equal(req.headers['content-length'], expectedLength);
+
+    res.writeHead(200);
+    res.end('done');
+  });
+});
+
+
+server.listen(common.port, function() {
+  var form = new FormData();
+
+  var options = {
+    header:
+      CRLF + '--' + form.getBoundary() + CRLF +
+      testHeader +
+      CRLF + CRLF,
+
+    // override content-length,
+    // much lower than actual buffer size (1000)
+    knownLength: 1
+  };
+
+  var bufferData = [];
+  for (var z = 0; z < 1000; z++) {
+    bufferData.push(1);
+  }
+  var buffer = new Buffer(bufferData);
+
+  form.append('my_buffer', buffer, options);
+
+  // (available to req handler)
+  expectedLength = form._lastBoundary().length + form._overheadLength + options.knownLength;
+
+  form.submit('http://localhost:' + common.port + '/', function(err, res) {
+    if (err) {
+      throw err;
+    }
+
+    assert.strictEqual(res.statusCode, 200);
+    server.close();
+  });
+
+});
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-form-get-length.js	(revision 484)
@@ -0,0 +1,93 @@
+var common = require('../common');
+var assert = common.assert;
+var FormData = require(common.dir.lib + '/form_data');
+var fake = require('fake').create();
+var fs = require('fs');
+
+(function testEmptyForm() {
+  var form = new FormData();
+  var callback = fake.callback(arguments.callee.name + '-getLength');
+  var calls = fake.expectAnytime(callback, [null, 0]).calls;
+
+  form.getLength(callback);
+
+  // Make sure our response is async
+  assert.strictEqual(calls.length, 0);
+})();
+
+(function testUtf8String() {
+  var FIELD = 'my_field';
+  var VALUE = 'May the â¬ be with you';
+
+  var form = new FormData();
+  form.append(FIELD, VALUE);
+  var callback = fake.callback(arguments.callee.name + '-getLength');
+
+  var expectedLength =
+    form._overheadLength +
+    Buffer.byteLength(VALUE) +
+    form._lastBoundary().length;
+
+  fake.expectAnytime(callback, [null, expectedLength]);
+  form.getLength(callback);
+})();
+
+(function testBuffer() {
+  var FIELD = 'my_field';
+  var VALUE = new Buffer(23);
+
+  var form = new FormData();
+  form.append(FIELD, VALUE);
+  var callback = fake.callback(arguments.callee.name + '-getLength');
+
+  var expectedLength =
+    form._overheadLength +
+    VALUE.length +
+    form._lastBoundary().length;
+
+  fake.expectAnytime(callback, [null, expectedLength]);
+  form.getLength(callback);
+})();
+
+
+(function testStringFileBufferFile() {
+  var fields = [
+    {
+      name: 'my_field',
+      value: 'Test 123',
+    },
+    {
+      name: 'my_image',
+      value: fs.createReadStream(common.dir.fixture + '/unicycle.jpg'),
+    },
+    {
+      name: 'my_buffer',
+      value: new Buffer('123'),
+    },
+    {
+      name: 'my_txt',
+      value: fs.createReadStream(common.dir.fixture + '/bacon.txt'),
+    },
+  ];
+
+  var form = new FormData();
+  var expectedLength = 0;
+
+  fields.forEach(function(field) {
+    form.append(field.name, field.value);
+    if (field.value.path) {
+      var stat = fs.statSync(field.value.path);
+      expectedLength += stat.size;
+    } else {
+      expectedLength += field.value.length;
+    }
+  });
+
+  expectedLength += form._overheadLength + form._lastBoundary().length;
+
+  var callback = fake.callback(arguments.callee.name + '-getLength');
+  fake.expectAnytime(callback, [null, expectedLength]);
+  form.getLength(callback);
+})();
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-get-boundary.js	(revision 484)
@@ -0,0 +1,18 @@
+var common = require('../common');
+var assert = common.assert;
+
+var FormData = require(common.dir.lib + '/form_data');
+
+(function testOneBoundaryPerForm() {
+  var form = new FormData();
+  var boundary = form.getBoundary();
+
+  assert.equal(boundary, form.getBoundary());
+  assert.equal(boundary.length, 50);
+})();
+
+(function testUniqueBoundaryPerForm() {
+  var formA = new FormData();
+  var formB = new FormData();
+  assert.notEqual(formA.getBoundary(), formB.getBoundary());
+})();
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-http-response.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-http-response.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-http-response.js	(revision 484)
@@ -0,0 +1,83 @@
+var common = require('../common');
+var assert = common.assert;
+var http = require('http');
+var path = require('path');
+var mime = require('mime');
+var request = require('request');
+var parseUrl = require('url').parse;
+var fs = require('fs');
+var FormData = require(common.dir.lib + '/form_data');
+var IncomingForm = require('formidable').IncomingForm;
+
+var remoteFile = 'http://nodejs.org/images/logo.png';
+
+var FIELDS;
+var server;
+
+var parsedUrl = parseUrl(remoteFile)
+  , options = {
+      method: 'get',
+      port: parsedUrl.port || 80,
+      path: parsedUrl.pathname,
+      host: parsedUrl.hostname
+    }
+  ;
+
+http.request(options, function(res) {
+
+  FIELDS = [
+    {name: 'my_field', value: 'my_value'},
+    {name: 'my_buffer', value: new Buffer([1, 2, 3])},
+    {name: 'remote_file', value: res }
+  ];
+
+  var form = new FormData();
+  FIELDS.forEach(function(field) {
+    form.append(field.name, field.value);
+  });
+
+  server.listen(common.port, function() {
+
+    form.submit('http://localhost:' + common.port + '/', function(err, res) {
+
+      if (err) {
+        throw err;
+      }
+
+      assert.strictEqual(res.statusCode, 200);
+      server.close();
+    });
+
+  });
+
+}).end();
+
+server = http.createServer(function(req, res) {
+
+  var form = new IncomingForm({uploadDir: common.dir.tmp});
+
+  form.parse(req);
+
+  form
+    .on('field', function(name, value) {
+      var field = FIELDS.shift();
+      assert.strictEqual(name, field.name);
+      assert.strictEqual(value, field.value+'');
+    })
+    .on('file', function(name, file) {
+      var field = FIELDS.shift();
+      assert.strictEqual(name, field.name);
+      // http response doesn't have path property
+      assert.strictEqual(file.name, path.basename(field.value.path || remoteFile));
+      assert.strictEqual(file.type, mime.lookup(file.name));
+    })
+    .on('end', function() {
+      res.writeHead(200);
+      res.end('done');
+    });
+});
+
+
+process.on('exit', function() {
+  assert.strictEqual(FIELDS.length, 0);
+});
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-pipe.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-pipe.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-pipe.js	(revision 484)
@@ -0,0 +1,73 @@
+var common = require('../common');
+var assert = common.assert;
+var http = require('http');
+var path = require('path');
+var mime = require('mime');
+var request = require('request');
+var fs = require('fs');
+var FormData = require(common.dir.lib + '/form_data');
+var IncomingForm = require('formidable').IncomingForm;
+
+var remoteFile = 'http://nodejs.org/images/logo.png';
+
+// wrap non simple values into function
+// just to deal with ReadStream "autostart"
+// Can't wait for 0.10
+var FIELDS = [
+  {name: 'my_field', value: 'my_value'},
+  {name: 'my_buffer', value: function(){ return new Buffer([1, 2, 3])} },
+  {name: 'my_file', value: function(){ return fs.createReadStream(common.dir.fixture + '/unicycle.jpg')} },
+  {name: 'remote_file', value: function(){ return request(remoteFile)} }
+];
+
+var server = http.createServer(function(req, res) {
+
+  var form = new IncomingForm({uploadDir: common.dir.tmp});
+
+  form.parse(req);
+
+  form
+    .on('field', function(name, value) {
+      var field = FIELDS.shift();
+      assert.strictEqual(name, field.name);
+      assert.strictEqual(value, field.value+'');
+    })
+    .on('file', function(name, file) {
+      var field = FIELDS.shift();
+      assert.strictEqual(name, field.name);
+      assert.strictEqual(file.name, path.basename(field.value.path));
+      assert.strictEqual(file.type, mime.lookup(file.name));
+    })
+    .on('end', function() {
+      res.writeHead(200);
+      res.end('done');
+    });
+});
+
+server.listen(common.port, function() {
+  var form = new FormData();
+  FIELDS.forEach(function(field) {
+    // important to append ReadStreams within the same tick
+    if ((typeof field.value == 'function')) {
+      field.value = field.value();
+    }
+    form.append(field.name, field.value);
+  });
+
+  var request = http.request({
+    method: 'post',
+    port: common.port,
+    path: '/upload',
+    headers: form.getHeaders()
+  });
+
+  form.pipe(request);
+
+  request.on('response', function(res) {
+    server.close();
+  });
+});
+
+process.on('exit', function() {
+  assert.strictEqual(FIELDS.length, 0);
+});
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-submit-custom.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-submit-custom.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-submit-custom.js	(revision 484)
@@ -0,0 +1,77 @@
+var common = require('../common');
+var assert = common.assert;
+var http = require('http');
+var path = require('path');
+var mime = require('mime');
+var request = require('request');
+var fs = require('fs');
+var FormData = require(common.dir.lib + '/form_data');
+var IncomingForm = require('formidable').IncomingForm;
+
+var remoteFile = 'http://nodejs.org/images/logo.png';
+
+// wrap non simple values into function
+// just to deal with ReadStream "autostart"
+// Can't wait for 0.10
+var FIELDS = [
+  {name: 'my_field', value: 'my_value'},
+  {name: 'my_buffer', value: function(){ return new Buffer([1, 2, 3])} },
+  {name: 'my_file', value: function(){ return fs.createReadStream(common.dir.fixture + '/unicycle.jpg')} },
+  {name: 'remote_file', value: function(){ return request(remoteFile)} }
+];
+
+var server = http.createServer(function(req, res) {
+
+  var form = new IncomingForm({uploadDir: common.dir.tmp});
+
+  form.parse(req);
+
+  form
+    .on('field', function(name, value) {
+      var field = FIELDS.shift();
+      assert.strictEqual(name, field.name);
+      assert.strictEqual(value, field.value+'');
+    })
+    .on('file', function(name, file) {
+      var field = FIELDS.shift();
+      assert.strictEqual(name, field.name);
+      assert.strictEqual(file.name, path.basename(field.value.path));
+      assert.strictEqual(file.type, mime.lookup(file.name));
+    })
+    .on('end', function() {
+      res.writeHead(200);
+      res.end('done');
+    });
+});
+
+server.listen(common.port, function() {
+
+  var form = new FormData();
+
+  FIELDS.forEach(function(field) {
+    // important to append ReadStreams within the same tick
+    if ((typeof field.value == 'function')) {
+      field.value = field.value();
+    }
+    form.append(field.name, field.value);
+  });
+
+  // custom params object passed to submit
+  form.submit({
+    port: common.port,
+    path: '/'
+  }, function(err, res) {
+
+    if (err) {
+      throw err;
+    }
+
+    assert.strictEqual(res.statusCode, 200);
+    server.close();
+  });
+
+});
+
+process.on('exit', function() {
+  assert.strictEqual(FIELDS.length, 0);
+});
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-submit.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-submit.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/integration/test-submit.js	(revision 484)
@@ -0,0 +1,73 @@
+var common = require('../common');
+var assert = common.assert;
+var http = require('http');
+var path = require('path');
+var mime = require('mime');
+var request = require('request');
+var fs = require('fs');
+var FormData = require(common.dir.lib + '/form_data');
+var IncomingForm = require('formidable').IncomingForm;
+
+var remoteFile = 'http://nodejs.org/images/logo.png';
+
+// wrap non simple values into function
+// just to deal with ReadStream "autostart"
+// Can't wait for 0.10
+var FIELDS = [
+  {name: 'my_field', value: 'my_value'},
+  {name: 'my_buffer', value: function(){ return new Buffer([1, 2, 3])} },
+  {name: 'my_file', value: function(){ return fs.createReadStream(common.dir.fixture + '/unicycle.jpg')} },
+  {name: 'remote_file', value: function(){ return request(remoteFile)} }
+];
+
+var server = http.createServer(function(req, res) {
+
+  var form = new IncomingForm({uploadDir: common.dir.tmp});
+
+  form.parse(req);
+
+  form
+    .on('field', function(name, value) {
+      var field = FIELDS.shift();
+      assert.strictEqual(name, field.name);
+      assert.strictEqual(value, field.value+'');
+    })
+    .on('file', function(name, file) {
+      var field = FIELDS.shift();
+      assert.strictEqual(name, field.name);
+      assert.strictEqual(file.name, path.basename(field.value.path));
+      assert.strictEqual(file.type, mime.lookup(file.name));
+    })
+    .on('end', function() {
+      res.writeHead(200);
+      res.end('done');
+    });
+});
+
+server.listen(common.port, function() {
+
+  var form = new FormData();
+
+  FIELDS.forEach(function(field) {
+    // important to append ReadStreams within the same tick
+    if ((typeof field.value == 'function')) {
+      field.value = field.value();
+    }
+    form.append(field.name, field.value);
+  });
+
+  form.submit('http://localhost:' + common.port + '/', function(err, res) {
+
+    if (err) {
+      throw err;
+    }
+
+    assert.strictEqual(res.statusCode, 200);
+    server.close();
+  });
+
+});
+
+process.on('exit', function() {
+  assert.strictEqual(FIELDS.length, 0);
+});
Index: Dev/trunk/src/node_modules/request/node_modules/form-data/test/run.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/form-data/test/run.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/form-data/test/run.js	(revision 484)
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+var far = require('far').create();
+
+far.add(__dirname);
+far.include(/test-.*\.js$/);
+
+far.execute();
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/.npmignore	(revision 484)
@@ -0,0 +1,18 @@
+.idea
+*.iml
+npm-debug.log
+dump.rdb
+node_modules
+results.tap
+results.xml
+npm-shrinkwrap.json
+config.json
+.DS_Store
+*/.DS_Store
+*/*/.DS_Store
+._*
+*/._*
+*/*/._*
+coverage.*
+lib-cov
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+
+node_js:
+  - 0.10
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/LICENSE	(revision 484)
@@ -0,0 +1,24 @@
+Copyright (c) 2012-2013, Eran Hammer.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Eran Hammer nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ERAN HAMMER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/Makefile	(revision 484)
@@ -0,0 +1,11 @@
+test:
+	@./node_modules/.bin/lab
+test-cov: 
+	@./node_modules/.bin/lab -r threshold -t 100
+test-cov-html:
+	@./node_modules/.bin/lab -r html -o coverage.html
+complexity:
+	@./node_modules/.bin/cr -o complexity.md -f markdown lib
+
+.PHONY: test test-cov test-cov-html complexity
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/README.md	(revision 484)
@@ -0,0 +1,620 @@
+![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png)
+
+<img align="right" src="https://raw.github.com/hueniverse/hawk/master/images/logo.png" /> **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial
+HTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz).
+
+Current version: **0.13**
+
+[![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk)
+
+# Table of Content
+
+- [**Introduction**](#introduction)
+  - [Replay Protection](#replay-protection)
+  - [Usage Example](#usage-example)
+  - [Protocol Example](#protocol-example)
+    - [Payload Validation](#payload-validation)
+    - [Response Payload Validation](#response-payload-validation)
+  - [Browser Support and Considerations](#browser-support-and-considerations)
+<p></p>
+- [**Single URI Authorization**](#single-uri-authorization)
+  - [Usage Example](#bewit-usage-example)
+<p></p>
+- [**Security Considerations**](#security-considerations)
+  - [MAC Keys Transmission](#mac-keys-transmission)
+  - [Confidentiality of Requests](#confidentiality-of-requests)
+  - [Spoofing by Counterfeit Servers](#spoofing-by-counterfeit-servers)
+  - [Plaintext Storage of Credentials](#plaintext-storage-of-credentials)
+  - [Entropy of Keys](#entropy-of-keys)
+  - [Coverage Limitations](#coverage-limitations)
+  - [Future Time Manipulation](#future-time-manipulation)
+  - [Client Clock Poisoning](#client-clock-poisoning)
+  - [Bewit Limitations](#bewit-limitations)
+<p></p>
+- [**Frequently Asked Questions**](#frequently-asked-questions)
+<p></p>
+- [**Acknowledgements**](#acknowledgements)
+
+# Introduction
+
+**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with
+partial cryptographic verification of the request and response, covering the HTTP method, request URI, host,
+and optionally the request payload.
+
+Similar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of
+client credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme,
+the key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is
+included in its place.
+
+However, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of
+replay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less
+"chattiness" (interaction with the server).
+
+Also unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because
+the client and server must both have access to the key material in the clear.
+
+The primary design goals of this scheme are to:
+* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources,
+* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where
+  to send an authenticated request), and
+* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client
+  failure to validate the server's identity as part of its TLS handshake.
+
+In addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using
+a query parameter called _bewit_ (in falconry, a leather strap used to attach a tracking device to the leg of a hawk).
+
+The **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server,
+which is beyond the scope of this module. Typically, the shared credentials are established via an initial
+TLS-protected phase or derived from some other shared confidential information available to both the client
+and the server.
+
+
+## Replay Protection
+
+Without replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more 
+than once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when 
+making requests. This gives the server enough information to prevent replay attacks.
+
+The nonce is generated by the client, and is a string unique across all requests with the same timestamp and
+key identifier combination. 
+
+The timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards
+are rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks.
+By default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in
+practice translates to a maximum of 2 minutes as the skew can be positive or negative).
+
+Using a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client
+clock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types
+(e.g. browsers) to deploy NTP, the server provides the client with its current time (in seconds precision) in response
+to a bad timestamp.
+
+There is no expectation that the client will adjust its system clock to match the server (in fact, this would be a
+potential attack vector). Instead, the client only uses the server's time to calculate an offset used only
+for communications with that particular server. The protocol rewards clients with synchronized clocks by reducing
+the number of round trips required to authenticate the first request.
+
+
+## Usage Example
+
+Server code:
+
+```javascript
+var Http = require('http');
+var Hawk = require('hawk');
+
+
+// Credentials lookup function
+
+var credentialsFunc = function (id, callback) {
+
+    var credentials = {
+        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+        algorithm: 'sha256',
+        user: 'Steve'
+    };
+
+    return callback(null, credentials);
+};
+
+// Create HTTP server
+
+var handler = function (req, res) {
+
+    // Authenticate incoming request
+
+    Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+        // Prepare response
+
+        var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');
+        var headers = { 'Content-Type': 'text/plain' };
+
+        // Generate Server-Authorization response header
+
+        var header = Hawk.server.header(credentials, artifacts, { payload: payload, contentType: headers['Content-Type'] });
+        headers['Server-Authorization'] = header;
+
+        // Send the response back
+
+        res.writeHead(!err ? 200 : 401, headers);
+        res.end(payload);
+    });
+};
+
+// Start server
+
+Http.createServer(handler).listen(8000, 'example.com');
+```
+
+Client code:
+
+```javascript
+var Request = require('request');
+var Hawk = require('hawk');
+
+
+// Client credentials
+
+var credentials = {
+    id: 'dh37fgj492je',
+    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+    algorithm: 'sha256'
+}
+
+// Request options
+
+var requestOptions = {
+    uri: 'http://example.com:8000/resource/1?b=1&a=2',
+    method: 'GET',
+    headers: {}
+};
+
+// Generate Authorization request header
+
+var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });
+requestOptions.headers.Authorization = header.field;
+
+// Send authenticated request
+
+Request(requestOptions, function (error, response, body) {
+
+    // Authenticate the server's response
+
+    var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });
+
+    // Output results
+
+    console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
+});
+```
+
+**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local
+machine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method.
+
+```javascript
+Hawk.sntp.start();
+```
+
+
+## Protocol Example
+
+The client attempts to access a protected resource without authentication, sending the following HTTP request to
+the resource server:
+
+```
+GET /resource/1?b=1&a=2 HTTP/1.1
+Host: example.com:8000
+```
+
+The resource server returns an authentication challenge.
+
+```
+HTTP/1.1 401 Unauthorized
+WWW-Authenticate: Hawk
+```
+
+The client has previously obtained a set of **Hawk** credentials for accessing resources on the "http://example.com/"
+server. The **Hawk** credentials issued to the client include the following attributes:
+
+* Key identifier: dh37fgj492je
+* Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn
+* Algorithm: sha256
+
+The client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1,
+1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline
+character):
+
+```
+hawk.1.header
+1353832234
+j4h3g2
+GET
+/resource?a=1&b=2
+example.com
+8000
+
+some-app-ext-data
+
+```
+
+The request MAC is calculated using HMAC with the specified hash algorithm "sha256" and the key over the normalized request string.
+The result is base64-encoded to produce the request MAC:
+
+```
+6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=
+```
+
+The client includes the **Hawk** key identifier, timestamp, nonce, application specific data, and request MAC with the request using
+the HTTP `Authorization` request header field:
+
+```
+GET /resource/1?b=1&a=2 HTTP/1.1
+Host: example.com:8000
+Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="
+```
+
+The server validates the request by calculating the request MAC again based on the request received and verifies the validity
+and scope of the **Hawk** credentials. If valid, the server responds with the requested resource.
+
+
+### Payload Validation
+
+**Hawk** provides optional payload validation. When generating the authentication header, the client calculates a payload hash
+using the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character):
+* `hawk.1.payload`
+* the content-type in lowercase, without any parameters (e.g. `application/json`)
+* the request payload prior to any content encoding (the exact representation requirements should be specified by the server for payloads other than simple single-part ascii to ensure interoperability)
+
+For example:
+
+* Payload: `Thank you for flying Hawk`
+* Content Type: `text/plain`
+* Hash (sha256): `Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=`
+
+Results in the following input to the payload hash function (newline terminated values):
+
+```
+hawk.1.payload
+text/plain
+Thank you for flying Hawk
+
+```
+
+Which produces the following hash value:
+
+```
+Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=
+```
+
+The client constructs the normalized request string (newline terminated values):
+
+```
+hawk.1.header
+1353832234
+j4h3g2
+POST
+/resource?a=1&b=2
+example.com
+8000
+Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=
+some-app-ext-data
+
+```
+
+Then calculates the request MAC and includes the **Hawk** key identifier, timestamp, nonce, payload hash, application specific data,
+and request MAC, with the request using the HTTP `Authorization` request header field:
+
+```
+POST /resource/1 HTTP/1.1
+Host: example.com:8000
+Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="
+```
+
+It is up to the server if and when it validates the payload for any given request, based solely on it's security policy
+and the nature of the data included.
+
+If the payload is available at the time of authentication, the server uses the hash value provided by the client to construct
+the normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value
+with the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash.
+
+However, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed
+at a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value
+provided by the client after validating the MAC.
+
+It is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value
+included in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided
+by the client, the payload may be modified by an attacker.
+
+
+## Response Payload Validation
+
+**Hawk** provides partial response payload validation. The server includes the `Server-Authorization` response header which enables the
+client to authenticate the response and ensure it is talking to the right server. **Hawk** defines the HTTP `Server-Authorization` header
+as a response header using the exact same syntax as the `Authorization` request header field.
+
+The header is contructed using the same process as the client's request header. The server uses the same credentials and other
+artifacts provided by the client to constructs the normalized request string. The `ext` and `hash` values are replaced with
+new values based on the server response. The rest as identical to those used by the client.
+
+The result MAC digest is included with the optional `hash` and `ext` values:
+
+```
+Server-Authorization: Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"
+```
+
+
+## Browser Support and Considerations
+
+A browser script is provided for including using a `<script>` tag in [lib/browser.js](/lib/browser.js).
+
+**Hawk** relies on the _Server-Authorization_ and _WWW-Authenticate_ headers in its response to communicate with the client.
+Therefore, in case of CORS requests, it is important to consider sending _Access-Control-Expose-Headers_ with the value
+_"WWW-Authenticate, Server-Authorization"_ on each response from your server. As explained in the
+[specifications](http://www.w3.org/TR/cors/#access-control-expose-headers-response-header), it will indicate that these headers
+can safely be accessed by the client (using getResponseHeader() on the XmlHttpRequest object). Otherwise you will be met with a
+["simple response header"](http://www.w3.org/TR/cors/#simple-response-header) which excludes these fields and would prevent the
+Hawk client from authenticating the requests.You can read more about the why and how in this
+[article](http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server)
+
+
+# Single URI Authorization
+
+There are cases in which limited and short-term access to a protected resource is granted to a third party which does not
+have access to the shared credentials. For example, displaying a protected image on a web page accessed by anyone. **Hawk**
+provides limited support for such URIs in the form of a _bewit_ - a URI query parameter appended to the request URI which contains
+the necessary credentials to authenticate the request.
+
+Because of the significant security risks involved in issuing such access, bewit usage is purposely limited only to GET requests
+and for a finite period of time. Both the client and server can issue bewit credentials, however, the server should not use the same
+credentials as the client to maintain clear traceability as to who issued which credentials.
+
+In order to simplify implementation, bewit credentials do not support single-use policy and can be replayed multiple times within
+the granted access timeframe. 
+
+
+## Bewit Usage Example
+
+Server code:
+
+```javascript
+var Http = require('http');
+var Hawk = require('hawk');
+
+
+// Credentials lookup function
+
+var credentialsFunc = function (id, callback) {
+
+    var credentials = {
+        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+        algorithm: 'sha256'
+    };
+
+    return callback(null, credentials);
+};
+
+// Create HTTP server
+
+var handler = function (req, res) {
+
+    Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+        res.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' });
+        res.end(!err ? 'Access granted' : 'Shoosh!');
+    });
+};
+
+Http.createServer(handler).listen(8000, 'example.com');
+```
+
+Bewit code generation:
+
+```javascript
+var Request = require('request');
+var Hawk = require('hawk');
+
+
+// Client credentials
+
+var credentials = {
+    id: 'dh37fgj492je',
+    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+    algorithm: 'sha256'
+}
+
+// Generate bewit
+
+var duration = 60 * 5;      // 5 Minutes
+var bewit = Hawk.uri.getBewit('http://example.com:8080/resource/1?b=1&a=2', { credentials: credentials, ttlSec: duration, ext: 'some-app-data' });
+var uri = 'http://example.com:8000/resource/1?b=1&a=2' + '&bewit=' + bewit;
+```
+
+
+# Security Considerations
+
+The greatest sources of security risks are usually found not in **Hawk** but in the policies and procedures surrounding its use.
+Implementers are strongly encouraged to assess how this module addresses their security requirements. This section includes
+an incomplete list of security considerations that must be reviewed and understood before deploying **Hawk** on the server.
+Many of the protections provided in **Hawk** depends on whether and how they are used.
+
+### MAC Keys Transmission
+
+**Hawk** does not provide any mechanism for obtaining or transmitting the set of shared credentials required. Any mechanism used
+to obtain **Hawk** credentials must ensure that these transmissions are protected using transport-layer mechanisms such as TLS.
+
+### Confidentiality of Requests
+
+While **Hawk** provides a mechanism for verifying the integrity of HTTP requests, it provides no guarantee of request
+confidentiality. Unless other precautions are taken, eavesdroppers will have full access to the request content. Servers should
+carefully consider the types of data likely to be sent as part of such requests, and employ transport-layer security mechanisms
+to protect sensitive resources.
+
+### Spoofing by Counterfeit Servers
+
+**Hawk** provides limited verification of the server authenticity. When receiving a response back from the server, the server
+may choose to include a response `Server-Authorization` header which the client can use to verify the response. However, it is up to
+the server to determine when such measure is included, to up to the client to enforce that policy.
+
+A hostile party could take advantage of this by intercepting the client's requests and returning misleading or otherwise
+incorrect responses. Service providers should consider such attacks when developing services using this protocol, and should
+require transport-layer security for any requests where the authenticity of the resource server or of server responses is an issue.
+
+### Plaintext Storage of Credentials
+
+The **Hawk** key functions the same way passwords do in traditional authentication systems. In order to compute the request MAC,
+the server must have access to the key in plaintext form. This is in contrast, for example, to modern operating systems, which
+store only a one-way hash of user credentials.
+
+If an attacker were to gain access to these keys - or worse, to the server's database of all such keys - he or she would be able
+to perform any action on behalf of any resource owner. Accordingly, it is critical that servers protect these keys from unauthorized
+access.
+
+### Entropy of Keys
+
+Unless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and request
+MAC values, and will thus be able to mount offline brute-force attacks to recover the key used. Servers should be careful to
+assign keys which are long enough, and random enough, to resist such attacks for at least the length of time that the **Hawk**
+credentials are valid.
+
+For example, if the credentials are valid for two weeks, servers should ensure that it is not possible to mount a brute force
+attack that recovers the key in less than two weeks. Of course, servers are urged to err on the side of caution, and use the
+longest key reasonable.
+
+It is equally important that the pseudo-random number generator (PRNG) used to generate these keys be of sufficiently high
+quality. Many PRNG implementations generate number sequences that may appear to be random, but which nevertheless exhibit
+patterns or other weaknesses which make cryptanalysis or brute force attacks easier. Implementers should be careful to use
+cryptographically secure PRNGs to avoid these problems.
+
+### Coverage Limitations
+
+The request MAC only covers the HTTP `Host` header and optionally the `Content-Type` header. It does not cover any other headers
+which can often affect how the request body is interpreted by the server. If the server behavior is influenced by the presence
+or value of such headers, an attacker can manipulate the request headers without being detected. Implementers should use the
+`ext` feature to pass application-specific information via the `Authorization` header which is protected by the request MAC.
+
+The response authentication, when performed, only covers the response payload, content-type, and the request information 
+provided by the client in it's request (method, resource, timestamp, nonce, etc.). It does not cover the HTTP status code or
+any other response header field (e.g. Location) which can affect the client's behaviour.
+
+### Future Time Manipulation
+
+The protocol relies on a clock sync between the client and server. To accomplish this, the server informs the client of its
+current time when an invalid timestamp is received.
+
+If an attacker is able to manipulate this information and cause the client to use an incorrect time, it would be able to cause
+the client to generate authenticated requests using time in the future. Such requests will fail when sent by the client, and will
+not likely leave a trace on the server (given the common implementation of nonce, if at all enforced). The attacker will then
+be able to replay the request at the correct time without detection.
+
+The client must only use the time information provided by the server if:
+* it was delivered over a TLS connection and the server identity has been verified, or
+* the `tsm` MAC digest calculated using the same client credentials over the timestamp has been verified.
+
+### Client Clock Poisoning
+
+When receiving a request with a bad timestamp, the server provides the client with its current time. The client must never use
+the time received from the server to adjust its own clock, and must only use it to calculate an offset for communicating with
+that particular server.
+
+### Bewit Limitations
+
+Special care must be taken when issuing bewit credentials to third parties. Bewit credentials are valid until expiration and cannot
+be revoked or limited without using other means. Whatever resource they grant access to will be completely exposed to anyone with
+access to the bewit credentials which act as bearer credentials for that particular resource. While bewit usage is limited to GET
+requests only and therefore cannot be used to perform transactions or change server state, it can still be used to expose private
+and sensitive information.
+
+
+# Frequently Asked Questions
+
+### Where is the protocol specification?
+
+If you are looking for some prose explaining how all this works, **this is it**. **Hawk** is being developed as an open source
+project instead of a standard. In other words, the [code](/hueniverse/hawk/tree/master/lib) is the specification. Not sure about
+something? Open an issue!
+
+### Is it done?
+
+At if version 0.10.0, **Hawk** is feature-complete. However, until this module reaches version 1.0.0 it is considered experimental
+and is likely to change. This also means your feedback and contribution are very welcome. Feel free to open issues with questions
+and suggestions.
+
+### Where can I find **Hawk** implementations in other languages?
+
+**Hawk**'s only reference implementation is provided in JavaScript as a node.js module. However, others are actively porting it to other
+platforms. There is already a [PHP](https://github.com/alexbilbie/PHP-Hawk),
+[.NET](https://github.com/pcibraro/hawknet), and [JAVA](https://github.com/wealdtech/hawk) libraries available. The full list
+is maintained [here](https://github.com/hueniverse/hawk/issues?labels=port). Please add an issue if you are working on another
+port. A cross-platform test-suite is in the works.
+
+### Why isn't the algorithm part of the challenge or dynamically negotiated?
+
+The algorithm used is closely related to the key issued as different algorithms require different key sizes (and other
+requirements). While some keys can be used for multiple algorithm, the protocol is designed to closely bind the key and algorithm
+together as part of the issued credentials.
+
+### Why is Host and Content-Type the only headers covered by the request MAC?
+
+It is really hard to include other headers. Headers can be changed by proxies and other intermediaries and there is no
+well-established way to normalize them. Many platforms change the case of header field names and values. The only
+straight-forward solution is to include the headers in some blob (say, base64 encoded JSON) and include that with the request,
+an approach taken by JWT and other such formats. However, that design violates the HTTP header boundaries, repeats information,
+and introduces other security issues because firewalls will not be aware of these "hidden" headers. In addition, any information
+repeated must be compared to the duplicated information in the header and therefore only moves the problem elsewhere.
+
+### Why not just use HTTP Digest?
+
+Digest requires pre-negotiation to establish a nonce. This means you can't just make a request - you must first send
+a protocol handshake to the server. This pattern has become unacceptable for most web services, especially mobile
+where extra round-trip are costly.
+
+### Why bother with all this nonce and timestamp business?
+
+**Hawk** is an attempt to find a reasonable, practical compromise between security and usability. OAuth 1.0 got timestamp
+and nonces halfway right but failed when it came to scalability and consistent developer experience. **Hawk** addresses
+it by requiring the client to sync its clock, but provides it with tools to accomplish it.
+
+In general, replay protection is a matter of application-specific threat model. It is less of an issue on a TLS-protected
+system where the clients are implemented using best practices and are under the control of the server. Instead of dropping
+replay protection, **Hawk** offers a required time window and an optional nonce verification. Together, it provides developers
+with the ability to decide how to enforce their security policy without impacting the client's implementation.
+
+### What are `app` and `dlg` in the authorization header and normalized mac string?
+
+The original motivation for **Hawk** was to replace the OAuth 1.0 use cases. This included both a simple client-server mode which
+this module is specifically designed for, and a delegated access mode which is being developed separately in
+[Oz](https://github.com/hueniverse/oz). In addition to the **Hawk** use cases, Oz requires another attribute: the application id `app`.
+This provides binding between the credentials and the application in a way that prevents an attacker from tricking an application
+to use credentials issued to someone else. It also has an optional 'delegated-by' attribute `dlg` which is the application id of the
+application the credentials were directly issued to. The goal of these two additions is to allow Oz to utilize **Hawk** directly,
+but with the additional security of delegated credentials.
+
+### What is the purpose of the static strings used in each normalized MAC input?
+
+When calculating a hash or MAC, a static prefix (tag) is added. The prefix is used to prevent MAC values from being
+used or reused for a purpose other than what they were created for (i.e. prevents switching MAC values between a request,
+response, and a bewit use cases). It also protects against expliots created after a potential change in how the protocol
+creates the normalized string. For example, if a future version would switch the order of nonce and timestamp, it
+can create an exploit opportunity for cases where the nonce is similar in format to a timestamp.
+
+### Does **Hawk** have anything to do with OAuth?
+
+Short answer: no.
+
+**Hawk** was originally proposed as the OAuth MAC Token specification. However, the OAuth working group in its consistent
+incompetence failed to produce a final, usable solution to address one of the most popular use cases of OAuth 1.0 - using it
+to authenticate simple client-server transactions (i.e. two-legged). As you can guess, the OAuth working group is still hard
+at work to produce more garbage.
+
+**Hawk** provides a simple HTTP authentication scheme for making client-server requests. It does not address the OAuth use case
+of delegating access to a third party. If you are looking for an OAuth alternative, check out [Oz](https://github.com/hueniverse/oz).
+
+
+# Acknowledgements
+
+**Hawk** is a derivative work of the [HTTP MAC Authentication Scheme](http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05) proposal
+co-authored by Ben Adida, Adam Barth, and Eran Hammer, which in turn was based on the OAuth 1.0 community specification.
+
+Special thanks to Ben Laurie for his always insightful feedback and advice.
+
+The **Hawk** logo was created by [Chris Carrasco](http://chriscarrasco.com).
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/example/usage.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/example/usage.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/example/usage.js	(revision 484)
@@ -0,0 +1,78 @@
+// Load modules
+
+var Http = require('http');
+var Request = require('request');
+var Hawk = require('../lib');
+
+
+// Declare internals
+
+var internals = {
+    credentials: {
+        dh37fgj492je: {
+            id: 'dh37fgj492je',                                             // Required by Hawk.client.header 
+            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+            algorithm: 'sha256',
+            user: 'Steve'
+        }
+    }
+};
+
+
+// Credentials lookup function
+
+var credentialsFunc = function (id, callback) {
+
+    return callback(null, internals.credentials[id]);
+};
+
+
+// Create HTTP server
+
+var handler = function (req, res) {
+
+    Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+        var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');
+        var headers = {
+            'Content-Type': 'text/plain',
+            'Server-Authorization': Hawk.server.header(credentials, artifacts, { payload: payload, contentType: 'text/plain' })
+        };
+
+        res.writeHead(!err ? 200 : 401, headers);
+        res.end(payload);
+    });
+};
+
+Http.createServer(handler).listen(8000, '127.0.0.1');
+
+
+// Send unauthenticated request
+
+Request('http://127.0.0.1:8000/resource/1?b=1&a=2', function (error, response, body) {
+
+    console.log(response.statusCode + ': ' + body);
+});
+
+
+// Send authenticated request
+
+credentialsFunc('dh37fgj492je', function (err, credentials) {
+
+    var header = Hawk.client.header('http://127.0.0.1:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'and welcome!' });
+    var options = {
+        uri: 'http://127.0.0.1:8000/resource/1?b=1&a=2',
+        method: 'GET',
+        headers: {
+            authorization: header.field
+        }
+    };
+
+    Request(options, function (error, response, body) {
+
+        var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });
+        console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
+        process.exit(0);
+    });
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/index.js	(revision 484)
@@ -0,0 +1,1 @@
+module.exports = require('./lib');
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/lib/browser.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/lib/browser.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/lib/browser.js	(revision 484)
@@ -0,0 +1,430 @@
+/*
+    HTTP Hawk Authentication Scheme
+    Copyright (c) 2012-2013, Eran Hammer <eran@hueniverse.com>
+    MIT Licensed
+*/
+
+
+// Declare namespace
+
+var hawk = {};
+
+
+// Export if used as a module
+
+if (typeof module !== "undefined" && module.exports) {
+    module.exports = hawk;
+}
+
+// Generate an Authorization header for a given request
+
+/*
+    uri: 'http://example.com/resource?a=b'
+    method: HTTP verb (e.g. 'GET', 'POST')
+    options: {
+
+        // Required
+
+        credentials: {
+            id: 'dh37fgj492je',
+            key: 'aoijedoaijsdlaksjdl',
+            algorithm: 'sha256'                                 // 'sha1', 'sha256'
+        },
+
+        // Optional
+
+        ext: 'application-specific',                        // Application specific data sent via the ext attribute
+        timestamp: Date.now() / 1000,                       // A pre-calculated timestamp in seconds
+        nonce: '2334f34f',                                  // A pre-generated nonce
+        localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
+        payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
+        contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
+        hash: 'U4MKKSmiVxk37JCCrAVIjV=',                    // Pre-calculated payload hash
+        app: '24s23423f34dx',                               // Oz application id
+        dlg: '234sz34tww3sd'                                // Oz delegated-by application id
+    }
+*/
+
+hawk.client = {
+
+    header: function (uri, method, options) {
+
+        var result = {
+            field: '',
+            artifacts: {}
+        };
+
+        // Validate inputs
+
+        if (!uri || (typeof uri !== 'string' && typeof uri !== 'object') ||
+            !method || typeof method !== 'string' ||
+            !options || typeof options !== 'object') {
+
+            return result;
+        }
+
+        // Application time
+
+        var timestamp = options.timestamp || Math.floor((hawk.utils.now() + (options.localtimeOffsetMsec || 0)) / 1000)
+
+        // Validate credentials
+
+        var credentials = options.credentials;
+        if (!credentials ||
+            !credentials.id ||
+            !credentials.key ||
+            !credentials.algorithm) {
+
+            // Invalid credential object
+            return result;
+        }
+
+        if (hawk.crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+            return result;
+        }
+
+        // Parse URI
+
+        if (typeof uri === 'string') {
+            uri = hawk.utils.parseUri(uri);
+        }
+
+        // Calculate signature
+
+        var artifacts = {
+            ts: timestamp,
+            nonce: options.nonce || hawk.utils.randomString(6),
+            method: method,
+            resource: uri.relative,
+            host: uri.hostname,
+            port: uri.port,
+            hash: options.hash,
+            ext: options.ext,
+            app: options.app,
+            dlg: options.dlg
+        };
+
+        result.artifacts = artifacts;
+
+        // Calculate payload hash
+
+        if (!artifacts.hash &&
+            options.hasOwnProperty('payload')) {
+
+            artifacts.hash = hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
+        }
+
+        var mac = hawk.crypto.calculateMac('header', credentials, artifacts);
+
+        // Construct header
+
+        var hasExt = artifacts.ext !== null && artifacts.ext !== undefined && artifacts.ext !== '';       // Other falsey values allowed
+        var header = 'Hawk id="' + credentials.id +
+                     '", ts="' + artifacts.ts +
+                     '", nonce="' + artifacts.nonce +
+                     (artifacts.hash ? '", hash="' + artifacts.hash : '') +
+                     (hasExt ? '", ext="' + hawk.utils.escapeHeaderAttribute(artifacts.ext) : '') +
+                     '", mac="' + mac + '"';
+
+        if (artifacts.app) {
+            header += ', app="' + artifacts.app +
+                      (artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"';
+        }
+
+        result.field = header;
+
+        return result;
+    },
+
+
+    // Validate server response
+
+    /*
+        request:    object created via 'new XMLHttpRequest()' after response received
+        artifacts:  object recieved from header().artifacts
+        options: {
+            payload:    optional payload received
+            required:   specifies if a Server-Authorization header is required. Defaults to 'false'
+        }
+    */
+
+    authenticate: function (request, credentials, artifacts, options) {
+
+        options = options || {};
+
+        if (request.getResponseHeader('www-authenticate')) {
+
+            // Parse HTTP WWW-Authenticate header
+
+            var attributes = hawk.utils.parseAuthorizationHeader(request.getResponseHeader('www-authenticate'), ['ts', 'tsm', 'error']);
+            if (!attributes) {
+                return false;
+            }
+
+            if (attributes.ts) {
+                var tsm = hawk.crypto.calculateTsMac(attributes.ts, credentials);
+                if (tsm !== attributes.tsm) {
+                    return false;
+                }
+
+                hawk.utils.setNtpOffset(attributes.ts - Math.floor(Date.now() / 1000));     // Keep offset at 1 second precision
+            }
+        }
+
+        // Parse HTTP Server-Authorization header
+
+        if (!request.getResponseHeader('server-authorization') &&
+            !options.required) {
+
+            return true;
+        }
+
+        var attributes = hawk.utils.parseAuthorizationHeader(request.getResponseHeader('server-authorization'), ['mac', 'ext', 'hash']);
+        if (!attributes) {
+            return false;
+        }
+
+        var modArtifacts = {
+            ts: artifacts.ts,
+            nonce: artifacts.nonce,
+            method: artifacts.method,
+            resource: artifacts.resource,
+            host: artifacts.host,
+            port: artifacts.port,
+            hash: attributes.hash,
+            ext: attributes.ext,
+            app: artifacts.app,
+            dlg: artifacts.dlg
+        };
+
+        var mac = hawk.crypto.calculateMac('response', credentials, modArtifacts);
+        if (mac !== attributes.mac) {
+            return false;
+        }
+
+        if (!options.hasOwnProperty('payload')) {
+            return true;
+        }
+
+        if (!attributes.hash) {
+            return false;
+        }
+
+        var calculatedHash = hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, request.getResponseHeader('content-type'));
+        return (calculatedHash === attributes.hash);
+    }
+};
+
+
+hawk.crypto = {
+
+    headerVersion: '1',
+
+    algorithms: ['sha1', 'sha256'],
+
+    calculateMac: function (type, credentials, options) {
+
+        var normalized = hawk.crypto.generateNormalizedString(type, options);
+
+        var hmac = CryptoJS['Hmac' + credentials.algorithm.toUpperCase()](normalized, credentials.key);
+        return hmac.toString(CryptoJS.enc.Base64);
+    },
+
+    generateNormalizedString: function (type, options) {
+
+        var normalized = 'hawk.' + hawk.crypto.headerVersion + '.' + type + '\n' +
+                         options.ts + '\n' +
+                         options.nonce + '\n' +
+                         options.method.toUpperCase() + '\n' +
+                         options.resource + '\n' +
+                         options.host.toLowerCase() + '\n' +
+                         options.port + '\n' +
+                         (options.hash || '') + '\n';
+
+        if (options.ext) {
+            normalized += options.ext.replace('\\', '\\\\').replace('\n', '\\n');
+        }
+
+        normalized += '\n';
+
+        if (options.app) {
+            normalized += options.app + '\n' +
+                          (options.dlg || '') + '\n';
+        }
+
+        return normalized;
+    },
+
+    calculatePayloadHash: function (payload, algorithm, contentType) {
+
+        var hash = CryptoJS.algo[algorithm.toUpperCase()].create();
+        hash.update('hawk.' + hawk.crypto.headerVersion + '.payload\n');
+        hash.update(hawk.utils.parseContentType(contentType) + '\n');
+        hash.update(payload || '');
+        hash.update('\n');
+        return hash.finalize().toString(CryptoJS.enc.Base64);
+    },
+
+    calculateTsMac: function (ts, credentials) {
+
+        var hash = CryptoJS['Hmac' + credentials.algorithm.toUpperCase()]('hawk.' + hawk.crypto.headerVersion + '.ts\n' + ts + '\n', credentials.key);
+        return hash.toString(CryptoJS.enc.Base64);
+    }
+};
+
+
+hawk.utils = {
+
+    storage: {                                      // localStorage compatible interface
+        _cache: {},
+        setItem: function (key, value) {
+
+            hawk.utils.storage._cache[key] = value;
+        },
+        getItem: function (key) {
+
+            return hawk.utils.storage._cache[key];
+        }
+    },
+
+    setStorage: function (storage) {
+
+        var ntpOffset = hawk.utils.getNtpOffset() || 0;
+        hawk.utils.storage = storage;
+        hawk.utils.setNtpOffset(ntpOffset);
+    },
+
+    setNtpOffset: function (offset) {
+
+        hawk.utils.storage.setItem('hawk_ntp_offset', offset);
+    },
+
+    getNtpOffset: function () {
+
+        return parseInt(hawk.utils.storage.getItem('hawk_ntp_offset') || '0', 10);
+    },
+
+    now: function () {
+
+        return Date.now() + hawk.utils.getNtpOffset();
+    },
+
+    escapeHeaderAttribute: function (attribute) {
+
+        return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"');
+    },
+
+    parseContentType: function (header) {
+
+        if (!header) {
+            return '';
+        }
+
+        return header.split(';')[0].trim().toLowerCase();
+    },
+
+    parseAuthorizationHeader: function (header, keys) {
+
+        if (!header) {
+            return null;
+        }
+
+        var headerParts = header.match(/^(\w+)(?:\s+(.*))?$/);       // Header: scheme[ something]
+        if (!headerParts) {
+            return null;
+        }
+
+        var scheme = headerParts[1];
+        if (scheme.toLowerCase() !== 'hawk') {
+            return null;
+        }
+
+        var attributesString = headerParts[2];
+        if (!attributesString) {
+            return null;
+        }
+
+        var attributes = {};
+        var verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, function ($0, $1, $2) {
+
+            // Check valid attribute names
+
+            if (keys.indexOf($1) === -1) {
+                return;
+            }
+
+            // Allowed attribute value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
+
+            if ($2.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/) === null) {
+                return;
+            }
+
+            // Check for duplicates
+
+            if (attributes.hasOwnProperty($1)) {
+                return;
+            }
+
+            attributes[$1] = $2;
+            return '';
+        });
+
+        if (verify !== '') {
+            return null;
+        }
+
+        return attributes;
+    },
+
+    randomString: function (size) {
+
+        var randomSource = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+        var len = randomSource.length;
+
+        var result = [];
+        for (var i = 0; i < size; ++i) {
+            result[i] = randomSource[Math.floor(Math.random() * len)];
+        }
+
+        return result.join('');
+    },
+
+    parseUri: function (input) {
+
+        // Based on: parseURI 1.2.2
+        // http://blog.stevenlevithan.com/archives/parseuri
+        // (c) Steven Levithan <stevenlevithan.com>
+        // MIT License
+
+        var keys = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'hostname', 'port', 'resource', 'relative', 'pathname', 'directory', 'file', 'query', 'fragment'];
+
+        var uriRegex = /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?(((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?)(?:#(.*))?)/;
+        var uriByNumber = uriRegex.exec(input);
+        var uri = {};
+
+        var i = 15;
+        while (i--) {
+            uri[keys[i]] = uriByNumber[i] || '';
+        }
+
+        if (uri.port === null ||
+            uri.port === '') {
+
+            uri.port = (uri.protocol.toLowerCase() === 'http' ? '80' : (uri.protocol.toLowerCase() === 'https' ? '443' : ''));
+        }
+
+        return uri;
+    }
+};
+
+
+// Based on: Crypto-JS v3.1.2
+// Copyright (c) 2009-2013, Jeff Mott. All rights reserved.
+// http://code.google.com/p/crypto-js/
+// http://code.google.com/p/crypto-js/wiki/License
+
+var CryptoJS=CryptoJS||function(h,r){var k={},l=k.lib={},n=function(){},f=l.Base={extend:function(a){n.prototype=this;var b=new n;a&&b.mixIn(a);b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)});b.init.prototype=b;b.$super=this;return b},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},j=l.WordArray=f.extend({init:function(a,b){a=this.words=a||[];this.sigBytes=b!=r?b:4*a.length},toString:function(a){return(a||s).stringify(this)},concat:function(a){var b=this.words,d=a.words,c=this.sigBytes;a=a.sigBytes;this.clamp();if(c%4)for(var e=0;e<a;e++)b[c+e>>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((c+e)%4);else if(65535<d.length)for(e=0;e<a;e+=4)b[c+e>>>2]=d[e>>>2];else b.push.apply(b,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,b=this.sigBytes;a[b>>>2]&=4294967295<<32-8*(b%4);a.length=h.ceil(b/4)},clone:function(){var a=f.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var b=[],d=0;d<a;d+=4)b.push(4294967296*h.random()|0);return new j.init(b,a)}}),m=k.enc={},s=m.Hex={stringify:function(a){var b=a.words;a=a.sigBytes;for(var d=[],c=0;c<a;c++){var e=b[c>>>2]>>>24-8*(c%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c<b;c+=2)d[c>>>3]|=parseInt(a.substr(c,2),16)<<24-4*(c%8);return new j.init(d,b/2)}},p=m.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var d=[],c=0;c<a;c++)d.push(String.fromCharCode(b[c>>>2]>>>24-8*(c%4)&255));return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c<b;c++)d[c>>>2]|=(a.charCodeAt(c)&255)<<24-8*(c%4);return new j.init(d,b)}},t=m.Utf8={stringify:function(a){try{return decodeURIComponent(escape(p.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return p.parse(unescape(encodeURIComponent(a)))}},q=l.BufferedBlockAlgorithm=f.extend({reset:function(){this._data=new j.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=t.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,d=b.words,c=b.sigBytes,e=this.blockSize,f=c/(4*e),f=a?h.ceil(f):h.max((f|0)-this._minBufferSize,0);a=f*e;c=h.min(4*a,c);if(a){for(var g=0;g<a;g+=e)this._doProcessBlock(d,g);g=d.splice(0,a);b.sigBytes-=c}return new j.init(g,c)},clone:function(){var a=f.clone.call(this);a._data=this._data.clone();return a},_minBufferSize:0});l.Hasher=q.extend({cfg:f.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){q.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,d){return(new a.init(d)).finalize(b)}},_createHmacHelper:function(a){return function(b,d){return(new u.HMAC.init(a,d)).finalize(b)}}});var u=k.algo={};return k}(Math);
+(function () { var k = CryptoJS, b = k.lib, m = b.WordArray, l = b.Hasher, d = [], b = k.algo.SHA1 = l.extend({ _doReset: function () { this._hash = new m.init([1732584193, 4023233417, 2562383102, 271733878, 3285377520]) }, _doProcessBlock: function (n, p) { for (var a = this._hash.words, e = a[0], f = a[1], h = a[2], j = a[3], b = a[4], c = 0; 80 > c; c++) { if (16 > c) d[c] = n[p + c] | 0; else { var g = d[c - 3] ^ d[c - 8] ^ d[c - 14] ^ d[c - 16]; d[c] = g << 1 | g >>> 31 } g = (e << 5 | e >>> 27) + b + d[c]; g = 20 > c ? g + ((f & h | ~f & j) + 1518500249) : 40 > c ? g + ((f ^ h ^ j) + 1859775393) : 60 > c ? g + ((f & h | f & j | h & j) - 1894007588) : g + ((f ^ h ^ j) - 899497514); b = j; j = h; h = f << 30 | f >>> 2; f = e; e = g } a[0] = a[0] + e | 0; a[1] = a[1] + f | 0; a[2] = a[2] + h | 0; a[3] = a[3] + j | 0; a[4] = a[4] + b | 0 }, _doFinalize: function () { var b = this._data, d = b.words, a = 8 * this._nDataBytes, e = 8 * b.sigBytes; d[e >>> 5] |= 128 << 24 - e % 32; d[(e + 64 >>> 9 << 4) + 14] = Math.floor(a / 4294967296); d[(e + 64 >>> 9 << 4) + 15] = a; b.sigBytes = 4 * d.length; this._process(); return this._hash }, clone: function () { var b = l.clone.call(this); b._hash = this._hash.clone(); return b } }); k.SHA1 = l._createHelper(b); k.HmacSHA1 = l._createHmacHelper(b) })();
+(function (k) { for (var g = CryptoJS, h = g.lib, v = h.WordArray, j = h.Hasher, h = g.algo, s = [], t = [], u = function (q) { return 4294967296 * (q - (q | 0)) | 0 }, l = 2, b = 0; 64 > b;) { var d; a: { d = l; for (var w = k.sqrt(d), r = 2; r <= w; r++) if (!(d % r)) { d = !1; break a } d = !0 } d && (8 > b && (s[b] = u(k.pow(l, 0.5))), t[b] = u(k.pow(l, 1 / 3)), b++); l++ } var n = [], h = h.SHA256 = j.extend({ _doReset: function () { this._hash = new v.init(s.slice(0)) }, _doProcessBlock: function (q, h) { for (var a = this._hash.words, c = a[0], d = a[1], b = a[2], k = a[3], f = a[4], g = a[5], j = a[6], l = a[7], e = 0; 64 > e; e++) { if (16 > e) n[e] = q[h + e] | 0; else { var m = n[e - 15], p = n[e - 2]; n[e] = ((m << 25 | m >>> 7) ^ (m << 14 | m >>> 18) ^ m >>> 3) + n[e - 7] + ((p << 15 | p >>> 17) ^ (p << 13 | p >>> 19) ^ p >>> 10) + n[e - 16] } m = l + ((f << 26 | f >>> 6) ^ (f << 21 | f >>> 11) ^ (f << 7 | f >>> 25)) + (f & g ^ ~f & j) + t[e] + n[e]; p = ((c << 30 | c >>> 2) ^ (c << 19 | c >>> 13) ^ (c << 10 | c >>> 22)) + (c & d ^ c & b ^ d & b); l = j; j = g; g = f; f = k + m | 0; k = b; b = d; d = c; c = m + p | 0 } a[0] = a[0] + c | 0; a[1] = a[1] + d | 0; a[2] = a[2] + b | 0; a[3] = a[3] + k | 0; a[4] = a[4] + f | 0; a[5] = a[5] + g | 0; a[6] = a[6] + j | 0; a[7] = a[7] + l | 0 }, _doFinalize: function () { var d = this._data, b = d.words, a = 8 * this._nDataBytes, c = 8 * d.sigBytes; b[c >>> 5] |= 128 << 24 - c % 32; b[(c + 64 >>> 9 << 4) + 14] = k.floor(a / 4294967296); b[(c + 64 >>> 9 << 4) + 15] = a; d.sigBytes = 4 * b.length; this._process(); return this._hash }, clone: function () { var b = j.clone.call(this); b._hash = this._hash.clone(); return b } }); g.SHA256 = j._createHelper(h); g.HmacSHA256 = j._createHmacHelper(h) })(Math);
+(function(){var c=CryptoJS,k=c.enc.Utf8;c.algo.HMAC=c.lib.Base.extend({init:function(a,b){a=this._hasher=new a.init;"string"==typeof b&&(b=k.parse(b));var c=a.blockSize,e=4*c;b.sigBytes>e&&(b=a.finalize(b));b.clamp();for(var f=this._oKey=b.clone(),g=this._iKey=b.clone(),h=f.words,j=g.words,d=0;d<c;d++)h[d]^=1549556828,j[d]^=909522486;f.sigBytes=g.sigBytes=e;this.reset()},reset:function(){var a=this._hasher;a.reset();a.update(this._iKey)},update:function(a){this._hasher.update(a);return this},finalize:function(a){var b=this._hasher;a=b.finalize(a);b.reset();return b.finalize(this._oKey.clone().concat(a))}})})();
+(function(){var h=CryptoJS,j=h.lib.WordArray;h.enc.Base64={stringify:function(b){var e=b.words,f=b.sigBytes,c=this._map;b.clamp();b=[];for(var a=0;a<f;a+=3)for(var d=(e[a>>>2]>>>24-8*(a%4)&255)<<16|(e[a+1>>>2]>>>24-8*((a+1)%4)&255)<<8|e[a+2>>>2]>>>24-8*((a+2)%4)&255,g=0;4>g&&a+0.75*g<f;g++)b.push(c.charAt(d>>>6*(3-g)&63));if(e=c.charAt(64))for(;b.length%4;)b.push(e);return b.join("")},parse:function(b){var e=b.length,f=this._map,c=f.charAt(64);c&&(c=b.indexOf(c),-1!=c&&(e=c));for(var c=[],a=0,d=0;d<e;d++)if(d%4){var g=f.indexOf(b.charAt(d-1))<<2*(d%4),h=f.indexOf(b.charAt(d))>>>6-2*(d%4);c[a>>>2]|=(g|h)<<24-8*(a%4);a++}return j.create(c,a)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/lib/client.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/lib/client.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/lib/client.js	(revision 484)
@@ -0,0 +1,285 @@
+// Load modules
+
+var Url = require('url');
+var Hoek = require('hoek');
+var Cryptiles = require('cryptiles');
+var Crypto = require('./crypto');
+var Utils = require('./utils');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Generate an Authorization header for a given request
+
+/*
+    uri: 'http://example.com/resource?a=b' or object from Url.parse()
+    method: HTTP verb (e.g. 'GET', 'POST')
+    options: {
+
+        // Required
+
+        credentials: {
+            id: 'dh37fgj492je',
+            key: 'aoijedoaijsdlaksjdl',
+            algorithm: 'sha256'                                 // 'sha1', 'sha256'
+        },
+
+        // Optional
+
+        ext: 'application-specific',                        // Application specific data sent via the ext attribute
+        timestamp: Date.now(),                              // A pre-calculated timestamp
+        nonce: '2334f34f',                                  // A pre-generated nonce
+        localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
+        payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
+        contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
+        hash: 'U4MKKSmiVxk37JCCrAVIjV=',                    // Pre-calculated payload hash
+        app: '24s23423f34dx',                               // Oz application id
+        dlg: '234sz34tww3sd'                                // Oz delegated-by application id
+    }
+*/
+
+exports.header = function (uri, method, options) {
+
+    var result = {
+        field: '',
+        artifacts: {}
+    };
+
+    // Validate inputs
+
+    if (!uri || (typeof uri !== 'string' && typeof uri !== 'object') ||
+        !method || typeof method !== 'string' ||
+        !options || typeof options !== 'object') {
+
+        return result;
+    }
+
+    // Application time
+
+    var timestamp = options.timestamp || Math.floor((Utils.now() + (options.localtimeOffsetMsec || 0)) / 1000)
+
+    // Validate credentials
+
+    var credentials = options.credentials;
+    if (!credentials ||
+        !credentials.id ||
+        !credentials.key ||
+        !credentials.algorithm) {
+
+        // Invalid credential object
+        return result;
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        return result;
+    }
+
+    // Parse URI
+
+    if (typeof uri === 'string') {
+        uri = Url.parse(uri);
+    }
+
+    // Calculate signature
+
+    var artifacts = {
+        ts: timestamp,
+        nonce: options.nonce || Cryptiles.randomString(6),
+        method: method,
+        resource: uri.pathname + (uri.search || ''),                            // Maintain trailing '?'
+        host: uri.hostname,
+        port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
+        hash: options.hash,
+        ext: options.ext,
+        app: options.app,
+        dlg: options.dlg
+    };
+
+    result.artifacts = artifacts;
+
+    // Calculate payload hash
+
+    if (!artifacts.hash &&
+        options.hasOwnProperty('payload')) {
+
+        artifacts.hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
+    }
+
+    var mac = Crypto.calculateMac('header', credentials, artifacts);
+
+    // Construct header
+
+    var hasExt = artifacts.ext !== null && artifacts.ext !== undefined && artifacts.ext !== '';       // Other falsey values allowed
+    var header = 'Hawk id="' + credentials.id +
+                 '", ts="' + artifacts.ts +
+                 '", nonce="' + artifacts.nonce +
+                 (artifacts.hash ? '", hash="' + artifacts.hash : '') +
+                 (hasExt ? '", ext="' + Utils.escapeHeaderAttribute(artifacts.ext) : '') +
+                 '", mac="' + mac + '"';
+
+    if (artifacts.app) {
+        header += ', app="' + artifacts.app +
+                  (artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"';
+    }
+
+    result.field = header;
+
+    return result;
+};
+
+
+// Validate server response
+
+/*
+    res:        node's response object
+    artifacts:  object recieved from header().artifacts
+    options: {
+        payload:    optional payload received
+        required:   specifies if a Server-Authorization header is required. Defaults to 'false'
+    }
+*/
+
+exports.authenticate = function (res, credentials, artifacts, options) {
+
+    artifacts = Hoek.clone(artifacts);
+    options = options || {};
+
+    if (res.headers['www-authenticate']) {
+
+        // Parse HTTP WWW-Authenticate header
+
+        var attributes = Utils.parseAuthorizationHeader(res.headers['www-authenticate'], ['ts', 'tsm', 'error']);
+        if (attributes instanceof Error) {
+            return false;
+        }
+
+        if (attributes.ts) {
+            var tsm = Crypto.calculateTsMac(attributes.ts, credentials);
+            if (tsm !== attributes.tsm) {
+                return false;
+            }
+        }
+    }
+
+    // Parse HTTP Server-Authorization header
+
+    if (!res.headers['server-authorization'] &&
+        !options.required) {
+
+        return true;
+    }
+
+    var attributes = Utils.parseAuthorizationHeader(res.headers['server-authorization'], ['mac', 'ext', 'hash']);
+    if (attributes instanceof Error) {
+        return false;
+    }
+
+    artifacts.ext = attributes.ext;
+    artifacts.hash = attributes.hash;
+
+    var mac = Crypto.calculateMac('response', credentials, artifacts);
+    if (mac !== attributes.mac) {
+        return false;
+    }
+
+    if (!options.hasOwnProperty('payload')) {
+        return true;
+    }
+
+    if (!attributes.hash) {
+        return false;
+    }
+
+    var calculatedHash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, res.headers['content-type']);
+    return (calculatedHash === attributes.hash);
+};
+
+
+// Generate a bewit value for a given URI
+
+/*
+ * credentials is an object with the following keys: 'id, 'key', 'algorithm'.
+ * options is an object with the following optional keys: 'ext', 'localtimeOffsetMsec'
+ */
+/*
+    uri: 'http://example.com/resource?a=b' or object from Url.parse()
+    options: {
+
+        // Required
+
+        credentials: {
+            id: 'dh37fgj492je',
+            key: 'aoijedoaijsdlaksjdl',
+            algorithm: 'sha256'                             // 'sha1', 'sha256'
+        },
+        ttlSec: 60 * 60,                                    // TTL in seconds
+
+        // Optional
+
+        ext: 'application-specific',                        // Application specific data sent via the ext attribute
+        localtimeOffsetMsec: 400                            // Time offset to sync with server time
+    };
+*/
+
+exports.getBewit = function (uri, options) {
+
+    // Validate inputs
+
+    if (!uri ||
+        (typeof uri !== 'string' && typeof uri !== 'object') ||
+        !options ||
+        typeof options !== 'object' ||
+        !options.ttlSec) {
+
+        return '';
+    }
+
+    options.ext = (options.ext === null || options.ext === undefined ? '' : options.ext);       // Zero is valid value
+
+    // Application time
+
+    var now = Utils.now() + (options.localtimeOffsetMsec || 0);
+
+    // Validate credentials
+
+    var credentials = options.credentials;
+    if (!credentials ||
+        !credentials.id ||
+        !credentials.key ||
+        !credentials.algorithm) {
+
+        return '';
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        return '';
+    }
+
+    // Parse URI
+
+    if (typeof uri === 'string') {
+        uri = Url.parse(uri);
+    }
+
+    // Calculate signature
+
+    var exp = Math.floor(now / 1000) + options.ttlSec;
+    var mac = Crypto.calculateMac('bewit', credentials, {
+        ts: exp,
+        nonce: '',
+        method: 'GET',
+        resource: uri.pathname + (uri.search || ''),                            // Maintain trailing '?'
+        host: uri.hostname,
+        port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
+        ext: options.ext
+    });
+
+    // Construct bewit: id\exp\mac\ext
+
+    var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + options.ext;
+    return Utils.base64urlEncode(bewit);
+};
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/lib/crypto.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/lib/crypto.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/lib/crypto.js	(revision 484)
@@ -0,0 +1,111 @@
+// Load modules
+
+var Crypto = require('crypto');
+var Url = require('url');
+var Utils = require('./utils');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// MAC normalization format version
+
+exports.headerVersion = '1';                        // Prevent comparison of mac values generated with different normalized string formats
+
+
+// Supported HMAC algorithms
+
+exports.algorithms = ['sha1', 'sha256'];
+
+
+// Calculate the request MAC
+
+/*
+    type: 'header',                                 // 'header', 'bewit', 'response'
+    credentials: {
+        key: 'aoijedoaijsdlaksjdl',
+        algorithm: 'sha256'                         // 'sha1', 'sha256'
+    },
+    options: {
+        method: 'GET',
+        resource: '/resource?a=1&b=2',
+        host: 'example.com',
+        port: 8080,
+        ts: 1357718381034,
+        nonce: 'd3d345f',
+        hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
+        ext: 'app-specific-data',
+        app: 'hf48hd83qwkj',                        // Application id (Oz)
+        dlg: 'd8djwekds9cj'                         // Delegated by application id (Oz), requires options.app
+    }
+*/
+
+exports.calculateMac = function (type, credentials, options) {
+
+    var normalized = exports.generateNormalizedString(type, options);
+
+    var hmac = Crypto.createHmac(credentials.algorithm, credentials.key).update(normalized);
+    var digest = hmac.digest('base64');
+    return digest;
+};
+
+
+exports.generateNormalizedString = function (type, options) {
+
+    var normalized = 'hawk.' + exports.headerVersion + '.' + type + '\n' +
+                     options.ts + '\n' +
+                     options.nonce + '\n' +
+                     options.method.toUpperCase() + '\n' +
+                     options.resource + '\n' +
+                     options.host.toLowerCase() + '\n' +
+                     options.port + '\n' +
+                     (options.hash || '') + '\n';
+
+    if (options.ext) {
+        normalized += options.ext.replace('\\', '\\\\').replace('\n', '\\n');
+    }
+
+    normalized += '\n';
+
+    if (options.app) {
+        normalized += options.app + '\n' +
+                      (options.dlg || '') + '\n';
+    }
+
+    return normalized;
+};
+
+
+exports.calculatePayloadHash = function (payload, algorithm, contentType) {
+
+    var hash = exports.initializePayloadHash(algorithm, contentType);
+    hash.update(payload || '');
+    return exports.finalizePayloadHash(hash);
+};
+
+
+exports.initializePayloadHash = function (algorithm, contentType) {
+
+    var hash = Crypto.createHash(algorithm);
+    hash.update('hawk.' + exports.headerVersion + '.payload\n');
+    hash.update(Utils.parseContentType(contentType) + '\n');
+    return hash;
+};
+
+
+exports.finalizePayloadHash = function (hash) {
+
+    hash.update('\n');
+    return hash.digest('base64');
+};
+
+
+exports.calculateTsMac = function (ts, credentials) {
+
+    var hmac = Crypto.createHmac(credentials.algorithm, credentials.key);
+    hmac.update('hawk.' + exports.headerVersion + '.ts\n' + ts + '\n');
+    return hmac.digest('base64');
+};
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/lib/index.js	(revision 484)
@@ -0,0 +1,15 @@
+// Export sub-modules
+
+exports.error = exports.Error = require('boom');
+exports.sntp = require('sntp');
+exports.server = require('./server');
+exports.client = require('./client');
+exports.crypto = require('./crypto');
+exports.utils = require('./utils');
+
+exports.uri = {
+    authenticate: exports.server.authenticateBewit,
+    getBewit: exports.client.getBewit
+};
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/lib/server.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/lib/server.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/lib/server.js	(revision 484)
@@ -0,0 +1,424 @@
+// Load modules
+
+var Boom = require('boom');
+var Hoek = require('hoek');
+var Cryptiles = require('cryptiles');
+var Crypto = require('./crypto');
+var Utils = require('./utils');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Hawk authentication
+
+/*
+   req:                 node's HTTP request object or an object as follows:
+  
+                        var request = {
+                            method: 'GET',
+                            url: '/resource/4?a=1&b=2',
+                            host: 'example.com',
+                            port: 8080,
+                            authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="'
+                        };
+  
+   credentialsFunc:     required function to lookup the set of Hawk credentials based on the provided credentials id.
+                        The credentials include the MAC key, MAC algorithm, and other attributes (such as username)
+                        needed by the application. This function is the equivalent of verifying the username and
+                        password in Basic authentication.
+  
+                        var credentialsFunc = function (id, callback) {
+    
+                            // Lookup credentials in database
+                            db.lookup(id, function (err, item) {
+    
+                                if (err || !item) {
+                                    return callback(err);
+                                }
+    
+                                var credentials = {
+                                    // Required
+                                    key: item.key,
+                                    algorithm: item.algorithm,
+                                    // Application specific
+                                    user: item.user
+                                };
+    
+                                return callback(null, credentials);
+                            });
+                        };
+  
+   options: {
+
+        hostHeaderName:        optional header field name, used to override the default 'Host' header when used
+                               behind a cache of a proxy. Apache2 changes the value of the 'Host' header while preserving
+                               the original (which is what the module must verify) in the 'x-forwarded-host' header field.
+                               Only used when passed a node Http.ServerRequest object.
+  
+        nonceFunc:             optional nonce validation function. The function signature is function(nonce, ts, callback)
+                               where 'callback' must be called using the signature function(err).
+  
+        timestampSkewSec:      optional number of seconds of permitted clock skew for incoming timestamps. Defaults to 60 seconds.
+                               Provides a +/- skew which means actual allowed window is double the number of seconds.
+  
+        localtimeOffsetMsec:   optional local clock time offset express in a number of milliseconds (positive or negative).
+                               Defaults to 0.
+  
+        payload:               optional payload for validation. The client calculates the hash value and includes it via the 'hash'
+                               header attribute. The server always ensures the value provided has been included in the request
+                               MAC. When this option is provided, it validates the hash value itself. Validation is done by calculating
+                               a hash value over the entire payload (assuming it has already be normalized to the same format and
+                               encoding used by the client to calculate the hash on request). If the payload is not available at the time
+                               of authentication, the authenticatePayload() method can be used by passing it the credentials and
+                               attributes.hash returned in the authenticate callback.
+    }
+
+    callback: function (err, credentials, artifacts) { }
+ */
+
+exports.authenticate = function (req, credentialsFunc, options, callback) {
+
+    callback = Utils.nextTick(callback);
+    
+    // Default options
+
+    options.nonceFunc = options.nonceFunc || function (nonce, ts, nonceCallback) { return nonceCallback(); };   // No validation
+    options.timestampSkewSec = options.timestampSkewSec || 60;                                                  // 60 seconds
+
+    // Application time
+
+    var now = Utils.now() + (options.localtimeOffsetMsec || 0);                 // Measure now before any other processing
+
+    // Convert node Http request object to a request configuration object
+
+    var request = Utils.parseRequest(req, options);
+    if (request instanceof Error) {
+        return callback(Boom.badRequest(request.message));
+    }
+
+    // Parse HTTP Authorization header
+
+    var attributes = Utils.parseAuthorizationHeader(request.authorization);
+    if (attributes instanceof Error) {
+        return callback(attributes);
+    }
+
+    // Construct artifacts container
+
+    var artifacts = {
+        method: request.method,
+        host: request.host,
+        port: request.port,
+        resource: request.url,
+        ts: attributes.ts,
+        nonce: attributes.nonce,
+        hash: attributes.hash,
+        ext: attributes.ext,
+        app: attributes.app,
+        dlg: attributes.dlg,
+        mac: attributes.mac,
+        id: attributes.id
+    };
+
+    // Verify required header attributes
+
+    if (!attributes.id ||
+        !attributes.ts ||
+        !attributes.nonce ||
+        !attributes.mac) {
+
+        return callback(Boom.badRequest('Missing attributes'), null, artifacts);
+    }
+
+    // Fetch Hawk credentials
+
+    credentialsFunc(attributes.id, function (err, credentials) {
+
+        if (err) {
+            return callback(err, credentials || null, artifacts);
+        }
+
+        if (!credentials) {
+            return callback(Boom.unauthorized('Unknown credentials', 'Hawk'), null, artifacts);
+        }
+
+        if (!credentials.key ||
+            !credentials.algorithm) {
+
+            return callback(Boom.internal('Invalid credentials'), credentials, artifacts);
+        }
+
+        if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+            return callback(Boom.internal('Unknown algorithm'), credentials, artifacts);
+        }
+
+        // Calculate MAC
+
+        var mac = Crypto.calculateMac('header', credentials, artifacts);
+        if (!Cryptiles.fixedTimeComparison(mac, attributes.mac)) {
+            return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials, artifacts);
+        }
+
+        // Check payload hash
+
+        if (options.payload !== null &&
+            options.payload !== undefined) {       // '' is valid
+
+            if (!attributes.hash) {
+                return callback(Boom.unauthorized('Missing required payload hash', 'Hawk'), credentials, artifacts);
+            }
+
+            var hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, request.contentType);
+            if (!Cryptiles.fixedTimeComparison(hash, attributes.hash)) {
+                return callback(Boom.unauthorized('Bad payload hash', 'Hawk'), credentials, artifacts);
+            }
+        }
+
+        // Check nonce
+
+        options.nonceFunc(attributes.nonce, attributes.ts, function (err) {
+
+            if (err) {
+                return callback(Boom.unauthorized('Invalid nonce', 'Hawk'), credentials, artifacts);
+            }
+
+            // Check timestamp staleness
+
+            if (Math.abs((attributes.ts * 1000) - now) > (options.timestampSkewSec * 1000)) {
+                var fresh = Math.floor((Utils.now() + (options.localtimeOffsetMsec || 0)) / 1000);            // Get fresh now
+                var tsm = Crypto.calculateTsMac(fresh, credentials);
+                return callback(Boom.unauthorized('Stale timestamp', 'Hawk', { ts: fresh, tsm: tsm }), credentials, artifacts);
+            }
+
+            // Successful authentication
+
+            return callback(null, credentials, artifacts);
+        });
+    });
+};
+
+
+// Authenticate payload hash - used when payload cannot be provided during authenticate()
+
+/*
+    payload:        raw request payload
+    credentials:    from authenticate callback
+    artifacts:      from authenticate callback
+    contentType:    req.headers['content-type']
+*/
+
+exports.authenticatePayload = function (payload, credentials, artifacts, contentType) {
+
+    var calculatedHash = Crypto.calculatePayloadHash(payload, credentials.algorithm, contentType);
+    return Cryptiles.fixedTimeComparison(calculatedHash, artifacts.hash);
+};
+
+
+// Generate a Server-Authorization header for a given response
+
+/*
+    credentials: {},                                        // Object received from authenticate()
+    artifacts: {}                                           // Object received from authenticate(); 'mac', 'hash', and 'ext' - ignored
+    options: {
+        ext: 'application-specific',                        // Application specific data sent via the ext attribute
+        payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
+        contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
+        hash: 'U4MKKSmiVxk37JCCrAVIjV='                     // Pre-calculated payload hash
+    }
+*/
+
+exports.header = function (credentials, artifacts, options) {
+
+    // Prepare inputs
+
+    options = options || {};
+
+    if (!artifacts ||
+        typeof artifacts !== 'object' ||
+        typeof options !== 'object') {
+
+        return '';
+    }
+
+    artifacts = Hoek.clone(artifacts);
+    delete artifacts.mac;
+    artifacts.hash = options.hash;
+    artifacts.ext = options.ext;
+
+    // Validate credentials
+
+    if (!credentials ||
+        !credentials.key ||
+        !credentials.algorithm) {
+
+        // Invalid credential object
+        return '';
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        return '';
+    }
+
+    // Calculate payload hash
+
+    if (!artifacts.hash &&
+        options.hasOwnProperty('payload')) {
+
+        artifacts.hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
+    }
+
+    var mac = Crypto.calculateMac('response', credentials, artifacts);
+
+    // Construct header
+
+    var header = 'Hawk mac="' + mac + '"' +
+                 (artifacts.hash ? ', hash="' + artifacts.hash + '"' : '');
+
+    if (artifacts.ext !== null &&
+        artifacts.ext !== undefined &&
+        artifacts.ext !== '') {                       // Other falsey values allowed
+
+        header += ', ext="' + Utils.escapeHeaderAttribute(artifacts.ext) + '"';
+    }
+
+    return header;
+};
+
+
+/*
+ * Arguments and options are the same as index.js with the exception that the only supported options are:
+ * 'hostHeaderName', 'localtimeOffsetMsec'
+ */
+
+exports.authenticateBewit = function (req, credentialsFunc, options, callback) {
+
+    callback = Utils.nextTick(callback);
+
+    // Application time
+
+    var now = Utils.now() + (options.localtimeOffsetMsec || 0);
+
+    // Convert node Http request object to a request configuration object
+
+    var request = Utils.parseRequest(req, options);
+    if (request instanceof Error) {
+        return callback(Boom.badRequest(request.message));
+    }
+
+    // Extract bewit
+
+    //                                 1     2             3           4     
+    var resource = request.url.match(/^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/);
+    if (!resource) {
+        return callback(Boom.unauthorized(null, 'Hawk'));
+    }
+
+    // Bewit not empty
+
+    if (!resource[3]) {
+        return callback(Boom.unauthorized('Empty bewit', 'Hawk'));
+    }
+
+    // Verify method is GET
+
+    if (request.method !== 'GET' &&
+        request.method !== 'HEAD') {
+
+        return callback(Boom.unauthorized('Invalid method', 'Hawk'));
+    }
+
+    // No other authentication
+
+    if (request.authorization) {
+        return callback(Boom.badRequest('Multiple authentications', 'Hawk'));
+    }
+
+    // Parse bewit
+
+    var bewitString = Utils.base64urlDecode(resource[3]);
+    if (bewitString instanceof Error) {
+        return callback(Boom.badRequest('Invalid bewit encoding'));
+    }
+
+    // Bewit format: id\exp\mac\ext ('\' is used because it is a reserved header attribute character)
+
+    var bewitParts = bewitString.split('\\');
+    if (!bewitParts ||
+        bewitParts.length !== 4) {
+
+        return callback(Boom.badRequest('Invalid bewit structure'));
+    }
+
+    var bewit = {
+        id: bewitParts[0],
+        exp: parseInt(bewitParts[1], 10),
+        mac: bewitParts[2],
+        ext: bewitParts[3] || ''
+    };
+
+    if (!bewit.id ||
+        !bewit.exp ||
+        !bewit.mac) {
+
+        return callback(Boom.badRequest('Missing bewit attributes'));
+    }
+
+    // Construct URL without bewit
+
+    var url = resource[1];
+    if (resource[4]) {
+        url += resource[2] + resource[4];
+    }
+
+    // Check expiration
+
+    if (bewit.exp * 1000 <= now) {
+        return callback(Boom.unauthorized('Access expired', 'Hawk'), null, bewit);
+    }
+
+    // Fetch Hawk credentials
+
+    credentialsFunc(bewit.id, function (err, credentials) {
+
+        if (err) {
+            return callback(err, credentials || null, bewit.ext);
+        }
+
+        if (!credentials) {
+            return callback(Boom.unauthorized('Unknown credentials', 'Hawk'), null, bewit);
+        }
+
+        if (!credentials.key ||
+            !credentials.algorithm) {
+
+            return callback(Boom.internal('Invalid credentials'), credentials, bewit);
+        }
+
+        if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+            return callback(Boom.internal('Unknown algorithm'), credentials, bewit);
+        }
+
+        // Calculate MAC
+
+        var mac = Crypto.calculateMac('bewit', credentials, {
+            ts: bewit.exp,
+            nonce: '',
+            method: 'GET',
+            resource: url,
+            host: request.host,
+            port: request.port,
+            ext: bewit.ext
+        });
+
+        if (!Cryptiles.fixedTimeComparison(mac, bewit.mac)) {
+            return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials, bewit);
+        }
+
+        // Successful authentication
+
+        return callback(null, credentials, bewit);
+    });
+};
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/lib/utils.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/lib/utils.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/lib/utils.js	(revision 484)
@@ -0,0 +1,174 @@
+// Load modules
+
+var Hoek = require('hoek');
+var Sntp = require('sntp');
+var Boom = require('boom');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Import Hoek Utilities
+
+internals.import = function () {
+
+    for (var i in Hoek) {
+        if (Hoek.hasOwnProperty(i)) {
+            exports[i] = Hoek[i];
+        }
+    }
+};
+
+internals.import();
+
+
+// Hawk version
+
+exports.version = function () {
+
+    return exports.loadPackage(__dirname + '/..').version;
+};
+
+
+// Extract host and port from request
+
+exports.parseHost = function (req, hostHeaderName) {
+
+    hostHeaderName = (hostHeaderName ? hostHeaderName.toLowerCase() : 'host');
+    var hostHeader = req.headers[hostHeaderName];
+    if (!hostHeader) {
+        return null;
+    }
+
+    var hostHeaderRegex = /^(?:(?:\r\n)?[\t ])*([^:]+)(?::(\d+))?(?:(?:\r\n)?[\t ])*$/;     // Does not support IPv6
+    var hostParts = hostHeader.match(hostHeaderRegex);
+
+    if (!hostParts ||
+        hostParts.length !== 3 ||
+        !hostParts[1]) {
+
+        return null;
+    }
+
+    return {
+        name: hostParts[1],
+        port: (hostParts[2] ? hostParts[2] : (req.connection && req.connection.encrypted ? 443 : 80))
+    };
+};
+
+
+// Parse Content-Type header content
+
+exports.parseContentType = function (header) {
+
+    if (!header) {
+        return '';
+    }
+
+    return header.split(';')[0].trim().toLowerCase();
+};
+
+
+// Convert node's  to request configuration object
+
+exports.parseRequest = function (req, options) {
+
+    if (!req.headers) {
+        return req;
+    }
+
+    // Obtain host and port information
+
+    var host = exports.parseHost(req, options.hostHeaderName);
+    if (!host) {
+        return new Error('Invalid Host header');
+    }
+
+    var request = {
+        method: req.method,
+        url: req.url,
+        host: host.name,
+        port: host.port,
+        authorization: req.headers.authorization,
+        contentType: req.headers['content-type'] || ''
+    };
+
+    return request;
+};
+
+
+exports.now = function () {
+
+    return Sntp.now();
+};
+
+
+// Parse Hawk HTTP Authorization header
+
+exports.parseAuthorizationHeader = function (header, keys) {
+
+    keys = keys || ['id', 'ts', 'nonce', 'hash', 'ext', 'mac', 'app', 'dlg'];
+
+    if (!header) {
+        return Boom.unauthorized(null, 'Hawk');
+    }
+
+    var headerParts = header.match(/^(\w+)(?:\s+(.*))?$/);       // Header: scheme[ something]
+    if (!headerParts) {
+        return Boom.badRequest('Invalid header syntax');
+    }
+
+    var scheme = headerParts[1];
+    if (scheme.toLowerCase() !== 'hawk') {
+        return Boom.unauthorized(null, 'Hawk');
+    }
+
+    var attributesString = headerParts[2];
+    if (!attributesString) {
+        return Boom.badRequest('Invalid header syntax');
+    }
+
+    var attributes = {};
+    var errorMessage = '';
+    var verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, function ($0, $1, $2) {
+
+        // Check valid attribute names
+
+        if (keys.indexOf($1) === -1) {
+            errorMessage = 'Unknown attribute: ' + $1;
+            return;
+        }
+
+        // Allowed attribute value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
+
+        if ($2.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/) === null) {
+            errorMessage = 'Bad attribute value: ' + $1;
+            return;
+        }
+
+        // Check for duplicates
+
+        if (attributes.hasOwnProperty($1)) {
+            errorMessage = 'Duplicate attribute: ' + $1;
+            return;
+        }
+
+        attributes[$1] = $2;
+        return '';
+    });
+
+    if (verify !== '') {
+        return Boom.badRequest(errorMessage || 'Bad header format');
+    }
+
+    return attributes;
+};
+
+
+exports.unauthorized = function (message) {
+
+    return Boom.unauthorized(message, 'Hawk');
+};
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/.npmignore	(revision 484)
@@ -0,0 +1,18 @@
+.idea
+*.iml
+npm-debug.log
+dump.rdb
+node_modules
+results.tap
+results.xml
+npm-shrinkwrap.json
+config.json
+.DS_Store
+*/.DS_Store
+*/*/.DS_Store
+._*
+*/._*
+*/*/._*
+coverage.*
+lib-cov
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+
+node_js:
+  - 0.10
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/LICENSE	(revision 484)
@@ -0,0 +1,24 @@
+Copyright (c) 2012-2013, Walmart.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Walmart nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/Makefile	(revision 484)
@@ -0,0 +1,11 @@
+test:
+	@node node_modules/lab/bin/lab
+test-cov: 
+	@node node_modules/lab/bin/lab -r threshold -t 100
+test-cov-html:
+	@node node_modules/lab/bin/lab -r html -o coverage.html
+complexity:
+	@node node_modules/complexity-report/src/cli.js -o complexity.md -f markdown lib
+
+.PHONY: test test-cov test-cov-html complexity
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/README.md	(revision 484)
@@ -0,0 +1,6 @@
+<a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a>
+![boom Logo](https://raw.github.com/spumko/boom/master/images/boom.png)
+
+HTTP-friendly error objects
+
+[![Build Status](https://secure.travis-ci.org/spumko/boom.png)](http://travis-ci.org/spumko/boom)
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/index.js	(revision 484)
@@ -0,0 +1,1 @@
+module.exports = require('./lib');
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/lib/index.js	(revision 484)
@@ -0,0 +1,207 @@
+// Load modules
+
+var Http = require('http');
+var NodeUtil = require('util');
+var Hoek = require('hoek');
+
+
+// Declare internals
+
+var internals = {};
+
+
+exports = module.exports = internals.Boom = function (/* (new Error) or (code, message) */) {
+
+    var self = this;
+
+    Hoek.assert(this.constructor === internals.Boom, 'Error must be instantiated using new');
+
+    Error.call(this);
+    this.isBoom = true;
+
+    this.response = {
+        code: 0,
+        payload: {},
+        headers: {}
+        // type: 'content-type'
+    };
+
+    if (arguments[0] instanceof Error) {
+
+        // Error
+
+        var error = arguments[0];
+
+        this.data = error;
+        this.response.code = error.code || 500;
+        if (error.message) {
+            this.message = error.message;
+        }
+    }
+    else {
+
+        // code, message
+
+        var code = arguments[0];
+        var message = arguments[1];
+
+        Hoek.assert(!isNaN(parseFloat(code)) && isFinite(code) && code >= 400, 'First argument must be a number (400+)');
+
+        this.response.code = code;
+        if (message) {
+            this.message = message;
+        }
+    }
+
+    // Response format
+
+    this.reformat();
+
+    return this;
+};
+
+NodeUtil.inherits(internals.Boom, Error);
+
+
+internals.Boom.prototype.reformat = function () {
+
+    this.response.payload.code = this.response.code;
+    this.response.payload.error = Http.STATUS_CODES[this.response.code] || 'Unknown';
+    if (this.message) {
+        this.response.payload.message = Hoek.escapeHtml(this.message);         // Prevent XSS from error message
+    }
+};
+
+
+// Utilities
+
+internals.Boom.badRequest = function (message) {
+
+    return new internals.Boom(400, message);
+};
+
+
+internals.Boom.unauthorized = function (message, scheme, attributes) {          // Or function (message, wwwAuthenticate[])
+
+    var err = new internals.Boom(401, message);
+
+    if (!scheme) {
+        return err;
+    }
+
+    var wwwAuthenticate = '';
+
+    if (typeof scheme === 'string') {
+
+        // function (message, scheme, attributes)
+
+        wwwAuthenticate = scheme;
+        if (attributes) {
+            var names = Object.keys(attributes);
+            for (var i = 0, il = names.length; i < il; ++i) {
+                if (i) {
+                    wwwAuthenticate += ',';
+                }
+
+                var value = attributes[names[i]];
+                if (value === null ||
+                    value === undefined) {              // Value can be zero
+
+                    value = '';
+                }
+                wwwAuthenticate += ' ' + names[i] + '="' + Hoek.escapeHeaderAttribute(value.toString()) + '"';
+            }
+        }
+
+        if (message) {
+            if (attributes) {
+                wwwAuthenticate += ',';
+            }
+            wwwAuthenticate += ' error="' + Hoek.escapeHeaderAttribute(message) + '"';
+        }
+        else {
+            err.isMissing = true;
+        }
+    }
+    else {
+
+        // function (message, wwwAuthenticate[])
+
+        var wwwArray = scheme;
+        for (var i = 0, il = wwwArray.length; i < il; ++i) {
+            if (i) {
+                wwwAuthenticate += ', ';
+            }
+
+            wwwAuthenticate += wwwArray[i];
+        }
+    }
+
+    err.response.headers['WWW-Authenticate'] = wwwAuthenticate;
+
+    return err;
+};
+
+
+internals.Boom.clientTimeout = function (message) {
+
+    return new internals.Boom(408, message);
+};
+
+
+internals.Boom.serverTimeout = function (message) {
+
+    return new internals.Boom(503, message);
+};
+
+
+internals.Boom.forbidden = function (message) {
+
+    return new internals.Boom(403, message);
+};
+
+
+internals.Boom.notFound = function (message) {
+
+    return new internals.Boom(404, message);
+};
+
+
+internals.Boom.internal = function (message, data) {
+
+    var err = new internals.Boom(500, message);
+
+    if (data && data.stack) {
+        err.trace = data.stack.split('\n');
+        err.outterTrace = Hoek.displayStack(1);
+    }
+    else {
+        err.trace = Hoek.displayStack(1);
+    }
+
+    err.data = data;
+    err.response.payload.message = 'An internal server error occurred';                     // Hide actual error from user
+
+    return err;
+};
+
+
+internals.Boom.passThrough = function (code, payload, contentType, headers) {
+
+    var err = new internals.Boom(500, 'Pass-through');                                      // 500 code is only used to initialize
+
+    err.data = {
+        code: code,
+        payload: payload,
+        type: contentType
+    };
+
+    err.response.code = code;
+    err.response.type = contentType;
+    err.response.headers = headers;
+    err.response.payload = payload;
+
+    return err;
+};
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/.npmignore	(revision 484)
@@ -0,0 +1,18 @@
+.idea
+*.iml
+npm-debug.log
+dump.rdb
+node_modules
+results.tap
+results.xml
+npm-shrinkwrap.json
+config.json
+.DS_Store
+*/.DS_Store
+*/*/.DS_Store
+._*
+*/._*
+*/*/._*
+coverage.*
+lib-cov
+complexity.md
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+
+node_js:
+  - 0.10
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/LICENSE	(revision 484)
@@ -0,0 +1,33 @@
+Copyright (c) 2011-2013, Walmart.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Walmart nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+                                  *   *   *
+
+
+Portions of this project were initially based on Postmile, Copyright (c) 2011, Yahoo Inc.
+Postmile is published at https://github.com/yahoo/postmile and its licensing terms are
+published at https://github.com/yahoo/postmile/blob/master/LICENSE.
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/Makefile	(revision 484)
@@ -0,0 +1,10 @@
+test:
+	@node node_modules/lab/bin/lab
+test-cov: 
+	@node node_modules/lab/bin/lab -r threshold -t 100
+test-cov-html:
+	@node node_modules/lab/bin/lab -r html -o coverage.html
+complexity:
+	@node node_modules/complexity-report/src/cli.js -o complexity.md -f markdown lib
+
+.PHONY: test test-cov test-cov-html complexity
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/README.md	(revision 484)
@@ -0,0 +1,436 @@
+<a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a>
+![hoek Logo](https://raw.github.com/spumko/hoek/master/images/hoek.png)
+
+General purpose node utilities
+
+[![Build Status](https://secure.travis-ci.org/spumko/hoek.png)](http://travis-ci.org/spumko/hoek)
+
+# Table of Contents
+
+* [Introduction](#introduction "Introduction")
+* [Object](#object "Object")
+  * [clone](#cloneobj "clone")
+  * [merge](#mergetarget-source-isnulloverride-ismergearrays "merge")
+  * [applyToDefaults](#applytodefaultsdefaults-options "applyToDefaults")
+  * [unique](#uniquearray-key "unique")
+  * [mapToObject](#maptoobjectarray-key "mapToObject")
+  * [intersect](#intersectarray1-array2 "intersect")
+  * [matchKeys](#matchkeysobj-keys "matchKeys")
+  * [flatten](#flattenarray-target "flatten")
+  * [removeKeys](#removekeysobject-keys "removeKeys")
+  * [reach](#reachobj-chain "reach")
+  * [inheritAsync](#inheritasyncself-obj-keys "inheritAsync")
+  * [rename](#renameobj-from-to "rename")
+* [Timer](#timer "Timer")
+* [Binary Encoding/Decoding](#binary "Binary Encoding/Decoding")
+  * [base64urlEncode](#binary64urlEncodevalue "binary64urlEncode")
+  * [base64urlDecode](#binary64urlDecodevalue "binary64urlDecode")
+* [Escaping Characters](#escaped "Escaping Characters")
+  * [escapeHtml](#escapeHtmlstring "escapeHtml")
+  * [escapeHeaderAttribute](#escapeHeaderAttributeattribute "escapeHeaderAttribute")
+  * [escapeRegex](#escapeRegexstring "escapeRegex")
+* [Errors](#errors "Errors")
+  * [assert](#assertmessage "assert")
+  * [abort](#abortmessage "abort")
+  * [displayStack](#displayStackslice "displayStack")
+  * [callStack](#callStackslice "callStack")
+  * [toss](#tosscondition "toss")
+* [Load files](#load-files "Load Files")
+  * [loadPackage](#loadPackagedir "loadpackage")
+  * [loadDirModules](#loadDirModulespath-excludefiles-target "loaddirmodules")
+
+
+
+# Introduction
+
+The *Hoek* general purpose node utilities library is used to aid in a variety of manners. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more. 
+
+For example, to use Hoek to set configuration with default options:
+```javascript
+var Hoek = require('hoek');
+
+var default = {url : "www.github.com", port : "8000", debug : true}
+
+var config = Hoek.applyToDefaults(default, {port : "3000", admin : true});
+
+// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }
+```
+
+Under each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the var Hoek = require('hoek') is omitted for brevity.
+
+## Object
+
+Hoek provides several helpful methods for objects and arrays.
+
+### clone(obj)
+
+This method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects). 
+
+```javascript
+
+var nestedObj = {
+        w: /^something$/ig,
+        x: {
+            a: [1, 2, 3],
+            b: 123456,
+            c: new Date()
+        },
+        y: 'y',
+        z: new Date()
+    };
+
+var copy = Hoek.clone(nestedObj);
+
+copy.x.b = 100;
+
+console.log(copy.y)        // results in 'y'
+console.log(nestedObj.x.b) // results in 123456
+console.log(copy.x.b)      // results in 100
+```
+
+### merge(target, source, isNullOverride, isMergeArrays)
+isNullOverride, isMergeArrays default to true
+
+Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
+
+
+```javascript
+
+var target = {a: 1, b : 2}
+var source = {a: 0, c: 5}
+var source2 = {a: null, c: 5}
+
+var targetArray = [1, 2, 3];
+var sourceArray = [4, 5];
+
+var newTarget = Hoek.merge(target, source);     // results in {a: 0, b: 2, c: 5}
+newTarget = Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}
+newTarget = Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}
+
+newTarget = Hoek.merge(targetArray, sourceArray)              // results in [1, 2, 3, 4, 5]
+newTarget = Hoek.merge(targetArray, sourceArray, true, false) // results in [4, 5]
+
+
+
+
+```
+
+### applyToDefaults(defaults, options)
+
+Apply options to a copy of the defaults
+
+```javascript
+
+var defaults = {host: "localhost", port: 8000};
+var options = {port: 8080};
+
+var config = Hoek.applyToDefaults(defaults, options); // results in {host: "localhost", port: 8080};
+
+
+```
+
+### unique(array, key)
+
+Remove duplicate items from Array
+
+```javascript
+
+var array = [1, 2, 2, 3, 3, 4, 5, 6];
+
+var newArray = Hoek.unique(array); // results in [1,2,3,4,5,6];
+
+array = [{id: 1}, {id: 1}, {id: 2}];
+
+newArray = Hoek.unique(array, "id") // results in [{id: 1}, {id: 2}]
+
+```
+
+### mapToObject(array, key)
+
+Convert an Array into an Object
+
+```javascript
+
+var array = [1,2,3];
+var newObject = Hoek.mapToObject(array); // results in [{"1": true}, {"2": true}, {"3": true}]
+
+array = [{id: 1}, {id: 2}];
+newObject = Hoek.mapToObject(array, "id") // results in [{"id": 1}, {"id": 2}]
+
+```
+### intersect(array1, array2)
+
+Find the common unique items in two arrays
+
+```javascript
+
+var array1 = [1, 2, 3];
+var array2 = [1, 4, 5];
+
+var newArray = Hoek.intersect(array1, array2) // results in [1]
+
+```
+
+### matchKeys(obj, keys) 
+
+Find which keys are present
+
+```javascript
+
+var obj = {a: 1, b: 2, c: 3};
+var keys = ["a", "e"];
+
+Hoek.matchKeys(obj, keys) // returns ["a"]
+
+```
+
+### flatten(array, target)
+
+Flatten an array
+
+```javascript
+
+var array = [1, 2, 3];
+var target = [4, 5]; 
+
+var flattenedArray = Hoek.flatten(array, target) // results in [4, 5, 1, 2, 3];
+
+```
+
+### removeKeys(object, keys)
+
+Remove keys
+
+```javascript
+
+var object = {a: 1, b: 2, c: 3, d: 4};
+
+var keys = ["a", "b"];
+
+Hoek.removeKeys(object, keys) // object is now {c: 3, d: 4}
+
+```
+
+### reach(obj, chain)
+
+Converts an object key chain string to reference
+
+```javascript
+
+var chain = 'a.b.c';
+var obj = {a : {b : { c : 1}}};
+
+Hoek.reach(obj, chain) // returns 1
+
+```
+
+### inheritAsync(self, obj, keys) 
+
+Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
+
+```javascript
+
+var targetFunc = function () { };
+
+var proto = {
+                a: function () {
+                    return 'a!';
+                },
+                b: function () {
+                    return 'b!';
+                },
+                c: function () {
+                    throw new Error('c!');
+                }
+            };
+
+var keys = ['a', 'c'];
+
+Hoek.inheritAsync(targetFunc, proto, ['a', 'c']);
+
+var target = new targetFunc();
+
+target.a(function(err, result){console.log(result)}         // returns 'a!'       
+
+target.c(function(err, result){console.log(result)}         // returns undefined
+
+target.b(function(err, result){console.log(result)}         // gives error: Object [object Object] has no method 'b'
+
+```
+
+### rename(obj, from, to)
+
+Rename a key of an object
+
+```javascript
+
+var obj = {a : 1, b : 2};
+
+Hoek.rename(obj, "a", "c");     // obj is now {c : 1, b : 2}
+
+```
+
+
+# Timer
+
+A Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
+
+```javascript
+
+
+example : 
+
+
+var timerObj = new Hoek.Timer();
+console.log("Time is now: " + timerObj.ts)
+console.log("Elapsed time from initialization: " + timerObj.elapsed() + 'milliseconds')
+
+```
+
+# Binary Encoding/Decoding
+
+### base64urlEncode(value)
+
+Encodes value in Base64 or URL encoding
+
+### base64urlDecode(value)
+
+Decodes data in Base64 or URL encoding.
+# Escaping Characters
+
+Hoek provides convenient methods for escaping html characters. The escaped characters are as followed:
+
+```javascript
+
+internals.htmlEscaped = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#x27;',
+    '`': '&#x60;'
+};
+
+```
+
+### escapeHtml(string)
+
+```javascript
+
+var string = '<html> hey </html>';
+var escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;
+
+```
+
+### escapeHeaderAttribute(attribute)
+
+Escape attribute value for use in HTTP header
+
+```javascript
+
+var a = Hoek.escapeHeaderAttribute('I said "go w\\o me"');  //returns I said \"go w\\o me\"
+
+
+```
+
+
+### escapeRegex(string)
+
+Escape string for Regex construction
+
+```javascript
+
+var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');  // returns 4\^f\$s\.4\*5\+\-_\?%\=#\!\:@\|~\\\/`"\(>\)\[<\]d\{\}s\,
+
+
+
+```
+
+# Errors
+
+### assert(message)
+
+```javascript
+
+var a = 1, b =2;
+
+Hoek.assert(a === b, 'a should equal b');  // ABORT: a should equal b
+
+```
+
+### abort(message)
+
+First checks if process.env.NODE_ENV === 'test', and if so, throws error message. Otherwise,
+displays most recent stack and then exits process.
+
+
+
+### displayStack(slice)
+
+Displays the trace stack
+
+```javascript
+
+var stack = Hoek.displayStack();
+console.log(stack) // returns something like:
+
+[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',
+  'Module._compile (module.js:449:26)',
+  'Module._extensions..js (module.js:467:10)',
+  'Module.load (module.js:356:32)',
+  'Module._load (module.js:312:12)',
+  'Module.runMain (module.js:492:10)',
+  'startup.processNextTick.process._tickCallback (node.js:244:9)' ]
+
+```
+
+### callStack(slice)
+
+Returns a trace stack array.
+
+```javascript
+
+var stack = Hoek.callStack();
+console.log(stack)  // returns something like:
+
+[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],
+  [ 'module.js', 449, 26, 'Module._compile', false ],
+  [ 'module.js', 467, 10, 'Module._extensions..js', false ],
+  [ 'module.js', 356, 32, 'Module.load', false ],
+  [ 'module.js', 312, 12, 'Module._load', false ],
+  [ 'module.js', 492, 10, 'Module.runMain', false ],
+  [ 'node.js',
+    244,
+    9,
+    'startup.processNextTick.process._tickCallback',
+    false ] ]
+
+
+```
+
+### toss(condition)
+
+toss(condition /*, [message], callback */)
+
+Return an error as first argument of a callback
+
+
+# Load Files
+
+### loadPackage(dir)
+
+Load and parse package.json process root or given directory
+
+```javascript
+
+var pack = Hoek.loadPackage();  // pack.name === 'hoek'
+
+```
+
+### loadDirModules(path, excludeFiles, target) 
+
+Loads modules from a given path; option to exclude files (array).
+
+
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/index.js	(revision 484)
@@ -0,0 +1,1 @@
+module.exports = require('./lib');
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/lib/escape.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/lib/escape.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/lib/escape.js	(revision 484)
@@ -0,0 +1,132 @@
+// Declare internals
+
+var internals = {};
+
+
+exports.escapeJavaScript = function (input) {
+
+    if (!input) {
+        return '';
+    }
+
+    var escaped = '';
+
+    for (var i = 0, il = input.length; i < il; ++i) {
+
+        var charCode = input.charCodeAt(i);
+
+        if (internals.isSafe(charCode)) {
+            escaped += input[i];
+        }
+        else {
+            escaped += internals.escapeJavaScriptChar(charCode);
+        }
+    }
+
+    return escaped;
+};
+
+
+exports.escapeHtml = function (input) {
+
+    if (!input) {
+        return '';
+    }
+
+    var escaped = '';
+
+    for (var i = 0, il = input.length; i < il; ++i) {
+
+        var charCode = input.charCodeAt(i);
+
+        if (internals.isSafe(charCode)) {
+            escaped += input[i];
+        }
+        else {
+            escaped += internals.escapeHtmlChar(charCode);
+        }
+    }
+
+    return escaped;
+};
+
+
+internals.escapeJavaScriptChar = function (charCode) {
+
+    if (charCode >= 256) {
+        return '\\u' + internals.padLeft('' + charCode, 4);
+    }
+
+    var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
+    return '\\x' + internals.padLeft(hexValue, 2);
+};
+
+
+internals.escapeHtmlChar = function (charCode) {
+
+    var namedEscape = internals.namedHtml[charCode];
+    if (typeof namedEscape !== 'undefined') {
+        return namedEscape;
+    }
+
+    if (charCode >= 256) {
+        return '&#' + charCode + ';';
+    }
+
+    var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
+    return '&#x' + internals.padLeft(hexValue, 2) + ';';
+};
+
+
+internals.padLeft = function (str, len) {
+
+    while (str.length < len) {
+        str = '0' + str;
+    }
+
+    return str;
+};
+
+
+internals.isSafe = function (charCode) {
+
+    return (typeof internals.safeCharCodes[charCode] !== 'undefined');
+};
+
+
+internals.namedHtml = {
+    '38': '&amp;',
+    '60': '&lt;',
+    '62': '&gt;',
+    '34': '&quot;',
+    '160': '&nbsp;',
+    '162': '&cent;',
+    '163': '&pound;',
+    '164': '&curren;',
+    '169': '&copy;',
+    '174': '&reg;'
+};
+
+
+internals.safeCharCodes = (function () {
+
+    var safe = {};
+
+    for (var i = 32; i < 123; ++i) {
+
+        if ((i >= 97 && i <= 122) ||         // a-z
+            (i >= 65 && i <= 90) ||          // A-Z
+            (i >= 48 && i <= 57) ||          // 0-9
+            i === 32 ||                      // space
+            i === 46 ||                      // .
+            i === 44 ||                      // ,
+            i === 45 ||                      // -
+            i === 58 ||                      // :
+            i === 95) {                      // _
+
+            safe[i] = null;
+        }
+    }
+
+    return safe;
+}());
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/lib/index.js	(revision 484)
@@ -0,0 +1,585 @@
+// Load modules
+
+var Fs = require('fs');
+var Escape = require('./escape');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Clone object or array
+
+exports.clone = function (obj, seen) {
+
+    if (typeof obj !== 'object' ||
+        obj === null) {
+
+        return obj;
+    }
+
+    seen = seen || { orig: [], copy: [] };
+
+    var lookup = seen.orig.indexOf(obj);
+    if (lookup !== -1) {
+        return seen.copy[lookup];
+    }
+
+    var newObj = (obj instanceof Array) ? [] : {};
+
+    seen.orig.push(obj);
+    seen.copy.push(newObj);
+
+    for (var i in obj) {
+        if (obj.hasOwnProperty(i)) {
+            if (obj[i] instanceof Buffer) {
+                newObj[i] = new Buffer(obj[i]);
+            }
+            else if (obj[i] instanceof Date) {
+                newObj[i] = new Date(obj[i].getTime());
+            }
+            else if (obj[i] instanceof RegExp) {
+                var flags = '' + (obj[i].global ? 'g' : '') + (obj[i].ignoreCase ? 'i' : '') + (obj[i].multiline ? 'm' : '');
+                newObj[i] = new RegExp(obj[i].source, flags);
+            }
+            else {
+                newObj[i] = exports.clone(obj[i], seen);
+            }
+        }
+    }
+
+    return newObj;
+};
+
+
+// Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
+
+exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {
+
+    exports.assert(target && typeof target == 'object', 'Invalid target value: must be an object');
+    exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');
+
+    if (!source) {
+        return target;
+    }
+
+    if (source instanceof Array) {
+        exports.assert(target instanceof Array, 'Cannot merge array onto an object');
+        if (isMergeArrays === false) {                                                  // isMergeArrays defaults to true
+            target.length = 0;                                                          // Must not change target assignment
+        }
+
+        for (var i = 0, il = source.length; i < il; ++i) {
+            target.push(source[i]);
+        }
+
+        return target;
+    }
+
+    var keys = Object.keys(source);
+    for (var k = 0, kl = keys.length; k < kl; ++k) {
+        var key = keys[k];
+        var value = source[key];
+        if (value &&
+            typeof value === 'object') {
+
+            if (!target[key] ||
+                typeof target[key] !== 'object') {
+
+                target[key] = exports.clone(value);
+            }
+            else {
+                exports.merge(target[key], source[key], isNullOverride, isMergeArrays);
+            }
+        }
+        else {
+            if (value !== null && value !== undefined) {            // Explicit to preserve empty strings
+                target[key] = value;
+            }
+            else if (isNullOverride !== false) {                    // Defaults to true
+                target[key] = value;
+            }
+        }
+    }
+
+    return target;
+};
+
+
+// Apply options to a copy of the defaults
+
+exports.applyToDefaults = function (defaults, options) {
+
+    exports.assert(defaults && typeof defaults == 'object', 'Invalid defaults value: must be an object');
+    exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
+
+    if (!options) {                                                 // If no options, return null
+        return null;
+    }
+
+    var copy = exports.clone(defaults);
+
+    if (options === true) {                                         // If options is set to true, use defaults
+        return copy;
+    }
+
+    return exports.merge(copy, options, false, false);
+};
+
+
+// Remove duplicate items from array
+
+exports.unique = function (array, key) {
+
+    var index = {};
+    var result = [];
+
+    for (var i = 0, il = array.length; i < il; ++i) {
+        var id = (key ? array[i][key] : array[i]);
+        if (index[id] !== true) {
+
+            result.push(array[i]);
+            index[id] = true;
+        }
+    }
+
+    return result;
+};
+
+
+// Convert array into object
+
+exports.mapToObject = function (array, key) {
+
+    if (!array) {
+        return null;
+    }
+
+    var obj = {};
+    for (var i = 0, il = array.length; i < il; ++i) {
+        if (key) {
+            if (array[i][key]) {
+                obj[array[i][key]] = true;
+            }
+        }
+        else {
+            obj[array[i]] = true;
+        }
+    }
+
+    return obj;
+};
+
+
+// Find the common unique items in two arrays
+
+exports.intersect = function (array1, array2, justFirst) {
+
+    if (!array1 || !array2) {
+        return [];
+    }
+
+    var common = [];
+    var hash = (array1 instanceof Array ? exports.mapToObject(array1) : array1);
+    var found = {};
+    for (var i = 0, il = array2.length; i < il; ++i) {
+        if (hash[array2[i]] && !found[array2[i]]) {
+            if (justFirst) {
+                return array2[i];
+            }
+
+            common.push(array2[i]);
+            found[array2[i]] = true;
+        }
+    }
+
+    return (justFirst ? null : common);
+};
+
+
+// Find which keys are present
+
+exports.matchKeys = function (obj, keys) {
+
+    var matched = [];
+    for (var i = 0, il = keys.length; i < il; ++i) {
+        if (obj.hasOwnProperty(keys[i])) {
+            matched.push(keys[i]);
+        }
+    }
+    return matched;
+};
+
+
+// Flatten array
+
+exports.flatten = function (array, target) {
+
+    var result = target || [];
+
+    for (var i = 0, il = array.length; i < il; ++i) {
+        if (Array.isArray(array[i])) {
+            exports.flatten(array[i], result);
+        }
+        else {
+            result.push(array[i]);
+        }
+    }
+
+    return result;
+};
+
+
+// Remove keys
+
+exports.removeKeys = function (object, keys) {
+
+    for (var i = 0, il = keys.length; i < il; i++) {
+        delete object[keys[i]];
+    }
+};
+
+
+// Convert an object key chain string ('a.b.c') to reference (object[a][b][c])
+
+exports.reach = function (obj, chain) {
+
+    var path = chain.split('.');
+    var ref = obj;
+    for (var i = 0, il = path.length; i < il; ++i) {
+        if (ref) {
+            ref = ref[path[i]];
+        }
+    }
+
+    return ref;
+};
+
+
+// Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
+
+exports.inheritAsync = function (self, obj, keys) {
+
+    keys = keys || null;
+
+    for (var i in obj) {
+        if (obj.hasOwnProperty(i)) {
+            if (keys instanceof Array &&
+                keys.indexOf(i) < 0) {
+
+                continue;
+            }
+
+            self.prototype[i] = (function (fn) {
+
+                return function (next) {
+
+                    var result = null;
+                    try {
+                        result = fn();
+                    }
+                    catch (err) {
+                        return next(err);
+                    }
+
+                    return next(null, result);
+                };
+            })(obj[i]);
+        }
+    }
+};
+
+
+exports.formatStack = function (stack) {
+
+    var trace = [];
+    for (var i = 0, il = stack.length; i < il; ++i) {
+        var item = stack[i];
+        trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
+    }
+
+    return trace;
+};
+
+
+exports.formatTrace = function (trace) {
+
+    var display = [];
+
+    for (var i = 0, il = trace.length; i < il; ++i) {
+        var row = trace[i];
+        display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
+    }
+
+    return display;
+};
+
+
+exports.callStack = function (slice) {
+
+    // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
+
+    var v8 = Error.prepareStackTrace;
+    Error.prepareStackTrace = function (err, stack) {
+
+        return stack;
+    };
+
+    var capture = {};
+    Error.captureStackTrace(capture, arguments.callee);
+    var stack = capture.stack;
+
+    Error.prepareStackTrace = v8;
+
+    var trace = exports.formatStack(stack);
+
+    if (slice) {
+        return trace.slice(slice);
+    }
+
+    return trace;
+};
+
+
+exports.displayStack = function (slice) {
+
+    var trace = exports.callStack(slice === undefined ? 1 : slice + 1);
+
+    return exports.formatTrace(trace);
+};
+
+
+exports.abortThrow = false;
+
+
+exports.abort = function (message, hideStack) {
+
+    if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
+        throw new Error(message || 'Unknown error');
+    }
+
+    var stack = '';
+    if (!hideStack) {
+        stack = exports.displayStack(1).join('\n\t');
+    }
+    console.log('ABORT: ' + message + '\n\t' + stack);
+    process.exit(1);
+};
+
+
+exports.assert = function (condition /*, msg1, msg2, msg3 */) {
+
+    if (condition) {
+        return;
+    }
+
+    var msgs = Array.prototype.slice.call(arguments, 1);
+    msgs = msgs.map(function (msg) {
+
+        return typeof msg === 'string' ? msg : msg instanceof Error ? msg.message : JSON.stringify(msg);
+    });
+    throw new Error(msgs.join(' ') || 'Unknown error');
+};
+
+
+exports.loadDirModules = function (path, excludeFiles, target) {      // target(filename, name, capName)
+
+    var exclude = {};
+    for (var i = 0, il = excludeFiles.length; i < il; ++i) {
+        exclude[excludeFiles[i] + '.js'] = true;
+    }
+
+    var files = Fs.readdirSync(path);
+    for (i = 0, il = files.length; i < il; ++i) {
+        var filename = files[i];
+        if (/\.js$/.test(filename) &&
+            !exclude[filename]) {
+
+            var name = filename.substr(0, filename.lastIndexOf('.'));
+            var capName = name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();
+
+            if (typeof target !== 'function') {
+                target[capName] = require(path + '/' + name);
+            }
+            else {
+                target(path + '/' + name, name, capName);
+            }
+        }
+    }
+};
+
+
+exports.rename = function (obj, from, to) {
+
+    obj[to] = obj[from];
+    delete obj[from];
+};
+
+
+exports.Timer = function () {
+
+    this.reset();
+};
+
+
+exports.Timer.prototype.reset = function () {
+
+    this.ts = Date.now();
+};
+
+
+exports.Timer.prototype.elapsed = function () {
+
+    return Date.now() - this.ts;
+};
+
+
+// Load and parse package.json process root or given directory
+
+exports.loadPackage = function (dir) {
+
+    var result = {};
+    var filepath = (dir || process.env.PWD) + '/package.json';
+    if (Fs.existsSync(filepath)) {
+        try {
+            result = JSON.parse(Fs.readFileSync(filepath));
+        }
+        catch (e) { }
+    }
+
+    return result;
+};
+
+
+// Escape string for Regex construction
+
+exports.escapeRegex = function (string) {
+
+    // Escape ^$.*+-?=!:|\/()[]{},
+    return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
+};
+
+
+// Return an error as first argument of a callback
+
+exports.toss = function (condition /*, [message], next */) {
+
+    var message = (arguments.length === 3 ? arguments[1] : '');
+    var next = (arguments.length === 3 ? arguments[2] : arguments[1]);
+
+    var err = (message instanceof Error ? message : (message ? new Error(message) : (condition instanceof Error ? condition : new Error())));
+
+    if (condition instanceof Error ||
+        !condition) {
+
+        return next(err);
+    }
+};
+
+
+// Base64url (RFC 4648) encode
+
+exports.base64urlEncode = function (value) {
+
+    return (new Buffer(value, 'binary')).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
+};
+
+
+// Base64url (RFC 4648) decode
+
+exports.base64urlDecode = function (encoded) {
+
+    if (encoded &&
+        !encoded.match(/^[\w\-]*$/)) {
+
+        return new Error('Invalid character');
+    }
+
+    try {
+        return (new Buffer(encoded.replace(/-/g, '+').replace(/:/g, '/'), 'base64')).toString('binary');
+    }
+    catch (err) {
+        return err;
+    }
+};
+
+
+// Escape attribute value for use in HTTP header
+
+exports.escapeHeaderAttribute = function (attribute) {
+
+    // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "
+
+    exports.assert(attribute.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/), 'Bad attribute value (' + attribute + ')');
+
+    return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"');                             // Escape quotes and slash
+};
+
+
+exports.escapeHtml = function (string) {
+
+    return Escape.escapeHtml(string);
+};
+
+
+exports.escapeJavaScript = function (string) {
+
+    return Escape.escapeJavaScript(string);
+};
+
+
+/*
+var event = {
+    timestamp: now.getTime(),
+    tags: ['tag'],
+    data: { some: 'data' }
+};
+*/
+
+exports.consoleFunc = console.log;
+
+exports.printEvent = function (event) {
+
+    var pad = function (value) {
+
+        return (value < 10 ? '0' : '') + value;
+    };
+
+    var now = new Date(event.timestamp);
+    var timestring = (now.getYear() - 100).toString() +
+        pad(now.getMonth() + 1) +
+        pad(now.getDate()) +
+        '/' +
+        pad(now.getHours()) +
+        pad(now.getMinutes()) +
+        pad(now.getSeconds()) +
+        '.' +
+        now.getMilliseconds();
+
+    var data = event.data;
+    if (typeof event.data !== 'string') {
+        try {
+            data = JSON.stringify(event.data);
+        }
+        catch (e) {
+            data = 'JSON Error: ' + e.message;
+        }
+    }
+
+    var output = timestring + ', ' + event.tags[0] + ', ' + data;
+    exports.consoleFunc(output);
+};
+
+
+exports.nextTick = function (callback) {
+
+    return function () {
+
+        var args = arguments;
+        process.nextTick(function () {
+
+            callback.apply(null, args);
+        });
+    };
+};
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/package.json	(revision 484)
@@ -0,0 +1,49 @@
+{
+  "name": "hoek",
+  "description": "General purpose node utilities",
+  "version": "0.9.1",
+  "author": {
+    "name": "Eran Hammer",
+    "email": "eran@hueniverse.com",
+    "url": "http://hueniverse.com"
+  },
+  "contributors": [
+    {
+      "name": "Van Nguyen",
+      "email": "the.gol.effect@gmail.com"
+    }
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/spumko/hoek"
+  },
+  "main": "index",
+  "keywords": [
+    "utilities"
+  ],
+  "engines": {
+    "node": ">=0.8.0"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "lab": "0.1.x",
+    "complexity-report": "0.x.x"
+  },
+  "scripts": {
+    "test": "make test-cov"
+  },
+  "licenses": [
+    {
+      "type": "BSD",
+      "url": "http://github.com/spumko/hoek/raw/master/LICENSE"
+    }
+  ],
+  "readme": "<a href=\"https://github.com/spumko\"><img src=\"https://raw.github.com/spumko/spumko/master/images/from.png\" align=\"right\" /></a>\r\n![hoek Logo](https://raw.github.com/spumko/hoek/master/images/hoek.png)\r\n\r\nGeneral purpose node utilities\r\n\r\n[![Build Status](https://secure.travis-ci.org/spumko/hoek.png)](http://travis-ci.org/spumko/hoek)\r\n\r\n# Table of Contents\r\n\r\n* [Introduction](#introduction \"Introduction\")\r\n* [Object](#object \"Object\")\r\n  * [clone](#cloneobj \"clone\")\r\n  * [merge](#mergetarget-source-isnulloverride-ismergearrays \"merge\")\r\n  * [applyToDefaults](#applytodefaultsdefaults-options \"applyToDefaults\")\r\n  * [unique](#uniquearray-key \"unique\")\r\n  * [mapToObject](#maptoobjectarray-key \"mapToObject\")\r\n  * [intersect](#intersectarray1-array2 \"intersect\")\r\n  * [matchKeys](#matchkeysobj-keys \"matchKeys\")\r\n  * [flatten](#flattenarray-target \"flatten\")\r\n  * [removeKeys](#removekeysobject-keys \"removeKeys\")\r\n  * [reach](#reachobj-chain \"reach\")\r\n  * [inheritAsync](#inheritasyncself-obj-keys \"inheritAsync\")\r\n  * [rename](#renameobj-from-to \"rename\")\r\n* [Timer](#timer \"Timer\")\r\n* [Binary Encoding/Decoding](#binary \"Binary Encoding/Decoding\")\r\n  * [base64urlEncode](#binary64urlEncodevalue \"binary64urlEncode\")\r\n  * [base64urlDecode](#binary64urlDecodevalue \"binary64urlDecode\")\r\n* [Escaping Characters](#escaped \"Escaping Characters\")\r\n  * [escapeHtml](#escapeHtmlstring \"escapeHtml\")\r\n  * [escapeHeaderAttribute](#escapeHeaderAttributeattribute \"escapeHeaderAttribute\")\r\n  * [escapeRegex](#escapeRegexstring \"escapeRegex\")\r\n* [Errors](#errors \"Errors\")\r\n  * [assert](#assertmessage \"assert\")\r\n  * [abort](#abortmessage \"abort\")\r\n  * [displayStack](#displayStackslice \"displayStack\")\r\n  * [callStack](#callStackslice \"callStack\")\r\n  * [toss](#tosscondition \"toss\")\r\n* [Load files](#load-files \"Load Files\")\r\n  * [loadPackage](#loadPackagedir \"loadpackage\")\r\n  * [loadDirModules](#loadDirModulespath-excludefiles-target \"loaddirmodules\")\r\n\r\n\r\n\r\n# Introduction\r\n\r\nThe *Hoek* general purpose node utilities library is used to aid in a variety of manners. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more. \r\n\r\nFor example, to use Hoek to set configuration with default options:\r\n```javascript\r\nvar Hoek = require('hoek');\r\n\r\nvar default = {url : \"www.github.com\", port : \"8000\", debug : true}\r\n\r\nvar config = Hoek.applyToDefaults(default, {port : \"3000\", admin : true});\r\n\r\n// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }\r\n```\r\n\r\nUnder each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the var Hoek = require('hoek') is omitted for brevity.\r\n\r\n## Object\r\n\r\nHoek provides several helpful methods for objects and arrays.\r\n\r\n### clone(obj)\r\n\r\nThis method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects). \r\n\r\n```javascript\r\n\r\nvar nestedObj = {\r\n        w: /^something$/ig,\r\n        x: {\r\n            a: [1, 2, 3],\r\n            b: 123456,\r\n            c: new Date()\r\n        },\r\n        y: 'y',\r\n        z: new Date()\r\n    };\r\n\r\nvar copy = Hoek.clone(nestedObj);\r\n\r\ncopy.x.b = 100;\r\n\r\nconsole.log(copy.y)        // results in 'y'\r\nconsole.log(nestedObj.x.b) // results in 123456\r\nconsole.log(copy.x.b)      // results in 100\r\n```\r\n\r\n### merge(target, source, isNullOverride, isMergeArrays)\r\nisNullOverride, isMergeArrays default to true\r\n\r\nMerge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied\r\n\r\n\r\n```javascript\r\n\r\nvar target = {a: 1, b : 2}\r\nvar source = {a: 0, c: 5}\r\nvar source2 = {a: null, c: 5}\r\n\r\nvar targetArray = [1, 2, 3];\r\nvar sourceArray = [4, 5];\r\n\r\nvar newTarget = Hoek.merge(target, source);     // results in {a: 0, b: 2, c: 5}\r\nnewTarget = Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}\r\nnewTarget = Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}\r\n\r\nnewTarget = Hoek.merge(targetArray, sourceArray)              // results in [1, 2, 3, 4, 5]\r\nnewTarget = Hoek.merge(targetArray, sourceArray, true, false) // results in [4, 5]\r\n\r\n\r\n\r\n\r\n```\r\n\r\n### applyToDefaults(defaults, options)\r\n\r\nApply options to a copy of the defaults\r\n\r\n```javascript\r\n\r\nvar defaults = {host: \"localhost\", port: 8000};\r\nvar options = {port: 8080};\r\n\r\nvar config = Hoek.applyToDefaults(defaults, options); // results in {host: \"localhost\", port: 8080};\r\n\r\n\r\n```\r\n\r\n### unique(array, key)\r\n\r\nRemove duplicate items from Array\r\n\r\n```javascript\r\n\r\nvar array = [1, 2, 2, 3, 3, 4, 5, 6];\r\n\r\nvar newArray = Hoek.unique(array); // results in [1,2,3,4,5,6];\r\n\r\narray = [{id: 1}, {id: 1}, {id: 2}];\r\n\r\nnewArray = Hoek.unique(array, \"id\") // results in [{id: 1}, {id: 2}]\r\n\r\n```\r\n\r\n### mapToObject(array, key)\r\n\r\nConvert an Array into an Object\r\n\r\n```javascript\r\n\r\nvar array = [1,2,3];\r\nvar newObject = Hoek.mapToObject(array); // results in [{\"1\": true}, {\"2\": true}, {\"3\": true}]\r\n\r\narray = [{id: 1}, {id: 2}];\r\nnewObject = Hoek.mapToObject(array, \"id\") // results in [{\"id\": 1}, {\"id\": 2}]\r\n\r\n```\r\n### intersect(array1, array2)\r\n\r\nFind the common unique items in two arrays\r\n\r\n```javascript\r\n\r\nvar array1 = [1, 2, 3];\r\nvar array2 = [1, 4, 5];\r\n\r\nvar newArray = Hoek.intersect(array1, array2) // results in [1]\r\n\r\n```\r\n\r\n### matchKeys(obj, keys) \r\n\r\nFind which keys are present\r\n\r\n```javascript\r\n\r\nvar obj = {a: 1, b: 2, c: 3};\r\nvar keys = [\"a\", \"e\"];\r\n\r\nHoek.matchKeys(obj, keys) // returns [\"a\"]\r\n\r\n```\r\n\r\n### flatten(array, target)\r\n\r\nFlatten an array\r\n\r\n```javascript\r\n\r\nvar array = [1, 2, 3];\r\nvar target = [4, 5]; \r\n\r\nvar flattenedArray = Hoek.flatten(array, target) // results in [4, 5, 1, 2, 3];\r\n\r\n```\r\n\r\n### removeKeys(object, keys)\r\n\r\nRemove keys\r\n\r\n```javascript\r\n\r\nvar object = {a: 1, b: 2, c: 3, d: 4};\r\n\r\nvar keys = [\"a\", \"b\"];\r\n\r\nHoek.removeKeys(object, keys) // object is now {c: 3, d: 4}\r\n\r\n```\r\n\r\n### reach(obj, chain)\r\n\r\nConverts an object key chain string to reference\r\n\r\n```javascript\r\n\r\nvar chain = 'a.b.c';\r\nvar obj = {a : {b : { c : 1}}};\r\n\r\nHoek.reach(obj, chain) // returns 1\r\n\r\n```\r\n\r\n### inheritAsync(self, obj, keys) \r\n\r\nInherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors\r\n\r\n```javascript\r\n\r\nvar targetFunc = function () { };\r\n\r\nvar proto = {\r\n                a: function () {\r\n                    return 'a!';\r\n                },\r\n                b: function () {\r\n                    return 'b!';\r\n                },\r\n                c: function () {\r\n                    throw new Error('c!');\r\n                }\r\n            };\r\n\r\nvar keys = ['a', 'c'];\r\n\r\nHoek.inheritAsync(targetFunc, proto, ['a', 'c']);\r\n\r\nvar target = new targetFunc();\r\n\r\ntarget.a(function(err, result){console.log(result)}         // returns 'a!'       \r\n\r\ntarget.c(function(err, result){console.log(result)}         // returns undefined\r\n\r\ntarget.b(function(err, result){console.log(result)}         // gives error: Object [object Object] has no method 'b'\r\n\r\n```\r\n\r\n### rename(obj, from, to)\r\n\r\nRename a key of an object\r\n\r\n```javascript\r\n\r\nvar obj = {a : 1, b : 2};\r\n\r\nHoek.rename(obj, \"a\", \"c\");     // obj is now {c : 1, b : 2}\r\n\r\n```\r\n\r\n\r\n# Timer\r\n\r\nA Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.\r\n\r\n```javascript\r\n\r\n\r\nexample : \r\n\r\n\r\nvar timerObj = new Hoek.Timer();\r\nconsole.log(\"Time is now: \" + timerObj.ts)\r\nconsole.log(\"Elapsed time from initialization: \" + timerObj.elapsed() + 'milliseconds')\r\n\r\n```\r\n\r\n# Binary Encoding/Decoding\r\n\r\n### base64urlEncode(value)\r\n\r\nEncodes value in Base64 or URL encoding\r\n\r\n### base64urlDecode(value)\r\n\r\nDecodes data in Base64 or URL encoding.\r\n# Escaping Characters\r\n\r\nHoek provides convenient methods for escaping html characters. The escaped characters are as followed:\r\n\r\n```javascript\r\n\r\ninternals.htmlEscaped = {\r\n    '&': '&amp;',\r\n    '<': '&lt;',\r\n    '>': '&gt;',\r\n    '\"': '&quot;',\r\n    \"'\": '&#x27;',\r\n    '`': '&#x60;'\r\n};\r\n\r\n```\r\n\r\n### escapeHtml(string)\r\n\r\n```javascript\r\n\r\nvar string = '<html> hey </html>';\r\nvar escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;\r\n\r\n```\r\n\r\n### escapeHeaderAttribute(attribute)\r\n\r\nEscape attribute value for use in HTTP header\r\n\r\n```javascript\r\n\r\nvar a = Hoek.escapeHeaderAttribute('I said \"go w\\\\o me\"');  //returns I said \\\"go w\\\\o me\\\"\r\n\r\n\r\n```\r\n\r\n\r\n### escapeRegex(string)\r\n\r\nEscape string for Regex construction\r\n\r\n```javascript\r\n\r\nvar a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\\\/`\"(>)[<]d{}s,');  // returns 4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`\"\\(>\\)\\[<\\]d\\{\\}s\\,\r\n\r\n\r\n\r\n```\r\n\r\n# Errors\r\n\r\n### assert(message)\r\n\r\n```javascript\r\n\r\nvar a = 1, b =2;\r\n\r\nHoek.assert(a === b, 'a should equal b');  // ABORT: a should equal b\r\n\r\n```\r\n\r\n### abort(message)\r\n\r\nFirst checks if process.env.NODE_ENV === 'test', and if so, throws error message. Otherwise,\r\ndisplays most recent stack and then exits process.\r\n\r\n\r\n\r\n### displayStack(slice)\r\n\r\nDisplays the trace stack\r\n\r\n```javascript\r\n\r\nvar stack = Hoek.displayStack();\r\nconsole.log(stack) // returns something like:\r\n\r\n[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',\r\n  'Module._compile (module.js:449:26)',\r\n  'Module._extensions..js (module.js:467:10)',\r\n  'Module.load (module.js:356:32)',\r\n  'Module._load (module.js:312:12)',\r\n  'Module.runMain (module.js:492:10)',\r\n  'startup.processNextTick.process._tickCallback (node.js:244:9)' ]\r\n\r\n```\r\n\r\n### callStack(slice)\r\n\r\nReturns a trace stack array.\r\n\r\n```javascript\r\n\r\nvar stack = Hoek.callStack();\r\nconsole.log(stack)  // returns something like:\r\n\r\n[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],\r\n  [ 'module.js', 449, 26, 'Module._compile', false ],\r\n  [ 'module.js', 467, 10, 'Module._extensions..js', false ],\r\n  [ 'module.js', 356, 32, 'Module.load', false ],\r\n  [ 'module.js', 312, 12, 'Module._load', false ],\r\n  [ 'module.js', 492, 10, 'Module.runMain', false ],\r\n  [ 'node.js',\r\n    244,\r\n    9,\r\n    'startup.processNextTick.process._tickCallback',\r\n    false ] ]\r\n\r\n\r\n```\r\n\r\n### toss(condition)\r\n\r\ntoss(condition /*, [message], callback */)\r\n\r\nReturn an error as first argument of a callback\r\n\r\n\r\n# Load Files\r\n\r\n### loadPackage(dir)\r\n\r\nLoad and parse package.json process root or given directory\r\n\r\n```javascript\r\n\r\nvar pack = Hoek.loadPackage();  // pack.name === 'hoek'\r\n\r\n```\r\n\r\n### loadDirModules(path, excludeFiles, target) \r\n\r\nLoads modules from a given path; option to exclude files (array).\r\n\r\n\r\n\r\n\r\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/spumko/hoek/issues"
+  },
+  "homepage": "https://github.com/spumko/hoek",
+  "_id": "hoek@0.9.1",
+  "_from": "hoek@0.9.x"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/escaper.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/escaper.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/escaper.js	(revision 484)
@@ -0,0 +1,86 @@
+// Load modules
+
+var Lab = require('lab');
+var Hoek = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hoek', function () {
+
+    describe('#escapeJavaScript', function () {
+
+        it('encodes / characters', function (done) {
+
+            var encoded = Hoek.escapeJavaScript('<script>alert(1)</script>');
+            expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e');
+            done();
+        });
+
+        it('encodes \' characters', function (done) {
+
+            var encoded = Hoek.escapeJavaScript('something(\'param\')');
+            expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29');
+            done();
+        });
+
+        it('encodes large unicode characters with the correct padding', function (done) {
+
+            var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000));
+            expect(encoded).to.equal('\\u0500\\u1000');
+            done();
+        });
+
+        it('doesn\'t throw an exception when passed null', function (done) {
+
+            var encoded = Hoek.escapeJavaScript(null);
+            expect(encoded).to.equal('');
+            done();
+        });
+    });
+
+    describe('#escapeHtml', function () {
+
+        it('encodes / characters', function (done) {
+
+            var encoded = Hoek.escapeHtml('<script>alert(1)</script>');
+            expect(encoded).to.equal('&lt;script&gt;alert&#x28;1&#x29;&lt;&#x2f;script&gt;');
+            done();
+        });
+
+        it('encodes < and > as named characters', function (done) {
+
+            var encoded = Hoek.escapeHtml('<script><>');
+            expect(encoded).to.equal('&lt;script&gt;&lt;&gt;');
+            done();
+        });
+
+        it('encodes large unicode characters', function (done) {
+
+            var encoded = Hoek.escapeHtml(String.fromCharCode(500) + String.fromCharCode(1000));
+            expect(encoded).to.equal('&#500;&#1000;');
+            done();
+        });
+
+        it('doesn\'t throw an exception when passed null', function (done) {
+
+            var encoded = Hoek.escapeHtml(null);
+            expect(encoded).to.equal('');
+            done();
+        });
+    });
+});
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/index.js	(revision 484)
@@ -0,0 +1,1078 @@
+// Load modules
+
+var Lab = require('lab');
+var Hoek = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hoek', function () {
+
+    var nestedObj = {
+        v: [7,8,9],
+        w: /^something$/igm,
+        x: {
+            a: [1, 2, 3],
+            b: 123456,
+            c: new Date(),
+            d: /hi/igm,
+            e: /hello/
+        },
+        y: 'y',
+        z: new Date()
+    };
+
+    var dupsArray = [nestedObj, { z: 'z' }, nestedObj];
+    var reducedDupsArray = [nestedObj, { z: 'z' }];
+
+    describe('#clone', function () {
+
+        it('should clone a nested object', function (done) {
+
+            var a = nestedObj;
+            var b = Hoek.clone(a);
+
+            expect(a).to.deep.equal(b);
+            expect(a.z.getTime()).to.equal(b.z.getTime());
+            done();
+        });
+
+        it('should clone a null object', function (done) {
+
+            var b = Hoek.clone(null);
+
+            expect(b).to.equal(null);
+            done();
+        });
+
+        it('should not convert undefined properties to null', function (done) {
+
+            var obj = { something: undefined };
+            var b = Hoek.clone(obj);
+
+            expect(typeof b.something).to.equal('undefined');
+            done();
+        });
+
+        it('should not throw on circular reference', function (done) {
+
+            var a = {};
+            a.x = a;
+
+            var test = (function () {
+
+                var b = Hoek.clone(a);
+            });
+
+            expect(test).to.not.throw();
+            done();
+        });
+
+        it('should properly clone circular reference', function (done) {
+
+            var x = {
+                'z': new Date()
+            };
+            x.y = x;
+
+            var b = Hoek.clone(x);
+            expect(Object.keys(b.y)).to.deep.equal(Object.keys(x))
+            expect(b.z).to.not.equal(x.z);
+            expect(b.y).to.not.equal(x.y);
+            expect(b.y.z).to.not.equal(x.y.z);
+            expect(b.y).to.equal(b);
+            expect(b.y.y.y.y).to.equal(b);
+            done();
+        });
+
+        it('should properly clone deeply nested object', function (done) {
+
+            var a = {
+                x: {
+                    y: {
+                        a: [1, 2, 3],
+                        b: 123456,
+                        c: new Date(),
+                        d: /hi/igm,
+                        e: /hello/
+                    },
+                }
+            };
+
+            var b = Hoek.clone(a);
+
+            expect(a).to.deep.equal(b);
+            expect(a.x.y.c.getTime()).to.equal(b.x.y.c.getTime());
+            done();
+        });
+
+        it('should properly clone arrays', function (done) {
+
+            var a = [1,2,3];
+
+            var b = Hoek.clone(a);
+
+            expect(a).to.deep.equal(b);
+            done();
+        });
+
+        it('should perform actual copy for shallow keys (no pass by reference)', function (done) {
+
+            var x = Hoek.clone(nestedObj);
+            var y = Hoek.clone(nestedObj);
+
+            // Date
+            expect(x.z).to.not.equal(nestedObj.z);
+            expect(x.z).to.not.equal(y.z);
+
+            // Regex
+            expect(x.w).to.not.equal(nestedObj.w);
+            expect(x.w).to.not.equal(y.w);
+
+            // Array
+            expect(x.v).to.not.equal(nestedObj.v);
+            expect(x.v).to.not.equal(y.v);
+
+            // Immutable(s)
+            x.y = 5;
+            expect(x.y).to.not.equal(nestedObj.y);
+            expect(x.y).to.not.equal(y.y);
+
+            done();
+        });
+
+        it('should perform actual copy for deep keys (no pass by reference)', function (done) {
+
+            var x = Hoek.clone(nestedObj);
+            var y = Hoek.clone(nestedObj);
+
+            expect(x.x.c).to.not.equal(nestedObj.x.c);
+            expect(x.x.c).to.not.equal(y.x.c);
+
+            expect(x.x.c.getTime()).to.equal(nestedObj.x.c.getTime());
+            expect(x.x.c.getTime()).to.equal(y.x.c.getTime());
+            done();
+        });
+
+        it('copies functions with properties', function (done) {
+
+            var a = {
+                x: function () { return 1; },
+                y: {}
+            };
+            a.x.z = 'string in function';
+            a.x.v = function () { return 2; };
+            a.y.u = a.x;
+
+            var b = Hoek.clone(a);
+            expect(b.x()).to.equal(1);
+            expect(b.x.v()).to.equal(2);
+            expect(b.y.u).to.equal(b.x);
+            expect(b.x.z).to.equal('string in function');
+            done();
+        });
+
+        it('should copy a buffer', function(done){
+            var tls = {
+                key: new Buffer([1,2,3,4,5]),
+                cert: new Buffer([1,2,3,4,5,6,10])
+            }
+
+            copiedTls = Hoek.clone(tls);
+            expect(Buffer.isBuffer(copiedTls.key)).to.equal(true);
+            expect(JSON.stringify(copiedTls.key)).to.equal(JSON.stringify(tls.key))
+            expect(Buffer.isBuffer(copiedTls.cert)).to.equal(true);
+            expect(JSON.stringify(copiedTls.cert)).to.equal(JSON.stringify(tls.cert))
+            done();
+        });
+    });
+
+    describe('#merge', function () {
+
+        it('does not throw if source is null', function (done) {
+
+            var a = {};
+            var b = null;
+            var c = null;
+
+            expect(function () {
+
+                c = Hoek.merge(a, b);
+            }).to.not.throw();
+
+            expect(c).to.equal(a);
+            done();
+        });
+
+        it('does not throw if source is undefined', function (done) {
+
+            var a = {};
+            var b = undefined;
+            var c = null;
+
+            expect(function () {
+
+                c = Hoek.merge(a, b);
+            }).to.not.throw();
+
+            expect(c).to.equal(a);
+            done();
+        });
+
+        it('throws if source is not an object', function (done) {
+
+            expect(function () {
+
+                var a = {};
+                var b = 0;
+
+                Hoek.merge(a, b);
+            }).to.throw('Invalid source value: must be null, undefined, or an object');
+            done();
+        });
+
+        it('throws if target is not an object', function (done) {
+
+            expect(function () {
+
+                var a = 0;
+                var b = {};
+
+                Hoek.merge(a, b);
+            }).to.throw('Invalid target value: must be an object');
+            done();
+        });
+
+        it('throws if target is not an array and source is', function (done) {
+
+            expect(function () {
+
+                var a = {};
+                var b = [1, 2];
+
+                Hoek.merge(a, b);
+            }).to.throw('Cannot merge array onto an object');
+            done();
+        });
+
+        it('returns the same object when merging arrays', function (done) {
+
+            var a = [];
+            var b = [1, 2];
+
+            expect(Hoek.merge(a, b)).to.equal(a);
+            done();
+        });
+
+        it('should combine an empty object with a non-empty object', function (done) {
+
+            var a = {};
+            var b = nestedObj;
+
+            var c = Hoek.merge(a, b);
+            expect(a).to.deep.equal(b);
+            expect(c).to.deep.equal(b);
+            done();
+        });
+
+        it('should override values in target', function (done) {
+
+            var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
+            var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
+
+            var c = Hoek.merge(a, b);
+            expect(c.x).to.equal(null);
+            expect(c.y).to.equal(2);
+            expect(c.z).to.equal(4);
+            expect(c.v).to.equal(0);
+            expect(c.m).to.equal('123');
+            expect(c.t).to.deep.equal({ u: 6 });
+            done();
+        });
+
+        it('should override values in target (flip)', function (done) {
+
+            var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
+            var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
+
+            var d = Hoek.merge(b, a);
+            expect(d.x).to.equal(1);
+            expect(d.y).to.equal(2);
+            expect(d.z).to.equal(3);
+            expect(d.v).to.equal(5);
+            expect(d.m).to.equal('abc');
+            expect(d.t).to.deep.equal('test');
+            done();
+        });
+    });
+
+    describe('#applyToDefaults', function () {
+
+        var defaults = {
+            a: 1,
+            b: 2,
+            c: {
+                d: 3,
+                e: [5, 6]
+            },
+            f: 6,
+            g: 'test'
+        };
+
+        it('should return null if options is false', function (done) {
+
+            var result = Hoek.applyToDefaults(defaults, false);
+            expect(result).to.equal(null);
+            done();
+        });
+
+        it('should return a copy of defaults if options is true', function (done) {
+
+            var result = Hoek.applyToDefaults(defaults, true);
+            expect(result).to.deep.equal(result);
+            done();
+        });
+
+        it('should apply object to defaults', function (done) {
+
+            var obj = {
+                a: null,
+                c: {
+                    e: [4]
+                },
+                f: 0,
+                g: {
+                    h: 5
+                }
+            };
+
+            var result = Hoek.applyToDefaults(defaults, obj);
+            expect(result.c.e).to.deep.equal([4]);
+            expect(result.a).to.equal(1);
+            expect(result.b).to.equal(2);
+            expect(result.f).to.equal(0);
+            expect(result.g).to.deep.equal({ h: 5 });
+            done();
+        });
+    });
+
+    describe('#unique', function () {
+
+        it('should ensure uniqueness within array of objects based on subkey', function (done) {
+
+            var a = Hoek.unique(dupsArray, 'x');
+            expect(a).to.deep.equal(reducedDupsArray);
+            done();
+        });
+
+        it('removes duplicated without key', function (done) {
+
+            expect(Hoek.unique([1, 2, 3, 4, 2, 1, 5])).to.deep.equal([1, 2, 3, 4, 5]);
+            done();
+        });
+    });
+
+    describe('#mapToObject', function () {
+
+        it('should return null on null array', function (done) {
+
+            var a = Hoek.mapToObject(null);
+            expect(a).to.equal(null);
+            done();
+        });
+
+        it('should convert basic array to existential object', function (done) {
+
+            var keys = [1, 2, 3, 4];
+            var a = Hoek.mapToObject(keys);
+            for (var i in keys) {
+                expect(a[keys[i]]).to.equal(true);
+            }
+            done();
+        });
+
+        it('should convert array of objects to existential object', function (done) {
+
+            var keys = [{ x: 1 }, { x: 2 }, { x: 3 }];
+            var subkey = 'x';
+            var a = Hoek.mapToObject(keys, subkey);
+            for (var i in keys) {
+                expect(a[keys[i][subkey]]).to.equal(true);
+            }
+            done();
+        });
+    });
+
+    describe('#intersect', function () {
+
+        it('should return the common objects of two arrays', function (done) {
+
+            var array1 = [1, 2, 3, 4, 4, 5, 5];
+            var array2 = [5, 4, 5, 6, 7];
+            var common = Hoek.intersect(array1, array2);
+            expect(common.length).to.equal(2);
+            done();
+        });
+
+        it('should return just the first common object of two arrays', function (done) {
+
+            var array1 = [1, 2, 3, 4, 4, 5, 5];
+            var array2 = [5, 4, 5, 6, 7];
+            var common = Hoek.intersect(array1, array2, true);
+            expect(common).to.equal(5);
+            done();
+        });
+
+        it('should return an empty array if either input is null', function (done) {
+
+            expect(Hoek.intersect([1], null).length).to.equal(0);
+            expect(Hoek.intersect(null, [1]).length).to.equal(0);
+            done();
+        });
+
+        it('should return the common objects of object and array', function (done) {
+
+            var array1 = [1, 2, 3, 4, 4, 5, 5];
+            var array2 = [5, 4, 5, 6, 7];
+            var common = Hoek.intersect(Hoek.mapToObject(array1), array2);
+            expect(common.length).to.equal(2);
+            done();
+        });
+    });
+
+    describe('#matchKeys', function () {
+
+        it('should match the existing object keys', function (done) {
+
+            var obj = {
+                a: 1,
+                b: 2,
+                c: 3,
+                d: null
+            };
+
+            expect(Hoek.matchKeys(obj, ['b', 'c', 'd', 'e'])).to.deep.equal(['b', 'c', 'd']);
+            done();
+        });
+    });
+
+    describe('#flatten', function () {
+
+        it('should return a flat array', function (done) {
+
+            var result = Hoek.flatten([1, 2, [3, 4, [5, 6], [7], 8], [9], [10, [11, 12]], 13]);
+            expect(result.length).to.equal(13);
+            expect(result).to.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
+            done();
+        });
+    });
+
+    describe('#removeKeys', function () {
+
+        var objWithHiddenKeys = {
+            location: {
+                name: 'San Bruno'
+            },
+            company: {
+                name: '@WalmartLabs'
+            }
+        };
+
+        it('should delete params with definition\'s hide set to true', function (done) {
+
+            var a = Hoek.removeKeys(objWithHiddenKeys, ['location']);
+            expect(objWithHiddenKeys.location).to.not.exist;
+            expect(objWithHiddenKeys.company).to.exist;
+            done();
+        });
+    });
+
+    describe('#reach', function () {
+
+        var obj = {
+            a: {
+                b: {
+                    c: {
+                        d: 1,
+                        e: 2
+                    },
+                    f: 'hello'
+                },
+                g: {
+                    h: 3
+                }
+            },
+            i: function () { }
+        };
+
+        it('returns a valid member', function (done) {
+
+            expect(Hoek.reach(obj, 'a.b.c.d')).to.equal(1);
+            done();
+        });
+
+        it('returns null on null object', function (done) {
+
+            expect(Hoek.reach(null, 'a.b.c.d')).to.not.exist;
+            done();
+        });
+
+        it('returns null on missing member', function (done) {
+
+            expect(Hoek.reach(obj, 'a.b.c.d.x')).to.not.exist;
+            done();
+        });
+
+        it('returns null on invalid member', function (done) {
+
+            expect(Hoek.reach(obj, 'a.b.c.d-.x')).to.not.exist;
+            done();
+        });
+
+        it('returns function member', function (done) {
+
+            expect(typeof Hoek.reach(obj, 'i')).to.equal('function');
+            done();
+        });
+    });
+
+    describe('#inheritAsync', function () {
+
+        it('should inherit selected methods and wrap in async call', function (done) {
+
+            var proto = {
+                a: function () {
+                    return 'a!';
+                },
+                b: function () {
+                    return 'b!';
+                },
+                c: function () {
+                    throw new Error('c!');
+                }
+            };
+
+            var targetFunc = function () { };
+            targetFunc.prototype.c = function () {
+
+                return 'oops';
+            };
+
+            Hoek.inheritAsync(targetFunc, proto, ['a', 'c']);
+            var target = new targetFunc();
+
+            expect(typeof target.a).to.equal('function');
+            expect(typeof target.c).to.equal('function');
+            expect(target.b).to.not.exist;
+
+            target.a(function (err, result) {
+
+                expect(err).to.not.exist;
+                expect(result).to.equal('a!');
+
+                target.c(function (err, result) {
+
+                    expect(result).to.not.exist;
+                    expect(err.message).to.equal('c!');
+                    done();
+                });
+            });
+        });
+    });
+
+    describe('#callStack', function () {
+
+        it('should return the full call stack', function (done) {
+
+            var stack = Hoek.callStack();
+            expect(stack[0][0]).to.contain('index.js');
+            expect(stack[0][2]).to.equal(30);
+            done();
+        });
+    });
+
+    describe('#displayStack ', function () {
+
+        it('should return the full call stack for display', function (done) {
+
+            var stack = Hoek.displayStack();
+            expect(stack[0]).to.contain('test/index.js:');
+            done();
+        });
+
+        it('should include constructor functions correctly', function (done) {
+
+            var Something = function (next) {
+
+                next();
+            };
+
+            var something = new Something(function () {
+
+                var stack = Hoek.displayStack();
+                expect(stack[1]).to.contain('new Something');
+                done();
+            });
+        });
+    });
+
+    describe('#abort', function () {
+
+        it('should exit process when not in test mode', function (done) {
+
+            var env = process.env.NODE_ENV;
+            var write = process.stdout.write;
+            var exit = process.exit;
+
+            process.env.NODE_ENV = 'nottatest';
+            process.stdout.write = function () { };
+            process.exit = function (state) {
+
+                process.exit = exit;
+                process.env.NODE_ENV = env;
+                process.stdout.write = write;
+
+                expect(state).to.equal(1);
+                done();
+            };
+
+            Hoek.abort('Boom');
+        });
+
+        it('should throw when not in test mode and abortThrow is true', function (done) {
+
+            var env = process.env.NODE_ENV;
+            process.env.NODE_ENV = 'nottatest';
+            Hoek.abortThrow = true;
+
+            var fn = function () {
+
+                Hoek.abort('my error message');
+            };
+
+            expect(fn).to.throw('my error message');
+            Hoek.abortThrow = false;
+            process.env.NODE_ENV = env;
+
+            done();
+        });
+
+
+        it('should respect hideStack argument', function (done) {
+
+            var env = process.env.NODE_ENV;
+            var write = process.stdout.write;
+            var exit = process.exit;
+            var output = '';
+
+            process.exit = function () { };
+            process.env.NODE_ENV = '';
+            process.stdout.write = function (message) {
+
+                output = message;
+            };
+
+            Hoek.abort('my error message', true);
+
+            process.env.NODE_ENV = env;
+            process.stdout.write = write;
+            process.exit = exit;
+
+            expect(output).to.equal('ABORT: my error message\n\t\n');
+
+            done();
+        });
+
+        it('should default to showing stack', function (done) {
+
+            var env = process.env.NODE_ENV;
+            var write = process.stdout.write;
+            var exit = process.exit;
+            var output = '';
+
+            process.exit = function () { };
+            process.env.NODE_ENV = '';
+            process.stdout.write = function (message) {
+
+                output = message;
+            };
+
+            Hoek.abort('my error message');
+
+            process.env.NODE_ENV = env;
+            process.stdout.write = write;
+            process.exit = exit;
+
+            expect(output).to.contain('index.js');
+
+            done();
+        });
+    });
+
+    describe('#assert', function () {
+
+        it('should throw an Error when using assert in a test', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, 'my error message');
+            };
+
+            expect(fn).to.throw('my error message');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with no message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false);
+            };
+
+            expect(fn).to.throw('Unknown error');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with multipart message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, 'This', 'is', 'my message');
+            };
+
+            expect(fn).to.throw('This is my message');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with object message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, 'This', 'is', { spinal: 'tap' });
+            };
+
+            expect(fn).to.throw('This is {"spinal":"tap"}');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with error object message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, new Error('This is spinal tap'));
+            };
+
+            expect(fn).to.throw('This is spinal tap');
+            done();
+        });
+    });
+
+    describe('#loadDirModules', function () {
+
+        it('should load modules from directory', function (done) {
+
+            var target = {};
+            Hoek.loadDirModules(__dirname + '/modules', ['test2'], target);
+            expect(target.Test1.x).to.equal(1);
+            expect(target.Test2).to.not.exist;
+            expect(target.Test3.z).to.equal(3);
+            done();
+        });
+
+        it('should list modules from directory into function', function (done) {
+
+            var target = {};
+            Hoek.loadDirModules(__dirname + '/modules', ['test2'], function (path, name, capName) {
+
+                target[name] = capName;
+            });
+
+            expect(target.test1).to.equal('Test1');
+            expect(target.test2).to.not.exist;
+            expect(target.test3).to.equal('Test3');
+            done();
+        });
+    });
+
+    describe('#rename', function () {
+
+        it('should rename object key', function (done) {
+
+            var a = { b: 'c' };
+            Hoek.rename(a, 'b', 'x');
+            expect(a.b).to.not.exist;
+            expect(a.x).to.equal('c');
+            done();
+        });
+    });
+
+    describe('Timer', function () {
+
+        it('should return time elapsed', function (done) {
+
+            var timer = new Hoek.Timer();
+            setTimeout(function () {
+
+                expect(timer.elapsed()).to.be.above(9);
+                done();
+            }, 12);
+        });
+    });
+
+    describe('#loadPackage', function () {
+
+        it('should', function (done) {
+
+            var pack = Hoek.loadPackage();
+            expect(pack.name).to.equal('hoek');
+            done();
+        });
+    });
+
+    describe('#escapeRegex', function () {
+
+        it('should escape all special regular expression characters', function (done) {
+
+            var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');
+            expect(a).to.equal('4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`"\\(>\\)\\[<\\]d\\{\\}s\\,');
+            done();
+        });
+    });
+
+    describe('#toss', function () {
+
+        it('should call callback with new error', function (done) {
+
+            var callback = function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('bug');
+                done();
+            };
+
+            Hoek.toss(true, 'feature', callback);
+            Hoek.toss(false, 'bug', callback);
+        });
+
+        it('should call callback with new error and no message', function (done) {
+
+            Hoek.toss(false, function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('');
+                done();
+            });
+        });
+
+        it('should call callback with error condition', function (done) {
+
+            Hoek.toss(new Error('boom'), function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('boom');
+                done();
+            });
+        });
+
+        it('should call callback with new error using message with error condition', function (done) {
+
+            Hoek.toss(new Error('ka'), 'boom', function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('boom');
+                done();
+            });
+        });
+
+        it('should call callback with new error using passed error with error condition', function (done) {
+
+            Hoek.toss(new Error('ka'), new Error('boom'), function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('boom');
+                done();
+            });
+        });
+    });
+
+    describe('Base64Url', function () {
+
+        var base64str = 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w';
+        var str = unescape('%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29*+%2C-./0123456789%3A%3B%3C%3D%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF');
+
+        describe('#base64urlEncode', function () {
+
+            it('should base64 URL-safe a string', function (done) {
+
+                expect(Hoek.base64urlEncode(str)).to.equal(base64str);
+                done();
+            });
+        });
+
+        describe('#base64urlDecode', function () {
+
+            it('should un-base64 URL-safe a string', function (done) {
+
+                expect(Hoek.base64urlDecode(base64str)).to.equal(str);
+                done();
+            });
+
+            it('should return error on undefined input', function (done) {
+
+                expect(Hoek.base64urlDecode().message).to.exist;
+                done();
+            });
+
+            it('should return error on invalid input', function (done) {
+
+                expect(Hoek.base64urlDecode('*').message).to.exist;
+                done();
+            });
+        });
+    });
+
+    describe('#escapeHeaderAttribute', function () {
+
+        it('should not alter ascii values', function (done) {
+
+            var a = Hoek.escapeHeaderAttribute('My Value');
+            expect(a).to.equal('My Value');
+            done();
+        });
+
+        it('should escape all special HTTP header attribute characters', function (done) {
+
+            var a = Hoek.escapeHeaderAttribute('I said go!!!#"' + String.fromCharCode(92));
+            expect(a).to.equal('I said go!!!#\\"\\\\');
+            done();
+        });
+
+        it('should throw on large unicode characters', function (done) {
+
+            var fn = function () {
+
+                Hoek.escapeHeaderAttribute('this is a test' + String.fromCharCode(500) + String.fromCharCode(300));
+            };
+
+            expect(fn).to.throw(Error);
+            done();
+        });
+
+        it('should throw on CRLF to prevent response splitting', function (done) {
+
+            var fn = function () {
+
+                Hoek.escapeHeaderAttribute('this is a test\r\n');
+            };
+
+            expect(fn).to.throw(Error);
+            done();
+        });
+    });
+
+    describe('#escapeHtml', function () {
+
+        it('should escape all special HTML characters', function (done) {
+
+            var a = Hoek.escapeHtml('&<>"\'`');
+            expect(a).to.equal('&amp;&lt;&gt;&quot;&#x27;&#x60;');
+            done();
+        });
+
+        it('should return empty string on falsy input', function (done) {
+
+            var a = Hoek.escapeHtml('');
+            expect(a).to.equal('');
+            done();
+        });
+
+        it('should return unchanged string on no reserved input', function (done) {
+
+            var a = Hoek.escapeHtml('abc');
+            expect(a).to.equal('abc');
+            done();
+        });
+    });
+
+    describe('#printEvent', function () {
+
+        it('outputs event as string', function (done) {
+
+            var event = {
+                timestamp: (new Date(2013, 1, 1, 6, 30, 45, 123)).getTime(),
+                tags: ['a', 'b', 'c'],
+                data: { some: 'data' }
+            };
+
+            Hoek.consoleFunc = function (string) {
+
+                Hoek.consoleFunc = console.log;
+                expect(string).to.equal('130201/063045.123, a, {"some":"data"}');
+                done();
+            };
+
+            Hoek.printEvent(event);
+        });
+
+        it('outputs JSON error', function (done) {
+
+            var event = {
+                timestamp: (new Date(2013, 1, 1, 6, 30, 45, 123)).getTime(),
+                tags: ['a', 'b', 'c'],
+                data: { some: 'data' }
+            };
+
+            event.data.a = event.data;
+
+            Hoek.consoleFunc = function (string) {
+
+                Hoek.consoleFunc = console.log;
+                expect(string).to.equal('130201/063045.123, a, JSON Error: Converting circular structure to JSON');
+                done();
+            };
+
+            Hoek.printEvent(event);
+        });
+    });
+
+    describe('#nextTick', function () {
+
+        it('calls the provided callback on nextTick', function (done) {
+
+            var a = 0;
+
+            var inc = function (step, next) {
+
+                a += step;
+                next();
+            };
+
+            var ticked = Hoek.nextTick(inc);
+
+            ticked(5, function () {
+
+                expect(a).to.equal(6);
+                done();
+            });
+
+            expect(a).to.equal(0);
+            inc(1, function () {
+
+                expect(a).to.equal(1);
+            });
+        });
+    });
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test1.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test1.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test1.js	(revision 484)
@@ -0,0 +1,1 @@
+exports.x = 1;
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test2.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test2.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test2.js	(revision 484)
@@ -0,0 +1,1 @@
+exports.y = 2;
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test3.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test3.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/node_modules/hoek/test/modules/test3.js	(revision 484)
@@ -0,0 +1,1 @@
+exports.z = 3;
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/package.json	(revision 484)
@@ -0,0 +1,47 @@
+{
+  "name": "boom",
+  "description": "HTTP-friendly error objects",
+  "version": "0.4.2",
+  "author": {
+    "name": "Eran Hammer",
+    "email": "eran@hueniverse.com",
+    "url": "http://hueniverse.com"
+  },
+  "contributors": [],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/spumko/boom"
+  },
+  "main": "index",
+  "keywords": [
+    "error",
+    "http"
+  ],
+  "engines": {
+    "node": ">=0.8.0"
+  },
+  "dependencies": {
+    "hoek": "0.9.x"
+  },
+  "devDependencies": {
+    "lab": "0.1.x",
+    "complexity-report": "0.x.x"
+  },
+  "scripts": {
+    "test": "make test-cov"
+  },
+  "licenses": [
+    {
+      "type": "BSD",
+      "url": "http://github.com/spumko/boom/raw/master/LICENSE"
+    }
+  ],
+  "readme": "<a href=\"https://github.com/spumko\"><img src=\"https://raw.github.com/spumko/spumko/master/images/from.png\" align=\"right\" /></a>\n![boom Logo](https://raw.github.com/spumko/boom/master/images/boom.png)\n\nHTTP-friendly error objects\n\n[![Build Status](https://secure.travis-ci.org/spumko/boom.png)](http://travis-ci.org/spumko/boom)\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/spumko/boom/issues"
+  },
+  "homepage": "https://github.com/spumko/boom",
+  "_id": "boom@0.4.2",
+  "_from": "boom@0.4.x"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/boom/test/index.js	(revision 484)
@@ -0,0 +1,245 @@
+// Load modules
+
+var Lab = require('lab');
+var Boom = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Boom', function () {
+
+    it('returns an error with info when constructed using another error', function (done) {
+
+        var error = new Error('ka-boom');
+        error.xyz = 123;
+        var err = new Boom(error);
+        expect(err.data.xyz).to.equal(123);
+        expect(err.message).to.equal('ka-boom');
+        expect(err.response).to.deep.equal({
+            code: 500,
+            payload: {
+                code: 500,
+                error: 'Internal Server Error',
+                message: 'ka-boom'
+            },
+            headers: {}
+        });
+        done();
+    });
+
+    describe('#isBoom', function () {
+
+        it('returns true for Boom object', function (done) {
+
+            expect(Boom.badRequest().isBoom).to.equal(true);
+            done();
+        });
+
+        it('returns false for Error object', function (done) {
+
+            expect(new Error().isBoom).to.not.exist;
+            done();
+        });
+    });
+
+    describe('#badRequest', function () {
+
+        it('returns a 400 error code', function (done) {
+
+            expect(Boom.badRequest().response.code).to.equal(400);
+            done();
+        });
+
+        it('sets the message with the passed in message', function (done) {
+
+            expect(Boom.badRequest('my message').message).to.equal('my message');
+            done();
+        });
+    });
+
+    describe('#unauthorized', function () {
+
+        it('returns a 401 error code', function (done) {
+
+            var err = Boom.unauthorized();
+            expect(err.response.code).to.equal(401);
+            expect(err.response.headers).to.deep.equal({});
+            done();
+        });
+
+        it('sets the message with the passed in message', function (done) {
+
+            expect(Boom.unauthorized('my message').message).to.equal('my message');
+            done();
+        });
+
+        it('returns a WWW-Authenticate header when passed a scheme', function (done) {
+
+            var err = Boom.unauthorized('boom', 'Test');
+            expect(err.response.code).to.equal(401);
+            expect(err.response.headers['WWW-Authenticate']).to.equal('Test error="boom"');
+            done();
+        });
+
+        it('returns a WWW-Authenticate header when passed a scheme and attributes', function (done) {
+
+            var err = Boom.unauthorized('boom', 'Test', { a: 1, b: 'something', c: null, d: 0 });
+            expect(err.response.code).to.equal(401);
+            expect(err.response.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0", error="boom"');
+            done();
+        });
+
+        it('sets the isMissing flag when error message is empty', function (done) {
+
+            var err = Boom.unauthorized('', 'Basic');
+            expect(err.isMissing).to.equal(true);
+            done();
+        });
+
+        it('does not set the isMissing flag when error message is not empty', function (done) {
+
+            var err = Boom.unauthorized('message', 'Basic');
+            expect(err.isMissing).to.equal(undefined);
+            done();
+        });
+
+        it('sets a WWW-Authenticate when passed as an array', function (done) {
+
+            var err = Boom.unauthorized('message', ['Basic', 'Example e="1"', 'Another x="3", y="4"']);
+            expect(err.response.headers['WWW-Authenticate']).to.equal('Basic, Example e="1", Another x="3", y="4"');
+            done();
+        });
+    });
+
+    describe('#clientTimeout', function () {
+
+        it('returns a 408 error code', function (done) {
+
+            expect(Boom.clientTimeout().response.code).to.equal(408);
+            done();
+        });
+
+        it('sets the message with the passed in message', function (done) {
+
+            expect(Boom.clientTimeout('my message').message).to.equal('my message');
+            done();
+        });
+    });
+
+    describe('#serverTimeout', function () {
+
+        it('returns a 503 error code', function (done) {
+
+            expect(Boom.serverTimeout().response.code).to.equal(503);
+            done();
+        });
+
+        it('sets the message with the passed in message', function (done) {
+
+            expect(Boom.serverTimeout('my message').message).to.equal('my message');
+            done();
+        });
+    });
+
+    describe('#forbidden', function () {
+
+        it('returns a 403 error code', function (done) {
+
+            expect(Boom.forbidden().response.code).to.equal(403);
+            done();
+        });
+
+        it('sets the message with the passed in message', function (done) {
+
+            expect(Boom.forbidden('my message').message).to.equal('my message');
+            done();
+        });
+    });
+
+    describe('#notFound', function () {
+
+        it('returns a 404 error code', function (done) {
+
+            expect(Boom.notFound().response.code).to.equal(404);
+            done();
+        });
+
+        it('sets the message with the passed in message', function (done) {
+
+            expect(Boom.notFound('my message').message).to.equal('my message');
+            done();
+        });
+    });
+
+    describe('#internal', function () {
+
+        it('returns a 500 error code', function (done) {
+
+            expect(Boom.internal().response.code).to.equal(500);
+            done();
+        });
+
+        it('sets the message with the passed in message', function (done) {
+
+            var err = Boom.internal('my message');
+            expect(err.message).to.equal('my message');
+            expect(err.response.payload.message).to.equal('An internal server error occurred');
+            done();
+        });
+
+        it('passes data on the callback if its passed in', function (done) {
+
+            expect(Boom.internal('my message', { my: 'data' }).data.my).to.equal('data');
+            done();
+        });
+
+        it('uses passed in stack if its available', function (done) {
+
+            var error = new Error();
+            error.stack = 'my stack line\nmy second stack line';
+            expect(Boom.internal('my message', error).trace[0]).to.equal('my stack line');
+            done();
+        });
+    });
+
+    describe('#passThrough', function () {
+
+        it('returns a pass-through error', function (done) {
+
+            var err = Boom.passThrough(499, { a: 1 }, 'application/text', { 'X-Test': 'Boom' });
+            expect(err.response.code).to.equal(499);
+            expect(err.message).to.equal('Pass-through');
+            expect(err.response).to.deep.equal({
+                code: 499,
+                payload: { a: 1 },
+                headers: { 'X-Test': 'Boom' },
+                type: 'application/text'
+            });
+            done();
+        });
+    });
+
+    describe('#reformat', function () {
+
+        it('encodes any HTML markup in the response payload', function (done) {
+
+            var boom = new Boom(new Error('<script>alert(1)</script>'));
+            expect(boom.response.payload.message).to.not.contain('<script>');
+            done();
+        });
+    });
+});
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/.npmignore	(revision 484)
@@ -0,0 +1,18 @@
+.idea
+*.iml
+npm-debug.log
+dump.rdb
+node_modules
+results.tap
+results.xml
+npm-shrinkwrap.json
+config.json
+.DS_Store
+*/.DS_Store
+*/*/.DS_Store
+._*
+*/._*
+*/*/._*
+coverage.*
+lib-cov
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+
+node_js:
+  - 0.10
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/LICENSE	(revision 484)
@@ -0,0 +1,24 @@
+Copyright (c) 2012-2013, Eran Hammer.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Eran Hammer nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ERAN HAMMER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/Makefile	(revision 484)
@@ -0,0 +1,11 @@
+test:
+	@./node_modules/.bin/lab
+test-cov: 
+	@./node_modules/.bin/lab -r threshold -t 100
+test-cov-html:
+	@./node_modules/.bin/lab -r html -o coverage.html
+complexity:
+	@./node_modules/.bin/cr -o complexity.md -f markdown lib
+
+.PHONY: test test-cov test-cov-html complexity
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/README.md	(revision 484)
@@ -0,0 +1,6 @@
+cryptiles
+=========
+
+General purpose crypto utilities
+
+[![Build Status](https://secure.travis-ci.org/hueniverse/cryptiles.png)](http://travis-ci.org/hueniverse/cryptiles)
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/index.js	(revision 484)
@@ -0,0 +1,1 @@
+module.exports = require('./lib');
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/lib/index.js	(revision 484)
@@ -0,0 +1,68 @@
+// Load modules
+
+var Crypto = require('crypto');
+var Boom = require('boom');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Generate a cryptographically strong pseudo-random data
+
+exports.randomString = function (size) {
+
+    var buffer = exports.randomBits((size + 1) * 6);
+    if (buffer instanceof Error) {
+        return buffer;
+    }
+
+    var string = buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
+    return string.slice(0, size);
+};
+
+
+exports.randomBits = function (bits) {
+
+    if (!bits ||
+        bits < 0) {
+
+        return Boom.internal('Invalid random bits count');
+    }
+
+    var bytes = Math.ceil(bits / 8);
+    try {
+        return Crypto.randomBytes(bytes);
+    }
+    catch (err) {
+        return Boom.internal('Failed generating random bits: ' + err.message);
+    }
+};
+
+
+// Compare two strings using fixed time algorithm (to prevent time-based analysis of MAC digest match)
+
+exports.fixedTimeComparison = function (a, b) {
+
+    if (typeof a !== 'string' ||
+        typeof b !== 'string') {
+
+        return false;
+    }
+
+    var mismatch = (a.length === b.length ? 0 : 1);
+    if (mismatch) {
+        b = a;
+    }
+
+    for (var i = 0, il = a.length; i < il; ++i) {
+        var ac = a.charCodeAt(i);
+        var bc = b.charCodeAt(i);
+        mismatch += (ac === bc ? 0 : 1);
+    }
+
+    return (mismatch === 0);
+};
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/package.json	(revision 484)
@@ -0,0 +1,48 @@
+{
+  "name": "cryptiles",
+  "description": "General purpose crypto utilities",
+  "version": "0.2.2",
+  "author": {
+    "name": "Eran Hammer",
+    "email": "eran@hueniverse.com",
+    "url": "http://hueniverse.com"
+  },
+  "contributors": [],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/hueniverse/cryptiles"
+  },
+  "main": "index",
+  "keywords": [
+    "cryptography",
+    "security",
+    "utilites"
+  ],
+  "engines": {
+    "node": ">=0.8.0"
+  },
+  "dependencies": {
+    "boom": "0.4.x"
+  },
+  "devDependencies": {
+    "lab": "0.1.x",
+    "complexity-report": "0.x.x"
+  },
+  "scripts": {
+    "test": "make test-cov"
+  },
+  "licenses": [
+    {
+      "type": "BSD",
+      "url": "http://github.com/hueniverse/cryptiles/raw/master/LICENSE"
+    }
+  ],
+  "readme": "cryptiles\n=========\n\nGeneral purpose crypto utilities\n\n[![Build Status](https://secure.travis-ci.org/hueniverse/cryptiles.png)](http://travis-ci.org/hueniverse/cryptiles)\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/hueniverse/cryptiles/issues"
+  },
+  "homepage": "https://github.com/hueniverse/cryptiles",
+  "_id": "cryptiles@0.2.2",
+  "_from": "cryptiles@0.2.x"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/cryptiles/test/index.js	(revision 484)
@@ -0,0 +1,101 @@
+// Load modules
+
+var Lab = require('lab');
+var Cryptiles = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Cryptiles', function () {
+
+    describe('#randomString', function () {
+
+        it('should generate the right length string', function (done) {
+
+            for (var i = 1; i <= 1000; ++i) {
+                expect(Cryptiles.randomString(i).length).to.equal(i);
+            }
+
+            done();
+        });
+
+        it('returns an error on invalid bits size', function (done) {
+
+            expect(Cryptiles.randomString(99999999999999999999).message).to.equal('Failed generating random bits: Argument #1 must be number > 0');
+            done();
+        });
+    });
+
+    describe('#randomBits', function () {
+
+        it('returns an error on invalid input', function (done) {
+
+            expect(Cryptiles.randomBits(0).message).to.equal('Invalid random bits count');
+            done();
+        });
+    });
+
+    describe('#fixedTimeComparison', function () {
+
+        var a = Cryptiles.randomString(50000);
+        var b = Cryptiles.randomString(150000);
+
+        it('should take the same amount of time comparing different string sizes', function (done) {
+
+            var now = Date.now();
+            Cryptiles.fixedTimeComparison(b, a);
+            var t1 = Date.now() - now;
+
+            now = Date.now();
+            Cryptiles.fixedTimeComparison(b, b);
+            var t2 = Date.now() - now;
+
+            expect(t2 - t1).to.be.within(-20, 20);
+            done();
+        });
+
+        it('should return true for equal strings', function (done) {
+
+            expect(Cryptiles.fixedTimeComparison(a, a)).to.equal(true);
+            done();
+        });
+
+        it('should return false for different strings (size, a < b)', function (done) {
+
+            expect(Cryptiles.fixedTimeComparison(a, a + 'x')).to.equal(false);
+            done();
+        });
+
+        it('should return false for different strings (size, a > b)', function (done) {
+
+            expect(Cryptiles.fixedTimeComparison(a + 'x', a)).to.equal(false);
+            done();
+        });
+
+        it('should return false for different strings (size, a = b)', function (done) {
+
+            expect(Cryptiles.fixedTimeComparison(a + 'x', a + 'y')).to.equal(false);
+            done();
+        });
+
+        it('should return false when not a string', function (done) {
+
+            expect(Cryptiles.fixedTimeComparison('x', null)).to.equal(false);
+            done();
+        });
+    });
+});
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/.npmignore	(revision 484)
@@ -0,0 +1,18 @@
+.idea
+*.iml
+npm-debug.log
+dump.rdb
+node_modules
+results.tap
+results.xml
+npm-shrinkwrap.json
+config.json
+.DS_Store
+*/.DS_Store
+*/*/.DS_Store
+._*
+*/._*
+*/*/._*
+coverage.*
+lib-cov
+complexity.md
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+
+node_js:
+  - 0.10
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE	(revision 484)
@@ -0,0 +1,33 @@
+Copyright (c) 2011-2013, Walmart.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Walmart nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+                                  *   *   *
+
+
+Portions of this project were initially based on Postmile, Copyright (c) 2011, Yahoo Inc.
+Postmile is published at https://github.com/yahoo/postmile and its licensing terms are
+published at https://github.com/yahoo/postmile/blob/master/LICENSE.
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/Makefile	(revision 484)
@@ -0,0 +1,10 @@
+test:
+	@./node_modules/.bin/lab
+test-cov: 
+	@./node_modules/.bin/lab -r threshold -t 100
+test-cov-html:
+	@./node_modules/.bin/lab -r html -o coverage.html
+complexity:
+	@./node_modules/.bin/cr -o complexity.md -f markdown lib
+
+.PHONY: test test-cov test-cov-html complexity
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/README.md	(revision 484)
@@ -0,0 +1,436 @@
+<a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a>
+![hoek Logo](https://raw.github.com/spumko/hoek/master/images/hoek.png)
+
+General purpose node utilities
+
+[![Build Status](https://secure.travis-ci.org/spumko/hoek.png)](http://travis-ci.org/spumko/hoek)
+
+# Table of Contents
+
+* [Introduction](#introduction "Introduction")
+* [Object](#object "Object")
+  * [clone](#cloneobj "clone")
+  * [merge](#mergetarget-source-isnulloverride-ismergearrays "merge")
+  * [applyToDefaults](#applytodefaultsdefaults-options "applyToDefaults")
+  * [unique](#uniquearray-key "unique")
+  * [mapToObject](#maptoobjectarray-key "mapToObject")
+  * [intersect](#intersectarray1-array2 "intersect")
+  * [matchKeys](#matchkeysobj-keys "matchKeys")
+  * [flatten](#flattenarray-target "flatten")
+  * [removeKeys](#removekeysobject-keys "removeKeys")
+  * [reach](#reachobj-chain "reach")
+  * [inheritAsync](#inheritasyncself-obj-keys "inheritAsync")
+  * [rename](#renameobj-from-to "rename")
+* [Timer](#timer "Timer")
+* [Binary Encoding/Decoding](#binary "Binary Encoding/Decoding")
+  * [base64urlEncode](#binary64urlEncodevalue "binary64urlEncode")
+  * [base64urlDecode](#binary64urlDecodevalue "binary64urlDecode")
+* [Escaping Characters](#escaped "Escaping Characters")
+  * [escapeHtml](#escapeHtmlstring "escapeHtml")
+  * [escapeHeaderAttribute](#escapeHeaderAttributeattribute "escapeHeaderAttribute")
+  * [escapeRegex](#escapeRegexstring "escapeRegex")
+* [Errors](#errors "Errors")
+  * [assert](#assertmessage "assert")
+  * [abort](#abortmessage "abort")
+  * [displayStack](#displayStackslice "displayStack")
+  * [callStack](#callStackslice "callStack")
+  * [toss](#tosscondition "toss")
+* [Load files](#load-files "Load Files")
+  * [loadPackage](#loadPackagedir "loadpackage")
+  * [loadDirModules](#loadDirModulespath-excludefiles-target "loaddirmodules")
+
+
+
+# Introduction
+
+The *Hoek* general purpose node utilities library is used to aid in a variety of manners. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more. 
+
+For example, to use Hoek to set configuration with default options:
+```javascript
+var Hoek = require('hoek');
+
+var default = {url : "www.github.com", port : "8000", debug : true}
+
+var config = Hoek.applyToDefaults(default, {port : "3000", admin : true});
+
+// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }
+```
+
+Under each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the var Hoek = require('hoek') is omitted for brevity.
+
+## Object
+
+Hoek provides several helpful methods for objects and arrays.
+
+### clone(obj)
+
+This method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects). 
+
+```javascript
+
+var nestedObj = {
+        w: /^something$/ig,
+        x: {
+            a: [1, 2, 3],
+            b: 123456,
+            c: new Date()
+        },
+        y: 'y',
+        z: new Date()
+    };
+
+var copy = Hoek.clone(nestedObj);
+
+copy.x.b = 100;
+
+console.log(copy.y)        // results in 'y'
+console.log(nestedObj.x.b) // results in 123456
+console.log(copy.x.b)      // results in 100
+```
+
+### merge(target, source, isNullOverride, isMergeArrays)
+isNullOverride, isMergeArrays default to true
+
+Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
+
+
+```javascript
+
+var target = {a: 1, b : 2}
+var source = {a: 0, c: 5}
+var source2 = {a: null, c: 5}
+
+var targetArray = [1, 2, 3];
+var sourceArray = [4, 5];
+
+var newTarget = Hoek.merge(target, source);     // results in {a: 0, b: 2, c: 5}
+newTarget = Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}
+newTarget = Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}
+
+newTarget = Hoek.merge(targetArray, sourceArray)              // results in [1, 2, 3, 4, 5]
+newTarget = Hoek.merge(targetArray, sourceArray, true, false) // results in [4, 5]
+
+
+
+
+```
+
+### applyToDefaults(defaults, options)
+
+Apply options to a copy of the defaults
+
+```javascript
+
+var defaults = {host: "localhost", port: 8000};
+var options = {port: 8080};
+
+var config = Hoek.applyToDefaults(defaults, options); // results in {host: "localhost", port: 8080};
+
+
+```
+
+### unique(array, key)
+
+Remove duplicate items from Array
+
+```javascript
+
+var array = [1, 2, 2, 3, 3, 4, 5, 6];
+
+var newArray = Hoek.unique(array); // results in [1,2,3,4,5,6];
+
+array = [{id: 1}, {id: 1}, {id: 2}];
+
+newArray = Hoek.unique(array, "id") // results in [{id: 1}, {id: 2}]
+
+```
+
+### mapToObject(array, key)
+
+Convert an Array into an Object
+
+```javascript
+
+var array = [1,2,3];
+var newObject = Hoek.mapToObject(array); // results in [{"1": true}, {"2": true}, {"3": true}]
+
+array = [{id: 1}, {id: 2}];
+newObject = Hoek.mapToObject(array, "id") // results in [{"id": 1}, {"id": 2}]
+
+```
+### intersect(array1, array2)
+
+Find the common unique items in two arrays
+
+```javascript
+
+var array1 = [1, 2, 3];
+var array2 = [1, 4, 5];
+
+var newArray = Hoek.intersect(array1, array2) // results in [1]
+
+```
+
+### matchKeys(obj, keys) 
+
+Find which keys are present
+
+```javascript
+
+var obj = {a: 1, b: 2, c: 3};
+var keys = ["a", "e"];
+
+Hoek.matchKeys(obj, keys) // returns ["a"]
+
+```
+
+### flatten(array, target)
+
+Flatten an array
+
+```javascript
+
+var array = [1, 2, 3];
+var target = [4, 5]; 
+
+var flattenedArray = Hoek.flatten(array, target) // results in [4, 5, 1, 2, 3];
+
+```
+
+### removeKeys(object, keys)
+
+Remove keys
+
+```javascript
+
+var object = {a: 1, b: 2, c: 3, d: 4};
+
+var keys = ["a", "b"];
+
+Hoek.removeKeys(object, keys) // object is now {c: 3, d: 4}
+
+```
+
+### reach(obj, chain)
+
+Converts an object key chain string to reference
+
+```javascript
+
+var chain = 'a.b.c';
+var obj = {a : {b : { c : 1}}};
+
+Hoek.reach(obj, chain) // returns 1
+
+```
+
+### inheritAsync(self, obj, keys) 
+
+Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
+
+```javascript
+
+var targetFunc = function () { };
+
+var proto = {
+                a: function () {
+                    return 'a!';
+                },
+                b: function () {
+                    return 'b!';
+                },
+                c: function () {
+                    throw new Error('c!');
+                }
+            };
+
+var keys = ['a', 'c'];
+
+Hoek.inheritAsync(targetFunc, proto, ['a', 'c']);
+
+var target = new targetFunc();
+
+target.a(function(err, result){console.log(result)}         // returns 'a!'       
+
+target.c(function(err, result){console.log(result)}         // returns undefined
+
+target.b(function(err, result){console.log(result)}         // gives error: Object [object Object] has no method 'b'
+
+```
+
+### rename(obj, from, to)
+
+Rename a key of an object
+
+```javascript
+
+var obj = {a : 1, b : 2};
+
+Hoek.rename(obj, "a", "c");     // obj is now {c : 1, b : 2}
+
+```
+
+
+# Timer
+
+A Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
+
+```javascript
+
+
+example : 
+
+
+var timerObj = new Hoek.Timer();
+console.log("Time is now: " + timerObj.ts)
+console.log("Elapsed time from initialization: " + timerObj.elapsed() + 'milliseconds')
+
+```
+
+# Binary Encoding/Decoding
+
+### base64urlEncode(value)
+
+Encodes value in Base64 or URL encoding
+
+### base64urlDecode(value)
+
+Decodes data in Base64 or URL encoding.
+# Escaping Characters
+
+Hoek provides convenient methods for escaping html characters. The escaped characters are as followed:
+
+```javascript
+
+internals.htmlEscaped = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#x27;',
+    '`': '&#x60;'
+};
+
+```
+
+### escapeHtml(string)
+
+```javascript
+
+var string = '<html> hey </html>';
+var escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;
+
+```
+
+### escapeHeaderAttribute(attribute)
+
+Escape attribute value for use in HTTP header
+
+```javascript
+
+var a = Hoek.escapeHeaderAttribute('I said "go w\\o me"');  //returns I said \"go w\\o me\"
+
+
+```
+
+
+### escapeRegex(string)
+
+Escape string for Regex construction
+
+```javascript
+
+var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');  // returns 4\^f\$s\.4\*5\+\-_\?%\=#\!\:@\|~\\\/`"\(>\)\[<\]d\{\}s\,
+
+
+
+```
+
+# Errors
+
+### assert(message)
+
+```javascript
+
+var a = 1, b =2;
+
+Hoek.assert(a === b, 'a should equal b');  // ABORT: a should equal b
+
+```
+
+### abort(message)
+
+First checks if process.env.NODE_ENV === 'test', and if so, throws error message. Otherwise,
+displays most recent stack and then exits process.
+
+
+
+### displayStack(slice)
+
+Displays the trace stack
+
+```javascript
+
+var stack = Hoek.displayStack();
+console.log(stack) // returns something like:
+
+[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',
+  'Module._compile (module.js:449:26)',
+  'Module._extensions..js (module.js:467:10)',
+  'Module.load (module.js:356:32)',
+  'Module._load (module.js:312:12)',
+  'Module.runMain (module.js:492:10)',
+  'startup.processNextTick.process._tickCallback (node.js:244:9)' ]
+
+```
+
+### callStack(slice)
+
+Returns a trace stack array.
+
+```javascript
+
+var stack = Hoek.callStack();
+console.log(stack)  // returns something like:
+
+[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],
+  [ 'module.js', 449, 26, 'Module._compile', false ],
+  [ 'module.js', 467, 10, 'Module._extensions..js', false ],
+  [ 'module.js', 356, 32, 'Module.load', false ],
+  [ 'module.js', 312, 12, 'Module._load', false ],
+  [ 'module.js', 492, 10, 'Module.runMain', false ],
+  [ 'node.js',
+    244,
+    9,
+    'startup.processNextTick.process._tickCallback',
+    false ] ]
+
+
+```
+
+### toss(condition)
+
+toss(condition /*, [message], callback */)
+
+Return an error as first argument of a callback
+
+
+# Load Files
+
+### loadPackage(dir)
+
+Load and parse package.json process root or given directory
+
+```javascript
+
+var pack = Hoek.loadPackage();  // pack.name === 'hoek'
+
+```
+
+### loadDirModules(path, excludeFiles, target) 
+
+Loads modules from a given path; option to exclude files (array).
+
+
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/index.js	(revision 484)
@@ -0,0 +1,1 @@
+module.exports = require('./lib');
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/lib/escape.js	(revision 484)
@@ -0,0 +1,132 @@
+// Declare internals
+
+var internals = {};
+
+
+exports.escapeJavaScript = function (input) {
+
+    if (!input) {
+        return '';
+    }
+
+    var escaped = '';
+
+    for (var i = 0, il = input.length; i < il; ++i) {
+
+        var charCode = input.charCodeAt(i);
+
+        if (internals.isSafe(charCode)) {
+            escaped += input[i];
+        }
+        else {
+            escaped += internals.escapeJavaScriptChar(charCode);
+        }
+    }
+
+    return escaped;
+};
+
+
+exports.escapeHtml = function (input) {
+
+    if (!input) {
+        return '';
+    }
+
+    var escaped = '';
+
+    for (var i = 0, il = input.length; i < il; ++i) {
+
+        var charCode = input.charCodeAt(i);
+
+        if (internals.isSafe(charCode)) {
+            escaped += input[i];
+        }
+        else {
+            escaped += internals.escapeHtmlChar(charCode);
+        }
+    }
+
+    return escaped;
+};
+
+
+internals.escapeJavaScriptChar = function (charCode) {
+
+    if (charCode >= 256) {
+        return '\\u' + internals.padLeft('' + charCode, 4);
+    }
+
+    var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
+    return '\\x' + internals.padLeft(hexValue, 2);
+};
+
+
+internals.escapeHtmlChar = function (charCode) {
+
+    var namedEscape = internals.namedHtml[charCode];
+    if (typeof namedEscape !== 'undefined') {
+        return namedEscape;
+    }
+
+    if (charCode >= 256) {
+        return '&#' + charCode + ';';
+    }
+
+    var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
+    return '&#x' + internals.padLeft(hexValue, 2) + ';';
+};
+
+
+internals.padLeft = function (str, len) {
+
+    while (str.length < len) {
+        str = '0' + str;
+    }
+
+    return str;
+};
+
+
+internals.isSafe = function (charCode) {
+
+    return (typeof internals.safeCharCodes[charCode] !== 'undefined');
+};
+
+
+internals.namedHtml = {
+    '38': '&amp;',
+    '60': '&lt;',
+    '62': '&gt;',
+    '34': '&quot;',
+    '160': '&nbsp;',
+    '162': '&cent;',
+    '163': '&pound;',
+    '164': '&curren;',
+    '169': '&copy;',
+    '174': '&reg;'
+};
+
+
+internals.safeCharCodes = (function () {
+
+    var safe = {};
+
+    for (var i = 32; i < 123; ++i) {
+
+        if ((i >= 97 && i <= 122) ||         // a-z
+            (i >= 65 && i <= 90) ||          // A-Z
+            (i >= 48 && i <= 57) ||          // 0-9
+            i === 32 ||                      // space
+            i === 46 ||                      // .
+            i === 44 ||                      // ,
+            i === 45 ||                      // -
+            i === 58 ||                      // :
+            i === 95) {                      // _
+
+            safe[i] = null;
+        }
+    }
+
+    return safe;
+}());
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js	(revision 484)
@@ -0,0 +1,580 @@
+// Load modules
+
+var Fs = require('fs');
+var Escape = require('./escape');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Clone object or array
+
+exports.clone = function (obj, seen) {
+
+    if (typeof obj !== 'object' ||
+        obj === null) {
+
+        return obj;
+    }
+
+    seen = seen || { orig: [], copy: [] };
+
+    var lookup = seen.orig.indexOf(obj);
+    if (lookup !== -1) {
+        return seen.copy[lookup];
+    }
+
+    var newObj = (obj instanceof Array) ? [] : {};
+
+    seen.orig.push(obj);
+    seen.copy.push(newObj);
+
+    for (var i in obj) {
+        if (obj.hasOwnProperty(i)) {
+            if (obj[i] instanceof Buffer) {
+                newObj[i] = new Buffer(obj[i]);
+            }
+            else if (obj[i] instanceof Date) {
+                newObj[i] = new Date(obj[i].getTime());
+            }
+            else if (obj[i] instanceof RegExp) {
+                var flags = '' + (obj[i].global ? 'g' : '') + (obj[i].ignoreCase ? 'i' : '') + (obj[i].multiline ? 'm' : '');
+                newObj[i] = new RegExp(obj[i].source, flags);
+            }
+            else {
+                newObj[i] = exports.clone(obj[i], seen);
+            }
+        }
+    }
+
+    return newObj;
+};
+
+
+// Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
+
+exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {
+
+    exports.assert(target && typeof target == 'object', 'Invalid target value: must be an object');
+    exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');
+
+    if (!source) {
+        return target;
+    }
+
+    if (source instanceof Array) {
+        exports.assert(target instanceof Array, 'Cannot merge array onto an object');
+        if (isMergeArrays === false) {                                                  // isMergeArrays defaults to true
+            target.length = 0;                                                          // Must not change target assignment
+        }
+
+        source.forEach(function (item) {
+
+            target.push(item);
+        });
+
+        return target;
+    }
+
+    Object.keys(source).forEach(function (key) {
+
+        var value = source[key];
+        if (value &&
+            typeof value === 'object') {
+
+            if (!target[key] ||
+                typeof target[key] !== 'object') {
+
+                target[key] = exports.clone(value);
+            }
+            else {
+                exports.merge(target[key], source[key], isNullOverride, isMergeArrays);
+            }
+        }
+        else {
+            if (value !== null && value !== undefined) {            // Explicit to preserve empty strings
+                target[key] = value;
+            }
+            else if (isNullOverride !== false) {                    // Defaults to true
+                target[key] = value;
+            }
+        }
+    });
+
+    return target;
+};
+
+
+// Apply options to a copy of the defaults
+
+exports.applyToDefaults = function (defaults, options) {
+
+    exports.assert(defaults && typeof defaults == 'object', 'Invalid defaults value: must be an object');
+    exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
+
+    if (!options) {                                                 // If no options, return null
+        return null;
+    }
+
+    var copy = exports.clone(defaults);
+
+    if (options === true) {                                         // If options is set to true, use defaults
+        return copy;
+    }
+
+    return exports.merge(copy, options, false, false);
+};
+
+
+// Remove duplicate items from array
+
+exports.unique = function (array, key) {
+
+    var index = {};
+    var result = [];
+
+    for (var i = 0, il = array.length; i < il; ++i) {
+        var id = (key ? array[i][key] : array[i]);
+        if (index[id] !== true) {
+
+            result.push(array[i]);
+            index[id] = true;
+        }
+    }
+
+    return result;
+};
+
+
+// Convert array into object
+
+exports.mapToObject = function (array, key) {
+
+    if (!array) {
+        return null;
+    }
+
+    var obj = {};
+    for (var i = 0, il = array.length; i < il; ++i) {
+        if (key) {
+            if (array[i][key]) {
+                obj[array[i][key]] = true;
+            }
+        }
+        else {
+            obj[array[i]] = true;
+        }
+    }
+
+    return obj;
+};
+
+
+// Find the common unique items in two arrays
+
+exports.intersect = function (array1, array2) {
+
+    if (!array1 || !array2) {
+        return [];
+    }
+
+    var common = [];
+    var hash = (array1 instanceof Array ? exports.mapToObject(array1) : array1);
+    var found = {};
+    for (var i = 0, il = array2.length; i < il; ++i) {
+        if (hash[array2[i]] && !found[array2[i]]) {
+            common.push(array2[i]);
+            found[array2[i]] = true;
+        }
+    }
+
+    return common;
+};
+
+
+// Find which keys are present
+
+exports.matchKeys = function (obj, keys) {
+
+    var matched = [];
+    for (var i = 0, il = keys.length; i < il; ++i) {
+        if (obj.hasOwnProperty(keys[i])) {
+            matched.push(keys[i]);
+        }
+    }
+    return matched;
+};
+
+
+// Flatten array
+
+exports.flatten = function (array, target) {
+
+    var result = target || [];
+
+    for (var i = 0, il = array.length; i < il; ++i) {
+        if (Array.isArray(array[i])) {
+            exports.flatten(array[i], result);
+        }
+        else {
+            result.push(array[i]);
+        }
+    }
+
+    return result;
+};
+
+
+// Remove keys
+
+exports.removeKeys = function (object, keys) {
+
+    for (var i = 0, il = keys.length; i < il; i++) {
+        delete object[keys[i]];
+    }
+};
+
+
+// Convert an object key chain string ('a.b.c') to reference (object[a][b][c])
+
+exports.reach = function (obj, chain) {
+
+    var path = chain.split('.');
+    var ref = obj;
+    path.forEach(function (level) {
+
+        if (ref) {
+            ref = ref[level];
+        }
+    });
+
+    return ref;
+};
+
+
+// Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
+
+exports.inheritAsync = function (self, obj, keys) {
+
+    keys = keys || null;
+
+    for (var i in obj) {
+        if (obj.hasOwnProperty(i)) {
+            if (keys instanceof Array &&
+                keys.indexOf(i) < 0) {
+
+                continue;
+            }
+
+            self.prototype[i] = (function (fn) {
+
+                return function (next) {
+
+                    var result = null;
+                    try {
+                        result = fn();
+                    }
+                    catch (err) {
+                        return next(err);
+                    }
+
+                    return next(null, result);
+                };
+            })(obj[i]);
+        }
+    }
+};
+
+
+exports.formatStack = function (stack) {
+
+    var trace = [];
+    stack.forEach(function (item) {
+
+        trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
+    });
+
+    return trace;
+};
+
+
+exports.formatTrace = function (trace) {
+
+    var display = [];
+    trace.forEach(function (row) {
+
+        display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
+    });
+
+    return display;
+};
+
+
+exports.callStack = function (slice) {
+
+    // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
+
+    var v8 = Error.prepareStackTrace;
+    Error.prepareStackTrace = function (err, stack) {
+
+        return stack;
+    };
+
+    var capture = {};
+    Error.captureStackTrace(capture, arguments.callee);
+    var stack = capture.stack;
+
+    Error.prepareStackTrace = v8;
+
+    var trace = exports.formatStack(stack);
+
+    if (slice) {
+        return trace.slice(slice);
+    }
+
+    return trace;
+};
+
+
+exports.displayStack = function (slice) {
+
+    var trace = exports.callStack(slice === undefined ? 1 : slice + 1);
+
+    return exports.formatTrace(trace);
+};
+
+
+exports.abortThrow = false;
+
+
+exports.abort = function (message, hideStack) {
+
+    if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
+        throw new Error(message || 'Unknown error');
+    }
+
+    var stack = '';
+    if (!hideStack) {
+        stack = exports.displayStack(1).join('\n\t');
+    }
+    console.log('ABORT: ' + message + '\n\t' + stack);
+    process.exit(1);
+};
+
+
+exports.assert = function (condition /*, msg1, msg2, msg3 */) {
+
+    if (condition) {
+        return;
+    }
+
+    var msgs = Array.prototype.slice.call(arguments, 1);
+    msgs = msgs.map(function (msg) {
+
+        return typeof msg === 'string' ? msg : msg instanceof Error ? msg.message : JSON.stringify(msg);
+    });
+    throw new Error(msgs.join(' ') || 'Unknown error');
+};
+
+
+exports.loadDirModules = function (path, excludeFiles, target) {      // target(filename, name, capName)
+
+    var exclude = {};
+    for (var i = 0, il = excludeFiles.length; i < il; ++i) {
+        exclude[excludeFiles[i] + '.js'] = true;
+    }
+
+    Fs.readdirSync(path).forEach(function (filename) {
+
+        if (/\.js$/.test(filename) &&
+            !exclude[filename]) {
+
+            var name = filename.substr(0, filename.lastIndexOf('.'));
+            var capName = name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();
+
+            if (typeof target !== 'function') {
+                target[capName] = require(path + '/' + name);
+            }
+            else {
+                target(path + '/' + name, name, capName);
+            }
+        }
+    });
+};
+
+
+exports.rename = function (obj, from, to) {
+
+    obj[to] = obj[from];
+    delete obj[from];
+};
+
+
+exports.Timer = function () {
+
+    this.reset();
+};
+
+
+exports.Timer.prototype.reset = function () {
+
+    this.ts = Date.now();
+};
+
+
+exports.Timer.prototype.elapsed = function () {
+
+    return Date.now() - this.ts;
+};
+
+
+// Load and parse package.json process root or given directory
+
+exports.loadPackage = function (dir) {
+
+    var result = {};
+    var filepath = (dir || process.env.PWD) + '/package.json';
+    if (Fs.existsSync(filepath)) {
+        try {
+            result = JSON.parse(Fs.readFileSync(filepath));
+        }
+        catch (e) { }
+    }
+
+    return result;
+};
+
+
+// Escape string for Regex construction
+
+exports.escapeRegex = function (string) {
+
+    // Escape ^$.*+-?=!:|\/()[]{},
+    return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
+};
+
+
+// Return an error as first argument of a callback
+
+exports.toss = function (condition /*, [message], next */) {
+
+    var message = (arguments.length === 3 ? arguments[1] : '');
+    var next = (arguments.length === 3 ? arguments[2] : arguments[1]);
+
+    var err = (message instanceof Error ? message : (message ? new Error(message) : (condition instanceof Error ? condition : new Error())));
+
+    if (condition instanceof Error ||
+        !condition) {
+
+        return next(err);
+    }
+};
+
+
+// Base64url (RFC 4648) encode
+
+exports.base64urlEncode = function (value) {
+
+    return (new Buffer(value, 'binary')).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
+};
+
+
+// Base64url (RFC 4648) decode
+
+exports.base64urlDecode = function (encoded) {
+
+    if (encoded &&
+        !encoded.match(/^[\w\-]*$/)) {
+
+        return new Error('Invalid character');
+    }
+
+    try {
+        return (new Buffer(encoded.replace(/-/g, '+').replace(/:/g, '/'), 'base64')).toString('binary');
+    }
+    catch (err) {
+        return err;
+    }
+};
+
+
+// Escape attribute value for use in HTTP header
+
+exports.escapeHeaderAttribute = function (attribute) {
+
+    // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "
+
+    exports.assert(attribute.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/), 'Bad attribute value (' + attribute + ')');
+
+    return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"');                             // Escape quotes and slash
+};
+
+
+exports.escapeHtml = function (string) {
+
+    return Escape.escapeHtml(string);
+};
+
+
+exports.escapeJavaScript = function (string) {
+
+    return Escape.escapeJavaScript(string);
+};
+
+
+/*
+var event = {
+    timestamp: now.getTime(),
+    tags: ['tag'],
+    data: { some: 'data' }
+};
+*/
+
+exports.consoleFunc = console.log;
+
+exports.printEvent = function (event) {
+
+    var pad = function (value) {
+
+        return (value < 10 ? '0' : '') + value;
+    };
+
+    var now = new Date(event.timestamp);
+    var timestring = (now.getYear() - 100).toString() +
+        pad(now.getMonth() + 1) +
+        pad(now.getDate()) +
+        '/' +
+        pad(now.getHours()) +
+        pad(now.getMinutes()) +
+        pad(now.getSeconds()) +
+        '.' +
+        now.getMilliseconds();
+
+    var data = event.data;
+    if (typeof event.data !== 'string') {
+        try {
+            data = JSON.stringify(event.data);
+        }
+        catch (e) {
+            data = 'JSON Error: ' + e.message;
+        }
+    }
+
+    var output = timestring + ', ' + event.tags[0] + ', ' + data;
+    exports.consoleFunc(output);
+};
+
+
+exports.nextTick = function (callback) {
+
+    return function () {
+
+        var args = arguments;
+        process.nextTick(function () {
+
+            callback.apply(null, args);
+        });
+    };
+};
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/package.json	(revision 484)
@@ -0,0 +1,49 @@
+{
+  "name": "hoek",
+  "description": "General purpose node utilities",
+  "version": "0.8.5",
+  "author": {
+    "name": "Eran Hammer",
+    "email": "eran@hueniverse.com",
+    "url": "http://hueniverse.com"
+  },
+  "contributors": [
+    {
+      "name": "Van Nguyen",
+      "email": "the.gol.effect@gmail.com"
+    }
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/spumko/hoek"
+  },
+  "main": "index",
+  "keywords": [
+    "utilities"
+  ],
+  "engines": {
+    "node": ">=0.8.0"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "lab": "0.1.x",
+    "complexity-report": "0.x.x"
+  },
+  "scripts": {
+    "test": "make test-cov"
+  },
+  "licenses": [
+    {
+      "type": "BSD",
+      "url": "http://github.com/spumko/hoek/raw/master/LICENSE"
+    }
+  ],
+  "readme": "<a href=\"https://github.com/spumko\"><img src=\"https://raw.github.com/spumko/spumko/master/images/from.png\" align=\"right\" /></a>\r\n![hoek Logo](https://raw.github.com/spumko/hoek/master/images/hoek.png)\r\n\r\nGeneral purpose node utilities\r\n\r\n[![Build Status](https://secure.travis-ci.org/spumko/hoek.png)](http://travis-ci.org/spumko/hoek)\r\n\r\n# Table of Contents\r\n\r\n* [Introduction](#introduction \"Introduction\")\r\n* [Object](#object \"Object\")\r\n  * [clone](#cloneobj \"clone\")\r\n  * [merge](#mergetarget-source-isnulloverride-ismergearrays \"merge\")\r\n  * [applyToDefaults](#applytodefaultsdefaults-options \"applyToDefaults\")\r\n  * [unique](#uniquearray-key \"unique\")\r\n  * [mapToObject](#maptoobjectarray-key \"mapToObject\")\r\n  * [intersect](#intersectarray1-array2 \"intersect\")\r\n  * [matchKeys](#matchkeysobj-keys \"matchKeys\")\r\n  * [flatten](#flattenarray-target \"flatten\")\r\n  * [removeKeys](#removekeysobject-keys \"removeKeys\")\r\n  * [reach](#reachobj-chain \"reach\")\r\n  * [inheritAsync](#inheritasyncself-obj-keys \"inheritAsync\")\r\n  * [rename](#renameobj-from-to \"rename\")\r\n* [Timer](#timer \"Timer\")\r\n* [Binary Encoding/Decoding](#binary \"Binary Encoding/Decoding\")\r\n  * [base64urlEncode](#binary64urlEncodevalue \"binary64urlEncode\")\r\n  * [base64urlDecode](#binary64urlDecodevalue \"binary64urlDecode\")\r\n* [Escaping Characters](#escaped \"Escaping Characters\")\r\n  * [escapeHtml](#escapeHtmlstring \"escapeHtml\")\r\n  * [escapeHeaderAttribute](#escapeHeaderAttributeattribute \"escapeHeaderAttribute\")\r\n  * [escapeRegex](#escapeRegexstring \"escapeRegex\")\r\n* [Errors](#errors \"Errors\")\r\n  * [assert](#assertmessage \"assert\")\r\n  * [abort](#abortmessage \"abort\")\r\n  * [displayStack](#displayStackslice \"displayStack\")\r\n  * [callStack](#callStackslice \"callStack\")\r\n  * [toss](#tosscondition \"toss\")\r\n* [Load files](#load-files \"Load Files\")\r\n  * [loadPackage](#loadPackagedir \"loadpackage\")\r\n  * [loadDirModules](#loadDirModulespath-excludefiles-target \"loaddirmodules\")\r\n\r\n\r\n\r\n# Introduction\r\n\r\nThe *Hoek* general purpose node utilities library is used to aid in a variety of manners. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more. \r\n\r\nFor example, to use Hoek to set configuration with default options:\r\n```javascript\r\nvar Hoek = require('hoek');\r\n\r\nvar default = {url : \"www.github.com\", port : \"8000\", debug : true}\r\n\r\nvar config = Hoek.applyToDefaults(default, {port : \"3000\", admin : true});\r\n\r\n// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }\r\n```\r\n\r\nUnder each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the var Hoek = require('hoek') is omitted for brevity.\r\n\r\n## Object\r\n\r\nHoek provides several helpful methods for objects and arrays.\r\n\r\n### clone(obj)\r\n\r\nThis method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects). \r\n\r\n```javascript\r\n\r\nvar nestedObj = {\r\n        w: /^something$/ig,\r\n        x: {\r\n            a: [1, 2, 3],\r\n            b: 123456,\r\n            c: new Date()\r\n        },\r\n        y: 'y',\r\n        z: new Date()\r\n    };\r\n\r\nvar copy = Hoek.clone(nestedObj);\r\n\r\ncopy.x.b = 100;\r\n\r\nconsole.log(copy.y)        // results in 'y'\r\nconsole.log(nestedObj.x.b) // results in 123456\r\nconsole.log(copy.x.b)      // results in 100\r\n```\r\n\r\n### merge(target, source, isNullOverride, isMergeArrays)\r\nisNullOverride, isMergeArrays default to true\r\n\r\nMerge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied\r\n\r\n\r\n```javascript\r\n\r\nvar target = {a: 1, b : 2}\r\nvar source = {a: 0, c: 5}\r\nvar source2 = {a: null, c: 5}\r\n\r\nvar targetArray = [1, 2, 3];\r\nvar sourceArray = [4, 5];\r\n\r\nvar newTarget = Hoek.merge(target, source);     // results in {a: 0, b: 2, c: 5}\r\nnewTarget = Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}\r\nnewTarget = Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}\r\n\r\nnewTarget = Hoek.merge(targetArray, sourceArray)              // results in [1, 2, 3, 4, 5]\r\nnewTarget = Hoek.merge(targetArray, sourceArray, true, false) // results in [4, 5]\r\n\r\n\r\n\r\n\r\n```\r\n\r\n### applyToDefaults(defaults, options)\r\n\r\nApply options to a copy of the defaults\r\n\r\n```javascript\r\n\r\nvar defaults = {host: \"localhost\", port: 8000};\r\nvar options = {port: 8080};\r\n\r\nvar config = Hoek.applyToDefaults(defaults, options); // results in {host: \"localhost\", port: 8080};\r\n\r\n\r\n```\r\n\r\n### unique(array, key)\r\n\r\nRemove duplicate items from Array\r\n\r\n```javascript\r\n\r\nvar array = [1, 2, 2, 3, 3, 4, 5, 6];\r\n\r\nvar newArray = Hoek.unique(array); // results in [1,2,3,4,5,6];\r\n\r\narray = [{id: 1}, {id: 1}, {id: 2}];\r\n\r\nnewArray = Hoek.unique(array, \"id\") // results in [{id: 1}, {id: 2}]\r\n\r\n```\r\n\r\n### mapToObject(array, key)\r\n\r\nConvert an Array into an Object\r\n\r\n```javascript\r\n\r\nvar array = [1,2,3];\r\nvar newObject = Hoek.mapToObject(array); // results in [{\"1\": true}, {\"2\": true}, {\"3\": true}]\r\n\r\narray = [{id: 1}, {id: 2}];\r\nnewObject = Hoek.mapToObject(array, \"id\") // results in [{\"id\": 1}, {\"id\": 2}]\r\n\r\n```\r\n### intersect(array1, array2)\r\n\r\nFind the common unique items in two arrays\r\n\r\n```javascript\r\n\r\nvar array1 = [1, 2, 3];\r\nvar array2 = [1, 4, 5];\r\n\r\nvar newArray = Hoek.intersect(array1, array2) // results in [1]\r\n\r\n```\r\n\r\n### matchKeys(obj, keys) \r\n\r\nFind which keys are present\r\n\r\n```javascript\r\n\r\nvar obj = {a: 1, b: 2, c: 3};\r\nvar keys = [\"a\", \"e\"];\r\n\r\nHoek.matchKeys(obj, keys) // returns [\"a\"]\r\n\r\n```\r\n\r\n### flatten(array, target)\r\n\r\nFlatten an array\r\n\r\n```javascript\r\n\r\nvar array = [1, 2, 3];\r\nvar target = [4, 5]; \r\n\r\nvar flattenedArray = Hoek.flatten(array, target) // results in [4, 5, 1, 2, 3];\r\n\r\n```\r\n\r\n### removeKeys(object, keys)\r\n\r\nRemove keys\r\n\r\n```javascript\r\n\r\nvar object = {a: 1, b: 2, c: 3, d: 4};\r\n\r\nvar keys = [\"a\", \"b\"];\r\n\r\nHoek.removeKeys(object, keys) // object is now {c: 3, d: 4}\r\n\r\n```\r\n\r\n### reach(obj, chain)\r\n\r\nConverts an object key chain string to reference\r\n\r\n```javascript\r\n\r\nvar chain = 'a.b.c';\r\nvar obj = {a : {b : { c : 1}}};\r\n\r\nHoek.reach(obj, chain) // returns 1\r\n\r\n```\r\n\r\n### inheritAsync(self, obj, keys) \r\n\r\nInherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors\r\n\r\n```javascript\r\n\r\nvar targetFunc = function () { };\r\n\r\nvar proto = {\r\n                a: function () {\r\n                    return 'a!';\r\n                },\r\n                b: function () {\r\n                    return 'b!';\r\n                },\r\n                c: function () {\r\n                    throw new Error('c!');\r\n                }\r\n            };\r\n\r\nvar keys = ['a', 'c'];\r\n\r\nHoek.inheritAsync(targetFunc, proto, ['a', 'c']);\r\n\r\nvar target = new targetFunc();\r\n\r\ntarget.a(function(err, result){console.log(result)}         // returns 'a!'       \r\n\r\ntarget.c(function(err, result){console.log(result)}         // returns undefined\r\n\r\ntarget.b(function(err, result){console.log(result)}         // gives error: Object [object Object] has no method 'b'\r\n\r\n```\r\n\r\n### rename(obj, from, to)\r\n\r\nRename a key of an object\r\n\r\n```javascript\r\n\r\nvar obj = {a : 1, b : 2};\r\n\r\nHoek.rename(obj, \"a\", \"c\");     // obj is now {c : 1, b : 2}\r\n\r\n```\r\n\r\n\r\n# Timer\r\n\r\nA Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.\r\n\r\n```javascript\r\n\r\n\r\nexample : \r\n\r\n\r\nvar timerObj = new Hoek.Timer();\r\nconsole.log(\"Time is now: \" + timerObj.ts)\r\nconsole.log(\"Elapsed time from initialization: \" + timerObj.elapsed() + 'milliseconds')\r\n\r\n```\r\n\r\n# Binary Encoding/Decoding\r\n\r\n### base64urlEncode(value)\r\n\r\nEncodes value in Base64 or URL encoding\r\n\r\n### base64urlDecode(value)\r\n\r\nDecodes data in Base64 or URL encoding.\r\n# Escaping Characters\r\n\r\nHoek provides convenient methods for escaping html characters. The escaped characters are as followed:\r\n\r\n```javascript\r\n\r\ninternals.htmlEscaped = {\r\n    '&': '&amp;',\r\n    '<': '&lt;',\r\n    '>': '&gt;',\r\n    '\"': '&quot;',\r\n    \"'\": '&#x27;',\r\n    '`': '&#x60;'\r\n};\r\n\r\n```\r\n\r\n### escapeHtml(string)\r\n\r\n```javascript\r\n\r\nvar string = '<html> hey </html>';\r\nvar escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;\r\n\r\n```\r\n\r\n### escapeHeaderAttribute(attribute)\r\n\r\nEscape attribute value for use in HTTP header\r\n\r\n```javascript\r\n\r\nvar a = Hoek.escapeHeaderAttribute('I said \"go w\\\\o me\"');  //returns I said \\\"go w\\\\o me\\\"\r\n\r\n\r\n```\r\n\r\n\r\n### escapeRegex(string)\r\n\r\nEscape string for Regex construction\r\n\r\n```javascript\r\n\r\nvar a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\\\/`\"(>)[<]d{}s,');  // returns 4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`\"\\(>\\)\\[<\\]d\\{\\}s\\,\r\n\r\n\r\n\r\n```\r\n\r\n# Errors\r\n\r\n### assert(message)\r\n\r\n```javascript\r\n\r\nvar a = 1, b =2;\r\n\r\nHoek.assert(a === b, 'a should equal b');  // ABORT: a should equal b\r\n\r\n```\r\n\r\n### abort(message)\r\n\r\nFirst checks if process.env.NODE_ENV === 'test', and if so, throws error message. Otherwise,\r\ndisplays most recent stack and then exits process.\r\n\r\n\r\n\r\n### displayStack(slice)\r\n\r\nDisplays the trace stack\r\n\r\n```javascript\r\n\r\nvar stack = Hoek.displayStack();\r\nconsole.log(stack) // returns something like:\r\n\r\n[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',\r\n  'Module._compile (module.js:449:26)',\r\n  'Module._extensions..js (module.js:467:10)',\r\n  'Module.load (module.js:356:32)',\r\n  'Module._load (module.js:312:12)',\r\n  'Module.runMain (module.js:492:10)',\r\n  'startup.processNextTick.process._tickCallback (node.js:244:9)' ]\r\n\r\n```\r\n\r\n### callStack(slice)\r\n\r\nReturns a trace stack array.\r\n\r\n```javascript\r\n\r\nvar stack = Hoek.callStack();\r\nconsole.log(stack)  // returns something like:\r\n\r\n[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],\r\n  [ 'module.js', 449, 26, 'Module._compile', false ],\r\n  [ 'module.js', 467, 10, 'Module._extensions..js', false ],\r\n  [ 'module.js', 356, 32, 'Module.load', false ],\r\n  [ 'module.js', 312, 12, 'Module._load', false ],\r\n  [ 'module.js', 492, 10, 'Module.runMain', false ],\r\n  [ 'node.js',\r\n    244,\r\n    9,\r\n    'startup.processNextTick.process._tickCallback',\r\n    false ] ]\r\n\r\n\r\n```\r\n\r\n### toss(condition)\r\n\r\ntoss(condition /*, [message], callback */)\r\n\r\nReturn an error as first argument of a callback\r\n\r\n\r\n# Load Files\r\n\r\n### loadPackage(dir)\r\n\r\nLoad and parse package.json process root or given directory\r\n\r\n```javascript\r\n\r\nvar pack = Hoek.loadPackage();  // pack.name === 'hoek'\r\n\r\n```\r\n\r\n### loadDirModules(path, excludeFiles, target) \r\n\r\nLoads modules from a given path; option to exclude files (array).\r\n\r\n\r\n\r\n\r\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/spumko/hoek/issues"
+  },
+  "homepage": "https://github.com/spumko/hoek",
+  "_id": "hoek@0.8.5",
+  "_from": "hoek@0.8.x"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js	(revision 484)
@@ -0,0 +1,86 @@
+// Load modules
+
+var Lab = require('lab');
+var Hoek = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hoek', function () {
+
+    describe('#escapeJavaScript', function () {
+
+        it('encodes / characters', function (done) {
+
+            var encoded = Hoek.escapeJavaScript('<script>alert(1)</script>');
+            expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e');
+            done();
+        });
+
+        it('encodes \' characters', function (done) {
+
+            var encoded = Hoek.escapeJavaScript('something(\'param\')');
+            expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29');
+            done();
+        });
+
+        it('encodes large unicode characters with the correct padding', function (done) {
+
+            var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000));
+            expect(encoded).to.equal('\\u0500\\u1000');
+            done();
+        });
+
+        it('doesn\'t throw an exception when passed null', function (done) {
+
+            var encoded = Hoek.escapeJavaScript(null);
+            expect(encoded).to.equal('');
+            done();
+        });
+    });
+
+    describe('#escapeHtml', function () {
+
+        it('encodes / characters', function (done) {
+
+            var encoded = Hoek.escapeHtml('<script>alert(1)</script>');
+            expect(encoded).to.equal('&lt;script&gt;alert&#x28;1&#x29;&lt;&#x2f;script&gt;');
+            done();
+        });
+
+        it('encodes < and > as named characters', function (done) {
+
+            var encoded = Hoek.escapeHtml('<script><>');
+            expect(encoded).to.equal('&lt;script&gt;&lt;&gt;');
+            done();
+        });
+
+        it('encodes large unicode characters', function (done) {
+
+            var encoded = Hoek.escapeHtml(String.fromCharCode(500) + String.fromCharCode(1000));
+            expect(encoded).to.equal('&#500;&#1000;');
+            done();
+        });
+
+        it('doesn\'t throw an exception when passed null', function (done) {
+
+            var encoded = Hoek.escapeHtml(null);
+            expect(encoded).to.equal('');
+            done();
+        });
+    });
+});
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js	(revision 484)
@@ -0,0 +1,1069 @@
+// Load modules
+
+var Lab = require('lab');
+var Hoek = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hoek', function () {
+
+    var nestedObj = {
+        v: [7,8,9],
+        w: /^something$/igm,
+        x: {
+            a: [1, 2, 3],
+            b: 123456,
+            c: new Date(),
+            d: /hi/igm,
+            e: /hello/
+        },
+        y: 'y',
+        z: new Date()
+    };
+
+    var dupsArray = [nestedObj, { z: 'z' }, nestedObj];
+    var reducedDupsArray = [nestedObj, { z: 'z' }];
+
+    describe('#clone', function () {
+
+        it('should clone a nested object', function (done) {
+
+            var a = nestedObj;
+            var b = Hoek.clone(a);
+
+            expect(a).to.deep.equal(b);
+            expect(a.z.getTime()).to.equal(b.z.getTime());
+            done();
+        });
+
+        it('should clone a null object', function (done) {
+
+            var b = Hoek.clone(null);
+
+            expect(b).to.equal(null);
+            done();
+        });
+
+        it('should not convert undefined properties to null', function (done) {
+
+            var obj = { something: undefined };
+            var b = Hoek.clone(obj);
+
+            expect(typeof b.something).to.equal('undefined');
+            done();
+        });
+
+        it('should not throw on circular reference', function (done) {
+
+            var a = {};
+            a.x = a;
+
+            var test = (function () {
+
+                var b = Hoek.clone(a);
+            });
+
+            expect(test).to.not.throw();
+            done();
+        });
+
+        it('should properly clone circular reference', function (done) {
+
+            var x = {
+                'z': new Date()
+            };
+            x.y = x;
+
+            var b = Hoek.clone(x);
+            expect(Object.keys(b.y)).to.deep.equal(Object.keys(x))
+            expect(b.z).to.not.equal(x.z);
+            expect(b.y).to.not.equal(x.y);
+            expect(b.y.z).to.not.equal(x.y.z);
+            expect(b.y).to.equal(b);
+            expect(b.y.y.y.y).to.equal(b);
+            done();
+        });
+
+        it('should properly clone deeply nested object', function (done) {
+
+            var a = {
+                x: {
+                    y: {
+                        a: [1, 2, 3],
+                        b: 123456,
+                        c: new Date(),
+                        d: /hi/igm,
+                        e: /hello/
+                    },
+                }
+            };
+
+            var b = Hoek.clone(a);
+
+            expect(a).to.deep.equal(b);
+            expect(a.x.y.c.getTime()).to.equal(b.x.y.c.getTime());
+            done();
+        });
+
+        it('should properly clone arrays', function (done) {
+
+            var a = [1,2,3];
+
+            var b = Hoek.clone(a);
+
+            expect(a).to.deep.equal(b);
+            done();
+        });
+
+        it('should perform actual copy for shallow keys (no pass by reference)', function (done) {
+
+            var x = Hoek.clone(nestedObj);
+            var y = Hoek.clone(nestedObj);
+
+            // Date
+            expect(x.z).to.not.equal(nestedObj.z);
+            expect(x.z).to.not.equal(y.z);
+
+            // Regex
+            expect(x.w).to.not.equal(nestedObj.w);
+            expect(x.w).to.not.equal(y.w);
+
+            // Array
+            expect(x.v).to.not.equal(nestedObj.v);
+            expect(x.v).to.not.equal(y.v);
+
+            // Immutable(s)
+            x.y = 5;
+            expect(x.y).to.not.equal(nestedObj.y);
+            expect(x.y).to.not.equal(y.y);
+
+            done();
+        });
+
+        it('should perform actual copy for deep keys (no pass by reference)', function (done) {
+
+            var x = Hoek.clone(nestedObj);
+            var y = Hoek.clone(nestedObj);
+
+            expect(x.x.c).to.not.equal(nestedObj.x.c);
+            expect(x.x.c).to.not.equal(y.x.c);
+
+            expect(x.x.c.getTime()).to.equal(nestedObj.x.c.getTime());
+            expect(x.x.c.getTime()).to.equal(y.x.c.getTime());
+            done();
+        });
+
+        it('copies functions with properties', function (done) {
+
+            var a = {
+                x: function () { return 1; },
+                y: {}
+            };
+            a.x.z = 'string in function';
+            a.x.v = function () { return 2; };
+            a.y.u = a.x;
+
+            var b = Hoek.clone(a);
+            expect(b.x()).to.equal(1);
+            expect(b.x.v()).to.equal(2);
+            expect(b.y.u).to.equal(b.x);
+            expect(b.x.z).to.equal('string in function');
+            done();
+        });
+
+        it('should copy a buffer', function(done){
+            var tls = {
+                key: new Buffer([1,2,3,4,5]),
+                cert: new Buffer([1,2,3,4,5,6,10])
+            }
+
+            copiedTls = Hoek.clone(tls);
+            expect(Buffer.isBuffer(copiedTls.key)).to.equal(true);
+            expect(JSON.stringify(copiedTls.key)).to.equal(JSON.stringify(tls.key))
+            expect(Buffer.isBuffer(copiedTls.cert)).to.equal(true);
+            expect(JSON.stringify(copiedTls.cert)).to.equal(JSON.stringify(tls.cert))
+            done();
+        });
+    });
+
+    describe('#merge', function () {
+
+        it('does not throw if source is null', function (done) {
+
+            var a = {};
+            var b = null;
+            var c = null;
+
+            expect(function () {
+
+                c = Hoek.merge(a, b);
+            }).to.not.throw();
+
+            expect(c).to.equal(a);
+            done();
+        });
+
+        it('does not throw if source is undefined', function (done) {
+
+            var a = {};
+            var b = undefined;
+            var c = null;
+
+            expect(function () {
+
+                c = Hoek.merge(a, b);
+            }).to.not.throw();
+
+            expect(c).to.equal(a);
+            done();
+        });
+
+        it('throws if source is not an object', function (done) {
+
+            expect(function () {
+
+                var a = {};
+                var b = 0;
+
+                Hoek.merge(a, b);
+            }).to.throw('Invalid source value: must be null, undefined, or an object');
+            done();
+        });
+
+        it('throws if target is not an object', function (done) {
+
+            expect(function () {
+
+                var a = 0;
+                var b = {};
+
+                Hoek.merge(a, b);
+            }).to.throw('Invalid target value: must be an object');
+            done();
+        });
+
+        it('throws if target is not an array and source is', function (done) {
+
+            expect(function () {
+
+                var a = {};
+                var b = [1, 2];
+
+                Hoek.merge(a, b);
+            }).to.throw('Cannot merge array onto an object');
+            done();
+        });
+
+        it('returns the same object when merging arrays', function (done) {
+
+            var a = [];
+            var b = [1, 2];
+
+            expect(Hoek.merge(a, b)).to.equal(a);
+            done();
+        });
+
+        it('should combine an empty object with a non-empty object', function (done) {
+
+            var a = {};
+            var b = nestedObj;
+
+            var c = Hoek.merge(a, b);
+            expect(a).to.deep.equal(b);
+            expect(c).to.deep.equal(b);
+            done();
+        });
+
+        it('should override values in target', function (done) {
+
+            var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
+            var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
+
+            var c = Hoek.merge(a, b);
+            expect(c.x).to.equal(null);
+            expect(c.y).to.equal(2);
+            expect(c.z).to.equal(4);
+            expect(c.v).to.equal(0);
+            expect(c.m).to.equal('123');
+            expect(c.t).to.deep.equal({ u: 6 });
+            done();
+        });
+
+        it('should override values in target (flip)', function (done) {
+
+            var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
+            var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
+
+            var d = Hoek.merge(b, a);
+            expect(d.x).to.equal(1);
+            expect(d.y).to.equal(2);
+            expect(d.z).to.equal(3);
+            expect(d.v).to.equal(5);
+            expect(d.m).to.equal('abc');
+            expect(d.t).to.deep.equal('test');
+            done();
+        });
+    });
+
+    describe('#applyToDefaults', function () {
+
+        var defaults = {
+            a: 1,
+            b: 2,
+            c: {
+                d: 3,
+                e: [5, 6]
+            },
+            f: 6,
+            g: 'test'
+        };
+
+        it('should return null if options is false', function (done) {
+
+            var result = Hoek.applyToDefaults(defaults, false);
+            expect(result).to.equal(null);
+            done();
+        });
+
+        it('should return a copy of defaults if options is true', function (done) {
+
+            var result = Hoek.applyToDefaults(defaults, true);
+            expect(result).to.deep.equal(result);
+            done();
+        });
+
+        it('should apply object to defaults', function (done) {
+
+            var obj = {
+                a: null,
+                c: {
+                    e: [4]
+                },
+                f: 0,
+                g: {
+                    h: 5
+                }
+            };
+
+            var result = Hoek.applyToDefaults(defaults, obj);
+            expect(result.c.e).to.deep.equal([4]);
+            expect(result.a).to.equal(1);
+            expect(result.b).to.equal(2);
+            expect(result.f).to.equal(0);
+            expect(result.g).to.deep.equal({ h: 5 });
+            done();
+        });
+    });
+
+    describe('#unique', function () {
+
+        it('should ensure uniqueness within array of objects based on subkey', function (done) {
+
+            var a = Hoek.unique(dupsArray, 'x');
+            expect(a).to.deep.equal(reducedDupsArray);
+            done();
+        });
+
+        it('removes duplicated without key', function (done) {
+
+            expect(Hoek.unique([1, 2, 3, 4, 2, 1, 5])).to.deep.equal([1, 2, 3, 4, 5]);
+            done();
+        });
+    });
+
+    describe('#mapToObject', function () {
+
+        it('should return null on null array', function (done) {
+
+            var a = Hoek.mapToObject(null);
+            expect(a).to.equal(null);
+            done();
+        });
+
+        it('should convert basic array to existential object', function (done) {
+
+            var keys = [1, 2, 3, 4];
+            var a = Hoek.mapToObject(keys);
+            for (var i in keys) {
+                expect(a[keys[i]]).to.equal(true);
+            }
+            done();
+        });
+
+        it('should convert array of objects to existential object', function (done) {
+
+            var keys = [{ x: 1 }, { x: 2 }, { x: 3 }];
+            var subkey = 'x';
+            var a = Hoek.mapToObject(keys, subkey);
+            for (var i in keys) {
+                expect(a[keys[i][subkey]]).to.equal(true);
+            }
+            done();
+        });
+    });
+
+    describe('#intersect', function () {
+
+        it('should return the common objects of two arrays', function (done) {
+
+            var array1 = [1, 2, 3, 4, 4, 5, 5];
+            var array2 = [5, 4, 5, 6, 7];
+            var common = Hoek.intersect(array1, array2);
+            expect(common.length).to.equal(2);
+            done();
+        });
+
+        it('should return an empty array if either input is null', function (done) {
+
+            expect(Hoek.intersect([1], null).length).to.equal(0);
+            expect(Hoek.intersect(null, [1]).length).to.equal(0);
+            done();
+        });
+
+        it('should return the common objects of object and array', function (done) {
+
+            var array1 = [1, 2, 3, 4, 4, 5, 5];
+            var array2 = [5, 4, 5, 6, 7];
+            var common = Hoek.intersect(Hoek.mapToObject(array1), array2);
+            expect(common.length).to.equal(2);
+            done();
+        });
+    });
+
+    describe('#matchKeys', function () {
+
+        it('should match the existing object keys', function (done) {
+
+            var obj = {
+                a: 1,
+                b: 2,
+                c: 3,
+                d: null
+            };
+
+            expect(Hoek.matchKeys(obj, ['b', 'c', 'd', 'e'])).to.deep.equal(['b', 'c', 'd']);
+            done();
+        });
+    });
+
+    describe('#flatten', function () {
+
+        it('should return a flat array', function (done) {
+
+            var result = Hoek.flatten([1, 2, [3, 4, [5, 6], [7], 8], [9], [10, [11, 12]], 13]);
+            expect(result.length).to.equal(13);
+            expect(result).to.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
+            done();
+        });
+    });
+
+    describe('#removeKeys', function () {
+
+        var objWithHiddenKeys = {
+            location: {
+                name: 'San Bruno'
+            },
+            company: {
+                name: '@WalmartLabs'
+            }
+        };
+
+        it('should delete params with definition\'s hide set to true', function (done) {
+
+            var a = Hoek.removeKeys(objWithHiddenKeys, ['location']);
+            expect(objWithHiddenKeys.location).to.not.exist;
+            expect(objWithHiddenKeys.company).to.exist;
+            done();
+        });
+    });
+
+    describe('#reach', function () {
+
+        var obj = {
+            a: {
+                b: {
+                    c: {
+                        d: 1,
+                        e: 2
+                    },
+                    f: 'hello'
+                },
+                g: {
+                    h: 3
+                }
+            },
+            i: function () { }
+        };
+
+        it('returns a valid member', function (done) {
+
+            expect(Hoek.reach(obj, 'a.b.c.d')).to.equal(1);
+            done();
+        });
+
+        it('returns null on null object', function (done) {
+
+            expect(Hoek.reach(null, 'a.b.c.d')).to.not.exist;
+            done();
+        });
+
+        it('returns null on missing member', function (done) {
+
+            expect(Hoek.reach(obj, 'a.b.c.d.x')).to.not.exist;
+            done();
+        });
+
+        it('returns null on invalid member', function (done) {
+
+            expect(Hoek.reach(obj, 'a.b.c.d-.x')).to.not.exist;
+            done();
+        });
+
+        it('returns function member', function (done) {
+
+            expect(typeof Hoek.reach(obj, 'i')).to.equal('function');
+            done();
+        });
+    });
+
+    describe('#inheritAsync', function () {
+
+        it('should inherit selected methods and wrap in async call', function (done) {
+
+            var proto = {
+                a: function () {
+                    return 'a!';
+                },
+                b: function () {
+                    return 'b!';
+                },
+                c: function () {
+                    throw new Error('c!');
+                }
+            };
+
+            var targetFunc = function () { };
+            targetFunc.prototype.c = function () {
+
+                return 'oops';
+            };
+
+            Hoek.inheritAsync(targetFunc, proto, ['a', 'c']);
+            var target = new targetFunc();
+
+            expect(typeof target.a).to.equal('function');
+            expect(typeof target.c).to.equal('function');
+            expect(target.b).to.not.exist;
+
+            target.a(function (err, result) {
+
+                expect(err).to.not.exist;
+                expect(result).to.equal('a!');
+
+                target.c(function (err, result) {
+
+                    expect(result).to.not.exist;
+                    expect(err.message).to.equal('c!');
+                    done();
+                });
+            });
+        });
+    });
+
+    describe('#callStack', function () {
+
+        it('should return the full call stack', function (done) {
+
+            var stack = Hoek.callStack();
+            expect(stack[0][0]).to.contain('index.js');
+            expect(stack[0][2]).to.equal(30);
+            done();
+        });
+    });
+
+    describe('#displayStack ', function () {
+
+        it('should return the full call stack for display', function (done) {
+
+            var stack = Hoek.displayStack();
+            expect(stack[0]).to.contain('test/index.js:');
+            done();
+        });
+
+        it('should include constructor functions correctly', function (done) {
+
+            var Something = function (next) {
+
+                next();
+            };
+
+            var something = new Something(function () {
+
+                var stack = Hoek.displayStack();
+                expect(stack[1]).to.contain('new Something');
+                done();
+            });
+        });
+    });
+
+    describe('#abort', function () {
+
+        it('should exit process when not in test mode', function (done) {
+
+            var env = process.env.NODE_ENV;
+            var write = process.stdout.write;
+            var exit = process.exit;
+
+            process.env.NODE_ENV = 'nottatest';
+            process.stdout.write = function () { };
+            process.exit = function (state) {
+
+                process.exit = exit;
+                process.env.NODE_ENV = env;
+                process.stdout.write = write;
+
+                expect(state).to.equal(1);
+                done();
+            };
+
+            Hoek.abort('Boom');
+        });
+
+        it('should throw when not in test mode and abortThrow is true', function (done) {
+
+            var env = process.env.NODE_ENV;
+            process.env.NODE_ENV = 'nottatest';
+            Hoek.abortThrow = true;
+
+            var fn = function () {
+
+                Hoek.abort('my error message');
+            };
+
+            expect(fn).to.throw('my error message');
+            Hoek.abortThrow = false;
+            process.env.NODE_ENV = env;
+
+            done();
+        });
+
+
+        it('should respect hideStack argument', function (done) {
+
+            var env = process.env.NODE_ENV;
+            var write = process.stdout.write;
+            var exit = process.exit;
+            var output = '';
+
+            process.exit = function () { };
+            process.env.NODE_ENV = '';
+            process.stdout.write = function (message) {
+
+                output = message;
+            };
+
+            Hoek.abort('my error message', true);
+
+            process.env.NODE_ENV = env;
+            process.stdout.write = write;
+            process.exit = exit;
+
+            expect(output).to.equal('ABORT: my error message\n\t\n');
+
+            done();
+        });
+
+        it('should default to showing stack', function (done) {
+
+            var env = process.env.NODE_ENV;
+            var write = process.stdout.write;
+            var exit = process.exit;
+            var output = '';
+
+            process.exit = function () { };
+            process.env.NODE_ENV = '';
+            process.stdout.write = function (message) {
+
+                output = message;
+            };
+
+            Hoek.abort('my error message');
+
+            process.env.NODE_ENV = env;
+            process.stdout.write = write;
+            process.exit = exit;
+
+            expect(output).to.contain('index.js');
+
+            done();
+        });
+    });
+
+    describe('#assert', function () {
+
+        it('should throw an Error when using assert in a test', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, 'my error message');
+            };
+
+            expect(fn).to.throw('my error message');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with no message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false);
+            };
+
+            expect(fn).to.throw('Unknown error');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with multipart message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, 'This', 'is', 'my message');
+            };
+
+            expect(fn).to.throw('This is my message');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with object message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, 'This', 'is', { spinal: 'tap' });
+            };
+
+            expect(fn).to.throw('This is {"spinal":"tap"}');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with error object message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, new Error('This is spinal tap'));
+            };
+
+            expect(fn).to.throw('This is spinal tap');
+            done();
+        });
+    });
+
+    describe('#loadDirModules', function () {
+
+        it('should load modules from directory', function (done) {
+
+            var target = {};
+            Hoek.loadDirModules(__dirname + '/modules', ['test2'], target);
+            expect(target.Test1.x).to.equal(1);
+            expect(target.Test2).to.not.exist;
+            expect(target.Test3.z).to.equal(3);
+            done();
+        });
+
+        it('should list modules from directory into function', function (done) {
+
+            var target = {};
+            Hoek.loadDirModules(__dirname + '/modules', ['test2'], function (path, name, capName) {
+
+                target[name] = capName;
+            });
+
+            expect(target.test1).to.equal('Test1');
+            expect(target.test2).to.not.exist;
+            expect(target.test3).to.equal('Test3');
+            done();
+        });
+    });
+
+    describe('#rename', function () {
+
+        it('should rename object key', function (done) {
+
+            var a = { b: 'c' };
+            Hoek.rename(a, 'b', 'x');
+            expect(a.b).to.not.exist;
+            expect(a.x).to.equal('c');
+            done();
+        });
+    });
+
+    describe('Timer', function () {
+
+        it('should return time elapsed', function (done) {
+
+            var timer = new Hoek.Timer();
+            setTimeout(function () {
+
+                expect(timer.elapsed()).to.be.above(9);
+                done();
+            }, 12);
+        });
+    });
+
+    describe('#loadPackage', function () {
+
+        it('should', function (done) {
+
+            var pack = Hoek.loadPackage();
+            expect(pack.name).to.equal('hoek');
+            done();
+        });
+    });
+
+    describe('#escapeRegex', function () {
+
+        it('should escape all special regular expression characters', function (done) {
+
+            var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');
+            expect(a).to.equal('4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`"\\(>\\)\\[<\\]d\\{\\}s\\,');
+            done();
+        });
+    });
+
+    describe('#toss', function () {
+
+        it('should call callback with new error', function (done) {
+
+            var callback = function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('bug');
+                done();
+            };
+
+            Hoek.toss(true, 'feature', callback);
+            Hoek.toss(false, 'bug', callback);
+        });
+
+        it('should call callback with new error and no message', function (done) {
+
+            Hoek.toss(false, function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('');
+                done();
+            });
+        });
+
+        it('should call callback with error condition', function (done) {
+
+            Hoek.toss(new Error('boom'), function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('boom');
+                done();
+            });
+        });
+
+        it('should call callback with new error using message with error condition', function (done) {
+
+            Hoek.toss(new Error('ka'), 'boom', function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('boom');
+                done();
+            });
+        });
+
+        it('should call callback with new error using passed error with error condition', function (done) {
+
+            Hoek.toss(new Error('ka'), new Error('boom'), function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('boom');
+                done();
+            });
+        });
+    });
+
+    describe('Base64Url', function () {
+
+        var base64str = 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w';
+        var str = unescape('%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29*+%2C-./0123456789%3A%3B%3C%3D%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF');
+
+        describe('#base64urlEncode', function () {
+
+            it('should base64 URL-safe a string', function (done) {
+
+                expect(Hoek.base64urlEncode(str)).to.equal(base64str);
+                done();
+            });
+        });
+
+        describe('#base64urlDecode', function () {
+
+            it('should un-base64 URL-safe a string', function (done) {
+
+                expect(Hoek.base64urlDecode(base64str)).to.equal(str);
+                done();
+            });
+
+            it('should return error on undefined input', function (done) {
+
+                expect(Hoek.base64urlDecode().message).to.exist;
+                done();
+            });
+
+            it('should return error on invalid input', function (done) {
+
+                expect(Hoek.base64urlDecode('*').message).to.exist;
+                done();
+            });
+        });
+    });
+
+    describe('#escapeHeaderAttribute', function () {
+
+        it('should not alter ascii values', function (done) {
+
+            var a = Hoek.escapeHeaderAttribute('My Value');
+            expect(a).to.equal('My Value');
+            done();
+        });
+
+        it('should escape all special HTTP header attribute characters', function (done) {
+
+            var a = Hoek.escapeHeaderAttribute('I said go!!!#"' + String.fromCharCode(92));
+            expect(a).to.equal('I said go!!!#\\"\\\\');
+            done();
+        });
+
+        it('should throw on large unicode characters', function (done) {
+
+            var fn = function () {
+
+                Hoek.escapeHeaderAttribute('this is a test' + String.fromCharCode(500) + String.fromCharCode(300));
+            };
+
+            expect(fn).to.throw(Error);
+            done();
+        });
+
+        it('should throw on CRLF to prevent response splitting', function (done) {
+
+            var fn = function () {
+
+                Hoek.escapeHeaderAttribute('this is a test\r\n');
+            };
+
+            expect(fn).to.throw(Error);
+            done();
+        });
+    });
+
+    describe('#escapeHtml', function () {
+
+        it('should escape all special HTML characters', function (done) {
+
+            var a = Hoek.escapeHtml('&<>"\'`');
+            expect(a).to.equal('&amp;&lt;&gt;&quot;&#x27;&#x60;');
+            done();
+        });
+
+        it('should return empty string on falsy input', function (done) {
+
+            var a = Hoek.escapeHtml('');
+            expect(a).to.equal('');
+            done();
+        });
+
+        it('should return unchanged string on no reserved input', function (done) {
+
+            var a = Hoek.escapeHtml('abc');
+            expect(a).to.equal('abc');
+            done();
+        });
+    });
+
+    describe('#printEvent', function () {
+
+        it('outputs event as string', function (done) {
+
+            var event = {
+                timestamp: (new Date(2013, 1, 1, 6, 30, 45, 123)).getTime(),
+                tags: ['a', 'b', 'c'],
+                data: { some: 'data' }
+            };
+
+            Hoek.consoleFunc = function (string) {
+
+                Hoek.consoleFunc = console.log;
+                expect(string).to.equal('130201/063045.123, a, {"some":"data"}');
+                done();
+            };
+
+            Hoek.printEvent(event);
+        });
+
+        it('outputs JSON error', function (done) {
+
+            var event = {
+                timestamp: (new Date(2013, 1, 1, 6, 30, 45, 123)).getTime(),
+                tags: ['a', 'b', 'c'],
+                data: { some: 'data' }
+            };
+
+            event.data.a = event.data;
+
+            Hoek.consoleFunc = function (string) {
+
+                Hoek.consoleFunc = console.log;
+                expect(string).to.equal('130201/063045.123, a, JSON Error: Converting circular structure to JSON');
+                done();
+            };
+
+            Hoek.printEvent(event);
+        });
+    });
+
+    describe('#nextTick', function () {
+
+        it('calls the provided callback on nextTick', function (done) {
+
+            var a = 0;
+
+            var inc = function (step, next) {
+
+                a += step;
+                next();
+            };
+
+            var ticked = Hoek.nextTick(inc);
+
+            ticked(5, function () {
+
+                expect(a).to.equal(6);
+                done();
+            });
+
+            expect(a).to.equal(0);
+            inc(1, function () {
+
+                expect(a).to.equal(1);
+            });
+        });
+    });
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js	(revision 484)
@@ -0,0 +1,1 @@
+exports.x = 1;
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js	(revision 484)
@@ -0,0 +1,1 @@
+exports.y = 2;
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js	(revision 484)
@@ -0,0 +1,1 @@
+exports.z = 3;
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/.npmignore	(revision 484)
@@ -0,0 +1,18 @@
+.idea
+*.iml
+npm-debug.log
+dump.rdb
+node_modules
+results.tap
+results.xml
+npm-shrinkwrap.json
+config.json
+.DS_Store
+*/.DS_Store
+*/*/.DS_Store
+._*
+*/._*
+*/*/._*
+coverage.*
+lib-cov
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+
+node_js:
+  - 0.10
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/LICENSE	(revision 484)
@@ -0,0 +1,24 @@
+Copyright (c) 2012-2013, Eran Hammer.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Eran Hammer nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ERAN HAMMER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/Makefile	(revision 484)
@@ -0,0 +1,11 @@
+test:
+	@./node_modules/.bin/lab
+test-cov: 
+	@./node_modules/.bin/lab -r threshold -t 100
+test-cov-html:
+	@./node_modules/.bin/lab -r html -o coverage.html
+complexity:
+	@./node_modules/.bin/cr -o complexity.md -f markdown lib
+
+.PHONY: test test-cov test-cov-html complexity
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/README.md	(revision 484)
@@ -0,0 +1,68 @@
+# sntp
+
+An SNTP v4 client (RFC4330) for node. Simpy connects to the NTP or SNTP server requested and returns the server time
+along with the roundtrip duration and clock offset. To adjust the local time to the NTP time, add the returned `t` offset
+to the local time.
+
+[![Build Status](https://secure.travis-ci.org/hueniverse/sntp.png)](http://travis-ci.org/hueniverse/sntp)
+
+# Usage
+
+```javascript
+var Sntp = require('sntp');
+
+// All options are optional
+
+var options = {
+    host: 'nist1-sj.ustiming.org',  // Defaults to pool.ntp.org
+    port: 123,                      // Defaults to 123 (NTP)
+    resolveReference: true,         // Default to false (not resolving)
+    timeout: 1000                   // Defaults to zero (no timeout)
+};
+
+// Request server time
+
+Sntp.time(options, function (err, time) {
+
+    if (err) {
+        console.log('Failed: ' + err.message);
+        process.exit(1);
+    }
+
+    console.log('Local clock is off by: ' + time.t + ' milliseconds');
+    process.exit(0);
+});
+```
+
+If an application needs to maintain continuous time synchronization, the module provides a stateful method for
+querying the current offset only when the last one is too old (defaults to daily).
+
+```javascript
+// Request offset once
+
+Sntp.offset(function (err, offset) {
+
+    console.log(offset);                    // New (served fresh)
+
+    // Request offset again
+
+    Sntp.offset(function (err, offset) {
+
+        console.log(offset);                // Identical (served from cache)
+    });
+});
+```
+
+To set a background offset refresh, start the interval and use the provided now() method. If for any reason the
+client fails to obtain an up-to-date offset, the current system clock is used.
+
+```javascript
+var before = Sntp.now();                    // System time without offset
+
+Sntp.start(function () {
+
+    var now = Sntp.now();                   // With offset
+    Sntp.stop();
+});
+```
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/examples/offset.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/examples/offset.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/examples/offset.js	(revision 484)
@@ -0,0 +1,16 @@
+var Sntp = require('../lib');
+
+// Request offset once
+
+Sntp.offset(function (err, offset) {
+
+    console.log(offset);                    // New (served fresh)
+
+    // Request offset again
+
+    Sntp.offset(function (err, offset) {
+
+        console.log(offset);                // Identical (served from cache)
+    });
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/examples/time.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/examples/time.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/examples/time.js	(revision 484)
@@ -0,0 +1,25 @@
+var Sntp = require('../lib');
+
+// All options are optional
+
+var options = {
+    host: 'nist1-sj.ustiming.org',  // Defaults to pool.ntp.org
+    port: 123,                      // Defaults to 123 (NTP)
+    resolveReference: true,         // Default to false (not resolving)
+    timeout: 1000                   // Defaults to zero (no timeout)
+};
+
+// Request server time
+
+Sntp.time(options, function (err, time) {
+
+    if (err) {
+        console.log('Failed: ' + err.message);
+        process.exit(1);
+    }
+
+    console.log(time);
+    console.log('Local clock is off by: ' + time.t + ' milliseconds');
+    process.exit(0);
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/index.js	(revision 484)
@@ -0,0 +1,1 @@
+module.exports = require('./lib');
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/lib/index.js	(revision 484)
@@ -0,0 +1,409 @@
+// Load modules
+
+var Dgram = require('dgram');
+var Dns = require('dns');
+var Hoek = require('hoek');
+
+
+// Declare internals
+
+var internals = {};
+
+
+exports.time = function (options, callback) {
+
+    if (arguments.length !== 2) {
+        callback = arguments[0];
+        options = {};
+    }
+
+    var settings = Hoek.clone(options);
+    settings.host = settings.host || 'pool.ntp.org';
+    settings.port = settings.port || 123;
+    settings.resolveReference = settings.resolveReference || false;
+
+    // Declare variables used by callback
+
+    var timeoutId = 0;
+    var sent = 0;
+
+    // Ensure callback is only called once
+
+    var isFinished = false;
+    var finish = function (err, result) {
+
+        if (timeoutId) {
+            clearTimeout(timeoutId);
+            timeoutId = 0;
+        }
+
+        if (!isFinished) {
+            isFinished = true;
+            socket.removeAllListeners();
+            socket.close();
+            return callback(err, result);
+        }
+    };
+
+    // Create UDP socket
+
+    var socket = Dgram.createSocket('udp4');
+
+    socket.once('error', function (err) {
+
+        return finish(err);
+    });
+
+    // Listen to incoming messages
+
+    socket.on('message', function (buffer, rinfo) {
+
+        var received = Date.now();
+
+        var message = new internals.NtpMessage(buffer);
+        if (!message.isValid) {
+            return finish(new Error('Invalid server response'), message);
+        }
+
+        if (message.originateTimestamp !== sent) {
+            return finish(new Error('Wrong originate timestamp'), message);
+        }
+
+        // Timestamp Name          ID   When Generated
+        // ------------------------------------------------------------
+        // Originate Timestamp     T1   time request sent by client
+        // Receive Timestamp       T2   time request received by server
+        // Transmit Timestamp      T3   time reply sent by server
+        // Destination Timestamp   T4   time reply received by client
+        //
+        // The roundtrip delay d and system clock offset t are defined as:
+        //
+        // d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2
+
+        var T1 = message.originateTimestamp;
+        var T2 = message.receiveTimestamp;
+        var T3 = message.transmitTimestamp;
+        var T4 = received;
+
+        message.d = (T4 - T1) - (T3 - T2);
+        message.t = ((T2 - T1) + (T3 - T4)) / 2;
+        message.receivedLocally = received;
+
+        if (!settings.resolveReference ||
+            message.stratum !== 'secondary') {
+
+            return finish(null, message);
+        }
+
+        // Resolve reference IP address
+
+        Dns.reverse(message.referenceId, function (err, domains) {
+
+            if (!err) {
+                message.referenceHost = domains[0];
+            }
+
+            return finish(null, message);
+        });
+    });
+
+    // Set timeout
+
+    if (settings.timeout) {
+        timeoutId = setTimeout(function () {
+
+            timeoutId = 0;
+            return finish(new Error('Timeout'));
+        }, settings.timeout);
+    }
+
+    // Construct NTP message
+
+    var message = new Buffer(48);
+    for (var i = 0; i < 48; i++) {                      // Zero message
+        message[i] = 0;
+    }
+
+    message[0] = (0 << 6) + (4 << 3) + (3 << 0)         // Set version number to 4 and Mode to 3 (client)
+    sent = Date.now();
+    internals.fromMsecs(sent, message, 40);               // Set transmit timestamp (returns as originate)
+
+    // Send NTP request
+
+    socket.send(message, 0, message.length, settings.port, settings.host, function (err, bytes) {
+
+        if (err ||
+            bytes !== 48) {
+
+            return finish(err || new Error('Could not send entire message'));
+        }
+    });
+};
+
+
+internals.NtpMessage = function (buffer) {
+
+    this.isValid = false;
+
+    // Validate
+
+    if (buffer.length !== 48) {
+        return;
+    }
+
+    // Leap indicator
+
+    var li = (buffer[0] >> 6);
+    switch (li) {
+        case 0: this.leapIndicator = 'no-warning'; break;
+        case 1: this.leapIndicator = 'last-minute-61'; break;
+        case 2: this.leapIndicator = 'last-minute-59'; break;
+        case 3: this.leapIndicator = 'alarm'; break;
+    }
+
+    // Version
+
+    var vn = ((buffer[0] & 0x38) >> 3);
+    this.version = vn;
+
+    // Mode
+
+    var mode = (buffer[0] & 0x7);
+    switch (mode) {
+        case 1: this.mode = 'symmetric-active'; break;
+        case 2: this.mode = 'symmetric-passive'; break;
+        case 3: this.mode = 'client'; break;
+        case 4: this.mode = 'server'; break;
+        case 5: this.mode = 'broadcast'; break;
+        case 0:
+        case 6:
+        case 7: this.mode = 'reserved'; break;
+    }
+
+    // Stratum
+
+    var stratum = buffer[1];
+    if (stratum === 0) {
+        this.stratum = 'death';
+    }
+    else if (stratum === 1) {
+        this.stratum = 'primary';
+    }
+    else if (stratum <= 15) {
+        this.stratum = 'secondary';
+    }
+    else {
+        this.stratum = 'reserved';
+    }
+
+    // Poll interval (msec)
+
+    this.pollInterval = Math.round(Math.pow(2, buffer[2])) * 1000;
+
+    // Precision (msecs)
+
+    this.precision = Math.pow(2, buffer[3]) * 1000;
+
+    // Root delay (msecs)
+
+    var rootDelay = 256 * (256 * (256 * buffer[4] + buffer[5]) + buffer[6]) + buffer[7];
+    this.rootDelay = 1000 * (rootDelay / 0x10000);
+
+    // Root dispersion (msecs)
+
+    this.rootDispersion = ((buffer[8] << 8) + buffer[9] + ((buffer[10] << 8) + buffer[11]) / Math.pow(2, 16)) * 1000;
+
+    // Reference identifier
+
+    this.referenceId = '';
+    switch (this.stratum) {
+        case 'death':
+        case 'primary':
+            this.referenceId = String.fromCharCode(buffer[12]) + String.fromCharCode(buffer[13]) + String.fromCharCode(buffer[14]) + String.fromCharCode(buffer[15]);
+            break;
+        case 'secondary':
+            this.referenceId = '' + buffer[12] + '.' + buffer[13] + '.' + buffer[14] + '.' + buffer[15];
+            break;
+    }
+
+    // Reference timestamp
+
+    this.referenceTimestamp = internals.toMsecs(buffer, 16);
+
+    // Originate timestamp
+
+    this.originateTimestamp = internals.toMsecs(buffer, 24);
+
+    // Receive timestamp
+
+    this.receiveTimestamp = internals.toMsecs(buffer, 32);
+
+    // Transmit timestamp
+
+    this.transmitTimestamp = internals.toMsecs(buffer, 40);
+
+    // Validate
+
+    if (this.version === 4 &&
+        this.stratum !== 'reserved' &&
+        this.mode === 'server' &&
+        this.originateTimestamp &&
+        this.receiveTimestamp &&
+        this.transmitTimestamp) {
+
+        this.isValid = true;
+    }
+
+    return this;
+};
+
+
+internals.toMsecs = function (buffer, offset) {
+
+    var seconds = 0;
+    var fraction = 0;
+
+    for (var i = 0; i < 4; ++i) {
+        seconds = (seconds * 256) + buffer[offset + i];
+    }
+
+    for (i = 4; i < 8; ++i) {
+        fraction = (fraction * 256) + buffer[offset + i];
+    }
+
+    return ((seconds - 2208988800 + (fraction / Math.pow(2, 32))) * 1000);
+};
+
+
+internals.fromMsecs = function (ts, buffer, offset) {
+
+    var seconds = Math.floor(ts / 1000) + 2208988800;
+    var fraction = Math.round((ts % 1000) / 1000 * Math.pow(2, 32));
+
+    buffer[offset + 0] = (seconds & 0xFF000000) >> 24;
+    buffer[offset + 1] = (seconds & 0x00FF0000) >> 16;
+    buffer[offset + 2] = (seconds & 0x0000FF00) >> 8;
+    buffer[offset + 3] = (seconds & 0x000000FF);
+
+    buffer[offset + 4] = (fraction & 0xFF000000) >> 24;
+    buffer[offset + 5] = (fraction & 0x00FF0000) >> 16;
+    buffer[offset + 6] = (fraction & 0x0000FF00) >> 8;
+    buffer[offset + 7] = (fraction & 0x000000FF);
+};
+
+
+// Offset singleton
+
+internals.last = {
+    offset: 0,
+    expires: 0,
+    host: '',
+    port: 0
+};
+
+
+exports.offset = function (options, callback) {
+
+    if (arguments.length !== 2) {
+        callback = arguments[0];
+        options = {};
+    }
+
+    var now = Date.now();
+    var clockSyncRefresh = options.clockSyncRefresh || 24 * 60 * 60 * 1000;                    // Daily
+
+    if (internals.last.offset &&
+        internals.last.host === options.host &&
+        internals.last.port === options.port &&
+        now < internals.last.expires) {
+
+        process.nextTick(function () {
+                
+            callback(null, internals.last.offset);
+        });
+
+        return;
+    }
+
+    exports.time(options, function (err, time) {
+
+        if (err) {
+            return callback(err, 0);
+        }
+
+        internals.last = {
+            offset: Math.round(time.t),
+            expires: now + clockSyncRefresh,
+            host: options.host,
+            port: options.port
+        };
+
+        return callback(null, internals.last.offset);
+    });
+};
+
+
+// Now singleton
+
+internals.now = {
+    intervalId: 0
+};
+
+
+exports.start = function (options, callback) {
+
+    if (arguments.length !== 2) {
+        callback = arguments[0];
+        options = {};
+    }
+
+    if (internals.now.intervalId) {
+        process.nextTick(function () {
+            
+            callback();
+        });
+        
+        return;
+    }
+
+    exports.offset(options, function (err, offset) {
+
+        internals.now.intervalId = setInterval(function () {
+
+            exports.offset(options, function () { });
+        }, options.clockSyncRefresh || 24 * 60 * 60 * 1000);                                // Daily
+
+        return callback();
+    });
+};
+
+
+exports.stop = function () {
+
+    if (!internals.now.intervalId) {
+        return;
+    }
+
+    clearInterval(internals.now.intervalId);
+    internals.now.intervalId = 0;
+};
+
+
+exports.isLive = function () {
+
+    return !!internals.now.intervalId;
+};
+
+
+exports.now = function () {
+
+    var now = Date.now();
+    if (!exports.isLive() ||
+        now >= internals.last.expires) {
+
+        return now;
+    }
+
+    return now + internals.last.offset;
+};
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/.npmignore	(revision 484)
@@ -0,0 +1,18 @@
+.idea
+*.iml
+npm-debug.log
+dump.rdb
+node_modules
+results.tap
+results.xml
+npm-shrinkwrap.json
+config.json
+.DS_Store
+*/.DS_Store
+*/*/.DS_Store
+._*
+*/._*
+*/*/._*
+coverage.*
+lib-cov
+complexity.md
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+
+node_js:
+  - 0.10
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/LICENSE	(revision 484)
@@ -0,0 +1,33 @@
+Copyright (c) 2011-2013, Walmart.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Walmart nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL WALMART BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+                                  *   *   *
+
+
+Portions of this project were initially based on Postmile, Copyright (c) 2011, Yahoo Inc.
+Postmile is published at https://github.com/yahoo/postmile and its licensing terms are
+published at https://github.com/yahoo/postmile/blob/master/LICENSE.
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/Makefile
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/Makefile	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/Makefile	(revision 484)
@@ -0,0 +1,10 @@
+test:
+	@node node_modules/lab/bin/lab
+test-cov: 
+	@node node_modules/lab/bin/lab -r threshold -t 100
+test-cov-html:
+	@node node_modules/lab/bin/lab -r html -o coverage.html
+complexity:
+	@node node_modules/complexity-report/src/cli.js -o complexity.md -f markdown lib
+
+.PHONY: test test-cov test-cov-html complexity
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/README.md	(revision 484)
@@ -0,0 +1,436 @@
+<a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a>
+![hoek Logo](https://raw.github.com/spumko/hoek/master/images/hoek.png)
+
+General purpose node utilities
+
+[![Build Status](https://secure.travis-ci.org/spumko/hoek.png)](http://travis-ci.org/spumko/hoek)
+
+# Table of Contents
+
+* [Introduction](#introduction "Introduction")
+* [Object](#object "Object")
+  * [clone](#cloneobj "clone")
+  * [merge](#mergetarget-source-isnulloverride-ismergearrays "merge")
+  * [applyToDefaults](#applytodefaultsdefaults-options "applyToDefaults")
+  * [unique](#uniquearray-key "unique")
+  * [mapToObject](#maptoobjectarray-key "mapToObject")
+  * [intersect](#intersectarray1-array2 "intersect")
+  * [matchKeys](#matchkeysobj-keys "matchKeys")
+  * [flatten](#flattenarray-target "flatten")
+  * [removeKeys](#removekeysobject-keys "removeKeys")
+  * [reach](#reachobj-chain "reach")
+  * [inheritAsync](#inheritasyncself-obj-keys "inheritAsync")
+  * [rename](#renameobj-from-to "rename")
+* [Timer](#timer "Timer")
+* [Binary Encoding/Decoding](#binary "Binary Encoding/Decoding")
+  * [base64urlEncode](#binary64urlEncodevalue "binary64urlEncode")
+  * [base64urlDecode](#binary64urlDecodevalue "binary64urlDecode")
+* [Escaping Characters](#escaped "Escaping Characters")
+  * [escapeHtml](#escapeHtmlstring "escapeHtml")
+  * [escapeHeaderAttribute](#escapeHeaderAttributeattribute "escapeHeaderAttribute")
+  * [escapeRegex](#escapeRegexstring "escapeRegex")
+* [Errors](#errors "Errors")
+  * [assert](#assertmessage "assert")
+  * [abort](#abortmessage "abort")
+  * [displayStack](#displayStackslice "displayStack")
+  * [callStack](#callStackslice "callStack")
+  * [toss](#tosscondition "toss")
+* [Load files](#load-files "Load Files")
+  * [loadPackage](#loadPackagedir "loadpackage")
+  * [loadDirModules](#loadDirModulespath-excludefiles-target "loaddirmodules")
+
+
+
+# Introduction
+
+The *Hoek* general purpose node utilities library is used to aid in a variety of manners. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more. 
+
+For example, to use Hoek to set configuration with default options:
+```javascript
+var Hoek = require('hoek');
+
+var default = {url : "www.github.com", port : "8000", debug : true}
+
+var config = Hoek.applyToDefaults(default, {port : "3000", admin : true});
+
+// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }
+```
+
+Under each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the var Hoek = require('hoek') is omitted for brevity.
+
+## Object
+
+Hoek provides several helpful methods for objects and arrays.
+
+### clone(obj)
+
+This method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects). 
+
+```javascript
+
+var nestedObj = {
+        w: /^something$/ig,
+        x: {
+            a: [1, 2, 3],
+            b: 123456,
+            c: new Date()
+        },
+        y: 'y',
+        z: new Date()
+    };
+
+var copy = Hoek.clone(nestedObj);
+
+copy.x.b = 100;
+
+console.log(copy.y)        // results in 'y'
+console.log(nestedObj.x.b) // results in 123456
+console.log(copy.x.b)      // results in 100
+```
+
+### merge(target, source, isNullOverride, isMergeArrays)
+isNullOverride, isMergeArrays default to true
+
+Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
+
+
+```javascript
+
+var target = {a: 1, b : 2}
+var source = {a: 0, c: 5}
+var source2 = {a: null, c: 5}
+
+var targetArray = [1, 2, 3];
+var sourceArray = [4, 5];
+
+var newTarget = Hoek.merge(target, source);     // results in {a: 0, b: 2, c: 5}
+newTarget = Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}
+newTarget = Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}
+
+newTarget = Hoek.merge(targetArray, sourceArray)              // results in [1, 2, 3, 4, 5]
+newTarget = Hoek.merge(targetArray, sourceArray, true, false) // results in [4, 5]
+
+
+
+
+```
+
+### applyToDefaults(defaults, options)
+
+Apply options to a copy of the defaults
+
+```javascript
+
+var defaults = {host: "localhost", port: 8000};
+var options = {port: 8080};
+
+var config = Hoek.applyToDefaults(defaults, options); // results in {host: "localhost", port: 8080};
+
+
+```
+
+### unique(array, key)
+
+Remove duplicate items from Array
+
+```javascript
+
+var array = [1, 2, 2, 3, 3, 4, 5, 6];
+
+var newArray = Hoek.unique(array); // results in [1,2,3,4,5,6];
+
+array = [{id: 1}, {id: 1}, {id: 2}];
+
+newArray = Hoek.unique(array, "id") // results in [{id: 1}, {id: 2}]
+
+```
+
+### mapToObject(array, key)
+
+Convert an Array into an Object
+
+```javascript
+
+var array = [1,2,3];
+var newObject = Hoek.mapToObject(array); // results in [{"1": true}, {"2": true}, {"3": true}]
+
+array = [{id: 1}, {id: 2}];
+newObject = Hoek.mapToObject(array, "id") // results in [{"id": 1}, {"id": 2}]
+
+```
+### intersect(array1, array2)
+
+Find the common unique items in two arrays
+
+```javascript
+
+var array1 = [1, 2, 3];
+var array2 = [1, 4, 5];
+
+var newArray = Hoek.intersect(array1, array2) // results in [1]
+
+```
+
+### matchKeys(obj, keys) 
+
+Find which keys are present
+
+```javascript
+
+var obj = {a: 1, b: 2, c: 3};
+var keys = ["a", "e"];
+
+Hoek.matchKeys(obj, keys) // returns ["a"]
+
+```
+
+### flatten(array, target)
+
+Flatten an array
+
+```javascript
+
+var array = [1, 2, 3];
+var target = [4, 5]; 
+
+var flattenedArray = Hoek.flatten(array, target) // results in [4, 5, 1, 2, 3];
+
+```
+
+### removeKeys(object, keys)
+
+Remove keys
+
+```javascript
+
+var object = {a: 1, b: 2, c: 3, d: 4};
+
+var keys = ["a", "b"];
+
+Hoek.removeKeys(object, keys) // object is now {c: 3, d: 4}
+
+```
+
+### reach(obj, chain)
+
+Converts an object key chain string to reference
+
+```javascript
+
+var chain = 'a.b.c';
+var obj = {a : {b : { c : 1}}};
+
+Hoek.reach(obj, chain) // returns 1
+
+```
+
+### inheritAsync(self, obj, keys) 
+
+Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
+
+```javascript
+
+var targetFunc = function () { };
+
+var proto = {
+                a: function () {
+                    return 'a!';
+                },
+                b: function () {
+                    return 'b!';
+                },
+                c: function () {
+                    throw new Error('c!');
+                }
+            };
+
+var keys = ['a', 'c'];
+
+Hoek.inheritAsync(targetFunc, proto, ['a', 'c']);
+
+var target = new targetFunc();
+
+target.a(function(err, result){console.log(result)}         // returns 'a!'       
+
+target.c(function(err, result){console.log(result)}         // returns undefined
+
+target.b(function(err, result){console.log(result)}         // gives error: Object [object Object] has no method 'b'
+
+```
+
+### rename(obj, from, to)
+
+Rename a key of an object
+
+```javascript
+
+var obj = {a : 1, b : 2};
+
+Hoek.rename(obj, "a", "c");     // obj is now {c : 1, b : 2}
+
+```
+
+
+# Timer
+
+A Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
+
+```javascript
+
+
+example : 
+
+
+var timerObj = new Hoek.Timer();
+console.log("Time is now: " + timerObj.ts)
+console.log("Elapsed time from initialization: " + timerObj.elapsed() + 'milliseconds')
+
+```
+
+# Binary Encoding/Decoding
+
+### base64urlEncode(value)
+
+Encodes value in Base64 or URL encoding
+
+### base64urlDecode(value)
+
+Decodes data in Base64 or URL encoding.
+# Escaping Characters
+
+Hoek provides convenient methods for escaping html characters. The escaped characters are as followed:
+
+```javascript
+
+internals.htmlEscaped = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#x27;',
+    '`': '&#x60;'
+};
+
+```
+
+### escapeHtml(string)
+
+```javascript
+
+var string = '<html> hey </html>';
+var escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;
+
+```
+
+### escapeHeaderAttribute(attribute)
+
+Escape attribute value for use in HTTP header
+
+```javascript
+
+var a = Hoek.escapeHeaderAttribute('I said "go w\\o me"');  //returns I said \"go w\\o me\"
+
+
+```
+
+
+### escapeRegex(string)
+
+Escape string for Regex construction
+
+```javascript
+
+var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');  // returns 4\^f\$s\.4\*5\+\-_\?%\=#\!\:@\|~\\\/`"\(>\)\[<\]d\{\}s\,
+
+
+
+```
+
+# Errors
+
+### assert(message)
+
+```javascript
+
+var a = 1, b =2;
+
+Hoek.assert(a === b, 'a should equal b');  // ABORT: a should equal b
+
+```
+
+### abort(message)
+
+First checks if process.env.NODE_ENV === 'test', and if so, throws error message. Otherwise,
+displays most recent stack and then exits process.
+
+
+
+### displayStack(slice)
+
+Displays the trace stack
+
+```javascript
+
+var stack = Hoek.displayStack();
+console.log(stack) // returns something like:
+
+[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',
+  'Module._compile (module.js:449:26)',
+  'Module._extensions..js (module.js:467:10)',
+  'Module.load (module.js:356:32)',
+  'Module._load (module.js:312:12)',
+  'Module.runMain (module.js:492:10)',
+  'startup.processNextTick.process._tickCallback (node.js:244:9)' ]
+
+```
+
+### callStack(slice)
+
+Returns a trace stack array.
+
+```javascript
+
+var stack = Hoek.callStack();
+console.log(stack)  // returns something like:
+
+[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],
+  [ 'module.js', 449, 26, 'Module._compile', false ],
+  [ 'module.js', 467, 10, 'Module._extensions..js', false ],
+  [ 'module.js', 356, 32, 'Module.load', false ],
+  [ 'module.js', 312, 12, 'Module._load', false ],
+  [ 'module.js', 492, 10, 'Module.runMain', false ],
+  [ 'node.js',
+    244,
+    9,
+    'startup.processNextTick.process._tickCallback',
+    false ] ]
+
+
+```
+
+### toss(condition)
+
+toss(condition /*, [message], callback */)
+
+Return an error as first argument of a callback
+
+
+# Load Files
+
+### loadPackage(dir)
+
+Load and parse package.json process root or given directory
+
+```javascript
+
+var pack = Hoek.loadPackage();  // pack.name === 'hoek'
+
+```
+
+### loadDirModules(path, excludeFiles, target) 
+
+Loads modules from a given path; option to exclude files (array).
+
+
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/index.js	(revision 484)
@@ -0,0 +1,1 @@
+module.exports = require('./lib');
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/lib/escape.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/lib/escape.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/lib/escape.js	(revision 484)
@@ -0,0 +1,132 @@
+// Declare internals
+
+var internals = {};
+
+
+exports.escapeJavaScript = function (input) {
+
+    if (!input) {
+        return '';
+    }
+
+    var escaped = '';
+
+    for (var i = 0, il = input.length; i < il; ++i) {
+
+        var charCode = input.charCodeAt(i);
+
+        if (internals.isSafe(charCode)) {
+            escaped += input[i];
+        }
+        else {
+            escaped += internals.escapeJavaScriptChar(charCode);
+        }
+    }
+
+    return escaped;
+};
+
+
+exports.escapeHtml = function (input) {
+
+    if (!input) {
+        return '';
+    }
+
+    var escaped = '';
+
+    for (var i = 0, il = input.length; i < il; ++i) {
+
+        var charCode = input.charCodeAt(i);
+
+        if (internals.isSafe(charCode)) {
+            escaped += input[i];
+        }
+        else {
+            escaped += internals.escapeHtmlChar(charCode);
+        }
+    }
+
+    return escaped;
+};
+
+
+internals.escapeJavaScriptChar = function (charCode) {
+
+    if (charCode >= 256) {
+        return '\\u' + internals.padLeft('' + charCode, 4);
+    }
+
+    var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
+    return '\\x' + internals.padLeft(hexValue, 2);
+};
+
+
+internals.escapeHtmlChar = function (charCode) {
+
+    var namedEscape = internals.namedHtml[charCode];
+    if (typeof namedEscape !== 'undefined') {
+        return namedEscape;
+    }
+
+    if (charCode >= 256) {
+        return '&#' + charCode + ';';
+    }
+
+    var hexValue = new Buffer(String.fromCharCode(charCode), 'ascii').toString('hex');
+    return '&#x' + internals.padLeft(hexValue, 2) + ';';
+};
+
+
+internals.padLeft = function (str, len) {
+
+    while (str.length < len) {
+        str = '0' + str;
+    }
+
+    return str;
+};
+
+
+internals.isSafe = function (charCode) {
+
+    return (typeof internals.safeCharCodes[charCode] !== 'undefined');
+};
+
+
+internals.namedHtml = {
+    '38': '&amp;',
+    '60': '&lt;',
+    '62': '&gt;',
+    '34': '&quot;',
+    '160': '&nbsp;',
+    '162': '&cent;',
+    '163': '&pound;',
+    '164': '&curren;',
+    '169': '&copy;',
+    '174': '&reg;'
+};
+
+
+internals.safeCharCodes = (function () {
+
+    var safe = {};
+
+    for (var i = 32; i < 123; ++i) {
+
+        if ((i >= 97 && i <= 122) ||         // a-z
+            (i >= 65 && i <= 90) ||          // A-Z
+            (i >= 48 && i <= 57) ||          // 0-9
+            i === 32 ||                      // space
+            i === 46 ||                      // .
+            i === 44 ||                      // ,
+            i === 45 ||                      // -
+            i === 58 ||                      // :
+            i === 95) {                      // _
+
+            safe[i] = null;
+        }
+    }
+
+    return safe;
+}());
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/lib/index.js	(revision 484)
@@ -0,0 +1,585 @@
+// Load modules
+
+var Fs = require('fs');
+var Escape = require('./escape');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Clone object or array
+
+exports.clone = function (obj, seen) {
+
+    if (typeof obj !== 'object' ||
+        obj === null) {
+
+        return obj;
+    }
+
+    seen = seen || { orig: [], copy: [] };
+
+    var lookup = seen.orig.indexOf(obj);
+    if (lookup !== -1) {
+        return seen.copy[lookup];
+    }
+
+    var newObj = (obj instanceof Array) ? [] : {};
+
+    seen.orig.push(obj);
+    seen.copy.push(newObj);
+
+    for (var i in obj) {
+        if (obj.hasOwnProperty(i)) {
+            if (obj[i] instanceof Buffer) {
+                newObj[i] = new Buffer(obj[i]);
+            }
+            else if (obj[i] instanceof Date) {
+                newObj[i] = new Date(obj[i].getTime());
+            }
+            else if (obj[i] instanceof RegExp) {
+                var flags = '' + (obj[i].global ? 'g' : '') + (obj[i].ignoreCase ? 'i' : '') + (obj[i].multiline ? 'm' : '');
+                newObj[i] = new RegExp(obj[i].source, flags);
+            }
+            else {
+                newObj[i] = exports.clone(obj[i], seen);
+            }
+        }
+    }
+
+    return newObj;
+};
+
+
+// Merge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied
+
+exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {
+
+    exports.assert(target && typeof target == 'object', 'Invalid target value: must be an object');
+    exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');
+
+    if (!source) {
+        return target;
+    }
+
+    if (source instanceof Array) {
+        exports.assert(target instanceof Array, 'Cannot merge array onto an object');
+        if (isMergeArrays === false) {                                                  // isMergeArrays defaults to true
+            target.length = 0;                                                          // Must not change target assignment
+        }
+
+        for (var i = 0, il = source.length; i < il; ++i) {
+            target.push(source[i]);
+        }
+
+        return target;
+    }
+
+    var keys = Object.keys(source);
+    for (var k = 0, kl = keys.length; k < kl; ++k) {
+        var key = keys[k];
+        var value = source[key];
+        if (value &&
+            typeof value === 'object') {
+
+            if (!target[key] ||
+                typeof target[key] !== 'object') {
+
+                target[key] = exports.clone(value);
+            }
+            else {
+                exports.merge(target[key], source[key], isNullOverride, isMergeArrays);
+            }
+        }
+        else {
+            if (value !== null && value !== undefined) {            // Explicit to preserve empty strings
+                target[key] = value;
+            }
+            else if (isNullOverride !== false) {                    // Defaults to true
+                target[key] = value;
+            }
+        }
+    }
+
+    return target;
+};
+
+
+// Apply options to a copy of the defaults
+
+exports.applyToDefaults = function (defaults, options) {
+
+    exports.assert(defaults && typeof defaults == 'object', 'Invalid defaults value: must be an object');
+    exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
+
+    if (!options) {                                                 // If no options, return null
+        return null;
+    }
+
+    var copy = exports.clone(defaults);
+
+    if (options === true) {                                         // If options is set to true, use defaults
+        return copy;
+    }
+
+    return exports.merge(copy, options, false, false);
+};
+
+
+// Remove duplicate items from array
+
+exports.unique = function (array, key) {
+
+    var index = {};
+    var result = [];
+
+    for (var i = 0, il = array.length; i < il; ++i) {
+        var id = (key ? array[i][key] : array[i]);
+        if (index[id] !== true) {
+
+            result.push(array[i]);
+            index[id] = true;
+        }
+    }
+
+    return result;
+};
+
+
+// Convert array into object
+
+exports.mapToObject = function (array, key) {
+
+    if (!array) {
+        return null;
+    }
+
+    var obj = {};
+    for (var i = 0, il = array.length; i < il; ++i) {
+        if (key) {
+            if (array[i][key]) {
+                obj[array[i][key]] = true;
+            }
+        }
+        else {
+            obj[array[i]] = true;
+        }
+    }
+
+    return obj;
+};
+
+
+// Find the common unique items in two arrays
+
+exports.intersect = function (array1, array2, justFirst) {
+
+    if (!array1 || !array2) {
+        return [];
+    }
+
+    var common = [];
+    var hash = (array1 instanceof Array ? exports.mapToObject(array1) : array1);
+    var found = {};
+    for (var i = 0, il = array2.length; i < il; ++i) {
+        if (hash[array2[i]] && !found[array2[i]]) {
+            if (justFirst) {
+                return array2[i];
+            }
+
+            common.push(array2[i]);
+            found[array2[i]] = true;
+        }
+    }
+
+    return (justFirst ? null : common);
+};
+
+
+// Find which keys are present
+
+exports.matchKeys = function (obj, keys) {
+
+    var matched = [];
+    for (var i = 0, il = keys.length; i < il; ++i) {
+        if (obj.hasOwnProperty(keys[i])) {
+            matched.push(keys[i]);
+        }
+    }
+    return matched;
+};
+
+
+// Flatten array
+
+exports.flatten = function (array, target) {
+
+    var result = target || [];
+
+    for (var i = 0, il = array.length; i < il; ++i) {
+        if (Array.isArray(array[i])) {
+            exports.flatten(array[i], result);
+        }
+        else {
+            result.push(array[i]);
+        }
+    }
+
+    return result;
+};
+
+
+// Remove keys
+
+exports.removeKeys = function (object, keys) {
+
+    for (var i = 0, il = keys.length; i < il; i++) {
+        delete object[keys[i]];
+    }
+};
+
+
+// Convert an object key chain string ('a.b.c') to reference (object[a][b][c])
+
+exports.reach = function (obj, chain) {
+
+    var path = chain.split('.');
+    var ref = obj;
+    for (var i = 0, il = path.length; i < il; ++i) {
+        if (ref) {
+            ref = ref[path[i]];
+        }
+    }
+
+    return ref;
+};
+
+
+// Inherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors
+
+exports.inheritAsync = function (self, obj, keys) {
+
+    keys = keys || null;
+
+    for (var i in obj) {
+        if (obj.hasOwnProperty(i)) {
+            if (keys instanceof Array &&
+                keys.indexOf(i) < 0) {
+
+                continue;
+            }
+
+            self.prototype[i] = (function (fn) {
+
+                return function (next) {
+
+                    var result = null;
+                    try {
+                        result = fn();
+                    }
+                    catch (err) {
+                        return next(err);
+                    }
+
+                    return next(null, result);
+                };
+            })(obj[i]);
+        }
+    }
+};
+
+
+exports.formatStack = function (stack) {
+
+    var trace = [];
+    for (var i = 0, il = stack.length; i < il; ++i) {
+        var item = stack[i];
+        trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
+    }
+
+    return trace;
+};
+
+
+exports.formatTrace = function (trace) {
+
+    var display = [];
+
+    for (var i = 0, il = trace.length; i < il; ++i) {
+        var row = trace[i];
+        display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
+    }
+
+    return display;
+};
+
+
+exports.callStack = function (slice) {
+
+    // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
+
+    var v8 = Error.prepareStackTrace;
+    Error.prepareStackTrace = function (err, stack) {
+
+        return stack;
+    };
+
+    var capture = {};
+    Error.captureStackTrace(capture, arguments.callee);
+    var stack = capture.stack;
+
+    Error.prepareStackTrace = v8;
+
+    var trace = exports.formatStack(stack);
+
+    if (slice) {
+        return trace.slice(slice);
+    }
+
+    return trace;
+};
+
+
+exports.displayStack = function (slice) {
+
+    var trace = exports.callStack(slice === undefined ? 1 : slice + 1);
+
+    return exports.formatTrace(trace);
+};
+
+
+exports.abortThrow = false;
+
+
+exports.abort = function (message, hideStack) {
+
+    if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
+        throw new Error(message || 'Unknown error');
+    }
+
+    var stack = '';
+    if (!hideStack) {
+        stack = exports.displayStack(1).join('\n\t');
+    }
+    console.log('ABORT: ' + message + '\n\t' + stack);
+    process.exit(1);
+};
+
+
+exports.assert = function (condition /*, msg1, msg2, msg3 */) {
+
+    if (condition) {
+        return;
+    }
+
+    var msgs = Array.prototype.slice.call(arguments, 1);
+    msgs = msgs.map(function (msg) {
+
+        return typeof msg === 'string' ? msg : msg instanceof Error ? msg.message : JSON.stringify(msg);
+    });
+    throw new Error(msgs.join(' ') || 'Unknown error');
+};
+
+
+exports.loadDirModules = function (path, excludeFiles, target) {      // target(filename, name, capName)
+
+    var exclude = {};
+    for (var i = 0, il = excludeFiles.length; i < il; ++i) {
+        exclude[excludeFiles[i] + '.js'] = true;
+    }
+
+    var files = Fs.readdirSync(path);
+    for (i = 0, il = files.length; i < il; ++i) {
+        var filename = files[i];
+        if (/\.js$/.test(filename) &&
+            !exclude[filename]) {
+
+            var name = filename.substr(0, filename.lastIndexOf('.'));
+            var capName = name.charAt(0).toUpperCase() + name.substr(1).toLowerCase();
+
+            if (typeof target !== 'function') {
+                target[capName] = require(path + '/' + name);
+            }
+            else {
+                target(path + '/' + name, name, capName);
+            }
+        }
+    }
+};
+
+
+exports.rename = function (obj, from, to) {
+
+    obj[to] = obj[from];
+    delete obj[from];
+};
+
+
+exports.Timer = function () {
+
+    this.reset();
+};
+
+
+exports.Timer.prototype.reset = function () {
+
+    this.ts = Date.now();
+};
+
+
+exports.Timer.prototype.elapsed = function () {
+
+    return Date.now() - this.ts;
+};
+
+
+// Load and parse package.json process root or given directory
+
+exports.loadPackage = function (dir) {
+
+    var result = {};
+    var filepath = (dir || process.env.PWD) + '/package.json';
+    if (Fs.existsSync(filepath)) {
+        try {
+            result = JSON.parse(Fs.readFileSync(filepath));
+        }
+        catch (e) { }
+    }
+
+    return result;
+};
+
+
+// Escape string for Regex construction
+
+exports.escapeRegex = function (string) {
+
+    // Escape ^$.*+-?=!:|\/()[]{},
+    return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
+};
+
+
+// Return an error as first argument of a callback
+
+exports.toss = function (condition /*, [message], next */) {
+
+    var message = (arguments.length === 3 ? arguments[1] : '');
+    var next = (arguments.length === 3 ? arguments[2] : arguments[1]);
+
+    var err = (message instanceof Error ? message : (message ? new Error(message) : (condition instanceof Error ? condition : new Error())));
+
+    if (condition instanceof Error ||
+        !condition) {
+
+        return next(err);
+    }
+};
+
+
+// Base64url (RFC 4648) encode
+
+exports.base64urlEncode = function (value) {
+
+    return (new Buffer(value, 'binary')).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
+};
+
+
+// Base64url (RFC 4648) decode
+
+exports.base64urlDecode = function (encoded) {
+
+    if (encoded &&
+        !encoded.match(/^[\w\-]*$/)) {
+
+        return new Error('Invalid character');
+    }
+
+    try {
+        return (new Buffer(encoded.replace(/-/g, '+').replace(/:/g, '/'), 'base64')).toString('binary');
+    }
+    catch (err) {
+        return err;
+    }
+};
+
+
+// Escape attribute value for use in HTTP header
+
+exports.escapeHeaderAttribute = function (attribute) {
+
+    // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "
+
+    exports.assert(attribute.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/), 'Bad attribute value (' + attribute + ')');
+
+    return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"');                             // Escape quotes and slash
+};
+
+
+exports.escapeHtml = function (string) {
+
+    return Escape.escapeHtml(string);
+};
+
+
+exports.escapeJavaScript = function (string) {
+
+    return Escape.escapeJavaScript(string);
+};
+
+
+/*
+var event = {
+    timestamp: now.getTime(),
+    tags: ['tag'],
+    data: { some: 'data' }
+};
+*/
+
+exports.consoleFunc = console.log;
+
+exports.printEvent = function (event) {
+
+    var pad = function (value) {
+
+        return (value < 10 ? '0' : '') + value;
+    };
+
+    var now = new Date(event.timestamp);
+    var timestring = (now.getYear() - 100).toString() +
+        pad(now.getMonth() + 1) +
+        pad(now.getDate()) +
+        '/' +
+        pad(now.getHours()) +
+        pad(now.getMinutes()) +
+        pad(now.getSeconds()) +
+        '.' +
+        now.getMilliseconds();
+
+    var data = event.data;
+    if (typeof event.data !== 'string') {
+        try {
+            data = JSON.stringify(event.data);
+        }
+        catch (e) {
+            data = 'JSON Error: ' + e.message;
+        }
+    }
+
+    var output = timestring + ', ' + event.tags[0] + ', ' + data;
+    exports.consoleFunc(output);
+};
+
+
+exports.nextTick = function (callback) {
+
+    return function () {
+
+        var args = arguments;
+        process.nextTick(function () {
+
+            callback.apply(null, args);
+        });
+    };
+};
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/package.json	(revision 484)
@@ -0,0 +1,49 @@
+{
+  "name": "hoek",
+  "description": "General purpose node utilities",
+  "version": "0.9.1",
+  "author": {
+    "name": "Eran Hammer",
+    "email": "eran@hueniverse.com",
+    "url": "http://hueniverse.com"
+  },
+  "contributors": [
+    {
+      "name": "Van Nguyen",
+      "email": "the.gol.effect@gmail.com"
+    }
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/spumko/hoek"
+  },
+  "main": "index",
+  "keywords": [
+    "utilities"
+  ],
+  "engines": {
+    "node": ">=0.8.0"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "lab": "0.1.x",
+    "complexity-report": "0.x.x"
+  },
+  "scripts": {
+    "test": "make test-cov"
+  },
+  "licenses": [
+    {
+      "type": "BSD",
+      "url": "http://github.com/spumko/hoek/raw/master/LICENSE"
+    }
+  ],
+  "readme": "<a href=\"https://github.com/spumko\"><img src=\"https://raw.github.com/spumko/spumko/master/images/from.png\" align=\"right\" /></a>\r\n![hoek Logo](https://raw.github.com/spumko/hoek/master/images/hoek.png)\r\n\r\nGeneral purpose node utilities\r\n\r\n[![Build Status](https://secure.travis-ci.org/spumko/hoek.png)](http://travis-ci.org/spumko/hoek)\r\n\r\n# Table of Contents\r\n\r\n* [Introduction](#introduction \"Introduction\")\r\n* [Object](#object \"Object\")\r\n  * [clone](#cloneobj \"clone\")\r\n  * [merge](#mergetarget-source-isnulloverride-ismergearrays \"merge\")\r\n  * [applyToDefaults](#applytodefaultsdefaults-options \"applyToDefaults\")\r\n  * [unique](#uniquearray-key \"unique\")\r\n  * [mapToObject](#maptoobjectarray-key \"mapToObject\")\r\n  * [intersect](#intersectarray1-array2 \"intersect\")\r\n  * [matchKeys](#matchkeysobj-keys \"matchKeys\")\r\n  * [flatten](#flattenarray-target \"flatten\")\r\n  * [removeKeys](#removekeysobject-keys \"removeKeys\")\r\n  * [reach](#reachobj-chain \"reach\")\r\n  * [inheritAsync](#inheritasyncself-obj-keys \"inheritAsync\")\r\n  * [rename](#renameobj-from-to \"rename\")\r\n* [Timer](#timer \"Timer\")\r\n* [Binary Encoding/Decoding](#binary \"Binary Encoding/Decoding\")\r\n  * [base64urlEncode](#binary64urlEncodevalue \"binary64urlEncode\")\r\n  * [base64urlDecode](#binary64urlDecodevalue \"binary64urlDecode\")\r\n* [Escaping Characters](#escaped \"Escaping Characters\")\r\n  * [escapeHtml](#escapeHtmlstring \"escapeHtml\")\r\n  * [escapeHeaderAttribute](#escapeHeaderAttributeattribute \"escapeHeaderAttribute\")\r\n  * [escapeRegex](#escapeRegexstring \"escapeRegex\")\r\n* [Errors](#errors \"Errors\")\r\n  * [assert](#assertmessage \"assert\")\r\n  * [abort](#abortmessage \"abort\")\r\n  * [displayStack](#displayStackslice \"displayStack\")\r\n  * [callStack](#callStackslice \"callStack\")\r\n  * [toss](#tosscondition \"toss\")\r\n* [Load files](#load-files \"Load Files\")\r\n  * [loadPackage](#loadPackagedir \"loadpackage\")\r\n  * [loadDirModules](#loadDirModulespath-excludefiles-target \"loaddirmodules\")\r\n\r\n\r\n\r\n# Introduction\r\n\r\nThe *Hoek* general purpose node utilities library is used to aid in a variety of manners. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more. \r\n\r\nFor example, to use Hoek to set configuration with default options:\r\n```javascript\r\nvar Hoek = require('hoek');\r\n\r\nvar default = {url : \"www.github.com\", port : \"8000\", debug : true}\r\n\r\nvar config = Hoek.applyToDefaults(default, {port : \"3000\", admin : true});\r\n\r\n// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }\r\n```\r\n\r\nUnder each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the var Hoek = require('hoek') is omitted for brevity.\r\n\r\n## Object\r\n\r\nHoek provides several helpful methods for objects and arrays.\r\n\r\n### clone(obj)\r\n\r\nThis method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects). \r\n\r\n```javascript\r\n\r\nvar nestedObj = {\r\n        w: /^something$/ig,\r\n        x: {\r\n            a: [1, 2, 3],\r\n            b: 123456,\r\n            c: new Date()\r\n        },\r\n        y: 'y',\r\n        z: new Date()\r\n    };\r\n\r\nvar copy = Hoek.clone(nestedObj);\r\n\r\ncopy.x.b = 100;\r\n\r\nconsole.log(copy.y)        // results in 'y'\r\nconsole.log(nestedObj.x.b) // results in 123456\r\nconsole.log(copy.x.b)      // results in 100\r\n```\r\n\r\n### merge(target, source, isNullOverride, isMergeArrays)\r\nisNullOverride, isMergeArrays default to true\r\n\r\nMerge all the properties of source into target, source wins in conflic, and by default null and undefined from source are applied\r\n\r\n\r\n```javascript\r\n\r\nvar target = {a: 1, b : 2}\r\nvar source = {a: 0, c: 5}\r\nvar source2 = {a: null, c: 5}\r\n\r\nvar targetArray = [1, 2, 3];\r\nvar sourceArray = [4, 5];\r\n\r\nvar newTarget = Hoek.merge(target, source);     // results in {a: 0, b: 2, c: 5}\r\nnewTarget = Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}\r\nnewTarget = Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}\r\n\r\nnewTarget = Hoek.merge(targetArray, sourceArray)              // results in [1, 2, 3, 4, 5]\r\nnewTarget = Hoek.merge(targetArray, sourceArray, true, false) // results in [4, 5]\r\n\r\n\r\n\r\n\r\n```\r\n\r\n### applyToDefaults(defaults, options)\r\n\r\nApply options to a copy of the defaults\r\n\r\n```javascript\r\n\r\nvar defaults = {host: \"localhost\", port: 8000};\r\nvar options = {port: 8080};\r\n\r\nvar config = Hoek.applyToDefaults(defaults, options); // results in {host: \"localhost\", port: 8080};\r\n\r\n\r\n```\r\n\r\n### unique(array, key)\r\n\r\nRemove duplicate items from Array\r\n\r\n```javascript\r\n\r\nvar array = [1, 2, 2, 3, 3, 4, 5, 6];\r\n\r\nvar newArray = Hoek.unique(array); // results in [1,2,3,4,5,6];\r\n\r\narray = [{id: 1}, {id: 1}, {id: 2}];\r\n\r\nnewArray = Hoek.unique(array, \"id\") // results in [{id: 1}, {id: 2}]\r\n\r\n```\r\n\r\n### mapToObject(array, key)\r\n\r\nConvert an Array into an Object\r\n\r\n```javascript\r\n\r\nvar array = [1,2,3];\r\nvar newObject = Hoek.mapToObject(array); // results in [{\"1\": true}, {\"2\": true}, {\"3\": true}]\r\n\r\narray = [{id: 1}, {id: 2}];\r\nnewObject = Hoek.mapToObject(array, \"id\") // results in [{\"id\": 1}, {\"id\": 2}]\r\n\r\n```\r\n### intersect(array1, array2)\r\n\r\nFind the common unique items in two arrays\r\n\r\n```javascript\r\n\r\nvar array1 = [1, 2, 3];\r\nvar array2 = [1, 4, 5];\r\n\r\nvar newArray = Hoek.intersect(array1, array2) // results in [1]\r\n\r\n```\r\n\r\n### matchKeys(obj, keys) \r\n\r\nFind which keys are present\r\n\r\n```javascript\r\n\r\nvar obj = {a: 1, b: 2, c: 3};\r\nvar keys = [\"a\", \"e\"];\r\n\r\nHoek.matchKeys(obj, keys) // returns [\"a\"]\r\n\r\n```\r\n\r\n### flatten(array, target)\r\n\r\nFlatten an array\r\n\r\n```javascript\r\n\r\nvar array = [1, 2, 3];\r\nvar target = [4, 5]; \r\n\r\nvar flattenedArray = Hoek.flatten(array, target) // results in [4, 5, 1, 2, 3];\r\n\r\n```\r\n\r\n### removeKeys(object, keys)\r\n\r\nRemove keys\r\n\r\n```javascript\r\n\r\nvar object = {a: 1, b: 2, c: 3, d: 4};\r\n\r\nvar keys = [\"a\", \"b\"];\r\n\r\nHoek.removeKeys(object, keys) // object is now {c: 3, d: 4}\r\n\r\n```\r\n\r\n### reach(obj, chain)\r\n\r\nConverts an object key chain string to reference\r\n\r\n```javascript\r\n\r\nvar chain = 'a.b.c';\r\nvar obj = {a : {b : { c : 1}}};\r\n\r\nHoek.reach(obj, chain) // returns 1\r\n\r\n```\r\n\r\n### inheritAsync(self, obj, keys) \r\n\r\nInherits a selected set of methods from an object, wrapping functions in asynchronous syntax and catching errors\r\n\r\n```javascript\r\n\r\nvar targetFunc = function () { };\r\n\r\nvar proto = {\r\n                a: function () {\r\n                    return 'a!';\r\n                },\r\n                b: function () {\r\n                    return 'b!';\r\n                },\r\n                c: function () {\r\n                    throw new Error('c!');\r\n                }\r\n            };\r\n\r\nvar keys = ['a', 'c'];\r\n\r\nHoek.inheritAsync(targetFunc, proto, ['a', 'c']);\r\n\r\nvar target = new targetFunc();\r\n\r\ntarget.a(function(err, result){console.log(result)}         // returns 'a!'       \r\n\r\ntarget.c(function(err, result){console.log(result)}         // returns undefined\r\n\r\ntarget.b(function(err, result){console.log(result)}         // gives error: Object [object Object] has no method 'b'\r\n\r\n```\r\n\r\n### rename(obj, from, to)\r\n\r\nRename a key of an object\r\n\r\n```javascript\r\n\r\nvar obj = {a : 1, b : 2};\r\n\r\nHoek.rename(obj, \"a\", \"c\");     // obj is now {c : 1, b : 2}\r\n\r\n```\r\n\r\n\r\n# Timer\r\n\r\nA Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.\r\n\r\n```javascript\r\n\r\n\r\nexample : \r\n\r\n\r\nvar timerObj = new Hoek.Timer();\r\nconsole.log(\"Time is now: \" + timerObj.ts)\r\nconsole.log(\"Elapsed time from initialization: \" + timerObj.elapsed() + 'milliseconds')\r\n\r\n```\r\n\r\n# Binary Encoding/Decoding\r\n\r\n### base64urlEncode(value)\r\n\r\nEncodes value in Base64 or URL encoding\r\n\r\n### base64urlDecode(value)\r\n\r\nDecodes data in Base64 or URL encoding.\r\n# Escaping Characters\r\n\r\nHoek provides convenient methods for escaping html characters. The escaped characters are as followed:\r\n\r\n```javascript\r\n\r\ninternals.htmlEscaped = {\r\n    '&': '&amp;',\r\n    '<': '&lt;',\r\n    '>': '&gt;',\r\n    '\"': '&quot;',\r\n    \"'\": '&#x27;',\r\n    '`': '&#x60;'\r\n};\r\n\r\n```\r\n\r\n### escapeHtml(string)\r\n\r\n```javascript\r\n\r\nvar string = '<html> hey </html>';\r\nvar escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;\r\n\r\n```\r\n\r\n### escapeHeaderAttribute(attribute)\r\n\r\nEscape attribute value for use in HTTP header\r\n\r\n```javascript\r\n\r\nvar a = Hoek.escapeHeaderAttribute('I said \"go w\\\\o me\"');  //returns I said \\\"go w\\\\o me\\\"\r\n\r\n\r\n```\r\n\r\n\r\n### escapeRegex(string)\r\n\r\nEscape string for Regex construction\r\n\r\n```javascript\r\n\r\nvar a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\\\/`\"(>)[<]d{}s,');  // returns 4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`\"\\(>\\)\\[<\\]d\\{\\}s\\,\r\n\r\n\r\n\r\n```\r\n\r\n# Errors\r\n\r\n### assert(message)\r\n\r\n```javascript\r\n\r\nvar a = 1, b =2;\r\n\r\nHoek.assert(a === b, 'a should equal b');  // ABORT: a should equal b\r\n\r\n```\r\n\r\n### abort(message)\r\n\r\nFirst checks if process.env.NODE_ENV === 'test', and if so, throws error message. Otherwise,\r\ndisplays most recent stack and then exits process.\r\n\r\n\r\n\r\n### displayStack(slice)\r\n\r\nDisplays the trace stack\r\n\r\n```javascript\r\n\r\nvar stack = Hoek.displayStack();\r\nconsole.log(stack) // returns something like:\r\n\r\n[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',\r\n  'Module._compile (module.js:449:26)',\r\n  'Module._extensions..js (module.js:467:10)',\r\n  'Module.load (module.js:356:32)',\r\n  'Module._load (module.js:312:12)',\r\n  'Module.runMain (module.js:492:10)',\r\n  'startup.processNextTick.process._tickCallback (node.js:244:9)' ]\r\n\r\n```\r\n\r\n### callStack(slice)\r\n\r\nReturns a trace stack array.\r\n\r\n```javascript\r\n\r\nvar stack = Hoek.callStack();\r\nconsole.log(stack)  // returns something like:\r\n\r\n[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],\r\n  [ 'module.js', 449, 26, 'Module._compile', false ],\r\n  [ 'module.js', 467, 10, 'Module._extensions..js', false ],\r\n  [ 'module.js', 356, 32, 'Module.load', false ],\r\n  [ 'module.js', 312, 12, 'Module._load', false ],\r\n  [ 'module.js', 492, 10, 'Module.runMain', false ],\r\n  [ 'node.js',\r\n    244,\r\n    9,\r\n    'startup.processNextTick.process._tickCallback',\r\n    false ] ]\r\n\r\n\r\n```\r\n\r\n### toss(condition)\r\n\r\ntoss(condition /*, [message], callback */)\r\n\r\nReturn an error as first argument of a callback\r\n\r\n\r\n# Load Files\r\n\r\n### loadPackage(dir)\r\n\r\nLoad and parse package.json process root or given directory\r\n\r\n```javascript\r\n\r\nvar pack = Hoek.loadPackage();  // pack.name === 'hoek'\r\n\r\n```\r\n\r\n### loadDirModules(path, excludeFiles, target) \r\n\r\nLoads modules from a given path; option to exclude files (array).\r\n\r\n\r\n\r\n\r\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/spumko/hoek/issues"
+  },
+  "homepage": "https://github.com/spumko/hoek",
+  "_id": "hoek@0.9.1",
+  "_from": "hoek@0.9.x"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/escaper.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/escaper.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/escaper.js	(revision 484)
@@ -0,0 +1,86 @@
+// Load modules
+
+var Lab = require('lab');
+var Hoek = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hoek', function () {
+
+    describe('#escapeJavaScript', function () {
+
+        it('encodes / characters', function (done) {
+
+            var encoded = Hoek.escapeJavaScript('<script>alert(1)</script>');
+            expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e');
+            done();
+        });
+
+        it('encodes \' characters', function (done) {
+
+            var encoded = Hoek.escapeJavaScript('something(\'param\')');
+            expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29');
+            done();
+        });
+
+        it('encodes large unicode characters with the correct padding', function (done) {
+
+            var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000));
+            expect(encoded).to.equal('\\u0500\\u1000');
+            done();
+        });
+
+        it('doesn\'t throw an exception when passed null', function (done) {
+
+            var encoded = Hoek.escapeJavaScript(null);
+            expect(encoded).to.equal('');
+            done();
+        });
+    });
+
+    describe('#escapeHtml', function () {
+
+        it('encodes / characters', function (done) {
+
+            var encoded = Hoek.escapeHtml('<script>alert(1)</script>');
+            expect(encoded).to.equal('&lt;script&gt;alert&#x28;1&#x29;&lt;&#x2f;script&gt;');
+            done();
+        });
+
+        it('encodes < and > as named characters', function (done) {
+
+            var encoded = Hoek.escapeHtml('<script><>');
+            expect(encoded).to.equal('&lt;script&gt;&lt;&gt;');
+            done();
+        });
+
+        it('encodes large unicode characters', function (done) {
+
+            var encoded = Hoek.escapeHtml(String.fromCharCode(500) + String.fromCharCode(1000));
+            expect(encoded).to.equal('&#500;&#1000;');
+            done();
+        });
+
+        it('doesn\'t throw an exception when passed null', function (done) {
+
+            var encoded = Hoek.escapeHtml(null);
+            expect(encoded).to.equal('');
+            done();
+        });
+    });
+});
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/index.js	(revision 484)
@@ -0,0 +1,1078 @@
+// Load modules
+
+var Lab = require('lab');
+var Hoek = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hoek', function () {
+
+    var nestedObj = {
+        v: [7,8,9],
+        w: /^something$/igm,
+        x: {
+            a: [1, 2, 3],
+            b: 123456,
+            c: new Date(),
+            d: /hi/igm,
+            e: /hello/
+        },
+        y: 'y',
+        z: new Date()
+    };
+
+    var dupsArray = [nestedObj, { z: 'z' }, nestedObj];
+    var reducedDupsArray = [nestedObj, { z: 'z' }];
+
+    describe('#clone', function () {
+
+        it('should clone a nested object', function (done) {
+
+            var a = nestedObj;
+            var b = Hoek.clone(a);
+
+            expect(a).to.deep.equal(b);
+            expect(a.z.getTime()).to.equal(b.z.getTime());
+            done();
+        });
+
+        it('should clone a null object', function (done) {
+
+            var b = Hoek.clone(null);
+
+            expect(b).to.equal(null);
+            done();
+        });
+
+        it('should not convert undefined properties to null', function (done) {
+
+            var obj = { something: undefined };
+            var b = Hoek.clone(obj);
+
+            expect(typeof b.something).to.equal('undefined');
+            done();
+        });
+
+        it('should not throw on circular reference', function (done) {
+
+            var a = {};
+            a.x = a;
+
+            var test = (function () {
+
+                var b = Hoek.clone(a);
+            });
+
+            expect(test).to.not.throw();
+            done();
+        });
+
+        it('should properly clone circular reference', function (done) {
+
+            var x = {
+                'z': new Date()
+            };
+            x.y = x;
+
+            var b = Hoek.clone(x);
+            expect(Object.keys(b.y)).to.deep.equal(Object.keys(x))
+            expect(b.z).to.not.equal(x.z);
+            expect(b.y).to.not.equal(x.y);
+            expect(b.y.z).to.not.equal(x.y.z);
+            expect(b.y).to.equal(b);
+            expect(b.y.y.y.y).to.equal(b);
+            done();
+        });
+
+        it('should properly clone deeply nested object', function (done) {
+
+            var a = {
+                x: {
+                    y: {
+                        a: [1, 2, 3],
+                        b: 123456,
+                        c: new Date(),
+                        d: /hi/igm,
+                        e: /hello/
+                    },
+                }
+            };
+
+            var b = Hoek.clone(a);
+
+            expect(a).to.deep.equal(b);
+            expect(a.x.y.c.getTime()).to.equal(b.x.y.c.getTime());
+            done();
+        });
+
+        it('should properly clone arrays', function (done) {
+
+            var a = [1,2,3];
+
+            var b = Hoek.clone(a);
+
+            expect(a).to.deep.equal(b);
+            done();
+        });
+
+        it('should perform actual copy for shallow keys (no pass by reference)', function (done) {
+
+            var x = Hoek.clone(nestedObj);
+            var y = Hoek.clone(nestedObj);
+
+            // Date
+            expect(x.z).to.not.equal(nestedObj.z);
+            expect(x.z).to.not.equal(y.z);
+
+            // Regex
+            expect(x.w).to.not.equal(nestedObj.w);
+            expect(x.w).to.not.equal(y.w);
+
+            // Array
+            expect(x.v).to.not.equal(nestedObj.v);
+            expect(x.v).to.not.equal(y.v);
+
+            // Immutable(s)
+            x.y = 5;
+            expect(x.y).to.not.equal(nestedObj.y);
+            expect(x.y).to.not.equal(y.y);
+
+            done();
+        });
+
+        it('should perform actual copy for deep keys (no pass by reference)', function (done) {
+
+            var x = Hoek.clone(nestedObj);
+            var y = Hoek.clone(nestedObj);
+
+            expect(x.x.c).to.not.equal(nestedObj.x.c);
+            expect(x.x.c).to.not.equal(y.x.c);
+
+            expect(x.x.c.getTime()).to.equal(nestedObj.x.c.getTime());
+            expect(x.x.c.getTime()).to.equal(y.x.c.getTime());
+            done();
+        });
+
+        it('copies functions with properties', function (done) {
+
+            var a = {
+                x: function () { return 1; },
+                y: {}
+            };
+            a.x.z = 'string in function';
+            a.x.v = function () { return 2; };
+            a.y.u = a.x;
+
+            var b = Hoek.clone(a);
+            expect(b.x()).to.equal(1);
+            expect(b.x.v()).to.equal(2);
+            expect(b.y.u).to.equal(b.x);
+            expect(b.x.z).to.equal('string in function');
+            done();
+        });
+
+        it('should copy a buffer', function(done){
+            var tls = {
+                key: new Buffer([1,2,3,4,5]),
+                cert: new Buffer([1,2,3,4,5,6,10])
+            }
+
+            copiedTls = Hoek.clone(tls);
+            expect(Buffer.isBuffer(copiedTls.key)).to.equal(true);
+            expect(JSON.stringify(copiedTls.key)).to.equal(JSON.stringify(tls.key))
+            expect(Buffer.isBuffer(copiedTls.cert)).to.equal(true);
+            expect(JSON.stringify(copiedTls.cert)).to.equal(JSON.stringify(tls.cert))
+            done();
+        });
+    });
+
+    describe('#merge', function () {
+
+        it('does not throw if source is null', function (done) {
+
+            var a = {};
+            var b = null;
+            var c = null;
+
+            expect(function () {
+
+                c = Hoek.merge(a, b);
+            }).to.not.throw();
+
+            expect(c).to.equal(a);
+            done();
+        });
+
+        it('does not throw if source is undefined', function (done) {
+
+            var a = {};
+            var b = undefined;
+            var c = null;
+
+            expect(function () {
+
+                c = Hoek.merge(a, b);
+            }).to.not.throw();
+
+            expect(c).to.equal(a);
+            done();
+        });
+
+        it('throws if source is not an object', function (done) {
+
+            expect(function () {
+
+                var a = {};
+                var b = 0;
+
+                Hoek.merge(a, b);
+            }).to.throw('Invalid source value: must be null, undefined, or an object');
+            done();
+        });
+
+        it('throws if target is not an object', function (done) {
+
+            expect(function () {
+
+                var a = 0;
+                var b = {};
+
+                Hoek.merge(a, b);
+            }).to.throw('Invalid target value: must be an object');
+            done();
+        });
+
+        it('throws if target is not an array and source is', function (done) {
+
+            expect(function () {
+
+                var a = {};
+                var b = [1, 2];
+
+                Hoek.merge(a, b);
+            }).to.throw('Cannot merge array onto an object');
+            done();
+        });
+
+        it('returns the same object when merging arrays', function (done) {
+
+            var a = [];
+            var b = [1, 2];
+
+            expect(Hoek.merge(a, b)).to.equal(a);
+            done();
+        });
+
+        it('should combine an empty object with a non-empty object', function (done) {
+
+            var a = {};
+            var b = nestedObj;
+
+            var c = Hoek.merge(a, b);
+            expect(a).to.deep.equal(b);
+            expect(c).to.deep.equal(b);
+            done();
+        });
+
+        it('should override values in target', function (done) {
+
+            var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
+            var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
+
+            var c = Hoek.merge(a, b);
+            expect(c.x).to.equal(null);
+            expect(c.y).to.equal(2);
+            expect(c.z).to.equal(4);
+            expect(c.v).to.equal(0);
+            expect(c.m).to.equal('123');
+            expect(c.t).to.deep.equal({ u: 6 });
+            done();
+        });
+
+        it('should override values in target (flip)', function (done) {
+
+            var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
+            var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
+
+            var d = Hoek.merge(b, a);
+            expect(d.x).to.equal(1);
+            expect(d.y).to.equal(2);
+            expect(d.z).to.equal(3);
+            expect(d.v).to.equal(5);
+            expect(d.m).to.equal('abc');
+            expect(d.t).to.deep.equal('test');
+            done();
+        });
+    });
+
+    describe('#applyToDefaults', function () {
+
+        var defaults = {
+            a: 1,
+            b: 2,
+            c: {
+                d: 3,
+                e: [5, 6]
+            },
+            f: 6,
+            g: 'test'
+        };
+
+        it('should return null if options is false', function (done) {
+
+            var result = Hoek.applyToDefaults(defaults, false);
+            expect(result).to.equal(null);
+            done();
+        });
+
+        it('should return a copy of defaults if options is true', function (done) {
+
+            var result = Hoek.applyToDefaults(defaults, true);
+            expect(result).to.deep.equal(result);
+            done();
+        });
+
+        it('should apply object to defaults', function (done) {
+
+            var obj = {
+                a: null,
+                c: {
+                    e: [4]
+                },
+                f: 0,
+                g: {
+                    h: 5
+                }
+            };
+
+            var result = Hoek.applyToDefaults(defaults, obj);
+            expect(result.c.e).to.deep.equal([4]);
+            expect(result.a).to.equal(1);
+            expect(result.b).to.equal(2);
+            expect(result.f).to.equal(0);
+            expect(result.g).to.deep.equal({ h: 5 });
+            done();
+        });
+    });
+
+    describe('#unique', function () {
+
+        it('should ensure uniqueness within array of objects based on subkey', function (done) {
+
+            var a = Hoek.unique(dupsArray, 'x');
+            expect(a).to.deep.equal(reducedDupsArray);
+            done();
+        });
+
+        it('removes duplicated without key', function (done) {
+
+            expect(Hoek.unique([1, 2, 3, 4, 2, 1, 5])).to.deep.equal([1, 2, 3, 4, 5]);
+            done();
+        });
+    });
+
+    describe('#mapToObject', function () {
+
+        it('should return null on null array', function (done) {
+
+            var a = Hoek.mapToObject(null);
+            expect(a).to.equal(null);
+            done();
+        });
+
+        it('should convert basic array to existential object', function (done) {
+
+            var keys = [1, 2, 3, 4];
+            var a = Hoek.mapToObject(keys);
+            for (var i in keys) {
+                expect(a[keys[i]]).to.equal(true);
+            }
+            done();
+        });
+
+        it('should convert array of objects to existential object', function (done) {
+
+            var keys = [{ x: 1 }, { x: 2 }, { x: 3 }];
+            var subkey = 'x';
+            var a = Hoek.mapToObject(keys, subkey);
+            for (var i in keys) {
+                expect(a[keys[i][subkey]]).to.equal(true);
+            }
+            done();
+        });
+    });
+
+    describe('#intersect', function () {
+
+        it('should return the common objects of two arrays', function (done) {
+
+            var array1 = [1, 2, 3, 4, 4, 5, 5];
+            var array2 = [5, 4, 5, 6, 7];
+            var common = Hoek.intersect(array1, array2);
+            expect(common.length).to.equal(2);
+            done();
+        });
+
+        it('should return just the first common object of two arrays', function (done) {
+
+            var array1 = [1, 2, 3, 4, 4, 5, 5];
+            var array2 = [5, 4, 5, 6, 7];
+            var common = Hoek.intersect(array1, array2, true);
+            expect(common).to.equal(5);
+            done();
+        });
+
+        it('should return an empty array if either input is null', function (done) {
+
+            expect(Hoek.intersect([1], null).length).to.equal(0);
+            expect(Hoek.intersect(null, [1]).length).to.equal(0);
+            done();
+        });
+
+        it('should return the common objects of object and array', function (done) {
+
+            var array1 = [1, 2, 3, 4, 4, 5, 5];
+            var array2 = [5, 4, 5, 6, 7];
+            var common = Hoek.intersect(Hoek.mapToObject(array1), array2);
+            expect(common.length).to.equal(2);
+            done();
+        });
+    });
+
+    describe('#matchKeys', function () {
+
+        it('should match the existing object keys', function (done) {
+
+            var obj = {
+                a: 1,
+                b: 2,
+                c: 3,
+                d: null
+            };
+
+            expect(Hoek.matchKeys(obj, ['b', 'c', 'd', 'e'])).to.deep.equal(['b', 'c', 'd']);
+            done();
+        });
+    });
+
+    describe('#flatten', function () {
+
+        it('should return a flat array', function (done) {
+
+            var result = Hoek.flatten([1, 2, [3, 4, [5, 6], [7], 8], [9], [10, [11, 12]], 13]);
+            expect(result.length).to.equal(13);
+            expect(result).to.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
+            done();
+        });
+    });
+
+    describe('#removeKeys', function () {
+
+        var objWithHiddenKeys = {
+            location: {
+                name: 'San Bruno'
+            },
+            company: {
+                name: '@WalmartLabs'
+            }
+        };
+
+        it('should delete params with definition\'s hide set to true', function (done) {
+
+            var a = Hoek.removeKeys(objWithHiddenKeys, ['location']);
+            expect(objWithHiddenKeys.location).to.not.exist;
+            expect(objWithHiddenKeys.company).to.exist;
+            done();
+        });
+    });
+
+    describe('#reach', function () {
+
+        var obj = {
+            a: {
+                b: {
+                    c: {
+                        d: 1,
+                        e: 2
+                    },
+                    f: 'hello'
+                },
+                g: {
+                    h: 3
+                }
+            },
+            i: function () { }
+        };
+
+        it('returns a valid member', function (done) {
+
+            expect(Hoek.reach(obj, 'a.b.c.d')).to.equal(1);
+            done();
+        });
+
+        it('returns null on null object', function (done) {
+
+            expect(Hoek.reach(null, 'a.b.c.d')).to.not.exist;
+            done();
+        });
+
+        it('returns null on missing member', function (done) {
+
+            expect(Hoek.reach(obj, 'a.b.c.d.x')).to.not.exist;
+            done();
+        });
+
+        it('returns null on invalid member', function (done) {
+
+            expect(Hoek.reach(obj, 'a.b.c.d-.x')).to.not.exist;
+            done();
+        });
+
+        it('returns function member', function (done) {
+
+            expect(typeof Hoek.reach(obj, 'i')).to.equal('function');
+            done();
+        });
+    });
+
+    describe('#inheritAsync', function () {
+
+        it('should inherit selected methods and wrap in async call', function (done) {
+
+            var proto = {
+                a: function () {
+                    return 'a!';
+                },
+                b: function () {
+                    return 'b!';
+                },
+                c: function () {
+                    throw new Error('c!');
+                }
+            };
+
+            var targetFunc = function () { };
+            targetFunc.prototype.c = function () {
+
+                return 'oops';
+            };
+
+            Hoek.inheritAsync(targetFunc, proto, ['a', 'c']);
+            var target = new targetFunc();
+
+            expect(typeof target.a).to.equal('function');
+            expect(typeof target.c).to.equal('function');
+            expect(target.b).to.not.exist;
+
+            target.a(function (err, result) {
+
+                expect(err).to.not.exist;
+                expect(result).to.equal('a!');
+
+                target.c(function (err, result) {
+
+                    expect(result).to.not.exist;
+                    expect(err.message).to.equal('c!');
+                    done();
+                });
+            });
+        });
+    });
+
+    describe('#callStack', function () {
+
+        it('should return the full call stack', function (done) {
+
+            var stack = Hoek.callStack();
+            expect(stack[0][0]).to.contain('index.js');
+            expect(stack[0][2]).to.equal(30);
+            done();
+        });
+    });
+
+    describe('#displayStack ', function () {
+
+        it('should return the full call stack for display', function (done) {
+
+            var stack = Hoek.displayStack();
+            expect(stack[0]).to.contain('test/index.js:');
+            done();
+        });
+
+        it('should include constructor functions correctly', function (done) {
+
+            var Something = function (next) {
+
+                next();
+            };
+
+            var something = new Something(function () {
+
+                var stack = Hoek.displayStack();
+                expect(stack[1]).to.contain('new Something');
+                done();
+            });
+        });
+    });
+
+    describe('#abort', function () {
+
+        it('should exit process when not in test mode', function (done) {
+
+            var env = process.env.NODE_ENV;
+            var write = process.stdout.write;
+            var exit = process.exit;
+
+            process.env.NODE_ENV = 'nottatest';
+            process.stdout.write = function () { };
+            process.exit = function (state) {
+
+                process.exit = exit;
+                process.env.NODE_ENV = env;
+                process.stdout.write = write;
+
+                expect(state).to.equal(1);
+                done();
+            };
+
+            Hoek.abort('Boom');
+        });
+
+        it('should throw when not in test mode and abortThrow is true', function (done) {
+
+            var env = process.env.NODE_ENV;
+            process.env.NODE_ENV = 'nottatest';
+            Hoek.abortThrow = true;
+
+            var fn = function () {
+
+                Hoek.abort('my error message');
+            };
+
+            expect(fn).to.throw('my error message');
+            Hoek.abortThrow = false;
+            process.env.NODE_ENV = env;
+
+            done();
+        });
+
+
+        it('should respect hideStack argument', function (done) {
+
+            var env = process.env.NODE_ENV;
+            var write = process.stdout.write;
+            var exit = process.exit;
+            var output = '';
+
+            process.exit = function () { };
+            process.env.NODE_ENV = '';
+            process.stdout.write = function (message) {
+
+                output = message;
+            };
+
+            Hoek.abort('my error message', true);
+
+            process.env.NODE_ENV = env;
+            process.stdout.write = write;
+            process.exit = exit;
+
+            expect(output).to.equal('ABORT: my error message\n\t\n');
+
+            done();
+        });
+
+        it('should default to showing stack', function (done) {
+
+            var env = process.env.NODE_ENV;
+            var write = process.stdout.write;
+            var exit = process.exit;
+            var output = '';
+
+            process.exit = function () { };
+            process.env.NODE_ENV = '';
+            process.stdout.write = function (message) {
+
+                output = message;
+            };
+
+            Hoek.abort('my error message');
+
+            process.env.NODE_ENV = env;
+            process.stdout.write = write;
+            process.exit = exit;
+
+            expect(output).to.contain('index.js');
+
+            done();
+        });
+    });
+
+    describe('#assert', function () {
+
+        it('should throw an Error when using assert in a test', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, 'my error message');
+            };
+
+            expect(fn).to.throw('my error message');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with no message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false);
+            };
+
+            expect(fn).to.throw('Unknown error');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with multipart message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, 'This', 'is', 'my message');
+            };
+
+            expect(fn).to.throw('This is my message');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with object message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, 'This', 'is', { spinal: 'tap' });
+            };
+
+            expect(fn).to.throw('This is {"spinal":"tap"}');
+            done();
+        });
+
+        it('should throw an Error when using assert in a test with error object message', function (done) {
+
+            var fn = function () {
+
+                Hoek.assert(false, new Error('This is spinal tap'));
+            };
+
+            expect(fn).to.throw('This is spinal tap');
+            done();
+        });
+    });
+
+    describe('#loadDirModules', function () {
+
+        it('should load modules from directory', function (done) {
+
+            var target = {};
+            Hoek.loadDirModules(__dirname + '/modules', ['test2'], target);
+            expect(target.Test1.x).to.equal(1);
+            expect(target.Test2).to.not.exist;
+            expect(target.Test3.z).to.equal(3);
+            done();
+        });
+
+        it('should list modules from directory into function', function (done) {
+
+            var target = {};
+            Hoek.loadDirModules(__dirname + '/modules', ['test2'], function (path, name, capName) {
+
+                target[name] = capName;
+            });
+
+            expect(target.test1).to.equal('Test1');
+            expect(target.test2).to.not.exist;
+            expect(target.test3).to.equal('Test3');
+            done();
+        });
+    });
+
+    describe('#rename', function () {
+
+        it('should rename object key', function (done) {
+
+            var a = { b: 'c' };
+            Hoek.rename(a, 'b', 'x');
+            expect(a.b).to.not.exist;
+            expect(a.x).to.equal('c');
+            done();
+        });
+    });
+
+    describe('Timer', function () {
+
+        it('should return time elapsed', function (done) {
+
+            var timer = new Hoek.Timer();
+            setTimeout(function () {
+
+                expect(timer.elapsed()).to.be.above(9);
+                done();
+            }, 12);
+        });
+    });
+
+    describe('#loadPackage', function () {
+
+        it('should', function (done) {
+
+            var pack = Hoek.loadPackage();
+            expect(pack.name).to.equal('hoek');
+            done();
+        });
+    });
+
+    describe('#escapeRegex', function () {
+
+        it('should escape all special regular expression characters', function (done) {
+
+            var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');
+            expect(a).to.equal('4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`"\\(>\\)\\[<\\]d\\{\\}s\\,');
+            done();
+        });
+    });
+
+    describe('#toss', function () {
+
+        it('should call callback with new error', function (done) {
+
+            var callback = function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('bug');
+                done();
+            };
+
+            Hoek.toss(true, 'feature', callback);
+            Hoek.toss(false, 'bug', callback);
+        });
+
+        it('should call callback with new error and no message', function (done) {
+
+            Hoek.toss(false, function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('');
+                done();
+            });
+        });
+
+        it('should call callback with error condition', function (done) {
+
+            Hoek.toss(new Error('boom'), function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('boom');
+                done();
+            });
+        });
+
+        it('should call callback with new error using message with error condition', function (done) {
+
+            Hoek.toss(new Error('ka'), 'boom', function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('boom');
+                done();
+            });
+        });
+
+        it('should call callback with new error using passed error with error condition', function (done) {
+
+            Hoek.toss(new Error('ka'), new Error('boom'), function (err) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('boom');
+                done();
+            });
+        });
+    });
+
+    describe('Base64Url', function () {
+
+        var base64str = 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w';
+        var str = unescape('%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29*+%2C-./0123456789%3A%3B%3C%3D%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF');
+
+        describe('#base64urlEncode', function () {
+
+            it('should base64 URL-safe a string', function (done) {
+
+                expect(Hoek.base64urlEncode(str)).to.equal(base64str);
+                done();
+            });
+        });
+
+        describe('#base64urlDecode', function () {
+
+            it('should un-base64 URL-safe a string', function (done) {
+
+                expect(Hoek.base64urlDecode(base64str)).to.equal(str);
+                done();
+            });
+
+            it('should return error on undefined input', function (done) {
+
+                expect(Hoek.base64urlDecode().message).to.exist;
+                done();
+            });
+
+            it('should return error on invalid input', function (done) {
+
+                expect(Hoek.base64urlDecode('*').message).to.exist;
+                done();
+            });
+        });
+    });
+
+    describe('#escapeHeaderAttribute', function () {
+
+        it('should not alter ascii values', function (done) {
+
+            var a = Hoek.escapeHeaderAttribute('My Value');
+            expect(a).to.equal('My Value');
+            done();
+        });
+
+        it('should escape all special HTTP header attribute characters', function (done) {
+
+            var a = Hoek.escapeHeaderAttribute('I said go!!!#"' + String.fromCharCode(92));
+            expect(a).to.equal('I said go!!!#\\"\\\\');
+            done();
+        });
+
+        it('should throw on large unicode characters', function (done) {
+
+            var fn = function () {
+
+                Hoek.escapeHeaderAttribute('this is a test' + String.fromCharCode(500) + String.fromCharCode(300));
+            };
+
+            expect(fn).to.throw(Error);
+            done();
+        });
+
+        it('should throw on CRLF to prevent response splitting', function (done) {
+
+            var fn = function () {
+
+                Hoek.escapeHeaderAttribute('this is a test\r\n');
+            };
+
+            expect(fn).to.throw(Error);
+            done();
+        });
+    });
+
+    describe('#escapeHtml', function () {
+
+        it('should escape all special HTML characters', function (done) {
+
+            var a = Hoek.escapeHtml('&<>"\'`');
+            expect(a).to.equal('&amp;&lt;&gt;&quot;&#x27;&#x60;');
+            done();
+        });
+
+        it('should return empty string on falsy input', function (done) {
+
+            var a = Hoek.escapeHtml('');
+            expect(a).to.equal('');
+            done();
+        });
+
+        it('should return unchanged string on no reserved input', function (done) {
+
+            var a = Hoek.escapeHtml('abc');
+            expect(a).to.equal('abc');
+            done();
+        });
+    });
+
+    describe('#printEvent', function () {
+
+        it('outputs event as string', function (done) {
+
+            var event = {
+                timestamp: (new Date(2013, 1, 1, 6, 30, 45, 123)).getTime(),
+                tags: ['a', 'b', 'c'],
+                data: { some: 'data' }
+            };
+
+            Hoek.consoleFunc = function (string) {
+
+                Hoek.consoleFunc = console.log;
+                expect(string).to.equal('130201/063045.123, a, {"some":"data"}');
+                done();
+            };
+
+            Hoek.printEvent(event);
+        });
+
+        it('outputs JSON error', function (done) {
+
+            var event = {
+                timestamp: (new Date(2013, 1, 1, 6, 30, 45, 123)).getTime(),
+                tags: ['a', 'b', 'c'],
+                data: { some: 'data' }
+            };
+
+            event.data.a = event.data;
+
+            Hoek.consoleFunc = function (string) {
+
+                Hoek.consoleFunc = console.log;
+                expect(string).to.equal('130201/063045.123, a, JSON Error: Converting circular structure to JSON');
+                done();
+            };
+
+            Hoek.printEvent(event);
+        });
+    });
+
+    describe('#nextTick', function () {
+
+        it('calls the provided callback on nextTick', function (done) {
+
+            var a = 0;
+
+            var inc = function (step, next) {
+
+                a += step;
+                next();
+            };
+
+            var ticked = Hoek.nextTick(inc);
+
+            ticked(5, function () {
+
+                expect(a).to.equal(6);
+                done();
+            });
+
+            expect(a).to.equal(0);
+            inc(1, function () {
+
+                expect(a).to.equal(1);
+            });
+        });
+    });
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test1.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test1.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test1.js	(revision 484)
@@ -0,0 +1,1 @@
+exports.x = 1;
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test2.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test2.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test2.js	(revision 484)
@@ -0,0 +1,1 @@
+exports.y = 2;
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test3.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test3.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/node_modules/hoek/test/modules/test3.js	(revision 484)
@@ -0,0 +1,1 @@
+exports.z = 3;
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/package.json	(revision 484)
@@ -0,0 +1,48 @@
+{
+  "name": "sntp",
+  "description": "SNTP Client",
+  "version": "0.2.4",
+  "author": {
+    "name": "Eran Hammer",
+    "email": "eran@hueniverse.com",
+    "url": "http://hueniverse.com"
+  },
+  "contributors": [],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/hueniverse/sntp"
+  },
+  "main": "index",
+  "keywords": [
+    "sntp",
+    "ntp",
+    "time"
+  ],
+  "engines": {
+    "node": ">=0.8.0"
+  },
+  "dependencies": {
+    "hoek": "0.9.x"
+  },
+  "devDependencies": {
+    "lab": "0.1.x",
+    "complexity-report": "0.x.x"
+  },
+  "scripts": {
+    "test": "make test-cov"
+  },
+  "licenses": [
+    {
+      "type": "BSD",
+      "url": "http://github.com/hueniverse/sntp/raw/master/LICENSE"
+    }
+  ],
+  "readme": "# sntp\n\nAn SNTP v4 client (RFC4330) for node. Simpy connects to the NTP or SNTP server requested and returns the server time\nalong with the roundtrip duration and clock offset. To adjust the local time to the NTP time, add the returned `t` offset\nto the local time.\n\n[![Build Status](https://secure.travis-ci.org/hueniverse/sntp.png)](http://travis-ci.org/hueniverse/sntp)\n\n# Usage\n\n```javascript\nvar Sntp = require('sntp');\n\n// All options are optional\n\nvar options = {\n    host: 'nist1-sj.ustiming.org',  // Defaults to pool.ntp.org\n    port: 123,                      // Defaults to 123 (NTP)\n    resolveReference: true,         // Default to false (not resolving)\n    timeout: 1000                   // Defaults to zero (no timeout)\n};\n\n// Request server time\n\nSntp.time(options, function (err, time) {\n\n    if (err) {\n        console.log('Failed: ' + err.message);\n        process.exit(1);\n    }\n\n    console.log('Local clock is off by: ' + time.t + ' milliseconds');\n    process.exit(0);\n});\n```\n\nIf an application needs to maintain continuous time synchronization, the module provides a stateful method for\nquerying the current offset only when the last one is too old (defaults to daily).\n\n```javascript\n// Request offset once\n\nSntp.offset(function (err, offset) {\n\n    console.log(offset);                    // New (served fresh)\n\n    // Request offset again\n\n    Sntp.offset(function (err, offset) {\n\n        console.log(offset);                // Identical (served from cache)\n    });\n});\n```\n\nTo set a background offset refresh, start the interval and use the provided now() method. If for any reason the\nclient fails to obtain an up-to-date offset, the current system clock is used.\n\n```javascript\nvar before = Sntp.now();                    // System time without offset\n\nSntp.start(function () {\n\n    var now = Sntp.now();                   // With offset\n    Sntp.stop();\n});\n```\n\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/hueniverse/sntp/issues"
+  },
+  "homepage": "https://github.com/hueniverse/sntp",
+  "_id": "sntp@0.2.4",
+  "_from": "sntp@0.2.x"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/test/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/test/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/node_modules/sntp/test/index.js	(revision 484)
@@ -0,0 +1,359 @@
+// Load modules
+
+var Dgram = require('dgram');
+var Lab = require('lab');
+var Sntp = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('SNTP', function () {
+
+    describe('#time', function () {
+
+        it('returns consistent result over multiple tries', function (done) {
+
+            Sntp.time(function (err, time) {
+
+                expect(err).to.not.exist;
+                expect(time).to.exist;
+                var t1 = time.t;
+
+                Sntp.time(function (err, time) {
+
+                    expect(err).to.not.exist;
+                    expect(time).to.exist;
+                    var t2 = time.t;
+                    expect(Math.abs(t1 - t2)).is.below(200);
+                    done();
+                });
+            });
+        });
+
+        it('resolves reference IP', function (done) {
+
+            Sntp.time({ host: 'ntp.exnet.com', resolveReference: true }, function (err, time) {
+
+                expect(err).to.not.exist;
+                expect(time).to.exist;
+                expect(time.referenceHost).to.exist;
+                done();
+            });
+        });
+
+        it('times out on no response', function (done) {
+
+            Sntp.time({ port: 124, timeout: 100 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(time).to.not.exist;
+                expect(err.message).to.equal('Timeout');
+                done();
+            });
+        });
+
+        it('errors on error event', function (done) {
+
+            var orig = Dgram.createSocket;
+            Dgram.createSocket = function (type) {
+
+                Dgram.createSocket = orig;
+                var socket = Dgram.createSocket(type);
+                process.nextTick(function () { socket.emit('error', new Error('Fake')) });
+                return socket;
+            };
+
+            Sntp.time(function (err, time) {
+
+                expect(err).to.exist;
+                expect(time).to.not.exist;
+                expect(err.message).to.equal('Fake');
+                done();
+            });
+        });
+
+        it('times out on invalid host', function (done) {
+
+            Sntp.time({ host: 'error', timeout: 10000 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(time).to.not.exist;
+                expect(err.message).to.equal('getaddrinfo ENOTFOUND');
+                done();
+            });
+        });
+
+        it('fails on bad response buffer size', function (done) {
+
+            var server = Dgram.createSocket('udp4');
+            server.on('message', function (message, remote) {
+                var message = new Buffer(10);
+                server.send(message, 0, message.length, remote.port, remote.address, function (err, bytes) {
+
+                    server.close();
+                });
+            });
+
+            server.bind(49123);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('Invalid server response');
+                done();
+            });
+        });
+
+        var messup = function (bytes) {
+
+            var server = Dgram.createSocket('udp4');
+            server.on('message', function (message, remote) {
+
+                var message = new Buffer([
+                    0x24, 0x01, 0x00, 0xe3,
+                    0x00, 0x00, 0x00, 0x00,
+                    0x00, 0x00, 0x00, 0x00,
+                    0x41, 0x43, 0x54, 0x53,
+                    0xd4, 0xa8, 0x2d, 0xc7,
+                    0x1c, 0x5d, 0x49, 0x1b,
+                    0xd4, 0xa8, 0x2d, 0xe6,
+                    0x67, 0xef, 0x9d, 0xb2,
+                    0xd4, 0xa8, 0x2d, 0xe6,
+                    0x71, 0xed, 0xb5, 0xfb,
+                    0xd4, 0xa8, 0x2d, 0xe6,
+                    0x71, 0xee, 0x6c, 0xc5
+                ]);
+
+                for (var i = 0, il = bytes.length; i < il; ++i) {
+                    message[bytes[i][0]] = bytes[i][1];
+                }
+
+                server.send(message, 0, message.length, remote.port, remote.address, function (err, bytes) {
+
+                    server.close();
+                });
+            });
+
+            server.bind(49123);
+        };
+
+        it('fails on bad version', function (done) {
+
+            messup([[0, (0 << 6) + (3 << 3) + (4 << 0)]]);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(time.version).to.equal(3);
+                expect(err.message).to.equal('Invalid server response');
+                done();
+            });
+        });
+
+        it('fails on bad originate timestamp and alarm li', function (done) {
+
+            messup([[0, (3 << 6) + (4 << 3) + (4 << 0)]]);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('Wrong originate timestamp');
+                expect(time.leapIndicator).to.equal('alarm');
+                done();
+            });
+        });
+
+        it('returns time with death stratum and last61 li', function (done) {
+
+            messup([[0, (1 << 6) + (4 << 3) + (4 << 0)], [1, 0]]);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(time.stratum).to.equal('death');
+                expect(time.leapIndicator).to.equal('last-minute-61');
+                done();
+            });
+        });
+
+        it('returns time with reserved stratum and last59 li', function (done) {
+
+            messup([[0, (2 << 6) + (4 << 3) + (4 << 0)], [1, 0x1f]]);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(time.stratum).to.equal('reserved');
+                expect(time.leapIndicator).to.equal('last-minute-59');
+                done();
+            });
+        });
+
+        it('fails on bad mode (symmetric-active)', function (done) {
+
+            messup([[0, (0 << 6) + (4 << 3) + (1 << 0)]]);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(time.mode).to.equal('symmetric-active');
+                done();
+            });
+        });
+
+        it('fails on bad mode (symmetric-passive)', function (done) {
+
+            messup([[0, (0 << 6) + (4 << 3) + (2 << 0)]]);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(time.mode).to.equal('symmetric-passive');
+                done();
+            });
+        });
+
+        it('fails on bad mode (client)', function (done) {
+
+            messup([[0, (0 << 6) + (4 << 3) + (3 << 0)]]);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(time.mode).to.equal('client');
+                done();
+            });
+        });
+
+        it('fails on bad mode (broadcast)', function (done) {
+
+            messup([[0, (0 << 6) + (4 << 3) + (5 << 0)]]);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(time.mode).to.equal('broadcast');
+                done();
+            });
+        });
+
+        it('fails on bad mode (reserved)', function (done) {
+
+            messup([[0, (0 << 6) + (4 << 3) + (6 << 0)]]);
+
+            Sntp.time({ host: 'localhost', port: 49123 }, function (err, time) {
+
+                expect(err).to.exist;
+                expect(time.mode).to.equal('reserved');
+                done();
+            });
+        });
+    });
+
+    describe('#offset', function () {
+
+        it('gets the current offset', function (done) {
+
+            Sntp.offset(function (err, offset) {
+
+                expect(err).to.not.exist;
+                expect(offset).to.not.equal(0);
+                done();
+            });
+        });
+
+        it('gets the current offset from cache', function (done) {
+
+            Sntp.offset(function (err, offset) {
+
+                expect(err).to.not.exist;
+                expect(offset).to.not.equal(0);
+                var offset1 = offset;
+                Sntp.offset({}, function (err, offset) {
+
+                    expect(err).to.not.exist;
+                    expect(offset).to.equal(offset1);
+                    done();
+                });
+            });
+        });
+
+        it('fails getting the current offset on invalid server', function (done) {
+
+            Sntp.offset({ host: 'error' }, function (err, offset) {
+
+                expect(err).to.exist;
+                expect(offset).to.equal(0);
+                done();
+            });
+        });
+    });
+
+    describe('#now', function () {
+
+        it('starts auto-sync, gets now, then stops', function (done) {
+
+            Sntp.stop();
+
+            var before = Sntp.now();
+            expect(before).to.equal(Date.now());
+
+            Sntp.start(function () {
+
+                var now = Sntp.now();
+                expect(now).to.not.equal(Date.now());
+                Sntp.stop();
+
+                done();
+            });
+        });
+
+        it('starts twice', function (done) {
+
+            Sntp.start(function () {
+
+                Sntp.start(function () {
+
+                    var now = Sntp.now();
+                    expect(now).to.not.equal(Date.now());
+                    Sntp.stop();
+
+                    done();
+                });
+            });
+        });
+
+        it('starts auto-sync, gets now, waits, gets again after timeout', function (done) {
+
+            Sntp.stop();
+
+            var before = Sntp.now();
+            expect(before).to.equal(Date.now());
+
+            Sntp.start({ clockSyncRefresh: 100 }, function () {
+
+                var now = Sntp.now();
+                expect(now).to.not.equal(Date.now());
+                expect(now).to.equal(Sntp.now());
+
+                setTimeout(function () {
+
+                    expect(Sntp.now()).to.not.equal(now);
+                    Sntp.stop();
+                    done();
+                }, 110);
+            });
+        });
+    });
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/package.json	(revision 484)
@@ -0,0 +1,53 @@
+{
+  "name": "hawk",
+  "description": "HTTP Hawk Authentication Scheme",
+  "version": "0.13.1",
+  "author": {
+    "name": "Eran Hammer",
+    "email": "eran@hueniverse.com",
+    "url": "http://hueniverse.com"
+  },
+  "contributors": [],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/hueniverse/hawk"
+  },
+  "main": "index",
+  "keywords": [
+    "http",
+    "authentication",
+    "scheme",
+    "hawk"
+  ],
+  "engines": {
+    "node": ">=0.8.0"
+  },
+  "dependencies": {
+    "hoek": "0.8.x",
+    "boom": "0.4.x",
+    "cryptiles": "0.2.x",
+    "sntp": "0.2.x"
+  },
+  "devDependencies": {
+    "lab": "0.1.x",
+    "complexity-report": "0.x.x",
+    "localStorage": "1.0.x"
+  },
+  "scripts": {
+    "test": "make test-cov"
+  },
+  "licenses": [
+    {
+      "type": "BSD",
+      "url": "http://github.com/hueniverse/hawk/raw/master/LICENSE"
+    }
+  ],
+  "readme": "![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png)\r\n\r\n<img align=\"right\" src=\"https://raw.github.com/hueniverse/hawk/master/images/logo.png\" /> **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial\r\nHTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz).\r\n\r\nCurrent version: **0.13**\r\n\r\n[![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk)\r\n\r\n# Table of Content\r\n\r\n- [**Introduction**](#introduction)\r\n  - [Replay Protection](#replay-protection)\r\n  - [Usage Example](#usage-example)\r\n  - [Protocol Example](#protocol-example)\r\n    - [Payload Validation](#payload-validation)\r\n    - [Response Payload Validation](#response-payload-validation)\r\n  - [Browser Support and Considerations](#browser-support-and-considerations)\r\n<p></p>\r\n- [**Single URI Authorization**](#single-uri-authorization)\r\n  - [Usage Example](#bewit-usage-example)\r\n<p></p>\r\n- [**Security Considerations**](#security-considerations)\r\n  - [MAC Keys Transmission](#mac-keys-transmission)\r\n  - [Confidentiality of Requests](#confidentiality-of-requests)\r\n  - [Spoofing by Counterfeit Servers](#spoofing-by-counterfeit-servers)\r\n  - [Plaintext Storage of Credentials](#plaintext-storage-of-credentials)\r\n  - [Entropy of Keys](#entropy-of-keys)\r\n  - [Coverage Limitations](#coverage-limitations)\r\n  - [Future Time Manipulation](#future-time-manipulation)\r\n  - [Client Clock Poisoning](#client-clock-poisoning)\r\n  - [Bewit Limitations](#bewit-limitations)\r\n<p></p>\r\n- [**Frequently Asked Questions**](#frequently-asked-questions)\r\n<p></p>\r\n- [**Acknowledgements**](#acknowledgements)\r\n\r\n# Introduction\r\n\r\n**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with\r\npartial cryptographic verification of the request and response, covering the HTTP method, request URI, host,\r\nand optionally the request payload.\r\n\r\nSimilar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of\r\nclient credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme,\r\nthe key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is\r\nincluded in its place.\r\n\r\nHowever, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of\r\nreplay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less\r\n\"chattiness\" (interaction with the server).\r\n\r\nAlso unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because\r\nthe client and server must both have access to the key material in the clear.\r\n\r\nThe primary design goals of this scheme are to:\r\n* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources,\r\n* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where\r\n  to send an authenticated request), and\r\n* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client\r\n  failure to validate the server's identity as part of its TLS handshake.\r\n\r\nIn addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using\r\na query parameter called _bewit_ (in falconry, a leather strap used to attach a tracking device to the leg of a hawk).\r\n\r\nThe **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server,\r\nwhich is beyond the scope of this module. Typically, the shared credentials are established via an initial\r\nTLS-protected phase or derived from some other shared confidential information available to both the client\r\nand the server.\r\n\r\n\r\n## Replay Protection\r\n\r\nWithout replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more \r\nthan once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when \r\nmaking requests. This gives the server enough information to prevent replay attacks.\r\n\r\nThe nonce is generated by the client, and is a string unique across all requests with the same timestamp and\r\nkey identifier combination. \r\n\r\nThe timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards\r\nare rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks.\r\nBy default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in\r\npractice translates to a maximum of 2 minutes as the skew can be positive or negative).\r\n\r\nUsing a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client\r\nclock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types\r\n(e.g. browsers) to deploy NTP, the server provides the client with its current time (in seconds precision) in response\r\nto a bad timestamp.\r\n\r\nThere is no expectation that the client will adjust its system clock to match the server (in fact, this would be a\r\npotential attack vector). Instead, the client only uses the server's time to calculate an offset used only\r\nfor communications with that particular server. The protocol rewards clients with synchronized clocks by reducing\r\nthe number of round trips required to authenticate the first request.\r\n\r\n\r\n## Usage Example\r\n\r\nServer code:\r\n\r\n```javascript\r\nvar Http = require('http');\r\nvar Hawk = require('hawk');\r\n\r\n\r\n// Credentials lookup function\r\n\r\nvar credentialsFunc = function (id, callback) {\r\n\r\n    var credentials = {\r\n        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\r\n        algorithm: 'sha256',\r\n        user: 'Steve'\r\n    };\r\n\r\n    return callback(null, credentials);\r\n};\r\n\r\n// Create HTTP server\r\n\r\nvar handler = function (req, res) {\r\n\r\n    // Authenticate incoming request\r\n\r\n    Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {\r\n\r\n        // Prepare response\r\n\r\n        var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');\r\n        var headers = { 'Content-Type': 'text/plain' };\r\n\r\n        // Generate Server-Authorization response header\r\n\r\n        var header = Hawk.server.header(credentials, artifacts, { payload: payload, contentType: headers['Content-Type'] });\r\n        headers['Server-Authorization'] = header;\r\n\r\n        // Send the response back\r\n\r\n        res.writeHead(!err ? 200 : 401, headers);\r\n        res.end(payload);\r\n    });\r\n};\r\n\r\n// Start server\r\n\r\nHttp.createServer(handler).listen(8000, 'example.com');\r\n```\r\n\r\nClient code:\r\n\r\n```javascript\r\nvar Request = require('request');\r\nvar Hawk = require('hawk');\r\n\r\n\r\n// Client credentials\r\n\r\nvar credentials = {\r\n    id: 'dh37fgj492je',\r\n    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\r\n    algorithm: 'sha256'\r\n}\r\n\r\n// Request options\r\n\r\nvar requestOptions = {\r\n    uri: 'http://example.com:8000/resource/1?b=1&a=2',\r\n    method: 'GET',\r\n    headers: {}\r\n};\r\n\r\n// Generate Authorization request header\r\n\r\nvar header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });\r\nrequestOptions.headers.Authorization = header.field;\r\n\r\n// Send authenticated request\r\n\r\nRequest(requestOptions, function (error, response, body) {\r\n\r\n    // Authenticate the server's response\r\n\r\n    var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });\r\n\r\n    // Output results\r\n\r\n    console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));\r\n});\r\n```\r\n\r\n**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local\r\nmachine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method.\r\n\r\n```javascript\r\nHawk.sntp.start();\r\n```\r\n\r\n\r\n## Protocol Example\r\n\r\nThe client attempts to access a protected resource without authentication, sending the following HTTP request to\r\nthe resource server:\r\n\r\n```\r\nGET /resource/1?b=1&a=2 HTTP/1.1\r\nHost: example.com:8000\r\n```\r\n\r\nThe resource server returns an authentication challenge.\r\n\r\n```\r\nHTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Hawk\r\n```\r\n\r\nThe client has previously obtained a set of **Hawk** credentials for accessing resources on the \"http://example.com/\"\r\nserver. The **Hawk** credentials issued to the client include the following attributes:\r\n\r\n* Key identifier: dh37fgj492je\r\n* Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn\r\n* Algorithm: sha256\r\n\r\nThe client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1,\r\n1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline\r\ncharacter):\r\n\r\n```\r\nhawk.1.header\r\n1353832234\r\nj4h3g2\r\nGET\r\n/resource?a=1&b=2\r\nexample.com\r\n8000\r\n\r\nsome-app-ext-data\r\n\r\n```\r\n\r\nThe request MAC is calculated using HMAC with the specified hash algorithm \"sha256\" and the key over the normalized request string.\r\nThe result is base64-encoded to produce the request MAC:\r\n\r\n```\r\n6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=\r\n```\r\n\r\nThe client includes the **Hawk** key identifier, timestamp, nonce, application specific data, and request MAC with the request using\r\nthe HTTP `Authorization` request header field:\r\n\r\n```\r\nGET /resource/1?b=1&a=2 HTTP/1.1\r\nHost: example.com:8000\r\nAuthorization: Hawk id=\"dh37fgj492je\", ts=\"1353832234\", nonce=\"j4h3g2\", ext=\"some-app-ext-data\", mac=\"6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=\"\r\n```\r\n\r\nThe server validates the request by calculating the request MAC again based on the request received and verifies the validity\r\nand scope of the **Hawk** credentials. If valid, the server responds with the requested resource.\r\n\r\n\r\n### Payload Validation\r\n\r\n**Hawk** provides optional payload validation. When generating the authentication header, the client calculates a payload hash\r\nusing the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character):\r\n* `hawk.1.payload`\r\n* the content-type in lowercase, without any parameters (e.g. `application/json`)\r\n* the request payload prior to any content encoding (the exact representation requirements should be specified by the server for payloads other than simple single-part ascii to ensure interoperability)\r\n\r\nFor example:\r\n\r\n* Payload: `Thank you for flying Hawk`\r\n* Content Type: `text/plain`\r\n* Hash (sha256): `Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=`\r\n\r\nResults in the following input to the payload hash function (newline terminated values):\r\n\r\n```\r\nhawk.1.payload\r\ntext/plain\r\nThank you for flying Hawk\r\n\r\n```\r\n\r\nWhich produces the following hash value:\r\n\r\n```\r\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\r\n```\r\n\r\nThe client constructs the normalized request string (newline terminated values):\r\n\r\n```\r\nhawk.1.header\r\n1353832234\r\nj4h3g2\r\nPOST\r\n/resource?a=1&b=2\r\nexample.com\r\n8000\r\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\r\nsome-app-ext-data\r\n\r\n```\r\n\r\nThen calculates the request MAC and includes the **Hawk** key identifier, timestamp, nonce, payload hash, application specific data,\r\nand request MAC, with the request using the HTTP `Authorization` request header field:\r\n\r\n```\r\nPOST /resource/1 HTTP/1.1\r\nHost: example.com:8000\r\nAuthorization: Hawk id=\"dh37fgj492je\", ts=\"1353832234\", nonce=\"j4h3g2\", hash=\"Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\", ext=\"some-app-ext-data\", mac=\"aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw=\"\r\n```\r\n\r\nIt is up to the server if and when it validates the payload for any given request, based solely on it's security policy\r\nand the nature of the data included.\r\n\r\nIf the payload is available at the time of authentication, the server uses the hash value provided by the client to construct\r\nthe normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value\r\nwith the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash.\r\n\r\nHowever, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed\r\nat a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value\r\nprovided by the client after validating the MAC.\r\n\r\nIt is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value\r\nincluded in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided\r\nby the client, the payload may be modified by an attacker.\r\n\r\n\r\n## Response Payload Validation\r\n\r\n**Hawk** provides partial response payload validation. The server includes the `Server-Authorization` response header which enables the\r\nclient to authenticate the response and ensure it is talking to the right server. **Hawk** defines the HTTP `Server-Authorization` header\r\nas a response header using the exact same syntax as the `Authorization` request header field.\r\n\r\nThe header is contructed using the same process as the client's request header. The server uses the same credentials and other\r\nartifacts provided by the client to constructs the normalized request string. The `ext` and `hash` values are replaced with\r\nnew values based on the server response. The rest as identical to those used by the client.\r\n\r\nThe result MAC digest is included with the optional `hash` and `ext` values:\r\n\r\n```\r\nServer-Authorization: Hawk mac=\"XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"\r\n```\r\n\r\n\r\n## Browser Support and Considerations\r\n\r\nA browser script is provided for including using a `<script>` tag in [lib/browser.js](/lib/browser.js).\r\n\r\n**Hawk** relies on the _Server-Authorization_ and _WWW-Authenticate_ headers in its response to communicate with the client.\r\nTherefore, in case of CORS requests, it is important to consider sending _Access-Control-Expose-Headers_ with the value\r\n_\"WWW-Authenticate, Server-Authorization\"_ on each response from your server. As explained in the\r\n[specifications](http://www.w3.org/TR/cors/#access-control-expose-headers-response-header), it will indicate that these headers\r\ncan safely be accessed by the client (using getResponseHeader() on the XmlHttpRequest object). Otherwise you will be met with a\r\n[\"simple response header\"](http://www.w3.org/TR/cors/#simple-response-header) which excludes these fields and would prevent the\r\nHawk client from authenticating the requests.You can read more about the why and how in this\r\n[article](http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server)\r\n\r\n\r\n# Single URI Authorization\r\n\r\nThere are cases in which limited and short-term access to a protected resource is granted to a third party which does not\r\nhave access to the shared credentials. For example, displaying a protected image on a web page accessed by anyone. **Hawk**\r\nprovides limited support for such URIs in the form of a _bewit_ - a URI query parameter appended to the request URI which contains\r\nthe necessary credentials to authenticate the request.\r\n\r\nBecause of the significant security risks involved in issuing such access, bewit usage is purposely limited only to GET requests\r\nand for a finite period of time. Both the client and server can issue bewit credentials, however, the server should not use the same\r\ncredentials as the client to maintain clear traceability as to who issued which credentials.\r\n\r\nIn order to simplify implementation, bewit credentials do not support single-use policy and can be replayed multiple times within\r\nthe granted access timeframe. \r\n\r\n\r\n## Bewit Usage Example\r\n\r\nServer code:\r\n\r\n```javascript\r\nvar Http = require('http');\r\nvar Hawk = require('hawk');\r\n\r\n\r\n// Credentials lookup function\r\n\r\nvar credentialsFunc = function (id, callback) {\r\n\r\n    var credentials = {\r\n        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\r\n        algorithm: 'sha256'\r\n    };\r\n\r\n    return callback(null, credentials);\r\n};\r\n\r\n// Create HTTP server\r\n\r\nvar handler = function (req, res) {\r\n\r\n    Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {\r\n\r\n        res.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' });\r\n        res.end(!err ? 'Access granted' : 'Shoosh!');\r\n    });\r\n};\r\n\r\nHttp.createServer(handler).listen(8000, 'example.com');\r\n```\r\n\r\nBewit code generation:\r\n\r\n```javascript\r\nvar Request = require('request');\r\nvar Hawk = require('hawk');\r\n\r\n\r\n// Client credentials\r\n\r\nvar credentials = {\r\n    id: 'dh37fgj492je',\r\n    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\r\n    algorithm: 'sha256'\r\n}\r\n\r\n// Generate bewit\r\n\r\nvar duration = 60 * 5;      // 5 Minutes\r\nvar bewit = Hawk.uri.getBewit('http://example.com:8080/resource/1?b=1&a=2', { credentials: credentials, ttlSec: duration, ext: 'some-app-data' });\r\nvar uri = 'http://example.com:8000/resource/1?b=1&a=2' + '&bewit=' + bewit;\r\n```\r\n\r\n\r\n# Security Considerations\r\n\r\nThe greatest sources of security risks are usually found not in **Hawk** but in the policies and procedures surrounding its use.\r\nImplementers are strongly encouraged to assess how this module addresses their security requirements. This section includes\r\nan incomplete list of security considerations that must be reviewed and understood before deploying **Hawk** on the server.\r\nMany of the protections provided in **Hawk** depends on whether and how they are used.\r\n\r\n### MAC Keys Transmission\r\n\r\n**Hawk** does not provide any mechanism for obtaining or transmitting the set of shared credentials required. Any mechanism used\r\nto obtain **Hawk** credentials must ensure that these transmissions are protected using transport-layer mechanisms such as TLS.\r\n\r\n### Confidentiality of Requests\r\n\r\nWhile **Hawk** provides a mechanism for verifying the integrity of HTTP requests, it provides no guarantee of request\r\nconfidentiality. Unless other precautions are taken, eavesdroppers will have full access to the request content. Servers should\r\ncarefully consider the types of data likely to be sent as part of such requests, and employ transport-layer security mechanisms\r\nto protect sensitive resources.\r\n\r\n### Spoofing by Counterfeit Servers\r\n\r\n**Hawk** provides limited verification of the server authenticity. When receiving a response back from the server, the server\r\nmay choose to include a response `Server-Authorization` header which the client can use to verify the response. However, it is up to\r\nthe server to determine when such measure is included, to up to the client to enforce that policy.\r\n\r\nA hostile party could take advantage of this by intercepting the client's requests and returning misleading or otherwise\r\nincorrect responses. Service providers should consider such attacks when developing services using this protocol, and should\r\nrequire transport-layer security for any requests where the authenticity of the resource server or of server responses is an issue.\r\n\r\n### Plaintext Storage of Credentials\r\n\r\nThe **Hawk** key functions the same way passwords do in traditional authentication systems. In order to compute the request MAC,\r\nthe server must have access to the key in plaintext form. This is in contrast, for example, to modern operating systems, which\r\nstore only a one-way hash of user credentials.\r\n\r\nIf an attacker were to gain access to these keys - or worse, to the server's database of all such keys - he or she would be able\r\nto perform any action on behalf of any resource owner. Accordingly, it is critical that servers protect these keys from unauthorized\r\naccess.\r\n\r\n### Entropy of Keys\r\n\r\nUnless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and request\r\nMAC values, and will thus be able to mount offline brute-force attacks to recover the key used. Servers should be careful to\r\nassign keys which are long enough, and random enough, to resist such attacks for at least the length of time that the **Hawk**\r\ncredentials are valid.\r\n\r\nFor example, if the credentials are valid for two weeks, servers should ensure that it is not possible to mount a brute force\r\nattack that recovers the key in less than two weeks. Of course, servers are urged to err on the side of caution, and use the\r\nlongest key reasonable.\r\n\r\nIt is equally important that the pseudo-random number generator (PRNG) used to generate these keys be of sufficiently high\r\nquality. Many PRNG implementations generate number sequences that may appear to be random, but which nevertheless exhibit\r\npatterns or other weaknesses which make cryptanalysis or brute force attacks easier. Implementers should be careful to use\r\ncryptographically secure PRNGs to avoid these problems.\r\n\r\n### Coverage Limitations\r\n\r\nThe request MAC only covers the HTTP `Host` header and optionally the `Content-Type` header. It does not cover any other headers\r\nwhich can often affect how the request body is interpreted by the server. If the server behavior is influenced by the presence\r\nor value of such headers, an attacker can manipulate the request headers without being detected. Implementers should use the\r\n`ext` feature to pass application-specific information via the `Authorization` header which is protected by the request MAC.\r\n\r\nThe response authentication, when performed, only covers the response payload, content-type, and the request information \r\nprovided by the client in it's request (method, resource, timestamp, nonce, etc.). It does not cover the HTTP status code or\r\nany other response header field (e.g. Location) which can affect the client's behaviour.\r\n\r\n### Future Time Manipulation\r\n\r\nThe protocol relies on a clock sync between the client and server. To accomplish this, the server informs the client of its\r\ncurrent time when an invalid timestamp is received.\r\n\r\nIf an attacker is able to manipulate this information and cause the client to use an incorrect time, it would be able to cause\r\nthe client to generate authenticated requests using time in the future. Such requests will fail when sent by the client, and will\r\nnot likely leave a trace on the server (given the common implementation of nonce, if at all enforced). The attacker will then\r\nbe able to replay the request at the correct time without detection.\r\n\r\nThe client must only use the time information provided by the server if:\r\n* it was delivered over a TLS connection and the server identity has been verified, or\r\n* the `tsm` MAC digest calculated using the same client credentials over the timestamp has been verified.\r\n\r\n### Client Clock Poisoning\r\n\r\nWhen receiving a request with a bad timestamp, the server provides the client with its current time. The client must never use\r\nthe time received from the server to adjust its own clock, and must only use it to calculate an offset for communicating with\r\nthat particular server.\r\n\r\n### Bewit Limitations\r\n\r\nSpecial care must be taken when issuing bewit credentials to third parties. Bewit credentials are valid until expiration and cannot\r\nbe revoked or limited without using other means. Whatever resource they grant access to will be completely exposed to anyone with\r\naccess to the bewit credentials which act as bearer credentials for that particular resource. While bewit usage is limited to GET\r\nrequests only and therefore cannot be used to perform transactions or change server state, it can still be used to expose private\r\nand sensitive information.\r\n\r\n\r\n# Frequently Asked Questions\r\n\r\n### Where is the protocol specification?\r\n\r\nIf you are looking for some prose explaining how all this works, **this is it**. **Hawk** is being developed as an open source\r\nproject instead of a standard. In other words, the [code](/hueniverse/hawk/tree/master/lib) is the specification. Not sure about\r\nsomething? Open an issue!\r\n\r\n### Is it done?\r\n\r\nAt if version 0.10.0, **Hawk** is feature-complete. However, until this module reaches version 1.0.0 it is considered experimental\r\nand is likely to change. This also means your feedback and contribution are very welcome. Feel free to open issues with questions\r\nand suggestions.\r\n\r\n### Where can I find **Hawk** implementations in other languages?\r\n\r\n**Hawk**'s only reference implementation is provided in JavaScript as a node.js module. However, others are actively porting it to other\r\nplatforms. There is already a [PHP](https://github.com/alexbilbie/PHP-Hawk),\r\n[.NET](https://github.com/pcibraro/hawknet), and [JAVA](https://github.com/wealdtech/hawk) libraries available. The full list\r\nis maintained [here](https://github.com/hueniverse/hawk/issues?labels=port). Please add an issue if you are working on another\r\nport. A cross-platform test-suite is in the works.\r\n\r\n### Why isn't the algorithm part of the challenge or dynamically negotiated?\r\n\r\nThe algorithm used is closely related to the key issued as different algorithms require different key sizes (and other\r\nrequirements). While some keys can be used for multiple algorithm, the protocol is designed to closely bind the key and algorithm\r\ntogether as part of the issued credentials.\r\n\r\n### Why is Host and Content-Type the only headers covered by the request MAC?\r\n\r\nIt is really hard to include other headers. Headers can be changed by proxies and other intermediaries and there is no\r\nwell-established way to normalize them. Many platforms change the case of header field names and values. The only\r\nstraight-forward solution is to include the headers in some blob (say, base64 encoded JSON) and include that with the request,\r\nan approach taken by JWT and other such formats. However, that design violates the HTTP header boundaries, repeats information,\r\nand introduces other security issues because firewalls will not be aware of these \"hidden\" headers. In addition, any information\r\nrepeated must be compared to the duplicated information in the header and therefore only moves the problem elsewhere.\r\n\r\n### Why not just use HTTP Digest?\r\n\r\nDigest requires pre-negotiation to establish a nonce. This means you can't just make a request - you must first send\r\na protocol handshake to the server. This pattern has become unacceptable for most web services, especially mobile\r\nwhere extra round-trip are costly.\r\n\r\n### Why bother with all this nonce and timestamp business?\r\n\r\n**Hawk** is an attempt to find a reasonable, practical compromise between security and usability. OAuth 1.0 got timestamp\r\nand nonces halfway right but failed when it came to scalability and consistent developer experience. **Hawk** addresses\r\nit by requiring the client to sync its clock, but provides it with tools to accomplish it.\r\n\r\nIn general, replay protection is a matter of application-specific threat model. It is less of an issue on a TLS-protected\r\nsystem where the clients are implemented using best practices and are under the control of the server. Instead of dropping\r\nreplay protection, **Hawk** offers a required time window and an optional nonce verification. Together, it provides developers\r\nwith the ability to decide how to enforce their security policy without impacting the client's implementation.\r\n\r\n### What are `app` and `dlg` in the authorization header and normalized mac string?\r\n\r\nThe original motivation for **Hawk** was to replace the OAuth 1.0 use cases. This included both a simple client-server mode which\r\nthis module is specifically designed for, and a delegated access mode which is being developed separately in\r\n[Oz](https://github.com/hueniverse/oz). In addition to the **Hawk** use cases, Oz requires another attribute: the application id `app`.\r\nThis provides binding between the credentials and the application in a way that prevents an attacker from tricking an application\r\nto use credentials issued to someone else. It also has an optional 'delegated-by' attribute `dlg` which is the application id of the\r\napplication the credentials were directly issued to. The goal of these two additions is to allow Oz to utilize **Hawk** directly,\r\nbut with the additional security of delegated credentials.\r\n\r\n### What is the purpose of the static strings used in each normalized MAC input?\r\n\r\nWhen calculating a hash or MAC, a static prefix (tag) is added. The prefix is used to prevent MAC values from being\r\nused or reused for a purpose other than what they were created for (i.e. prevents switching MAC values between a request,\r\nresponse, and a bewit use cases). It also protects against expliots created after a potential change in how the protocol\r\ncreates the normalized string. For example, if a future version would switch the order of nonce and timestamp, it\r\ncan create an exploit opportunity for cases where the nonce is similar in format to a timestamp.\r\n\r\n### Does **Hawk** have anything to do with OAuth?\r\n\r\nShort answer: no.\r\n\r\n**Hawk** was originally proposed as the OAuth MAC Token specification. However, the OAuth working group in its consistent\r\nincompetence failed to produce a final, usable solution to address one of the most popular use cases of OAuth 1.0 - using it\r\nto authenticate simple client-server transactions (i.e. two-legged). As you can guess, the OAuth working group is still hard\r\nat work to produce more garbage.\r\n\r\n**Hawk** provides a simple HTTP authentication scheme for making client-server requests. It does not address the OAuth use case\r\nof delegating access to a third party. If you are looking for an OAuth alternative, check out [Oz](https://github.com/hueniverse/oz).\r\n\r\n\r\n# Acknowledgements\r\n\r\n**Hawk** is a derivative work of the [HTTP MAC Authentication Scheme](http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05) proposal\r\nco-authored by Ben Adida, Adam Barth, and Eran Hammer, which in turn was based on the OAuth 1.0 community specification.\r\n\r\nSpecial thanks to Ben Laurie for his always insightful feedback and advice.\r\n\r\nThe **Hawk** logo was created by [Chris Carrasco](http://chriscarrasco.com).\r\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/hueniverse/hawk/issues"
+  },
+  "homepage": "https://github.com/hueniverse/hawk",
+  "_id": "hawk@0.13.1",
+  "_from": "hawk@~0.13.0"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/test/browser.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/test/browser.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/test/browser.js	(revision 484)
@@ -0,0 +1,723 @@
+// Load modules
+
+var Lab = require('lab');
+var Hawk = require('../lib');
+var Browser = require('../lib/browser');
+var LocalStorage = require('localStorage');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Browser', function () {
+
+    var credentialsFunc = function (id, callback) {
+
+        var credentials = {
+            id: id,
+            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+            algorithm: (id === '1' ? 'sha1' : 'sha256'),
+            user: 'steve'
+        };
+
+        return callback(null, credentials);
+    };
+
+    it('should generate a header then successfully parse it (configuration)', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
+            expect(req.authorization).to.exist;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (node request)', function (done) {
+
+        var req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        var payload = 'some not so random text';
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
+            req.headers.authorization = reqHeader.field;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain'
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
+                expect(res.headers['server-authorization']).to.exist;
+
+                expect(Browser.client.authenticate(res, credentials, artifacts, { payload: 'some reply' })).to.equal(true);
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (no server header options)', function (done) {
+
+        var req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        var payload = 'some not so random text';
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
+            req.headers.authorization = reqHeader.field;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain'
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts);
+                expect(res.headers['server-authorization']).to.exist;
+
+                expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (no server header)', function (done) {
+
+        var req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        var payload = 'some not so random text';
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
+            req.headers.authorization = reqHeader.field;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain'
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
+                done();
+            });
+        });
+    });
+
+    it('should generate a header with stale ts and successfully authenticate on second call', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            Browser.utils.setNtpOffset(60 * 60 * 1000);
+            var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' });
+            req.authorization = header.field;
+            expect(req.authorization).to.exist;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('Stale timestamp');
+
+                var res = {
+                    headers: {
+                        'www-authenticate': err.response.headers['WWW-Authenticate']
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000);
+                expect(Browser.client.authenticate(res, credentials, header.artifacts)).to.equal(true);
+                expect(Browser.utils.getNtpOffset()).to.equal(0);
+
+                req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
+                expect(req.authorization).to.exist;
+
+                Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                    expect(err).to.not.exist;
+                    expect(credentials.user).to.equal('steve');
+                    expect(artifacts.ext).to.equal('some-app-data');
+                    done();
+                });
+            });
+        });
+    });
+
+    it('should generate a header with stale ts and successfully authenticate on second call (manual localStorage)', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+            Browser.utils.setStorage(LocalStorage)
+
+            Browser.utils.setNtpOffset(60 * 60 * 1000);
+            var header = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' });
+            req.authorization = header.field;
+            expect(req.authorization).to.exist;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('Stale timestamp');
+
+                var res = {
+                    headers: {
+                        'www-authenticate': err.response.headers['WWW-Authenticate']
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                expect(parseInt(LocalStorage.getItem('hawk_ntp_offset'))).to.equal(60 * 60 * 1000);
+                expect(Browser.utils.getNtpOffset()).to.equal(60 * 60 * 1000);
+                expect(Browser.client.authenticate(res, credentials, header.artifacts)).to.equal(true);
+                expect(Browser.utils.getNtpOffset()).to.equal(0);
+                expect(parseInt(LocalStorage.getItem('hawk_ntp_offset'))).to.equal(0);
+
+                req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
+                expect(req.authorization).to.exist;
+
+                Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                    expect(err).to.not.exist;
+                    expect(credentials.user).to.equal('steve');
+                    expect(artifacts.ext).to.equal('some-app-data');
+                    done();
+                });
+            });
+        });
+    });
+
+    it('should generate a header then fails to parse it (missing server header hash)', function (done) {
+
+        var req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        var payload = 'some not so random text';
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            var reqHeader = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
+            req.headers.authorization = reqHeader.field;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain'
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts);
+                expect(res.headers['server-authorization']).to.exist;
+
+                expect(Browser.client.authenticate(res, credentials, artifacts, { payload: 'some reply' })).to.equal(false);
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (with hash)', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it then validate payload', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(Hawk.server.authenticatePayload('hola!', credentials, artifacts)).to.be.true;
+                expect(Hawk.server.authenticatePayload('hello!', credentials, artifacts)).to.be.false;
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (app)', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', app: 'asd23ased' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(artifacts.app).to.equal('asd23ased');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (app, dlg)', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', app: 'asd23ased', dlg: '23434szr3q4d' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(artifacts.app).to.equal('asd23ased');
+                expect(artifacts.dlg).to.equal('23434szr3q4d');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then fail authentication due to bad hash', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, { payload: 'byebye!' }, function (err, credentials, artifacts) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Bad payload hash');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header for one resource then fail to authenticate another', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Browser.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
+            req.url = '/something/else';
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.exist;
+                expect(credentials).to.exist;
+                done();
+            });
+        });
+    });
+
+    describe('client', function () {
+
+        describe('#header', function () {
+
+            it('should return a valid authorization header (sha1)', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: '2983d45yun89q',
+                    algorithm: 'sha1'
+                };
+
+                var header = Browser.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about' }).field;
+                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="');
+                done();
+            });
+
+            it('should return a valid authorization header (sha256)', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: '2983d45yun89q',
+                    algorithm: 'sha256'
+                };
+
+                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
+                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
+                done();
+            });
+
+            it('should return a valid authorization header (no ext)', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: '2983d45yun89q',
+                    algorithm: 'sha256'
+                };
+
+                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
+                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
+                done();
+            });
+
+            it('should return an empty authorization header on missing options', function (done) {
+
+                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST').field;
+                expect(header).to.equal('');
+                done();
+            });
+
+            it('should return an empty authorization header on invalid credentials', function (done) {
+
+                var credentials = {
+                    key: '2983d45yun89q',
+                    algorithm: 'sha256'
+                };
+
+                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 }).field;
+                expect(header).to.equal('');
+                done();
+            });
+
+            it('should return an empty authorization header on invalid algorithm', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: '2983d45yun89q',
+                    algorithm: 'hmac-sha-0'
+                };
+
+                var header = Browser.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 }).field;
+                expect(header).to.equal('');
+                done();
+            });
+        });
+
+        describe('#authenticate', function () {
+
+            it('should return false on invalid header', function (done) {
+
+                var res = {
+                    headers: {
+                        'server-authorization': 'Hawk mac="abc", bad="xyz"'
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                expect(Browser.client.authenticate(res, {})).to.equal(false);
+                done();
+            });
+
+            it('should return false on invalid mac', function (done) {
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain',
+                        'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                var artifacts = {
+                    method: 'POST',
+                    host: 'example.com',
+                    port: '8080',
+                    resource: '/resource/4?filter=a',
+                    ts: '1362336900',
+                    nonce: 'eb5S_L',
+                    hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                    ext: 'some-app-data',
+                    app: undefined,
+                    dlg: undefined,
+                    mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
+                    id: '123456'
+                };
+
+                var credentials = {
+                    id: '123456',
+                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                    algorithm: 'sha256',
+                    user: 'steve'
+                };
+
+                expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(false);
+                done();
+            });
+
+            it('should return true on ignoring hash', function (done) {
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain',
+                        'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                var artifacts = {
+                    method: 'POST',
+                    host: 'example.com',
+                    port: '8080',
+                    resource: '/resource/4?filter=a',
+                    ts: '1362336900',
+                    nonce: 'eb5S_L',
+                    hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                    ext: 'some-app-data',
+                    app: undefined,
+                    dlg: undefined,
+                    mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
+                    id: '123456'
+                };
+
+                var credentials = {
+                    id: '123456',
+                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                    algorithm: 'sha256',
+                    user: 'steve'
+                };
+
+                expect(Browser.client.authenticate(res, credentials, artifacts)).to.equal(true);
+                done();
+            });
+
+            it('should fail on invalid WWW-Authenticate header format', function (done) {
+
+                var res = {
+                    headers: {
+                        'www-authenticate': 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"'
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                expect(Browser.client.authenticate(res, {})).to.equal(false);
+                done();
+            });
+
+            it('should fail on invalid WWW-Authenticate header format', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                    algorithm: 'sha256',
+                    user: 'steve'
+                };
+
+                var res = {
+                    headers: {
+                        'www-authenticate': 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"'
+                    },
+                    getResponseHeader: function (header) {
+
+                        return res.headers[header.toLowerCase()];
+                    }
+                };
+
+                expect(Browser.client.authenticate(res, credentials)).to.equal(false);
+                done();
+            });
+        });
+    });
+
+    describe('#parseAuthorizationHeader', function (done) {
+
+        it('returns null on missing header', function (done) {
+
+            expect(Browser.utils.parseAuthorizationHeader()).to.equal(null);
+            done();
+        });
+
+        it('returns null on bad header syntax (structure)', function (done) {
+
+            expect(Browser.utils.parseAuthorizationHeader('Hawk')).to.equal(null);
+            done();
+        });
+
+        it('returns null on bad header syntax (parts)', function (done) {
+
+            expect(Browser.utils.parseAuthorizationHeader(' ')).to.equal(null);
+            done();
+        });
+
+        it('returns null on bad scheme name', function (done) {
+
+            expect(Browser.utils.parseAuthorizationHeader('Basic asdasd')).to.equal(null);
+            done();
+        });
+
+        it('returns null on bad attribute value', function (done) {
+
+            expect(Browser.utils.parseAuthorizationHeader('Hawk test="\t"', ['test'])).to.equal(null);
+            done();
+        });
+
+        it('returns null on duplicated attribute', function (done) {
+
+            expect(Browser.utils.parseAuthorizationHeader('Hawk test="a", test="b"', ['test'])).to.equal(null);
+            done();
+        });
+    });
+});
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/test/client.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/test/client.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/test/client.js	(revision 484)
@@ -0,0 +1,206 @@
+// Load modules
+
+var Url = require('url');
+var Lab = require('lab');
+var Hawk = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hawk', function () {
+
+    describe('client', function () {
+
+        describe('#header', function () {
+
+            it('should return a valid authorization header (sha1)', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: '2983d45yun89q',
+                    algorithm: 'sha1'
+                };
+
+                var header = Hawk.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about' }).field;
+                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="');
+                done();
+            });
+
+            it('should return a valid authorization header (sha256)', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: '2983d45yun89q',
+                    algorithm: 'sha256'
+                };
+
+                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
+                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
+                done();
+            });
+
+            it('should return a valid authorization header (no ext)', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: '2983d45yun89q',
+                    algorithm: 'sha256'
+                };
+
+                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
+                expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
+                done();
+            });
+
+            it('should return an empty authorization header on missing options', function (done) {
+
+                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST').field;
+                expect(header).to.equal('');
+                done();
+            });
+
+            it('should return an empty authorization header on invalid credentials', function (done) {
+
+                var credentials = {
+                    key: '2983d45yun89q',
+                    algorithm: 'sha256'
+                };
+
+                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 }).field;
+                expect(header).to.equal('');
+                done();
+            });
+
+            it('should return an empty authorization header on invalid algorithm', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: '2983d45yun89q',
+                    algorithm: 'hmac-sha-0'
+                };
+
+                var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 }).field;
+                expect(header).to.equal('');
+                done();
+            });
+        });
+
+        describe('#authenticate', function () {
+
+            it('should return false on invalid header', function (done) {
+
+                var res = {
+                    headers: {
+                        'server-authorization': 'Hawk mac="abc", bad="xyz"'
+                    }
+                };
+
+                expect(Hawk.client.authenticate(res, {})).to.equal(false);
+                done();
+            });
+
+            it('should return false on invalid mac', function (done) {
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain',
+                        'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
+                    }
+                };
+
+                var artifacts = {
+                    method: 'POST',
+                    host: 'example.com',
+                    port: '8080',
+                    resource: '/resource/4?filter=a',
+                    ts: '1362336900',
+                    nonce: 'eb5S_L',
+                    hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                    ext: 'some-app-data',
+                    app: undefined,
+                    dlg: undefined,
+                    mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
+                    id: '123456'
+                };
+
+                var credentials = {
+                    id: '123456',
+                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                    algorithm: 'sha256',
+                    user: 'steve'
+                };
+
+                expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(false);
+                done();
+            });
+
+            it('should return true on ignoring hash', function (done) {
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain',
+                        'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
+                    }
+                };
+
+                var artifacts = {
+                    method: 'POST',
+                    host: 'example.com',
+                    port: '8080',
+                    resource: '/resource/4?filter=a',
+                    ts: '1362336900',
+                    nonce: 'eb5S_L',
+                    hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                    ext: 'some-app-data',
+                    app: undefined,
+                    dlg: undefined,
+                    mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
+                    id: '123456'
+                };
+
+                var credentials = {
+                    id: '123456',
+                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                    algorithm: 'sha256',
+                    user: 'steve'
+                };
+
+                expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true);
+                done();
+            });
+
+            it('should fail on invalid WWW-Authenticate header format', function (done) {
+
+                var header = 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"';
+                expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(false);
+                done();
+            });
+
+            it('should fail on invalid WWW-Authenticate header format', function (done) {
+
+                var credentials = {
+                    id: '123456',
+                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                    algorithm: 'sha256',
+                    user: 'steve'
+                };
+
+                var header = 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"';
+                expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, credentials)).to.equal(false);
+                done();
+            });
+        });
+    });
+});
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/test/crypto.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/test/crypto.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/test/crypto.js	(revision 484)
@@ -0,0 +1,86 @@
+// Load modules
+
+var Lab = require('lab');
+var Hawk = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hawk', function () {
+
+    describe('Crypto', function () {
+
+        describe('#generateNormalizedString', function () {
+
+            it('should return a valid normalized string', function (done) {
+
+                expect(Hawk.crypto.generateNormalizedString('header', {
+                    credentials: {
+                        key: 'dasdfasdf',
+                        algorithm: 'sha256'
+                    },
+                    ts: 1357747017,
+                    nonce: 'k3k4j5',
+                    method: 'GET',
+                    resource: '/resource/something',
+                    host: 'example.com',
+                    port: 8080
+                })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\n\n');
+
+                done();
+            });
+
+            it('should return a valid normalized string (ext)', function (done) {
+
+                expect(Hawk.crypto.generateNormalizedString('header', {
+                    credentials: {
+                        key: 'dasdfasdf',
+                        algorithm: 'sha256'
+                    },
+                    ts: 1357747017,
+                    nonce: 'k3k4j5',
+                    method: 'GET',
+                    resource: '/resource/something',
+                    host: 'example.com',
+                    port: 8080,
+                    ext: 'this is some app data'
+                })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\nthis is some app data\n');
+
+                done();
+            });
+
+            it('should return a valid normalized string (payload + ext)', function (done) {
+
+                expect(Hawk.crypto.generateNormalizedString('header', {
+                    credentials: {
+                        key: 'dasdfasdf',
+                        algorithm: 'sha256'
+                    },
+                    ts: 1357747017,
+                    nonce: 'k3k4j5',
+                    method: 'GET',
+                    resource: '/resource/something',
+                    host: 'example.com',
+                    port: 8080,
+                    hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
+                    ext: 'this is some app data'
+                })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\nU4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=\nthis is some app data\n');
+
+                done();
+            });
+        });
+    });
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/test/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/test/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/test/index.js	(revision 484)
@@ -0,0 +1,316 @@
+// Load modules
+
+var Url = require('url');
+var Lab = require('lab');
+var Hawk = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hawk', function () {
+
+    var credentialsFunc = function (id, callback) {
+
+        var credentials = {
+            id: id,
+            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+            algorithm: (id === '1' ? 'sha1' : 'sha256'),
+            user: 'steve'
+        };
+
+        return callback(null, credentials);
+    };
+
+    it('should generate a header then successfully parse it (configuration)', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Hawk.client.header(Url.parse('http://example.com:8080/resource/4?filter=a'), req.method, { credentials: credentials, ext: 'some-app-data' }).field;
+            expect(req.authorization).to.exist;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (node request)', function (done) {
+
+        var req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        var payload = 'some not so random text';
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
+            req.headers.authorization = reqHeader.field;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain'
+                    }
+                };
+
+                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
+                expect(res.headers['server-authorization']).to.exist;
+
+                expect(Hawk.client.authenticate(res, credentials, artifacts, { payload: 'some reply' })).to.equal(true);
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (no server header options)', function (done) {
+
+        var req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        var payload = 'some not so random text';
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
+            req.headers.authorization = reqHeader.field;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain'
+                    }
+                };
+
+                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts);
+                expect(res.headers['server-authorization']).to.exist;
+
+                expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true);
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then fails to parse it (missing server header hash)', function (done) {
+
+        var req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        var payload = 'some not so random text';
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
+            req.headers.authorization = reqHeader.field;
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(Hawk.server.authenticatePayload(payload, credentials, artifacts, req.headers['content-type'])).to.equal(true);
+
+                var res = {
+                    headers: {
+                        'content-type': 'text/plain'
+                    }
+                };
+
+                res.headers['server-authorization'] = Hawk.server.header(credentials, artifacts);
+                expect(res.headers['server-authorization']).to.exist;
+
+                expect(Hawk.client.authenticate(res, credentials, artifacts, { payload: 'some reply' })).to.equal(false);
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (with hash)', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it then validate payload', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(Hawk.server.authenticatePayload('hola!', credentials, artifacts)).to.be.true;
+                expect(Hawk.server.authenticatePayload('hello!', credentials, artifacts)).to.be.false;
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (app)', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', app: 'asd23ased' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(artifacts.app).to.equal('asd23ased');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then successfully parse it (app, dlg)', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data', app: 'asd23ased', dlg: '23434szr3q4d' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(artifacts.ext).to.equal('some-app-data');
+                expect(artifacts.app).to.equal('asd23ased');
+                expect(artifacts.dlg).to.equal('23434szr3q4d');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header then fail authentication due to bad hash', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, payload: 'hola!', ext: 'some-app-data' }).field;
+            Hawk.server.authenticate(req, credentialsFunc, { payload: 'byebye!' }, function (err, credentials, artifacts) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Bad payload hash');
+                done();
+            });
+        });
+    });
+
+    it('should generate a header for one resource then fail to authenticate another', function (done) {
+
+        var req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        credentialsFunc('123456', function (err, credentials) {
+
+            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials, ext: 'some-app-data' }).field;
+            req.url = '/something/else';
+
+            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                expect(err).to.exist;
+                expect(credentials).to.exist;
+                done();
+            });
+        });
+    });
+});
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/test/readme.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/test/readme.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/test/readme.js	(revision 484)
@@ -0,0 +1,98 @@
+// Load modules
+
+var Lab = require('lab');
+var Hoek = require('hoek');
+var Hawk = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hawk', function () {
+
+    describe('README', function () {
+
+        describe('core', function () {
+
+            var credentials = {
+                id: 'dh37fgj492je',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256'
+            };
+
+            var options = {
+                credentials: credentials,
+                timestamp: 1353832234,
+                nonce: 'j4h3g2',
+                ext: 'some-app-ext-data'
+            };
+
+            it('should generate a header protocol example', function (done) {
+
+                var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', options).field;
+
+                expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="');
+                done();
+            });
+
+            it('should generate a normalized string protocol example', function (done) {
+
+                var normalized = Hawk.crypto.generateNormalizedString('header', {
+                    credentials: credentials,
+                    ts: options.timestamp,
+                    nonce: options.nonce,
+                    method: 'GET',
+                    resource: '/resource?a=1&b=2',
+                    host: 'example.com',
+                    port: 8000,
+                    ext: options.ext
+                });
+
+                expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nGET\n/resource?a=1&b=2\nexample.com\n8000\n\nsome-app-ext-data\n');
+                done();
+            });
+
+            var payloadOptions = Hoek.clone(options);
+            payloadOptions.payload = 'Thank you for flying Hawk';
+            payloadOptions.contentType = 'text/plain';
+
+            it('should generate a header protocol example (with payload)', function (done) {
+
+                var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'POST', payloadOptions).field;
+
+                expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="');
+                done();
+            });
+
+            it('should generate a normalized string protocol example (with payload)', function (done) {
+
+                var normalized = Hawk.crypto.generateNormalizedString('header', {
+                    credentials: credentials,
+                    ts: options.timestamp,
+                    nonce: options.nonce,
+                    method: 'POST',
+                    resource: '/resource?a=1&b=2',
+                    host: 'example.com',
+                    port: 8000,
+                    hash: Hawk.crypto.calculatePayloadHash(payloadOptions.payload, credentials.algorithm, payloadOptions.contentType),
+                    ext: options.ext
+                });
+
+                expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nPOST\n/resource?a=1&b=2\nexample.com\n8000\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\nsome-app-ext-data\n');
+                done();
+            });
+        });
+    });
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/test/server.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/test/server.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/test/server.js	(revision 484)
@@ -0,0 +1,648 @@
+// Load modules
+
+var Url = require('url');
+var Lab = require('lab');
+var Hawk = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hawk', function () {
+
+    describe('server', function () {
+
+        var credentialsFunc = function (id, callback) {
+
+            var credentials = {
+                id: id,
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: (id === '1' ? 'sha1' : 'sha256'),
+                user: 'steve'
+            };
+
+            return callback(null, credentials);
+        };
+
+        describe('#authenticate', function () {
+
+            it('should parse a valid authentication header (sha1)', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"',
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.not.exist;
+                    expect(credentials.user).to.equal('steve');
+                    done();
+                });
+            });
+
+            it('should parse a valid authentication header (sha256)', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/1?b=1&a=2',
+                    host: 'example.com',
+                    port: 8000,
+                    authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"',
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.not.exist;
+                    expect(credentials.user).to.equal('steve');
+                    done();
+                });
+            });
+
+            it('should parse a valid authentication header (POST with payload)', function (done) {
+
+                var req = {
+                    method: 'POST',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123456", ts="1357926341", nonce="1AwuJD", hash="qAiXIVv+yjDATneWxZP2YCTa9aHRgQdnH9b3Wc+o3dg=", ext="some-app-data", mac="UeYcj5UoTVaAWXNvJfLVia7kU3VabxCqrccXP8sUGC4="',
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1357926341000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.not.exist;
+                    expect(credentials.user).to.equal('steve');
+                    done();
+                });
+            });
+
+            it('should fail on missing hash', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/1?b=1&a=2',
+                    host: 'example.com',
+                    port: 8000,
+                    authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"',
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { payload: 'body', localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Missing required payload hash');
+                    done();
+                });
+            });
+
+            it('should fail on a stale timestamp', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123456", ts="1362337299", nonce="UzmxSs", ext="some-app-data", mac="wnNUxchvvryMH2RxckTdZ/gY3ijzvccx4keVvELC61w="',
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Stale timestamp');
+                    var header = err.response.headers['WWW-Authenticate'];
+                    var ts = header.match(/^Hawk ts\=\"(\d+)\"\, tsm\=\"([^\"]+)\"\, error=\"Stale timestamp\"$/);
+                    var now = Hawk.utils.now();
+                    expect(parseInt(ts[1], 10) * 1000).to.be.within(now - 1000, now + 1000);
+
+                    var res = {
+                        headers: {
+                            'www-authenticate': header
+                        }
+                    };
+
+                    expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true);
+                    done();
+                });
+            });
+
+            it('should fail on a replay', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="bXx7a7p1h9QYQNZ8x7QhvDQym8ACgab4m3lVSFn4DBw=", ext="hello"',
+                };
+
+                var memoryCache = {};
+                var options = {
+                    localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(),
+                    nonceFunc: function (nonce, ts, callback) {
+
+                        if (memoryCache[nonce]) {
+                            return callback(new Error());
+                        }
+
+                        memoryCache[nonce] = true;
+                        return callback();
+                    }
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials, artifacts) {
+
+                    expect(err).to.not.exist;
+                    expect(credentials.user).to.equal('steve');
+
+                    Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials, artifacts) {
+
+                        expect(err).to.exist;
+                        expect(err.response.payload.message).to.equal('Invalid nonce');
+                        done();
+                    });
+                });
+            });
+
+            it('should fail on an invalid authentication header: wrong scheme', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Basic asdasdasdasd'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.not.exist;
+                    done();
+                });
+            });
+
+            it('should fail on an invalid authentication header: no scheme', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: '!@#'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Invalid header syntax');
+                    done();
+                });
+            });
+
+            it('should fail on an missing authorization header', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.isMissing).to.equal(true);
+                    done();
+                });
+            });
+
+            it('should fail on an missing host header', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    headers: {
+                        authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                    }
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Invalid Host header');
+                    done();
+                });
+            });
+
+            it('should fail on an missing authorization attribute (id)', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Missing attributes');
+                    done();
+                });
+            });
+
+            it('should fail on an missing authorization attribute (ts)', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Missing attributes');
+                    done();
+                });
+            });
+
+            it('should fail on an missing authorization attribute (nonce)', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", ts="1353788437", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Missing attributes');
+                    done();
+                });
+            });
+
+            it('should fail on an missing authorization attribute (mac)', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", ext="hello"'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Missing attributes');
+                    done();
+                });
+            });
+
+            it('should fail on an unknown authorization attribute', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", x="3", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Unknown attribute: x');
+                    done();
+                });
+            });
+
+            it('should fail on an bad authorization header format', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123\\", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Bad header format');
+                    done();
+                });
+            });
+
+            it('should fail on an bad authorization attribute value', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="\t", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Bad attribute value: id');
+                    done();
+                });
+            });
+
+            it('should fail on an empty authorization attribute value', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Bad attribute value: id');
+                    done();
+                });
+            });
+
+            it('should fail on duplicated authorization attribute key', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", id="456", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Duplicate attribute: id');
+                    done();
+                });
+            });
+
+            it('should fail on an invalid authorization header format', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk'
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Invalid header syntax');
+                    done();
+                });
+            });
+
+            it('should fail on an bad host header (missing host)', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    headers: {
+                        host: ':8080',
+                        authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                    }
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Invalid Host header');
+                    done();
+                });
+            });
+
+            it('should fail on an bad host header (pad port)', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    headers: {
+                        host: 'example.com:something',
+                        authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                    }
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Invalid Host header');
+                    done();
+                });
+            });
+
+            it('should fail on credentialsFunc error', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                var credentialsFunc = function (id, callback) {
+
+                    return callback(new Error('Unknown user'));
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.message).to.equal('Unknown user');
+                    done();
+                });
+            });
+
+            it('should fail on missing credentials', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                var credentialsFunc = function (id, callback) {
+
+                    return callback(null, null);
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Unknown credentials');
+                    done();
+                });
+            });
+
+            it('should fail on invalid credentials', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                var credentialsFunc = function (id, callback) {
+
+                    var credentials = {
+                        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                        user: 'steve'
+                    };
+
+                    return callback(null, credentials);
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.message).to.equal('Invalid credentials');
+                    expect(err.response.payload.message).to.equal('An internal server error occurred');
+                    done();
+                });
+            });
+
+            it('should fail on unknown credentials algorithm', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                var credentialsFunc = function (id, callback) {
+
+                    var credentials = {
+                        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                        algorithm: 'hmac-sha-0',
+                        user: 'steve'
+                    };
+
+                    return callback(null, credentials);
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.message).to.equal('Unknown algorithm');
+                    expect(err.response.payload.message).to.equal('An internal server error occurred');
+                    done();
+                });
+            });
+
+            it('should fail on unknown bad mac', function (done) {
+
+                var req = {
+                    method: 'GET',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080,
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcU4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                };
+
+                var credentialsFunc = function (id, callback) {
+
+                    var credentials = {
+                        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                        algorithm: 'sha256',
+                        user: 'steve'
+                    };
+
+                    return callback(null, credentials);
+                };
+
+                Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Bad mac');
+                    done();
+                });
+            });
+        });
+
+        describe('#header', function () {
+
+            it('should return an empty authorization header on missing options', function (done) {
+
+                var header = Hawk.server.header();
+                expect(header).to.equal('');
+                done();
+            });
+
+            it('should return an empty authorization header on missing credentials', function (done) {
+
+                var header = Hawk.server.header(null, {});
+                expect(header).to.equal('');
+                done();
+            });
+
+            it('should return an empty authorization header on invalid credentials', function (done) {
+
+                var credentials = {
+                    key: '2983d45yun89q'
+                };
+
+                var header = Hawk.server.header(credentials);
+                expect(header).to.equal('');
+                done();
+            });
+
+            it('should return an empty authorization header on invalid algorithm', function (done) {
+
+                var artifacts = {
+                    id: '123456'
+                };
+
+                var credentials = {
+                    key: '2983d45yun89q',
+                    algorithm: 'hmac-sha-0'
+                };
+
+                var header = Hawk.server.header(credentials, artifacts);
+                expect(header).to.equal('');
+                done();
+            });
+        });
+    });
+});
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/test/uri.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/test/uri.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/test/uri.js	(revision 484)
@@ -0,0 +1,456 @@
+// Load modules
+
+var Http = require('http');
+var Lab = require('lab');
+var Hawk = require('../lib');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hawk', function () {
+
+    describe('Uri', function () {
+
+        var credentialsFunc = function (id, callback) {
+
+            var credentials = {
+                id: id,
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            return callback(null, credentials);
+        };
+
+        it('should generate a bewit then successfully authenticate it', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?a=1&b=2',
+                host: 'example.com',
+                port: 80
+            };
+
+            credentialsFunc('123456', function (err, credentials) {
+
+                var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials, ttlSec: 60 * 60 * 24 * 365 * 100, ext: 'some-app-data' });
+                req.url += '&bewit=' + bewit;
+
+                Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                    expect(err).to.not.exist;
+                    expect(credentials.user).to.equal('steve');
+                    expect(attributes.ext).to.equal('some-app-data');
+                    done();
+                });
+            });
+        });
+
+        it('should generate a bewit then successfully authenticate it (no ext)', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?a=1&b=2',
+                host: 'example.com',
+                port: 80
+            };
+
+            credentialsFunc('123456', function (err, credentials) {
+
+                var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials, ttlSec: 60 * 60 * 24 * 365 * 100 });
+                req.url += '&bewit=' + bewit;
+
+                Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                    expect(err).to.not.exist;
+                    expect(credentials.user).to.equal('steve');
+                    done();
+                });
+            });
+        });
+
+        it('should successfully authenticate a request (last param)', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(attributes.ext).to.equal('some-app-data');
+                done();
+            });
+        });
+
+        it('should successfully authenticate a request (first param)', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ&a=1&b=2',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(attributes.ext).to.equal('some-app-data');
+                done();
+            });
+        });
+
+        it('should successfully authenticate a request (only param)', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.not.exist;
+                expect(credentials.user).to.equal('steve');
+                expect(attributes.ext).to.equal('some-app-data');
+                done();
+            });
+        });
+
+        it('should fail on multiple authentication', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Basic asdasdasdasd'
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Multiple authentications');
+                done();
+            });
+        });
+
+        it('should fail on method other than GET', function (done) {
+
+            credentialsFunc('123456', function (err, credentials) {
+
+                var req = {
+                    method: 'POST',
+                    url: '/resource/4?filter=a',
+                    host: 'example.com',
+                    port: 8080
+                };
+
+                var exp = Math.floor(Hawk.utils.now() / 1000) + 60;
+                var ext = 'some-app-data';
+                var mac = Hawk.crypto.calculateMac('bewit', credentials, {
+                    timestamp: exp,
+                    nonce: '',
+                    method: req.method,
+                    resource: req.url,
+                    host: req.host,
+                    port: req.port,
+                    ext: ext
+                });
+
+                var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + ext;
+
+                req.url += '&bewit=' + Hawk.utils.base64urlEncode(bewit);
+
+                Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                    expect(err).to.exist;
+                    expect(err.response.payload.message).to.equal('Invalid method');
+                    done();
+                });
+            });
+        });
+
+        it('should fail on invalid host header', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+                headers: {
+                    host: 'example.com:something'
+                }
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Invalid Host header');
+                done();
+            });
+        });
+
+        it('should fail on empty bewit', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Empty bewit');
+                expect(err.isMissing).to.not.exist;
+                done();
+            });
+        });
+
+        it('should fail on invalid bewit', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=*',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Invalid bewit encoding');
+                expect(err.isMissing).to.not.exist;
+                done();
+            });
+        });
+
+        it('should fail on missing bewit', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.not.exist;
+                expect(err.isMissing).to.equal(true);
+                done();
+            });
+        });
+
+        it('should fail on invalid bewit structure', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=abc',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Invalid bewit structure');
+                done();
+            });
+        });
+
+        it('should fail on empty bewit attribute', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=YVxcY1xk',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Missing bewit attributes');
+                done();
+            });
+        });
+
+        it('should fail on expired access', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDEzNTY0MTg1ODNcWk1wZlMwWU5KNHV0WHpOMmRucTRydEk3NXNXTjFjeWVITTcrL0tNZFdVQT1cc29tZS1hcHAtZGF0YQ',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Access expired');
+                done();
+            });
+        });
+
+        it('should fail on credentials function error', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, function (id, callback) { callback(Hawk.error.badRequest('Boom')); }, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Boom');
+                done();
+            });
+        });
+
+        it('should fail on null credentials function response', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, function (id, callback) { callback(null, null); }, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Unknown credentials');
+                done();
+            });
+        });
+
+        it('should fail on invalid credentials function response', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, function (id, callback) { callback(null, {}); }, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('Invalid credentials');
+                done();
+            });
+        });
+
+        it('should fail on invalid credentials function response (unknown algorithm)', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, function (id, callback) { callback(null, { key: 'xxx', algorithm: 'xxx' }); }, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.message).to.equal('Unknown algorithm');
+                done();
+            });
+        });
+
+        it('should fail on expired access', function (done) {
+
+            var req = {
+                method: 'GET',
+                url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+                host: 'example.com',
+                port: 8080
+            };
+
+            Hawk.uri.authenticate(req, function (id, callback) { callback(null, { key: 'xxx', algorithm: 'sha256' }); }, {}, function (err, credentials, attributes) {
+
+                expect(err).to.exist;
+                expect(err.response.payload.message).to.equal('Bad mac');
+                done();
+            });
+        });
+    });
+
+    describe('#getBewit', function () {
+
+        it('should return a valid bewit value', function (done) {
+
+            var credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
+            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6');
+            done();
+        });
+
+        it('should return an empty bewit on invalid credentials', function (done) {
+
+            var credentials = {
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' });
+            expect(bewit).to.equal('');
+            done();
+        });
+
+        it('should return an empty bewit on invalid algorithm', function (done) {
+
+            var credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'hmac-sha-0'
+            };
+
+            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, ext: 'xandyandz' });
+            expect(bewit).to.equal('');
+            done();
+        });
+
+        it('should return an empty bewit on missing options', function (done) {
+
+            var credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'hmac-sha-0'
+            };
+
+            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow');
+            expect(bewit).to.equal('');
+            done();
+        });
+    });
+});
+
Index: Dev/trunk/src/node_modules/request/node_modules/hawk/test/utils.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/hawk/test/utils.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/hawk/test/utils.js	(revision 484)
@@ -0,0 +1,82 @@
+// Load modules
+
+var Lab = require('lab');
+var Hawk = require('../lib');
+var Package = require('../package.json');
+
+
+// Declare internals
+
+var internals = {};
+
+
+// Test shortcuts
+
+var expect = Lab.expect;
+var before = Lab.before;
+var after = Lab.after;
+var describe = Lab.experiment;
+var it = Lab.test;
+
+
+describe('Hawk', function () {
+
+    describe('Utils', function () {
+
+        describe('#parseHost', function () {
+
+            it('returns port 80 for non tls node request', function (done) {
+
+                var req = {
+                    method: 'POST',
+                    url: '/resource/4?filter=a',
+                    headers: {
+                        host: 'example.com',
+                        'content-type': 'text/plain;x=y'
+                    }
+                };
+
+                expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(80);
+                done();
+            });
+
+            it('returns port 443 for non tls node request', function (done) {
+
+                var req = {
+                    method: 'POST',
+                    url: '/resource/4?filter=a',
+                    headers: {
+                        host: 'example.com',
+                        'content-type': 'text/plain;x=y'
+                    },
+                    connection: {
+                        encrypted: true
+                    }
+                };
+
+                expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443);
+                done();
+            });
+        });
+
+        describe('#version', function () {
+
+            it('returns the correct package version number', function (done) {
+
+                expect(Hawk.utils.version()).to.equal(Package.version);
+                done();
+            });
+        });
+
+        describe('#unauthorized', function () {
+
+            it('returns a hawk 401', function (done) {
+
+                expect(Hawk.utils.unauthorized('kaboom').response.headers['WWW-Authenticate']).to.equal('Hawk error="kaboom"');
+                done();
+            });
+        });
+    });
+});
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/.dir-locals.el
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/.dir-locals.el	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/.dir-locals.el	(revision 484)
@@ -0,0 +1,6 @@
+((nil . ((indent-tabs-mode . nil)
+         (tab-width . 8)
+         (fill-column . 80)))
+ (js-mode . ((js-indent-level . 2)
+             (indent-tabs-mode . nil)
+             )))
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/.npmignore	(revision 484)
@@ -0,0 +1,6 @@
+.gitmodules
+Makefile
+deps
+docs
+test
+tools
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/LICENSE	(revision 484)
@@ -0,0 +1,18 @@
+Copyright Joyent, Inc. All rights reserved.
+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.
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/README.md	(revision 484)
@@ -0,0 +1,73 @@
+node-http-signature is a node.js library that has client and server components
+for Joyent's `HTTP Signature Scheme`.
+
+## Usage
+
+Note the example below signs a request with the same key/cert used to start an
+HTTP server. This is almost certainly not what you actaully want, but is just
+used to illustrate the API calls; you will need to provide your own key
+management in addition to this library.
+
+### Client
+
+    var fs = require('fs');
+    var https = require('https');
+    var httpSignature = require('http-signature');
+
+    var key = fs.readFileSync('./key.pem', 'ascii');
+
+    var options = {
+      host: 'localhost',
+      port: 8443,
+      path: '/',
+      method: 'GET',
+      headers: {}
+    };
+
+    // Adds a 'Date' header in, signs it, and adds the
+    // 'Authorization' header in.
+    var req = https.request(options, function(res) {
+      console.log(res.statusCode);
+    });
+
+
+    httpSignature.sign(req, {
+      key: key,
+      keyId: './cert.pem'
+    });
+
+    req.end();
+
+### Server
+
+    var fs = require('fs');
+    var https = require('https');
+    var httpSignature = require('http-signature');
+
+    var options = {
+      key: fs.readFileSync('./key.pem'),
+      cert: fs.readFileSync('./cert.pem')
+    };
+
+    https.createServer(options, function (req, res) {
+      var rc = 200;
+      var parsed = httpSignature.parseRequest(req);
+      var pub = fs.readFileSync(parsed.keyId, 'ascii');
+      if (!httpSignature.verifySignature(parsed, pub))
+        rc = 401;
+
+      res.writeHead(rc);
+      res.end();
+    }).listen(8443);
+
+## Installation
+
+    npm install http-signature
+
+## License
+
+MIT.
+
+## Bugs
+
+See <https://github.com/joyent/node-http-signature/issues>.
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/http_signing.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/http_signing.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/http_signing.md	(revision 484)
@@ -0,0 +1,273 @@
+# Abstract
+
+This document describes a way to add origin authentication, message integrity,
+and replay resistance to HTTP REST requests.  It is intended to be used over
+the HTTPS protocol.
+
+# Copyright Notice
+
+Copyright (c) 2011 Joyent, Inc. and the persons identified as document authors.
+All rights reserved.
+
+Code Components extracted from this document must include MIT License text.
+
+# Introduction
+
+This protocol is intended to provide a standard way for clients to sign HTTP
+requests.  RFC2617 (HTTP Authentication) defines Basic and Digest authentication
+mechanisms, and RFC5246 (TLS 1.2) defines client-auth, both of which are widely
+employed on the Internet today.  However, it is common place that the burdens of
+PKI prevent web service operators from deploying that methodoloy, and so many
+fall back to Basic authentication, which has poor security characteristics.
+
+Additionally, OAuth provides a fully-specified alternative for authorization
+of web service requests, but is not (always) ideal for machine to machine
+communication, as the key acquisition steps (generally) imply a fixed
+infrastructure that may not make sense to a service provider (e.g., symmetric
+keys).
+
+Several web service providers have invented their own schemes for signing
+HTTP requests, but to date, none have been placed in the public domain as a
+standard.  This document serves that purpose.  There are no techniques in this
+proposal that are novel beyond previous art, however, this aims to be a simple
+mechanism for signing these requests.
+
+# Signature Authentication Scheme
+
+The "signature" authentication scheme is based on the model that the client must
+authenticate itself with a digital signature produced by either a private
+asymmetric key (e.g., RSA) or a shared symmetric key (e.g., HMAC).  The scheme
+is parameterized enough such that it is not bound to any particular key type or
+signing algorithm.  However, it does explicitly assume that clients can send an
+HTTP `Date` header.
+
+## Authorization Header
+
+The client is expected to send an Authorization header (as defined in RFC 2617)
+with the following parameterization:
+
+    credentials := "Signature" params digitalSignature
+    params := 1#(keyId | [algorithm] | [headers] | [ext])
+    digitalSignature := plain-string
+
+    keyId := "keyId" "=" <"> plain-string <">
+    algorithm := "algorithm" "=" <"> plain-string <">
+    headers := "headers" "=" <"> 1#headers-value <">
+    ext := "ext" "=" <"> plain-string <">
+
+    headers-value := plain-string
+    plain-string   = 1*( %x20-21 / %x23-5B / %x5D-7E )
+
+### Signature Parameters
+
+#### keyId
+
+REQUIRED.  The `keyId` field is an opaque string that the server can use to look
+up the component they need to validate the signature.  It could be an SSH key
+fingerprint, an LDAP DN, etc.  Management of keys and assignment of `keyId` is
+out of scope for this document.
+
+#### algorithm
+
+REQUIRED. The `algorithm` parameter is used if the client and server agree on a
+non-standard digital signature algorithm.  The full list of supported signature
+mechanisms is listed below.
+
+#### headers
+
+OPTIONAL.  The `headers` parameter is used to specify the list of HTTP headers
+used to sign the request.  If specified, it should be a quoted list of HTTP
+header names, separated by a single space character.  By default, only one
+HTTP header is signed, which is the `Date` header.  Note that the list MUST be
+specified in the order the values are concatenated together during signing. To
+include the HTTP request line in the signature calculation, use the special
+`request-line` value.  While this is overloading the definition of `headers` in
+HTTP linguism, the request-line is defined in RFC 2616, and as the outlier from
+headers in useful signature calculation, it is deemed simpler to simply use
+`request-line` than to add a separate parameter for it.
+
+#### extensions
+
+OPTIONAL.  The `extensions` parameter is used to include additional information
+which is covered by the request.  The content and format of the string is out of
+scope for this document, and expected to be specified by implementors.
+
+### Digital Signature
+
+The `digitalSignature` portion of the credentials is a REQUIRED field, and is
+generated by the client. The client uses the `algorithm` and `headers` request
+parameters to form a canonicalized `signing string`.  This `signing string` is
+then signed with the key associated with `keyId` and the algorithm corresponding
+to `algorithm`.  The result is then `Base64` encoded.
+
+### Signing String Composition
+
+In order to generate the string that is signed with a key, the client MUST
+take the values of each HTTP header specified by `headers`, in the order they
+appear, and separate with an ASCII newline `\n`.  The last header in the list
+MUST NOT include a trailing ASCII newline.
+
+# Example Requests
+
+All requests refer to the following request (body ommitted):
+
+    POST /foo HTTP/1.1
+    Host: example.org
+    Date: Tue, 07 Jun 2011 20:51:35 GMT
+    Content-Type: application/json
+    Content-MD5: h0auK8hnYJKmHTLhKtMTkQ==
+    Content-Length: 123
+
+## Default parameterization
+
+    Authorization: Signature keyId="123" Base64(RSA-SHA256(Tue, 07 Jun 2011 20:51:35 GMT))
+
+## Header List
+
+    Authorization: Signature keyId="123",headers="content-type Date content-md5" Base64(RSA-SHA256(Tue, 07 Jun 2011 20:51:35 GMT))
+
+The client would compose the signing string as (`+ "\n"` inserted for
+readability):
+
+    application/json + "\n"
+    Tue, 07 Jun 2011 20:51:35 GMT + "\n"
+    h0auK8hnYJKmHTLhKtMTkQ==
+
+## Algorithm
+
+    Authorization: Signature keyId="123",algorithm="hmac-sha1" Base64(HMAC-SHA1(Tue, 07 Jun 2011 20:51:35 GMT))
+
+# Signing Algorithms
+
+Currently supported algorithm names are:
+
+* rsa-sha1
+* rsa-sha256
+* rsa-sha512
+* hmac-sha1
+* hmac-sha256
+* hmac-sha512
+
+# Security Considerations
+
+## Default Parameters
+
+Note the default parameterization of the `Signature` scheme is only safe if all
+requests are carried over a secure transport (i.e., TLS).  Sending the default
+scheme over a non-secure transport will leave the request vulnerable to
+spoofing, tampering, replay/repudiaton, and integrity violations (if using the
+STRIDE threat-modeling methodology).
+
+## Insecure Transports
+
+If sending the request over plain HTTP, service providers SHOULD require clients
+to sign ALL HTTP headers, and the `request-line`.  Additionally, service
+providers SHOULD require `Content-MD5` calculations to be performed to ensure
+against any tampering from clients.
+
+## Nonces
+
+Nonces are out of scope for this document simply because many service providers
+fail to implement them correctly, or do not adopt security specfiications
+because of the infrastructure complexity.  Given the `header` parameterization,
+a service provider is fully enabled to add nonce semantics into this scheme by
+using something like an `x-request-nonce` header, and ensuring it is signed
+with the `Date` header.
+
+## Clock Skew
+
+As the default scheme is to sign the `Date` header, service providers SHOULD
+protect against logged replay attacks by enforcing a clock skew.  The server
+SHOULD be synchronized with NTP, and the recommendation in this specification
+is to allow 300s of clock skew (in either direction).
+
+## Required Headers to Sign
+
+It is out of scope for this document to dictate what headers a service provider
+will want to enforce, but service providers SHOULD at minimum include the
+`Date` header.
+
+# References
+
+## Normative References
+
+* [RFC2616] Hypertext Transfer Protocol -- HTTP/1.1
+* [RFC2617] HTTP Authentication: Basic and Digest Access Authentication
+* [RFC5246] The Transport Layer Security (TLS) Protocol Version 1.2
+
+## Informative References
+
+    Name: Mark Cavage (editor)
+    Company: Joyent, Inc.
+    Email: mark.cavage@joyent.com
+    URI: http://www.joyent.com
+
+# Appendix A - Test Values
+
+The following test data uses the RSA (2048b) keys, which we will refer
+to as `keyId=Test` in the following samples:
+
+   -----BEGIN PUBLIC KEY-----
+   MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3
+   6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6
+   Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw
+   oYi+1hqp1fIekaxsyQIDAQAB
+   -----END PUBLIC KEY-----
+
+    -----BEGIN RSA PRIVATE KEY-----
+    MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF
+    NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F
+    UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB
+    AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA
+    QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK
+    kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg
+    f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u
+    412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc
+    mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7
+    kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA
+    gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW
+    G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI
+    7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA==
+    -----END RSA PRIVATE KEY-----
+
+And all examples use this request:
+
+    POST /foo?param=value&pet=dog HTTP/1.1
+    Host: example.com
+    Date: Thu, 05 Jan 2012 21:31:40 GMT
+    Content-Type: application/json
+    Content-MD5: Sd/dVLAcvNLSq16eXua5uQ==
+    Content-Length: 18
+
+    {"hello": "world"}
+
+### Default
+
+The string to sign would be:
+
+```
+Thu, 05 Jan 2012 21:31:40 GMT
+```
+
+The Authorization header would be:
+
+    Authorization: Signature keyId="Test",algorithm="rsa-sha256" MDyO5tSvin5FBVdq3gMBTwtVgE8U/JpzSwFvY7gu7Q2tiZ5TvfHzf/RzmRoYwO8PoV1UGaw6IMwWzxDQkcoYOwvG/w4ljQBBoNusO/mYSvKrbqxUmZi8rNtrMcb82MS33bai5IeLnOGl31W1UbL4qE/wL8U9wCPGRJlCFLsTgD8=
+
+### All Headers
+
+Parameterized to include all headers, the string to sign would be:
+
+```
+/foo?param=value&pet=dog HTTP/1.1
+example.com
+Thu, 05 Jan 2012 21:31:40 GMT
+application/json
+Sd/dVLAcvNLSq16eXua5uQ==
+18
+```
+
+The Authorization header would be:
+
+    Authorization: Signature
+    keyId="Test",algorithm="rsa-sha256",headers="request-line host date content-type content-md5 content-length" gVrKP7wVh1+FmWbNlhj0pNXIe9XmeOA6EcnoOKAvUILnwaMFzaKaam9UmeDPwjC9TdT+jSRqjtyZE49kZcSpYAHxGlPQ4ziXFRfPprlN/3Xwg3sUOGqbBiS3WFuY3QOOWv4tzc5p70g74U/QvHNNiYMcjoz89vRJhefbFSNwCDs=
+
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/index.js	(revision 484)
@@ -0,0 +1,25 @@
+// Copyright 2011 Joyent, Inc.  All rights reserved.
+
+var parser = require('./parser');
+var signer = require('./signer');
+var verify = require('./verify');
+var util = require('./util');
+
+
+
+///--- API
+
+module.exports = {
+
+  parse: parser.parseRequest,
+  parseRequest: parser.parseRequest,
+
+  sign: signer.signRequest,
+  signRequest: signer.signRequest,
+
+  sshKeyToPEM: util.sshKeyToPEM,
+  sshKeyFingerprint: util.fingerprint,
+
+  verify: verify.verifySignature,
+  verifySignature: verify.verifySignature
+};
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/parser.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/parser.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/parser.js	(revision 484)
@@ -0,0 +1,290 @@
+// Copyright 2012 Joyent, Inc.  All rights reserved.
+
+var assert = require('assert-plus');
+var util = require('util');
+
+
+
+///--- Globals
+
+var Algorithms = {
+  'rsa-sha1': true,
+  'rsa-sha256': true,
+  'rsa-sha512': true,
+  'dsa-sha1': true,
+  'hmac-sha1': true,
+  'hmac-sha256': true,
+  'hmac-sha512': true
+};
+
+var State = {
+  New: 0,
+  Params: 1,
+  Signature: 2
+};
+
+var ParamsState = {
+  Name: 0,
+  Value: 1
+};
+
+
+
+///--- Specific Errors
+
+function HttpSignatureError(message, caller) {
+  if (Error.captureStackTrace)
+    Error.captureStackTrace(this, caller || HttpSignatureError);
+
+  this.message = message;
+  this.name = caller.name;
+}
+util.inherits(HttpSignatureError, Error);
+
+function ExpiredRequestError(message) {
+  HttpSignatureError.call(this, message, ExpiredRequestError);
+}
+util.inherits(ExpiredRequestError, HttpSignatureError);
+
+
+function InvalidHeaderError(message) {
+  HttpSignatureError.call(this, message, InvalidHeaderError);
+}
+util.inherits(InvalidHeaderError, HttpSignatureError);
+
+
+function InvalidParamsError(message) {
+  HttpSignatureError.call(this, message, InvalidParamsError);
+}
+util.inherits(InvalidParamsError, HttpSignatureError);
+
+
+function MissingHeaderError(message) {
+  HttpSignatureError.call(this, message, MissingHeaderError);
+}
+util.inherits(MissingHeaderError, HttpSignatureError);
+
+
+
+///--- Exported API
+
+module.exports = {
+
+  /**
+   * Parses the 'Authorization' header out of an http.ServerRequest object.
+   *
+   * Note that this API will fully validate the Authorization header, and throw
+   * on any error.  It will not however check the signature, or the keyId format
+   * as those are specific to your environment.  You can use the options object
+   * to pass in extra constraints.
+   *
+   * As a response object you can expect this:
+   *
+   *     {
+   *       "scheme": "Signature",
+   *       "params": {
+   *         "keyId": "foo",
+   *         "algorithm": "rsa-sha256",
+   *         "headers": [
+   *           "date" or "x-date",
+   *           "content-md5"
+   *         ]
+   *       },
+   *       "signature": "base64",
+   *       "signingString": "ready to be passed to crypto.verify()"
+   *     }
+   *
+   * @param {Object} request an http.ServerRequest.
+   * @param {Object} options an optional options object with:
+   *                   - clockSkew: allowed clock skew in seconds (default 300).
+   *                   - headers: required header names (def: date or x-date)
+   *                   - algorithms: algorithms to support (default: all).
+   * @return {Object} parsed out object (see above).
+   * @throws {TypeError} on invalid input.
+   * @throws {InvalidHeaderError} on an invalid Authorization header error.
+   * @throws {InvalidParamsError} if the params in the scheme are invalid.
+   * @throws {MissingHeaderError} if the params indicate a header not present,
+   *                              either in the request headers from the params,
+   *                              or not in the params from a required header
+   *                              in options.
+   * @throws {ExpiredRequestError} if the value of date or x-date exceeds skew.
+   */
+  parseRequest: function parseRequest(request, options) {
+    assert.object(request, 'request');
+    assert.object(request.headers, 'request.headers');
+    if (options === undefined) {
+      options = {};
+    }
+    if (options.headers === undefined) {
+      options.headers = [request.headers['x-date'] ? 'x-date' : 'date'];
+    }
+    assert.object(options, 'options');
+    assert.arrayOfString(options.headers, 'options.headers');
+    assert.optionalNumber(options.clockSkew, 'options.clockSkew');
+
+    if (!request.headers.authorization)
+      throw new MissingHeaderError('no authorization header present in ' +
+                                   'the request');
+
+    options.clockSkew = options.clockSkew || 300;
+
+
+    var i = 0;
+    var state = State.New;
+    var substate = ParamsState.Name;
+    var tmpName = '';
+    var tmpValue = '';
+
+    var parsed = {
+      scheme: '',
+      params: {},
+      signature: '',
+      signingString: '',
+
+      get algorithm() {
+        return this.params.algorithm.toUpperCase();
+      },
+
+      get keyId() {
+        return this.params.keyId;
+      }
+
+    };
+
+    var authz = request.headers.authorization;
+    for (i = 0; i < authz.length; i++) {
+      var c = authz.charAt(i);
+
+      switch (Number(state)) {
+
+      case State.New:
+        if (c !== ' ') parsed.scheme += c;
+        else state = State.Params;
+        break;
+
+      case State.Params:
+        switch (Number(substate)) {
+
+        case ParamsState.Name:
+          if (c === '"') {
+            parsed.params[tmpName] = '';
+            tmpValue = '';
+            substate = ParamsState.Value;
+          } else if (c === ' ') {
+            state = State.Signature;
+          } else if (c !== '=' && c !== ',') {
+            tmpName += c;
+          }
+          break;
+
+        case ParamsState.Value:
+          if (c === '"') {
+            parsed.params[tmpName] = tmpValue;
+            tmpName = '';
+            substate = ParamsState.Name;
+          } else {
+            tmpValue += c;
+          }
+          break;
+
+        default:
+          throw new Error('Invalid substate');
+        }
+        break;
+
+
+      case State.Signature:
+        parsed.signature += c;
+        break;
+
+      default:
+        throw new Error('Invalid substate');
+      }
+
+    }
+
+    if (!parsed.params.headers || parsed.params.headers === '') {
+      if (request.headers['x-date']) {
+        parsed.params.headers = ['x-date'];
+      } else {
+        parsed.params.headers = ['date'];
+      }
+    } else {
+      parsed.params.headers = parsed.params.headers.split(' ');
+    }
+
+    // Minimally validate the parsed object
+    if (!parsed.scheme || parsed.scheme !== 'Signature')
+      throw new InvalidHeaderError('scheme was not "Signature"');
+
+    if (!parsed.params.keyId)
+      throw new InvalidHeaderError('keyId was not specified');
+
+    if (!parsed.params.algorithm)
+      throw new InvalidHeaderError('algorithm was not specified');
+
+    if (!parsed.signature)
+      throw new InvalidHeaderError('signature was empty');
+
+    // Check the algorithm against the official list
+    parsed.params.algorithm = parsed.params.algorithm.toLowerCase();
+    if (!Algorithms[parsed.params.algorithm])
+      throw new InvalidParamsError(parsed.params.algorithm +
+                                   ' is not supported');
+
+    // Build the signingString
+    for (i = 0; i < parsed.params.headers.length; i++) {
+      var h = parsed.params.headers[i].toLowerCase();
+      parsed.params.headers[i] = h;
+
+      var value;
+      if (h !== 'request-line') {
+        value = request.headers[h];
+        if (!value)
+          throw new MissingHeaderError(h + ' was not in the request');
+      } else {
+        value =
+          request.method + ' ' + request.url + ' HTTP/' + request.httpVersion;
+      }
+
+      parsed.signingString += value;
+      if ((i + 1) < parsed.params.headers.length)
+        parsed.signingString += '\n';
+    }
+
+    // Check against the constraints
+    var date;
+    if (request.headers.date || request.headers['x-date']) {
+        if (request.headers['x-date']) {
+          date = new Date(request.headers['x-date']);
+        } else {
+          date = new Date(request.headers.date);
+        }
+      var now = new Date();
+      var skew = Math.abs(now.getTime() - date.getTime());
+
+      if (skew > options.clockSkew * 1000) {
+        throw new ExpiredRequestError('clock skew of ' +
+                                      (skew / 1000) +
+                                      's was greater than ' +
+                                      options.clockSkew + 's');
+      }
+    }
+
+    options.headers.forEach(function (hdr) {
+      // Remember that we already checked any headers in the params
+      // were in the request, so if this passes we're good.
+      if (parsed.params.headers.indexOf(hdr) < 0)
+        throw new MissingHeaderError(hdr + ' was not a signed header');
+    });
+
+    if (options.algorithms) {
+      if (options.algorithms.indexOf(parsed.params.algorithm) === -1)
+        throw new InvalidParamsError(parsed.params.algorithm +
+                                     ' is not a supported algorithm');
+    }
+
+    return parsed;
+  }
+
+};
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/signer.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/signer.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/signer.js	(revision 484)
@@ -0,0 +1,173 @@
+// Copyright 2012 Joyent, Inc.  All rights reserved.
+
+var assert = require('assert-plus');
+var crypto = require('crypto');
+var http = require('http');
+
+var sprintf = require('util').format;
+
+
+
+///--- Globals
+
+var Algorithms = {
+  'rsa-sha1': true,
+  'rsa-sha256': true,
+  'rsa-sha512': true,
+  'dsa-sha1': true,
+  'hmac-sha1': true,
+  'hmac-sha256': true,
+  'hmac-sha512': true
+};
+
+var Authorization = 'Signature keyId="%s",algorithm="%s",headers="%s" %s';
+
+
+
+///--- Specific Errors
+
+function MissingHeaderError(message) {
+    this.name = 'MissingHeaderError';
+    this.message = message;
+    this.stack = (new Error()).stack;
+}
+MissingHeaderError.prototype = new Error();
+
+
+function InvalidAlgorithmError(message) {
+    this.name = 'InvalidAlgorithmError';
+    this.message = message;
+    this.stack = (new Error()).stack;
+}
+InvalidAlgorithmError.prototype = new Error();
+
+
+
+///--- Internal Functions
+
+function _pad(val) {
+  if (parseInt(val, 10) < 10) {
+    val = '0' + val;
+  }
+  return val;
+}
+
+
+function _rfc1123() {
+  var date = new Date();
+
+  var months = ['Jan',
+                'Feb',
+                'Mar',
+                'Apr',
+                'May',
+                'Jun',
+                'Jul',
+                'Aug',
+                'Sep',
+                'Oct',
+                'Nov',
+                'Dec'];
+  var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+  return days[date.getUTCDay()] + ', ' +
+    _pad(date.getUTCDate()) + ' ' +
+    months[date.getUTCMonth()] + ' ' +
+    date.getUTCFullYear() + ' ' +
+    _pad(date.getUTCHours()) + ':' +
+    _pad(date.getUTCMinutes()) + ':' +
+    _pad(date.getUTCSeconds()) +
+    ' GMT';
+}
+
+
+
+///--- Exported API
+
+module.exports = {
+
+  /**
+   * Adds an 'Authorization' header to an http.ClientRequest object.
+   *
+   * Note that this API will add a Date header if it's not already set. Any
+   * other headers in the options.headers array MUST be present, or this
+   * will throw.
+   *
+   * You shouldn't need to check the return type; it's just there if you want
+   * to be pedantic.
+   *
+   * @param {Object} request an instance of http.ClientRequest.
+   * @param {Object} options signing parameters object:
+   *                   - {String} keyId required.
+   *                   - {String} key required (either a PEM or HMAC key).
+   *                   - {Array} headers optional; defaults to ['date'].
+   *                   - {String} algorithm optional; defaults to 'rsa-sha256'.
+   * @return {Boolean} true if Authorization (and optionally Date) were added.
+   * @throws {TypeError} on bad parameter types (input).
+   * @throws {InvalidAlgorithmError} if algorithm was bad.
+   * @throws {MissingHeaderError} if a header to be signed was specified but
+   *                              was not present.
+   */
+  signRequest: function signRequest(request, options) {
+    assert.object(request, 'request');
+    assert.object(options, 'options');
+    assert.optionalString(options.algorithm, 'options.algorithm');
+    assert.string(options.keyId, 'options.keyId');
+    assert.optionalArrayOfString(options.headers, 'options.headers');
+
+    if (!request.getHeader('Date'))
+      request.setHeader('Date', _rfc1123());
+    if (!options.headers)
+      options.headers = ['date'];
+    if (!options.algorithm)
+      options.algorithm = 'rsa-sha256';
+
+    options.algorithm = options.algorithm.toLowerCase();
+
+    if (!Algorithms[options.algorithm])
+      throw new InvalidAlgorithmError(options.algorithm + ' is not supported');
+
+    var i;
+    var stringToSign = '';
+    for (i = 0; i < options.headers.length; i++) {
+      if (typeof (options.headers[i]) !== 'string')
+        throw new TypeError('options.headers must be an array of Strings');
+
+      var h = options.headers[i].toLowerCase();
+      request.getHeader(h);
+
+      var value = request.getHeader(h);
+      if (!value) {
+        if (h === 'request-line') {
+          value = request.method + ' ' + request.path + ' HTTP/1.1';
+        } else {
+          throw new MissingHeaderError(h + ' was not in the request');
+        }
+      }
+
+      stringToSign += value;
+      if ((i + 1) < options.headers.length)
+        stringToSign += '\n';
+    }
+
+    var alg = options.algorithm.match(/(hmac|rsa)-(\w+)/);
+    var signature;
+    if (alg[1] === 'hmac') {
+      var hmac = crypto.createHmac(alg[2].toUpperCase(), options.key);
+      hmac.update(stringToSign);
+      signature = hmac.digest('base64');
+    } else {
+      var signer = crypto.createSign(options.algorithm.toUpperCase());
+      signer.update(stringToSign);
+      signature = signer.sign(options.key, 'base64');
+    }
+
+    request.setHeader('Authorization', sprintf(Authorization,
+                                               options.keyId,
+                                               options.algorithm,
+                                               options.headers.join(' '),
+                                               signature));
+
+    return true;
+  }
+
+};
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/util.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/util.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/util.js	(revision 484)
@@ -0,0 +1,249 @@
+// Copyright 2012 Joyent, Inc.  All rights reserved.
+
+var assert = require('assert-plus');
+var crypto = require('crypto');
+
+var asn1 = require('asn1');
+var ctype = require('ctype');
+
+
+
+///--- Helpers
+
+function readNext(buffer, offset) {
+  var len = ctype.ruint32(buffer, 'big', offset);
+  offset += 4;
+
+  var newOffset = offset + len;
+
+  return {
+    data: buffer.slice(offset, newOffset),
+    offset: newOffset
+  };
+}
+
+
+function writeInt(writer, buffer) {
+  writer.writeByte(0x02); // ASN1.Integer
+  writer.writeLength(buffer.length);
+
+  for (var i = 0; i < buffer.length; i++)
+    writer.writeByte(buffer[i]);
+
+  return writer;
+}
+
+
+function rsaToPEM(key) {
+  var buffer;
+  var der;
+  var exponent;
+  var i;
+  var modulus;
+  var newKey = '';
+  var offset = 0;
+  var type;
+  var tmp;
+
+  try {
+    buffer = new Buffer(key.split(' ')[1], 'base64');
+
+    tmp = readNext(buffer, offset);
+    type = tmp.data.toString();
+    offset = tmp.offset;
+
+    if (type !== 'ssh-rsa')
+      throw new Error('Invalid ssh key type: ' + type);
+
+    tmp = readNext(buffer, offset);
+    exponent = tmp.data;
+    offset = tmp.offset;
+
+    tmp = readNext(buffer, offset);
+    modulus = tmp.data;
+  } catch (e) {
+    throw new Error('Invalid ssh key: ' + key);
+  }
+
+  // DER is a subset of BER
+  der = new asn1.BerWriter();
+
+  der.startSequence();
+
+  der.startSequence();
+  der.writeOID('1.2.840.113549.1.1.1');
+  der.writeNull();
+  der.endSequence();
+
+  der.startSequence(0x03); // bit string
+  der.writeByte(0x00);
+
+  // Actual key
+  der.startSequence();
+  writeInt(der, modulus);
+  writeInt(der, exponent);
+  der.endSequence();
+
+  // bit string
+  der.endSequence();
+
+  der.endSequence();
+
+  tmp = der.buffer.toString('base64');
+  for (i = 0; i < tmp.length; i++) {
+    if ((i % 64) === 0)
+      newKey += '\n';
+    newKey += tmp.charAt(i);
+  }
+
+  if (!/\\n$/.test(newKey))
+    newKey += '\n';
+
+  return '-----BEGIN PUBLIC KEY-----' + newKey + '-----END PUBLIC KEY-----\n';
+}
+
+
+function dsaToPEM(key) {
+  var buffer;
+  var offset = 0;
+  var tmp;
+  var der;
+  var newKey = '';
+
+  var type;
+  var p;
+  var q;
+  var g;
+  var y;
+
+  try {
+    buffer = new Buffer(key.split(' ')[1], 'base64');
+
+    tmp = readNext(buffer, offset);
+    type = tmp.data.toString();
+    offset = tmp.offset;
+
+    /* JSSTYLED */
+    if (!/^ssh-ds[as].*/.test(type))
+      throw new Error('Invalid ssh key type: ' + type);
+
+    tmp = readNext(buffer, offset);
+    p = tmp.data;
+    offset = tmp.offset;
+
+    tmp = readNext(buffer, offset);
+    q = tmp.data;
+    offset = tmp.offset;
+
+    tmp = readNext(buffer, offset);
+    g = tmp.data;
+    offset = tmp.offset;
+
+    tmp = readNext(buffer, offset);
+    y = tmp.data;
+  } catch (e) {
+    console.log(e.stack);
+    throw new Error('Invalid ssh key: ' + key);
+  }
+
+  // DER is a subset of BER
+  der = new asn1.BerWriter();
+
+  der.startSequence();
+
+  der.startSequence();
+  der.writeOID('1.2.840.10040.4.1');
+
+  der.startSequence();
+  writeInt(der, p);
+  writeInt(der, q);
+  writeInt(der, g);
+  der.endSequence();
+
+  der.endSequence();
+
+  der.startSequence(0x03); // bit string
+  der.writeByte(0x00);
+  writeInt(der, y);
+  der.endSequence();
+
+  der.endSequence();
+
+  tmp = der.buffer.toString('base64');
+  for (var i = 0; i < tmp.length; i++) {
+    if ((i % 64) === 0)
+      newKey += '\n';
+    newKey += tmp.charAt(i);
+  }
+
+  if (!/\\n$/.test(newKey))
+    newKey += '\n';
+
+  return '-----BEGIN PUBLIC KEY-----' + newKey + '-----END PUBLIC KEY-----\n';
+}
+
+
+///--- API
+
+module.exports = {
+
+  /**
+   * Converts an OpenSSH public key (rsa only) to a PKCS#8 PEM file.
+   *
+   * The intent of this module is to interoperate with OpenSSL only,
+   * specifically the node crypto module's `verify` method.
+   *
+   * @param {String} key an OpenSSH public key.
+   * @return {String} PEM encoded form of the RSA public key.
+   * @throws {TypeError} on bad input.
+   * @throws {Error} on invalid ssh key formatted data.
+   */
+  sshKeyToPEM: function sshKeyToPEM(key) {
+    assert.string(key, 'ssh_key');
+
+    /* JSSTYLED */
+    if (/^ssh-rsa.*/.test(key))
+      return rsaToPEM(key);
+
+    /* JSSTYLED */
+    if (/^ssh-ds[as].*/.test(key))
+      return dsaToPEM(key);
+
+    throw new Error('Only RSA and DSA public keys are allowed');
+  },
+
+
+  /**
+   * Generates an OpenSSH fingerprint from an ssh public key.
+   *
+   * @param {String} key an OpenSSH public key.
+   * @return {String} key fingerprint.
+   * @throws {TypeError} on bad input.
+   * @throws {Error} if what you passed doesn't look like an ssh public key.
+   */
+  fingerprint: function fingerprint(key) {
+    assert.string(key, 'ssh_key');
+
+    var pieces = key.split(' ');
+    if (!pieces || !pieces.length || pieces.length < 2)
+      throw new Error('invalid ssh key');
+
+    var data = new Buffer(pieces[1], 'base64');
+
+    var hash = crypto.createHash('md5');
+    hash.update(data);
+    var digest = hash.digest('hex');
+
+    var fp = '';
+    for (var i = 0; i < digest.length; i++) {
+      if (i && i % 2 === 0)
+        fp += ':';
+
+      fp += digest[i];
+    }
+
+    return fp;
+  }
+
+
+};
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/verify.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/verify.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/lib/verify.js	(revision 484)
@@ -0,0 +1,42 @@
+// Copyright 2011 Joyent, Inc.  All rights reserved.
+
+var assert = require('assert-plus');
+var crypto = require('crypto');
+
+
+
+///--- Exported API
+
+module.exports = {
+
+  /**
+   * Simply wraps up the node crypto operations for you, and returns
+   * true or false.  You are expected to pass in an object that was
+   * returned from `parse()`.
+   *
+   * @param {Object} parsedSignature the object you got from `parse`.
+   * @param {String} key either an RSA private key PEM or HMAC secret.
+   * @return {Boolean} true if valid, false otherwise.
+   * @throws {TypeError} if you pass in bad arguments.
+   */
+  verifySignature: function verifySignature(parsedSignature, key) {
+    assert.object(parsedSignature, 'parsedSignature');
+    assert.string(key, 'key');
+
+    var alg = parsedSignature.algorithm.match(/(HMAC|RSA|DSA)-(\w+)/);
+    if (!alg || alg.length !== 3)
+      throw new TypeError('parsedSignature: unsupported algorithm ' +
+                          parsedSignature.algorithm);
+
+    if (alg[1] === 'HMAC') {
+      var hmac = crypto.createHmac(alg[2].toLowerCase(), key);
+      hmac.update(parsedSignature.signingString);
+      return (hmac.digest('base64') === parsedSignature.signature);
+    } else {
+      var verify = crypto.createVerify(alg[0]);
+      verify.update(parsedSignature.signingString);
+      return verify.verify(key, parsedSignature.signature, 'base64');
+    }
+  }
+
+};
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/.npmignore	(revision 484)
@@ -0,0 +1,2 @@
+node_modules
+*.log
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/LICENSE	(revision 484)
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Mark Cavage, All rights reserved.
+
+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
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/README.md	(revision 484)
@@ -0,0 +1,50 @@
+node-asn1 is a library for encoding and decoding ASN.1 datatypes in pure JS.
+Currently BER encoding is supported; at some point I'll likely have to do DER.
+
+## Usage
+
+Mostly, if you're *actually* needing to read and write ASN.1, you probably don't
+need this readme to explain what and why.  If you have no idea what ASN.1 is,
+see this: ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
+
+The source is pretty much self-explanatory, and has read/write methods for the
+common types out there.
+
+### Decoding
+
+The following reads an ASN.1 sequence with a boolean.
+
+    var Ber = require('asn1').Ber;
+
+    var reader = new Ber.Reader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff]));
+
+    reader.readSequence();
+    console.log('Sequence len: ' + reader.length);
+    if (reader.peek() === Ber.Boolean)
+      console.log(reader.readBoolean());
+
+### Encoding
+
+The following generates the same payload as above.
+
+    var Ber = require('asn1').Ber;
+
+    var writer = new Ber.Writer();
+
+    writer.startSequence();
+    writer.writeBoolean(true);
+    writer.endSequence();
+
+    console.log(writer.buffer);
+
+## Installation
+
+    npm install asn1
+
+## License
+
+MIT.
+
+## Bugs
+
+See <https://github.com/mcavage/node-asn1/issues>.
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/errors.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/errors.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/errors.js	(revision 484)
@@ -0,0 +1,13 @@
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
+
+
+module.exports = {
+
+  newInvalidAsn1Error: function(msg) {
+    var e = new Error();
+    e.name = 'InvalidAsn1Error';
+    e.message = msg || '';
+    return e;
+  }
+
+};
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/index.js	(revision 484)
@@ -0,0 +1,27 @@
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
+
+var errors = require('./errors');
+var types = require('./types');
+
+var Reader = require('./reader');
+var Writer = require('./writer');
+
+
+///--- Exports
+
+module.exports = {
+
+  Reader: Reader,
+
+  Writer: Writer
+
+};
+
+for (var t in types) {
+  if (types.hasOwnProperty(t))
+    module.exports[t] = types[t];
+}
+for (var e in errors) {
+  if (errors.hasOwnProperty(e))
+    module.exports[e] = errors[e];
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/reader.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/reader.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/reader.js	(revision 484)
@@ -0,0 +1,267 @@
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
+
+var assert = require('assert');
+
+var ASN1 = require('./types');
+var errors = require('./errors');
+
+
+///--- Globals
+
+var newInvalidAsn1Error = errors.newInvalidAsn1Error;
+
+
+
+///--- API
+
+function Reader(data) {
+  if (!data || !Buffer.isBuffer(data))
+    throw new TypeError('data must be a node Buffer');
+
+  this._buf = data;
+  this._size = data.length;
+
+  // These hold the "current" state
+  this._len = 0;
+  this._offset = 0;
+
+  var self = this;
+  this.__defineGetter__('length', function() { return self._len; });
+  this.__defineGetter__('offset', function() { return self._offset; });
+  this.__defineGetter__('remain', function() {
+    return self._size - self._offset;
+  });
+  this.__defineGetter__('buffer', function() {
+    return self._buf.slice(self._offset);
+  });
+}
+
+
+/**
+ * Reads a single byte and advances offset; you can pass in `true` to make this
+ * a "peek" operation (i.e., get the byte, but don't advance the offset).
+ *
+ * @param {Boolean} peek true means don't move offset.
+ * @return {Number} the next byte, null if not enough data.
+ */
+Reader.prototype.readByte = function(peek) {
+  if (this._size - this._offset < 1)
+    return null;
+
+  var b = this._buf[this._offset] & 0xff;
+
+  if (!peek)
+    this._offset += 1;
+
+  return b;
+};
+
+
+Reader.prototype.peek = function() {
+  return this.readByte(true);
+};
+
+
+/**
+ * Reads a (potentially) variable length off the BER buffer.  This call is
+ * not really meant to be called directly, as callers have to manipulate
+ * the internal buffer afterwards.
+ *
+ * As a result of this call, you can call `Reader.length`, until the
+ * next thing called that does a readLength.
+ *
+ * @return {Number} the amount of offset to advance the buffer.
+ * @throws {InvalidAsn1Error} on bad ASN.1
+ */
+Reader.prototype.readLength = function(offset) {
+  if (offset === undefined)
+    offset = this._offset;
+
+  if (offset >= this._size)
+    return null;
+
+  var lenB = this._buf[offset++] & 0xff;
+  if (lenB === null)
+    return null;
+
+  if ((lenB & 0x80) == 0x80) {
+    lenB &= 0x7f;
+
+    if (lenB == 0)
+      throw newInvalidAsn1Error('Indefinite length not supported');
+
+    if (lenB > 4)
+      throw newInvalidAsn1Error('encoding too long');
+
+    if (this._size - offset < lenB)
+      return null;
+
+    this._len = 0;
+    for (var i = 0; i < lenB; i++)
+      this._len = (this._len << 8) + (this._buf[offset++] & 0xff);
+
+  } else {
+    // Wasn't a variable length
+    this._len = lenB;
+  }
+
+  return offset;
+};
+
+
+/**
+ * Parses the next sequence in this BER buffer.
+ *
+ * To get the length of the sequence, call `Reader.length`.
+ *
+ * @return {Number} the sequence's tag.
+ */
+Reader.prototype.readSequence = function(tag) {
+  var seq = this.peek();
+  if (seq === null)
+    return null;
+  if (tag !== undefined && tag !== seq)
+    throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
+                              ': got 0x' + seq.toString(16));
+
+  var o = this.readLength(this._offset + 1); // stored in `length`
+  if (o === null)
+    return null;
+
+  this._offset = o;
+  return seq;
+};
+
+
+Reader.prototype.readInt = function() {
+  return this._readTag(ASN1.Integer);
+};
+
+
+Reader.prototype.readBoolean = function() {
+  return (this._readTag(ASN1.Boolean) === 0 ? false : true);
+};
+
+
+Reader.prototype.readEnumeration = function() {
+  return this._readTag(ASN1.Enumeration);
+};
+
+
+Reader.prototype.readString = function(tag, retbuf) {
+  if (!tag)
+    tag = ASN1.OctetString;
+
+  var b = this.peek();
+  if (b === null)
+    return null;
+
+  if (b !== tag)
+    throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
+                              ': got 0x' + b.toString(16));
+
+  var o = this.readLength(this._offset + 1); // stored in `length`
+
+  if (o === null)
+    return null;
+
+  if (this.length > this._size - o)
+    return null;
+
+  this._offset = o;
+
+  if (this.length === 0)
+    return '';
+
+  var str = this._buf.slice(this._offset, this._offset + this.length);
+  this._offset += this.length;
+
+  return retbuf ? str : str.toString('utf8');
+};
+
+Reader.prototype.readOID = function(tag) {
+  if (!tag)
+    tag = ASN1.OID;
+
+  var b = this.peek();
+  if (b === null)
+    return null;
+
+  if (b !== tag)
+    throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
+                              ': got 0x' + b.toString(16));
+
+  var o = this.readLength(this._offset + 1); // stored in `length`
+  if (o === null)
+    return null;
+
+  if (this.length > this._size - o)
+    return null;
+
+  this._offset = o;
+
+  var values = [];
+  var value = 0;
+
+  for (var i = 0; i < this.length; i++) {
+    var byte = this._buf[this._offset++] & 0xff;
+
+    value <<= 7;
+    value += byte & 0x7f;
+    if ((byte & 0x80) == 0) {
+      values.push(value);
+      value = 0;
+    }
+  }
+
+  value = values.shift();
+  values.unshift(value % 40);
+  values.unshift((value / 40) >> 0);
+
+  return values.join('.');
+};
+
+
+Reader.prototype._readTag = function(tag) {
+  assert.ok(tag !== undefined);
+
+  var b = this.peek();
+
+  if (b === null)
+    return null;
+
+  if (b !== tag)
+    throw newInvalidAsn1Error('Expected 0x' + tag.toString(16) +
+                              ': got 0x' + b.toString(16));
+
+  var o = this.readLength(this._offset + 1); // stored in `length`
+  if (o === null)
+    return null;
+
+  if (this.length > 4)
+    throw newInvalidAsn1Error('Integer too long: ' + this.length);
+
+  if (this.length > this._size - o)
+    return null;
+  this._offset = o;
+
+  var fb = this._buf[this._offset++];
+  var value = 0;
+
+  value = fb & 0x7F;
+  for (var i = 1; i < this.length; i++) {
+    value <<= 8;
+    value |= (this._buf[this._offset++] & 0xff);
+  }
+
+  if ((fb & 0x80) == 0x80)
+    value = -value;
+
+  return value;
+};
+
+
+
+///--- Exported API
+
+module.exports = Reader;
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/types.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/types.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/types.js	(revision 484)
@@ -0,0 +1,36 @@
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
+
+
+module.exports = {
+  EOC: 0,
+  Boolean: 1,
+  Integer: 2,
+  BitString: 3,
+  OctetString: 4,
+  Null: 5,
+  OID: 6,
+  ObjectDescriptor: 7,
+  External: 8,
+  Real: 9, // float
+  Enumeration: 10,
+  PDV: 11,
+  Utf8String: 12,
+  RelativeOID: 13,
+  Sequence: 16,
+  Set: 17,
+  NumericString: 18,
+  PrintableString: 19,
+  T61String: 20,
+  VideotexString: 21,
+  IA5String: 22,
+  UTCTime: 23,
+  GeneralizedTime: 24,
+  GraphicString: 25,
+  VisibleString: 26,
+  GeneralString: 28,
+  UniversalString: 29,
+  CharacterString: 30,
+  BMPString: 31,
+  Constructor: 32,
+  Context: 128
+};
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/writer.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/writer.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/ber/writer.js	(revision 484)
@@ -0,0 +1,317 @@
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
+
+var assert = require('assert');
+var ASN1 = require('./types');
+var errors = require('./errors');
+
+
+///--- Globals
+
+var newInvalidAsn1Error = errors.newInvalidAsn1Error;
+
+var DEFAULT_OPTS = {
+  size: 1024,
+  growthFactor: 8
+};
+
+
+///--- Helpers
+
+function merge(from, to) {
+  assert.ok(from);
+  assert.equal(typeof(from), 'object');
+  assert.ok(to);
+  assert.equal(typeof(to), 'object');
+
+  var keys = Object.getOwnPropertyNames(from);
+  keys.forEach(function(key) {
+    if (to[key])
+      return;
+
+    var value = Object.getOwnPropertyDescriptor(from, key);
+    Object.defineProperty(to, key, value);
+  });
+
+  return to;
+}
+
+
+
+///--- API
+
+function Writer(options) {
+  options = merge(DEFAULT_OPTS, options || {});
+
+  this._buf = new Buffer(options.size || 1024);
+  this._size = this._buf.length;
+  this._offset = 0;
+  this._options = options;
+
+  // A list of offsets in the buffer where we need to insert
+  // sequence tag/len pairs.
+  this._seq = [];
+
+  var self = this;
+  this.__defineGetter__('buffer', function() {
+    if (self._seq.length)
+      throw new InvalidAsn1Error(self._seq.length + ' unended sequence(s)');
+
+    return self._buf.slice(0, self._offset);
+  });
+}
+
+
+Writer.prototype.writeByte = function(b) {
+  if (typeof(b) !== 'number')
+    throw new TypeError('argument must be a Number');
+
+  this._ensure(1);
+  this._buf[this._offset++] = b;
+};
+
+
+Writer.prototype.writeInt = function(i, tag) {
+  if (typeof(i) !== 'number')
+    throw new TypeError('argument must be a Number');
+  if (typeof(tag) !== 'number')
+    tag = ASN1.Integer;
+
+  var sz = 4;
+
+  while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000)) &&
+         (sz > 1)) {
+    sz--;
+    i <<= 8;
+  }
+
+  if (sz > 4)
+    throw new InvalidAsn1Error('BER ints cannot be > 0xffffffff');
+
+  this._ensure(2 + sz);
+  this._buf[this._offset++] = tag;
+  this._buf[this._offset++] = sz;
+
+  while (sz-- > 0) {
+    this._buf[this._offset++] = ((i & 0xff000000) >> 24);
+    i <<= 8;
+  }
+
+};
+
+
+Writer.prototype.writeNull = function() {
+  this.writeByte(ASN1.Null);
+  this.writeByte(0x00);
+};
+
+
+Writer.prototype.writeEnumeration = function(i, tag) {
+  if (typeof(i) !== 'number')
+    throw new TypeError('argument must be a Number');
+  if (typeof(tag) !== 'number')
+    tag = ASN1.Enumeration;
+
+  return this.writeInt(i, tag);
+};
+
+
+Writer.prototype.writeBoolean = function(b, tag) {
+  if (typeof(b) !== 'boolean')
+    throw new TypeError('argument must be a Boolean');
+  if (typeof(tag) !== 'number')
+    tag = ASN1.Boolean;
+
+  this._ensure(3);
+  this._buf[this._offset++] = tag;
+  this._buf[this._offset++] = 0x01;
+  this._buf[this._offset++] = b ? 0xff : 0x00;
+};
+
+
+Writer.prototype.writeString = function(s, tag) {
+  if (typeof(s) !== 'string')
+    throw new TypeError('argument must be a string (was: ' + typeof(s) + ')');
+  if (typeof(tag) !== 'number')
+    tag = ASN1.OctetString;
+
+  var len = Buffer.byteLength(s);
+  this.writeByte(tag);
+  this.writeLength(len);
+  if (len) {
+    this._ensure(len);
+    this._buf.write(s, this._offset);
+    this._offset += len;
+  }
+};
+
+
+Writer.prototype.writeBuffer = function(buf, tag) {
+  if (typeof(tag) !== 'number')
+    throw new TypeError('tag must be a number');
+  if (!Buffer.isBuffer(buf))
+    throw new TypeError('argument must be a buffer');
+
+  this.writeByte(tag);
+  this.writeLength(buf.length);
+  this._ensure(buf.length);
+  buf.copy(this._buf, this._offset, 0, buf.length);
+  this._offset += buf.length;
+};
+
+
+Writer.prototype.writeStringArray = function(strings) {
+  if ((!strings instanceof Array))
+    throw new TypeError('argument must be an Array[String]');
+
+  var self = this;
+  strings.forEach(function(s) {
+    self.writeString(s);
+  });
+};
+
+// This is really to solve DER cases, but whatever for now
+Writer.prototype.writeOID = function(s, tag) {
+  if (typeof(s) !== 'string')
+    throw new TypeError('argument must be a string');
+  if (typeof(tag) !== 'number')
+    tag = ASN1.OID;
+
+  if (!/^([0-9]+\.){3,}[0-9]+$/.test(s))
+    throw new Error('argument is not a valid OID string');
+
+  function encodeOctet(bytes, octet) {
+    if (octet < 128) {
+        bytes.push(octet);
+    } else if (octet < 16384) {
+        bytes.push((octet >>> 7) | 0x80);
+        bytes.push(octet & 0x7F);
+    } else if (octet < 2097152) {
+      bytes.push((octet >>> 14) | 0x80);
+      bytes.push(((octet >>> 7) | 0x80) & 0xFF);
+      bytes.push(octet & 0x7F);
+    } else if (octet < 268435456) {
+      bytes.push((octet >>> 21) | 0x80);
+      bytes.push(((octet >>> 14) | 0x80) & 0xFF);
+      bytes.push(((octet >>> 7) | 0x80) & 0xFF);
+      bytes.push(octet & 0x7F);
+    } else {
+      bytes.push(((octet >>> 28) | 0x80) & 0xFF);
+      bytes.push(((octet >>> 21) | 0x80) & 0xFF);
+      bytes.push(((octet >>> 14) | 0x80) & 0xFF);
+      bytes.push(((octet >>> 7) | 0x80) & 0xFF);
+      bytes.push(octet & 0x7F);
+    }
+  }
+
+  var tmp = s.split('.');
+  var bytes = [];
+  bytes.push(parseInt(tmp[0], 10) * 40 + parseInt(tmp[1], 10));
+  tmp.slice(2).forEach(function(b) {
+    encodeOctet(bytes, parseInt(b, 10));
+  });
+
+  var self = this;
+  this._ensure(2 + bytes.length);
+  this.writeByte(tag);
+  this.writeLength(bytes.length);
+  bytes.forEach(function(b) {
+    self.writeByte(b);
+  });
+};
+
+
+Writer.prototype.writeLength = function(len) {
+  if (typeof(len) !== 'number')
+    throw new TypeError('argument must be a Number');
+
+  this._ensure(4);
+
+  if (len <= 0x7f) {
+    this._buf[this._offset++] = len;
+  } else if (len <= 0xff) {
+    this._buf[this._offset++] = 0x81;
+    this._buf[this._offset++] = len;
+  } else if (len <= 0xffff) {
+    this._buf[this._offset++] = 0x82;
+    this._buf[this._offset++] = len >> 8;
+    this._buf[this._offset++] = len;
+  } else if (len <= 0xffffff) {
+    this._shift(start, len, 1);
+    this._buf[this._offset++] = 0x83;
+    this._buf[this._offset++] = len >> 16;
+    this._buf[this._offset++] = len >> 8;
+    this._buf[this._offset++] = len;
+  } else {
+    throw new InvalidAsn1ERror('Length too long (> 4 bytes)');
+  }
+};
+
+Writer.prototype.startSequence = function(tag) {
+  if (typeof(tag) !== 'number')
+    tag = ASN1.Sequence | ASN1.Constructor;
+
+  this.writeByte(tag);
+  this._seq.push(this._offset);
+  this._ensure(3);
+  this._offset += 3;
+};
+
+
+Writer.prototype.endSequence = function() {
+  var seq = this._seq.pop();
+  var start = seq + 3;
+  var len = this._offset - start;
+
+  if (len <= 0x7f) {
+    this._shift(start, len, -2);
+    this._buf[seq] = len;
+  } else if (len <= 0xff) {
+    this._shift(start, len, -1);
+    this._buf[seq] = 0x81;
+    this._buf[seq + 1] = len;
+  } else if (len <= 0xffff) {
+    this._buf[seq] = 0x82;
+    this._buf[seq + 1] = len >> 8;
+    this._buf[seq + 2] = len;
+  } else if (len <= 0xffffff) {
+    this._shift(start, len, 1);
+    this._buf[seq] = 0x83;
+    this._buf[seq + 1] = len >> 16;
+    this._buf[seq + 2] = len >> 8;
+    this._buf[seq + 3] = len;
+  } else {
+    throw new InvalidAsn1Error('Sequence too long');
+  }
+};
+
+
+Writer.prototype._shift = function(start, len, shift) {
+  assert.ok(start !== undefined);
+  assert.ok(len !== undefined);
+  assert.ok(shift);
+
+  this._buf.copy(this._buf, start + shift, start, start + len);
+  this._offset += shift;
+};
+
+Writer.prototype._ensure = function(len) {
+  assert.ok(len);
+
+  if (this._size - this._offset < len) {
+    var sz = this._size * this._options.growthFactor;
+    if (sz - this._offset < len)
+      sz += len;
+
+    var buf = new Buffer(sz);
+
+    this._buf.copy(buf, 0, 0, this._offset);
+    this._buf = buf;
+    this._size = sz;
+  }
+};
+
+
+
+///--- Exported API
+
+module.exports = Writer;
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/lib/index.js	(revision 484)
@@ -0,0 +1,20 @@
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
+
+// If you have no idea what ASN.1 or BER is, see this:
+// ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
+
+var Ber = require('./ber/index');
+
+
+
+///--- Exported API
+
+module.exports = {
+
+  Ber: Ber,
+
+  BerReader: Ber.Reader,
+
+  BerWriter: Ber.Writer
+
+};
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/package.json	(revision 484)
@@ -0,0 +1,43 @@
+{
+  "author": {
+    "name": "Mark Cavage",
+    "email": "mcavage@gmail.com"
+  },
+  "contributors": [
+    {
+      "name": "David Gwynne",
+      "email": "loki@animata.net"
+    },
+    {
+      "name": "Yunong Xiao",
+      "email": "yunong@joyent.com"
+    }
+  ],
+  "name": "asn1",
+  "description": "Contains parsers and serializers for ASN.1 (currently BER only)",
+  "version": "0.1.11",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mcavage/node-asn1.git"
+  },
+  "main": "lib/index.js",
+  "engines": {
+    "node": ">=0.4.9"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "tap": "0.1.4"
+  },
+  "scripts": {
+    "pretest": "which gjslint; if [[ \"$?\" = 0 ]] ; then  gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi",
+    "test": "./node_modules/.bin/tap ./tst"
+  },
+  "readme": "node-asn1 is a library for encoding and decoding ASN.1 datatypes in pure JS.\nCurrently BER encoding is supported; at some point I'll likely have to do DER.\n\n## Usage\n\nMostly, if you're *actually* needing to read and write ASN.1, you probably don't\nneed this readme to explain what and why.  If you have no idea what ASN.1 is,\nsee this: ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc\n\nThe source is pretty much self-explanatory, and has read/write methods for the\ncommon types out there.\n\n### Decoding\n\nThe following reads an ASN.1 sequence with a boolean.\n\n    var Ber = require('asn1').Ber;\n\n    var reader = new Ber.Reader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff]));\n\n    reader.readSequence();\n    console.log('Sequence len: ' + reader.length);\n    if (reader.peek() === Ber.Boolean)\n      console.log(reader.readBoolean());\n\n### Encoding\n\nThe following generates the same payload as above.\n\n    var Ber = require('asn1').Ber;\n\n    var writer = new Ber.Writer();\n\n    writer.startSequence();\n    writer.writeBoolean(true);\n    writer.endSequence();\n\n    console.log(writer.buffer);\n\n## Installation\n\n    npm install asn1\n\n## License\n\nMIT.\n\n## Bugs\n\nSee <https://github.com/mcavage/node-asn1/issues>.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/mcavage/node-asn1/issues"
+  },
+  "homepage": "https://github.com/mcavage/node-asn1",
+  "_id": "asn1@0.1.11",
+  "_from": "asn1@0.1.11"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/reader.test.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/reader.test.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/reader.test.js	(revision 484)
@@ -0,0 +1,172 @@
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
+
+var test = require('tap').test;
+
+
+
+///--- Globals
+
+var BerReader;
+
+
+
+///--- Tests
+
+test('load library', function(t) {
+  BerReader = require('../../lib/index').BerReader;
+  t.ok(BerReader);
+  try {
+    new BerReader();
+    t.fail('Should have thrown');
+  } catch (e) {
+    t.ok(e instanceof TypeError, 'Should have been a type error');
+  }
+  t.end();
+});
+
+
+test('read byte', function(t) {
+  var reader = new BerReader(new Buffer([0xde]));
+  t.ok(reader);
+  t.equal(reader.readByte(), 0xde, 'wrong value');
+  t.end();
+});
+
+
+test('read 1 byte int', function(t) {
+  var reader = new BerReader(new Buffer([0x02, 0x01, 0x03]));
+  t.ok(reader);
+  t.equal(reader.readInt(), 0x03, 'wrong value');
+  t.equal(reader.length, 0x01, 'wrong length');
+  t.end();
+});
+
+
+test('read 2 byte int', function(t) {
+  var reader = new BerReader(new Buffer([0x02, 0x02, 0x7e, 0xde]));
+  t.ok(reader);
+  t.equal(reader.readInt(), 0x7ede, 'wrong value');
+  t.equal(reader.length, 0x02, 'wrong length');
+  t.end();
+});
+
+
+test('read 3 byte int', function(t) {
+  var reader = new BerReader(new Buffer([0x02, 0x03, 0x7e, 0xde, 0x03]));
+  t.ok(reader);
+  t.equal(reader.readInt(), 0x7ede03, 'wrong value');
+  t.equal(reader.length, 0x03, 'wrong length');
+  t.end();
+});
+
+
+test('read 4 byte int', function(t) {
+  var reader = new BerReader(new Buffer([0x02, 0x04, 0x7e, 0xde, 0x03, 0x01]));
+  t.ok(reader);
+  t.equal(reader.readInt(), 0x7ede0301, 'wrong value');
+  t.equal(reader.length, 0x04, 'wrong length');
+  t.end();
+});
+
+
+test('read boolean true', function(t) {
+  var reader = new BerReader(new Buffer([0x01, 0x01, 0xff]));
+  t.ok(reader);
+  t.equal(reader.readBoolean(), true, 'wrong value');
+  t.equal(reader.length, 0x01, 'wrong length');
+  t.end();
+});
+
+
+test('read boolean false', function(t) {
+  var reader = new BerReader(new Buffer([0x01, 0x01, 0x00]));
+  t.ok(reader);
+  t.equal(reader.readBoolean(), false, 'wrong value');
+  t.equal(reader.length, 0x01, 'wrong length');
+  t.end();
+});
+
+
+test('read enumeration', function(t) {
+  var reader = new BerReader(new Buffer([0x0a, 0x01, 0x20]));
+  t.ok(reader);
+  t.equal(reader.readEnumeration(), 0x20, 'wrong value');
+  t.equal(reader.length, 0x01, 'wrong length');
+  t.end();
+});
+
+
+test('read string', function(t) {
+  var dn = 'cn=foo,ou=unit,o=test';
+  var buf = new Buffer(dn.length + 2);
+  buf[0] = 0x04;
+  buf[1] = Buffer.byteLength(dn);
+  buf.write(dn, 2);
+  var reader = new BerReader(buf);
+  t.ok(reader);
+  t.equal(reader.readString(), dn, 'wrong value');
+  t.equal(reader.length, dn.length, 'wrong length');
+  t.end();
+});
+
+
+test('read sequence', function(t) {
+  var reader = new BerReader(new Buffer([0x30, 0x03, 0x01, 0x01, 0xff]));
+  t.ok(reader);
+  t.equal(reader.readSequence(), 0x30, 'wrong value');
+  t.equal(reader.length, 0x03, 'wrong length');
+  t.equal(reader.readBoolean(), true, 'wrong value');
+  t.equal(reader.length, 0x01, 'wrong length');
+  t.end();
+});
+
+
+test('anonymous LDAPv3 bind', function(t) {
+  var BIND = new Buffer(14);
+  BIND[0] = 0x30;  // Sequence
+  BIND[1] = 12;    // len
+  BIND[2] = 0x02;  // ASN.1 Integer
+  BIND[3] = 1;     // len
+  BIND[4] = 0x04;  // msgid (make up 4)
+  BIND[5] = 0x60;  // Bind Request
+  BIND[6] = 7;     // len
+  BIND[7] = 0x02;  // ASN.1 Integer
+  BIND[8] = 1;     // len
+  BIND[9] = 0x03;  // v3
+  BIND[10] = 0x04; // String (bind dn)
+  BIND[11] = 0;    // len
+  BIND[12] = 0x80; // ContextSpecific (choice)
+  BIND[13] = 0;    // simple bind
+
+  // Start testing ^^
+  var ber = new BerReader(BIND);
+  t.equal(ber.readSequence(), 48, 'Not an ASN.1 Sequence');
+  t.equal(ber.length, 12, 'Message length should be 12');
+  t.equal(ber.readInt(), 4, 'Message id should have been 4');
+  t.equal(ber.readSequence(), 96, 'Bind Request should have been 96');
+  t.equal(ber.length, 7, 'Bind length should have been 7');
+  t.equal(ber.readInt(), 3, 'LDAP version should have been 3');
+  t.equal(ber.readString(), '', 'Bind DN should have been empty');
+  t.equal(ber.length, 0, 'string length should have been 0');
+  t.equal(ber.readByte(), 0x80, 'Should have been ContextSpecific (choice)');
+  t.equal(ber.readByte(), 0, 'Should have been simple bind');
+  t.equal(null, ber.readByte(), 'Should be out of data');
+  t.end();
+});
+
+
+test('long string', function(t) {
+  var buf = new Buffer(256);
+  var o;
+  var s =
+    '2;649;CN=Red Hat CS 71GA Demo,O=Red Hat CS 71GA Demo,C=US;' +
+    'CN=RHCS Agent - admin01,UID=admin01,O=redhat,C=US [1] This is ' +
+    'Teena Vradmin\'s description.';
+  buf[0] = 0x04;
+  buf[1] = 0x81;
+  buf[2] = 0x94;
+  buf.write(s, 3);
+  var ber = new BerReader(buf.slice(0, 3 + s.length));
+  t.equal(ber.readString(), s);
+  t.end();
+});
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/writer.test.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/writer.test.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/asn1/tst/ber/writer.test.js	(revision 484)
@@ -0,0 +1,296 @@
+// Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved.
+
+var test = require('tap').test;
+var sys = require('sys');
+
+///--- Globals
+
+var BerWriter;
+
+var BerReader;
+
+
+///--- Tests
+
+test('load library', function(t) {
+  BerWriter = require('../../lib/index').BerWriter;
+  t.ok(BerWriter);
+  t.ok(new BerWriter());
+  t.end();
+});
+
+
+test('write byte', function(t) {
+  var writer = new BerWriter();
+
+  writer.writeByte(0xC2);
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 1, 'Wrong length');
+  t.equal(ber[0], 0xC2, 'value wrong');
+
+  t.end();
+});
+
+
+test('write 1 byte int', function(t) {
+  var writer = new BerWriter();
+
+  writer.writeInt(0x7f);
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 3, 'Wrong length for an int: ' + ber.length);
+  t.equal(ber[0], 0x02, 'ASN.1 tag wrong (2) -> ' + ber[0]);
+  t.equal(ber[1], 0x01, 'length wrong(1) -> ' + ber[1]);
+  t.equal(ber[2], 0x7f, 'value wrong(3) -> ' + ber[2]);
+
+  t.end();
+});
+
+
+test('write 2 byte int', function(t) {
+  var writer = new BerWriter();
+
+  writer.writeInt(0x7ffe);
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 4, 'Wrong length for an int');
+  t.equal(ber[0], 0x02, 'ASN.1 tag wrong');
+  t.equal(ber[1], 0x02, 'length wrong');
+  t.equal(ber[2], 0x7f, 'value wrong (byte 1)');
+  t.equal(ber[3], 0xfe, 'value wrong (byte 2)');
+
+  t.end();
+});
+
+
+test('write 3 byte int', function(t) {
+  var writer = new BerWriter();
+
+  writer.writeInt(0x7ffffe);
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 5, 'Wrong length for an int');
+  t.equal(ber[0], 0x02, 'ASN.1 tag wrong');
+  t.equal(ber[1], 0x03, 'length wrong');
+  t.equal(ber[2], 0x7f, 'value wrong (byte 1)');
+  t.equal(ber[3], 0xff, 'value wrong (byte 2)');
+  t.equal(ber[4], 0xfe, 'value wrong (byte 3)');
+
+  t.end();
+});
+
+
+test('write 4 byte int', function(t) {
+  var writer = new BerWriter();
+
+  writer.writeInt(0x7ffffffe);
+  var ber = writer.buffer;
+
+  t.ok(ber);
+
+  t.equal(ber.length, 6, 'Wrong length for an int');
+  t.equal(ber[0], 0x02, 'ASN.1 tag wrong');
+  t.equal(ber[1], 0x04, 'length wrong');
+  t.equal(ber[2], 0x7f, 'value wrong (byte 1)');
+  t.equal(ber[3], 0xff, 'value wrong (byte 2)');
+  t.equal(ber[4], 0xff, 'value wrong (byte 3)');
+  t.equal(ber[5], 0xfe, 'value wrong (byte 4)');
+
+  t.end();
+});
+
+
+test('write boolean', function(t) {
+  var writer = new BerWriter();
+
+  writer.writeBoolean(true);
+  writer.writeBoolean(false);
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 6, 'Wrong length');
+  t.equal(ber[0], 0x01, 'tag wrong');
+  t.equal(ber[1], 0x01, 'length wrong');
+  t.equal(ber[2], 0xff, 'value wrong');
+  t.equal(ber[3], 0x01, 'tag wrong');
+  t.equal(ber[4], 0x01, 'length wrong');
+  t.equal(ber[5], 0x00, 'value wrong');
+
+  t.end();
+});
+
+
+test('write string', function(t) {
+  var writer = new BerWriter();
+  writer.writeString('hello world');
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 13, 'wrong length');
+  t.equal(ber[0], 0x04, 'wrong tag');
+  t.equal(ber[1], 11, 'wrong length');
+  t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value');
+
+  t.end();
+});
+
+test('write buffer', function(t) {
+  var writer = new BerWriter();
+  // write some stuff to start with
+  writer.writeString('hello world');
+  var ber = writer.buffer;
+  var buf = new Buffer([0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01,
+     0xff, 0x01, 0x01, 0xff]);
+  writer.writeBuffer(buf.slice(2, buf.length), 0x04);
+  ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 26, 'wrong length');
+  t.equal(ber[0], 0x04, 'wrong tag');
+  t.equal(ber[1], 11, 'wrong length');
+  t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value');
+  t.equal(ber[13], buf[0], 'wrong tag');
+  t.equal(ber[14], buf[1], 'wrong length');
+  for (var i = 13, j = 0; i < ber.length && j < buf.length; i++, j++) {
+    t.equal(ber[i], buf[j], 'buffer contents not identical');
+  }
+  t.end();
+});
+
+test('write string array', function(t) {
+  var writer = new BerWriter();
+  writer.writeStringArray(['hello world', 'fubar!']);
+  var ber = writer.buffer;
+
+  t.ok(ber);
+
+  t.equal(ber.length, 21, 'wrong length');
+  t.equal(ber[0], 0x04, 'wrong tag');
+  t.equal(ber[1], 11, 'wrong length');
+  t.equal(ber.slice(2, 13).toString('utf8'), 'hello world', 'wrong value');
+
+  t.equal(ber[13], 0x04, 'wrong tag');
+  t.equal(ber[14], 6, 'wrong length');
+  t.equal(ber.slice(15).toString('utf8'), 'fubar!', 'wrong value');
+
+  t.end();
+});
+
+
+test('resize internal buffer', function(t) {
+  var writer = new BerWriter({size: 2});
+  writer.writeString('hello world');
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 13, 'wrong length');
+  t.equal(ber[0], 0x04, 'wrong tag');
+  t.equal(ber[1], 11, 'wrong length');
+  t.equal(ber.slice(2).toString('utf8'), 'hello world', 'wrong value');
+
+  t.end();
+});
+
+
+test('sequence', function(t) {
+  var writer = new BerWriter({size: 25});
+  writer.startSequence();
+  writer.writeString('hello world');
+  writer.endSequence();
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  console.log(ber);
+  t.equal(ber.length, 15, 'wrong length');
+  t.equal(ber[0], 0x30, 'wrong tag');
+  t.equal(ber[1], 13, 'wrong length');
+  t.equal(ber[2], 0x04, 'wrong tag');
+  t.equal(ber[3], 11, 'wrong length');
+  t.equal(ber.slice(4).toString('utf8'), 'hello world', 'wrong value');
+
+  t.end();
+});
+
+
+test('nested sequence', function(t) {
+  var writer = new BerWriter({size: 25});
+  writer.startSequence();
+  writer.writeString('hello world');
+  writer.startSequence();
+  writer.writeString('hello world');
+  writer.endSequence();
+  writer.endSequence();
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 30, 'wrong length');
+  t.equal(ber[0], 0x30, 'wrong tag');
+  t.equal(ber[1], 28, 'wrong length');
+  t.equal(ber[2], 0x04, 'wrong tag');
+  t.equal(ber[3], 11, 'wrong length');
+  t.equal(ber.slice(4, 15).toString('utf8'), 'hello world', 'wrong value');
+  t.equal(ber[15], 0x30, 'wrong tag');
+  t.equal(ber[16], 13, 'wrong length');
+  t.equal(ber[17], 0x04, 'wrong tag');
+  t.equal(ber[18], 11, 'wrong length');
+  t.equal(ber.slice(19, 30).toString('utf8'), 'hello world', 'wrong value');
+
+  t.end();
+});
+
+
+test('LDAP bind message', function(t) {
+  var dn = 'cn=foo,ou=unit,o=test';
+  var writer = new BerWriter();
+  writer.startSequence();
+  writer.writeInt(3);             // msgid = 3
+  writer.startSequence(0x60);     // ldap bind
+  writer.writeInt(3);             // ldap v3
+  writer.writeString(dn);
+  writer.writeByte(0x80);
+  writer.writeByte(0x00);
+  writer.endSequence();
+  writer.endSequence();
+  var ber = writer.buffer;
+
+  t.ok(ber);
+  t.equal(ber.length, 35, 'wrong length (buffer)');
+  t.equal(ber[0], 0x30, 'wrong tag');
+  t.equal(ber[1], 33, 'wrong length');
+  t.equal(ber[2], 0x02, 'wrong tag');
+  t.equal(ber[3], 1, 'wrong length');
+  t.equal(ber[4], 0x03, 'wrong value');
+  t.equal(ber[5], 0x60, 'wrong tag');
+  t.equal(ber[6], 28, 'wrong length');
+  t.equal(ber[7], 0x02, 'wrong tag');
+  t.equal(ber[8], 1, 'wrong length');
+  t.equal(ber[9], 0x03, 'wrong value');
+  t.equal(ber[10], 0x04, 'wrong tag');
+  t.equal(ber[11], dn.length, 'wrong length');
+  t.equal(ber.slice(12, 33).toString('utf8'), dn, 'wrong value');
+  t.equal(ber[33], 0x80, 'wrong tag');
+  t.equal(ber[34], 0x00, 'wrong len');
+
+  t.end();
+});
+
+
+test('Write OID', function(t) {
+  var oid = '1.2.840.113549.1.1.1';
+  var writer = new BerWriter();
+  writer.writeOID(oid);
+
+  var ber = writer.buffer;
+  t.ok(ber);
+  console.log(require('util').inspect(ber));
+  console.log(require('util').inspect(new Buffer([0x06, 0x09, 0x2a, 0x86,
+                                                  0x48, 0x86, 0xf7, 0x0d,
+                                                  0x01, 0x01, 0x01])));
+
+  t.end();
+});
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/assert-plus/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/assert-plus/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/assert-plus/README.md	(revision 484)
@@ -0,0 +1,126 @@
+# node-assert-plus
+
+This library is a super small wrapper over node's assert module that has two
+things: (1) the ability to disable assertions with the environment variable
+NODE_NDEBUG, and (2) some API wrappers for argument testing.  Like
+`assert.string(myArg, 'myArg')`.  As a simple example, most of my code looks
+like this:
+
+    var assert = require('assert-plus');
+
+    function fooAccount(options, callback) {
+	    assert.object(options, 'options');
+		assert.number(options.id, 'options.id);
+		assert.bool(options.isManager, 'options.isManager');
+		assert.string(options.name, 'options.name');
+		assert.arrayOfString(options.email, 'options.email');
+		assert.func(callback, 'callback');
+
+        // Do stuff
+		callback(null, {});
+    }
+
+# API
+
+All methods that *aren't* part of node's core assert API are simply assumed to
+take an argument, and then a string 'name' that's not a message; `AssertionError`
+will be thrown if the assertion fails with a message like:
+
+    AssertionError: foo (string) is required
+	at test (/home/mark/work/foo/foo.js:3:9)
+	at Object.<anonymous> (/home/mark/work/foo/foo.js:15:1)
+	at Module._compile (module.js:446:26)
+	at Object..js (module.js:464:10)
+	at Module.load (module.js:353:31)
+	at Function._load (module.js:311:12)
+	at Array.0 (module.js:484:10)
+	at EventEmitter._tickCallback (node.js:190:38)
+
+from:
+
+    function test(foo) {
+	    assert.string(foo, 'foo');
+    }
+
+There you go.  You can check that arrays are of a homogenous type with `Arrayof$Type`:
+
+    function test(foo) {
+	    assert.arrayOfString(foo, 'foo');
+    }
+
+You can assert IFF an argument is not `undefined` (i.e., an optional arg):
+
+    assert.optionalString(foo, 'foo');
+
+Lastly, you can opt-out of assertion checking altogether by setting the
+environment variable `NODE_NDEBUG=1`.  This is pseudo-useful if you have
+lots of assertions, and don't want to pay `typeof ()` taxes to v8 in
+production.
+
+The complete list of APIs is:
+
+* assert.bool
+* assert.buffer
+* assert.func
+* assert.number
+* assert.object
+* assert.string
+* assert.arrayOfBool
+* assert.arrayOfFunc
+* assert.arrayOfNumber
+* assert.arrayOfObject
+* assert.arrayOfString
+* assert.optionalBool
+* assert.optionalBuffer
+* assert.optionalFunc
+* assert.optionalNumber
+* assert.optionalObject
+* assert.optionalString
+* assert.optionalArrayOfBool
+* assert.optionalArrayOfFunc
+* assert.optionalArrayOfNumber
+* assert.optionalArrayOfObject
+* assert.optionalArrayOfString
+* assert.AssertionError
+* assert.fail
+* assert.ok
+* assert.equal
+* assert.notEqual
+* assert.deepEqual
+* assert.notDeepEqual
+* assert.strictEqual
+* assert.notStrictEqual
+* assert.throws
+* assert.doesNotThrow
+* assert.ifError
+
+# Installation
+
+    npm install assert-plus
+
+## License
+
+The MIT License (MIT)
+Copyright (c) 2012 Mark Cavage
+
+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.
+
+## Bugs
+
+See <https://github.com/mcavage/node-assert-plus/issues>.
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/assert-plus/assert.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/assert-plus/assert.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/assert-plus/assert.js	(revision 484)
@@ -0,0 +1,196 @@
+// Copyright (c) 2012, Mark Cavage. All rights reserved.
+
+var assert = require('assert');
+var Stream = require('stream').Stream;
+var util = require('util');
+
+
+
+///--- Globals
+
+var NDEBUG = process.env.NODE_NDEBUG || false;
+
+
+
+///--- Messages
+
+var ARRAY_TYPE_REQUIRED = '%s ([%s]) required';
+var TYPE_REQUIRED = '%s (%s) is required';
+
+
+
+///--- Internal
+
+function capitalize(str) {
+        return (str.charAt(0).toUpperCase() + str.slice(1));
+}
+
+function uncapitalize(str) {
+        return (str.charAt(0).toLowerCase() + str.slice(1));
+}
+
+function _() {
+        return (util.format.apply(util, arguments));
+}
+
+
+function _assert(arg, type, name, stackFunc) {
+        if (!NDEBUG) {
+                name = name || type;
+                stackFunc = stackFunc || _assert.caller;
+                var t = typeof (arg);
+
+                if (t !== type) {
+                        throw new assert.AssertionError({
+                                message: _(TYPE_REQUIRED, name, type),
+                                actual: t,
+                                expected: type,
+                                operator: '===',
+                                stackStartFunction: stackFunc
+                        });
+                }
+        }
+}
+
+
+
+///--- API
+
+function array(arr, type, name) {
+        if (!NDEBUG) {
+                name = name || type;
+
+                if (!Array.isArray(arr)) {
+                        throw new assert.AssertionError({
+                                message: _(ARRAY_TYPE_REQUIRED, name, type),
+                                actual: typeof (arr),
+                                expected: 'array',
+                                operator: 'Array.isArray',
+                                stackStartFunction: array.caller
+                        });
+                }
+
+                for (var i = 0; i < arr.length; i++) {
+                        _assert(arr[i], type, name, array);
+                }
+        }
+}
+
+
+function bool(arg, name) {
+        _assert(arg, 'boolean', name, bool);
+}
+
+
+function buffer(arg, name) {
+        if (!Buffer.isBuffer(arg)) {
+                throw new assert.AssertionError({
+                        message: _(TYPE_REQUIRED, name, type),
+                        actual: typeof (arg),
+                        expected: 'buffer',
+                        operator: 'Buffer.isBuffer',
+                        stackStartFunction: buffer
+                });
+        }
+}
+
+
+function func(arg, name) {
+        _assert(arg, 'function', name);
+}
+
+
+function number(arg, name) {
+        _assert(arg, 'number', name);
+}
+
+
+function object(arg, name) {
+        _assert(arg, 'object', name);
+}
+
+
+function stream(arg, name) {
+        if (!(arg instanceof Stream)) {
+                throw new assert.AssertionError({
+                        message: _(TYPE_REQUIRED, name, type),
+                        actual: typeof (arg),
+                        expected: 'Stream',
+                        operator: 'instanceof',
+                        stackStartFunction: buffer
+                });
+        }
+}
+
+
+function string(arg, name) {
+        _assert(arg, 'string', name);
+}
+
+
+
+///--- Exports
+
+module.exports = {
+        bool: bool,
+        buffer: buffer,
+        func: func,
+        number: number,
+        object: object,
+        stream: stream,
+        string: string
+};
+
+
+Object.keys(module.exports).forEach(function (k) {
+        if (k === 'buffer')
+                return;
+
+        var name = 'arrayOf' + capitalize(k);
+
+        if (k === 'bool')
+                k = 'boolean';
+        if (k === 'func')
+                k = 'function';
+        module.exports[name] = function (arg, name) {
+                array(arg, k, name);
+        };
+});
+
+Object.keys(module.exports).forEach(function (k) {
+        var _name = 'optional' + capitalize(k);
+        var s = uncapitalize(k.replace('arrayOf', ''));
+        if (s === 'bool')
+                s = 'boolean';
+        if (s === 'func')
+                s = 'function';
+
+        if (k.indexOf('arrayOf') !== -1) {
+          module.exports[_name] = function (arg, name) {
+                  if (!NDEBUG && arg !== undefined) {
+                          array(arg, s, name);
+                  }
+          };
+        } else {
+          module.exports[_name] = function (arg, name) {
+                  if (!NDEBUG && arg !== undefined) {
+                          _assert(arg, s, name);
+                  }
+          };
+        }
+});
+
+
+// Reexport built-in assertions
+Object.keys(assert).forEach(function (k) {
+        if (k === 'AssertionError') {
+                module.exports[k] = assert[k];
+                return;
+        }
+
+        module.exports[k] = function () {
+                if (!NDEBUG) {
+                        assert[k].apply(assert[k], arguments);
+                }
+        };
+});
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/assert-plus/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/assert-plus/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/assert-plus/package.json	(revision 484)
@@ -0,0 +1,20 @@
+{
+  "author": {
+    "name": "Mark Cavage",
+    "email": "mcavage@gmail.com"
+  },
+  "name": "assert-plus",
+  "description": "Extra assertions on top of node's assert module",
+  "version": "0.1.2",
+  "main": "./assert.js",
+  "dependencies": {},
+  "devDependencies": {},
+  "optionalDependencies": {},
+  "engines": {
+    "node": ">=0.6"
+  },
+  "readme": "# node-assert-plus\n\nThis library is a super small wrapper over node's assert module that has two\nthings: (1) the ability to disable assertions with the environment variable\nNODE_NDEBUG, and (2) some API wrappers for argument testing.  Like\n`assert.string(myArg, 'myArg')`.  As a simple example, most of my code looks\nlike this:\n\n    var assert = require('assert-plus');\n\n    function fooAccount(options, callback) {\n\t    assert.object(options, 'options');\n\t\tassert.number(options.id, 'options.id);\n\t\tassert.bool(options.isManager, 'options.isManager');\n\t\tassert.string(options.name, 'options.name');\n\t\tassert.arrayOfString(options.email, 'options.email');\n\t\tassert.func(callback, 'callback');\n\n        // Do stuff\n\t\tcallback(null, {});\n    }\n\n# API\n\nAll methods that *aren't* part of node's core assert API are simply assumed to\ntake an argument, and then a string 'name' that's not a message; `AssertionError`\nwill be thrown if the assertion fails with a message like:\n\n    AssertionError: foo (string) is required\n\tat test (/home/mark/work/foo/foo.js:3:9)\n\tat Object.<anonymous> (/home/mark/work/foo/foo.js:15:1)\n\tat Module._compile (module.js:446:26)\n\tat Object..js (module.js:464:10)\n\tat Module.load (module.js:353:31)\n\tat Function._load (module.js:311:12)\n\tat Array.0 (module.js:484:10)\n\tat EventEmitter._tickCallback (node.js:190:38)\n\nfrom:\n\n    function test(foo) {\n\t    assert.string(foo, 'foo');\n    }\n\nThere you go.  You can check that arrays are of a homogenous type with `Arrayof$Type`:\n\n    function test(foo) {\n\t    assert.arrayOfString(foo, 'foo');\n    }\n\nYou can assert IFF an argument is not `undefined` (i.e., an optional arg):\n\n    assert.optionalString(foo, 'foo');\n\nLastly, you can opt-out of assertion checking altogether by setting the\nenvironment variable `NODE_NDEBUG=1`.  This is pseudo-useful if you have\nlots of assertions, and don't want to pay `typeof ()` taxes to v8 in\nproduction.\n\nThe complete list of APIs is:\n\n* assert.bool\n* assert.buffer\n* assert.func\n* assert.number\n* assert.object\n* assert.string\n* assert.arrayOfBool\n* assert.arrayOfFunc\n* assert.arrayOfNumber\n* assert.arrayOfObject\n* assert.arrayOfString\n* assert.optionalBool\n* assert.optionalBuffer\n* assert.optionalFunc\n* assert.optionalNumber\n* assert.optionalObject\n* assert.optionalString\n* assert.optionalArrayOfBool\n* assert.optionalArrayOfFunc\n* assert.optionalArrayOfNumber\n* assert.optionalArrayOfObject\n* assert.optionalArrayOfString\n* assert.AssertionError\n* assert.fail\n* assert.ok\n* assert.equal\n* assert.notEqual\n* assert.deepEqual\n* assert.notDeepEqual\n* assert.strictEqual\n* assert.notStrictEqual\n* assert.throws\n* assert.doesNotThrow\n* assert.ifError\n\n# Installation\n\n    npm install assert-plus\n\n## License\n\nThe MIT License (MIT)\nCopyright (c) 2012 Mark Cavage\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n## Bugs\n\nSee <https://github.com/mcavage/node-assert-plus/issues>.\n",
+  "readmeFilename": "README.md",
+  "_id": "assert-plus@0.1.2",
+  "_from": "assert-plus@0.1.2"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/CHANGELOG
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/CHANGELOG	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/CHANGELOG	(revision 484)
@@ -0,0 +1,71 @@
+This contains tickets fixed in each version release in reverse chronological
+order. There is one ticket per line. Each commits message has the tickets fixed
+in it. The commit message also has the corresponding github issue. i.e. CTYPE-42
+would be issue 42. Each issue can be found at:
+https://github.com/rmustacc/node-ctype/issues/%d.
+
+CTYPE v0.5.2
+CTYPE-46 Release 0.5.2
+CTYPE-45 error in setEndian logic
+
+v0.5.1
+CTYPE-44 Release 0.5.1
+Contributed by Terin Stock:
+CTYPE-41 CTypeParser.writeStruct should return its offset
+Contributed by Terin Stock:
+CTYPE-42 int64_t returns wrong size
+
+v0.5.0
+CTYPE-40 Release 0.5.0
+CTYPE-39 want > 0.6 engine support
+
+v0.4.0
+CTYPE-37 Release v0.4.0
+CTYPE-6 want additional entry point for write
+CTYPE-20 Add 64-bit int support into core parser
+CTYPE-31 Fix bounds errors node/2129
+CTYPE-33 Update copyright holders
+CTYPE-34 ctf.js confuses sign bit.
+CTYPE-35 Make the README more useful for getting started
+CTYPE-36 want manual page on ctio functions
+
+v0.3.1
+CTYPE-29 Release 0.3.1
+CTYPE-28 Want v0.6 npm support
+
+v0.3.0
+CTYPE-27 Release v0.3.0
+CTYPE-26 Want alternate default char behavior
+
+v0.2.1
+CTYPE-25 Release v0.2.1
+CTYPE-24 Writing structs is busted
+
+v0.2.0:
+CTYPE-23 Release v0.2.0
+CTYPE-21 Add support for CTF JSON data
+CTYPE-22 Add Javascriptlint profile
+CTYPE-15 Pull in ctio updates from node/master
+
+v0.1.0:
+CTYPE-18 Bump version to v0.1.0
+CTYPE-17 Fix nested structures
+CTYPE-16 Remove extraneous logging
+CTYPE-14 toAbs64 and toApprox64 are not exported
+
+v0.0.3:
+CTYPE-12 Bump version to v0.0.3
+CTYPE-11 fix typo in wuint64
+CTYPE-10 Integrate jsstyle
+
+v0.0.2:
+CTYPE-8 dump npm version to v0.0.2
+CTYPE-9 want changelog
+CTYPE-7 fix typo in detypes.
+
+v0.0.1:
+CTYPE-5 Missing from NPM registry
+CTYPE-4 int16_t calls wrong read function
+CTYPE-3 API example types are missing quotes as strings
+CTYPE-2 doc missing 64-bit functions
+CTYPE-1 Need license
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/LICENSE	(revision 484)
@@ -0,0 +1,24 @@
+The following license applies to all files unless the file is specified below.
+Each file specified below has its license information embedded in it:
+
+tools/jsstyle
+
+Copyright 2011, Robert Mustacchi. All rights reserved.
+Copyright 2011, Joyent, Inc. All rights reserved.
+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.
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/README
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/README	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/README	(revision 484)
@@ -0,0 +1,82 @@
+Node-CType is a way to read and write binary data in structured and easy to use
+format. Its name comes from the C header file.
+
+To get started, simply clone the repository or use npm to install it. Once it is
+there, simply require it.
+
+git clone git://github.com/rmustacc/node-ctype
+npm install ctype
+var mod_ctype = require('ctype')
+
+
+There are two APIs that you can use, depending on what abstraction you'd like.
+The low level API let's you read and write individual integers and floats from
+buffers. The higher level API let's you read and write structures of these. To
+illustrate this, let's looks look at how we would read and write a binary
+encoded x,y point.
+
+In C we would define this structure as follows:
+
+typedef struct point {
+	uint16_t	p_x;
+	uint16_t	p_y;
+} point_t;
+
+To read a binary encoded point from a Buffer, we first need to create a CType
+parser (where we specify the endian and other options) and add the typedef.
+
+var parser = new mod_ctype.Parser({ endian: 'big' });
+parser.typedef('point_t', [
+	{ x: { type: 'uint16_t' } },
+	{ y: { type: 'uint16_t' } }
+]);
+
+From here, given a buffer buf and an offset into it, we can read a point.
+
+var out = parser.readData([ { point: { type: 'point_t' } } ], buffer, 0);
+console.log(out);
+{ point: { x: 23, y: 42 } }
+
+Another way to get the same information would be to use the low level methods.
+Note that these require you to manually deal with the offset. Here's how we'd
+get the same values of x and y from the buffer.
+
+var x = mod_ctype.ruint16(buf, 'big', 0);
+var y = mod_ctype.ruint16(buf, 'big', 2);
+console.log(x + ', ' + y);
+23, 42
+
+The true power of this API comes from the ability to define and nest typedefs,
+just as you would in C. By default, the following types are defined by default.
+Note that they return a Number, unless indicated otherwise.
+
+    * int8_t
+    * int16_t
+    * int32_t
+    * int64_t (returns an array where val[0] << 32 + val[1] would be the value)
+    * uint8_t
+    * uint16_t
+    * uint32_t
+    * uint64_t (returns an array where val[0] << 32 + val[1] would be the value)
+    * float
+    * double
+    * char (either returns a buffer with that character or a uint8_t)
+    * char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0)
+
+
+ctf2json integration:
+
+Node-CType supports consuming the output of ctf2json. Once you read in a JSON file,
+all you have to do to add all the definitions it contains is:
+
+var data, parser;
+data = JSON.parse(parsedJSONData);
+parser = mod_ctype.parseCTF(data, { endian: 'big' });
+
+For more documentation, see the file README.old. Full documentation is in the
+process of being rewritten as a series of manual pages which will be available
+in the repository and online for viewing.
+
+To read the ctio manual page simple run, from the root of the workspace:
+
+man -Mman -s 3ctype ctio
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/README.old
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/README.old	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/README.old	(revision 484)
@@ -0,0 +1,298 @@
+This library provides a way to read and write binary data.
+
+Node CType is a way to read and write binary data in structured and easy to use
+formats. It's name comes from the header file, though it does not share as much
+with it as it perhaps should.
+
+There are two levels of the API. One is the raw API which everything is built on
+top of, while the other provides a much nicer abstraction and is built entirely
+by using the lower level API. The hope is that the low level API is both clear
+and useful. The low level API gets it's names from stdint.h (a rather
+appropriate source). The lower level API is presented at the end of this
+document.
+
+Standard CType API
+
+The CType interface is presented as a parser object that controls the
+endianness combined with a series of methods to change that value, parse and
+write out buffers, and a way to provide typedefs.  Standard Types
+
+The CType parser supports the following basic types which return Numbers except
+as indicated:
+
+    * int8_t
+    * int16_t
+    * int32_t
+    * int64_t (returns an array where val[0] << 32 + val[1] would be the value)
+    * uint8_t
+    * uint16_t
+    * uint32_t
+    * uint64_t (returns an array where val[0] << 32 + val[1] would be the value)
+    * float
+    * double
+    * char (returns a buffer with just that single character)
+    * char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0)
+
+Specifying Structs
+
+The CType parser also supports the notion of structs. A struct is an array of
+JSON objects that defines an order of keys which have types and values. One
+would build a struct to represent a point (x,y) as follows:
+
+[
+    { x: { type: 'int16_t' }},
+    { y: { type: 'int16_t' }}
+]
+
+When this is passed into the read routine, it would read the first two bytes
+(as defined by int16_t) to determine the Number to use for X, and then it would
+read the next two bytes to determine the value of Y. When read this could
+return something like:
+
+{
+    x: 42,
+    y: -23
+}
+
+When someone wants to write values, we use the same format as above, but with
+additional value field:
+
+[
+    { x: { type: 'int16_t', value: 42 }},
+    { y: { type: 'int16_t', value: -23 }}
+]
+
+Now, the structure above may be optionally annotated with offsets. This tells
+us to rather than read continuously we should read the given value at the
+specified offset. If an offset is provided, it is is effectively the equivalent
+of lseek(offset, SEEK_SET). Thus, subsequent values will be read from that
+offset and incremented by the appropriate value. As an example:
+
+[
+    { x: { type: 'int16_t' }},
+    { y: { type: 'int16_t', offset: 20 }},
+    { z: { type: 'int16_t' }}
+]
+
+We would read x from the first starting offset given to us, for the sake of
+example, let's assume that's 0. After reading x, the next offset to read from
+would be 2; however, y specifies an offset, thus we jump directly to that
+offset and read y from byte 20. We would then read z from byte 22.
+
+The same offsets may be used when writing values.
+
+Typedef
+
+The basic set of types while covers the basics, is somewhat limiting. To make
+this richer, there is functionality to typedef something like in C. One can use
+typedef to add a new name to an existing type or to define a name to refer to a
+struct. Thus the following are all examples of a typedef:
+
+typedef('size_t', 'uint32_t');
+typedef('ssize_t', 'int32_t');
+typedef('point_t', [
+    { x: { type: 'int16_t' }},
+    { y: { type: 'int16_t' }}
+]);
+
+Once something has been typedef'd it can be used in any of the definitions
+previously shown.
+
+One cannot remove a typedef once created, this is analogous to C.
+
+The set of defined types can be printed with lstypes. The format of this output
+is subject to change, but likely will look something like:
+
+> lstypes();
+{
+    size_t: 'uint32_t',
+    ssize_t: 'int32_t',
+    point_t: [
+        { x: { type: 'int16_t' }},
+        { y: { type: 'int16_t' }}
+    ]
+}
+
+Specifying arrays
+
+Arrays can be specified by appending []s to a type. Arrays must have the size
+specified. The size must be specified and it can be done in one of two ways:
+
+    * An explicit non-zero integer size
+    * A name of a previously declared variable in the struct whose value is a
+      number.
+
+Note, that when using the name of a variable, it should be the string name for
+the key. This is only valid inside structs and the value must be declared
+before the value with the array. The following are examples:
+
+[
+    { ip_addr4: { type: 'uint8_t[4]' }},
+    { len: { type: 'uint32_t' }},
+    { data: { type: 'uint8_t[len]' }}
+]
+
+Arrays are permitted in typedefs; however, they must have a declared integer
+size. The following are examples of valid and invalid arrays:
+
+typedef('path', 'char[1024]'); /* Good */
+typedef('path', 'char[len]');  /* Bad! */
+
+64 bit values:
+
+Unfortunately Javascript represents values with a double, so you lose precision
+and the ability to represent Integers roughly beyond 2^53. To alleviate this, I
+propose the following for returning 64 bit integers when read:
+
+value[2]: Each entry is a 32 bit number which can be reconstructed to the
+original by the following formula:
+
+value[0] << 32 + value[1] (Note this will not work in Javascript)
+
+CTF JSON data:
+
+node-ctype can also handle JSON data that mathces the format described in the
+documentation of the tool ctf2json. Given the JSON data which specifies type
+information, it will transform that into a parser that understands all of the
+types defined inside of it. This is useful for more complicated structures that
+have a lot of typedefs.
+
+Interface overview
+
+The following is the header-file like interface to the parser object:
+
+/*
+ * Create a new instance of the parser. Each parser has its own store of
+ * typedefs and endianness. Conf is an object with the following values:
+ *
+ *      endian          Either 'big' or 'little' do determine the endianness we
+ *                      want to read from or write to.
+ *
+ */
+function CTypeParser(conf);
+
+/*
+ * Parses the CTF JSON data and creates a parser that understands all of those
+ * types.
+ *
+ *	data		Parsed JSON data that maches that CTF JSON
+ *			specification.
+ *
+ *	conf		The configuration object to create a new CTypeParser
+ *			from.
+ */
+CTypeParser parseCTF(data, conf);
+
+/*
+ * This is what we were born to do. We read the data from a buffer and return it
+ * in an object whose keys match the values from the object.
+ *
+ *      def             The array definition of the data to read in
+ *
+ *      buffer          The buffer to read data from
+ *
+ *      offset          The offset to start writing to
+ *
+ * Returns an object where each key corresponds to an entry in def and the value
+ * is the read value.
+ */
+Object CTypeParser.readData(<Type Definition>, buffer, offset);
+
+/*
+ * This is the second half of what we were born to do, write out the data
+ * itself.
+ *
+ *      def             The array definition of the data to write out with
+ *                      values
+ *
+ *      buffer          The buffer to write to
+ *
+ *      offset          The offset in the buffer to write to
+ */
+void CTypeParser.writeData(<Type Definition>, buffer, offset);
+
+/*
+ * A user has requested to add a type, let us honor their request. Yet, if their
+ * request doth spurn us, send them unto the Hells which Dante describes.
+ *
+ *      name            The string for the type definition we're adding
+ *
+ *      value           Either a string that is a type/array name or an object
+ *                      that describes a struct.
+ */
+void CTypeParser.prototype.typedef(name, value);
+
+Object CTypeParser.prototype.lstypes();
+
+/*
+ * Get the endian value for the current parser
+ */
+String CTypeParser.prototype.getEndian();
+
+/*
+ * Sets the current endian value for the Parser. If the value is not valid,
+ * throws an Error.
+ *
+ *      endian          Either 'big' or 'little' do determine the endianness we
+ *                      want to read from or write to.
+ *
+ */
+void CTypeParser.protoype.setEndian(String);
+
+/*
+ * Attempts to convert an array of two integers returned from rsint64 / ruint64
+ * into an absolute 64 bit number. If however the value would exceed 2^52 this
+ * will instead throw an error. The mantissa in a double is a 52 bit number and
+ * rather than potentially give you a value that is an approximation this will
+ * error. If you would rather an approximation, please see toApprox64.
+ *
+ *	val		An array of two 32-bit integers
+ */
+Number function toAbs64(val)
+
+/*
+ * Will return the 64 bit value as returned in an array from rsint64 / ruint64
+ * to a value as close as it can. Note that Javascript stores all numbers as a
+ * double and the mantissa only has 52 bits. Thus this version may approximate
+ * the value.
+ *
+ *	val		An array of two 32-bit integers
+ */
+Number function toApprox64(val)
+
+Low Level API
+
+The following function are provided at the low level:
+
+Read unsigned integers from a buffer:
+Number ruint8(buffer, endian, offset);
+Number ruint16(buffer, endian, offset);
+Number ruint32(buffer, endian, offset);
+Number[] ruint64(buffer, endian, offset);
+
+Read signed integers from a buffer:
+Number rsint8(buffer, endian, offset);
+Number rsint16(buffer, endian, offset);
+Number rsint32(buffer, endian, offset);
+Number[] rsint64(buffer, endian, offset);
+
+Read floating point numbers from a buffer:
+Number rfloat(buffer, endian, offset);   /* IEEE-754 Single precision */
+Number rdouble(buffer, endian, offset);  /* IEEE-754 Double precision */
+
+Write unsigned integers to a buffer:
+void wuint8(Number, endian, buffer, offset);
+void wuint16(Number, endian, buffer, offset);
+void wuint32(Number, endian, buffer, offset);
+void wuint64(Number[], endian, buffer, offset);
+
+Write signed integers from a buffer:
+void wsint8(Number, endian, buffer, offset);
+void wsint16(Number, endian, buffer, offset);
+void wsint32(Number, endian, buffer, offset);
+void wsint64(Number[], endian, buffer offset);
+
+Write floating point numbers from a buffer:
+void wfloat(Number, buffer, endian, offset);   /* IEEE-754 Single precision */
+void wdouble(Number, buffer, endian, offset);  /* IEEE-754 Double precision */
+
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/ctf.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/ctf.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/ctf.js	(revision 484)
@@ -0,0 +1,245 @@
+/*
+ * ctf.js
+ *
+ * Understand and parse all of the different JSON formats of CTF data and
+ * translate that into a series of node-ctype friendly pieces. The reason for
+ * the abstraction is to handle different changes in the file format.
+ *
+ * We have to be careful here that we don't end up using a name that is already
+ * a built in type.
+ */
+var mod_assert = require('assert');
+var ASSERT = mod_assert.ok;
+
+var ctf_versions = [ '1.0' ];
+var ctf_entries = [ 'integer', 'float', 'typedef', 'struct' ];
+var ctf_deftypes = [ 'int8_t', 'uint8_t', 'int16_t', 'uint16_t', 'int32_t',
+    'uint32_t', 'float', 'double' ];
+
+function ctfParseInteger(entry, ctype)
+{
+	var name, sign, len, type;
+
+	name = entry['name'];
+	if (!('signed' in entry['integer']))
+		throw (new Error('Malformed CTF JSON: integer missing ' +
+		    'signed value'));
+
+
+	if (!('length' in entry['integer']))
+		throw (new Error('Malformed CTF JSON: integer missing ' +
+		    'length value'));
+
+	sign = entry['integer']['signed'];
+	len = entry['integer']['length'];
+	type = null;
+
+	if (sign && len == 1)
+		type = 'int8_t';
+	else if (len == 1)
+		type = 'uint8_t';
+	else if (sign && len == 2)
+		type = 'int16_t';
+	else if (len == 2)
+		type = 'uint16_t';
+	else if (sign && len == 4)
+		type = 'int32_t';
+	else if (len == 4)
+		type = 'uint32_t';
+	else if (sign && len == 8)
+		type = 'int64_t';
+	else if (len == 8)
+		type = 'uint64_t';
+
+	if (type === null)
+		throw (new Error('Malformed CTF JSON: integer has ' +
+		    'unsupported length and sign - ' + len + '/' + sign));
+
+	/*
+	 * This means that this is the same as one of our built in types. If
+	 * that's the case defining it would be an error. So instead of trying
+	 * to typedef it, we'll return here.
+	 */
+	if (name == type)
+		return;
+
+	if (name == 'char') {
+		ASSERT(type == 'int8_t');
+		return;
+	}
+
+	ctype.typedef(name, type);
+}
+
+function ctfParseFloat(entry, ctype)
+{
+	var name, len;
+
+	name = entry['name'];
+	if (!('length' in entry['float']))
+		throw (new Error('Malformed CTF JSON: float missing ' +
+		    'length value'));
+
+	len = entry['float']['length'];
+	if (len != 4 && len != 8)
+		throw (new Error('Malformed CTF JSON: float has invalid ' +
+		    'length value'));
+
+	if (len == 4) {
+		if (name == 'float')
+			return;
+		ctype.typedef(name, 'float');
+	} else if (len == 8) {
+		if (name == 'double')
+			return;
+		ctype.typedef(name, 'double');
+	}
+}
+
+function ctfParseTypedef(entry, ctype)
+{
+	var name, type, ii;
+
+	name = entry['name'];
+	if (typeof (entry['typedef']) != 'string')
+		throw (new Error('Malformed CTF JSON: typedef value in not ' +
+		    'a string'));
+
+	type = entry['typedef'];
+
+	/*
+	 * We need to ensure that we're not looking at type that's one of our
+	 * built in types. Traditionally in C a uint32_t would be a typedef to
+	 * some kind of integer. However, those size types are built ins.
+	 */
+	for (ii = 0; ii < ctf_deftypes.length; ii++) {
+		if (name == ctf_deftypes[ii])
+			return;
+	}
+
+	ctype.typedef(name, type);
+}
+
+function ctfParseStruct(entry, ctype)
+{
+	var name, type, ii, val, index, member, push;
+
+	member = [];
+	if (!Array.isArray(entry['struct']))
+		throw (new Error('Malformed CTF JSON: struct value is not ' +
+		    'an array'));
+
+	for (ii = 0; ii < entry['struct'].length; ii++) {
+		val = entry['struct'][ii];
+		if (!('name' in val))
+			throw (new Error('Malformed CTF JSON: struct member ' +
+			    'missing name'));
+
+		if (!('type' in val))
+			throw (new Error('Malformed CTF JSON: struct member ' +
+			    'missing type'));
+
+		if (typeof (val['name']) != 'string')
+			throw (new Error('Malformed CTF JSON: struct member ' +
+			    'name isn\'t a string'));
+
+		if (typeof (val['type']) != 'string')
+			throw (new Error('Malformed CTF JSON: struct member ' +
+			    'type isn\'t a string'));
+
+		/*
+		 * CTF version 2 specifies array names as <type> [<num>] where
+		 * as node-ctype does this as <type>[<num>].
+		 */
+		name = val['name'];
+		type = val['type'];
+		index = type.indexOf(' [');
+		if (index != -1) {
+			type = type.substring(0, index) +
+			    type.substring(index + 1, type.length);
+		}
+		push = {};
+		push[name] = { 'type': type };
+		member.push(push);
+	}
+
+	name = entry['name'];
+	ctype.typedef(name, member);
+}
+
+function ctfParseEntry(entry, ctype)
+{
+	var ii, found;
+
+	if (!('name' in entry))
+		throw (new Error('Malformed CTF JSON: entry missing "name" ' +
+		    'section'));
+
+	for (ii = 0; ii < ctf_entries.length; ii++) {
+		if (ctf_entries[ii] in entry)
+			found++;
+	}
+
+	if (found === 0)
+		throw (new Error('Malformed CTF JSON: found no entries'));
+
+	if (found >= 2)
+		throw (new Error('Malformed CTF JSON: found more than one ' +
+		    'entry'));
+
+	if ('integer' in entry) {
+		ctfParseInteger(entry, ctype);
+		return;
+	}
+
+	if ('float' in entry) {
+		ctfParseFloat(entry, ctype);
+		return;
+	}
+
+	if ('typedef' in entry) {
+		ctfParseTypedef(entry, ctype);
+		return;
+	}
+
+	if ('struct' in entry) {
+		ctfParseStruct(entry, ctype);
+		return;
+	}
+
+	ASSERT(false, 'shouldn\'t reach here');
+}
+
+function ctfParseJson(json, ctype)
+{
+	var version, ii;
+
+	ASSERT(json);
+	ASSERT(ctype);
+	if (!('metadata' in json))
+		throw (new Error('Invalid CTF JSON: missing metadata section'));
+
+	if (!('ctf2json_version' in json['metadata']))
+		throw (new Error('Invalid CTF JSON: missing ctf2json_version'));
+
+	version = json['metadata']['ctf2json_version'];
+	for (ii = 0; ii < ctf_versions.length; ii++) {
+		if (ctf_versions[ii] == version)
+			break;
+	}
+
+	if (ii == ctf_versions.length)
+		throw (new Error('Unsuported ctf2json_version: ' + version));
+
+	if (!('data' in json))
+		throw (new Error('Invalid CTF JSON: missing data section'));
+
+	if (!Array.isArray(json['data']))
+		throw (new Error('Malformed CTF JSON: data section is not ' +
+		    'an array'));
+
+	for (ii = 0; ii < json['data'].length; ii++)
+		ctfParseEntry(json['data'][ii], ctype);
+}
+
+exports.ctfParseJson = ctfParseJson;
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/ctio.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/ctio.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/ctio.js	(revision 484)
@@ -0,0 +1,1485 @@
+/*
+ * rm - Feb 2011
+ * ctio.js:
+ *
+ * A simple way to read and write simple ctypes. Of course, as you'll find the
+ * code isn't as simple as it might appear. The following types are currently
+ * supported in big and little endian formats:
+ *
+ * 	uint8_t			int8_t
+ * 	uint16_t		int16_t
+ * 	uint32_t		int32_t
+ *	float (single precision IEEE 754)
+ *	double (double precision IEEE 754)
+ *
+ * This is designed to work in Node and v8. It may in fact work in other
+ * Javascript interpreters (that'd be pretty neat), but it hasn't been tested.
+ * If you find that it does in fact work, that's pretty cool. Try and pass word
+ * back to the original author.
+ *
+ * Note to the reader: If you're tabstop isn't set to 8, parts of this may look
+ * weird.
+ */
+
+/*
+ * Numbers in Javascript have a secret: all numbers must be represented with an
+ * IEEE-754 double. The double has a mantissa with a length of 52 bits with an
+ * implicit one. Thus the range of integers that can be represented is limited
+ * to the size of the mantissa, this makes reading and writing 64-bit integers
+ * difficult, but far from impossible.
+ *
+ * Another side effect of this representation is what happens when you use the
+ * bitwise operators, i.e. shift left, shift right, and, or, etc. In Javascript,
+ * each operand and the result is cast to a signed 32-bit number. However, in
+ * the case of >>> the values are cast to an unsigned number.
+ */
+
+/*
+ * A reminder on endian related issues:
+ *
+ * Big Endian: MSB -> First byte
+ * Little Endian: MSB->Last byte
+ */
+var mod_assert = require('assert');
+
+/*
+ * An 8 bit unsigned integer involves doing no significant work.
+ */
+function ruint8(buffer, endian, offset)
+{
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	return (buffer[offset]);
+}
+
+/*
+ * For 16 bit unsigned numbers we can do all the casting that we want to do.
+ */
+function rgint16(buffer, endian, offset)
+{
+	var val = 0;
+
+	if (endian == 'big') {
+		val = buffer[offset] << 8;
+		val |=  buffer[offset+1];
+	} else {
+		val = buffer[offset];
+		val |= buffer[offset+1] << 8;
+	}
+
+	return (val);
+
+}
+
+function ruint16(buffer, endian, offset)
+{
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 1 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	return (rgint16(buffer, endian, offset));
+}
+
+/*
+ * Because most bitshifting is done using signed numbers, if we would go into
+ * the realm where we use that 32nd bit, we'll end up going into the negative
+ * range. i.e.:
+ * > 200 << 24
+ * -939524096
+ *
+ * Not the value you'd expect. To work around this, we end up having to do some
+ * abuse of the JavaScript standard. in this case, we know that a >>> shift is
+ * defined to cast our value to an *unsigned* 32-bit number. Because of that, we
+ * use that instead to save us some additional math, though it does feel a
+ * little weird and it isn't obvious as to why you woul dwant to do this at
+ * first.
+ */
+function rgint32(buffer, endian, offset)
+{
+	var val = 0;
+
+	if (endian == 'big') {
+		val = buffer[offset+1] << 16;
+		val |= buffer[offset+2] << 8;
+		val |= buffer[offset+3];
+		val = val + (buffer[offset] << 24 >>> 0);
+	} else {
+		val = buffer[offset+2] << 16;
+		val |= buffer[offset+1] << 8;
+		val |= buffer[offset];
+		val = val + (buffer[offset + 3] << 24 >>> 0);
+	}
+
+	return (val);
+}
+
+function ruint32(buffer, endian, offset)
+{
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 3 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	return (rgint32(buffer, endian, offset));
+}
+
+/*
+ * Reads a 64-bit unsigned number. The astue observer will note that this
+ * doesn't quite work. Javascript has chosen to only have numbers that can be
+ * represented by a double. A double only has 52 bits of mantissa with an
+ * implicit 1, thus we have up to 53 bits to represent an integer. However, 2^53
+ * doesn't quite give us what we want. Isn't 53 bits enough for anyone? What
+ * could you have possibly wanted to represent that was larger than that? Oh,
+ * maybe a size? You mean we bypassed the 4 GB limit on file sizes, when did
+ * that happen?
+ *
+ * To get around this egregious language issue, we're going to instead construct
+ * an array of two 32 bit unsigned integers. Where arr[0] << 32 + arr[1] would
+ * give the actual number. However, note that the above code probably won't
+ * produce the desired results because of the way Javascript numbers are
+ * doubles.
+ */
+function rgint64(buffer, endian, offset)
+{
+	var val = new Array(2);
+
+	if (endian == 'big') {
+		val[0] = ruint32(buffer, endian, offset);
+		val[1] = ruint32(buffer, endian, offset+4);
+	} else {
+		val[0] = ruint32(buffer, endian, offset+4);
+		val[1] = ruint32(buffer, endian, offset);
+	}
+
+	return (val);
+}
+
+function ruint64(buffer, endian, offset)
+{
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 7 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	return (rgint64(buffer, endian, offset));
+}
+
+
+/*
+ * Signed integer types, yay team! A reminder on how two's complement actually
+ * works. The first bit is the signed bit, i.e. tells us whether or not the
+ * number should be positive or negative. If the two's complement value is
+ * positive, then we're done, as it's equivalent to the unsigned representation.
+ *
+ * Now if the number is positive, you're pretty much done, you can just leverage
+ * the unsigned translations and return those. Unfortunately, negative numbers
+ * aren't quite that straightforward.
+ *
+ * At first glance, one might be inclined to use the traditional formula to
+ * translate binary numbers between the positive and negative values in two's
+ * complement. (Though it doesn't quite work for the most negative value)
+ * Mainly:
+ *  - invert all the bits
+ *  - add one to the result
+ *
+ * Of course, this doesn't quite work in Javascript. Take for example the value
+ * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
+ * course, Javascript will do the following:
+ *
+ * > ~0xff80
+ * -65409
+ *
+ * Whoh there, Javascript, that's not quite right. But wait, according to
+ * Javascript that's perfectly correct. When Javascript ends up seeing the
+ * constant 0xff80, it has no notion that it is actually a signed number. It
+ * assumes that we've input the unsigned value 0xff80. Thus, when it does the
+ * binary negation, it casts it into a signed value, (positive 0xff80). Then
+ * when you perform binary negation on that, it turns it into a negative number.
+ *
+ * Instead, we're going to have to use the following general formula, that works
+ * in a rather Javascript friendly way. I'm glad we don't support this kind of
+ * weird numbering scheme in the kernel.
+ *
+ * (BIT-MAX - (unsigned)val + 1) * -1
+ *
+ * The astute observer, may think that this doesn't make sense for 8-bit numbers
+ * (really it isn't necessary for them). However, when you get 16-bit numbers,
+ * you do. Let's go back to our prior example and see how this will look:
+ *
+ * (0xffff - 0xff80 + 1) * -1
+ * (0x007f + 1) * -1
+ * (0x0080) * -1
+ *
+ * Doing it this way ends up allowing us to treat it appropriately in
+ * Javascript. Sigh, that's really quite ugly for what should just be a few bit
+ * shifts, ~ and &.
+ */
+
+/*
+ * Endianness doesn't matter for 8-bit signed values. We could in fact optimize
+ * this case because the more traditional methods work, but for consistency,
+ * we'll keep doing this the same way.
+ */
+function rsint8(buffer, endian, offset)
+{
+	var neg;
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	neg = buffer[offset] & 0x80;
+	if (!neg)
+		return (buffer[offset]);
+
+	return ((0xff - buffer[offset] + 1) * -1);
+}
+
+/*
+ * The 16-bit version requires a bit more effort. In this case, we can leverage
+ * our unsigned code to generate the value we want to return.
+ */
+function rsint16(buffer, endian, offset)
+{
+	var neg, val;
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 1 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	val = rgint16(buffer, endian, offset);
+	neg = val & 0x8000;
+	if (!neg)
+		return (val);
+
+	return ((0xffff - val + 1) * -1);
+}
+
+/*
+ * We really shouldn't leverage our 32-bit code here and instead utilize the
+ * fact that we know that since these are signed numbers, we can do all the
+ * shifting and binary anding to generate the 32-bit number. But, for
+ * consistency we'll do the same. If we want to do otherwise, we should instead
+ * make the 32 bit unsigned code do the optimization. But as long as there
+ * aren't floats secretly under the hood for that, we /should/ be okay.
+ */
+function rsint32(buffer, endian, offset)
+{
+	var neg, val;
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 3 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	val = rgint32(buffer, endian, offset);
+	neg = val & 0x80000000;
+	if (!neg)
+		return (val);
+
+	return ((0xffffffff - val + 1) * -1);
+}
+
+/*
+ * The signed version of this code suffers from all of the same problems of the
+ * other 64 bit version.
+ */
+function rsint64(buffer, endian, offset)
+{
+	var neg, val;
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 3 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	val = rgint64(buffer, endian, offset);
+	neg = val[0] & 0x80000000;
+
+	if (!neg)
+		return (val);
+
+	val[0] = (0xffffffff - val[0]) * -1;
+	val[1] = (0xffffffff - val[1] + 1) * -1;
+
+	/*
+	 * If we had the key 0x8000000000000000, that would leave the lower 32
+	 * bits as 0xffffffff, however, since we're goint to add one, that would
+	 * actually leave the lower 32-bits as 0x100000000, which would break
+	 * our ability to write back a value that we received. To work around
+	 * this, if we actually get that value, we're going to bump the upper
+	 * portion by 1 and set this to zero.
+	 */
+	mod_assert.ok(val[1] <= 0x100000000);
+	if (val[1] == -0x100000000) {
+		val[1] = 0;
+		val[0]--;
+	}
+
+	return (val);
+}
+
+/*
+ * We now move onto IEEE 754: The traditional form for floating point numbers
+ * and what is secretly hiding at the heart of everything in this. I really hope
+ * that someone is actually using this, as otherwise, this effort is probably
+ * going to be more wasted.
+ *
+ * One might be tempted to use parseFloat here, but that wouldn't work at all
+ * for several reasons. Mostly due to the way floats actually work, and
+ * parseFloat only actually works in base 10. I don't see base 10 anywhere near
+ * this file.
+ *
+ * In this case we'll implement the single and double precision versions. The
+ * quadruple precision, while probably useful, wouldn't really be accepted by
+ * Javascript, so let's not even waste our time.
+ *
+ * So let's review how this format looks like. A single precision value is 32
+ * bits and has three parts:
+ *   -  Sign bit
+ *   -  Exponent (Using bias notation)
+ *   -  Mantissa
+ *
+ * |s|eeeeeeee|mmmmmmmmmmmmmmmmmmmmmmmmm|
+ * 31| 30-23  |  22    	-       0       |
+ *
+ * The exponent is stored in a biased input. The bias in this case 127.
+ * Therefore, our exponent is equal to the 8-bit value - 127.
+ *
+ * By default, a number is normalized in IEEE, that means that the mantissa has
+ * an implicit one that we don't see. So really the value stored is 1.m.
+ * However, if the exponent is all zeros, then instead we have to shift
+ * everything to the right one and there is no more implicit one.
+ *
+ * Special values:
+ *  - Positive Infinity:
+ *	Sign:		0
+ *	Exponent: 	All 1s
+ *	Mantissa:	0
+ *  - Negative Infinity:
+ *	Sign:		1
+ *	Exponent: 	All 1s
+ *	Mantissa:	0
+ *  - NaN:
+ *	Sign:		*
+ *	Exponent: 	All 1s
+ *	Mantissa:	non-zero
+ *  - Zero:
+ *	Sign:		*
+ *	Exponent:	All 0s
+ *	Mantissa:	0
+ *
+ * In the case of zero, the sign bit determines whether we get a positive or
+ * negative zero. However, since Javascript cannot determine the difference
+ * between the two: i.e. -0 == 0, we just always return 0.
+ *
+ */
+function rfloat(buffer, endian, offset)
+{
+	var bytes = [];
+	var sign, exponent, mantissa, val;
+	var bias = 127;
+	var maxexp = 0xff;
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 3 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	/* Normalize the bytes to be in endian order */
+	if (endian == 'big') {
+		bytes[0] = buffer[offset];
+		bytes[1] = buffer[offset+1];
+		bytes[2] = buffer[offset+2];
+		bytes[3] = buffer[offset+3];
+	} else {
+		bytes[3] = buffer[offset];
+		bytes[2] = buffer[offset+1];
+		bytes[1] = buffer[offset+2];
+		bytes[0] = buffer[offset+3];
+	}
+
+	sign = bytes[0] & 0x80;
+	exponent = (bytes[0] & 0x7f) << 1;
+	exponent |= (bytes[1] & 0x80) >>> 7;
+	mantissa = (bytes[1] & 0x7f) << 16;
+	mantissa |= bytes[2] << 8;
+	mantissa |= bytes[3];
+
+	/* Check for special cases before we do general parsing */
+	if (!sign && exponent == maxexp && mantissa === 0)
+		return (Number.POSITIVE_INFINITY);
+
+	if (sign && exponent == maxexp && mantissa === 0)
+		return (Number.NEGATIVE_INFINITY);
+
+	if (exponent == maxexp && mantissa !== 0)
+		return (Number.NaN);
+
+	/*
+	 * Javascript really doesn't have support for positive or negative zero.
+	 * So we're not going to try and give it to you. That would be just
+	 * plain weird. Besides -0 == 0.
+	 */
+	if (exponent === 0 && mantissa === 0)
+		return (0);
+
+	/*
+	 * Now we can deal with the bias and the determine whether the mantissa
+	 * has the implicit one or not.
+	 */
+	exponent -= bias;
+	if (exponent == -bias) {
+		exponent++;
+		val = 0;
+	} else {
+		val = 1;
+	}
+
+	val = (val + mantissa * Math.pow(2, -23)) * Math.pow(2, exponent);
+
+	if (sign)
+		val *= -1;
+
+	return (val);
+}
+
+/*
+ * Doubles in IEEE 754 are like their brothers except for a few changes and
+ * increases in size:
+ *   - The exponent is now 11 bits
+ *   - The mantissa is now 52 bits
+ *   - The bias is now 1023
+ *
+ * |s|eeeeeeeeeee|mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm|
+ * 63| 62 - 52   | 	51		-			0     |
+ * 63| 62 - 52   |      51              -                       0     |
+ *
+ * While the size has increased a fair amount, we're going to end up keeping the
+ * same general formula for calculating the final value. As a reminder, this
+ * formula is:
+ *
+ * (-1)^s * (n + m) * 2^(e-b)
+ *
+ * Where:
+ *	s	is the sign bit
+ *	n	is (exponent > 0) ? 1 : 0 -- Determines whether we're normalized
+ *					     or not
+ *	m	is the mantissa
+ *	e	is the exponent specified
+ *	b	is the bias for the exponent
+ *
+ */
+function rdouble(buffer, endian, offset)
+{
+	var bytes = [];
+	var sign, exponent, mantissa, val, lowmant;
+	var bias = 1023;
+	var maxexp = 0x7ff;
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 7 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	/* Normalize the bytes to be in endian order */
+	if (endian == 'big') {
+		bytes[0] = buffer[offset];
+		bytes[1] = buffer[offset+1];
+		bytes[2] = buffer[offset+2];
+		bytes[3] = buffer[offset+3];
+		bytes[4] = buffer[offset+4];
+		bytes[5] = buffer[offset+5];
+		bytes[6] = buffer[offset+6];
+		bytes[7] = buffer[offset+7];
+	} else {
+		bytes[7] = buffer[offset];
+		bytes[6] = buffer[offset+1];
+		bytes[5] = buffer[offset+2];
+		bytes[4] = buffer[offset+3];
+		bytes[3] = buffer[offset+4];
+		bytes[2] = buffer[offset+5];
+		bytes[1] = buffer[offset+6];
+		bytes[0] = buffer[offset+7];
+	}
+
+	/*
+	 * We can construct the exponent and mantissa the same way as we did in
+	 * the case of a float, just increase the range of the exponent.
+	 */
+	sign = bytes[0] & 0x80;
+	exponent = (bytes[0] & 0x7f) << 4;
+	exponent |= (bytes[1] & 0xf0) >>> 4;
+
+	/*
+	 * This is going to be ugly but then again, we're dealing with IEEE 754.
+	 * This could probably be done as a node add on in a few lines of C++,
+	 * but oh we'll, we've made it this far so let's be native the rest of
+	 * the way...
+	 *
+	 * What we're going to do is break the mantissa into two parts, the
+	 * lower 24 bits and the upper 28 bits. We'll multiply the upper 28 bits
+	 * by the appropriate power and then add in the lower 24-bits. Not
+	 * really that great. It's pretty much a giant kludge to deal with
+	 * Javascript eccentricities around numbers.
+	 */
+	lowmant = bytes[7];
+	lowmant |= bytes[6] << 8;
+	lowmant |= bytes[5] << 16;
+	mantissa = bytes[4];
+	mantissa |= bytes[3] << 8;
+	mantissa |= bytes[2] << 16;
+	mantissa |= (bytes[1] & 0x0f) << 24;
+	mantissa *= Math.pow(2, 24); /* Equivalent to << 24, but JS compat */
+	mantissa += lowmant;
+
+	/* Check for special cases before we do general parsing */
+	if (!sign && exponent == maxexp && mantissa === 0)
+		return (Number.POSITIVE_INFINITY);
+
+	if (sign && exponent == maxexp && mantissa === 0)
+		return (Number.NEGATIVE_INFINITY);
+
+	if (exponent == maxexp && mantissa !== 0)
+		return (Number.NaN);
+
+	/*
+	 * Javascript really doesn't have support for positive or negative zero.
+	 * So we're not going to try and give it to you. That would be just
+	 * plain weird. Besides -0 == 0.
+	 */
+	if (exponent === 0 && mantissa === 0)
+		return (0);
+
+	/*
+	 * Now we can deal with the bias and the determine whether the mantissa
+	 * has the implicit one or not.
+	 */
+	exponent -= bias;
+	if (exponent == -bias) {
+		exponent++;
+		val = 0;
+	} else {
+		val = 1;
+	}
+
+	val = (val + mantissa * Math.pow(2, -52)) * Math.pow(2, exponent);
+
+	if (sign)
+		val *= -1;
+
+	return (val);
+}
+
+/*
+ * Now that we have gone through the pain of reading the individual types, we're
+ * probably going to want some way to write these back. None of this is going to
+ * be good. But since we have Javascript numbers this should certainly be more
+ * interesting. Though we can constrain this end a little bit more in what is
+ * valid. For now, let's go back to our friends the unsigned value.
+ */
+
+/*
+ * Unsigned numbers seem deceptively easy. Here are the general steps and rules
+ * that we are going to take:
+ *   -  If the number is negative, throw an Error
+ *   -  Truncate any floating point portion
+ *   -  Take the modulus of the number in our base
+ *   -  Write it out to the buffer in the endian format requested at the offset
+ */
+
+/*
+ * We have to make sure that the value is a valid integer. This means that it is
+ * non-negative. It has no fractional component and that it does not exceed the
+ * maximum allowed value.
+ *
+ *	value		The number to check for validity
+ *
+ *	max		The maximum value
+ */
+function prepuint(value, max)
+{
+	if (typeof (value) != 'number')
+		throw (new (Error('cannot write a non-number as a number')));
+
+	if (value < 0)
+		throw (new Error('specified a negative value for writing an ' +
+		    'unsigned value'));
+
+	if (value > max)
+		throw (new Error('value is larger than maximum value for ' +
+		    'type'));
+
+	if (Math.floor(value) !== value)
+		throw (new Error('value has a fractional component'));
+
+	return (value);
+}
+
+/*
+ * 8-bit version, classy. We can ignore endianness which is good.
+ */
+function wuint8(value, endian, buffer, offset)
+{
+	var val;
+
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	val = prepuint(value, 0xff);
+	buffer[offset] = val;
+}
+
+/*
+ * Pretty much the same as the 8-bit version, just this time we need to worry
+ * about endian related issues.
+ */
+function wgint16(val, endian, buffer, offset)
+{
+	if (endian == 'big') {
+		buffer[offset] = (val & 0xff00) >>> 8;
+		buffer[offset+1] = val & 0x00ff;
+	} else {
+		buffer[offset+1] = (val & 0xff00) >>> 8;
+		buffer[offset] = val & 0x00ff;
+	}
+}
+
+function wuint16(value, endian, buffer, offset)
+{
+	var val;
+
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 1 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	val = prepuint(value, 0xffff);
+	wgint16(val, endian, buffer, offset);
+}
+
+/*
+ * The 32-bit version is going to have to be a little different unfortunately.
+ * We can't quite bitshift to get the largest byte, because that would end up
+ * getting us caught by the signed values.
+ *
+ * And yes, we do want to subtract out the lower part by default. This means
+ * that when we do the division, it will be treated as a bit shift and we won't
+ * end up generating a floating point value. If we did generate a floating point
+ * value we'd have to truncate it intelligently, this saves us that problem and
+ * may even be somewhat faster under the hood.
+ */
+function wgint32(val, endian, buffer, offset)
+{
+	if (endian == 'big') {
+		buffer[offset] = (val - (val & 0x00ffffff)) / Math.pow(2, 24);
+		buffer[offset+1] = (val >>> 16) & 0xff;
+		buffer[offset+2] = (val >>> 8) & 0xff;
+		buffer[offset+3] = val & 0xff;
+	} else {
+		buffer[offset+3] = (val - (val & 0x00ffffff)) /
+		    Math.pow(2, 24);
+		buffer[offset+2] = (val >>> 16) & 0xff;
+		buffer[offset+1] = (val >>> 8) & 0xff;
+		buffer[offset] = val & 0xff;
+	}
+}
+
+function wuint32(value, endian, buffer, offset)
+{
+	var val;
+
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 3 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	val = prepuint(value, 0xffffffff);
+	wgint32(val, endian, buffer, offset);
+}
+
+/*
+ * Unlike the other versions, we expect the value to be in the form of two
+ * arrays where value[0] << 32 + value[1] would result in the value that we
+ * want.
+ */
+function wgint64(value, endian, buffer, offset)
+{
+	if (endian == 'big') {
+		wgint32(value[0], endian, buffer, offset);
+		wgint32(value[1], endian, buffer, offset+4);
+	} else {
+		wgint32(value[0], endian, buffer, offset+4);
+		wgint32(value[1], endian, buffer, offset);
+	}
+}
+
+function wuint64(value, endian, buffer, offset)
+{
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (!(value instanceof Array))
+		throw (new Error('value must be an array'));
+
+	if (value.length != 2)
+		throw (new Error('value must be an array of length 2'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 7 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	prepuint(value[0], 0xffffffff);
+	prepuint(value[1], 0xffffffff);
+	wgint64(value, endian, buffer, offset);
+}
+
+/*
+ * We now move onto our friends in the signed number category. Unlike unsigned
+ * numbers, we're going to have to worry a bit more about how we put values into
+ * arrays. Since we are only worrying about signed 32-bit values, we're in
+ * slightly better shape. Unfortunately, we really can't do our favorite binary
+ * & in this system. It really seems to do the wrong thing. For example:
+ *
+ * > -32 & 0xff
+ * 224
+ *
+ * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
+ * this aren't treated as a signed number. Ultimately a bad thing.
+ *
+ * What we're going to want to do is basically create the unsigned equivalent of
+ * our representation and pass that off to the wuint* functions. To do that
+ * we're going to do the following:
+ *
+ *  - if the value is positive
+ *	we can pass it directly off to the equivalent wuint
+ *  - if the value is negative
+ *	we do the following computation:
+ *	mb + val + 1, where
+ *	mb	is the maximum unsigned value in that byte size
+ *	val	is the Javascript negative integer
+ *
+ *
+ * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
+ * you do out the computations:
+ *
+ * 0xffff - 128 + 1
+ * 0xffff - 127
+ * 0xff80
+ *
+ * You can then encode this value as the signed version. This is really rather
+ * hacky, but it should work and get the job done which is our goal here.
+ *
+ * Thus the overall flow is:
+ *   -  Truncate the floating point part of the number
+ *   -  We don't have to take the modulus, because the unsigned versions will
+ *   	take care of that for us. And we don't have to worry about that
+ *   	potentially causing bad things to happen because of sign extension
+ *   -  Pass it off to the appropriate unsigned version, potentially modifying
+ *	the negative portions as necessary.
+ */
+
+/*
+ * A series of checks to make sure we actually have a signed 32-bit number
+ */
+function prepsint(value, max, min)
+{
+	if (typeof (value) != 'number')
+		throw (new (Error('cannot write a non-number as a number')));
+
+	if (value > max)
+		throw (new Error('value larger than maximum allowed value'));
+
+	if (value < min)
+		throw (new Error('value smaller than minimum allowed value'));
+
+	if (Math.floor(value) !== value)
+		throw (new Error('value has a fractional component'));
+
+	return (value);
+}
+
+/*
+ * The 8-bit version of the signed value. Overall, fairly straightforward.
+ */
+function wsint8(value, endian, buffer, offset)
+{
+	var val;
+
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	val = prepsint(value, 0x7f, -0x80);
+	if (val >= 0)
+		wuint8(val, endian, buffer, offset);
+	else
+		wuint8(0xff + val + 1, endian, buffer, offset);
+}
+
+/*
+ * The 16-bit version of the signed value. Also, fairly straightforward.
+ */
+function wsint16(value, endian, buffer, offset)
+{
+	var val;
+
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 1 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	val = prepsint(value, 0x7fff, -0x8000);
+	if (val >= 0)
+		wgint16(val, endian, buffer, offset);
+	else
+		wgint16(0xffff + val + 1, endian, buffer, offset);
+
+}
+
+/*
+ * We can do this relatively easily by leveraging the code used for 32-bit
+ * unsigned code.
+ */
+function wsint32(value, endian, buffer, offset)
+{
+	var val;
+
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 3 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	val = prepsint(value, 0x7fffffff, -0x80000000);
+	if (val >= 0)
+		wgint32(val, endian, buffer, offset);
+	else
+		wgint32(0xffffffff + val + 1, endian, buffer, offset);
+}
+
+/*
+ * The signed 64 bit integer should by in the same format as when received.
+ * Mainly it should ensure that the value is an array of two integers where
+ * value[0] << 32 + value[1] is the desired number. Furthermore, the two values
+ * need to be equal.
+ */
+function wsint64(value, endian, buffer, offset)
+{
+	var vzpos, vopos;
+	var vals = new Array(2);
+
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (!(value instanceof Array))
+		throw (new Error('value must be an array'));
+
+	if (value.length != 2)
+		throw (new Error('value must be an array of length 2'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+	if (offset + 7 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	/*
+	 * We need to make sure that we have the same sign on both values. The
+	 * hokiest way to to do this is to multiply the number by +inf. If we do
+	 * this, we'll get either +/-inf depending on the sign of the value.
+	 * Once we have this, we can compare it to +inf to see if the number is
+	 * positive or not.
+	 */
+	vzpos = (value[0] * Number.POSITIVE_INFINITY) ==
+	    Number.POSITIVE_INFINITY;
+	vopos = (value[1] * Number.POSITIVE_INFINITY) ==
+	    Number.POSITIVE_INFINITY;
+
+	/*
+	 * If either of these is zero, then we don't actually need this check.
+	 */
+	if (value[0] != 0 && value[1] != 0 && vzpos != vopos)
+		throw (new Error('Both entries in the array must have ' +
+		    'the same sign'));
+
+	/*
+	 * Doing verification for a signed 64-bit integer is actually a big
+	 * trickier than it appears. We can't quite use our standard techniques
+	 * because we need to compare both sets of values. The first value is
+	 * pretty straightforward. If the first value is beond the extremes than
+	 * we error out. However, the valid range of the second value varies
+	 * based on the first one. If the first value is negative, and *not* the
+	 * largest negative value, than it can be any integer within the range [
+	 * 0, 0xffffffff ]. If it is the largest negative number, it must be
+	 * zero.
+	 *
+	 * If the first number is positive, than it doesn't matter what the
+	 * value is. We just simply have to make sure we have a valid positive
+	 * integer.
+	 */
+	if (vzpos) {
+		prepuint(value[0], 0x7fffffff);
+		prepuint(value[1], 0xffffffff);
+	} else {
+		prepsint(value[0], 0, -0x80000000);
+		prepsint(value[1], 0, -0xffffffff);
+		if (value[0] == -0x80000000 && value[1] != 0)
+			throw (new Error('value smaller than minimum ' +
+			    'allowed value'));
+	}
+
+	/* Fix negative numbers */
+	if (value[0] < 0 || value[1] < 0) {
+		vals[0] = 0xffffffff - Math.abs(value[0]);
+		vals[1] = 0x100000000 - Math.abs(value[1]);
+		if (vals[1] == 0x100000000) {
+			vals[1] = 0;
+			vals[0]++;
+		}
+	} else {
+		vals[0] = value[0];
+		vals[1] = value[1];
+	}
+	wgint64(vals, endian, buffer, offset);
+}
+
+/*
+ * Now we are moving onto the weirder of these, the float and double. For this
+ * we're going to just have to do something that's pretty weird. First off, we
+ * have no way to get at the underlying float representation, at least not
+ * easily. But that doesn't mean we can't figure it out, we just have to use our
+ * heads.
+ *
+ * One might propose to use Number.toString(2). Of course, this is not really
+ * that good, because the ECMAScript 262 v3 Standard says the following Section
+ * 15.7.4.2-Number.prototype.toString (radix):
+ *
+ * If radix is an integer from 2 to 36, but not 10, the result is a string, the
+ * choice of which is implementation-dependent.
+ *
+ * Well that doesn't really help us one bit now does it? We could use the
+ * standard base 10 version of the string, but that's just going to create more
+ * errors as we end up trying to convert it back to a binary value. So, really
+ * this just means we have to be non-lazy and parse the structure intelligently.
+ *
+ * First off, we can do the basic checks: NaN, positive and negative infinity.
+ *
+ * Now that those are done we can work backwards to generate the mantissa and
+ * exponent.
+ *
+ * The first thing we need to do is determine the sign bit, easy to do, check
+ * whether the value is less than 0. And convert the number to its absolute
+ * value representation. Next, we need to determine if the value is less than
+ * one or greater than or equal to one and from there determine what power was
+ * used to get there. What follows is now specific to floats, though the general
+ * ideas behind this will hold for doubles as well, but the exact numbers
+ * involved will change.
+ *
+ * Once we have that power we can determine the exponent and the mantissa. Call
+ * the value that has the number of bits to reach the power ebits. In the
+ * general case they have the following values:
+ *
+ *	exponent	127 + ebits
+ *	mantissa	value * 2^(23 - ebits) & 0x7fffff
+ *
+ * In the case where the value of ebits is <= -127 we are now in the case where
+ * we no longer have normalized numbers. In this case the values take on the
+ * following values:
+ *
+ * 	exponent	0
+ *	mantissa	value * 2^149 & 0x7fffff
+ *
+ * Once we have the values for the sign, mantissa, and exponent. We reconstruct
+ * the four bytes as follows:
+ *
+ *	byte0		sign bit and seven most significant bits from the exp
+ *			sign << 7 | (exponent & 0xfe) >>> 1
+ *
+ *	byte1		lsb from the exponent and 7 top bits from the mantissa
+ *			(exponent & 0x01) << 7 | (mantissa & 0x7f0000) >>> 16
+ *
+ *	byte2		bits 8-15 (zero indexing) from mantissa
+ *			mantissa & 0xff00 >> 8
+ *
+ *	byte3		bits 0-7 from mantissa
+ *			mantissa & 0xff
+ *
+ * Once we have this we have to assign them into the buffer in proper endian
+ * order.
+ */
+
+/*
+ * Compute the log base 2 of the value. Now, someone who remembers basic
+ * properties of logarithms will point out that we could use the change of base
+ * formula for logs, and in fact that would be astute, because that's what we'll
+ * do for now. It feels cleaner, albeit it may be less efficient than just
+ * iterating and dividing by 2. We may want to come back and revisit that some
+ * day.
+ */
+function log2(value)
+{
+	return (Math.log(value) / Math.log(2));
+}
+
+/*
+ * Helper to determine the exponent of the number we're looking at.
+ */
+function intexp(value)
+{
+	return (Math.floor(log2(value)));
+}
+
+/*
+ * Helper to determine the exponent of the fractional part of the value.
+ */
+function fracexp(value)
+{
+	return (Math.floor(log2(value)));
+}
+
+function wfloat(value, endian, buffer, offset)
+{
+	var sign, exponent, mantissa, ebits;
+	var bytes = [];
+
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+
+	if (offset + 3 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	if (isNaN(value)) {
+		sign = 0;
+		exponent = 0xff;
+		mantissa = 23;
+	} else if (value == Number.POSITIVE_INFINITY) {
+		sign = 0;
+		exponent = 0xff;
+		mantissa = 0;
+	} else if (value == Number.NEGATIVE_INFINITY) {
+		sign = 1;
+		exponent = 0xff;
+		mantissa = 0;
+	} else {
+		/* Well we have some work to do */
+
+		/* Thankfully the sign bit is trivial */
+		if (value < 0) {
+			sign = 1;
+			value = Math.abs(value);
+		} else {
+			sign = 0;
+		}
+
+		/* Use the correct function to determine number of bits */
+		if (value < 1)
+			ebits = fracexp(value);
+		else
+			ebits = intexp(value);
+
+		/* Time to deal with the issues surrounding normalization */
+		if (ebits <= -127) {
+			exponent = 0;
+			mantissa = (value * Math.pow(2, 149)) & 0x7fffff;
+		} else {
+			exponent = 127 + ebits;
+			mantissa = value * Math.pow(2, 23 - ebits);
+			mantissa &= 0x7fffff;
+		}
+	}
+
+	bytes[0] = sign << 7 | (exponent & 0xfe) >>> 1;
+	bytes[1] = (exponent & 0x01) << 7 | (mantissa & 0x7f0000) >>> 16;
+	bytes[2] = (mantissa & 0x00ff00) >>> 8;
+	bytes[3] = mantissa & 0x0000ff;
+
+	if (endian == 'big') {
+		buffer[offset] = bytes[0];
+		buffer[offset+1] = bytes[1];
+		buffer[offset+2] = bytes[2];
+		buffer[offset+3] = bytes[3];
+	} else {
+		buffer[offset] = bytes[3];
+		buffer[offset+1] = bytes[2];
+		buffer[offset+2] = bytes[1];
+		buffer[offset+3] = bytes[0];
+	}
+}
+
+/*
+ * Now we move onto doubles. Doubles are similar to floats in pretty much all
+ * ways except that the processing isn't quite as straightforward because we
+ * can't always use shifting, i.e. we have > 32 bit values.
+ *
+ * We're going to proceed in an identical fashion to floats and utilize the same
+ * helper functions. All that really is changing are the specific values that we
+ * use to do the calculations. Thus, to review we have to do the following.
+ *
+ * First get the sign bit and convert the value to its absolute value
+ * representation. Next, we determine the number of bits that we used to get to
+ * the value, branching whether the value is greater than or less than 1. Once
+ * we have that value which we will again call ebits, we have to do the
+ * following in the general case:
+ *
+ *	exponent	1023 + ebits
+ *	mantissa	[value * 2^(52 - ebits)] % 2^52
+ *
+ * In the case where the value of ebits <= -1023 we no longer use normalized
+ * numbers, thus like with floats we have to do slightly different processing:
+ *
+ *	exponent	0
+ *	mantissa	[value * 2^1074] % 2^52
+ *
+ * Once we have determined the sign, exponent and mantissa we can construct the
+ * bytes as follows:
+ *
+ *	byte0		sign bit and seven most significant bits form the exp
+ *			sign << 7 | (exponent & 0x7f0) >>> 4
+ *
+ *	byte1		Remaining 4 bits from the exponent and the four most
+ *			significant bits from the mantissa 48-51
+ *			(exponent & 0x00f) << 4 | mantissa >>> 48
+ *
+ *	byte2		Bits 40-47 from the mantissa
+ *			(mantissa >>> 40) & 0xff
+ *
+ *	byte3		Bits 32-39 from the mantissa
+ *			(mantissa >>> 32) & 0xff
+ *
+ *	byte4		Bits 24-31 from the mantissa
+ *			(mantissa >>> 24) & 0xff
+ *
+ *	byte5		Bits 16-23 from the Mantissa
+ *			(mantissa >>> 16) & 0xff
+ *
+ *	byte6		Bits 8-15 from the mantissa
+ *			(mantissa >>> 8) & 0xff
+ *
+ *	byte7		Bits 0-7 from the mantissa
+ *			mantissa & 0xff
+ *
+ * Now we can't quite do the right shifting that we want in bytes 1 - 3, because
+ * we'll have extended too far and we'll lose those values when we try and do
+ * the shift. Instead we have to use an alternate approach. To try and stay out
+ * of floating point, what we'll do is say that mantissa -= bytes[4-7] and then
+ * divide by 2^32. Once we've done that we can use binary arithmetic. Oof,
+ * that's ugly, but it seems to avoid using floating point (just based on how v8
+ * seems to be optimizing for base 2 arithmetic).
+ */
+function wdouble(value, endian, buffer, offset)
+{
+	var sign, exponent, mantissa, ebits;
+	var bytes = [];
+
+	if (value === undefined)
+		throw (new Error('missing value'));
+
+	if (endian === undefined)
+		throw (new Error('missing endian'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset'));
+
+
+	if (offset + 7 >= buffer.length)
+		throw (new Error('Trying to read beyond buffer length'));
+
+	if (isNaN(value)) {
+		sign = 0;
+		exponent = 0x7ff;
+		mantissa = 23;
+	} else if (value == Number.POSITIVE_INFINITY) {
+		sign = 0;
+		exponent = 0x7ff;
+		mantissa = 0;
+	} else if (value == Number.NEGATIVE_INFINITY) {
+		sign = 1;
+		exponent = 0x7ff;
+		mantissa = 0;
+	} else {
+		/* Well we have some work to do */
+
+		/* Thankfully the sign bit is trivial */
+		if (value < 0) {
+			sign = 1;
+			value = Math.abs(value);
+		} else {
+			sign = 0;
+		}
+
+		/* Use the correct function to determine number of bits */
+		if (value < 1)
+			ebits = fracexp(value);
+		else
+			ebits = intexp(value);
+
+		/*
+		 * This is a total hack to determine a denormalized value.
+		 * Unfortunately, we sometimes do not get a proper value for
+		 * ebits, i.e. we lose the values that would get rounded off.
+		 *
+		 *
+		 * The astute observer may wonder why we would be
+		 * multiplying by two Math.pows rather than just summing
+		 * them. Well, that's to get around a small bug in the
+		 * way v8 seems to implement the function. On occasion
+		 * doing:
+		 *
+		 * foo * Math.pow(2, 1023 + 51)
+		 *
+		 * Causes us to overflow to infinity, where as doing:
+		 *
+		 * foo * Math.pow(2, 1023) * Math.pow(2, 51)
+		 *
+		 * Does not cause us to overflow. Go figure.
+		 *
+		 */
+		if (value <= 2.225073858507201e-308 || ebits <= -1023) {
+			exponent = 0;
+			mantissa = value * Math.pow(2, 1023) * Math.pow(2, 51);
+			mantissa %= Math.pow(2, 52);
+		} else {
+			/*
+			 * We might have gotten fucked by our floating point
+			 * logarithm magic. This is rather crappy, but that's
+			 * our luck. If we just had a log base 2 or access to
+			 * the stupid underlying representation this would have
+			 * been much easier and we wouldn't have such stupid
+			 * kludges or hacks.
+			 */
+			if (ebits > 1023)
+				ebits = 1023;
+			exponent = 1023 + ebits;
+			mantissa = value * Math.pow(2, -ebits);
+			mantissa *= Math.pow(2, 52);
+			mantissa %= Math.pow(2, 52);
+		}
+	}
+
+	/* Fill the bytes in backwards to deal with the size issues */
+	bytes[7] = mantissa & 0xff;
+	bytes[6] = (mantissa >>> 8) & 0xff;
+	bytes[5] = (mantissa >>> 16) & 0xff;
+	mantissa = (mantissa - (mantissa & 0xffffff)) / Math.pow(2, 24);
+	bytes[4] = mantissa & 0xff;
+	bytes[3] = (mantissa >>> 8) & 0xff;
+	bytes[2] = (mantissa >>> 16) & 0xff;
+	bytes[1] = (exponent & 0x00f) << 4 | mantissa >>> 24;
+	bytes[0] = (sign << 7) | (exponent & 0x7f0) >>> 4;
+
+	if (endian == 'big') {
+		buffer[offset] = bytes[0];
+		buffer[offset+1] = bytes[1];
+		buffer[offset+2] = bytes[2];
+		buffer[offset+3] = bytes[3];
+		buffer[offset+4] = bytes[4];
+		buffer[offset+5] = bytes[5];
+		buffer[offset+6] = bytes[6];
+		buffer[offset+7] = bytes[7];
+	} else {
+		buffer[offset+7] = bytes[0];
+		buffer[offset+6] = bytes[1];
+		buffer[offset+5] = bytes[2];
+		buffer[offset+4] = bytes[3];
+		buffer[offset+3] = bytes[4];
+		buffer[offset+2] = bytes[5];
+		buffer[offset+1] = bytes[6];
+		buffer[offset] = bytes[7];
+	}
+}
+
+/*
+ * Actually export our work above. One might argue that we shouldn't expose
+ * these interfaces and just force people to use the higher level abstractions
+ * around this work. However, unlike say other libraries we've come across, this
+ * interface has several properties: it makes sense, it's simple, and it's
+ * useful.
+ */
+exports.ruint8 = ruint8;
+exports.ruint16 = ruint16;
+exports.ruint32 = ruint32;
+exports.ruint64 = ruint64;
+exports.wuint8 = wuint8;
+exports.wuint16 = wuint16;
+exports.wuint32 = wuint32;
+exports.wuint64 = wuint64;
+
+exports.rsint8 = rsint8;
+exports.rsint16 = rsint16;
+exports.rsint32 = rsint32;
+exports.rsint64 = rsint64;
+exports.wsint8 = wsint8;
+exports.wsint16 = wsint16;
+exports.wsint32 = wsint32;
+exports.wsint64 = wsint64;
+
+exports.rfloat = rfloat;
+exports.rdouble = rdouble;
+exports.wfloat = wfloat;
+exports.wdouble = wdouble;
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/ctype.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/ctype.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/ctype.js	(revision 484)
@@ -0,0 +1,944 @@
+/*
+ * rm - Feb 2011
+ * ctype.js
+ *
+ * This module provides a simple abstraction towards reading and writing
+ * different types of binary data. It is designed to use ctio.js and provide a
+ * richer and more expressive API on top of it.
+ *
+ * By default we support the following as built in basic types:
+ *	int8_t
+ *	int16_t
+ *	int32_t
+ *	uint8_t
+ *	uint16_t
+ *	uint32_t
+ *	uint64_t
+ *	float
+ *	double
+ *	char
+ *	char[]
+ *
+ * Each type is returned as a Number, with the exception of char and char[]
+ * which are returned as Node Buffers. A char is considered a uint8_t.
+ *
+ * Requests to read and write data are specified as an array of JSON objects.
+ * This is also the same way that one declares structs. Even if just a single
+ * value is requested, it must be done as a struct. The array order determines
+ * the order that we try and read values. Each entry has the following format
+ * with values marked with a * being optional.
+ *
+ * { key: { type: /type/, value*: /value/, offset*: /offset/ }
+ *
+ * If offset is defined, we lseek(offset, SEEK_SET) before reading the next
+ * value. Value is defined when we're writing out data, otherwise it's ignored.
+ *
+ */
+
+var mod_ctf = require('./ctf.js');
+var mod_ctio = require('./ctio.js');
+var mod_assert = require('assert');
+
+/*
+ * This is the set of basic types that we support.
+ *
+ *	read		The function to call to read in a value from a buffer
+ *
+ *	write		The function to call to write a value to a buffer
+ *
+ */
+var deftypes = {
+    'uint8_t':  { read: ctReadUint8, write: ctWriteUint8 },
+    'uint16_t': { read: ctReadUint16, write: ctWriteUint16 },
+    'uint32_t': { read: ctReadUint32, write: ctWriteUint32 },
+    'uint64_t': { read: ctReadUint64, write: ctWriteUint64 },
+    'int8_t': { read: ctReadSint8, write: ctWriteSint8 },
+    'int16_t': { read: ctReadSint16, write: ctWriteSint16 },
+    'int32_t': { read: ctReadSint32, write: ctWriteSint32 },
+    'int64_t': { read: ctReadSint64, write: ctWriteSint64 },
+    'float': { read: ctReadFloat, write: ctWriteFloat },
+    'double': { read: ctReadDouble, write: ctWriteDouble },
+    'char': { read: ctReadChar, write: ctWriteChar },
+    'char[]': { read: ctReadCharArray, write: ctWriteCharArray }
+};
+
+/*
+ * The following are wrappers around the CType IO low level API. They encode
+ * knowledge about the size and return something in the expected format.
+ */
+function ctReadUint8(endian, buffer, offset)
+{
+	var val = mod_ctio.ruint8(buffer, endian, offset);
+	return ({ value: val, size: 1 });
+}
+
+function ctReadUint16(endian, buffer, offset)
+{
+	var val = mod_ctio.ruint16(buffer, endian, offset);
+	return ({ value: val, size: 2 });
+}
+
+function ctReadUint32(endian, buffer, offset)
+{
+	var val = mod_ctio.ruint32(buffer, endian, offset);
+	return ({ value: val, size: 4 });
+}
+
+function ctReadUint64(endian, buffer, offset)
+{
+	var val = mod_ctio.ruint64(buffer, endian, offset);
+	return ({ value: val, size: 8 });
+}
+
+function ctReadSint8(endian, buffer, offset)
+{
+	var val = mod_ctio.rsint8(buffer, endian, offset);
+	return ({ value: val, size: 1 });
+}
+
+function ctReadSint16(endian, buffer, offset)
+{
+	var val = mod_ctio.rsint16(buffer, endian, offset);
+	return ({ value: val, size: 2 });
+}
+
+function ctReadSint32(endian, buffer, offset)
+{
+	var val = mod_ctio.rsint32(buffer, endian, offset);
+	return ({ value: val, size: 4 });
+}
+
+function ctReadSint64(endian, buffer, offset)
+{
+	var val = mod_ctio.rsint64(buffer, endian, offset);
+	return ({ value: val, size: 8 });
+}
+
+function ctReadFloat(endian, buffer, offset)
+{
+	var val = mod_ctio.rfloat(buffer, endian, offset);
+	return ({ value: val, size: 4 });
+}
+
+function ctReadDouble(endian, buffer, offset)
+{
+	var val = mod_ctio.rdouble(buffer, endian, offset);
+	return ({ value: val, size: 8 });
+}
+
+/*
+ * Reads a single character into a node buffer
+ */
+function ctReadChar(endian, buffer, offset)
+{
+	var res = new Buffer(1);
+	res[0] = mod_ctio.ruint8(buffer, endian, offset);
+	return ({ value: res, size: 1 });
+}
+
+function ctReadCharArray(length, endian, buffer, offset)
+{
+	var ii;
+	var res = new Buffer(length);
+
+	for (ii = 0; ii < length; ii++)
+		res[ii] = mod_ctio.ruint8(buffer, endian, offset + ii);
+
+	return ({ value: res, size: length });
+}
+
+function ctWriteUint8(value, endian, buffer, offset)
+{
+	mod_ctio.wuint8(value, endian, buffer, offset);
+	return (1);
+}
+
+function ctWriteUint16(value, endian, buffer, offset)
+{
+	mod_ctio.wuint16(value, endian, buffer, offset);
+	return (2);
+}
+
+function ctWriteUint32(value, endian, buffer, offset)
+{
+	mod_ctio.wuint32(value, endian, buffer, offset);
+	return (4);
+}
+
+function ctWriteUint64(value, endian, buffer, offset)
+{
+	mod_ctio.wuint64(value, endian, buffer, offset);
+	return (8);
+}
+
+function ctWriteSint8(value, endian, buffer, offset)
+{
+	mod_ctio.wsint8(value, endian, buffer, offset);
+	return (1);
+}
+
+function ctWriteSint16(value, endian, buffer, offset)
+{
+	mod_ctio.wsint16(value, endian, buffer, offset);
+	return (2);
+}
+
+function ctWriteSint32(value, endian, buffer, offset)
+{
+	mod_ctio.wsint32(value, endian, buffer, offset);
+	return (4);
+}
+
+function ctWriteSint64(value, endian, buffer, offset)
+{
+	mod_ctio.wsint64(value, endian, buffer, offset);
+	return (8);
+}
+
+function ctWriteFloat(value, endian, buffer, offset)
+{
+	mod_ctio.wfloat(value, endian, buffer, offset);
+	return (4);
+}
+
+function ctWriteDouble(value, endian, buffer, offset)
+{
+	mod_ctio.wdouble(value, endian, buffer, offset);
+	return (8);
+}
+
+/*
+ * Writes a single character into a node buffer
+ */
+function ctWriteChar(value, endian, buffer, offset)
+{
+	if (!(value instanceof Buffer))
+		throw (new Error('Input must be a buffer'));
+
+	mod_ctio.ruint8(value[0], endian, buffer, offset);
+	return (1);
+}
+
+/*
+ * We're going to write 0s into the buffer if the string is shorter than the
+ * length of the array.
+ */
+function ctWriteCharArray(value, length, endian, buffer, offset)
+{
+	var ii;
+
+	if (!(value instanceof Buffer))
+		throw (new Error('Input must be a buffer'));
+
+	if (value.length > length)
+		throw (new Error('value length greater than array length'));
+
+	for (ii = 0; ii < value.length && ii < length; ii++)
+		mod_ctio.wuint8(value[ii], endian, buffer, offset + ii);
+
+	for (; ii < length; ii++)
+		mod_ctio.wuint8(0, endian, offset + ii);
+
+
+	return (length);
+}
+
+/*
+ * Each parser has their own set of types. We want to make sure that they each
+ * get their own copy as they may need to modify it.
+ */
+function ctGetBasicTypes()
+{
+	var ret = {};
+	var key;
+	for (key in deftypes)
+		ret[key] = deftypes[key];
+
+	return (ret);
+}
+
+/*
+ * Given a string in the form of type[length] we want to split this into an
+ * object that extracts that information. We want to note that we could possibly
+ * have nested arrays so this should only check the furthest one. It may also be
+ * the case that we have no [] pieces, in which case we just return the current
+ * type.
+ */
+function ctParseType(str)
+{
+	var begInd, endInd;
+	var type, len;
+	if (typeof (str) != 'string')
+		throw (new Error('type must be a Javascript string'));
+
+	endInd = str.lastIndexOf(']');
+	if (endInd == -1) {
+		if (str.lastIndexOf('[') != -1)
+			throw (new Error('found invalid type with \'[\' but ' +
+			    'no corresponding \']\''));
+
+		return ({ type: str });
+	}
+
+	begInd = str.lastIndexOf('[');
+	if (begInd == -1)
+		throw (new Error('found invalid type with \']\' but ' +
+		    'no corresponding \'[\''));
+
+	if (begInd >= endInd)
+		throw (new Error('malformed type, \']\' appears before \'[\''));
+
+	type = str.substring(0, begInd);
+	len = str.substring(begInd + 1, endInd);
+
+	return ({ type: type, len: len });
+}
+
+/*
+ * Given a request validate that all of the fields for it are valid and make
+ * sense. This includes verifying the following notions:
+ *  - Each type requested is present in types
+ *  - Only allow a name for a field to be specified once
+ *  - If an array is specified, validate that the requested field exists and
+ *    comes before it.
+ *  - If fields is defined, check that each entry has the occurrence of field
+ */
+function ctCheckReq(def, types, fields)
+{
+	var ii, jj;
+	var req, keys, key;
+	var found = {};
+
+	if (!(def instanceof Array))
+		throw (new Error('definition is not an array'));
+
+	if (def.length === 0)
+		throw (new Error('definition must have at least one element'));
+
+	for (ii = 0; ii < def.length; ii++) {
+		req = def[ii];
+		if (!(req instanceof Object))
+			throw (new Error('definition must be an array of' +
+			    'objects'));
+
+		keys = Object.keys(req);
+		if (keys.length != 1)
+			throw (new Error('definition entry must only have ' +
+			    'one key'));
+
+		if (keys[0] in found)
+			throw (new Error('Specified name already ' +
+			    'specified: ' + keys[0]));
+
+		if (!('type' in req[keys[0]]))
+			throw (new Error('missing required type definition'));
+
+		key = ctParseType(req[keys[0]]['type']);
+
+		/*
+		 * We may have nested arrays, we need to check the validity of
+		 * the types until the len field is undefined in key. However,
+		 * each time len is defined we need to verify it is either an
+		 * integer or corresponds to an already seen key.
+		 */
+		while (key['len'] !== undefined) {
+			if (isNaN(parseInt(key['len'], 10))) {
+				if (!(key['len'] in found))
+					throw (new Error('Given an array ' +
+					    'length without a matching type'));
+
+			}
+
+			key = ctParseType(key['type']);
+		}
+
+		/* Now we can validate if the type is valid */
+		if (!(key['type'] in types))
+			throw (new Error('type not found or typdefed: ' +
+			    key['type']));
+
+		/* Check for any required fields */
+		if (fields !== undefined) {
+			for (jj = 0; jj < fields.length; jj++) {
+				if (!(fields[jj] in req[keys[0]]))
+					throw (new Error('Missing required ' +
+					    'field: ' + fields[jj]));
+			}
+		}
+
+		found[keys[0]] = true;
+	}
+}
+
+
+/*
+ * Create a new instance of the parser. Each parser has its own store of
+ * typedefs and endianness. Conf is an object with the following required
+ * values:
+ *
+ *	endian		Either 'big' or 'little' do determine the endianness we
+ *			want to read from or write to.
+ *
+ * And the following optional values:
+ *
+ * 	char-type	Valid options here are uint8 and int8. If uint8 is
+ * 			specified this changes the default behavior of a single
+ * 			char from being a buffer of a single character to being
+ * 			a uint8_t. If int8, it becomes an int8_t instead.
+ */
+function CTypeParser(conf)
+{
+	if (!conf) throw (new Error('missing required argument'));
+
+	if (!('endian' in conf))
+		throw (new Error('missing required endian value'));
+
+	if (conf['endian'] != 'big' && conf['endian'] != 'little')
+		throw (new Error('Invalid endian type'));
+
+	if ('char-type' in conf && (conf['char-type'] != 'uint8' &&
+	    conf['char-type'] != 'int8'))
+		throw (new Error('invalid option for char-type: ' +
+		    conf['char-type']));
+
+	this.endian = conf['endian'];
+	this.types = ctGetBasicTypes();
+
+	/*
+	 * There may be a more graceful way to do this, but this will have to
+	 * serve.
+	 */
+	if ('char-type' in conf && conf['char-type'] == 'uint8')
+		this.types['char'] = this.types['uint8_t'];
+
+	if ('char-type' in conf && conf['char-type'] == 'int8')
+		this.types['char'] = this.types['int8_t'];
+}
+
+/*
+ * Sets the current endian value for the Parser. If the value is not valid,
+ * throws an Error.
+ *
+ *	endian		Either 'big' or 'little' do determine the endianness we
+ *			want to read from or write to.
+ *
+ */
+CTypeParser.prototype.setEndian = function (endian)
+{
+	if (endian != 'big' && endian != 'little')
+		throw (new Error('invalid endian type, must be big or ' +
+		    'little'));
+
+	this.endian = endian;
+};
+
+/*
+ * Returns the current value of the endian value for the parser.
+ */
+CTypeParser.prototype.getEndian = function ()
+{
+	return (this.endian);
+};
+
+/*
+ * A user has requested to add a type, let us honor their request. Yet, if their
+ * request doth spurn us, send them unto the Hells which Dante describes.
+ *
+ * 	name		The string for the type definition we're adding
+ *
+ *	value		Either a string that is a type/array name or an object
+ *			that describes a struct.
+ */
+CTypeParser.prototype.typedef = function (name, value)
+{
+	var type;
+
+	if (name === undefined)
+		throw (new (Error('missing required typedef argument: name')));
+
+	if (value === undefined)
+		throw (new (Error('missing required typedef argument: value')));
+
+	if (typeof (name) != 'string')
+		throw (new (Error('the name of a type must be a string')));
+
+	type = ctParseType(name);
+
+	if (type['len'] !== undefined)
+		throw (new Error('Cannot have an array in the typedef name'));
+
+	if (name in this.types)
+		throw (new Error('typedef name already present: ' + name));
+
+	if (typeof (value) != 'string' && !(value instanceof Array))
+		throw (new Error('typedef value must either be a string or ' +
+		    'struct'));
+
+	if (typeof (value) == 'string') {
+		type = ctParseType(value);
+		if (type['len'] !== undefined) {
+			if (isNaN(parseInt(type['len'], 10)))
+				throw (new (Error('typedef value must use ' +
+				    'fixed size array when outside of a ' +
+				    'struct')));
+		}
+
+		this.types[name] = value;
+	} else {
+		/* We have a struct, validate it */
+		ctCheckReq(value, this.types);
+		this.types[name] = value;
+	}
+};
+
+/*
+ * Include all of the typedefs, but none of the built in types. This should be
+ * treated as read-only.
+ */
+CTypeParser.prototype.lstypes = function ()
+{
+	var key;
+	var ret = {};
+
+	for (key in this.types) {
+		if (key in deftypes)
+			continue;
+		ret[key] = this.types[key];
+	}
+
+	return (ret);
+};
+
+/*
+ * Given a type string that may have array types that aren't numbers, try and
+ * fill them in from the values object. The object should be of the format where
+ * indexing into it should return a number for that type.
+ *
+ *	str		The type string
+ *
+ *	values		An object that can be used to fulfill type information
+ */
+function ctResolveArray(str, values)
+{
+	var ret = '';
+	var type = ctParseType(str);
+
+	while (type['len'] !== undefined) {
+		if (isNaN(parseInt(type['len'], 10))) {
+			if (typeof (values[type['len']]) != 'number')
+				throw (new Error('cannot sawp in non-number ' +
+				    'for array value'));
+			ret = '[' + values[type['len']] + ']' + ret;
+		} else {
+			ret = '[' + type['len'] + ']' + ret;
+		}
+		type = ctParseType(type['type']);
+	}
+
+	ret = type['type'] + ret;
+
+	return (ret);
+}
+
+/*
+ * [private] Either the typedef resolves to another type string or to a struct.
+ * If it resolves to a struct, we just pass it off to read struct. If not, we
+ * can just pass it off to read entry.
+ */
+CTypeParser.prototype.resolveTypedef = function (type, dispatch, buffer,
+    offset, value)
+{
+	var pt;
+
+	mod_assert.ok(type in this.types);
+	if (typeof (this.types[type]) == 'string') {
+		pt = ctParseType(this.types[type]);
+		if (dispatch == 'read')
+			return (this.readEntry(pt, buffer, offset));
+		else if (dispatch == 'write')
+			return (this.writeEntry(value, pt, buffer, offset));
+		else
+			throw (new Error('invalid dispatch type to ' +
+			    'resolveTypedef'));
+	} else {
+		if (dispatch == 'read')
+			return (this.readStruct(this.types[type], buffer,
+			    offset));
+		else if (dispatch == 'write')
+			return (this.writeStruct(value, this.types[type],
+			    buffer, offset));
+		else
+			throw (new Error('invalid dispatch type to ' +
+			    'resolveTypedef'));
+	}
+
+};
+
+/*
+ * [private] Try and read in the specific entry.
+ */
+CTypeParser.prototype.readEntry = function (type, buffer, offset)
+{
+	var parse, len;
+
+	/*
+	 * Because we want to special case char[]s this is unfortunately
+	 * a bit uglier than it really should be. We want to special
+	 * case char[]s so that we return a node buffer, thus they are a
+	 * first class type where as all other arrays just call into a
+	 * generic array routine which calls their data-specific routine
+	 * the specified number of times.
+	 *
+	 * The valid dispatch options we have are:
+	 *  - Array and char => char[] handler
+	 *  - Generic array handler
+	 *  - Generic typedef handler
+	 *  - Basic type handler
+	 */
+	if (type['len'] !== undefined) {
+		len = parseInt(type['len'], 10);
+		if (isNaN(len))
+			throw (new Error('somehow got a non-numeric length'));
+
+		if (type['type'] == 'char')
+			parse = this.types['char[]']['read'](len,
+			    this.endian, buffer, offset);
+		else
+			parse = this.readArray(type['type'],
+			    len, buffer, offset);
+	} else {
+		if (type['type'] in deftypes)
+			parse = this.types[type['type']]['read'](this.endian,
+			    buffer, offset);
+		else
+			parse = this.resolveTypedef(type['type'], 'read',
+			    buffer, offset);
+	}
+
+	return (parse);
+};
+
+/*
+ * [private] Read an array of data
+ */
+CTypeParser.prototype.readArray = function (type, length, buffer, offset)
+{
+	var ii, ent, pt;
+	var baseOffset = offset;
+	var ret = new Array(length);
+	pt = ctParseType(type);
+
+	for (ii = 0; ii < length; ii++) {
+		ent = this.readEntry(pt, buffer, offset);
+		offset += ent['size'];
+		ret[ii] = ent['value'];
+	}
+
+	return ({ value: ret, size: offset - baseOffset });
+};
+
+/*
+ * [private] Read a single struct in.
+ */
+CTypeParser.prototype.readStruct = function (def, buffer, offset)
+{
+	var parse, ii, type, entry, key;
+	var baseOffset = offset;
+	var ret = {};
+
+	/* Walk it and handle doing what's necessary */
+	for (ii = 0; ii < def.length; ii++) {
+		key = Object.keys(def[ii])[0];
+		entry = def[ii][key];
+
+		/* Resolve all array values */
+		type = ctParseType(ctResolveArray(entry['type'], ret));
+
+		if ('offset' in entry)
+			offset = baseOffset + entry['offset'];
+
+		parse = this.readEntry(type, buffer, offset);
+
+		offset += parse['size'];
+		ret[key] = parse['value'];
+	}
+
+	return ({ value: ret, size: (offset-baseOffset)});
+};
+
+/*
+ * This is what we were born to do. We read the data from a buffer and return it
+ * in an object whose keys match the values from the object.
+ *
+ *	def		The array definition of the data to read in
+ *
+ *	buffer		The buffer to read data from
+ *
+ *	offset		The offset to start writing to
+ *
+ * Returns an object where each key corresponds to an entry in def and the value
+ * is the read value.
+ */
+CTypeParser.prototype.readData = function (def, buffer, offset)
+{
+	/* Sanity check for arguments */
+	if (def === undefined)
+		throw (new Error('missing definition for what we should be' +
+		    'parsing'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer for what we should be ' +
+		    'parsing'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset for what we should be ' +
+		    'parsing'));
+
+	/* Sanity check the object definition */
+	ctCheckReq(def, this.types);
+
+	return (this.readStruct(def, buffer, offset)['value']);
+};
+
+/*
+ * [private] Write out an array of data
+ */
+CTypeParser.prototype.writeArray = function (value, type, length, buffer,
+    offset)
+{
+	var ii, pt;
+	var baseOffset = offset;
+	if (!(value instanceof Array))
+		throw (new Error('asked to write an array, but value is not ' +
+		    'an array'));
+
+	if (value.length != length)
+		throw (new Error('asked to write array of length ' + length +
+		    ' but that does not match value length: ' + value.length));
+
+	pt = ctParseType(type);
+	for (ii = 0; ii < length; ii++)
+		offset += this.writeEntry(value[ii], pt, buffer, offset);
+
+	return (offset - baseOffset);
+};
+
+/*
+ * [private] Write the specific entry
+ */
+CTypeParser.prototype.writeEntry = function (value, type, buffer, offset)
+{
+	var len, ret;
+
+	if (type['len'] !== undefined) {
+		len = parseInt(type['len'], 10);
+		if (isNaN(len))
+			throw (new Error('somehow got a non-numeric length'));
+
+		if (type['type'] == 'char')
+			ret = this.types['char[]']['write'](value, len,
+			    this.endian, buffer, offset);
+		else
+			ret = this.writeArray(value, type['type'],
+			    len, buffer, offset);
+	} else {
+		if (type['type'] in deftypes)
+			ret = this.types[type['type']]['write'](value,
+			    this.endian, buffer, offset);
+		else
+			ret = this.resolveTypedef(type['type'], 'write',
+			    buffer, offset, value);
+	}
+
+	return (ret);
+};
+
+/*
+ * [private] Write a single struct out.
+ */
+CTypeParser.prototype.writeStruct = function (value, def, buffer, offset)
+{
+	var ii, entry, type, key;
+	var baseOffset = offset;
+	var vals = {};
+
+	for (ii = 0; ii < def.length; ii++) {
+		key = Object.keys(def[ii])[0];
+		entry = def[ii][key];
+
+		type = ctParseType(ctResolveArray(entry['type'], vals));
+
+		if ('offset' in entry)
+			offset = baseOffset + entry['offset'];
+
+		offset += this.writeEntry(value[ii], type, buffer, offset);
+		/* Now that we've written it out, we can use it for arrays */
+		vals[key] = value[ii];
+	}
+
+	return (offset);
+};
+
+/*
+ * Unfortunately, we're stuck with the sins of an initial poor design. Because
+ * of that, we are going to have to support the old way of writing data via
+ * writeData. There we insert the values that you want to write into the
+ * definition. A little baroque. Internally, we use the new model. So we need to
+ * just get those values out of there. But to maintain the principle of least
+ * surprise, we're not going to modify the input data.
+ */
+function getValues(def)
+{
+	var ii, out, key;
+	out = [];
+	for (ii = 0; ii < def.length; ii++) {
+		key = Object.keys(def[ii])[0];
+		mod_assert.ok('value' in def[ii][key]);
+		out.push(def[ii][key]['value']);
+	}
+
+	return (out);
+}
+
+/*
+ * This is the second half of what we were born to do, write out the data
+ * itself. Historically this function required you to put your values in the
+ * definition section. This was not the smartest thing to do and a bit of an
+ * oversight to be honest. As such, this function now takes a values argument.
+ * If values is non-null and non-undefined, it will be used to determine the
+ * values. This means that the old method is still supported, but is no longer
+ * acceptable.
+ *
+ *	def		The array definition of the data to write out with
+ *			values
+ *
+ *	buffer		The buffer to write to
+ *
+ *	offset		The offset in the buffer to write to
+ *
+ *	values		An array of values to write.
+ */
+CTypeParser.prototype.writeData = function (def, buffer, offset, values)
+{
+	var hv;
+
+	if (def === undefined)
+		throw (new Error('missing definition for what we should be' +
+		    'parsing'));
+
+	if (buffer === undefined)
+		throw (new Error('missing buffer for what we should be ' +
+		    'parsing'));
+
+	if (offset === undefined)
+		throw (new Error('missing offset for what we should be ' +
+		    'parsing'));
+
+	hv = (values != null && values != undefined);
+	if (hv) {
+		if (!Array.isArray(values))
+			throw (new Error('missing values for writing'));
+		ctCheckReq(def, this.types);
+	} else {
+		ctCheckReq(def, this.types, [ 'value' ]);
+	}
+
+	this.writeStruct(hv ? values : getValues(def), def, buffer, offset);
+};
+
+/*
+ * Functions to go to and from 64 bit numbers in a way that is compatible with
+ * Javascript limitations. There are two sets. One where the user is okay with
+ * an approximation and one where they are definitely not okay with an
+ * approximation.
+ */
+
+/*
+ * Attempts to convert an array of two integers returned from rsint64 / ruint64
+ * into an absolute 64 bit number. If however the value would exceed 2^52 this
+ * will instead throw an error. The mantissa in a double is a 52 bit number and
+ * rather than potentially give you a value that is an approximation this will
+ * error. If you would rather an approximation, please see toApprox64.
+ *
+ *	val		An array of two 32-bit integers
+ */
+function toAbs64(val)
+{
+	if (val === undefined)
+		throw (new Error('missing required arg: value'));
+
+	if (!Array.isArray(val))
+		throw (new Error('value must be an array'));
+
+	if (val.length != 2)
+		throw (new Error('value must be an array of length 2'));
+
+	/* We have 20 bits worth of precision in this range */
+	if (val[0] >= 0x100000)
+		throw (new Error('value would become approximated'));
+
+	return (val[0] * Math.pow(2, 32) + val[1]);
+}
+
+/*
+ * Will return the 64 bit value as returned in an array from rsint64 / ruint64
+ * to a value as close as it can. Note that Javascript stores all numbers as a
+ * double and the mantissa only has 52 bits. Thus this version may approximate
+ * the value.
+ *
+ *	val		An array of two 32-bit integers
+ */
+function toApprox64(val)
+{
+	if (val === undefined)
+		throw (new Error('missing required arg: value'));
+
+	if (!Array.isArray(val))
+		throw (new Error('value must be an array'));
+
+	if (val.length != 2)
+		throw (new Error('value must be an array of length 2'));
+
+	return (Math.pow(2, 32) * val[0] + val[1]);
+}
+
+function parseCTF(json, conf)
+{
+	var ctype = new CTypeParser(conf);
+	mod_ctf.ctfParseJson(json, ctype);
+
+	return (ctype);
+}
+
+/*
+ * Export the few things we actually want to. Currently this is just the CType
+ * Parser and ctio.
+ */
+exports.Parser = CTypeParser;
+exports.toAbs64 = toAbs64;
+exports.toApprox64 = toApprox64;
+
+exports.parseCTF = parseCTF;
+
+exports.ruint8 = mod_ctio.ruint8;
+exports.ruint16 = mod_ctio.ruint16;
+exports.ruint32 = mod_ctio.ruint32;
+exports.ruint64 = mod_ctio.ruint64;
+exports.wuint8 = mod_ctio.wuint8;
+exports.wuint16 = mod_ctio.wuint16;
+exports.wuint32 = mod_ctio.wuint32;
+exports.wuint64 = mod_ctio.wuint64;
+
+exports.rsint8 = mod_ctio.rsint8;
+exports.rsint16 = mod_ctio.rsint16;
+exports.rsint32 = mod_ctio.rsint32;
+exports.rsint64 = mod_ctio.rsint64;
+exports.wsint8 = mod_ctio.wsint8;
+exports.wsint16 = mod_ctio.wsint16;
+exports.wsint32 = mod_ctio.wsint32;
+exports.wsint64 = mod_ctio.wsint64;
+
+exports.rfloat = mod_ctio.rfloat;
+exports.rdouble = mod_ctio.rdouble;
+exports.wfloat = mod_ctio.wfloat;
+exports.wdouble = mod_ctio.wdouble;
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/man/man3ctype/ctio.3ctype
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/man/man3ctype/ctio.3ctype	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/man/man3ctype/ctio.3ctype	(revision 484)
@@ -0,0 +1,241 @@
+'\" te
+.\" Copyright (c) 2011, Robert Mustacchi.  All Rights Reserved.
+.\" Copyright (c) 2011, Joyent, Inc.  All Rights Reserved.
+.\"
+.\" 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.
+.TH CTIO 3CTYPE "December 12, 2011"
+.SH NAME
+ctio, ruint8, ruint16, ruint32, ruint64, wuint8, wuint16, wuint32, wuint64,
+rsint8, rsint16, rsint32, rsint64, wsint8, wsint16, wsint32, wsint64, rfloat,
+rdouble, wfloat, wdouble \- integer and float operations
+.SH SYNOPSIS
+.LP
+.nf
+var mod_ctype = require('ctype');
+
+\fBNumber\fR \fBmod_ctype.ruint8\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBNumber\fR \fBmod_ctype.ruint16\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBNumber\fR \fBmod_ctype.ruint32\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBNumber[2]\fR \fBmod_ctype.ruint64\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBNumber\fR \fBmod_ctype.rsint8\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBNumber\fR \fBmod_ctype.rsint16\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBNumber\fR \fBmod_ctype.rsint32\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBNumber[2]\fR \fBmod_ctype.rsint64\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBNumber\fR \fBmod_ctype.rfloat\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBNumber\fR \fBmod_ctype.rdouble\fR(\fBBuffer\fR \fIbuf\fR, \fBString\fR \fIendian\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wuint8\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wuint16\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wuint32\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wuint64\fR(\fBNumber[2]\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wsint8\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wsint16\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wsint32\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wsint64\fR(\fBNumber[2]\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wfloat\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.LP
+.nf
+\fBvoid\fR \fBmod_ctype.wdouble\fR(\fBNumber\fR value, \fBString\fR \fIendian\fR, \fBBuffer\fR \fIbuf\fR, \fBNumber\fR \fIoffset\fR);
+.fi
+
+.SH DESCRIPTION
+.sp
+.LP
+The argument \fIbuf\fR refers to a valid buffer (from calling new Buffer()). The
+argument \fIendian\fR is either the string 'big' or 'little' and controls
+whether the data in the buffer is interpreted as big or little endian. The argument
+\fIoffset\fR indicates the starting index into the buffer to read or write. All
+functions ensure that starting at \fIoffset\fR does not overflow the end of the
+buffer. The argument \fIvalue\fR is a Number that is the valid type for the
+specific function. All functions that take \fIvalue\fR as an argument, verify
+that the passed value is valid.
+
+.SS "\fBruint8()\fR, \fBruint16()\fR, \fBruint32()\fR"
+.sp
+.LP
+The \fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR functions read an 8,
+16, and 32-bit unsigned value from \fIbuf\fR and return it. The value read is
+influenced by the values of \fIoffset\fR and \fRendian\fI.
+
+
+.SS "\fBrsint8()\fR, \fBrsint16()\fR, \fBrsint32()\fR"
+.sp
+.LP
+The \fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR functions work just as
+\fBruint8()\fR, \fBruint16()\fR, and \fBruint32()\fR, except they return signed
+integers.
+
+.SS "\fBruint64()\fR, \fBrsint64()\fR"
+.sp
+.LP
+The \fBruint64()\fR and \fBrsint64()\fR functions read unsigned and signed 64
+bit integers respectively from \fBbuf\fR. Due to the limitations of ECMAScript's
+\fBNumber\fR type, they cannot be stored as one value without a loss of
+precision. Instead of returning the values as a single \fBNumber\fR, the
+functions return an array of two numbers. The first entry always contains the
+upper 32-bits and the second value contains the lower 32-bits. The lossy
+transformation into a number would be \fIres[0]*Math.pow(2,32)+res[1]\fR.
+Note that, unless an entry is zero, both array entries are guaranteed to have
+the same sign.
+
+.SS "\fBwuint8()\fR, \fBwuint16()\fR, \fBwuint32()\fR"
+.sp
+.LP
+The functions \fBwuint8()\fR, \fBwuint16()\fR, and \fBwuint32()\fR modify the
+contents of \fBbuf\fR by writing an 8, 16, and 32-bit unsigned integer
+respectively to \fBbuf\fR. It is illegal to pass a number that is not an integer
+within the domain of the integer size, for example, for \fBwuint8()\fR the valid
+range is \fB[0, 255]\fR. The value will be written in either big or little
+endian format based upon the value of \fBendian\fR.
+
+
+.SS "\fBwsint8()\fR, \fBwsint16()\fR, \fBwsint32()\fR"
+.sp
+.LP
+The functions \fBwsint8()\fR, \fBwsint16()\fR, and \fBwsint32()\fR function
+identically to the functions \fBwuint8()\fR, \fBwuint16()\fR, and
+\fBwuint32()\fR except that they the valid domain for \fBvalue\fR is that of a
+signed number instead of an unsigned number. For example the \fBwsint8()\fR has
+a domain of \fB[-128, 127]\fR.
+
+.SS "\fBwuint64()\fR, \fBwsint64()\fR"
+.sp
+.LP
+The functions \fBwuint64()\fR and \fBswint64()\fR write out 64-bit unsigned and
+signed integers to \fBbuf\fR. The \fBvalue\fR argument must be in the same
+format as described in \fBruint64()\fR and \fBrsint64()\fR.
+
+.SS "\fBrfloat()\fR, \fBrdouble()\fR"
+.sp
+.LP
+The functions "\fBrfloat()\fR and \fBrdouble()\fR" work like the other read
+functions, except that they read a single precision and double precision
+IEEE-754 floating point value instead.
+
+.SS "\fBwfloat()\fR, \fBwdouble()\fR"
+.sp
+.LP
+The functions "\fBrfloat()\fR and \fBrdouble()\fR" work like the other write 
+functions, except that the domain for a float is that of a single precision 4
+byte value. The domain for a double is any \fBNumber\fR in ECMAScript, which is
+defined to be represented by a double.
+
+.SH ATTRIBUTES
+.sp
+.LP
+See \fBattributes\fR(5) for descriptions of the following attributes:
+.sp
+
+.sp
+.TS
+box;
+c | c
+l | l .
+ATTRIBUTE TYPE	ATTRIBUTE VALUE
+_
+Interface Stability	Committed
+_
+MT-Level	See below.
+_
+Standard	Not standardized.
+.TE
+
+.sp
+.LP
+
+All functions are MT-safe in so far as there aren't shared memory MT concerns in
+most node programs. If one where to concoct such an environment, these functions
+wouldn't be MT-safe.
+
+.SH SEE ALSO
+.sp
+.LP
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/package.json	(revision 484)
@@ -0,0 +1,18 @@
+{
+  "name": "ctype",
+  "version": "0.5.2",
+  "description": "read and write binary structures and data types",
+  "homepage": "https://github.com/rmustacc/node-ctype",
+  "author": {
+    "name": "Robert Mustacchi",
+    "email": "rm@fingolfin.org"
+  },
+  "engines": {
+    "node": ">= 0.4"
+  },
+  "main": "ctype.js",
+  "readme": "Node-CType is a way to read and write binary data in structured and easy to use\nformat. Its name comes from the C header file.\n\nTo get started, simply clone the repository or use npm to install it. Once it is\nthere, simply require it.\n\ngit clone git://github.com/rmustacc/node-ctype\nnpm install ctype\nvar mod_ctype = require('ctype')\n\n\nThere are two APIs that you can use, depending on what abstraction you'd like.\nThe low level API let's you read and write individual integers and floats from\nbuffers. The higher level API let's you read and write structures of these. To\nillustrate this, let's looks look at how we would read and write a binary\nencoded x,y point.\n\nIn C we would define this structure as follows:\n\ntypedef struct point {\n\tuint16_t\tp_x;\n\tuint16_t\tp_y;\n} point_t;\n\nTo read a binary encoded point from a Buffer, we first need to create a CType\nparser (where we specify the endian and other options) and add the typedef.\n\nvar parser = new mod_ctype.Parser({ endian: 'big' });\nparser.typedef('point_t', [\n\t{ x: { type: 'uint16_t' } },\n\t{ y: { type: 'uint16_t' } }\n]);\n\nFrom here, given a buffer buf and an offset into it, we can read a point.\n\nvar out = parser.readData([ { point: { type: 'point_t' } } ], buffer, 0);\nconsole.log(out);\n{ point: { x: 23, y: 42 } }\n\nAnother way to get the same information would be to use the low level methods.\nNote that these require you to manually deal with the offset. Here's how we'd\nget the same values of x and y from the buffer.\n\nvar x = mod_ctype.ruint16(buf, 'big', 0);\nvar y = mod_ctype.ruint16(buf, 'big', 2);\nconsole.log(x + ', ' + y);\n23, 42\n\nThe true power of this API comes from the ability to define and nest typedefs,\njust as you would in C. By default, the following types are defined by default.\nNote that they return a Number, unless indicated otherwise.\n\n    * int8_t\n    * int16_t\n    * int32_t\n    * int64_t (returns an array where val[0] << 32 + val[1] would be the value)\n    * uint8_t\n    * uint16_t\n    * uint32_t\n    * uint64_t (returns an array where val[0] << 32 + val[1] would be the value)\n    * float\n    * double\n    * char (either returns a buffer with that character or a uint8_t)\n    * char[] (returns an object with the buffer and the number of characters read which is either the total amount requested or until the first 0)\n\n\nctf2json integration:\n\nNode-CType supports consuming the output of ctf2json. Once you read in a JSON file,\nall you have to do to add all the definitions it contains is:\n\nvar data, parser;\ndata = JSON.parse(parsedJSONData);\nparser = mod_ctype.parseCTF(data, { endian: 'big' });\n\nFor more documentation, see the file README.old. Full documentation is in the\nprocess of being rewritten as a series of manual pages which will be available\nin the repository and online for viewing.\n\nTo read the ctio manual page simple run, from the root of the workspace:\n\nman -Mman -s 3ctype ctio\n",
+  "readmeFilename": "README",
+  "_id": "ctype@0.5.2",
+  "_from": "ctype@0.5.2"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsl.conf
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsl.conf	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsl.conf	(revision 484)
@@ -0,0 +1,129 @@
+#
+# Configuration File for JavaScript Lint 0.3.0
+# Developed by Matthias Miller (http://www.JavaScriptLint.com)
+#
+# This configuration file can be used to lint a collection of scripts, or to enable
+# or disable warnings for scripts that are linted via the command line.
+#
+
+### Warnings
+# Enable or disable warnings based on requirements.
+# Use "+WarningName" to display or "-WarningName" to suppress.
+#
++no_return_value              # function {0} does not always return a value
++duplicate_formal             # duplicate formal argument {0}
++equal_as_assign              # test for equality (==) mistyped as assignment (=)?{0}
++var_hides_arg                # variable {0} hides argument
++redeclared_var               # redeclaration of {0} {1}
++anon_no_return_value         # anonymous function does not always return a value
++missing_semicolon            # missing semicolon
++meaningless_block            # meaningless block; curly braces have no impact
++comma_separated_stmts        # multiple statements separated by commas (use semicolons?)
++unreachable_code             # unreachable code
++missing_break                # missing break statement
++missing_break_for_last_case  # missing break statement for last case in switch
++comparison_type_conv         # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
+-inc_dec_within_stmt          # increment (++) and decrement (--) operators used as part of greater statement
++useless_void                 # use of the void type may be unnecessary (void is always undefined)
+-useless_quotes			# quotation marks are unnecessary
++multiple_plus_minus          # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
++use_of_label                 # use of label
+-block_without_braces         # block statement without curly braces
++leading_decimal_point        # leading decimal point may indicate a number or an object member
++trailing_decimal_point       # trailing decimal point may indicate a number or an object member
+-octal_number                 # leading zeros make an octal number
++nested_comment               # nested comment
++misplaced_regex              # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
++ambiguous_newline            # unexpected end of line; it is ambiguous whether these lines are part of the same statement
++empty_statement              # empty statement or extra semicolon
+-missing_option_explicit      # the "option explicit" control comment is missing
++partial_option_explicit      # the "option explicit" control comment, if used, must be in the first script tag
++dup_option_explicit          # duplicate "option explicit" control comment
++useless_assign               # useless assignment
++ambiguous_nested_stmt        # block statements containing block statements should use curly braces to resolve ambiguity
++ambiguous_else_stmt          # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
++missing_default_case         # missing default case in switch statement
++duplicate_case_in_switch     # duplicate case in switch statements
++default_not_at_end           # the default case is not at the end of the switch statement
++legacy_cc_not_understood     # couldn't understand control comment using /*@keyword@*/ syntax
++jsl_cc_not_understood        # couldn't understand control comment using /*jsl:keyword*/ syntax
++useless_comparison           # useless comparison; comparing identical expressions
++with_statement               # with statement hides undeclared variables; use temporary variable instead
++trailing_comma_in_array      # extra comma is not recommended in array initializers
++assign_to_function_call      # assignment to a function call
++parseint_missing_radix       # parseInt missing radix parameter
+-unreferenced_argument        # argument declared but never referenced: {name}
+
+### Output format
+# Customize the format of the error message.
+#    __FILE__ indicates current file path
+#    __FILENAME__ indicates current file name
+#    __LINE__ indicates current line
+#    __ERROR__ indicates error message
+#
+# Visual Studio syntax (default):
++output-format __FILE__(__LINE__): __ERROR__
+# Alternative syntax:
+#+output-format __FILE__:__LINE__: __ERROR__
+
+
+### Context
+# Show the in-line position of the error.
+# Use "+context" to display or "-context" to suppress.
+#
++context
+
+
+### Semicolons
+# By default, assignments of an anonymous function to a variable or
+# property (such as a function prototype) must be followed by a semicolon.
+#
+#+lambda_assign_requires_semicolon # deprecated setting
+
+
+### Control Comments
+# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
+# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
+# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
+# although legacy control comments are enabled by default for backward compatibility.
+#
++legacy_control_comments
+
+
+### JScript Function Extensions
+# JScript allows member functions to be defined like this:
+#     function MyObj() { /*constructor*/ }
+#     function MyObj.prototype.go() { /*member function*/ }
+#
+# It also allows events to be attached like this:
+#     function window::onload() { /*init page*/ }
+#
+# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
+#
+#-jscript_function_extensions # deprecated setting
+
+
+### Defining identifiers
+# By default, "option explicit" is enabled on a per-file basis.
+# To enable this for all files, use "+always_use_option_explicit"
+-always_use_option_explicit
+
+# Define certain identifiers of which the lint is not aware.
+# (Use this in conjunction with the "undeclared identifier" warning.)
+#
+# Common uses for webpages might be:
+#+define window
+#+define document
++define require
++define exports
++define console
++define Buffer
++define JSON
+
+### Files
+# Specify which files to lint
+# Use "+recurse" to enable recursion (disabled by default).
+# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
+# or "+process Folder\Path\*.htm".
+#
+#+process jsl-test.js
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsstyle
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsstyle	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsstyle	(revision 484)
@@ -0,0 +1,839 @@
+#!/usr/bin/env perl
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2011 Joyent, Inc. All rights reserved.
+#
+# jsstyle - check for some common stylistic errors.
+#
+#	jsstyle is a sort of "lint" for Javascript coding style.  This tool is
+#	derived from the cstyle tool, used to check for the style used in the
+#	Solaris kernel, sometimes known as "Bill Joy Normal Form".
+#
+#	There's a lot this can't check for, like proper indentation of code
+#	blocks.  There's also a lot more this could check for.
+#
+#	A note to the non perl literate:
+#
+#		perl regular expressions are pretty much like egrep
+#		regular expressions, with the following special symbols
+#
+#		\s	any space character
+#		\S	any non-space character
+#		\w	any "word" character [a-zA-Z0-9_]
+#		\W	any non-word character
+#		\d	a digit [0-9]
+#		\D	a non-digit
+#		\b	word boundary (between \w and \W)
+#		\B	non-word boundary
+#
+
+require 5.0;
+use IO::File;
+use Getopt::Std;
+use strict;
+
+my $usage =
+"usage: jsstyle [-chvC] [-o constructs] file ...
+	-c	check continuation indentation inside functions
+	-h	perform heuristic checks that are sometimes wrong
+	-v	verbose
+	-C	don't check anything in header block comments
+	-o constructs
+		allow a comma-seperated list of optional constructs:
+		    doxygen	allow doxygen-style block comments (/** /*!)
+		    splint	allow splint-style lint comments (/*@ ... @*/)
+";
+
+my %opts;
+
+if (!getopts("cho:vC", \%opts)) {
+	print $usage;
+	exit 2;
+}
+
+my $check_continuation = $opts{'c'};
+my $heuristic = $opts{'h'};
+my $verbose = $opts{'v'};
+my $ignore_hdr_comment = $opts{'C'};
+
+my $doxygen_comments = 0;
+my $splint_comments = 0;
+
+if (defined($opts{'o'})) {
+	for my $x (split /,/, $opts{'o'}) {
+		if ($x eq "doxygen") {
+			$doxygen_comments = 1;
+		} elsif ($x eq "splint") {
+			$splint_comments = 1;
+		} else {
+			print "jsstyle: unrecognized construct \"$x\"\n";
+			print $usage;
+			exit 2;
+		}
+	}
+}
+
+my ($filename, $line, $prev);		# shared globals
+
+my $fmt;
+my $hdr_comment_start;
+
+if ($verbose) {
+	$fmt = "%s: %d: %s\n%s\n";
+} else {
+	$fmt = "%s: %d: %s\n";
+}
+
+if ($doxygen_comments) {
+	# doxygen comments look like "/*!" or "/**"; allow them.
+	$hdr_comment_start = qr/^\s*\/\*[\!\*]?$/;
+} else {
+	$hdr_comment_start = qr/^\s*\/\*$/;
+}
+
+# Note, following must be in single quotes so that \s and \w work right.
+my $lint_re = qr/\/\*(?:
+	jsl:\w+?|ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*|
+	CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|
+	FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*|
+	PROTOLIB[0-9]*|SCANFLIKE[0-9]*|JSSTYLED.*?
+    )\*\//x;
+
+my $splint_re = qr/\/\*@.*?@\*\//x;
+
+my $err_stat = 0;		# exit status
+
+if ($#ARGV >= 0) {
+	foreach my $arg (@ARGV) {
+		my $fh = new IO::File $arg, "r";
+		if (!defined($fh)) {
+			printf "%s: cannot open\n", $arg;
+		} else {
+			&jsstyle($arg, $fh);
+			close $fh;
+		}
+	}
+} else {
+	&jsstyle("<stdin>", *STDIN);
+}
+exit $err_stat;
+
+my $no_errs = 0;		# set for JSSTYLED-protected lines
+
+sub err($) {
+	my ($error) = @_;
+	unless ($no_errs) {
+		printf $fmt, $filename, $., $error, $line;
+		$err_stat = 1;
+	}
+}
+
+sub err_prefix($$) {
+	my ($prevline, $error) = @_;
+	my $out = $prevline."\n".$line;
+	unless ($no_errs) {
+		printf $fmt, $filename, $., $error, $out;
+		$err_stat = 1;
+	}
+}
+
+sub err_prev($) {
+	my ($error) = @_;
+	unless ($no_errs) {
+		printf $fmt, $filename, $. - 1, $error, $prev;
+		$err_stat = 1;
+	}
+}
+
+sub jsstyle($$) {
+
+my ($fn, $filehandle) = @_;
+$filename = $fn;			# share it globally
+
+my $in_cpp = 0;
+my $next_in_cpp = 0;
+
+my $in_comment = 0;
+my $in_header_comment = 0;
+my $comment_done = 0;
+my $in_function = 0;
+my $in_function_header = 0;
+my $in_declaration = 0;
+my $note_level = 0;
+my $nextok = 0;
+my $nocheck = 0;
+
+my $in_string = 0;
+
+my ($okmsg, $comment_prefix);
+
+$line = '';
+$prev = '';
+reset_indent();
+
+line: while (<$filehandle>) {
+	s/\r?\n$//;	# strip return and newline
+
+	# save the original line, then remove all text from within
+	# double or single quotes, we do not want to check such text.
+
+	$line = $_;
+
+	#
+	# C allows strings to be continued with a backslash at the end of
+	# the line.  We translate that into a quoted string on the previous
+	# line followed by an initial quote on the next line.
+	#
+	# (we assume that no-one will use backslash-continuation with character
+	# constants)
+	#
+	$_ = '"' . $_		if ($in_string && !$nocheck && !$in_comment);
+
+	#
+	# normal strings and characters
+	#
+	s/'([^\\']|\\.)*'/\'\'/g;
+	s/"([^\\"]|\\.)*"/\"\"/g;
+
+	#
+	# detect string continuation
+	#
+	if ($nocheck || $in_comment) {
+		$in_string = 0;
+	} else {
+		#
+		# Now that all full strings are replaced with "", we check
+		# for unfinished strings continuing onto the next line.
+		#
+		$in_string =
+		    (s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ ||
+		    s/^("")*"([^\\"]|\\.)*\\$/""/);
+	}
+
+	#
+	# figure out if we are in a cpp directive
+	#
+	$in_cpp = $next_in_cpp || /^\s*#/;	# continued or started
+	$next_in_cpp = $in_cpp && /\\$/;	# only if continued
+
+	# strip off trailing backslashes, which appear in long macros
+	s/\s*\\$//;
+
+	# an /* END JSSTYLED */ comment ends a no-check block.
+	if ($nocheck) {
+		if (/\/\* *END *JSSTYLED *\*\//) {
+			$nocheck = 0;
+		} else {
+			reset_indent();
+			next line;
+		}
+	}
+
+	# a /*JSSTYLED*/ comment indicates that the next line is ok.
+	if ($nextok) {
+		if ($okmsg) {
+			err($okmsg);
+		}
+		$nextok = 0;
+		$okmsg = 0;
+		if (/\/\* *JSSTYLED.*\*\//) {
+			/^.*\/\* *JSSTYLED *(.*) *\*\/.*$/;
+			$okmsg = $1;
+			$nextok = 1;
+		}
+		$no_errs = 1;
+	} elsif ($no_errs) {
+		$no_errs = 0;
+	}
+
+	# check length of line.
+	# first, a quick check to see if there is any chance of being too long.
+	if (($line =~ tr/\t/\t/) * 7 + length($line) > 80) {
+		# yes, there is a chance.
+		# replace tabs with spaces and check again.
+		my $eline = $line;
+		1 while $eline =~
+		    s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
+		if (length($eline) > 80) {
+			err("line > 80 characters");
+		}
+	}
+
+	# ignore NOTE(...) annotations (assumes NOTE is on lines by itself).
+	if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE
+		s/[^()]//g;			  # eliminate all non-parens
+		$note_level += s/\(//g - length;  # update paren nest level
+		next;
+	}
+
+	# a /* BEGIN JSSTYLED */ comment starts a no-check block.
+	if (/\/\* *BEGIN *JSSTYLED *\*\//) {
+		$nocheck = 1;
+	}
+
+	# a /*JSSTYLED*/ comment indicates that the next line is ok.
+	if (/\/\* *JSSTYLED.*\*\//) {
+		/^.*\/\* *JSSTYLED *(.*) *\*\/.*$/;
+		$okmsg = $1;
+		$nextok = 1;
+	}
+	if (/\/\/ *JSSTYLED/) {
+		/^.*\/\/ *JSSTYLED *(.*)$/;
+		$okmsg = $1;
+		$nextok = 1;
+	}
+
+	# universal checks; apply to everything
+	if (/\t +\t/) {
+		err("spaces between tabs");
+	}
+	if (/ \t+ /) {
+		err("tabs between spaces");
+	}
+	if (/\s$/) {
+		err("space or tab at end of line");
+	}
+	if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) {
+		err("comment preceded by non-blank");
+	}
+
+	# is this the beginning or ending of a function?
+	# (not if "struct foo\n{\n")
+	if (/^{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) {
+		$in_function = 1;
+		$in_declaration = 1;
+		$in_function_header = 0;
+		$prev = $line;
+		next line;
+	}
+	if (/^}\s*(\/\*.*\*\/\s*)*$/) {
+		if ($prev =~ /^\s*return\s*;/) {
+			err_prev("unneeded return at end of function");
+		}
+		$in_function = 0;
+		reset_indent();		# we don't check between functions
+		$prev = $line;
+		next line;
+	}
+	if (/^\w*\($/) {
+		$in_function_header = 1;
+	}
+
+	# a blank line terminates the declarations within a function.
+	# XXX - but still a problem in sub-blocks.
+	if ($in_declaration && /^$/) {
+		$in_declaration = 0;
+	}
+
+	if ($comment_done) {
+		$in_comment = 0;
+		$in_header_comment = 0;
+		$comment_done = 0;
+	}
+	# does this looks like the start of a block comment?
+	if (/$hdr_comment_start/) {
+		if (!/^\t*\/\*/) {
+			err("block comment not indented by tabs");
+		}
+		$in_comment = 1;
+		/^(\s*)\//;
+		$comment_prefix = $1;
+		if ($comment_prefix eq "") {
+			$in_header_comment = 1;
+		}
+		$prev = $line;
+		next line;
+	}
+	# are we still in the block comment?
+	if ($in_comment) {
+		if (/^$comment_prefix \*\/$/) {
+			$comment_done = 1;
+		} elsif (/\*\//) {
+			$comment_done = 1;
+			err("improper block comment close")
+			    unless ($ignore_hdr_comment && $in_header_comment);
+		} elsif (!/^$comment_prefix \*[ \t]/ &&
+		    !/^$comment_prefix \*$/) {
+			err("improper block comment")
+			    unless ($ignore_hdr_comment && $in_header_comment);
+		}
+	}
+
+	if ($in_header_comment && $ignore_hdr_comment) {
+		$prev = $line;
+		next line;
+	}
+
+	# check for errors that might occur in comments and in code.
+
+	# allow spaces to be used to draw pictures in header comments.
+	#if (/[^ ]     / && !/".*     .*"/ && !$in_header_comment) {
+	#	err("spaces instead of tabs");
+	#}
+	#if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ &&
+	#    (!/^    \w/ || $in_function != 0)) {
+	#	err("indent by spaces instead of tabs");
+	#}
+	if (/^ {2,}/ && !/^    [^ ]/) {
+		err("indent by spaces instead of tabs");
+	}
+	if (/^\t+ [^ \t\*]/ || /^\t+  \S/ || /^\t+   \S/) {
+		err("continuation line not indented by 4 spaces");
+	}
+
+	if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) {
+		err("improper first line of block comment");
+	}
+
+	if ($in_comment) {	# still in comment, don't do further checks
+		$prev = $line;
+		next line;
+	}
+
+	if ((/[^(]\/\*\S/ || /^\/\*\S/) &&
+	    !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
+		err("missing blank after open comment");
+	}
+	if (/\S\*\/[^)]|\S\*\/$/ &&
+	    !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
+		err("missing blank before close comment");
+	}
+	if (/\/\/\S/) {		# C++ comments
+		err("missing blank after start comment");
+	}
+	# check for unterminated single line comments, but allow them when
+	# they are used to comment out the argument list of a function
+	# declaration.
+	if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) {
+		err("unterminated single line comment");
+	}
+
+	if (/^(#else|#endif|#include)(.*)$/) {
+		$prev = $line;
+		next line;
+	}
+
+	#
+	# delete any comments and check everything else.  Note that
+	# ".*?" is a non-greedy match, so that we don't get confused by
+	# multiple comments on the same line.
+	#
+	s/\/\*.*?\*\///g;
+	s/\/\/.*$//;		# C++ comments
+
+	# delete any trailing whitespace; we have already checked for that.
+	s/\s*$//;
+
+	# following checks do not apply to text in comments.
+	if (/"/) {
+		err("literal string using double-quote instead of single");
+	}
+
+	if (/[^=!<>\s][!<>=]=/ || /[^<>!=][!<>=]==?[^\s,=]/ ||
+	    (/[^->]>[^,=>\s]/ && !/[^->]>$/) ||
+	    (/[^<]<[^,=<\s]/ && !/[^<]<$/) ||
+	    /[^<\s]<[^<]/ || /[^->\s]>[^>]/) {
+		err("missing space around relational operator");
+	}
+	if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ ||
+	    (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) ||
+	    (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) {
+		# XXX - should only check this for C++ code
+		# XXX - there are probably other forms that should be allowed
+		if (!/\soperator=/) {
+			err("missing space around assignment operator");
+		}
+	}
+	if (/[,;]\S/ && !/\bfor \(;;\)/) {
+		err("comma or semicolon followed by non-blank");
+	}
+	# allow "for" statements to have empty "while" clauses
+	if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) {
+		err("comma or semicolon preceded by blank");
+	}
+	if (/^\s*(&&|\|\|)/) {
+		err("improper boolean continuation");
+	}
+	if (/\S   *(&&|\|\|)/ || /(&&|\|\|)   *\S/) {
+		err("more than one space around boolean operator");
+	}
+	if (/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\(/) {
+		err("missing space between keyword and paren");
+	}
+	if (/(\b(catch|for|if|with|while|switch|return)\b.*){2,}/) {
+		# multiple "case" and "sizeof" allowed
+		err("more than one keyword on line");
+	}
+	if (/\b(delete|typeof|instanceOf|with|throw|catch|new|function|in|for|if|while|switch|return|case)\s\s+\(/ &&
+	    !/^#if\s+\(/) {
+		err("extra space between keyword and paren");
+	}
+	# try to detect "func (x)" but not "if (x)" or
+	# "#define foo (x)" or "int (*func)();"
+	if (/\w\s\(/) {
+		my $s = $_;
+		# strip off all keywords on the line
+		s/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\s\(/XXX(/g;
+		s/#elif\s\(/XXX(/g;
+		s/^#define\s+\w+\s+\(/XXX(/;
+		# do not match things like "void (*f)();"
+		# or "typedef void (func_t)();"
+		s/\w\s\(+\*/XXX(*/g;
+		s/\b(void)\s+\(+/XXX(/og;
+		if (/\w\s\(/) {
+			err("extra space between function name and left paren");
+		}
+		$_ = $s;
+	}
+
+	if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) {
+		err("unparenthesized return expression");
+	}
+	if (/\btypeof\b/ && !/\btypeof\s*\(.*\)/) {
+		err("unparenthesized typeof expression");
+	}
+	if (/\(\s/) {
+		err("whitespace after left paren");
+	}
+	# allow "for" statements to have empty "continue" clauses
+	if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) {
+		err("whitespace before right paren");
+	}
+	if (/^\s*\(void\)[^ ]/) {
+		err("missing space after (void) cast");
+	}
+	if (/\S{/ && !/({|\(){/) {
+		err("missing space before left brace");
+	}
+	if ($in_function && /^\s+{/ &&
+	    ($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) {
+		err("left brace starting a line");
+	}
+	if (/}(else|while)/) {
+		err("missing space after right brace");
+	}
+	if (/}\s\s+(else|while)/) {
+		err("extra space after right brace");
+	}
+	if (/^\s+#/) {
+		err("preprocessor statement not in column 1");
+	}
+	if (/^#\s/) {
+		err("blank after preprocessor #");
+	}
+
+	#
+	# We completely ignore, for purposes of indentation:
+	#  * lines outside of functions
+	#  * preprocessor lines
+	#
+	if ($check_continuation && $in_function && !$in_cpp) {
+		process_indent($_);
+	}
+
+	if ($heuristic) {
+		# cannot check this everywhere due to "struct {\n...\n} foo;"
+		if ($in_function && !$in_declaration &&
+		    /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ &&
+		    !/} (else|while)/ && !/}}/) {
+			err("possible bad text following right brace");
+		}
+		# cannot check this because sub-blocks in
+		# the middle of code are ok
+		if ($in_function && /^\s+{/) {
+			err("possible left brace starting a line");
+		}
+	}
+	if (/^\s*else\W/) {
+		if ($prev =~ /^\s*}$/) {
+			err_prefix($prev,
+			    "else and right brace should be on same line");
+		}
+	}
+	$prev = $line;
+}
+
+if ($prev eq "") {
+	err("last line in file is blank");
+}
+
+}
+
+#
+# Continuation-line checking
+#
+# The rest of this file contains the code for the continuation checking
+# engine.  It's a pretty simple state machine which tracks the expression
+# depth (unmatched '('s and '['s).
+#
+# Keep in mind that the argument to process_indent() has already been heavily
+# processed; all comments have been replaced by control-A, and the contents of
+# strings and character constants have been elided.
+#
+
+my $cont_in;		# currently inside of a continuation
+my $cont_off;		# skipping an initializer or definition
+my $cont_noerr;		# suppress cascading errors
+my $cont_start;		# the line being continued
+my $cont_base;		# the base indentation
+my $cont_first;		# this is the first line of a statement
+my $cont_multiseg;	# this continuation has multiple segments
+
+my $cont_special;	# this is a C statement (if, for, etc.)
+my $cont_macro;		# this is a macro
+my $cont_case;		# this is a multi-line case
+
+my @cont_paren;		# the stack of unmatched ( and [s we've seen
+
+sub
+reset_indent()
+{
+	$cont_in = 0;
+	$cont_off = 0;
+}
+
+sub
+delabel($)
+{
+	#
+	# replace labels with tabs.  Note that there may be multiple
+	# labels on a line.
+	#
+	local $_ = $_[0];
+
+	while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) {
+		my ($pre_tabs, $label, $rest) = ($1, $2, $3);
+		$_ = $pre_tabs;
+		while ($label =~ s/^([^\t]*)(\t+)//) {
+			$_ .= "\t" x (length($2) + length($1) / 8);
+		}
+		$_ .= ("\t" x (length($label) / 8)).$rest;
+	}
+
+	return ($_);
+}
+
+sub
+process_indent($)
+{
+	require strict;
+	local $_ = $_[0];			# preserve the global $_
+
+	s///g;	# No comments
+	s/\s+$//;	# Strip trailing whitespace
+
+	return			if (/^$/);	# skip empty lines
+
+	# regexps used below; keywords taking (), macros, and continued cases
+	my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b';
+	my $macro = '[A-Z_][A-Z_0-9]*\(';
+	my $case = 'case\b[^:]*$';
+
+	# skip over enumerations, array definitions, initializers, etc.
+	if ($cont_off <= 0 && !/^\s*$special/ &&
+	    (/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*)){/ ||
+	    (/^\s*{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) {
+		$cont_in = 0;
+		$cont_off = tr/{/{/ - tr/}/}/;
+		return;
+	}
+	if ($cont_off) {
+		$cont_off += tr/{/{/ - tr/}/}/;
+		return;
+	}
+
+	if (!$cont_in) {
+		$cont_start = $line;
+
+		if (/^\t* /) {
+			err("non-continuation indented 4 spaces");
+			$cont_noerr = 1;		# stop reporting
+		}
+		$_ = delabel($_);	# replace labels with tabs
+
+		# check if the statement is complete
+		return		if (/^\s*\}?$/);
+		return		if (/^\s*\}?\s*else\s*\{?$/);
+		return		if (/^\s*do\s*\{?$/);
+		return		if (/{$/);
+		return		if (/}[,;]?$/);
+
+		# Allow macros on their own lines
+		return		if (/^\s*[A-Z_][A-Z_0-9]*$/);
+
+		# cases we don't deal with, generally non-kosher
+		if (/{/) {
+			err("stuff after {");
+			return;
+		}
+
+		# Get the base line, and set up the state machine
+		/^(\t*)/;
+		$cont_base = $1;
+		$cont_in = 1;
+		@cont_paren = ();
+		$cont_first = 1;
+		$cont_multiseg = 0;
+
+		# certain things need special processing
+		$cont_special = /^\s*$special/? 1 : 0;
+		$cont_macro = /^\s*$macro/? 1 : 0;
+		$cont_case = /^\s*$case/? 1 : 0;
+	} else {
+		$cont_first = 0;
+
+		# Strings may be pulled back to an earlier (half-)tabstop
+		unless ($cont_noerr || /^$cont_base    / ||
+		    (/^\t*(?:    )?(?:gettext\()?\"/ && !/^$cont_base\t/)) {
+			err_prefix($cont_start,
+			    "continuation should be indented 4 spaces");
+		}
+	}
+
+	my $rest = $_;			# keeps the remainder of the line
+
+	#
+	# The split matches 0 characters, so that each 'special' character
+	# is processed separately.  Parens and brackets are pushed and
+	# popped off the @cont_paren stack.  For normal processing, we wait
+	# until a ; or { terminates the statement.  "special" processing
+	# (if/for/while/switch) is allowed to stop when the stack empties,
+	# as is macro processing.  Case statements are terminated with a :
+	# and an empty paren stack.
+	#
+	foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) {
+		next		if (length($_) == 0);
+
+		# rest contains the remainder of the line
+		my $rxp = "[^\Q$_\E]*\Q$_\E";
+		$rest =~ s/^$rxp//;
+
+		if (/\(/ || /\[/) {
+			push @cont_paren, $_;
+		} elsif (/\)/ || /\]/) {
+			my $cur = $_;
+			tr/\)\]/\(\[/;
+
+			my $old = (pop @cont_paren);
+			if (!defined($old)) {
+				err("unexpected '$cur'");
+				$cont_in = 0;
+				last;
+			} elsif ($old ne $_) {
+				err("'$cur' mismatched with '$old'");
+				$cont_in = 0;
+				last;
+			}
+
+			#
+			# If the stack is now empty, do special processing
+			# for if/for/while/switch and macro statements.
+			#
+			next		if (@cont_paren != 0);
+			if ($cont_special) {
+				if ($rest =~ /^\s*{?$/) {
+					$cont_in = 0;
+					last;
+				}
+				if ($rest =~ /^\s*;$/) {
+					err("empty if/for/while body ".
+					    "not on its own line");
+					$cont_in = 0;
+					last;
+				}
+				if (!$cont_first && $cont_multiseg == 1) {
+					err_prefix($cont_start,
+					    "multiple statements continued ".
+					    "over multiple lines");
+					$cont_multiseg = 2;
+				} elsif ($cont_multiseg == 0) {
+					$cont_multiseg = 1;
+				}
+				# We've finished this section, start
+				# processing the next.
+				goto section_ended;
+			}
+			if ($cont_macro) {
+				if ($rest =~ /^$/) {
+					$cont_in = 0;
+					last;
+				}
+			}
+		} elsif (/\;/) {
+			if ($cont_case) {
+				err("unexpected ;");
+			} elsif (!$cont_special) {
+				err("unexpected ;")	if (@cont_paren != 0);
+				if (!$cont_first && $cont_multiseg == 1) {
+					err_prefix($cont_start,
+					    "multiple statements continued ".
+					    "over multiple lines");
+					$cont_multiseg = 2;
+				} elsif ($cont_multiseg == 0) {
+					$cont_multiseg = 1;
+				}
+				if ($rest =~ /^$/) {
+					$cont_in = 0;
+					last;
+				}
+				if ($rest =~ /^\s*special/) {
+					err("if/for/while/switch not started ".
+					    "on its own line");
+				}
+				goto section_ended;
+			}
+		} elsif (/\{/) {
+			err("{ while in parens/brackets") if (@cont_paren != 0);
+			err("stuff after {")		if ($rest =~ /[^\s}]/);
+			$cont_in = 0;
+			last;
+		} elsif (/\}/) {
+			err("} while in parens/brackets") if (@cont_paren != 0);
+			if (!$cont_special && $rest !~ /^\s*(while|else)\b/) {
+				if ($rest =~ /^$/) {
+					err("unexpected }");
+				} else {
+					err("stuff after }");
+				}
+				$cont_in = 0;
+				last;
+			}
+		} elsif (/\:/ && $cont_case && @cont_paren == 0) {
+			err("stuff after multi-line case") if ($rest !~ /$^/);
+			$cont_in = 0;
+			last;
+		}
+		next;
+section_ended:
+		# End of a statement or if/while/for loop.  Reset
+		# cont_special and cont_macro based on the rest of the
+		# line.
+		$cont_special = ($rest =~ /^\s*$special/)? 1 : 0;
+		$cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0;
+		$cont_case = 0;
+		next;
+	}
+	$cont_noerr = 0			if (!$cont_in);
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/float.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/float.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/float.json	(revision 484)
@@ -0,0 +1,13 @@
+{ "metadata":
+	{
+		"ctf2json_version": "1.0",
+		"created_at": 1316563626,
+		"derived_from": "/lib/libc.so",
+		"ctf_version": 2,
+		"requested_types": [ "float" ]
+	},
+"data":
+	[
+		{ "name": "float", "float": { "length": 4 } }
+	]
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/int.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/int.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/int.json	(revision 484)
@@ -0,0 +1,13 @@
+{ "metadata":
+	{
+		"ctf2json_version": "1.0",
+		"created_at": 1316563631,
+		"derived_from": "/lib/libc.so",
+		"ctf_version": 2,
+		"requested_types": [ "int" ]
+	},
+"data":
+	[
+		{ "name": "int", "integer": { "length": 4, "signed": true } }
+	]
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/psinfo.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/psinfo.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/psinfo.json	(revision 484)
@@ -0,0 +1,104 @@
+{ "metadata":
+	{
+		"ctf2json_version": "1.0",
+		"created_at": 1316563573,
+		"derived_from": "/lib/libc.so",
+		"ctf_version": 2,
+		"requested_types": [ "psinfo_t" ]
+	},
+"data":
+	[
+		{ "name": "int", "integer": { "length": 4, "signed": true } },
+		{ "name": "char", "integer": { "length": 1, "signed": true } },
+		{ "name": "unsigned short", "integer": { "length": 2, "signed": false } },
+		{ "name": "long", "integer": { "length": 4, "signed": true } },
+		{ "name": "unsigned", "integer": { "length": 4, "signed": false } },
+		{ "name": "size_t", "typedef": "unsigned" },
+		{ "name": "unsigned long", "integer": { "length": 4, "signed": false } },
+		{ "name": "time_t", "typedef": "long" },
+		{ "name": "struct timespec", "struct": [
+			{ "name": "tv_sec", "type": "time_t" },
+			{ "name": "tv_nsec", "type": "long" }
+		] },
+		{ "name": "zoneid_t", "typedef": "long" },
+		{ "name": "taskid_t", "typedef": "long" },
+		{ "name": "dev_t", "typedef": "unsigned long" },
+		{ "name": "uid_t", "typedef": "unsigned" },
+		{ "name": "gid_t", "typedef": "unsigned" },
+		{ "name": "timestruc_t", "typedef": "struct timespec" },
+		{ "name": "short", "integer": { "length": 2, "signed": true } },
+		{ "name": "projid_t", "typedef": "long" },
+		{ "name": "ushort_t", "typedef": "unsigned short" },
+		{ "name": "poolid_t", "typedef": "long" },
+		{ "name": "uintptr_t", "typedef": "unsigned" },
+		{ "name": "id_t", "typedef": "long" },
+		{ "name": "pid_t", "typedef": "long" },
+		{ "name": "processorid_t", "typedef": "int" },
+		{ "name": "psetid_t", "typedef": "int" },
+		{ "name": "struct lwpsinfo", "struct": [
+			{ "name": "pr_flag", "type": "int" },
+			{ "name": "pr_lwpid", "type": "id_t" },
+			{ "name": "pr_addr", "type": "uintptr_t" },
+			{ "name": "pr_wchan", "type": "uintptr_t" },
+			{ "name": "pr_stype", "type": "char" },
+			{ "name": "pr_state", "type": "char" },
+			{ "name": "pr_sname", "type": "char" },
+			{ "name": "pr_nice", "type": "char" },
+			{ "name": "pr_syscall", "type": "short" },
+			{ "name": "pr_oldpri", "type": "char" },
+			{ "name": "pr_cpu", "type": "char" },
+			{ "name": "pr_pri", "type": "int" },
+			{ "name": "pr_pctcpu", "type": "ushort_t" },
+			{ "name": "pr_pad", "type": "ushort_t" },
+			{ "name": "pr_start", "type": "timestruc_t" },
+			{ "name": "pr_time", "type": "timestruc_t" },
+			{ "name": "pr_clname", "type": "char [8]" },
+			{ "name": "pr_name", "type": "char [16]" },
+			{ "name": "pr_onpro", "type": "processorid_t" },
+			{ "name": "pr_bindpro", "type": "processorid_t" },
+			{ "name": "pr_bindpset", "type": "psetid_t" },
+			{ "name": "pr_lgrp", "type": "int" },
+			{ "name": "pr_filler", "type": "int [4]" }
+		] },
+		{ "name": "lwpsinfo_t", "typedef": "struct lwpsinfo" },
+		{ "name": "struct psinfo", "struct": [
+			{ "name": "pr_flag", "type": "int" },
+			{ "name": "pr_nlwp", "type": "int" },
+			{ "name": "pr_pid", "type": "pid_t" },
+			{ "name": "pr_ppid", "type": "pid_t" },
+			{ "name": "pr_pgid", "type": "pid_t" },
+			{ "name": "pr_sid", "type": "pid_t" },
+			{ "name": "pr_uid", "type": "uid_t" },
+			{ "name": "pr_euid", "type": "uid_t" },
+			{ "name": "pr_gid", "type": "gid_t" },
+			{ "name": "pr_egid", "type": "gid_t" },
+			{ "name": "pr_addr", "type": "uintptr_t" },
+			{ "name": "pr_size", "type": "size_t" },
+			{ "name": "pr_rssize", "type": "size_t" },
+			{ "name": "pr_pad1", "type": "size_t" },
+			{ "name": "pr_ttydev", "type": "dev_t" },
+			{ "name": "pr_pctcpu", "type": "ushort_t" },
+			{ "name": "pr_pctmem", "type": "ushort_t" },
+			{ "name": "pr_start", "type": "timestruc_t" },
+			{ "name": "pr_time", "type": "timestruc_t" },
+			{ "name": "pr_ctime", "type": "timestruc_t" },
+			{ "name": "pr_fname", "type": "char [16]" },
+			{ "name": "pr_psargs", "type": "char [80]" },
+			{ "name": "pr_wstat", "type": "int" },
+			{ "name": "pr_argc", "type": "int" },
+			{ "name": "pr_argv", "type": "uintptr_t" },
+			{ "name": "pr_envp", "type": "uintptr_t" },
+			{ "name": "pr_dmodel", "type": "char" },
+			{ "name": "pr_pad2", "type": "char [3]" },
+			{ "name": "pr_taskid", "type": "taskid_t" },
+			{ "name": "pr_projid", "type": "projid_t" },
+			{ "name": "pr_nzomb", "type": "int" },
+			{ "name": "pr_poolid", "type": "poolid_t" },
+			{ "name": "pr_zoneid", "type": "zoneid_t" },
+			{ "name": "pr_contract", "type": "id_t" },
+			{ "name": "pr_filler", "type": "int [1]" },
+			{ "name": "pr_lwp", "type": "lwpsinfo_t" }
+		] },
+		{ "name": "psinfo_t", "typedef": "struct psinfo" }
+	]
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/struct.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/struct.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/struct.json	(revision 484)
@@ -0,0 +1,19 @@
+{ "metadata":
+	{
+		"ctf2json_version": "1.0",
+		"created_at": 1316563648,
+		"derived_from": "/lib/libc.so",
+		"ctf_version": 2,
+		"requested_types": [ "timestruc_t" ]
+	},
+"data":
+	[
+		{ "name": "long", "integer": { "length": 4, "signed": true } },
+		{ "name": "time_t", "typedef": "long" },
+		{ "name": "struct timespec", "struct": [
+			{ "name": "tv_sec", "type": "time_t" },
+			{ "name": "tv_nsec", "type": "long" }
+		] },
+		{ "name": "timestruc_t", "typedef": "struct timespec" }
+	]
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.fail.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.fail.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.fail.js	(revision 484)
@@ -0,0 +1,39 @@
+/*
+ * Test several conditions that should always cause us to throw.
+ */
+var mod_assert = require('assert');
+var mod_ctype = require('../../ctype.js');
+
+var cases = [
+{ json: { }, msg: 'bad JSON - no metadata or data' },
+{ json: { metadata: {} }, msg: 'bad JSON - bad metadata section' },
+{ json: { metadata: { 'JSON version': [] } },
+    msg: 'bad JSON - bad JSON version' },
+{ json: { metadata: { 'JSON version': 2 } },
+    msg: 'bad JSON - bad JSON version' },
+{ json: { metadata: { 'JSON version': '100.20' } },
+    msg: 'bad JSON - bad JSON version' },
+{ json: { metadata: { 'JSON version': '1.0' } },
+    msg: 'missing data section' },
+{ json: { metadata: { 'JSON version': '1.0' }, data: 1 },
+    msg: 'invalid data section' },
+{ json: { metadata: { 'JSON version': '1.0' }, data: 1.1 },
+    msg: 'invalid data section' },
+{ json: { metadata: { 'JSON version': '1.0' }, data: '1.1' },
+    msg: 'invalid data section' },
+{ json: { metadata: { 'JSON version': '1.0' }, data: {} },
+    msg: 'invalid data section' }
+];
+
+function test()
+{
+	var ii;
+
+	for (ii = 0; ii < cases.length; ii++) {
+		mod_assert.throws(function () {
+		    mod_ctype.parseCTF(cases[ii].json);
+		}, Error, cases[ii].msg);
+	}
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.float.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.float.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.float.js	(revision 484)
@@ -0,0 +1,14 @@
+var mod_fs = require('fs');
+var mod_ctype = require('../../ctype.js');
+var mod_assert = require('assert');
+
+function test()
+{
+	var data, parser;
+
+	data = JSON.parse(mod_fs.readFileSync('./float.json').toString());
+	parser = mod_ctype.parseCTF(data, { endian: 'big' });
+	mod_assert.deepEqual(parser.lstypes(), {});
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.int.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.int.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.int.js	(revision 484)
@@ -0,0 +1,14 @@
+var mod_fs = require('fs');
+var mod_ctype = require('../../ctype.js');
+var mod_assert = require('assert');
+
+function test()
+{
+	var data, parser;
+
+	data = JSON.parse(mod_fs.readFileSync('./int.json').toString());
+	parser = mod_ctype.parseCTF(data, { endian: 'big' });
+	mod_assert.deepEqual(parser.lstypes(), { 'int': 'int32_t' });
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.psinfo.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.psinfo.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.psinfo.js	(revision 484)
@@ -0,0 +1,17 @@
+var mod_fs = require('fs');
+var mod_ctype = require('../../ctype.js');
+var mod_assert = require('assert');
+
+/*
+ * This is too unwieldly to actually write out. Just make sure we can parse it
+ * without errrors.
+ */
+function test()
+{
+	var data;
+
+	data = JSON.parse(mod_fs.readFileSync('./psinfo.json').toString());
+	mod_ctype.parseCTF(data, { endian: 'big' });
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.struct.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.struct.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.struct.js	(revision 484)
@@ -0,0 +1,18 @@
+var mod_fs = require('fs');
+var mod_ctype = require('../../ctype.js');
+var mod_assert = require('assert');
+
+function test()
+{
+	var data, parser;
+
+	data = JSON.parse(mod_fs.readFileSync('./struct.json').toString());
+	parser = mod_ctype.parseCTF(data, { endian: 'big' });
+	mod_assert.deepEqual(parser.lstypes(), { 'long': 'int32_t',
+	    'time_t': 'long',
+	    'timestruc_t': 'struct timespec',
+	    'struct timespec': [ { 'tv_sec': { 'type': 'time_t' } },
+	        { 'tv_nsec': { 'type': 'long' } } ] });
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.typedef.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.typedef.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/tst.typedef.js	(revision 484)
@@ -0,0 +1,15 @@
+var mod_fs = require('fs');
+var mod_ctype = require('../../ctype.js');
+var mod_assert = require('assert');
+
+function test()
+{
+	var data, parser;
+
+	data = JSON.parse(mod_fs.readFileSync('./typedef.json').toString());
+	parser = mod_ctype.parseCTF(data, { endian: 'big' });
+	mod_assert.deepEqual(parser.lstypes(), { 'bar_t': 'int',
+	    'int': 'int32_t' });
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/typedef.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/typedef.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctf/typedef.json	(revision 484)
@@ -0,0 +1,14 @@
+{ "metadata":
+	{
+		"ctf2json_version": "1.0",
+		"created_at": 1316302348,
+		"derived_from": "/lib/libc.so",
+		"ctf_version": 2,
+		"requested_types": [ "bar_t" ]
+	},
+"data":
+	[
+		{ "name": "int", "integer": { "length": 4, "signed": true } },
+		{ "name": "bar_t", "typedef": "int" }
+	]
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.rfloat.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.rfloat.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.rfloat.js	(revision 484)
@@ -0,0 +1,767 @@
+/*
+ * Battery of tests to break our floating point implementation. Oh ho ho.
+ *
+ * There are a few useful ways to generate the expected output. The first is
+ * just write a C program and write raw bytes out and inspect with xxd. Remember
+ * to consider whether or not you're on a big endian or little endian machine.
+ * Another useful site I found to help with some of this was:
+ *
+ * http://babbage.cs.qc.edu/IEEE-754/
+ */
+
+var mod_ctype = require('../../../ctio.js');
+var ASSERT = require('assert');
+
+function testfloat()
+{
+	var buffer = new Buffer(4);
+	/* Start off with some of the easy ones: +zero */
+	buffer[0] = 0;
+	buffer[1] = 0;
+	buffer[2] = 0;
+	buffer[3] = 0;
+
+	ASSERT.equal(0, mod_ctype.rfloat(buffer, 'big', 0));
+	ASSERT.equal(0, mod_ctype.rfloat(buffer, 'little', 0));
+
+	/* Test -0 */
+	buffer[0] = 0x80;
+	ASSERT.equal(0, mod_ctype.rfloat(buffer, 'big', 0));
+	buffer[3] = buffer[0];
+	buffer[0] = 0;
+	ASSERT.equal(0, mod_ctype.rfloat(buffer, 'little', 0));
+
+	/* Catch +infin */
+	buffer[0] = 0x7f;
+	buffer[1] = 0x80;
+	buffer[2] = 0x00;
+	buffer[3] = 0x00;
+	ASSERT.equal(Number.POSITIVE_INFINITY,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+	buffer[3] = 0x7f;
+	buffer[2] = 0x80;
+	buffer[1] = 0x00;
+	buffer[0] = 0x00;
+	ASSERT.equal(Number.POSITIVE_INFINITY,
+	    mod_ctype.rfloat(buffer, 'litle', 0));
+
+	/* Catch -infin */
+	buffer[0] = 0xff;
+	buffer[1] = 0x80;
+	buffer[2] = 0x00;
+	buffer[3] = 0x00;
+	ASSERT.equal(Number.NEGATIVE_INFINITY,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+	buffer[3] = 0xff;
+	buffer[2] = 0x80;
+	buffer[1] = 0x00;
+	buffer[0] = 0x00;
+	ASSERT.equal(Number.NEGATIVE_INFINITY,
+	    mod_ctype.rfloat(buffer, 'litle', 0));
+
+	/* Catch NaN */
+
+	buffer[0] = 0x7f;
+	buffer[1] = 0x80;
+	buffer[2] = 0x00;
+	buffer[3] = 0x23;
+	ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'big', 0)));
+	buffer[3] = 0x7f;
+	buffer[2] = 0x80;
+	buffer[1] = 0x00;
+	buffer[0] = 0x23;
+	ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'little', 0)));
+
+	/* Catch -infin */
+	buffer[0] = 0xff;
+	buffer[1] = 0x80;
+	buffer[2] = 0x00;
+	buffer[3] = 0x23;
+	ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'big', 0)));
+	buffer[3] = 0xff;
+	buffer[2] = 0x80;
+	buffer[1] = 0x00;
+	buffer[0] = 0x23;
+	ASSERT.ok(isNaN(mod_ctype.rfloat(buffer, 'little', 0)));
+
+	/* On to some basic tests */
+	/* 1.125 */
+	buffer[0] = 0x3f;
+	buffer[1] = 0x90;
+	buffer[2] = 0x00;
+	buffer[3] = 0x00;
+	ASSERT.equal(1.125, mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x3f;
+	buffer[2] = 0x90;
+	buffer[1] = 0x00;
+	buffer[0] = 0x00;
+	ASSERT.equal(1.125, mod_ctype.rfloat(buffer, 'little', 0));
+
+	/* ff34a2b0 -2.4010576103645774e+38 */
+	buffer[0] = 0xff;
+	buffer[1] = 0x34;
+	buffer[2] = 0xa2;
+	buffer[3] = 0xb0;
+	ASSERT.equal(-2.4010576103645774e+38,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0xff;
+	buffer[2] = 0x34;
+	buffer[1] = 0xa2;
+	buffer[0] = 0xb0;
+	ASSERT.equal(-2.4010576103645774e+38,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+	/* Denormalized tests */
+
+	/* 0003f89a +/- 3.6468792534053364e-40 */
+	buffer[0] = 0x00;
+	buffer[1] = 0x03;
+	buffer[2] = 0xf8;
+	buffer[3] = 0x9a;
+	ASSERT.equal(3.6468792534053364e-40,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x00;
+	buffer[2] = 0x03;
+	buffer[1] = 0xf8;
+	buffer[0] = 0x9a;
+	ASSERT.equal(3.6468792534053364e-40,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+	buffer[0] = 0x80;
+	buffer[1] = 0x03;
+	buffer[2] = 0xf8;
+	buffer[3] = 0x9a;
+	ASSERT.equal(-3.6468792534053364e-40,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x80;
+	buffer[2] = 0x03;
+	buffer[1] = 0xf8;
+	buffer[0] = 0x9a;
+	ASSERT.equal(-3.6468792534053364e-40,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+
+	/* Maximum and minimum normalized and denormalized values */
+
+	/* Largest normalized number +/- 3.4028234663852886e+38 */
+
+	buffer[0] = 0x7f;
+	buffer[1] = 0x7f;
+	buffer[2] = 0xff;
+	buffer[3] = 0xff;
+	ASSERT.equal(3.4028234663852886e+38,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x7f;
+	buffer[2] = 0x7f;
+	buffer[1] = 0xff;
+	buffer[0] = 0xff;
+	ASSERT.equal(3.4028234663852886e+38,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+	buffer[0] = 0xff;
+	buffer[1] = 0x7f;
+	buffer[2] = 0xff;
+	buffer[3] = 0xff;
+	ASSERT.equal(-3.4028234663852886e+38,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0xff;
+	buffer[2] = 0x7f;
+	buffer[1] = 0xff;
+	buffer[0] = 0xff;
+	ASSERT.equal(-3.4028234663852886e+38,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+	/* Smallest normalied number +/- 1.1754943508222875e-38 */
+	buffer[0] = 0x00;
+	buffer[1] = 0x80;
+	buffer[2] = 0x00;
+	buffer[3] = 0x00;
+	ASSERT.equal(1.1754943508222875e-38,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x00;
+	buffer[2] = 0x80;
+	buffer[1] = 0x00;
+	buffer[0] = 0x00;
+	ASSERT.equal(1.1754943508222875e-38,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+	buffer[0] = 0x80;
+	buffer[1] = 0x80;
+	buffer[2] = 0x00;
+	buffer[3] = 0x00;
+	ASSERT.equal(-1.1754943508222875e-38,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x80;
+	buffer[2] = 0x80;
+	buffer[1] = 0x00;
+	buffer[0] = 0x00;
+	ASSERT.equal(-1.1754943508222875e-38,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+
+	/* Smallest denormalized number 1.401298464324817e-45 */
+	buffer[0] = 0x00;
+	buffer[1] = 0x00;
+	buffer[2] = 0x00;
+	buffer[3] = 0x01;
+	ASSERT.equal(1.401298464324817e-45,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x00;
+	buffer[2] = 0x00;
+	buffer[1] = 0x00;
+	buffer[0] = 0x01;
+	ASSERT.equal(1.401298464324817e-45,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+	buffer[0] = 0x80;
+	buffer[1] = 0x00;
+	buffer[2] = 0x00;
+	buffer[3] = 0x01;
+	ASSERT.equal(-1.401298464324817e-45,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x80;
+	buffer[2] = 0x00;
+	buffer[1] = 0x00;
+	buffer[0] = 0x01;
+	ASSERT.equal(-1.401298464324817e-45,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+	/* Largest denormalized value +/- 1.1754942106924411e-38 */
+	buffer[0] = 0x00;
+	buffer[1] = 0x7f;
+	buffer[2] = 0xff;
+	buffer[3] = 0xff;
+	ASSERT.equal(1.1754942106924411e-38,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x00;
+	buffer[2] = 0x7f;
+	buffer[1] = 0xff;
+	buffer[0] = 0xff;
+	ASSERT.equal(1.1754942106924411e-38,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+	buffer[0] = 0x80;
+	buffer[1] = 0x7f;
+	buffer[2] = 0xff;
+	buffer[3] = 0xff;
+	ASSERT.equal(-1.1754942106924411e-38,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+
+	buffer[3] = 0x80;
+	buffer[2] = 0x7f;
+	buffer[1] = 0xff;
+	buffer[0] = 0xff;
+	ASSERT.equal(-1.1754942106924411e-38,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+
+	/* Do some quick offset testing */
+	buffer = new Buffer(6);
+	buffer[0] = 0x7f;
+	buffer[1] = 0x4e;
+	buffer[2] = 0x8a;
+	buffer[3] = 0x79;
+	buffer[4] = 0xcd;
+	buffer[5] = 0x3f;
+
+	ASSERT.equal(2.745399582697325e+38,
+	    mod_ctype.rfloat(buffer, 'big', 0));
+	ASSERT.equal(1161619072,
+	    mod_ctype.rfloat(buffer, 'big', 1));
+	ASSERT.equal(-1.2027516403607578e-32,
+	    mod_ctype.rfloat(buffer, 'big', 2));
+
+	ASSERT.equal(8.97661320504413e+34,
+	    mod_ctype.rfloat(buffer, 'little', 0));
+	ASSERT.equal(-261661920,
+	    mod_ctype.rfloat(buffer, 'little', 1));
+	ASSERT.equal(1.605271577835083,
+	    mod_ctype.rfloat(buffer, 'little', 2));
+
+}
+
+function testdouble()
+{
+	var buffer = new Buffer(10);
+
+	/* Check 0 */
+	buffer[0] = 0;
+	buffer[1] = 0;
+	buffer[2] = 0;
+	buffer[3] = 0;
+	buffer[4] = 0;
+	buffer[5] = 0;
+	buffer[6] = 0;
+	buffer[7] = 0;
+	ASSERT.equal(0,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+	ASSERT.equal(0,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	buffer[0] = 0x80;
+	buffer[1] = 0;
+	buffer[2] = 0;
+	buffer[3] = 0;
+	buffer[4] = 0;
+	buffer[5] = 0;
+	buffer[6] = 0;
+	buffer[7] = 0;
+	ASSERT.equal(0,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+	buffer[7] = 0x80;
+	buffer[6] = 0;
+	buffer[5] = 0;
+	buffer[4] = 0;
+	buffer[3] = 0;
+	buffer[2] = 0;
+	buffer[1] = 0;
+	buffer[0] = 0;
+	ASSERT.equal(0,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* Check NaN */
+	buffer[0] = 0x7f;
+	buffer[1] = 0xf0;
+	buffer[2] = 0;
+	buffer[3] = 0;
+	buffer[4] = 0;
+	buffer[5] = 0;
+	buffer[6] = 0;
+	buffer[7] = 23;
+	ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'big', 0)));
+
+	buffer[7] = 0x7f;
+	buffer[6] = 0xf0;
+	buffer[5] = 0;
+	buffer[4] = 0;
+	buffer[3] = 0;
+	buffer[2] = 0;
+	buffer[1] = 0;
+	buffer[0] = 23;
+	ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'little', 0)));
+
+	buffer[0] = 0xff;
+	buffer[1] = 0xf0;
+	buffer[2] = 0;
+	buffer[3] = 0;
+	buffer[4] = 0;
+	buffer[5] = 0;
+	buffer[6] = 0;
+	buffer[7] = 23;
+	ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'big', 0)));
+
+	buffer[7] = 0xff;
+	buffer[6] = 0xf0;
+	buffer[5] = 0;
+	buffer[4] = 0;
+	buffer[3] = 0;
+	buffer[2] = 0;
+	buffer[1] = 0;
+	buffer[0] = 23;
+	ASSERT.ok(isNaN(mod_ctype.rdouble(buffer, 'little', 0)));
+
+	/* pos inf */
+	buffer[0] = 0x7f;
+	buffer[1] = 0xf0;
+	buffer[2] = 0;
+	buffer[3] = 0;
+	buffer[4] = 0;
+	buffer[5] = 0;
+	buffer[6] = 0;
+	buffer[7] = 0;
+	ASSERT.equal(Number.POSITIVE_INFINITY,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x7f;
+	buffer[6] = 0xf0;
+	buffer[5] = 0;
+	buffer[4] = 0;
+	buffer[3] = 0;
+	buffer[2] = 0;
+	buffer[1] = 0;
+	buffer[0] = 0;
+	ASSERT.equal(Number.POSITIVE_INFINITY,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* neg inf */
+	buffer[0] = 0xff;
+	buffer[1] = 0xf0;
+	buffer[2] = 0;
+	buffer[3] = 0;
+	buffer[4] = 0;
+	buffer[5] = 0;
+	buffer[6] = 0;
+	buffer[7] = 0;
+	ASSERT.equal(Number.NEGATIVE_INFINITY,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0xff;
+	buffer[6] = 0xf0;
+	buffer[5] = 0;
+	buffer[4] = 0;
+	buffer[3] = 0;
+	buffer[2] = 0;
+	buffer[1] = 0;
+	buffer[0] = 0;
+	ASSERT.equal(Number.NEGATIVE_INFINITY,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* Simple normalized values */
+
+	/* +/- 1.125 */
+	buffer[0] = 0x3f;
+	buffer[1] = 0xf2;
+	buffer[2] = 0;
+	buffer[3] = 0;
+	buffer[4] = 0;
+	buffer[5] = 0;
+	buffer[6] = 0;
+	buffer[7] = 0;
+	ASSERT.equal(1.125,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x3f;
+	buffer[6] = 0xf2;
+	buffer[5] = 0;
+	buffer[4] = 0;
+	buffer[3] = 0;
+	buffer[2] = 0;
+	buffer[1] = 0;
+	buffer[0] = 0;
+	ASSERT.equal(1.125,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	buffer[0] = 0xbf;
+	buffer[1] = 0xf2;
+	buffer[2] = 0;
+	buffer[3] = 0;
+	buffer[4] = 0;
+	buffer[5] = 0;
+	buffer[6] = 0;
+	buffer[7] = 0;
+	ASSERT.equal(-1.125,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0xbf;
+	buffer[6] = 0xf2;
+	buffer[5] = 0;
+	buffer[4] = 0;
+	buffer[3] = 0;
+	buffer[2] = 0;
+	buffer[1] = 0;
+	buffer[0] = 0;
+	ASSERT.equal(-1.125,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* +/- 1.4397318913736026e+283 */
+	buffer[0] = 0x7a;
+	buffer[1] = 0xb8;
+	buffer[2] = 0xc9;
+	buffer[3] = 0x34;
+	buffer[4] = 0x72;
+	buffer[5] = 0x16;
+	buffer[6] = 0xf9;
+	buffer[7] = 0x0e;
+	ASSERT.equal(1.4397318913736026e+283,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x7a;
+	buffer[6] = 0xb8;
+	buffer[5] = 0xc9;
+	buffer[4] = 0x34;
+	buffer[3] = 0x72;
+	buffer[2] = 0x16;
+	buffer[1] = 0xf9;
+	buffer[0] = 0x0e;
+	ASSERT.equal(1.4397318913736026e+283,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	buffer[0] = 0xfa;
+	buffer[1] = 0xb8;
+	buffer[2] = 0xc9;
+	buffer[3] = 0x34;
+	buffer[4] = 0x72;
+	buffer[5] = 0x16;
+	buffer[6] = 0xf9;
+	buffer[7] = 0x0e;
+	ASSERT.equal(-1.4397318913736026e+283,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0xfa;
+	buffer[6] = 0xb8;
+	buffer[5] = 0xc9;
+	buffer[4] = 0x34;
+	buffer[3] = 0x72;
+	buffer[2] = 0x16;
+	buffer[1] = 0xf9;
+	buffer[0] = 0x0e;
+	ASSERT.equal(-1.4397318913736026e+283,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* Denormalized values */
+	/* +/- 8.82521232268344e-309 */
+	buffer[0] = 0x00;
+	buffer[1] = 0x06;
+	buffer[2] = 0x58;
+	buffer[3] = 0x94;
+	buffer[4] = 0x13;
+	buffer[5] = 0x27;
+	buffer[6] = 0x8a;
+	buffer[7] = 0xcd;
+	ASSERT.equal(8.82521232268344e-309,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x00;
+	buffer[6] = 0x06;
+	buffer[5] = 0x58;
+	buffer[4] = 0x94;
+	buffer[3] = 0x13;
+	buffer[2] = 0x27;
+	buffer[1] = 0x8a;
+	buffer[0] = 0xcd;
+	ASSERT.equal(8.82521232268344e-309,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	buffer[0] = 0x80;
+	buffer[1] = 0x06;
+	buffer[2] = 0x58;
+	buffer[3] = 0x94;
+	buffer[4] = 0x13;
+	buffer[5] = 0x27;
+	buffer[6] = 0x8a;
+	buffer[7] = 0xcd;
+	ASSERT.equal(-8.82521232268344e-309,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x80;
+	buffer[6] = 0x06;
+	buffer[5] = 0x58;
+	buffer[4] = 0x94;
+	buffer[3] = 0x13;
+	buffer[2] = 0x27;
+	buffer[1] = 0x8a;
+	buffer[0] = 0xcd;
+	ASSERT.equal(-8.82521232268344e-309,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* Edge cases, maximum and minimum values */
+
+	/* Smallest denormalized value 5e-324 */
+	buffer[0] = 0x00;
+	buffer[1] = 0x00;
+	buffer[2] = 0x00;
+	buffer[3] = 0x00;
+	buffer[4] = 0x00;
+	buffer[5] = 0x00;
+	buffer[6] = 0x00;
+	buffer[7] = 0x01;
+	ASSERT.equal(5e-324,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x00;
+	buffer[6] = 0x00;
+	buffer[5] = 0x00;
+	buffer[4] = 0x00;
+	buffer[3] = 0x00;
+	buffer[2] = 0x00;
+	buffer[1] = 0x00;
+	buffer[0] = 0x01;
+	ASSERT.equal(5e-324,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	buffer[0] = 0x80;
+	buffer[1] = 0x00;
+	buffer[2] = 0x00;
+	buffer[3] = 0x00;
+	buffer[4] = 0x00;
+	buffer[5] = 0x00;
+	buffer[6] = 0x00;
+	buffer[7] = 0x01;
+	ASSERT.equal(-5e-324,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x80;
+	buffer[6] = 0x00;
+	buffer[5] = 0x00;
+	buffer[4] = 0x00;
+	buffer[3] = 0x00;
+	buffer[2] = 0x00;
+	buffer[1] = 0x00;
+	buffer[0] = 0x01;
+	ASSERT.equal(-5e-324,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* Largest denormalized value 2.225073858507201e-308 */
+	buffer[0] = 0x00;
+	buffer[1] = 0x0f;
+	buffer[2] = 0xff;
+	buffer[3] = 0xff;
+	buffer[4] = 0xff;
+	buffer[5] = 0xff;
+	buffer[6] = 0xff;
+	buffer[7] = 0xff;
+	ASSERT.equal(2.225073858507201e-308,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x00;
+	buffer[6] = 0x0f;
+	buffer[5] = 0xff;
+	buffer[4] = 0xff;
+	buffer[3] = 0xff;
+	buffer[2] = 0xff;
+	buffer[1] = 0xff;
+	buffer[0] = 0xff;
+	ASSERT.equal(2.225073858507201e-308,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	buffer[0] = 0x80;
+	buffer[1] = 0x0f;
+	buffer[2] = 0xff;
+	buffer[3] = 0xff;
+	buffer[4] = 0xff;
+	buffer[5] = 0xff;
+	buffer[6] = 0xff;
+	buffer[7] = 0xff;
+	ASSERT.equal(-2.225073858507201e-308,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x80;
+	buffer[6] = 0x0f;
+	buffer[5] = 0xff;
+	buffer[4] = 0xff;
+	buffer[3] = 0xff;
+	buffer[2] = 0xff;
+	buffer[1] = 0xff;
+	buffer[0] = 0xff;
+	ASSERT.equal(-2.225073858507201e-308,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* Smallest normalized value 2.2250738585072014e-308 */
+	buffer[0] = 0x00;
+	buffer[1] = 0x10;
+	buffer[2] = 0x00;
+	buffer[3] = 0x00;
+	buffer[4] = 0x00;
+	buffer[5] = 0x00;
+	buffer[6] = 0x00;
+	buffer[7] = 0x00;
+	ASSERT.equal(2.2250738585072014e-308,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x00;
+	buffer[6] = 0x10;
+	buffer[5] = 0x00;
+	buffer[4] = 0x00;
+	buffer[3] = 0x00;
+	buffer[2] = 0x00;
+	buffer[1] = 0x00;
+	buffer[0] = 0x00;
+	ASSERT.equal(2.2250738585072014e-308,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	buffer[0] = 0x80;
+	buffer[1] = 0x10;
+	buffer[2] = 0x00;
+	buffer[3] = 0x00;
+	buffer[4] = 0x00;
+	buffer[5] = 0x00;
+	buffer[6] = 0x00;
+	buffer[7] = 0x00;
+	ASSERT.equal(-2.2250738585072014e-308,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x80;
+	buffer[6] = 0x10;
+	buffer[5] = 0x00;
+	buffer[4] = 0x00;
+	buffer[3] = 0x00;
+	buffer[2] = 0x00;
+	buffer[1] = 0x00;
+	buffer[0] = 0x00;
+	ASSERT.equal(-2.2250738585072014e-308,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* Largest normalized value 1.7976931348623157e+308 */
+	buffer[0] = 0x7f;
+	buffer[1] = 0xef;
+	buffer[2] = 0xff;
+	buffer[3] = 0xff;
+	buffer[4] = 0xff;
+	buffer[5] = 0xff;
+	buffer[6] = 0xff;
+	buffer[7] = 0xff;
+	ASSERT.equal(1.7976931348623157e+308,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0x7f;
+	buffer[6] = 0xef;
+	buffer[5] = 0xff;
+	buffer[4] = 0xff;
+	buffer[3] = 0xff;
+	buffer[2] = 0xff;
+	buffer[1] = 0xff;
+	buffer[0] = 0xff;
+	ASSERT.equal(1.7976931348623157e+308,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	buffer[0] = 0xff;
+	buffer[1] = 0xef;
+	buffer[2] = 0xff;
+	buffer[3] = 0xff;
+	buffer[4] = 0xff;
+	buffer[5] = 0xff;
+	buffer[6] = 0xff;
+	buffer[7] = 0xff;
+	ASSERT.equal(-1.7976931348623157e+308,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+
+	buffer[7] = 0xff;
+	buffer[6] = 0xef;
+	buffer[5] = 0xff;
+	buffer[4] = 0xff;
+	buffer[3] = 0xff;
+	buffer[2] = 0xff;
+	buffer[1] = 0xff;
+	buffer[0] = 0xff;
+	ASSERT.equal(-1.7976931348623157e+308,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+
+	/* Try offsets */
+	buffer[0] = 0xde;
+	buffer[1] = 0xad;
+	buffer[2] = 0xbe;
+	buffer[3] = 0xef;
+	buffer[4] = 0xba;
+	buffer[5] = 0xdd;
+	buffer[6] = 0xca;
+	buffer[7] = 0xfe;
+	buffer[8] = 0x16;
+	buffer[9] = 0x79;
+
+	ASSERT.equal(-1.1885958404126936e+148,
+	    mod_ctype.rdouble(buffer, 'big', 0));
+	ASSERT.equal(-2.4299184080448593e-88,
+	    mod_ctype.rdouble(buffer, 'big', 1));
+	ASSERT.equal(-0.000015130017658081283,
+	    mod_ctype.rdouble(buffer, 'big', 2));
+
+	ASSERT.equal(-5.757458694845505e+302,
+	    mod_ctype.rdouble(buffer, 'little', 0));
+	ASSERT.equal(6.436459604192476e-198,
+	    mod_ctype.rdouble(buffer, 'little', 1));
+	ASSERT.equal(1.9903745632417286e+275,
+	    mod_ctype.rdouble(buffer, 'little', 2));
+}
+
+testfloat();
+testdouble();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.wfloat.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.wfloat.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/float/tst.wfloat.js	(revision 484)
@@ -0,0 +1,753 @@
+/*
+ * Another place to find bugs that may yet plague us. This time with writing out
+ * floats to arrays. We are lazy and did basically just take the opposite of our
+ * test code to read in values.
+ */
+
+var mod_ctype = require('../../../ctio.js');
+var ASSERT = require('assert');
+
+
+/*
+ *	A useful thing to keep around for debugging
+ *	console.log('buffer[0]: ' + buffer[0].toString(16));
+ *	console.log('buffer[1]: ' + buffer[1].toString(16));
+ *	console.log('buffer[2]: ' + buffer[2].toString(16));
+ *	console.log('buffer[3]: ' + buffer[3].toString(16));
+ *	console.log('buffer[4]: ' + buffer[4].toString(16));
+ *	console.log('buffer[5]: ' + buffer[5].toString(16));
+ * 	console.log('buffer[6]: ' + buffer[6].toString(16));
+ *	console.log('buffer[7]: ' + buffer[7].toString(16));
+ */
+
+function testfloat()
+{
+	var buffer = new Buffer(4);
+	mod_ctype.wfloat(0, 'big', buffer, 0);
+	/* Start off with some of the easy ones: +zero */
+	ASSERT.equal(0, buffer[0]);
+	ASSERT.equal(0, buffer[1]);
+	ASSERT.equal(0, buffer[2]);
+	ASSERT.equal(0, buffer[3]);
+	mod_ctype.wfloat(0, 'little', buffer, 0);
+	ASSERT.equal(0, buffer[0]);
+	ASSERT.equal(0, buffer[1]);
+	ASSERT.equal(0, buffer[2]);
+	ASSERT.equal(0, buffer[3]);
+
+	/* Catch +infin */
+	mod_ctype.wfloat(Number.POSITIVE_INFINITY, 'big', buffer, 0);
+	ASSERT.equal(0x7f, buffer[0]);
+	ASSERT.equal(0x80, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	mod_ctype.wfloat(Number.POSITIVE_INFINITY, 'little', buffer, 0);
+	ASSERT.equal(0x7f, buffer[3]);
+	ASSERT.equal(0x80, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	/* Catch -infin */
+	mod_ctype.wfloat(Number.NEGATIVE_INFINITY, 'big', buffer, 0);
+	ASSERT.equal(0xff, buffer[0]);
+	ASSERT.equal(0x80, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	mod_ctype.wfloat(Number.NEGATIVE_INFINITY, 'little', buffer, 0);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0x80, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	/* Catch NaN */
+
+	/*
+	 * NaN Is a litle weird in its requirements, so we're going to encode a
+	 * bit of how we actually implement it into this test. Probably not the
+	 * best, since technically the sign is a don't care and the mantissa
+	 * needs to just be non-zero.
+	 */
+	mod_ctype.wfloat(NaN, 'big', buffer, 0);
+	ASSERT.equal(0x7f, buffer[0]);
+	ASSERT.equal(0x80, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x17, buffer[3]);
+	mod_ctype.wfloat(NaN, 'little', buffer, 0);
+	ASSERT.equal(0x7f, buffer[3]);
+	ASSERT.equal(0x80, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x17, buffer[0]);
+
+	/* On to some basic tests */
+	/* 1.125 */
+	mod_ctype.wfloat(1.125, 'big', buffer, 0);
+	ASSERT.equal(0x3f, buffer[0]);
+	ASSERT.equal(0x90, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	mod_ctype.wfloat(1.125, 'little', buffer, 0);
+	ASSERT.equal(0x3f, buffer[3]);
+	ASSERT.equal(0x90, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	mod_ctype.wfloat(1.0000001192092896, 'big', buffer, 0);
+	ASSERT.equal(0x3f, buffer[0]);
+	ASSERT.equal(0x80, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x01, buffer[3]);
+	mod_ctype.wfloat(1.0000001192092896, 'little', buffer, 0);
+	ASSERT.equal(0x3f, buffer[3]);
+	ASSERT.equal(0x80, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x01, buffer[0]);
+
+	mod_ctype.wfloat(1.0000001192092896, 'big', buffer, 0);
+	ASSERT.equal(0x3f, buffer[0]);
+	ASSERT.equal(0x80, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x01, buffer[3]);
+	mod_ctype.wfloat(1.0000001192092896, 'little', buffer, 0);
+	ASSERT.equal(0x3f, buffer[3]);
+	ASSERT.equal(0x80, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x01, buffer[0]);
+
+	mod_ctype.wfloat(2.3283067140944524e-10, 'big', buffer, 0);
+	ASSERT.equal(0x2f, buffer[0]);
+	ASSERT.equal(0x80, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x01, buffer[3]);
+	mod_ctype.wfloat(2.3283067140944524e-10, 'little', buffer, 0);
+	ASSERT.equal(0x2f, buffer[3]);
+	ASSERT.equal(0x80, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x01, buffer[0]);
+
+	/* ff34a2b0 -2.4010576103645774e+38 */
+	mod_ctype.wfloat(-2.4010576103645774e+38,
+	    'big', buffer, 0);
+	ASSERT.equal(0xff, buffer[0]);
+	ASSERT.equal(0x34, buffer[1]);
+	ASSERT.equal(0xa2, buffer[2]);
+	ASSERT.equal(0xb0, buffer[3]);
+	mod_ctype.wfloat(-2.4010576103645774e+38,
+	    'little', buffer, 0);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0x34, buffer[2]);
+	ASSERT.equal(0xa2, buffer[1]);
+	ASSERT.equal(0xb0, buffer[0]);
+
+	/* Denormalized tests */
+
+	/* 0003f89a +/- 3.6468792534053364e-40 */
+	mod_ctype.wfloat(3.6468792534053364e-40,
+	    'big', buffer, 0);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x03, buffer[1]);
+	ASSERT.equal(0xf8, buffer[2]);
+	ASSERT.equal(0x9a, buffer[3]);
+	mod_ctype.wfloat(3.6468792534053364e-40,
+	    'little', buffer, 0);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x03, buffer[2]);
+	ASSERT.equal(0xf8, buffer[1]);
+	ASSERT.equal(0x9a, buffer[0]);
+
+	mod_ctype.wfloat(-3.6468792534053364e-40,
+	    'big', buffer, 0);
+	ASSERT.equal(0x80, buffer[0]);
+	ASSERT.equal(0x03, buffer[1]);
+	ASSERT.equal(0xf8, buffer[2]);
+	ASSERT.equal(0x9a, buffer[3]);
+	mod_ctype.wfloat(-3.6468792534053364e-40,
+	    'little', buffer, 0);
+	ASSERT.equal(0x80, buffer[3]);
+	ASSERT.equal(0x03, buffer[2]);
+	ASSERT.equal(0xf8, buffer[1]);
+	ASSERT.equal(0x9a, buffer[0]);
+
+	/* Maximum and minimum normalized and denormalized values */
+
+	/* Largest normalized number +/- 3.4028234663852886e+38 */
+
+	mod_ctype.wfloat(3.4028234663852886e+38,
+	    'big', buffer, 0);
+	ASSERT.equal(0x7f, buffer[0]);
+	ASSERT.equal(0x7f, buffer[1]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[3]);
+	mod_ctype.wfloat(3.4028234663852886e+38,
+	    'little', buffer, 0);
+	ASSERT.equal(0x7f, buffer[3]);
+	ASSERT.equal(0x7f, buffer[2]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xff, buffer[0]);
+
+	mod_ctype.wfloat(-3.4028234663852886e+38,
+	    'big', buffer, 0);
+	ASSERT.equal(0xff, buffer[0]);
+	ASSERT.equal(0x7f, buffer[1]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[3]);
+	mod_ctype.wfloat(-3.4028234663852886e+38,
+	    'little', buffer, 0);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0x7f, buffer[2]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xff, buffer[0]);
+
+	/* Smallest normalied number +/- 1.1754943508222875e-38 */
+
+	mod_ctype.wfloat(1.1754943508222875e-38,
+	    'big', buffer, 0);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x80, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	mod_ctype.wfloat(1.1754943508222875e-38,
+	    'little', buffer, 0);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x80, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	mod_ctype.wfloat(-1.1754943508222875e-38,
+	    'big', buffer, 0);
+	ASSERT.equal(0x80, buffer[0]);
+	ASSERT.equal(0x80, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	mod_ctype.wfloat(-1.1754943508222875e-38,
+	    'little', buffer, 0);
+	ASSERT.equal(0x80, buffer[3]);
+	ASSERT.equal(0x80, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	/* Smallest denormalized number 1.401298464324817e-45 */
+	mod_ctype.wfloat(1.401298464324817e-45,
+	    'big', buffer, 0);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x01, buffer[3]);
+	mod_ctype.wfloat(1.401298464324817e-45,
+	    'little', buffer, 0);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x01, buffer[0]);
+
+	mod_ctype.wfloat(-1.401298464324817e-45,
+	    'big', buffer, 0);
+	ASSERT.equal(0x80, buffer[0]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x01, buffer[3]);
+	mod_ctype.wfloat(-1.401298464324817e-45,
+	    'little', buffer, 0);
+	ASSERT.equal(0x80, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x01, buffer[0]);
+
+	/* Largest denormalized value +/- 1.1754942106924411e-38 */
+
+	mod_ctype.wfloat(1.1754942106924411e-38,
+	    'big', buffer, 0);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x7f, buffer[1]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[3]);
+	mod_ctype.wfloat(1.1754942106924411e-38,
+	    'little', buffer, 0);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x7f, buffer[2]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xff, buffer[0]);
+
+	mod_ctype.wfloat(-1.1754942106924411e-38,
+	    'big', buffer, 0);
+	ASSERT.equal(0x80, buffer[0]);
+	ASSERT.equal(0x7f, buffer[1]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[3]);
+	mod_ctype.wfloat(-1.1754942106924411e-38,
+	    'little', buffer, 0);
+	ASSERT.equal(0x80, buffer[3]);
+	ASSERT.equal(0x7f, buffer[2]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xff, buffer[0]);
+
+	/* Do some quick offset testing */
+	buffer = new Buffer(6);
+	mod_ctype.wfloat(-1.2027516403607578e-32,
+	    'big', buffer, 2);
+	ASSERT.equal(0x8a, buffer[2]);
+	ASSERT.equal(0x79, buffer[3]);
+	ASSERT.equal(0xcd, buffer[4]);
+	ASSERT.equal(0x3f, buffer[5]);
+
+	mod_ctype.wfloat(-1.2027516403607578e-32,
+	    'little', buffer, 2);
+	ASSERT.equal(0x8a, buffer[5]);
+	ASSERT.equal(0x79, buffer[4]);
+	ASSERT.equal(0xcd, buffer[3]);
+	ASSERT.equal(0x3f, buffer[2]);
+
+}
+
+function testdouble()
+{
+	var buffer = new Buffer(10);
+
+	/* Check 0 */
+	mod_ctype.wdouble(0, 'big', buffer, 0);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[7]);
+	mod_ctype.wdouble(0, 'little', buffer, 0);
+	ASSERT.equal(0x00, buffer[7]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	/* Check NaN */
+	/* Similar to floats we are only generating a subset of values */
+	mod_ctype.wdouble(NaN, 'big', buffer, 0);
+	ASSERT.equal(0x7f, buffer[0]);
+	ASSERT.equal(0xf0, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x17, buffer[7]);
+	mod_ctype.wdouble(NaN, 'little', buffer, 0);
+	ASSERT.equal(0x7f, buffer[7]);
+	ASSERT.equal(0xf0, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x17, buffer[0]);
+
+	/* pos inf */
+	mod_ctype.wdouble(Number.POSITIVE_INFINITY,
+	    'big', buffer, 0);
+	ASSERT.equal(0x7f, buffer[0]);
+	ASSERT.equal(0xf0, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[7]);
+	mod_ctype.wdouble(Number.POSITIVE_INFINITY,
+	    'little', buffer, 0);
+	ASSERT.equal(0x7f, buffer[7]);
+	ASSERT.equal(0xf0, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	/* neg inf */
+	mod_ctype.wdouble(Number.NEGATIVE_INFINITY,
+	    'big', buffer, 0);
+	ASSERT.equal(0xff, buffer[0]);
+	ASSERT.equal(0xf0, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[7]);
+	mod_ctype.wdouble(Number.NEGATIVE_INFINITY,
+	    'little', buffer, 0);
+	ASSERT.equal(0xff, buffer[7]);
+	ASSERT.equal(0xf0, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	/* Simple normalized values */
+
+	/* +/- 1.125 */
+	mod_ctype.wdouble(1.125,
+	    'big', buffer, 0);
+	ASSERT.equal(0x3f, buffer[0]);
+	ASSERT.equal(0xf2, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[7]);
+
+	mod_ctype.wdouble(1.125,
+	    'little', buffer, 0);
+	ASSERT.equal(0x3f, buffer[7]);
+	ASSERT.equal(0xf2, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	mod_ctype.wdouble(-1.125,
+	    'big', buffer, 0);
+	ASSERT.equal(0xbf, buffer[0]);
+	ASSERT.equal(0xf2, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[7]);
+
+	mod_ctype.wdouble(-1.125,
+	    'little', buffer, 0);
+	ASSERT.equal(0xbf, buffer[7]);
+	ASSERT.equal(0xf2, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+
+	/* +/- 1.4397318913736026e+283 */
+	mod_ctype.wdouble(1.4397318913736026e+283,
+	    'big', buffer, 0);
+	ASSERT.equal(0x7a, buffer[0]);
+	ASSERT.equal(0xb8, buffer[1]);
+	ASSERT.equal(0xc9, buffer[2]);
+	ASSERT.equal(0x34, buffer[3]);
+	ASSERT.equal(0x72, buffer[4]);
+	ASSERT.equal(0x16, buffer[5]);
+	ASSERT.equal(0xf9, buffer[6]);
+	ASSERT.equal(0x0e, buffer[7]);
+
+	mod_ctype.wdouble(1.4397318913736026e+283,
+	    'little', buffer, 0);
+	ASSERT.equal(0x7a, buffer[7]);
+	ASSERT.equal(0xb8, buffer[6]);
+	ASSERT.equal(0xc9, buffer[5]);
+	ASSERT.equal(0x34, buffer[4]);
+	ASSERT.equal(0x72, buffer[3]);
+	ASSERT.equal(0x16, buffer[2]);
+	ASSERT.equal(0xf9, buffer[1]);
+	ASSERT.equal(0x0e, buffer[0]);
+
+	mod_ctype.wdouble(-1.4397318913736026e+283,
+	    'big', buffer, 0);
+	ASSERT.equal(0xfa, buffer[0]);
+	ASSERT.equal(0xb8, buffer[1]);
+	ASSERT.equal(0xc9, buffer[2]);
+	ASSERT.equal(0x34, buffer[3]);
+	ASSERT.equal(0x72, buffer[4]);
+	ASSERT.equal(0x16, buffer[5]);
+	ASSERT.equal(0xf9, buffer[6]);
+	ASSERT.equal(0x0e, buffer[7]);
+
+	mod_ctype.wdouble(-1.4397318913736026e+283,
+	    'little', buffer, 0);
+	ASSERT.equal(0xfa, buffer[7]);
+	ASSERT.equal(0xb8, buffer[6]);
+	ASSERT.equal(0xc9, buffer[5]);
+	ASSERT.equal(0x34, buffer[4]);
+	ASSERT.equal(0x72, buffer[3]);
+	ASSERT.equal(0x16, buffer[2]);
+	ASSERT.equal(0xf9, buffer[1]);
+	ASSERT.equal(0x0e, buffer[0]);
+
+	/* Denormalized values */
+	/* +/- 8.82521232268344e-309 */
+	mod_ctype.wdouble(8.82521232268344e-309,
+	    'big', buffer, 0);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x06, buffer[1]);
+	ASSERT.equal(0x58, buffer[2]);
+	ASSERT.equal(0x94, buffer[3]);
+	ASSERT.equal(0x13, buffer[4]);
+	ASSERT.equal(0x27, buffer[5]);
+	ASSERT.equal(0x8a, buffer[6]);
+	ASSERT.equal(0xcd, buffer[7]);
+
+	mod_ctype.wdouble(8.82521232268344e-309,
+	    'little', buffer, 0);
+	ASSERT.equal(0x00, buffer[7]);
+	ASSERT.equal(0x06, buffer[6]);
+	ASSERT.equal(0x58, buffer[5]);
+	ASSERT.equal(0x94, buffer[4]);
+	ASSERT.equal(0x13, buffer[3]);
+	ASSERT.equal(0x27, buffer[2]);
+	ASSERT.equal(0x8a, buffer[1]);
+	ASSERT.equal(0xcd, buffer[0]);
+
+	mod_ctype.wdouble(-8.82521232268344e-309,
+	    'big', buffer, 0);
+	ASSERT.equal(0x80, buffer[0]);
+	ASSERT.equal(0x06, buffer[1]);
+	ASSERT.equal(0x58, buffer[2]);
+	ASSERT.equal(0x94, buffer[3]);
+	ASSERT.equal(0x13, buffer[4]);
+	ASSERT.equal(0x27, buffer[5]);
+	ASSERT.equal(0x8a, buffer[6]);
+	ASSERT.equal(0xcd, buffer[7]);
+
+	mod_ctype.wdouble(-8.82521232268344e-309,
+	    'little', buffer, 0);
+	ASSERT.equal(0x80, buffer[7]);
+	ASSERT.equal(0x06, buffer[6]);
+	ASSERT.equal(0x58, buffer[5]);
+	ASSERT.equal(0x94, buffer[4]);
+	ASSERT.equal(0x13, buffer[3]);
+	ASSERT.equal(0x27, buffer[2]);
+	ASSERT.equal(0x8a, buffer[1]);
+	ASSERT.equal(0xcd, buffer[0]);
+
+
+	/* Edge cases, maximum and minimum values */
+
+	/* Smallest denormalized value 5e-324 */
+	mod_ctype.wdouble(5e-324,
+	    'big', buffer, 0);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x01, buffer[7]);
+
+	mod_ctype.wdouble(5e-324,
+	    'little', buffer, 0);
+	ASSERT.equal(0x00, buffer[7]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x01, buffer[0]);
+
+	mod_ctype.wdouble(-5e-324,
+	    'big', buffer, 0);
+	ASSERT.equal(0x80, buffer[0]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x01, buffer[7]);
+
+	mod_ctype.wdouble(-5e-324,
+	    'little', buffer, 0);
+	ASSERT.equal(0x80, buffer[7]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x01, buffer[0]);
+
+
+
+	/* Largest denormalized value 2.225073858507201e-308 */
+	mod_ctype.wdouble(2.225073858507201e-308,
+	    'big', buffer, 0);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x0f, buffer[1]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0xff, buffer[4]);
+	ASSERT.equal(0xff, buffer[5]);
+	ASSERT.equal(0xff, buffer[6]);
+	ASSERT.equal(0xff, buffer[7]);
+
+	mod_ctype.wdouble(2.225073858507201e-308,
+	    'little', buffer, 0);
+	ASSERT.equal(0x00, buffer[7]);
+	ASSERT.equal(0x0f, buffer[6]);
+	ASSERT.equal(0xff, buffer[5]);
+	ASSERT.equal(0xff, buffer[4]);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xff, buffer[0]);
+
+	mod_ctype.wdouble(-2.225073858507201e-308,
+	    'big', buffer, 0);
+	ASSERT.equal(0x80, buffer[0]);
+	ASSERT.equal(0x0f, buffer[1]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0xff, buffer[4]);
+	ASSERT.equal(0xff, buffer[5]);
+	ASSERT.equal(0xff, buffer[6]);
+	ASSERT.equal(0xff, buffer[7]);
+
+	mod_ctype.wdouble(-2.225073858507201e-308,
+	    'little', buffer, 0);
+	ASSERT.equal(0x80, buffer[7]);
+	ASSERT.equal(0x0f, buffer[6]);
+	ASSERT.equal(0xff, buffer[5]);
+	ASSERT.equal(0xff, buffer[4]);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xff, buffer[0]);
+
+
+	/* Smallest normalized value 2.2250738585072014e-308 */
+	mod_ctype.wdouble(2.2250738585072014e-308,
+	    'big', buffer, 0);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x10, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[7]);
+
+	mod_ctype.wdouble(2.2250738585072014e-308,
+	    'little', buffer, 0);
+	ASSERT.equal(0x00, buffer[7]);
+	ASSERT.equal(0x10, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+	mod_ctype.wdouble(-2.2250738585072014e-308,
+	    'big', buffer, 0);
+	ASSERT.equal(0x80, buffer[0]);
+	ASSERT.equal(0x10, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[7]);
+
+	mod_ctype.wdouble(-2.2250738585072014e-308,
+	    'little', buffer, 0);
+	ASSERT.equal(0x80, buffer[7]);
+	ASSERT.equal(0x10, buffer[6]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[4]);
+	ASSERT.equal(0x00, buffer[3]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[0]);
+
+
+	/* Largest normalized value 1.7976931348623157e+308 */
+	mod_ctype.wdouble(1.7976931348623157e+308,
+	    'big', buffer, 0);
+	ASSERT.equal(0x7f, buffer[0]);
+	ASSERT.equal(0xef, buffer[1]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0xff, buffer[4]);
+	ASSERT.equal(0xff, buffer[5]);
+	ASSERT.equal(0xff, buffer[6]);
+	ASSERT.equal(0xff, buffer[7]);
+
+	mod_ctype.wdouble(1.7976931348623157e+308,
+	    'little', buffer, 0);
+	ASSERT.equal(0x7f, buffer[7]);
+	ASSERT.equal(0xef, buffer[6]);
+	ASSERT.equal(0xff, buffer[5]);
+	ASSERT.equal(0xff, buffer[4]);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xff, buffer[0]);
+
+	mod_ctype.wdouble(-1.7976931348623157e+308,
+	    'big', buffer, 0);
+	ASSERT.equal(0xff, buffer[0]);
+	ASSERT.equal(0xef, buffer[1]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0xff, buffer[4]);
+	ASSERT.equal(0xff, buffer[5]);
+	ASSERT.equal(0xff, buffer[6]);
+	ASSERT.equal(0xff, buffer[7]);
+
+	mod_ctype.wdouble(-1.7976931348623157e+308,
+	    'little', buffer, 0);
+	ASSERT.equal(0xff, buffer[7]);
+	ASSERT.equal(0xef, buffer[6]);
+	ASSERT.equal(0xff, buffer[5]);
+	ASSERT.equal(0xff, buffer[4]);
+	ASSERT.equal(0xff, buffer[3]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xff, buffer[0]);
+
+
+	/* Try offsets */
+	buffer[0] = 0xde;
+	buffer[1] = 0xad;
+	buffer[2] = 0xbe;
+	buffer[3] = 0xef;
+	buffer[4] = 0xba;
+	buffer[5] = 0xdd;
+	buffer[6] = 0xca;
+	buffer[7] = 0xfe;
+	buffer[8] = 0x16;
+	buffer[9] = 0x79;
+
+	mod_ctype.wdouble(-0.000015130017658081283,
+	    'big', buffer, 2);
+	ASSERT.equal(0xbe, buffer[2]);
+	ASSERT.equal(0xef, buffer[3]);
+	ASSERT.equal(0xba, buffer[4]);
+	ASSERT.equal(0xdd, buffer[5]);
+	ASSERT.equal(0xca, buffer[6]);
+	ASSERT.equal(0xfe, buffer[7]);
+	ASSERT.equal(0x16, buffer[8]);
+	ASSERT.equal(0x79, buffer[9]);
+
+	mod_ctype.wdouble(-0.000015130017658081283,
+	    'little', buffer, 2);
+	ASSERT.equal(0xbe, buffer[9]);
+	ASSERT.equal(0xef, buffer[8]);
+	ASSERT.equal(0xba, buffer[7]);
+	ASSERT.equal(0xdd, buffer[6]);
+	ASSERT.equal(0xca, buffer[5]);
+	ASSERT.equal(0xfe, buffer[4]);
+	ASSERT.equal(0x16, buffer[3]);
+	ASSERT.equal(0x79, buffer[2]);
+}
+
+testfloat();
+testdouble();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.64.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.64.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.64.js	(revision 484)
@@ -0,0 +1,638 @@
+/*
+ * Test our ability to read and write signed 64-bit integers.
+ */
+
+var mod_ctype = require('../../../ctio.js');
+var ASSERT = require('assert');
+
+function testRead()
+{
+	var res, data;
+	data = new Buffer(10);
+
+	data[0] = 0x32;
+	data[1] = 0x65;
+	data[2] = 0x42;
+	data[3] = 0x56;
+	data[4] = 0x23;
+	data[5] = 0xff;
+	data[6] = 0xff;
+	data[7] = 0xff;
+	data[8] = 0x89;
+	data[9] = 0x11;
+	res = mod_ctype.rsint64(data, 'big', 0);
+	ASSERT.equal(0x32654256, res[0]);
+	ASSERT.equal(0x23ffffff, res[1]);
+	res = mod_ctype.rsint64(data, 'big', 1);
+	ASSERT.equal(0x65425623, res[0]);
+	ASSERT.equal(0xffffff89, res[1]);
+	res = mod_ctype.rsint64(data, 'big', 2);
+	ASSERT.equal(0x425623ff, res[0]);
+	ASSERT.equal(0xffff8911, res[1]);
+	res = mod_ctype.rsint64(data, 'little', 0);
+	ASSERT.equal(-0x000000dc, res[0]);
+	ASSERT.equal(-0xa9bd9ace, res[1]);
+	res = mod_ctype.rsint64(data, 'little', 1);
+	ASSERT.equal(-0x76000000, res[0]);
+	ASSERT.equal(-0xdca9bd9b, res[1]);
+	res = mod_ctype.rsint64(data, 'little', 2);
+	ASSERT.equal(0x1189ffff, res[0]);
+	ASSERT.equal(0xff235642, res[1]);
+
+	data.fill(0x00);
+	res = mod_ctype.rsint64(data, 'big', 0);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(0x00000000, res[1]);
+	res = mod_ctype.rsint64(data, 'big', 1);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(0x00000000, res[1]);
+	res = mod_ctype.rsint64(data, 'big', 2);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(0x00000000, res[1]);
+	res = mod_ctype.rsint64(data, 'little', 0);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(0x00000000, res[1]);
+	res = mod_ctype.rsint64(data, 'little', 1);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(0x00000000, res[1]);
+	res = mod_ctype.rsint64(data, 'little', 2);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(0x00000000, res[1]);
+
+	data.fill(0xff);
+	res = mod_ctype.rsint64(data, 'big', 0);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(-1, res[1]);
+	res = mod_ctype.rsint64(data, 'big', 1);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(-1, res[1]);
+	res = mod_ctype.rsint64(data, 'big', 2);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(-1, res[1]);
+	res = mod_ctype.rsint64(data, 'little', 0);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(-1, res[1]);
+	res = mod_ctype.rsint64(data, 'little', 1);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(-1, res[1]);
+	res = mod_ctype.rsint64(data, 'little', 2);
+	ASSERT.equal(0x00000000, res[0]);
+	ASSERT.equal(-1, res[1]);
+
+	data[0] = 0x80;
+	data[1] = 0x00;
+	data[2] = 0x00;
+	data[3] = 0x00;
+	data[4] = 0x00;
+	data[5] = 0x00;
+	data[6] = 0x00;
+	data[7] = 0x00;
+	res = mod_ctype.rsint64(data, 'big', 0);
+	ASSERT.equal(-0x80000000, res[0]);
+	ASSERT.equal(0, res[1]);
+
+
+	data[7] = 0x80;
+	data[6] = 0x00;
+	data[5] = 0x00;
+	data[4] = 0x00;
+	data[3] = 0x00;
+	data[2] = 0x00;
+	data[1] = 0x00;
+	data[0] = 0x00;
+	res = mod_ctype.rsint64(data, 'little', 0);
+	ASSERT.equal(-0x80000000, res[0]);
+	ASSERT.equal(0, res[1]);
+
+	data[0] = 0x80;
+	data[1] = 0x00;
+	data[2] = 0x00;
+	data[3] = 0x00;
+	data[4] = 0x00;
+	data[5] = 0x00;
+	data[6] = 0x00;
+	data[7] = 0x01;
+	res = mod_ctype.rsint64(data, 'big', 0);
+	ASSERT.equal(-0x7fffffff, res[0]);
+	ASSERT.equal(-0xffffffff, res[1]);
+
+
+}
+
+function testWriteZero()
+{
+	var data, buf;
+	buf = new Buffer(10);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wsint64(data, 'big', buf, 0);
+	ASSERT.equal(0, buf[0]);
+	ASSERT.equal(0, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wsint64(data, 'big', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wsint64(data, 'big', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0, buf[8]);
+	ASSERT.equal(0, buf[9]);
+
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wsint64(data, 'little', buf, 0);
+	ASSERT.equal(0, buf[0]);
+	ASSERT.equal(0, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wsint64(data, 'little', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wsint64(data, 'little', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0, buf[8]);
+	ASSERT.equal(0, buf[9]);
+}
+
+/*
+ * Also include tests that are going to force us to go into a negative value and
+ * insure that it's written correctly.
+ */
+function testWrite()
+{
+	var data, buf;
+
+	buf = new Buffer(10);
+	data = [ 0x234456, 0x87 ];
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'big', buf, 0);
+	ASSERT.equal(0x00, buf[0]);
+	ASSERT.equal(0x23, buf[1]);
+	ASSERT.equal(0x44, buf[2]);
+	ASSERT.equal(0x56, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x87, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'big', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x23, buf[2]);
+	ASSERT.equal(0x44, buf[3]);
+	ASSERT.equal(0x56, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x00, buf[7]);
+	ASSERT.equal(0x87, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'big', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x23, buf[3]);
+	ASSERT.equal(0x44, buf[4]);
+	ASSERT.equal(0x56, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x00, buf[7]);
+	ASSERT.equal(0x00, buf[8]);
+	ASSERT.equal(0x87, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'little', buf, 0);
+	ASSERT.equal(0x87, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x56, buf[4]);
+	ASSERT.equal(0x44, buf[5]);
+	ASSERT.equal(0x23, buf[6]);
+	ASSERT.equal(0x00, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'little', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x87, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x56, buf[5]);
+	ASSERT.equal(0x44, buf[6]);
+	ASSERT.equal(0x23, buf[7]);
+	ASSERT.equal(0x00, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'little', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0x87, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x56, buf[6]);
+	ASSERT.equal(0x44, buf[7]);
+	ASSERT.equal(0x23, buf[8]);
+	ASSERT.equal(0x00, buf[9]);
+
+	data = [0x3421, 0x34abcdba];
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'big', buf, 0);
+	ASSERT.equal(0x00, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x34, buf[2]);
+	ASSERT.equal(0x21, buf[3]);
+	ASSERT.equal(0x34, buf[4]);
+	ASSERT.equal(0xab, buf[5]);
+	ASSERT.equal(0xcd, buf[6]);
+	ASSERT.equal(0xba, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'big', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x34, buf[3]);
+	ASSERT.equal(0x21, buf[4]);
+	ASSERT.equal(0x34, buf[5]);
+	ASSERT.equal(0xab, buf[6]);
+	ASSERT.equal(0xcd, buf[7]);
+	ASSERT.equal(0xba, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'big', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x34, buf[4]);
+	ASSERT.equal(0x21, buf[5]);
+	ASSERT.equal(0x34, buf[6]);
+	ASSERT.equal(0xab, buf[7]);
+	ASSERT.equal(0xcd, buf[8]);
+	ASSERT.equal(0xba, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'little', buf, 0);
+	ASSERT.equal(0xba, buf[0]);
+	ASSERT.equal(0xcd, buf[1]);
+	ASSERT.equal(0xab, buf[2]);
+	ASSERT.equal(0x34, buf[3]);
+	ASSERT.equal(0x21, buf[4]);
+	ASSERT.equal(0x34, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x00, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'little', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0xba, buf[1]);
+	ASSERT.equal(0xcd, buf[2]);
+	ASSERT.equal(0xab, buf[3]);
+	ASSERT.equal(0x34, buf[4]);
+	ASSERT.equal(0x21, buf[5]);
+	ASSERT.equal(0x34, buf[6]);
+	ASSERT.equal(0x00, buf[7]);
+	ASSERT.equal(0x00, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'little', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0xba, buf[2]);
+	ASSERT.equal(0xcd, buf[3]);
+	ASSERT.equal(0xab, buf[4]);
+	ASSERT.equal(0x34, buf[5]);
+	ASSERT.equal(0x21, buf[6]);
+	ASSERT.equal(0x34, buf[7]);
+	ASSERT.equal(0x00, buf[8]);
+	ASSERT.equal(0x00, buf[9]);
+
+
+	data = [ -0x80000000, 0 ];
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'big', buf, 0);
+	ASSERT.equal(0x80, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x00, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'little', buf, 0);
+	ASSERT.equal(0x00, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x80, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	data = [ -0x7fffffff, -0xffffffff ];
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'big', buf, 0);
+	ASSERT.equal(0x80, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x01, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'little', buf, 0);
+	ASSERT.equal(0x01, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x80, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	data = [ 0x0, -0x1];
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'big', buf, 0);
+	ASSERT.equal(0xff, buf[0]);
+	ASSERT.equal(0xff, buf[1]);
+	ASSERT.equal(0xff, buf[2]);
+	ASSERT.equal(0xff, buf[3]);
+	ASSERT.equal(0xff, buf[4]);
+	ASSERT.equal(0xff, buf[5]);
+	ASSERT.equal(0xff, buf[6]);
+	ASSERT.equal(0xff, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wsint64(data, 'little', buf, 0);
+	ASSERT.equal(0xff, buf[0]);
+	ASSERT.equal(0xff, buf[1]);
+	ASSERT.equal(0xff, buf[2]);
+	ASSERT.equal(0xff, buf[3]);
+	ASSERT.equal(0xff, buf[4]);
+	ASSERT.equal(0xff, buf[5]);
+	ASSERT.equal(0xff, buf[6]);
+	ASSERT.equal(0xff, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+}
+
+/*
+ * Make sure we catch invalid writes.
+ */
+function testWriteInvalid()
+{
+	var data, buf;
+
+	/* Buffer too small */
+	buf = new Buffer(4);
+	data = [ 0, 0];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 0);
+	}, Error, 'buffer too small');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 0);
+	}, Error, 'buffer too small');
+
+	/* Beyond the end of the buffer */
+	buf = new Buffer(12);
+	data = [ 0, 0];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 11);
+	}, Error, 'write beyond end of buffer');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 11);
+	}, Error, 'write beyond end of buffer');
+
+	/* Write fractional values */
+	buf = new Buffer(12);
+	data = [ 3.33, 0 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	data = [ 0, 3.3 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	data = [ -3.33, 0 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	data = [ 0, -3.3 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	data = [ 3.33, 2.42 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	data = [ 3.33, -2.42 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	data = [ -3.33, -2.42 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	data = [ -3.33, 2.42 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	/* Signs don't match */
+	buf = new Buffer(12);
+	data = [ 0x800000, -0x32 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	data = [ -0x800000, 0x32 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	/* Write values that are too large */
+	buf = new Buffer(12);
+	data = [ 0x80000000, 0 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	data = [ 0x7fffffff, 0x100000000 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	data = [ 0x00, 0x800000000 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	data = [ 0xffffffffff, 0xffffff238 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	data = [ 0x23, 0xffffff238 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	data = [ -0x80000000, -0xfff238 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	data = [ -0x80000004, -0xfff238 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wsint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+}
+
+
+testRead();
+testWrite();
+testWriteZero();
+testWriteInvalid();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.rint.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.rint.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.rint.js	(revision 484)
@@ -0,0 +1,101 @@
+/*
+ * Tests to verify we're reading in signed integers correctly
+ */
+var mod_ctype = require('../../../ctio.js');
+var ASSERT = require('assert');
+
+/*
+ * Test 8 bit signed integers
+ */
+function test8()
+{
+	var data = new Buffer(4);
+
+	data[0] = 0x23;
+	ASSERT.equal(0x23, mod_ctype.rsint8(data, 'big', 0));
+	ASSERT.equal(0x23, mod_ctype.rsint8(data, 'little', 0));
+
+	data[0] = 0xff;
+	ASSERT.equal(-1, mod_ctype.rsint8(data, 'big', 0));
+	ASSERT.equal(-1, mod_ctype.rsint8(data, 'little', 0));
+
+	data[0] = 0x87;
+	data[1] = 0xab;
+	data[2] = 0x7c;
+	data[3] = 0xef;
+	ASSERT.equal(-121, mod_ctype.rsint8(data, 'big', 0));
+	ASSERT.equal(-85, mod_ctype.rsint8(data, 'big', 1));
+	ASSERT.equal(124, mod_ctype.rsint8(data, 'big', 2));
+	ASSERT.equal(-17, mod_ctype.rsint8(data, 'big', 3));
+	ASSERT.equal(-121, mod_ctype.rsint8(data, 'little', 0));
+	ASSERT.equal(-85, mod_ctype.rsint8(data, 'little', 1));
+	ASSERT.equal(124, mod_ctype.rsint8(data, 'little', 2));
+	ASSERT.equal(-17, mod_ctype.rsint8(data, 'little', 3));
+}
+
+function test16()
+{
+	var buffer = new Buffer(6);
+	buffer[0] = 0x16;
+	buffer[1] = 0x79;
+	ASSERT.equal(0x1679, mod_ctype.rsint16(buffer, 'big', 0));
+	ASSERT.equal(0x7916, mod_ctype.rsint16(buffer, 'little', 0));
+
+	buffer[0] = 0xff;
+	buffer[1] = 0x80;
+	ASSERT.equal(-128, mod_ctype.rsint16(buffer, 'big', 0));
+	ASSERT.equal(-32513, mod_ctype.rsint16(buffer, 'little', 0));
+
+	/* test offset with weenix */
+	buffer[0] = 0x77;
+	buffer[1] = 0x65;
+	buffer[2] = 0x65;
+	buffer[3] = 0x6e;
+	buffer[4] = 0x69;
+	buffer[5] = 0x78;
+	ASSERT.equal(0x7765, mod_ctype.rsint16(buffer, 'big', 0));
+	ASSERT.equal(0x6565, mod_ctype.rsint16(buffer, 'big', 1));
+	ASSERT.equal(0x656e, mod_ctype.rsint16(buffer, 'big', 2));
+	ASSERT.equal(0x6e69, mod_ctype.rsint16(buffer, 'big', 3));
+	ASSERT.equal(0x6978, mod_ctype.rsint16(buffer, 'big', 4));
+	ASSERT.equal(0x6577, mod_ctype.rsint16(buffer, 'little', 0));
+	ASSERT.equal(0x6565, mod_ctype.rsint16(buffer, 'little', 1));
+	ASSERT.equal(0x6e65, mod_ctype.rsint16(buffer, 'little', 2));
+	ASSERT.equal(0x696e, mod_ctype.rsint16(buffer, 'little', 3));
+	ASSERT.equal(0x7869, mod_ctype.rsint16(buffer, 'little', 4));
+}
+
+function test32()
+{
+	var buffer = new Buffer(6);
+	buffer[0] = 0x43;
+	buffer[1] = 0x53;
+	buffer[2] = 0x16;
+	buffer[3] = 0x79;
+	ASSERT.equal(0x43531679, mod_ctype.rsint32(buffer, 'big', 0));
+	ASSERT.equal(0x79165343, mod_ctype.rsint32(buffer, 'little', 0));
+
+	buffer[0] = 0xff;
+	buffer[1] = 0xfe;
+	buffer[2] = 0xef;
+	buffer[3] = 0xfa;
+	ASSERT.equal(-69638, mod_ctype.rsint32(buffer, 'big', 0));
+	ASSERT.equal(-84934913, mod_ctype.rsint32(buffer, 'little', 0));
+
+	buffer[0] = 0x42;
+	buffer[1] = 0xc3;
+	buffer[2] = 0x95;
+	buffer[3] = 0xa9;
+	buffer[4] = 0x36;
+	buffer[5] = 0x17;
+	ASSERT.equal(0x42c395a9, mod_ctype.rsint32(buffer, 'big', 0));
+	ASSERT.equal(-1013601994, mod_ctype.rsint32(buffer, 'big', 1));
+	ASSERT.equal(-1784072681, mod_ctype.rsint32(buffer, 'big', 2));
+	ASSERT.equal(-1449802942, mod_ctype.rsint32(buffer, 'little', 0));
+	ASSERT.equal(917083587, mod_ctype.rsint32(buffer, 'little', 1));
+	ASSERT.equal(389458325, mod_ctype.rsint32(buffer, 'little', 2));
+}
+
+test8();
+test16();
+test32();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wbounds.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wbounds.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wbounds.js	(revision 484)
@@ -0,0 +1,53 @@
+/*
+ * Test to make sure that we properly are erroring whenever we try to write
+ * beyond the size of the integer.
+ */
+
+var mod_ctio = require('../../../ctio.js');
+var mod_assert = require('assert');
+var tb = new Buffer(16); /* Largest buffer we'll need */
+
+var cases = [
+	{ func:
+	function () {
+		mod_ctio.wsint8(0x80, 'big', tb, 0);
+	}, test: '+int8_t' },
+	{ func:
+	function () {
+		mod_ctio.wsint8(-0x81, 'big', tb, 0);
+	}, test: '-int8_t' },
+
+	{ func:
+	function () {
+		mod_ctio.wsint16(0x8000, 'big', tb, 0);
+	}, test: '+int16_t' },
+	{ func:
+	function () {
+		mod_ctio.wsint16(-0x8001, 'big', tb, 0);
+	}, test: '-int16_t' },
+	{ func:
+	function () {
+		mod_ctio.wsint32(0x80000000, 'big', tb, 0);
+	}, test: '+int32_t' },
+	{ func:
+	function () {
+		mod_ctio.wsint32(-0x80000001, 'big', tb, 0);
+	}, test: '-int32_t' },
+	{ func:
+	function () {
+		mod_ctio.wsint64([ 0x80000000, 0 ], 'big', tb, 0);
+	}, test: '+int64_t' },
+	{ func:
+	function () {
+		mod_ctio.wsint64([ -0x80000000, -1 ], 'big', tb, 0);
+	}, test: '-int64_t' }
+];
+
+function test()
+{
+	var ii;
+	for (ii = 0; ii < cases.length; ii++)
+		mod_assert.throws(cases[ii]['func'], Error, cases[ii]['test']);
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wint.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wint.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/int/tst.wint.js	(revision 484)
@@ -0,0 +1,92 @@
+/*
+ * Tests to verify we're writing signed integers correctly
+ */
+var mod_ctype = require('../../../ctio.js');
+var ASSERT = require('assert');
+
+function test8()
+{
+	var buffer = new Buffer(4);
+	mod_ctype.wsint8(0x23, 'big', buffer, 0);
+	mod_ctype.wsint8(0x23, 'little', buffer, 1);
+	mod_ctype.wsint8(-5, 'big', buffer, 2);
+	mod_ctype.wsint8(-5, 'little', buffer, 3);
+
+	ASSERT.equal(0x23, buffer[0]);
+	ASSERT.equal(0x23, buffer[1]);
+	ASSERT.equal(0xfb, buffer[2]);
+	ASSERT.equal(0xfb, buffer[3]);
+
+	/* Make sure we handle truncation correctly */
+	ASSERT.throws(function () {
+	     mod_ctype.wsint8(0xabc, 'big', buffer, 0);
+	});
+	ASSERT.throws(function () {
+	     mod_ctype.wsint8(0xabc, 'little', buffer, 0);
+	});
+}
+
+function test16()
+{
+	var buffer = new Buffer(6);
+	mod_ctype.wsint16(0x0023, 'big', buffer, 0);
+	mod_ctype.wsint16(0x0023, 'little', buffer, 2);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x23, buffer[1]);
+	ASSERT.equal(0x23, buffer[2]);
+	ASSERT.equal(0x00, buffer[3]);
+	mod_ctype.wsint16(-5, 'big', buffer, 0);
+	mod_ctype.wsint16(-5, 'little', buffer, 2);
+	ASSERT.equal(0xff, buffer[0]);
+	ASSERT.equal(0xfb, buffer[1]);
+	ASSERT.equal(0xfb, buffer[2]);
+	ASSERT.equal(0xff, buffer[3]);
+
+	mod_ctype.wsint16(-1679, 'big', buffer, 1);
+	mod_ctype.wsint16(-1679, 'little', buffer, 3);
+	ASSERT.equal(0xf9, buffer[1]);
+	ASSERT.equal(0x71, buffer[2]);
+	ASSERT.equal(0x71, buffer[3]);
+	ASSERT.equal(0xf9, buffer[4]);
+}
+
+function test32()
+{
+	var buffer = new Buffer(8);
+	mod_ctype.wsint32(0x23, 'big', buffer, 0);
+	mod_ctype.wsint32(0x23, 'little', buffer, 4);
+	ASSERT.equal(0x00, buffer[0]);
+	ASSERT.equal(0x00, buffer[1]);
+	ASSERT.equal(0x00, buffer[2]);
+	ASSERT.equal(0x23, buffer[3]);
+	ASSERT.equal(0x23, buffer[4]);
+	ASSERT.equal(0x00, buffer[5]);
+	ASSERT.equal(0x00, buffer[6]);
+	ASSERT.equal(0x00, buffer[7]);
+
+	mod_ctype.wsint32(-5, 'big', buffer, 0);
+	mod_ctype.wsint32(-5, 'little', buffer, 4);
+	ASSERT.equal(0xff, buffer[0]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xff, buffer[2]);
+	ASSERT.equal(0xfb, buffer[3]);
+	ASSERT.equal(0xfb, buffer[4]);
+	ASSERT.equal(0xff, buffer[5]);
+	ASSERT.equal(0xff, buffer[6]);
+	ASSERT.equal(0xff, buffer[7]);
+
+	mod_ctype.wsint32(-805306713, 'big', buffer, 0);
+	mod_ctype.wsint32(-805306713, 'litle', buffer, 4);
+	ASSERT.equal(0xcf, buffer[0]);
+	ASSERT.equal(0xff, buffer[1]);
+	ASSERT.equal(0xfe, buffer[2]);
+	ASSERT.equal(0xa7, buffer[3]);
+	ASSERT.equal(0xa7, buffer[4]);
+	ASSERT.equal(0xfe, buffer[5]);
+	ASSERT.equal(0xff, buffer[6]);
+	ASSERT.equal(0xcf, buffer[7]);
+}
+
+test8();
+test16();
+test32();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.64.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.64.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.64.js	(revision 484)
@@ -0,0 +1,451 @@
+/*
+ * Test our ability to read and write unsigned 64-bit integers.
+ */
+
+var mod_ctype = require('../../../ctio.js');
+var ASSERT = require('assert');
+
+function testRead()
+{
+	var res, data;
+	data = new Buffer(10);
+
+	data[0] = 0x32;
+	data[1] = 0x65;
+	data[2] = 0x42;
+	data[3] = 0x56;
+	data[4] = 0x23;
+	data[5] = 0xff;
+	data[6] = 0xff;
+	data[7] = 0xff;
+	data[8] = 0x89;
+	data[9] = 0x11;
+	res = mod_ctype.ruint64(data, 'big', 0);
+	ASSERT.equal(0x32654256, res[0]);
+	ASSERT.equal(0x23ffffff, res[1]);
+	res = mod_ctype.ruint64(data, 'big', 1);
+	ASSERT.equal(0x65425623, res[0]);
+	ASSERT.equal(0xffffff89, res[1]);
+	res = mod_ctype.ruint64(data, 'big', 2);
+	ASSERT.equal(0x425623ff, res[0]);
+	ASSERT.equal(0xffff8911, res[1]);
+	res = mod_ctype.ruint64(data, 'little', 0);
+	ASSERT.equal(0xffffff23, res[0]);
+	ASSERT.equal(0x56426532, res[1]);
+	res = mod_ctype.ruint64(data, 'little', 1);
+	ASSERT.equal(0x89ffffff, res[0]);
+	ASSERT.equal(0x23564265, res[1]);
+	res = mod_ctype.ruint64(data, 'little', 2);
+	ASSERT.equal(0x1189ffff, res[0]);
+	ASSERT.equal(0xff235642, res[1]);
+
+}
+
+function testReadOver()
+{
+	var res, data;
+	data = new Buffer(10);
+
+	data[0] = 0x80;
+	data[1] = 0xff;
+	data[2] = 0x80;
+	data[3] = 0xff;
+	data[4] = 0x80;
+	data[5] = 0xff;
+	data[6] = 0x80;
+	data[7] = 0xff;
+	data[8] = 0x80;
+	data[9] = 0xff;
+	res = mod_ctype.ruint64(data, 'big', 0);
+	ASSERT.equal(0x80ff80ff, res[0]);
+	ASSERT.equal(0x80ff80ff, res[1]);
+	res = mod_ctype.ruint64(data, 'big', 1);
+	ASSERT.equal(0xff80ff80, res[0]);
+	ASSERT.equal(0xff80ff80, res[1]);
+	res = mod_ctype.ruint64(data, 'big', 2);
+	ASSERT.equal(0x80ff80ff, res[0]);
+	ASSERT.equal(0x80ff80ff, res[1]);
+	res = mod_ctype.ruint64(data, 'little', 0);
+	ASSERT.equal(0xff80ff80, res[0]);
+	ASSERT.equal(0xff80ff80, res[1]);
+	res = mod_ctype.ruint64(data, 'little', 1);
+	ASSERT.equal(0x80ff80ff, res[0]);
+	ASSERT.equal(0x80ff80ff, res[1]);
+	res = mod_ctype.ruint64(data, 'little', 2);
+	ASSERT.equal(0xff80ff80, res[0]);
+	ASSERT.equal(0xff80ff80, res[1]);
+}
+
+function testWriteZero()
+{
+	var data, buf;
+	buf = new Buffer(10);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wuint64(data, 'big', buf, 0);
+	ASSERT.equal(0, buf[0]);
+	ASSERT.equal(0, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wuint64(data, 'big', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wuint64(data, 'big', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0, buf[8]);
+	ASSERT.equal(0, buf[9]);
+
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wuint64(data, 'little', buf, 0);
+	ASSERT.equal(0, buf[0]);
+	ASSERT.equal(0, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wuint64(data, 'little', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	data = [0, 0];
+	mod_ctype.wuint64(data, 'little', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0, buf[2]);
+	ASSERT.equal(0, buf[3]);
+	ASSERT.equal(0, buf[4]);
+	ASSERT.equal(0, buf[5]);
+	ASSERT.equal(0, buf[6]);
+	ASSERT.equal(0, buf[7]);
+	ASSERT.equal(0, buf[8]);
+	ASSERT.equal(0, buf[9]);
+}
+
+/*
+ * Also include tests that are going to force us to go into a negative value and
+ * insure that it's written correctly.
+ */
+function testWrite()
+{
+	var data, buf;
+
+	buf = new Buffer(10);
+	data = [ 0x234456, 0x87 ];
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'big', buf, 0);
+	ASSERT.equal(0x00, buf[0]);
+	ASSERT.equal(0x23, buf[1]);
+	ASSERT.equal(0x44, buf[2]);
+	ASSERT.equal(0x56, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x87, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'big', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x23, buf[2]);
+	ASSERT.equal(0x44, buf[3]);
+	ASSERT.equal(0x56, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x00, buf[7]);
+	ASSERT.equal(0x87, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'big', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x23, buf[3]);
+	ASSERT.equal(0x44, buf[4]);
+	ASSERT.equal(0x56, buf[5]);
+	ASSERT.equal(0x00, buf[6]);
+	ASSERT.equal(0x00, buf[7]);
+	ASSERT.equal(0x00, buf[8]);
+	ASSERT.equal(0x87, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'little', buf, 0);
+	ASSERT.equal(0x87, buf[0]);
+	ASSERT.equal(0x00, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x56, buf[4]);
+	ASSERT.equal(0x44, buf[5]);
+	ASSERT.equal(0x23, buf[6]);
+	ASSERT.equal(0x00, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'little', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x87, buf[1]);
+	ASSERT.equal(0x00, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x56, buf[5]);
+	ASSERT.equal(0x44, buf[6]);
+	ASSERT.equal(0x23, buf[7]);
+	ASSERT.equal(0x00, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'little', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0x87, buf[2]);
+	ASSERT.equal(0x00, buf[3]);
+	ASSERT.equal(0x00, buf[4]);
+	ASSERT.equal(0x00, buf[5]);
+	ASSERT.equal(0x56, buf[6]);
+	ASSERT.equal(0x44, buf[7]);
+	ASSERT.equal(0x23, buf[8]);
+	ASSERT.equal(0x00, buf[9]);
+
+	data = [0xffff3421, 0x34abcdba];
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'big', buf, 0);
+	ASSERT.equal(0xff, buf[0]);
+	ASSERT.equal(0xff, buf[1]);
+	ASSERT.equal(0x34, buf[2]);
+	ASSERT.equal(0x21, buf[3]);
+	ASSERT.equal(0x34, buf[4]);
+	ASSERT.equal(0xab, buf[5]);
+	ASSERT.equal(0xcd, buf[6]);
+	ASSERT.equal(0xba, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'big', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0xff, buf[1]);
+	ASSERT.equal(0xff, buf[2]);
+	ASSERT.equal(0x34, buf[3]);
+	ASSERT.equal(0x21, buf[4]);
+	ASSERT.equal(0x34, buf[5]);
+	ASSERT.equal(0xab, buf[6]);
+	ASSERT.equal(0xcd, buf[7]);
+	ASSERT.equal(0xba, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'big', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0xff, buf[2]);
+	ASSERT.equal(0xff, buf[3]);
+	ASSERT.equal(0x34, buf[4]);
+	ASSERT.equal(0x21, buf[5]);
+	ASSERT.equal(0x34, buf[6]);
+	ASSERT.equal(0xab, buf[7]);
+	ASSERT.equal(0xcd, buf[8]);
+	ASSERT.equal(0xba, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'little', buf, 0);
+	ASSERT.equal(0xba, buf[0]);
+	ASSERT.equal(0xcd, buf[1]);
+	ASSERT.equal(0xab, buf[2]);
+	ASSERT.equal(0x34, buf[3]);
+	ASSERT.equal(0x21, buf[4]);
+	ASSERT.equal(0x34, buf[5]);
+	ASSERT.equal(0xff, buf[6]);
+	ASSERT.equal(0xff, buf[7]);
+	ASSERT.equal(0x66, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'little', buf, 1);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0xba, buf[1]);
+	ASSERT.equal(0xcd, buf[2]);
+	ASSERT.equal(0xab, buf[3]);
+	ASSERT.equal(0x34, buf[4]);
+	ASSERT.equal(0x21, buf[5]);
+	ASSERT.equal(0x34, buf[6]);
+	ASSERT.equal(0xff, buf[7]);
+	ASSERT.equal(0xff, buf[8]);
+	ASSERT.equal(0x66, buf[9]);
+
+	buf.fill(0x66);
+	mod_ctype.wuint64(data, 'little', buf, 2);
+	ASSERT.equal(0x66, buf[0]);
+	ASSERT.equal(0x66, buf[1]);
+	ASSERT.equal(0xba, buf[2]);
+	ASSERT.equal(0xcd, buf[3]);
+	ASSERT.equal(0xab, buf[4]);
+	ASSERT.equal(0x34, buf[5]);
+	ASSERT.equal(0x21, buf[6]);
+	ASSERT.equal(0x34, buf[7]);
+	ASSERT.equal(0xff, buf[8]);
+	ASSERT.equal(0xff, buf[9]);
+}
+
+/*
+ * Make sure we catch invalid writes.
+ */
+function testWriteInvalid()
+{
+	var data, buf;
+
+	/* Buffer too small */
+	buf = new Buffer(4);
+	data = [ 0, 0];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 0);
+	}, Error, 'buffer too small');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 0);
+	}, Error, 'buffer too small');
+
+	/* Beyond the end of the buffer */
+	buf = new Buffer(12);
+	data = [ 0, 0];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 11);
+	}, Error, 'write beyond end of buffer');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 11);
+	}, Error, 'write beyond end of buffer');
+
+	/* Write negative values */
+	buf = new Buffer(12);
+	data = [ -3, 0 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 1);
+	}, Error, 'write negative number');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 1);
+	}, Error, 'write negative number');
+
+	data = [ 0, -3 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 1);
+	}, Error, 'write negative number');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 1);
+	}, Error, 'write negative number');
+
+	data = [ -3, -3 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 1);
+	}, Error, 'write negative number');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 1);
+	}, Error, 'write negative number');
+
+
+	/* Write fractional values */
+	buf = new Buffer(12);
+	data = [ 3.33, 0 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	data = [ 0, 3.3 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	data = [ 3.33, 2.42 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 1);
+	}, Error, 'write fractions');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 1);
+	}, Error, 'write fractions');
+
+	/* Write values that are too large */
+	buf = new Buffer(12);
+	data = [ 0xffffffffff, 23 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	data = [ 0xffffffffff, 0xffffff238 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+
+	data = [ 0x23, 0xffffff238 ];
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'big', buf, 1);
+	}, Error, 'write too large');
+	ASSERT.throws(function () {
+	    mod_ctype.wuint64(data, 'little', buf, 1);
+	}, Error, 'write too large');
+}
+
+
+testRead();
+testReadOver();
+testWriteZero();
+testWrite();
+testWriteInvalid();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.roundtrip.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.roundtrip.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.roundtrip.js	(revision 484)
@@ -0,0 +1,81 @@
+/*
+ * A battery of tests for sucessful round-trip between writes and reads
+ */
+
+var mod_ctype = require('../../../ctio.js');
+var ASSERT = require('assert');
+
+
+/*
+ * What the heck, let's just test every value for 8-bits.
+ */
+
+function test8() {
+	var data = new Buffer(1);
+	var i;
+	for (i = 0; i < 256; i++) {
+		mod_ctype.wuint8(i, 'big', data, 0);
+		ASSERT.equal(i, mod_ctype.ruint8(data, 'big', 0));
+		mod_ctype.wuint8(i, 'little', data, 0);
+		ASSERT.equal(i, mod_ctype.ruint8(data, 'little', 0));
+	}
+	ASSERT.ok(true);
+}
+
+/*
+ * Test a random sample of 256 values in the 16-bit unsigned range
+ */
+
+function test16() {
+	var data = new Buffer(2);
+	var i = 0;
+	for (i = 0; i < 256; i++) {
+		var value = Math.round(Math.random() * Math.pow(2, 16));
+		mod_ctype.wuint16(value, 'big', data, 0);
+		ASSERT.equal(value, mod_ctype.ruint16(data, 'big', 0));
+		mod_ctype.wuint16(value, 'little', data, 0);
+		ASSERT.equal(value, mod_ctype.ruint16(data, 'little', 0));
+	}
+}
+
+/*
+ * Test a random sample of 256 values in the 32-bit unsigned range
+ */
+
+function test32() {
+	var data = new Buffer(4);
+	var i = 0;
+	for (i = 0; i < 256; i++) {
+		var value = Math.round(Math.random() * Math.pow(2, 32));
+		mod_ctype.wuint32(value, 'big', data, 0);
+		ASSERT.equal(value, mod_ctype.ruint32(data, 'big', 0));
+		mod_ctype.wuint32(value, 'little', data, 0);
+		ASSERT.equal(value, mod_ctype.ruint32(data, 'little', 0));
+	}
+}
+
+/*
+ * Test a random sample of 256 values in the 64-bit unsigned range
+ */
+
+function test64() {
+	var data = new Buffer(8);
+	var i = 0;
+	for (i = 0; i < 256; i++) {
+		var low = Math.round(Math.random() * Math.pow(2, 32));
+		var high = Math.round(Math.random() * Math.pow(2, 32));
+		mod_ctype.wuint64([high, low], 'big', data, 0);
+		var result = mod_ctype.ruint64(data, 'big', 0);
+		ASSERT.equal(high, result[0]);
+		ASSERT.equal(low, result[1]);
+		mod_ctype.wuint64([high, low], 'little', data, 0);
+		result = mod_ctype.ruint64(data, 'little', 0);
+		ASSERT.equal(high, result[0]);
+		ASSERT.equal(low, result[1]);
+	}
+}
+
+exports.test8 = test8;
+exports.test16 = test16;
+exports.test32 = test32;
+exports.test64 = test64;
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.ruint.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.ruint.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.ruint.js	(revision 484)
@@ -0,0 +1,95 @@
+/*
+ * A battery of tests to help us read a series of uints
+ */
+
+var mod_ctype = require('../../../ctio.js');
+var ASSERT = require('assert');
+
+/*
+ * We need to check the following things:
+ *  - We are correctly resolving big endian (doesn't mean anything for 8 bit)
+ *  - Correctly resolving little endian (doesn't mean anything for 8 bit)
+ *  - Correctly using the offsets
+ *  - Correctly interpreting values that are beyond the signed range as unsigned
+ */
+function test8()
+{
+	var data = new Buffer(4);
+	data[0] = 23;
+	data[1] = 23;
+	data[2] = 23;
+	data[3] = 23;
+	ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 0));
+	ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 0));
+	ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 1));
+	ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 1));
+	ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 2));
+	ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 2));
+	ASSERT.equal(23, mod_ctype.ruint8(data, 'big', 3));
+	ASSERT.equal(23, mod_ctype.ruint8(data, 'little', 3));
+	data[0] = 255; /* If it became a signed int, would be -1 */
+	ASSERT.equal(255, mod_ctype.ruint8(data, 'big', 0));
+	ASSERT.equal(255, mod_ctype.ruint8(data, 'little', 0));
+}
+
+/*
+ * Test 16 bit unsigned integers. We need to verify the same set as 8 bit, only
+ * now some of the issues actually matter:
+ *  - We are correctly resolving big endian
+ *  - Correctly resolving little endian
+ *  - Correctly using the offsets
+ *  - Correctly interpreting values that are beyond the signed range as unsigned
+ */
+function test16()
+{
+	var data = new Buffer(4);
+	/* Test signed values first */
+	data[0] = 0;
+	data[1] = 0x23;
+	data[2] = 0x42;
+	data[3] = 0x3f;
+
+	ASSERT.equal(0x23, mod_ctype.ruint16(data, 'big', 0));
+	ASSERT.equal(0x2342, mod_ctype.ruint16(data, 'big', 1));
+	ASSERT.equal(0x423f, mod_ctype.ruint16(data, 'big', 2));
+
+	ASSERT.equal(0x2300, mod_ctype.ruint16(data, 'little', 0));
+	ASSERT.equal(0x4223, mod_ctype.ruint16(data, 'little', 1));
+	ASSERT.equal(0x3f42, mod_ctype.ruint16(data, 'little', 2));
+
+	data[0] = 0xfe;
+	data[1] = 0xfe;
+
+	ASSERT.equal(0xfefe, mod_ctype.ruint16(data, 'big', 0));
+	ASSERT.equal(0xfefe, mod_ctype.ruint16(data, 'little', 0));
+}
+
+/*
+ * Test 32 bit unsigned integers. We need to verify the same set as 8 bit, only
+ * now some of the issues actually matter:
+ *  - We are correctly resolving big endian
+ *  - Correctly using the offsets
+ *  - Correctly interpreting values that are beyond the signed range as unsigned
+ */
+function test32()
+{
+	var data = new Buffer(8);
+	data[0] = 0x32;
+	data[1] = 0x65;
+	data[2] = 0x42;
+	data[3] = 0x56;
+	data[4] = 0x23;
+	data[5] = 0xff;
+
+	ASSERT.equal(0x32654256, mod_ctype.ruint32(data, 'big', 0));
+	ASSERT.equal(0x65425623, mod_ctype.ruint32(data, 'big', 1));
+	ASSERT.equal(0x425623ff, mod_ctype.ruint32(data, 'big', 2));
+
+	ASSERT.equal(0x56426532, mod_ctype.ruint32(data, 'little', 0));
+	ASSERT.equal(0x23564265, mod_ctype.ruint32(data, 'little', 1));
+	ASSERT.equal(0xff235642, mod_ctype.ruint32(data, 'little', 2));
+}
+
+test8();
+test16();
+test32();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.wuint.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.wuint.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctio/uint/tst.wuint.js	(revision 484)
@@ -0,0 +1,156 @@
+/*
+ * A battery of tests to help us read a series of uints
+ */
+
+var mod_ctype = require('../../../ctio.js');
+var ASSERT = require('assert');
+
+/*
+ * We need to check the following things:
+ *  - We are correctly resolving big endian (doesn't mean anything for 8 bit)
+ *  - Correctly resolving little endian (doesn't mean anything for 8 bit)
+ *  - Correctly using the offsets
+ *  - Correctly interpreting values that are beyond the signed range as unsigned
+ */
+function test8()
+{
+	var data = new Buffer(4);
+	mod_ctype.wuint8(23, 'big', data, 0);
+	mod_ctype.wuint8(23, 'big', data, 1);
+	mod_ctype.wuint8(23, 'big', data, 2);
+	mod_ctype.wuint8(23, 'big', data, 3);
+	ASSERT.equal(23, data[0]);
+	ASSERT.equal(23, data[1]);
+	ASSERT.equal(23, data[2]);
+	ASSERT.equal(23, data[3]);
+	mod_ctype.wuint8(23, 'little', data, 0);
+	mod_ctype.wuint8(23, 'little', data, 1);
+	mod_ctype.wuint8(23, 'little', data, 2);
+	mod_ctype.wuint8(23, 'little', data, 3);
+	ASSERT.equal(23, data[0]);
+	ASSERT.equal(23, data[1]);
+	ASSERT.equal(23, data[2]);
+	ASSERT.equal(23, data[3]);
+	mod_ctype.wuint8(255, 'big', data, 0);
+	ASSERT.equal(255, data[0]);
+	mod_ctype.wuint8(255, 'little', data, 0);
+	ASSERT.equal(255, data[0]);
+}
+
+function test16()
+{
+	var value = 0x2343;
+	var data = new Buffer(4);
+	mod_ctype.wuint16(value, 'big', data, 0);
+	ASSERT.equal(0x23, data[0]);
+	ASSERT.equal(0x43, data[1]);
+	mod_ctype.wuint16(value, 'big', data, 1);
+	ASSERT.equal(0x23, data[1]);
+	ASSERT.equal(0x43, data[2]);
+	mod_ctype.wuint16(value, 'big', data, 2);
+	ASSERT.equal(0x23, data[2]);
+	ASSERT.equal(0x43, data[3]);
+
+	mod_ctype.wuint16(value, 'little', data, 0);
+	ASSERT.equal(0x23, data[1]);
+	ASSERT.equal(0x43, data[0]);
+
+	mod_ctype.wuint16(value, 'little', data, 1);
+	ASSERT.equal(0x23, data[2]);
+	ASSERT.equal(0x43, data[1]);
+
+	mod_ctype.wuint16(value, 'little', data, 2);
+	ASSERT.equal(0x23, data[3]);
+	ASSERT.equal(0x43, data[2]);
+
+	value = 0xff80;
+	mod_ctype.wuint16(value, 'little', data, 0);
+	ASSERT.equal(0xff, data[1]);
+	ASSERT.equal(0x80, data[0]);
+
+	mod_ctype.wuint16(value, 'big', data, 0);
+	ASSERT.equal(0xff, data[0]);
+	ASSERT.equal(0x80, data[1]);
+}
+
+function test32()
+{
+	var data = new Buffer(6);
+	var value = 0xe7f90a6d;
+
+	mod_ctype.wuint32(value, 'big', data, 0);
+	ASSERT.equal(0xe7, data[0]);
+	ASSERT.equal(0xf9, data[1]);
+	ASSERT.equal(0x0a, data[2]);
+	ASSERT.equal(0x6d, data[3]);
+
+	mod_ctype.wuint32(value, 'big', data, 1);
+	ASSERT.equal(0xe7, data[1]);
+	ASSERT.equal(0xf9, data[2]);
+	ASSERT.equal(0x0a, data[3]);
+	ASSERT.equal(0x6d, data[4]);
+
+	mod_ctype.wuint32(value, 'big', data, 2);
+	ASSERT.equal(0xe7, data[2]);
+	ASSERT.equal(0xf9, data[3]);
+	ASSERT.equal(0x0a, data[4]);
+	ASSERT.equal(0x6d, data[5]);
+
+	mod_ctype.wuint32(value, 'little', data, 0);
+	ASSERT.equal(0xe7, data[3]);
+	ASSERT.equal(0xf9, data[2]);
+	ASSERT.equal(0x0a, data[1]);
+	ASSERT.equal(0x6d, data[0]);
+
+	mod_ctype.wuint32(value, 'little', data, 1);
+	ASSERT.equal(0xe7, data[4]);
+	ASSERT.equal(0xf9, data[3]);
+	ASSERT.equal(0x0a, data[2]);
+	ASSERT.equal(0x6d, data[1]);
+
+	mod_ctype.wuint32(value, 'little', data, 2);
+	ASSERT.equal(0xe7, data[5]);
+	ASSERT.equal(0xf9, data[4]);
+	ASSERT.equal(0x0a, data[3]);
+	ASSERT.equal(0x6d, data[2]);
+}
+
+function test64()
+{
+	var data = new Buffer(10);
+	var value = 0x0007cda8e7f90a6d;
+	var high = Math.floor(value / Math.pow(2, 32));
+	var low = value - (high * Math.pow(2, 32));
+	ASSERT.equal(0x0007cda8, high);
+	ASSERT.equal(0xe7f90a6d, low);
+
+	mod_ctype.wuint64([high, low], 'big', data, 0);
+	ASSERT.equal(0x00, data[0]);
+	ASSERT.equal(0x07, data[1]);
+	ASSERT.equal(0xcd, data[2]);
+	ASSERT.equal(0xa8, data[3]);
+	ASSERT.equal(0xe7, data[4]);
+	ASSERT.equal(0xf9, data[5]);
+	ASSERT.equal(0x0a, data[6]);
+	ASSERT.equal(0x6d, data[7]);
+
+	mod_ctype.wuint64([high, low], 'little', data, 0);
+	ASSERT.equal(0x6d, data[0]);
+	ASSERT.equal(0x0a, data[1]);
+	ASSERT.equal(0xf9, data[2]);
+	ASSERT.equal(0xe7, data[3]);
+	ASSERT.equal(0xa8, data[4]);
+	ASSERT.equal(0xcd, data[5]);
+	ASSERT.equal(0x07, data[6]);
+	ASSERT.equal(0x00, data[7]);
+}
+
+test8();
+test16();
+test32();
+test64();
+
+exports.test8 = test8;
+exports.test16 = test16;
+exports.test32 = test32;
+exports.test64 = test64;
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicr.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicr.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicr.js	(revision 484)
@@ -0,0 +1,50 @@
+/*
+ * Simple does to see if it works at all
+ */
+var mod_ctype = require('../../ctype');
+var ASSERT = require('assert');
+var mod_sys = require('sys');
+
+function test()
+{
+	var ii, p, result, buffer;
+
+	p = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer(4);
+	buffer[0] = 23;
+	buffer[3] = 42;
+	result = p.readData([ { x: { type: 'uint8_t' }},
+	    { y: { type: 'uint8_t', offset: 3 }}
+	], buffer, 0);
+	ASSERT.equal(23, result['x']);
+	ASSERT.equal(42, result['y']);
+
+	buffer = new Buffer(23);
+	for (ii = 0; ii < 23; ii++)
+		buffer[ii] = 0;
+
+	buffer.write('Hello, world!');
+	result = p.readData([ { x: { type: 'char[20]' }} ], buffer, 0);
+
+	/*
+	 * This is currently broken behvaior, need to redesign check
+	 * ASSERT.equal('Hello, world!', result['x'].toString('utf-8', 0,
+	 *  result['x'].length));
+	 */
+
+	buffer = new Buffer(4);
+	buffer[0] = 0x03;
+	buffer[1] = 0x24;
+	buffer[2] = 0x25;
+	buffer[3] = 0x26;
+	result = p.readData([ { y: { type: 'uint8_t' }},
+	    { x: { type: 'uint8_t[y]' }}], buffer, 0);
+	console.log(mod_sys.inspect(result, true));
+
+	p.typedef('ssize_t', 'int32_t');
+	ASSERT.deepEqual({ 'ssize_t': 'int32_t' }, p.lstypes());
+	result = p.readData([ { x: { type: 'ssize_t' } } ], buffer, 0);
+	ASSERT.equal(0x26252403, result['x']);
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicw.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicw.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.basicw.js	(revision 484)
@@ -0,0 +1,44 @@
+/*
+ * Simple does it fucking work at all test
+ */
+
+var mod_ctype = require('../../ctype');
+var ASSERT = require('assert');
+var mod_sys = require('sys');
+
+function test()
+{
+	var ii, p, buffer, buf2;
+
+	p = new mod_ctype.Parser({ endian: 'big' });
+	buffer = new Buffer(4);
+	p.writeData([ { x: { type: 'uint8_t', value: 23 }},
+	    { y: { type: 'uint8_t', offset: 3, value: 42 }}
+	], buffer, 0);
+	ASSERT.equal(23, buffer[0]);
+	ASSERT.equal(42, buffer[3]);
+
+	buffer = new Buffer(20);
+	for (ii = 0; ii < 20; ii++)
+		buffer[ii] = 0;
+
+	buffer.write('Hello, world!');
+	buf2 = new Buffer(22);
+	p.writeData([ { x: { type: 'char[20]', value: buffer }} ], buf2, 0);
+	for (ii = 0; ii < 20; ii++)
+		ASSERT.equal(buffer[ii], buf2[ii]);
+	/*
+	 * This is currently broken behvaior, need to redesign check
+	 * ASSERT.equal('Hello, world!', result['x'].toString('utf-8', 0,
+	 *   result['x'].length));
+	 */
+
+	buffer = new Buffer(4);
+	p.writeData([ { y: { type: 'uint8_t', value: 3 }},
+	    { x: { type: 'uint8_t[y]', value: [ 0x24, 0x25, 0x26] }}],
+	    buffer, 0);
+	console.log(mod_sys.inspect(buffer));
+
+	p.typedef('ssize_t', 'int32_t');
+	ASSERT.deepEqual({ 'ssize_t': 'int32_t' }, p.lstypes());
+}
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.char.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.char.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.char.js	(revision 484)
@@ -0,0 +1,42 @@
+/*
+ * Test the different forms of reading characters:
+ *
+ *  - the default, a single element buffer
+ *  - uint8, values are uint8_ts
+ *  - int8, values are int8_ts
+ */
+var mod_ctype = require('../../ctype');
+var mod_assert = require('assert');
+
+function test()
+{
+	var p, buf, res;
+
+	buf = new Buffer(1);
+	buf[0] = 255;
+
+	p = new mod_ctype.Parser({ endian: 'little'});
+	res = p.readData([ { c: { type: 'char' }} ], buf, 0);
+	res = res['c'];
+	mod_assert.ok(res instanceof Buffer);
+	mod_assert.equal(255, res[0]);
+
+	p = new mod_ctype.Parser({ endian: 'little',
+	    'char-type': 'int8' });
+	res = p.readData([ { c: { type: 'char' }} ], buf, 0);
+	res = res['c'];
+	mod_assert.ok(typeof (res) == 'number', 'got typeof (res): ' +
+	    typeof (res));
+	mod_assert.equal(-1, res);
+
+	p = new mod_ctype.Parser({ endian: 'little',
+	    'char-type': 'uint8' });
+	res = p.readData([ { c: { type: 'char' }} ], buf, 0);
+	res = res['c'];
+	mod_assert.ok(typeof (res) == 'number', 'got typeof (res): ' +
+	    typeof (res));
+	mod_assert.equal(255, res);
+
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.endian.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.endian.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.endian.js	(revision 484)
@@ -0,0 +1,45 @@
+/*
+ * Simple test to make sure that the endian setting works.
+ */
+
+var mod_ctype = require('../../ctype.js');
+var mod_assert = require('assert');
+
+function test()
+{
+	var parser, buf;
+
+	parser = new mod_ctype.Parser({
+	    endian: 'little'
+	});
+
+	buf = new Buffer(2);
+	parser.writeData([ { key: { type: 'uint16_t' } } ], buf, 0, [ 0x1234 ]);
+	mod_assert.equal(buf[0], 0x34);
+	mod_assert.equal(buf[1], 0x12);
+	parser.setEndian('big');
+
+	parser.writeData([ { key: { type: 'uint16_t' } } ], buf, 0, [ 0x1234 ]);
+	mod_assert.equal(buf[0], 0x12);
+	mod_assert.equal(buf[1], 0x34);
+
+	parser.setEndian('little');
+	parser.writeData([ { key: { type: 'uint16_t' } } ], buf, 0, [ 0x1234 ]);
+	mod_assert.equal(buf[0], 0x34);
+	mod_assert.equal(buf[1], 0x12);
+}
+
+function fail()
+{
+	var parser;
+
+	parser = new mod_ctype.Parser({
+	    endian: 'little'
+	});
+	mod_assert.throws(function () {
+		parser.setEndian('littlebigwrong');
+	});
+}
+
+test();
+fail();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.oldwrite.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.oldwrite.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.oldwrite.js	(revision 484)
@@ -0,0 +1,28 @@
+/*
+ * A long overdue test to go through and verify that we can read and write
+ * structures as well as nested structures.
+ */
+
+var mod_ctype = require('../../ctype.js');
+var mod_assert = require('assert');
+
+function test()
+{
+	var parser, buf, data;
+	parser = new mod_ctype.Parser({
+	    endian: 'little'
+	});
+	parser.typedef('point_t', [
+	    { x: { type: 'uint8_t' } },
+	    { y: { type: 'uint8_t' } }
+	]);
+	buf = new Buffer(2);
+	data = [
+	    { point: { type: 'point_t', value: [ 23, 42 ] } }
+	];
+	parser.writeData(data, buf, 0);
+	mod_assert.ok(buf[0] == 23);
+	mod_assert.ok(buf[1] == 42);
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.readSize.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.readSize.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.readSize.js	(revision 484)
@@ -0,0 +1,128 @@
+/*
+ * Testing to ensure we're reading the expected number bytes
+ */
+var mod_ctype = require('../../ctype');
+var ASSERT = require('assert');
+
+function testUint8()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('80', 'hex');
+	result = parser.readStruct([ { item: { type: 'uint8_t' } } ], buffer,
+	    0);
+	ASSERT.equal(result['size'], 1);
+}
+
+function testSint8()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('80', 'hex');
+	result = parser.readStruct([ { item: { type: 'int8_t' } } ], buffer, 0);
+	ASSERT.equal(result['size'], 1);
+}
+
+function testUint16()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('8000', 'hex');
+	result = parser.readStruct([ { item: { type: 'uint16_t' } } ], buffer,
+	    0);
+	ASSERT.equal(result['size'], 2);
+}
+
+function testSint16()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('8000', 'hex');
+	result = parser.readStruct([ { item: { type: 'int16_t' } } ], buffer,
+	    0);
+	ASSERT.equal(result['size'], 2);
+}
+
+function testUint32()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('80000000', 'hex');
+	result = parser.readStruct([ { item: { type: 'uint32_t' } } ], buffer,
+	    0);
+	ASSERT.equal(result['size'], 4);
+}
+
+function testSint32()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('80000000', 'hex');
+	result = parser.readStruct([ { item: { type: 'int32_t' } } ], buffer,
+	    0);
+	ASSERT.equal(result['size'], 4);
+}
+
+function testUint64()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('8000000000000000', 'hex');
+	result = parser.readStruct([ { item: { type: 'uint64_t' } } ], buffer,
+	    0);
+	ASSERT.equal(result['size'], 8);
+}
+
+function testSint64()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('8000000000000000', 'hex');
+	result = parser.readStruct([ { item: { type: 'int64_t' } } ], buffer,
+	    0);
+	ASSERT.equal(result['size'], 8);
+}
+
+function testFloat()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('ABAAAA3E', 'hex');
+	result = parser.readStruct([ { item: { type: 'float' } } ], buffer, 0);
+	ASSERT.equal(result['size'], 4);
+}
+
+function testDouble()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('000000000000F03F', 'hex');
+	result = parser.readStruct([ { item: { type: 'double' } } ], buffer, 0);
+	ASSERT.equal(result['size'], 8);
+}
+
+function testChar()
+{
+	var parser, result, buffer;
+	parser = new mod_ctype.Parser({ endian: 'little' });
+	buffer = new Buffer('t');
+	result = parser.readStruct([ { item: { type: 'char' } } ], buffer, 0);
+	ASSERT.equal(result['size'], 1);
+}
+
+function test()
+{
+	testSint8();
+	testUint8();
+	testSint16();
+	testUint16();
+	testSint32();
+	testUint32();
+	testSint64();
+	testUint64();
+	testFloat();
+	testDouble();
+	testChar();
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.structw.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.structw.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.structw.js	(revision 484)
@@ -0,0 +1,28 @@
+/*
+ * A long overdue test to go through and verify that we can read and write
+ * structures as well as nested structures.
+ */
+
+var mod_ctype = require('../../ctype.js');
+var mod_assert = require('assert');
+
+function test()
+{
+	var parser, buf, data;
+	parser = new mod_ctype.Parser({
+	    endian: 'little'
+	});
+	parser.typedef('point_t', [
+	    { x: { type: 'uint8_t' } },
+	    { y: { type: 'uint8_t' } }
+	]);
+	buf = new Buffer(2);
+	data = [
+	    { point: { type: 'point_t' } }
+	];
+	parser.writeData(data, buf, 0, [ [ 23, 42 ] ]);
+	mod_assert.ok(buf[0] == 23);
+	mod_assert.ok(buf[1] == 42);
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.writeStruct.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.writeStruct.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/node_modules/ctype/tst/ctype/tst.writeStruct.js	(revision 484)
@@ -0,0 +1,31 @@
+/*
+ * Test to verify that the offset is incremented when structures are written to.
+ * Hopefully we will not regress issue #41
+ */
+
+var mod_ctype = require('../../ctype.js');
+var mod_assert = require('assert');
+
+function test()
+{
+	var parser, buf, data;
+	parser = new mod_ctype.Parser({
+	    endian: 'little'
+	});
+	parser.typedef('point_t', [
+	    { x: { type: 'uint8_t' } },
+	    { y: { type: 'uint8_t' } }
+	]);
+	buf = new Buffer(4);
+	data = [
+	    { point1: { type: 'point_t' } },
+	    { point2: { type: 'point_t' } }
+	];
+	parser.writeData(data, buf, 0, [ [ 23, 42 ], [ 91, 18 ] ]);
+	mod_assert.ok(buf[0] == 23);
+	mod_assert.ok(buf[1] == 42);
+	mod_assert.ok(buf[2] == 91);
+	mod_assert.ok(buf[3] == 18);
+}
+
+test();
Index: Dev/trunk/src/node_modules/request/node_modules/http-signature/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/http-signature/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/http-signature/package.json	(revision 484)
@@ -0,0 +1,36 @@
+{
+  "author": {
+    "name": "Joyent, Inc"
+  },
+  "name": "http-signature",
+  "description": "Reference implementation of Joyent's HTTP Signature Scheme",
+  "version": "0.9.11",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/joyent/node-http-signature.git"
+  },
+  "engines": {
+    "node": ">=0.8"
+  },
+  "main": "lib/index.js",
+  "scripts": {
+    "test": "./node_modules/.bin/tap tst/*.js"
+  },
+  "dependencies": {
+    "assert-plus": "0.1.2",
+    "asn1": "0.1.11",
+    "ctype": "0.5.2"
+  },
+  "devDependencies": {
+    "node-uuid": "1.4.0",
+    "tap": "0.3.1"
+  },
+  "readme": "node-http-signature is a node.js library that has client and server components\nfor Joyent's `HTTP Signature Scheme`.\n\n## Usage\n\nNote the example below signs a request with the same key/cert used to start an\nHTTP server. This is almost certainly not what you actaully want, but is just\nused to illustrate the API calls; you will need to provide your own key\nmanagement in addition to this library.\n\n### Client\n\n    var fs = require('fs');\n    var https = require('https');\n    var httpSignature = require('http-signature');\n\n    var key = fs.readFileSync('./key.pem', 'ascii');\n\n    var options = {\n      host: 'localhost',\n      port: 8443,\n      path: '/',\n      method: 'GET',\n      headers: {}\n    };\n\n    // Adds a 'Date' header in, signs it, and adds the\n    // 'Authorization' header in.\n    var req = https.request(options, function(res) {\n      console.log(res.statusCode);\n    });\n\n\n    httpSignature.sign(req, {\n      key: key,\n      keyId: './cert.pem'\n    });\n\n    req.end();\n\n### Server\n\n    var fs = require('fs');\n    var https = require('https');\n    var httpSignature = require('http-signature');\n\n    var options = {\n      key: fs.readFileSync('./key.pem'),\n      cert: fs.readFileSync('./cert.pem')\n    };\n\n    https.createServer(options, function (req, res) {\n      var rc = 200;\n      var parsed = httpSignature.parseRequest(req);\n      var pub = fs.readFileSync(parsed.keyId, 'ascii');\n      if (!httpSignature.verifySignature(parsed, pub))\n        rc = 401;\n\n      res.writeHead(rc);\n      res.end();\n    }).listen(8443);\n\n## Installation\n\n    npm install http-signature\n\n## License\n\nMIT.\n\n## Bugs\n\nSee <https://github.com/joyent/node-http-signature/issues>.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/joyent/node-http-signature/issues"
+  },
+  "homepage": "https://github.com/joyent/node-http-signature",
+  "_id": "http-signature@0.9.11",
+  "_from": "http-signature@~0.9.11"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/LICENSE	(revision 484)
@@ -0,0 +1,27 @@
+Copyright (c) Isaac Z. Schlueter ("Author")
+All rights reserved.
+
+The BSD License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/README.md	(revision 484)
@@ -0,0 +1,27 @@
+# json-stringify-safe
+
+Like JSON.stringify, but doesn't throw on circular references.
+
+## Usage
+
+Takes the same arguments as `JSON.stringify`.
+
+```javascript
+var stringify = require('json-stringify-safe');
+var circularObj = {};
+circularObj.circularRef = circularObj;
+circularObj.list = [ circularObj, circularObj ];
+console.log(stringify(circularObj, null, 2));
+```
+
+Output:
+
+```json
+{
+  "circularRef": "[Circular]",
+  "list": [
+    "[Circular]",
+    "[Circular]"
+  ]
+}
+```
Index: Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/package.json	(revision 484)
@@ -0,0 +1,33 @@
+{
+  "name": "json-stringify-safe",
+  "version": "4.0.0",
+  "description": "Like JSON.stringify, but doesn't blow up on circular refs",
+  "main": "stringify.js",
+  "scripts": {
+    "test": "node test.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/json-stringify-safe"
+  },
+  "keywords": [
+    "json",
+    "stringify",
+    "circular",
+    "safe"
+  ],
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me",
+    "url": "http://blog.izs.me"
+  },
+  "license": "BSD",
+  "readmeFilename": "README.md",
+  "readme": "# json-stringify-safe\n\nLike JSON.stringify, but doesn't throw on circular references.\n\n## Usage\n\nTakes the same arguments as `JSON.stringify`.\n\n```javascript\nvar stringify = require('json-stringify-safe');\nvar circularObj = {};\ncircularObj.circularRef = circularObj;\ncircularObj.list = [ circularObj, circularObj ];\nconsole.log(stringify(circularObj, null, 2));\n```\n\nOutput:\n\n```json\n{\n  \"circularRef\": \"[Circular]\",\n  \"list\": [\n    \"[Circular]\",\n    \"[Circular]\"\n  ]\n}\n```\n",
+  "bugs": {
+    "url": "https://github.com/isaacs/json-stringify-safe/issues"
+  },
+  "homepage": "https://github.com/isaacs/json-stringify-safe",
+  "_id": "json-stringify-safe@4.0.0",
+  "_from": "json-stringify-safe@~4.0.0"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/stringify.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/stringify.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/stringify.js	(revision 484)
@@ -0,0 +1,25 @@
+module.exports = stringify;
+
+function getSerialize (fn, decycle) {
+  var seen = [];
+  decycle = decycle || function(key, value) {
+    return '[Circular]';
+  };
+  return function(key, value) {
+    var ret = value;
+    if (typeof value === 'object' && value) {
+      if (seen.indexOf(value) !== -1)
+        ret = decycle(key, value);
+      else
+        seen.push(value);
+    }
+    if (fn) ret = fn(key, ret);
+    return ret;
+  }
+}
+
+function stringify(obj, fn, spaces, decycle) {
+  return JSON.stringify(obj, getSerialize(fn, decycle), spaces);
+}
+
+stringify.getSerialize = getSerialize;
Index: Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/test.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/test.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/json-stringify-safe/test.js	(revision 484)
@@ -0,0 +1,96 @@
+var stringify = require('./stringify.js');
+
+var circularObj = { a: 'b' };
+circularObj.circularRef = circularObj;
+circularObj.list = [ circularObj, circularObj ];
+
+//////////
+// default
+var testObj = {
+  "a": "b",
+  "circularRef": "[Circular]",
+  "list": [
+    "[Circular]",
+    "[Circular]"
+  ]
+};
+
+var assert = require('assert');
+assert.equal(JSON.stringify(testObj, null, 2),
+             stringify(circularObj, null, 2));
+
+assert.equal(JSON.stringify(testObj, null, 2),
+            JSON.stringify(circularObj, stringify.getSerialize(), 2));
+
+
+////////
+// prune
+testObj = {
+  "a": "b",
+  "list": [
+    null,
+    null
+  ]
+};
+
+function prune(k, v) {}
+
+assert.equal(JSON.stringify(testObj, null, 2),
+             stringify(circularObj, null, 2, prune));
+
+///////////
+// re-cycle
+// (throws)
+function recycle(k, v) {
+  return v;
+}
+
+assert.throws(function() {
+  stringify(circularObj, null, 2, recycle);
+});
+
+////////
+// fancy
+testObj = {
+  "a": "b",
+  "circularRef": "circularRef{a:string,circularRef:Object,list:Array}",
+  "list": [
+    "0{a:string,circularRef:Object,list:Array}",
+    "1{a:string,circularRef:Object,list:Array}"
+  ]
+};
+
+function signer(key, value) {
+  var ret = key + '{';
+  var f = false;
+  for (var i in value) {
+    if (f)
+      ret += ',';
+    f = true;
+    ret += i + ':';
+    var v = value[i];
+    switch (typeof v) {
+      case 'object':
+        if (!v)
+          ret += 'null';
+        else if (Array.isArray(v))
+          ret += 'Array'
+        else
+          ret += v.constructor && v.constructor.name || 'Object';
+        break;
+      default:
+        ret += typeof v;
+        break;
+    }
+  }
+  ret += '}';
+  return ret;
+}
+
+assert.equal(JSON.stringify(testObj, null, 2),
+             stringify(circularObj, null, 2, signer));
+
+
+////////
+// pass!
+console.log('ok');
Index: Dev/trunk/src/node_modules/request/node_modules/mime/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/mime/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/mime/LICENSE	(revision 484)
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Benjamin Thomas, Robert Kieffer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: Dev/trunk/src/node_modules/request/node_modules/mime/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/mime/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/mime/README.md	(revision 484)
@@ -0,0 +1,66 @@
+# mime
+
+Comprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.
+
+## Install
+
+Install with [npm](http://github.com/isaacs/npm):
+
+    npm install mime
+
+## API - Queries
+
+### mime.lookup(path)
+Get the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.').  E.g.
+
+    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.default_type
+Sets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)
+
+### mime.extension(type)
+Get the default extension for `type`
+
+    mime.extension('text/html');                 // => 'html'
+    mime.extension('application/octet-stream');  // => 'bin'
+
+### mime.charsets.lookup()
+
+Map mime-type to charset
+
+    mime.charsets.lookup('text/plain');        // => 'UTF-8'
+
+(The logic for charset lookups is pretty rudimentary.  Feel free to suggest improvements.)
+
+## API - Defining Custom Types
+
+The following APIs allow you to add your own type mappings within your project.  If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).
+
+### mime.define()
+
+Add custom mime/extension mappings
+
+    mime.define({
+        'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],
+        'application/x-my-type': ['x-mt', 'x-mtt'],
+        // etc ...
+    });
+
+    mime.lookup('x-sft');                 // => 'text/x-some-format'
+
+The first entry in the extensions array is returned by `mime.extension()`. E.g.
+
+    mime.extension('text/x-some-format'); // => 'x-sf'
+
+### mime.load(filepath)
+
+Load mappings from an Apache ".types" format file
+
+    mime.load('./my_project.types');
+
+The .types file format is simple -  See the `types` dir for examples.
Index: Dev/trunk/src/node_modules/request/node_modules/mime/mime.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/mime/mime.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/mime/mime.js	(revision 484)
@@ -0,0 +1,114 @@
+var path = require('path');
+var fs = require('fs');
+
+function Mime() {
+  // Map of extension -> mime type
+  this.types = Object.create(null);
+
+  // Map of mime type -> extension
+  this.extensions = Object.create(null);
+}
+
+/**
+ * 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
+ */
+Mime.prototype.define = function (map) {
+  for (var type in map) {
+    var exts = map[type];
+
+    for (var i = 0; i < exts.length; i++) {
+      if (process.env.DEBUG_MIME && this.types[exts]) {
+        console.warn(this._loading.replace(/.*\//, ''), 'changes "' + exts[i] + '" extension type from ' +
+          this.types[exts] + ' to ' + type);
+      }
+
+      this.types[exts[i]] = type;
+    }
+
+    // Default extension is the first one we encounter
+    if (!this.extensions[type]) {
+      this.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.
+ */
+Mime.prototype.load = function(file) {
+
+  this._loading = file;
+  // Read file and split into lines
+  var map = {},
+      content = fs.readFileSync(file, 'ascii'),
+      lines = content.split(/[\r\n]+/);
+
+  lines.forEach(function(line) {
+    // Clean up whitespace/comments, and split into fields
+    var fields = line.replace(/\s*#.*|^\s*|\s*$/g, '').split(/\s+/);
+    map[fields.shift()] = fields;
+  });
+
+  this.define(map);
+
+  this._loading = null;
+};
+
+/**
+ * Lookup a mime type based on extension
+ */
+Mime.prototype.lookup = function(path, fallback) {
+  var ext = path.replace(/.*[\.\/\\]/, '').toLowerCase();
+
+  return this.types[ext] || fallback || this.default_type;
+};
+
+/**
+ * Return file extension associated with a mime type
+ */
+Mime.prototype.extension = function(mimeType) {
+  var type = mimeType.match(/^\s*([^;\s]*)(?:;|\s|$)/)[1].toLowerCase();
+  return this.extensions[type];
+};
+
+// Default instance
+var mime = new Mime();
+
+// Load local copy of
+// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
+mime.load(path.join(__dirname, 'types/mime.types'));
+
+// Load additional types from node.js community
+mime.load(path.join(__dirname, 'types/node.types'));
+
+// Default type
+mime.default_type = mime.lookup('bin');
+
+//
+// Additional API specific to the default instance
+//
+
+mime.Mime = Mime;
+
+/**
+ * Lookup a charset based on mime type.
+ */
+mime.charsets = {
+  lookup: function(mimeType, fallback) {
+    // Assume text types are utf8
+    return (/^text\//).test(mimeType) ? 'UTF-8' : fallback;
+  }
+};
+
+module.exports = mime;
Index: Dev/trunk/src/node_modules/request/node_modules/mime/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/mime/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/mime/package.json	(revision 484)
@@ -0,0 +1,36 @@
+{
+  "author": {
+    "name": "Robert Kieffer",
+    "email": "robert@broofa.com",
+    "url": "http://github.com/broofa"
+  },
+  "contributors": [
+    {
+      "name": "Benjamin Thomas",
+      "email": "benjamin@benjaminthomas.org",
+      "url": "http://github.com/bentomas"
+    }
+  ],
+  "dependencies": {},
+  "description": "A comprehensive library for mime-type mapping",
+  "devDependencies": {},
+  "keywords": [
+    "util",
+    "mime"
+  ],
+  "main": "mime.js",
+  "name": "mime",
+  "repository": {
+    "url": "https://github.com/broofa/node-mime",
+    "type": "git"
+  },
+  "version": "1.2.11",
+  "readme": "# mime\n\nComprehensive MIME type mapping API. Includes all 600+ types and 800+ extensions defined by the Apache project, plus additional types submitted by the node.js community.\n\n## Install\n\nInstall with [npm](http://github.com/isaacs/npm):\n\n    npm install mime\n\n## API - Queries\n\n### mime.lookup(path)\nGet the mime type associated with a file, if no mime type is found `application/octet-stream` is returned. Performs a case-insensitive lookup using the extension in `path` (the substring after the last '/' or '.').  E.g.\n\n    var mime = require('mime');\n\n    mime.lookup('/path/to/file.txt');         // => 'text/plain'\n    mime.lookup('file.txt');                  // => 'text/plain'\n    mime.lookup('.TXT');                      // => 'text/plain'\n    mime.lookup('htm');                       // => 'text/html'\n\n### mime.default_type\nSets the mime type returned when `mime.lookup` fails to find the extension searched for. (Default is `application/octet-stream`.)\n\n### mime.extension(type)\nGet the default extension for `type`\n\n    mime.extension('text/html');                 // => 'html'\n    mime.extension('application/octet-stream');  // => 'bin'\n\n### mime.charsets.lookup()\n\nMap mime-type to charset\n\n    mime.charsets.lookup('text/plain');        // => 'UTF-8'\n\n(The logic for charset lookups is pretty rudimentary.  Feel free to suggest improvements.)\n\n## API - Defining Custom Types\n\nThe following APIs allow you to add your own type mappings within your project.  If you feel a type should be included as part of node-mime, see [requesting new types](https://github.com/broofa/node-mime/wiki/Requesting-New-Types).\n\n### mime.define()\n\nAdd custom mime/extension mappings\n\n    mime.define({\n        'text/x-some-format': ['x-sf', 'x-sft', 'x-sfml'],\n        'application/x-my-type': ['x-mt', 'x-mtt'],\n        // etc ...\n    });\n\n    mime.lookup('x-sft');                 // => 'text/x-some-format'\n\nThe first entry in the extensions array is returned by `mime.extension()`. E.g.\n\n    mime.extension('text/x-some-format'); // => 'x-sf'\n\n### mime.load(filepath)\n\nLoad mappings from an Apache \".types\" format file\n\n    mime.load('./my_project.types');\n\nThe .types file format is simple -  See the `types` dir for examples.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/broofa/node-mime/issues"
+  },
+  "homepage": "https://github.com/broofa/node-mime",
+  "_id": "mime@1.2.11",
+  "_from": "mime@~1.2.9"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/mime/test.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/mime/test.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/mime/test.js	(revision 484)
@@ -0,0 +1,84 @@
+/**
+ * Usage: node test.js
+ */
+
+var mime = require('./mime');
+var assert = require('assert');
+var path = require('path');
+
+function eq(a, b) {
+  console.log('Test: ' + a + ' === ' + b);
+  assert.strictEqual.apply(null, arguments);
+}
+
+console.log(Object.keys(mime.extensions).length + ' types');
+console.log(Object.keys(mime.types).length + ' extensions\n');
+
+//
+// Test mime lookups
+//
+
+eq('text/plain', mime.lookup('text.txt'));     // normal file
+eq('text/plain', mime.lookup('TEXT.TXT'));     // uppercase
+eq('text/plain', mime.lookup('dir/text.txt')); // dir + file
+eq('text/plain', mime.lookup('.text.txt'));    // hidden file
+eq('text/plain', mime.lookup('.txt'));         // nameless
+eq('text/plain', mime.lookup('txt'));          // extension-only
+eq('text/plain', mime.lookup('/txt'));         // extension-less ()
+eq('text/plain', mime.lookup('\\txt'));        // Windows, extension-less
+eq('application/octet-stream', mime.lookup('text.nope')); // unrecognized
+eq('fallback', mime.lookup('text.fallback', 'fallback')); // alternate default
+
+//
+// Test extensions
+//
+
+eq('txt', mime.extension(mime.types.text));
+eq('html', mime.extension(mime.types.htm));
+eq('bin', mime.extension('application/octet-stream'));
+eq('bin', mime.extension('application/octet-stream '));
+eq('html', mime.extension(' text/html; charset=UTF-8'));
+eq('html', mime.extension('text/html; charset=UTF-8 '));
+eq('html', mime.extension('text/html; charset=UTF-8'));
+eq('html', mime.extension('text/html ; charset=UTF-8'));
+eq('html', mime.extension('text/html;charset=UTF-8'));
+eq('html', mime.extension('text/Html;charset=UTF-8'));
+eq(undefined, mime.extension('unrecognized'));
+
+//
+// Test node.types lookups
+//
+
+eq('application/font-woff', mime.lookup('file.woff'));
+eq('application/octet-stream', mime.lookup('file.buffer'));
+eq('audio/mp4', mime.lookup('file.m4a'));
+eq('font/opentype', mime.lookup('file.otf'));
+
+//
+// Test charsets
+//
+
+eq('UTF-8', mime.charsets.lookup('text/plain'));
+eq(undefined, mime.charsets.lookup(mime.types.js));
+eq('fallback', mime.charsets.lookup('application/octet-stream', 'fallback'));
+
+//
+// Test for overlaps between mime.types and node.types
+//
+
+var apacheTypes = new mime.Mime(), nodeTypes = new mime.Mime();
+apacheTypes.load(path.join(__dirname, 'types/mime.types'));
+nodeTypes.load(path.join(__dirname, 'types/node.types'));
+
+var keys = [].concat(Object.keys(apacheTypes.types))
+             .concat(Object.keys(nodeTypes.types));
+keys.sort();
+for (var i = 1; i < keys.length; i++) {
+  if (keys[i] == keys[i-1]) {
+    console.warn('Warning: ' +
+      'node.types defines ' + keys[i] + '->' + nodeTypes.types[keys[i]] +
+      ', mime.types defines ' + keys[i] + '->' + apacheTypes.types[keys[i]]);
+  }
+}
+
+console.log('\nOK');
Index: Dev/trunk/src/node_modules/request/node_modules/mime/types/mime.types
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/mime/types/mime.types	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/mime/types/mime.types	(revision 484)
@@ -0,0 +1,1588 @@
+# This file maps Internet media types to unique file extension(s).
+# Although created for httpd, this file is used by many software systems
+# and has been placed in the public domain for unlimited redisribution.
+#
+# The table below contains both registered and (common) unregistered types.
+# A type that has no unique extension can be ignored -- they are listed
+# here to guide configurations toward known types and to make it easier to
+# identify "new" types.  File extensions are also commonly used to indicate
+# content languages and encodings, so choose them carefully.
+#
+# Internet media types should be registered as described in RFC 4288.
+# The registry is at <http://www.iana.org/assignments/media-types/>.
+#
+# MIME type (lowercased)			Extensions
+# ============================================	==========
+# application/1d-interleaved-parityfec
+# application/3gpp-ims+xml
+# application/activemessage
+application/andrew-inset			ez
+# application/applefile
+application/applixware				aw
+application/atom+xml				atom
+application/atomcat+xml				atomcat
+# application/atomicmail
+application/atomsvc+xml				atomsvc
+# application/auth-policy+xml
+# application/batch-smtp
+# application/beep+xml
+# application/calendar+xml
+# application/cals-1840
+# application/ccmp+xml
+application/ccxml+xml				ccxml
+application/cdmi-capability			cdmia
+application/cdmi-container			cdmic
+application/cdmi-domain				cdmid
+application/cdmi-object				cdmio
+application/cdmi-queue				cdmiq
+# application/cea-2018+xml
+# application/cellml+xml
+# application/cfw
+# application/cnrp+xml
+# application/commonground
+# application/conference-info+xml
+# application/cpl+xml
+# application/csta+xml
+# application/cstadata+xml
+application/cu-seeme				cu
+# application/cybercash
+application/davmount+xml			davmount
+# application/dca-rft
+# application/dec-dx
+# application/dialog-info+xml
+# application/dicom
+# application/dns
+application/docbook+xml				dbk
+# application/dskpp+xml
+application/dssc+der				dssc
+application/dssc+xml				xdssc
+# application/dvcs
+application/ecmascript				ecma
+# application/edi-consent
+# application/edi-x12
+# application/edifact
+application/emma+xml				emma
+# application/epp+xml
+application/epub+zip				epub
+# application/eshop
+# application/example
+application/exi					exi
+# application/fastinfoset
+# application/fastsoap
+# application/fits
+application/font-tdpfr				pfr
+# application/framework-attributes+xml
+application/gml+xml				gml
+application/gpx+xml				gpx
+application/gxf					gxf
+# 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/inkml+xml				ink inkml
+# 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/jsonml+json				jsonml
+# application/kpml-request+xml
+# application/kpml-response+xml
+application/lost+xml				lostxml
+application/mac-binhex40			hqx
+application/mac-compactpro			cpt
+# application/macwriteii
+application/mads+xml				mads
+application/marc				mrc
+application/marcxml+xml				mrcx
+application/mathematica				ma nb mb
+# application/mathml-content+xml
+# application/mathml-presentation+xml
+application/mathml+xml				mathml
+# application/mbms-associated-procedure-description+xml
+# application/mbms-deregister+xml
+# application/mbms-envelope+xml
+# application/mbms-msk+xml
+# application/mbms-msk-response+xml
+# application/mbms-protection-description+xml
+# application/mbms-reception-report+xml
+# application/mbms-register+xml
+# application/mbms-register-response+xml
+# application/mbms-user-service-description+xml
+application/mbox				mbox
+# application/media_control+xml
+application/mediaservercontrol+xml		mscml
+application/metalink+xml			metalink
+application/metalink4+xml			meta4
+application/mets+xml				mets
+# application/mikey
+application/mods+xml				mods
+# application/moss-keys
+# application/moss-signature
+# application/mosskey-data
+# application/mosskey-request
+application/mp21				m21 mp21
+application/mp4					mp4s
+# application/mpeg4-generic
+# application/mpeg4-iod
+# application/mpeg4-iod-xmt
+# application/msc-ivr+xml
+# application/msc-mixer+xml
+application/msword				doc dot
+application/mxf					mxf
+# application/nasdata
+# application/news-checkgroups
+# application/news-groupinfo
+# application/news-transmission
+# application/nss
+# application/ocsp-request
+# application/ocsp-response
+application/octet-stream	bin dms lrf mar so dist distz pkg bpk dump elc deploy
+application/oda					oda
+application/oebps-package+xml			opf
+application/ogg					ogx
+application/omdoc+xml				omdoc
+application/onenote				onetoc onetoc2 onetmp onepkg
+application/oxps				oxps
+# application/parityfec
+application/patch-ops-error+xml			xer
+application/pdf					pdf
+application/pgp-encrypted			pgp
+# application/pgp-keys
+application/pgp-signature			asc sig
+application/pics-rules				prf
+# application/pidf+xml
+# application/pidf-diff+xml
+application/pkcs10				p10
+application/pkcs7-mime				p7m p7c
+application/pkcs7-signature			p7s
+application/pkcs8				p8
+application/pkix-attr-cert			ac
+application/pkix-cert				cer
+application/pkix-crl				crl
+application/pkix-pkipath			pkipath
+application/pkixcmp				pki
+application/pls+xml				pls
+# application/poc-settings+xml
+application/postscript				ai eps ps
+# application/prs.alvestrand.titrax-sheet
+application/prs.cww				cww
+# application/prs.nprend
+# application/prs.plucker
+# application/prs.rdf-xml-crypt
+# application/prs.xsf+xml
+application/pskc+xml				pskcxml
+# application/qsig
+application/rdf+xml				rdf
+application/reginfo+xml				rif
+application/relax-ng-compact-syntax		rnc
+# application/remote-printing
+application/resource-lists+xml			rl
+application/resource-lists-diff+xml		rld
+# application/riscos
+# application/rlmi+xml
+application/rls-services+xml			rs
+application/rpki-ghostbusters			gbr
+application/rpki-manifest			mft
+application/rpki-roa				roa
+# application/rpki-updown
+application/rsd+xml				rsd
+application/rss+xml				rss
+application/rtf					rtf
+# application/rtx
+# application/samlassertion+xml
+# application/samlmetadata+xml
+application/sbml+xml				sbml
+application/scvp-cv-request			scq
+application/scvp-cv-response			scs
+application/scvp-vp-request			spq
+application/scvp-vp-response			spp
+application/sdp					sdp
+# application/set-payment
+application/set-payment-initiation		setpay
+# application/set-registration
+application/set-registration-initiation		setreg
+# application/sgml
+# application/sgml-open-catalog
+application/shf+xml				shf
+# application/sieve
+# application/simple-filter+xml
+# application/simple-message-summary
+# application/simplesymbolcontainer
+# application/slate
+# application/smil
+application/smil+xml				smi smil
+# application/soap+fastinfoset
+# application/soap+xml
+application/sparql-query			rq
+application/sparql-results+xml			srx
+# application/spirits-event+xml
+application/srgs				gram
+application/srgs+xml				grxml
+application/sru+xml				sru
+application/ssdl+xml				ssdl
+application/ssml+xml				ssml
+# application/tamp-apex-update
+# application/tamp-apex-update-confirm
+# application/tamp-community-update
+# application/tamp-community-update-confirm
+# application/tamp-error
+# application/tamp-sequence-adjust
+# application/tamp-sequence-adjust-confirm
+# application/tamp-status-query
+# application/tamp-status-response
+# application/tamp-update
+# application/tamp-update-confirm
+application/tei+xml				tei teicorpus
+application/thraud+xml				tfi
+# application/timestamp-query
+# application/timestamp-reply
+application/timestamped-data			tsd
+# application/tve-trigger
+# application/ulpfec
+# application/vcard+xml
+# 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.formscentral.fcdt		fcdt
+application/vnd.adobe.fxp			fxp fxpl
+# application/vnd.adobe.partial-upload
+application/vnd.adobe.xdp+xml			xdp
+application/vnd.adobe.xfdf			xfdf
+# application/vnd.aether.imp
+# application/vnd.ah-barcode
+application/vnd.ahead.space			ahead
+application/vnd.airzip.filesecure.azf		azf
+application/vnd.airzip.filesecure.azs		azs
+application/vnd.amazon.ebook			azw
+application/vnd.americandynamics.acc		acc
+application/vnd.amiga.ami			ami
+# application/vnd.amundsen.maze+xml
+application/vnd.android.package-archive		apk
+application/vnd.anser-web-certificate-issue-initiation	cii
+application/vnd.anser-web-funds-transfer-initiation	fti
+application/vnd.antix.game-component		atx
+application/vnd.apple.installer+xml		mpkg
+application/vnd.apple.mpegurl			m3u8
+# application/vnd.arastra.swi
+application/vnd.aristanetworks.swi		swi
+application/vnd.astraea-software.iota		iota
+application/vnd.audiograph			aep
+# application/vnd.autopackage
+# application/vnd.avistar+xml
+application/vnd.blueice.multipass		mpm
+# application/vnd.bluetooth.ep.oob
+application/vnd.bmi				bmi
+application/vnd.businessobjects			rep
+# application/vnd.cab-jscript
+# application/vnd.canon-cpdl
+# application/vnd.canon-lips
+# application/vnd.cendio.thinlinc.clientconf
+application/vnd.chemdraw+xml			cdxml
+application/vnd.chipnuts.karaoke-mmd		mmd
+application/vnd.cinderella			cdy
+# application/vnd.cirpack.isdn-ext
+application/vnd.claymore			cla
+application/vnd.cloanto.rp9			rp9
+application/vnd.clonk.c4group			c4g c4d c4f c4p c4u
+application/vnd.cluetrust.cartomobile-config		c11amc
+application/vnd.cluetrust.cartomobile-config-pkg	c11amz
+# application/vnd.collection+json
+# 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
+application/vnd.curl.car			car
+application/vnd.curl.pcurl			pcurl
+# application/vnd.cybank
+application/vnd.dart				dart
+application/vnd.data-vision.rdz			rdz
+application/vnd.dece.data			uvf uvvf uvd uvvd
+application/vnd.dece.ttml+xml			uvt uvvt
+application/vnd.dece.unspecified		uvx uvvx
+application/vnd.dece.zip			uvz uvvz
+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.ds-keypoint			kpxx
+application/vnd.dvb.ait				ait
+# application/vnd.dvb.dvbj
+# application/vnd.dvb.esgcontainer
+# application/vnd.dvb.ipdcdftnotifaccess
+# application/vnd.dvb.ipdcesgaccess
+# application/vnd.dvb.ipdcesgaccess2
+# application/vnd.dvb.ipdcesgpdd
+# application/vnd.dvb.ipdcroaming
+# application/vnd.dvb.iptv.alfec-base
+# application/vnd.dvb.iptv.alfec-enhancement
+# application/vnd.dvb.notif-aggregate-root+xml
+# application/vnd.dvb.notif-container+xml
+# application/vnd.dvb.notif-generic+xml
+# application/vnd.dvb.notif-ia-msglist+xml
+# application/vnd.dvb.notif-ia-registration-request+xml
+# application/vnd.dvb.notif-ia-registration-response+xml
+# application/vnd.dvb.notif-init+xml
+# application/vnd.dvb.pfr
+application/vnd.dvb.service			svc
+# application/vnd.dxr
+application/vnd.dynageo				geo
+# application/vnd.easykaraoke.cdgdownload
+# application/vnd.ecdis-update
+application/vnd.ecowin.chart			mag
+# application/vnd.ecowin.filerequest
+# application/vnd.ecowin.fileupdate
+# application/vnd.ecowin.series
+# application/vnd.ecowin.seriesrequest
+# application/vnd.ecowin.seriesupdate
+# application/vnd.emclient.accessrequest+xml
+application/vnd.enliven				nml
+# application/vnd.eprints.data+xml
+application/vnd.epson.esf			esf
+application/vnd.epson.msf			msf
+application/vnd.epson.quickanime		qam
+application/vnd.epson.salt			slt
+application/vnd.epson.ssf			ssf
+# application/vnd.ericsson.quickcall
+application/vnd.eszigno3+xml			es3 et3
+# application/vnd.etsi.aoc+xml
+# application/vnd.etsi.cug+xml
+# application/vnd.etsi.iptvcommand+xml
+# application/vnd.etsi.iptvdiscovery+xml
+# application/vnd.etsi.iptvprofile+xml
+# application/vnd.etsi.iptvsad-bc+xml
+# application/vnd.etsi.iptvsad-cod+xml
+# application/vnd.etsi.iptvsad-npvr+xml
+# application/vnd.etsi.iptvservice+xml
+# application/vnd.etsi.iptvsync+xml
+# application/vnd.etsi.iptvueprofile+xml
+# application/vnd.etsi.mcid+xml
+# application/vnd.etsi.overload-control-policy-dataset+xml
+# application/vnd.etsi.sci+xml
+# application/vnd.etsi.simservs+xml
+# application/vnd.etsi.tsl+xml
+# application/vnd.etsi.tsl.der
+# application/vnd.eudora.data
+application/vnd.ezpix-album			ez2
+application/vnd.ezpix-package			ez3
+# application/vnd.f-secure.mobile
+application/vnd.fdf				fdf
+application/vnd.fdsn.mseed			mseed
+application/vnd.fdsn.seed			seed dataless
+# application/vnd.ffsns
+# application/vnd.fints
+application/vnd.flographit			gph
+application/vnd.fluxtime.clip			ftc
+# application/vnd.font-fontforge-sfd
+application/vnd.framemaker			fm frame maker book
+application/vnd.frogans.fnc			fnc
+application/vnd.frogans.ltf			ltf
+application/vnd.fsc.weblaunch			fsc
+application/vnd.fujitsu.oasys			oas
+application/vnd.fujitsu.oasys2			oa2
+application/vnd.fujitsu.oasys3			oa3
+application/vnd.fujitsu.oasysgp			fg5
+application/vnd.fujitsu.oasysprs		bh2
+# application/vnd.fujixerox.art-ex
+# application/vnd.fujixerox.art4
+# application/vnd.fujixerox.hbpl
+application/vnd.fujixerox.ddd			ddd
+application/vnd.fujixerox.docuworks		xdw
+application/vnd.fujixerox.docuworks.binder	xbd
+# application/vnd.fut-misnet
+application/vnd.fuzzysheet			fzs
+application/vnd.genomatix.tuxedo		txd
+# application/vnd.geocube+xml
+application/vnd.geogebra.file			ggb
+application/vnd.geogebra.tool			ggt
+application/vnd.geometry-explorer		gex gre
+application/vnd.geonext				gxt
+application/vnd.geoplan				g2w
+application/vnd.geospace			g3w
+# application/vnd.globalplatform.card-content-mgt
+# application/vnd.globalplatform.card-content-mgt-response
+application/vnd.gmx				gmx
+application/vnd.google-earth.kml+xml		kml
+application/vnd.google-earth.kmz		kmz
+application/vnd.grafeq				gqf gqs
+# application/vnd.gridmp
+application/vnd.groove-account			gac
+application/vnd.groove-help			ghf
+application/vnd.groove-identity-message		gim
+application/vnd.groove-injector			grv
+application/vnd.groove-tool-message		gtm
+application/vnd.groove-tool-template		tpl
+application/vnd.groove-vcard			vcg
+# application/vnd.hal+json
+application/vnd.hal+xml				hal
+application/vnd.handheld-entertainment+xml	zmm
+application/vnd.hbci				hbci
+# application/vnd.hcl-bireports
+application/vnd.hhe.lesson-player		les
+application/vnd.hp-hpgl				hpgl
+application/vnd.hp-hpid				hpid
+application/vnd.hp-hps				hps
+application/vnd.hp-jlyt				jlt
+application/vnd.hp-pcl				pcl
+application/vnd.hp-pclxl			pclxl
+# application/vnd.httphone
+application/vnd.hydrostatix.sof-data		sfd-hdstx
+# application/vnd.hzn-3d-crossword
+# application/vnd.ibm.afplinedata
+# application/vnd.ibm.electronic-media
+application/vnd.ibm.minipay			mpy
+application/vnd.ibm.modcap			afp listafp list3820
+application/vnd.ibm.rights-management		irm
+application/vnd.ibm.secure-container		sc
+application/vnd.iccprofile			icc icm
+application/vnd.igloader			igl
+application/vnd.immervision-ivp			ivp
+application/vnd.immervision-ivu			ivu
+# application/vnd.informedcontrol.rms+xml
+# application/vnd.informix-visionary
+# application/vnd.infotech.project
+# application/vnd.infotech.project+xml
+# application/vnd.innopath.wamp.notification
+application/vnd.insors.igm			igm
+application/vnd.intercon.formnet		xpw xpx
+application/vnd.intergeo			i2g
+# application/vnd.intertrust.digibox
+# application/vnd.intertrust.nncp
+application/vnd.intu.qbo			qbo
+application/vnd.intu.qfx			qfx
+# application/vnd.iptc.g2.conceptitem+xml
+# application/vnd.iptc.g2.knowledgeitem+xml
+# application/vnd.iptc.g2.newsitem+xml
+# application/vnd.iptc.g2.newsmessage+xml
+# application/vnd.iptc.g2.packageitem+xml
+# application/vnd.iptc.g2.planningitem+xml
+application/vnd.ipunplugged.rcprofile		rcprofile
+application/vnd.irepository.package+xml		irp
+application/vnd.is-xpr				xpr
+application/vnd.isac.fcs			fcs
+application/vnd.jam				jam
+# application/vnd.japannet-directory-service
+# application/vnd.japannet-jpnstore-wakeup
+# application/vnd.japannet-payment-wakeup
+# application/vnd.japannet-registration
+# application/vnd.japannet-registration-wakeup
+# application/vnd.japannet-setstore-wakeup
+# application/vnd.japannet-verification
+# application/vnd.japannet-verification-wakeup
+application/vnd.jcp.javame.midlet-rms		rms
+application/vnd.jisp				jisp
+application/vnd.joost.joda-archive		joda
+application/vnd.kahootz				ktz ktr
+application/vnd.kde.karbon			karbon
+application/vnd.kde.kchart			chrt
+application/vnd.kde.kformula			kfo
+application/vnd.kde.kivio			flw
+application/vnd.kde.kontour			kon
+application/vnd.kde.kpresenter			kpr kpt
+application/vnd.kde.kspread			ksp
+application/vnd.kde.kword			kwd kwt
+application/vnd.kenameaapp			htke
+application/vnd.kidspiration			kia
+application/vnd.kinar				kne knp
+application/vnd.koan				skp skd skt skm
+application/vnd.kodak-descriptor		sse
+application/vnd.las.las+xml			lasxml
+# application/vnd.liberty-request+xml
+application/vnd.llamagraphics.life-balance.desktop	lbd
+application/vnd.llamagraphics.life-balance.exchange+xml	lbe
+application/vnd.lotus-1-2-3			123
+application/vnd.lotus-approach			apr
+application/vnd.lotus-freelance			pre
+application/vnd.lotus-notes			nsf
+application/vnd.lotus-organizer			org
+application/vnd.lotus-screencam			scm
+application/vnd.lotus-wordpro			lwp
+application/vnd.macports.portpkg		portpkg
+# application/vnd.marlin.drm.actiontoken+xml
+# application/vnd.marlin.drm.conftoken+xml
+# application/vnd.marlin.drm.license+xml
+# application/vnd.marlin.drm.mdcf
+application/vnd.mcd				mcd
+application/vnd.medcalcdata			mc1
+application/vnd.mediastation.cdkey		cdkey
+# application/vnd.meridian-slingshot
+application/vnd.mfer				mwf
+application/vnd.mfmp				mfm
+application/vnd.micrografx.flo			flo
+application/vnd.micrografx.igx			igx
+application/vnd.mif				mif
+# application/vnd.minisoft-hp3000-save
+# application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf			daf
+application/vnd.mobius.dis			dis
+application/vnd.mobius.mbk			mbk
+application/vnd.mobius.mqy			mqy
+application/vnd.mobius.msl			msl
+application/vnd.mobius.plc			plc
+application/vnd.mobius.txf			txf
+application/vnd.mophun.application		mpn
+application/vnd.mophun.certificate		mpc
+# application/vnd.motorola.flexsuite
+# application/vnd.motorola.flexsuite.adsi
+# application/vnd.motorola.flexsuite.fis
+# application/vnd.motorola.flexsuite.gotap
+# application/vnd.motorola.flexsuite.kmr
+# application/vnd.motorola.flexsuite.ttc
+# application/vnd.motorola.flexsuite.wem
+# application/vnd.motorola.iprm
+application/vnd.mozilla.xul+xml			xul
+application/vnd.ms-artgalry			cil
+# application/vnd.ms-asf
+application/vnd.ms-cab-compressed		cab
+# application/vnd.ms-color.iccprofile
+application/vnd.ms-excel			xls xlm xla xlc xlt xlw
+application/vnd.ms-excel.addin.macroenabled.12		xlam
+application/vnd.ms-excel.sheet.binary.macroenabled.12	xlsb
+application/vnd.ms-excel.sheet.macroenabled.12		xlsm
+application/vnd.ms-excel.template.macroenabled.12	xltm
+application/vnd.ms-fontobject			eot
+application/vnd.ms-htmlhelp			chm
+application/vnd.ms-ims				ims
+application/vnd.ms-lrm				lrm
+# application/vnd.ms-office.activex+xml
+application/vnd.ms-officetheme			thmx
+# application/vnd.ms-opentype
+# application/vnd.ms-package.obfuscated-opentype
+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-printing.printticket+xml
+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.mynfc				taglet
+# application/vnd.ncd.control
+# application/vnd.ncd.reference
+# application/vnd.nervana
+# application/vnd.netfpx
+application/vnd.neurolanguage.nlu		nlu
+application/vnd.nitf				ntf nitf
+application/vnd.noblenet-directory		nnd
+application/vnd.noblenet-sealer			nns
+application/vnd.noblenet-web			nnw
+# application/vnd.nokia.catalogs
+# application/vnd.nokia.conml+wbxml
+# application/vnd.nokia.conml+xml
+# application/vnd.nokia.isds-radio-presets
+# application/vnd.nokia.iptv.config+xml
+# application/vnd.nokia.landmark+wbxml
+# application/vnd.nokia.landmark+xml
+# application/vnd.nokia.landmarkcollection+xml
+# application/vnd.nokia.n-gage.ac+xml
+application/vnd.nokia.n-gage.data		ngdat
+application/vnd.nokia.n-gage.symbian.install	n-gage
+# application/vnd.nokia.ncd
+# application/vnd.nokia.pcd+wbxml
+# application/vnd.nokia.pcd+xml
+application/vnd.nokia.radio-preset		rpst
+application/vnd.nokia.radio-presets		rpss
+application/vnd.novadigm.edm			edm
+application/vnd.novadigm.edx			edx
+application/vnd.novadigm.ext			ext
+# application/vnd.ntt-local.file-transfer
+# application/vnd.ntt-local.sip-ta_remote
+# application/vnd.ntt-local.sip-ta_tcp_stream
+application/vnd.oasis.opendocument.chart		odc
+application/vnd.oasis.opendocument.chart-template	otc
+application/vnd.oasis.opendocument.database		odb
+application/vnd.oasis.opendocument.formula		odf
+application/vnd.oasis.opendocument.formula-template	odft
+application/vnd.oasis.opendocument.graphics		odg
+application/vnd.oasis.opendocument.graphics-template	otg
+application/vnd.oasis.opendocument.image		odi
+application/vnd.oasis.opendocument.image-template	oti
+application/vnd.oasis.opendocument.presentation		odp
+application/vnd.oasis.opendocument.presentation-template	otp
+application/vnd.oasis.opendocument.spreadsheet		ods
+application/vnd.oasis.opendocument.spreadsheet-template	ots
+application/vnd.oasis.opendocument.text			odt
+application/vnd.oasis.opendocument.text-master		odm
+application/vnd.oasis.opendocument.text-template	ott
+application/vnd.oasis.opendocument.text-web		oth
+# application/vnd.obn
+# application/vnd.oftn.l10n+json
+# application/vnd.oipf.contentaccessdownload+xml
+# application/vnd.oipf.contentaccessstreaming+xml
+# application/vnd.oipf.cspg-hexbinary
+# application/vnd.oipf.dae.svg+xml
+# application/vnd.oipf.dae.xhtml+xml
+# application/vnd.oipf.mippvcontrolmessage+xml
+# application/vnd.oipf.pae.gem
+# application/vnd.oipf.spdiscovery+xml
+# application/vnd.oipf.spdlist+xml
+# application/vnd.oipf.ueprofile+xml
+# application/vnd.oipf.userprofile+xml
+application/vnd.olpc-sugar			xo
+# application/vnd.oma-scws-config
+# application/vnd.oma-scws-http-request
+# application/vnd.oma-scws-http-response
+# application/vnd.oma.bcast.associated-procedure-parameter+xml
+# application/vnd.oma.bcast.drm-trigger+xml
+# application/vnd.oma.bcast.imd+xml
+# application/vnd.oma.bcast.ltkm
+# application/vnd.oma.bcast.notification+xml
+# application/vnd.oma.bcast.provisioningtrigger
+# application/vnd.oma.bcast.sgboot
+# application/vnd.oma.bcast.sgdd+xml
+# application/vnd.oma.bcast.sgdu
+# application/vnd.oma.bcast.simple-symbol-container
+# application/vnd.oma.bcast.smartcard-trigger+xml
+# application/vnd.oma.bcast.sprov+xml
+# application/vnd.oma.bcast.stkm
+# application/vnd.oma.cab-address-book+xml
+# application/vnd.oma.cab-feature-handler+xml
+# application/vnd.oma.cab-pcc+xml
+# application/vnd.oma.cab-user-prefs+xml
+# application/vnd.oma.dcd
+# application/vnd.oma.dcdc
+application/vnd.oma.dd2+xml			dd2
+# application/vnd.oma.drm.risd+xml
+# application/vnd.oma.group-usage-list+xml
+# application/vnd.oma.pal+xml
+# application/vnd.oma.poc.detailed-progress-report+xml
+# application/vnd.oma.poc.final-report+xml
+# application/vnd.oma.poc.groups+xml
+# application/vnd.oma.poc.invocation-descriptor+xml
+# application/vnd.oma.poc.optimized-progress-report+xml
+# application/vnd.oma.push
+# application/vnd.oma.scidm.messages+xml
+# application/vnd.oma.xcap-directory+xml
+# application/vnd.omads-email+xml
+# application/vnd.omads-file+xml
+# application/vnd.omads-folder+xml
+# application/vnd.omaloc-supl-init
+application/vnd.openofficeorg.extension		oxt
+# application/vnd.openxmlformats-officedocument.custom-properties+xml
+# application/vnd.openxmlformats-officedocument.customxmlproperties+xml
+# application/vnd.openxmlformats-officedocument.drawing+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chart+xml
+# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml
+# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml
+# application/vnd.openxmlformats-officedocument.extended-properties+xml
+# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml
+# application/vnd.openxmlformats-officedocument.presentationml.comments+xml
+# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml
+# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml
+application/vnd.openxmlformats-officedocument.presentationml.presentation	pptx
+# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml
+application/vnd.openxmlformats-officedocument.presentationml.slide	sldx
+# application/vnd.openxmlformats-officedocument.presentationml.slide+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml
+application/vnd.openxmlformats-officedocument.presentationml.slideshow	ppsx
+# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml
+# application/vnd.openxmlformats-officedocument.presentationml.tags+xml
+application/vnd.openxmlformats-officedocument.presentationml.template	potx
+# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml
+# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet	xlsx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml
+application/vnd.openxmlformats-officedocument.spreadsheetml.template	xltx
+# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml
+# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
+# application/vnd.openxmlformats-officedocument.theme+xml
+# application/vnd.openxmlformats-officedocument.themeoverride+xml
+# application/vnd.openxmlformats-officedocument.vmldrawing
+# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.document	docx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml
+application/vnd.openxmlformats-officedocument.wordprocessingml.template	dotx
+# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml
+# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml
+# application/vnd.openxmlformats-package.core-properties+xml
+# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml
+# application/vnd.openxmlformats-package.relationships+xml
+# application/vnd.quobject-quoxdocument
+# application/vnd.osa.netdeploy
+application/vnd.osgeo.mapguide.package		mgp
+# application/vnd.osgi.bundle
+application/vnd.osgi.dp				dp
+application/vnd.osgi.subsystem			esa
+# application/vnd.otps.ct-kip+xml
+application/vnd.palm				pdb pqa oprc
+# application/vnd.paos.xml
+application/vnd.pawaafile			paw
+application/vnd.pg.format			str
+application/vnd.pg.osasli			ei6
+# application/vnd.piaccess.application-licence
+application/vnd.picsel				efif
+application/vnd.pmi.widget			wg
+# application/vnd.poc.group-advertisement+xml
+application/vnd.pocketlearn			plf
+application/vnd.powerbuilder6			pbd
+# application/vnd.powerbuilder6-s
+# application/vnd.powerbuilder7
+# application/vnd.powerbuilder7-s
+# application/vnd.powerbuilder75
+# application/vnd.powerbuilder75-s
+# application/vnd.preminet
+application/vnd.previewsystems.box		box
+application/vnd.proteus.magazine		mgz
+application/vnd.publishare-delta-tree		qps
+application/vnd.pvi.ptid1			ptid
+# application/vnd.pwg-multiplexed
+# application/vnd.pwg-xhtml-print+xml
+# application/vnd.qualcomm.brew-app-res
+application/vnd.quark.quarkxpress		qxd qxt qwd qwt qxl qxb
+# application/vnd.radisys.moml+xml
+# application/vnd.radisys.msml+xml
+# application/vnd.radisys.msml-audit+xml
+# application/vnd.radisys.msml-audit-conf+xml
+# application/vnd.radisys.msml-audit-conn+xml
+# application/vnd.radisys.msml-audit-dialog+xml
+# application/vnd.radisys.msml-audit-stream+xml
+# application/vnd.radisys.msml-conf+xml
+# application/vnd.radisys.msml-dialog+xml
+# application/vnd.radisys.msml-dialog-base+xml
+# application/vnd.radisys.msml-dialog-fax-detect+xml
+# application/vnd.radisys.msml-dialog-fax-sendrecv+xml
+# application/vnd.radisys.msml-dialog-group+xml
+# application/vnd.radisys.msml-dialog-speech+xml
+# application/vnd.radisys.msml-dialog-transform+xml
+# application/vnd.rainstor.data
+# application/vnd.rapid
+application/vnd.realvnc.bed			bed
+application/vnd.recordare.musicxml		mxl
+application/vnd.recordare.musicxml+xml		musicxml
+# application/vnd.renlearn.rlprint
+application/vnd.rig.cryptonote			cryptonote
+application/vnd.rim.cod				cod
+application/vnd.rn-realmedia			rm
+application/vnd.rn-realmedia-vbr		rmvb
+application/vnd.route66.link66+xml		link66
+# application/vnd.rs-274x
+# application/vnd.ruckus.download
+# application/vnd.s3sms
+application/vnd.sailingtracker.track		st
+# application/vnd.sbm.cid
+# application/vnd.sbm.mid2
+# application/vnd.scribus
+# application/vnd.sealed.3df
+# application/vnd.sealed.csf
+# application/vnd.sealed.doc
+# application/vnd.sealed.eml
+# application/vnd.sealed.mht
+# application/vnd.sealed.net
+# application/vnd.sealed.ppt
+# application/vnd.sealed.tiff
+# application/vnd.sealed.xls
+# application/vnd.sealedmedia.softseal.html
+# application/vnd.sealedmedia.softseal.pdf
+application/vnd.seemail				see
+application/vnd.sema				sema
+application/vnd.semd				semd
+application/vnd.semf				semf
+application/vnd.shana.informed.formdata		ifm
+application/vnd.shana.informed.formtemplate	itp
+application/vnd.shana.informed.interchange	iif
+application/vnd.shana.informed.package		ipk
+application/vnd.simtech-mindmapper		twd twds
+application/vnd.smaf				mmf
+# application/vnd.smart.notebook
+application/vnd.smart.teacher			teacher
+# application/vnd.software602.filler.form+xml
+# application/vnd.software602.filler.form-xml-zip
+application/vnd.solent.sdkm+xml			sdkm sdkd
+application/vnd.spotfire.dxp			dxp
+application/vnd.spotfire.sfs			sfs
+# application/vnd.sss-cod
+# application/vnd.sss-dtf
+# application/vnd.sss-ntf
+application/vnd.stardivision.calc		sdc
+application/vnd.stardivision.draw		sda
+application/vnd.stardivision.impress		sdd
+application/vnd.stardivision.math		smf
+application/vnd.stardivision.writer		sdw vor
+application/vnd.stardivision.writer-global	sgl
+application/vnd.stepmania.package		smzip
+application/vnd.stepmania.stepchart		sm
+# application/vnd.street-stream
+application/vnd.sun.xml.calc			sxc
+application/vnd.sun.xml.calc.template		stc
+application/vnd.sun.xml.draw			sxd
+application/vnd.sun.xml.draw.template		std
+application/vnd.sun.xml.impress			sxi
+application/vnd.sun.xml.impress.template	sti
+application/vnd.sun.xml.math			sxm
+application/vnd.sun.xml.writer			sxw
+application/vnd.sun.xml.writer.global		sxg
+application/vnd.sun.xml.writer.template		stw
+# application/vnd.sun.wadl+xml
+application/vnd.sus-calendar			sus susp
+application/vnd.svd				svd
+# application/vnd.swiftview-ics
+application/vnd.symbian.install			sis sisx
+application/vnd.syncml+xml			xsm
+application/vnd.syncml.dm+wbxml			bdm
+application/vnd.syncml.dm+xml			xdm
+# application/vnd.syncml.dm.notification
+# application/vnd.syncml.ds.notification
+application/vnd.tao.intent-module-archive	tao
+application/vnd.tcpdump.pcap			pcap cap dmp
+application/vnd.tmobile-livetv			tmo
+application/vnd.trid.tpt			tpt
+application/vnd.triscape.mxs			mxs
+application/vnd.trueapp				tra
+# application/vnd.truedoc
+# application/vnd.ubisoft.webplayer
+application/vnd.ufdl				ufd ufdl
+application/vnd.uiq.theme			utz
+application/vnd.umajin				umj
+application/vnd.unity				unityweb
+application/vnd.uoml+xml			uoml
+# application/vnd.uplanet.alert
+# application/vnd.uplanet.alert-wbxml
+# application/vnd.uplanet.bearer-choice
+# application/vnd.uplanet.bearer-choice-wbxml
+# application/vnd.uplanet.cacheop
+# application/vnd.uplanet.cacheop-wbxml
+# application/vnd.uplanet.channel
+# application/vnd.uplanet.channel-wbxml
+# application/vnd.uplanet.list
+# application/vnd.uplanet.list-wbxml
+# application/vnd.uplanet.listcmd
+# application/vnd.uplanet.listcmd-wbxml
+# application/vnd.uplanet.signal
+application/vnd.vcx				vcx
+# application/vnd.vd-study
+# application/vnd.vectorworks
+# application/vnd.verimatrix.vcas
+# application/vnd.vidsoft.vidconference
+application/vnd.visio				vsd vst vss vsw
+application/vnd.visionary			vis
+# application/vnd.vividence.scriptfile
+application/vnd.vsf				vsf
+# application/vnd.wap.sic
+# application/vnd.wap.slc
+application/vnd.wap.wbxml			wbxml
+application/vnd.wap.wmlc			wmlc
+application/vnd.wap.wmlscriptc			wmlsc
+application/vnd.webturbo			wtb
+# application/vnd.wfa.wsc
+# application/vnd.wmc
+# application/vnd.wmf.bootstrap
+# application/vnd.wolfram.mathematica
+# application/vnd.wolfram.mathematica.package
+application/vnd.wolfram.player			nbp
+application/vnd.wordperfect			wpd
+application/vnd.wqd				wqd
+# application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf				stf
+# application/vnd.wv.csp+wbxml
+# application/vnd.wv.csp+xml
+# application/vnd.wv.ssp+xml
+application/vnd.xara				xar
+application/vnd.xfdl				xfdl
+# application/vnd.xfdl.webform
+# application/vnd.xmi+xml
+# application/vnd.xmpie.cpkg
+# application/vnd.xmpie.dpkg
+# application/vnd.xmpie.plan
+# application/vnd.xmpie.ppkg
+# application/vnd.xmpie.xlim
+application/vnd.yamaha.hv-dic			hvd
+application/vnd.yamaha.hv-script		hvs
+application/vnd.yamaha.hv-voice			hvp
+application/vnd.yamaha.openscoreformat			osf
+application/vnd.yamaha.openscoreformat.osfpvg+xml	osfpvg
+# application/vnd.yamaha.remote-setup
+application/vnd.yamaha.smaf-audio		saf
+application/vnd.yamaha.smaf-phrase		spf
+# application/vnd.yamaha.through-ngn
+# application/vnd.yamaha.tunnel-udpencap
+application/vnd.yellowriver-custom-menu		cmp
+application/vnd.zul				zir zirz
+application/vnd.zzazz.deck+xml			zaz
+application/voicexml+xml			vxml
+# application/vq-rtcpxr
+# application/watcherinfo+xml
+# application/whoispp-query
+# application/whoispp-response
+application/widget				wgt
+application/winhlp				hlp
+# application/wita
+# application/wordperfect5.1
+application/wsdl+xml				wsdl
+application/wspolicy+xml			wspolicy
+application/x-7z-compressed			7z
+application/x-abiword				abw
+application/x-ace-compressed			ace
+# application/x-amf
+application/x-apple-diskimage			dmg
+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-blorb				blb blorb
+application/x-bzip				bz
+application/x-bzip2				bz2 boz
+application/x-cbr				cbr cba cbt cbz cb7
+application/x-cdlink				vcd
+application/x-cfs-compressed			cfs
+application/x-chat				chat
+application/x-chess-pgn				pgn
+application/x-conference			nsc
+# application/x-compress
+application/x-cpio				cpio
+application/x-csh				csh
+application/x-debian-package			deb udeb
+application/x-dgc-compressed			dgc
+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-envoy				evy
+application/x-eva				eva
+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/font-woff				woff
+# application/x-font-vfont
+application/x-freearc				arc
+application/x-futuresplash			spl
+application/x-gca-compressed			gca
+application/x-glulx				ulx
+application/x-gnumeric				gnumeric
+application/x-gramps-xml			gramps
+application/x-gtar				gtar
+# application/x-gzip
+application/x-hdf				hdf
+application/x-install-instructions		install
+application/x-iso9660-image			iso
+application/x-java-jnlp-file			jnlp
+application/x-latex				latex
+application/x-lzh-compressed			lzh lha
+application/x-mie				mie
+application/x-mobipocket-ebook			prc mobi
+application/x-ms-application			application
+application/x-ms-shortcut			lnk
+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 wmz emf emz
+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-nzb				nzb
+application/x-pkcs12				p12 pfx
+application/x-pkcs7-certificates		p7b spc
+application/x-pkcs7-certreqresp			p7r
+application/x-rar-compressed			rar
+application/x-research-info-systems		ris
+application/x-sh				sh
+application/x-shar				shar
+application/x-shockwave-flash			swf
+application/x-silverlight-app			xap
+application/x-sql				sql
+application/x-stuffit				sit
+application/x-stuffitx				sitx
+application/x-subrip				srt
+application/x-sv4cpio				sv4cpio
+application/x-sv4crc				sv4crc
+application/x-t3vm-image			t3
+application/x-tads				gam
+application/x-tar				tar
+application/x-tcl				tcl
+application/x-tex				tex
+application/x-tex-tfm				tfm
+application/x-texinfo				texinfo texi
+application/x-tgif				obj
+application/x-ustar				ustar
+application/x-wais-source			src
+application/x-x509-ca-cert			der crt
+application/x-xfig				fig
+application/x-xliff+xml				xlf
+application/x-xpinstall				xpi
+application/x-xz				xz
+application/x-zmachine				z1 z2 z3 z4 z5 z6 z7 z8
+# application/x400-bp
+application/xaml+xml				xaml
+# application/xcap-att+xml
+# application/xcap-caps+xml
+application/xcap-diff+xml			xdf
+# application/xcap-el+xml
+# application/xcap-error+xml
+# application/xcap-ns+xml
+# application/xcon-conference-info-diff+xml
+# application/xcon-conference-info+xml
+application/xenc+xml				xenc
+application/xhtml+xml				xhtml xht
+# application/xhtml-voice+xml
+application/xml					xml xsl
+application/xml-dtd				dtd
+# application/xml-external-parsed-entity
+# application/xmpp+xml
+application/xop+xml				xop
+application/xproc+xml				xpl
+application/xslt+xml				xslt
+application/xspf+xml				xspf
+application/xv+xml				mxml xhvml xvml xvm
+application/yang				yang
+application/yin+xml				yin
+application/zip					zip
+# audio/1d-interleaved-parityfec
+# audio/32kadpcm
+# audio/3gpp
+# audio/3gpp2
+# audio/ac3
+audio/adpcm					adp
+# audio/amr
+# audio/amr-wb
+# audio/amr-wb+
+# audio/asc
+# audio/atrac-advanced-lossless
+# audio/atrac-x
+# audio/atrac3
+audio/basic					au snd
+# audio/bv16
+# audio/bv32
+# audio/clearmode
+# audio/cn
+# audio/dat12
+# audio/dls
+# audio/dsr-es201108
+# audio/dsr-es202050
+# audio/dsr-es202211
+# audio/dsr-es202212
+# audio/dv
+# 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/fwdred
+# audio/g719
+# audio/g722
+# audio/g7221
+# audio/g723
+# audio/g726-16
+# audio/g726-24
+# audio/g726-32
+# audio/g726-40
+# audio/g728
+# audio/g729
+# audio/g7291
+# audio/g729d
+# audio/g729e
+# audio/gsm
+# audio/gsm-efr
+# audio/gsm-hr-08
+# audio/ilbc
+# audio/ip-mr_v2.5
+# audio/isac
+# 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/musepack
+audio/ogg					oga ogg spx
+# audio/opus
+# 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/s3m					s3m
+audio/silk					sil
+# audio/smv
+# audio/smv0
+# audio/smv-qcp
+# audio/sp-midi
+# audio/speex
+# audio/t140c
+# audio/t38
+# audio/telephone-event
+# audio/tone
+# audio/uemclip
+# audio/ulpfec
+# audio/vdvi
+# audio/vmr-wb
+# audio/vnd.3gpp.iufp
+# audio/vnd.4sb
+# audio/vnd.audiokoz
+# audio/vnd.celp
+# audio/vnd.cisco.nse
+# audio/vnd.cmles.radio-events
+# audio/vnd.cns.anp1
+# audio/vnd.cns.inf1
+audio/vnd.dece.audio				uva uvva
+audio/vnd.digital-winds				eol
+# audio/vnd.dlna.adts
+# audio/vnd.dolby.heaac.1
+# audio/vnd.dolby.heaac.2
+# audio/vnd.dolby.mlp
+# audio/vnd.dolby.mps
+# audio/vnd.dolby.pl2
+# audio/vnd.dolby.pl2x
+# audio/vnd.dolby.pl2z
+# audio/vnd.dolby.pulse.1
+audio/vnd.dra					dra
+audio/vnd.dts					dts
+audio/vnd.dts.hd				dtshd
+# audio/vnd.dvb.file
+# audio/vnd.everad.plj
+# audio/vnd.hns.audio
+audio/vnd.lucent.voice				lvp
+audio/vnd.ms-playready.media.pya		pya
+# audio/vnd.nokia.mobile-xmf
+# audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800			ecelp4800
+audio/vnd.nuera.ecelp7470			ecelp7470
+audio/vnd.nuera.ecelp9600			ecelp9600
+# audio/vnd.octel.sbc
+# audio/vnd.qcelp
+# audio/vnd.rhetorex.32kadpcm
+audio/vnd.rip					rip
+# audio/vnd.sealedmedia.softseal.mpeg
+# audio/vnd.vmx.cvsd
+# audio/vorbis
+# audio/vorbis-config
+audio/webm					weba
+audio/x-aac					aac
+audio/x-aiff					aif aiff aifc
+audio/x-caf					caf
+audio/x-flac					flac
+audio/x-matroska				mka
+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-tta
+audio/x-wav					wav
+audio/xm					xm
+chemical/x-cdx					cdx
+chemical/x-cif					cif
+chemical/x-cmdf					cmdf
+chemical/x-cml					cml
+chemical/x-csml					csml
+# chemical/x-pdb
+chemical/x-xyz					xyz
+image/bmp					bmp
+image/cgm					cgm
+# image/example
+# image/fits
+image/g3fax					g3
+image/gif					gif
+image/ief					ief
+# image/jp2
+image/jpeg					jpeg jpg jpe
+# image/jpm
+# image/jpx
+image/ktx					ktx
+# image/naplps
+image/png					png
+image/prs.btif					btif
+# image/prs.pti
+image/sgi					sgi
+image/svg+xml					svg svgz
+# image/t38
+image/tiff					tiff tif
+# image/tiff-fx
+image/vnd.adobe.photoshop			psd
+# image/vnd.cns.inf2
+image/vnd.dece.graphic				uvi uvvi uvg uvvg
+image/vnd.dvb.subtitle				sub
+image/vnd.djvu					djvu djv
+image/vnd.dwg					dwg
+image/vnd.dxf					dxf
+image/vnd.fastbidsheet				fbs
+image/vnd.fpx					fpx
+image/vnd.fst					fst
+image/vnd.fujixerox.edmics-mmr			mmr
+image/vnd.fujixerox.edmics-rlc			rlc
+# image/vnd.globalgraphics.pgb
+# image/vnd.microsoft.icon
+# image/vnd.mix
+image/vnd.ms-modi				mdi
+image/vnd.ms-photo				wdp
+image/vnd.net-fpx				npx
+# image/vnd.radiance
+# image/vnd.sealed.png
+# image/vnd.sealedmedia.softseal.gif
+# image/vnd.sealedmedia.softseal.jpg
+# image/vnd.svf
+image/vnd.wap.wbmp				wbmp
+image/vnd.xiff					xif
+image/webp					webp
+image/x-3ds					3ds
+image/x-cmu-raster				ras
+image/x-cmx					cmx
+image/x-freehand				fh fhc fh4 fh5 fh7
+image/x-icon					ico
+image/x-mrsid-image				sid
+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-tga					tga
+image/x-xbitmap					xbm
+image/x-xpixmap					xpm
+image/x-xwindowdump				xwd
+# message/cpim
+# message/delivery-status
+# message/disposition-notification
+# message/example
+# message/external-body
+# message/feedback-report
+# message/global
+# message/global-delivery-status
+# message/global-disposition-notification
+# message/global-headers
+# message/http
+# message/imdn+xml
+# message/news
+# message/partial
+message/rfc822					eml mime
+# message/s-http
+# message/sip
+# message/sipfrag
+# message/tracking-status
+# message/vnd.si.simp
+# model/example
+model/iges					igs iges
+model/mesh					msh mesh silo
+model/vnd.collada+xml				dae
+model/vnd.dwf					dwf
+# model/vnd.flatland.3dml
+model/vnd.gdl					gdl
+# model/vnd.gs-gdl
+# model/vnd.gs.gdl
+model/vnd.gtw					gtw
+# model/vnd.moml+xml
+model/vnd.mts					mts
+# model/vnd.parasolid.transmit.binary
+# model/vnd.parasolid.transmit.text
+model/vnd.vtu					vtu
+model/vrml					wrl vrml
+model/x3d+binary				x3db x3dbz
+model/x3d+vrml					x3dv x3dvz
+model/x3d+xml					x3d x3dz
+# multipart/alternative
+# multipart/appledouble
+# multipart/byteranges
+# multipart/digest
+# multipart/encrypted
+# multipart/example
+# multipart/form-data
+# multipart/header-set
+# multipart/mixed
+# multipart/parallel
+# multipart/related
+# multipart/report
+# multipart/signed
+# multipart/voice-message
+# text/1d-interleaved-parityfec
+text/cache-manifest				appcache
+text/calendar					ics ifb
+text/css					css
+text/csv					csv
+# text/directory
+# text/dns
+# text/ecmascript
+# text/enriched
+# text/example
+# text/fwdred
+text/html					html htm
+# text/javascript
+text/n3						n3
+# text/parityfec
+text/plain					txt text conf def list log in
+# text/prs.fallenstein.rst
+text/prs.lines.tag				dsc
+# text/vnd.radisys.msml-basic-layout
+# text/red
+# text/rfc822-headers
+text/richtext					rtx
+# text/rtf
+# text/rtp-enc-aescm128
+# text/rtx
+text/sgml					sgml sgm
+# text/t140
+text/tab-separated-values			tsv
+text/troff					t tr roff man me ms
+text/turtle					ttl
+# text/ulpfec
+text/uri-list					uri uris urls
+text/vcard					vcard
+# 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.dvb.subtitle				sub
+# 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-java-source				java
+text/x-opml					opml
+text/x-pascal					p pas
+text/x-nfo					nfo
+text/x-setext					etx
+text/x-sfv					sfv
+text/x-uuencode					uu
+text/x-vcalendar				vcs
+text/x-vcard					vcf
+# text/xml
+# text/xml-external-parsed-entity
+# video/1d-interleaved-parityfec
+video/3gpp					3gp
+# video/3gpp-tt
+video/3gpp2					3g2
+# video/bmpeg
+# video/bt656
+# video/celb
+# video/dv
+# video/example
+video/h261					h261
+video/h263					h263
+# video/h263-1998
+# video/h263-2000
+video/h264					h264
+# video/h264-rcdo
+# video/h264-svc
+video/jpeg					jpgv
+# video/jpeg2000
+video/jpm					jpm jpgm
+video/mj2					mj2 mjp2
+# video/mp1s
+# video/mp2p
+# video/mp2t
+video/mp4					mp4 mp4v mpg4
+# video/mp4v-es
+video/mpeg					mpeg mpg mpe m1v m2v
+# video/mpeg4-generic
+# video/mpv
+# video/nv
+video/ogg					ogv
+# video/parityfec
+# video/pointer
+video/quicktime					qt mov
+# video/raw
+# video/rtp-enc-aescm128
+# video/rtx
+# video/smpte292m
+# video/ulpfec
+# video/vc1
+# video/vnd.cctv
+video/vnd.dece.hd				uvh uvvh
+video/vnd.dece.mobile				uvm uvvm
+# video/vnd.dece.mp4
+video/vnd.dece.pd				uvp uvvp
+video/vnd.dece.sd				uvs uvvs
+video/vnd.dece.video				uvv uvvv
+# video/vnd.directv.mpeg
+# video/vnd.directv.mpeg-tts
+# video/vnd.dlna.mpeg-tts
+video/vnd.dvb.file				dvb
+video/vnd.fvt					fvt
+# video/vnd.hns.video
+# video/vnd.iptvforum.1dparityfec-1010
+# video/vnd.iptvforum.1dparityfec-2005
+# video/vnd.iptvforum.2dparityfec-1010
+# video/vnd.iptvforum.2dparityfec-2005
+# video/vnd.iptvforum.ttsavc
+# video/vnd.iptvforum.ttsmpeg2
+# video/vnd.motorola.video
+# video/vnd.motorola.videop
+video/vnd.mpegurl				mxu m4u
+video/vnd.ms-playready.media.pyv		pyv
+# video/vnd.nokia.interleaved-multimedia
+# video/vnd.nokia.videovoip
+# video/vnd.objectvideo
+# video/vnd.sealed.mpeg1
+# video/vnd.sealed.mpeg4
+# video/vnd.sealed.swf
+# video/vnd.sealedmedia.softseal.mov
+video/vnd.uvvu.mp4				uvu uvvu
+video/vnd.vivo					viv
+video/webm					webm
+video/x-f4v					f4v
+video/x-fli					fli
+video/x-flv					flv
+video/x-m4v					m4v
+video/x-matroska				mkv mk3d mks
+video/x-mng					mng
+video/x-ms-asf					asf asx
+video/x-ms-vob					vob
+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
+video/x-smv					smv
+x-conference/x-cooltalk				ice
Index: Dev/trunk/src/node_modules/request/node_modules/mime/types/node.types
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/mime/types/node.types	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/mime/types/node.types	(revision 484)
@@ -0,0 +1,77 @@
+# What: WebVTT
+# Why: To allow formats intended for marking up external text track resources.
+# http://dev.w3.org/html5/webvtt/
+# Added by: niftylettuce
+text/vtt  vtt
+
+# What: Google Chrome Extension
+# Why: To allow apps to (work) be served with the right content type header.
+# http://codereview.chromium.org/2830017
+# Added by: niftylettuce
+application/x-chrome-extension  crx
+
+# What: HTC support
+# Why: To properly render .htc files such as CSS3PIE
+# Added by: niftylettuce
+text/x-component  htc
+
+# What: HTML5 application cache manifes ('.manifest' extension)
+# Why: De-facto standard. Required by Mozilla browser when serving HTML5 apps
+# per https://developer.mozilla.org/en/offline_resources_in_firefox
+# Added by: louisremi
+text/cache-manifest  manifest
+
+# What: node binary buffer format
+# Why: semi-standard extension w/in the node community
+# Added by: tootallnate
+application/octet-stream  buffer
+
+# What: The "protected" MP-4 formats used by iTunes.
+# Why: Required for streaming music to browsers (?)
+# Added by: broofa
+application/mp4  m4p
+audio/mp4  m4a
+
+# What: Video format, Part of RFC1890
+# Why: See https://github.com/bentomas/node-mime/pull/6
+# Added by: mjrusso
+video/MP2T  ts
+
+# What: EventSource mime type
+# Why: mime type of Server-Sent Events stream
+# http://www.w3.org/TR/eventsource/#text-event-stream
+# Added by: francois2metz
+text/event-stream  event-stream
+
+# What: Mozilla App manifest mime type
+# Why: https://developer.mozilla.org/en/Apps/Manifest#Serving_manifests
+# Added by: ednapiranha
+application/x-web-app-manifest+json   webapp
+
+# What: Lua file types
+# Why: Googling around shows de-facto consensus on these
+# Added by: creationix (Issue #45)
+text/x-lua  lua
+application/x-lua-bytecode  luac
+
+# What: Markdown files, as per http://daringfireball.net/projects/markdown/syntax
+# Why: http://stackoverflow.com/questions/10701983/what-is-the-mime-type-for-markdown
+# Added by: avoidwork
+text/x-markdown  markdown md mkd
+
+# What: ini files
+# Why: because they're just text files
+# Added by: Matthew Kastor
+text/plain  ini
+
+# What: DASH Adaptive Streaming manifest
+# Why: https://developer.mozilla.org/en-US/docs/DASH_Adaptive_Streaming_for_HTML_5_Video
+# Added by: eelcocramer
+application/dash+xml mdp
+
+# What: OpenType font files - http://www.microsoft.com/typography/otspec/
+# Why:  Browsers usually ignore the font MIME types and sniff the content,
+#       but Chrome, shows a warning if OpenType fonts aren't served with
+#       the `font/opentype` MIME type: http://i.imgur.com/8c5RN8M.png.
+# Added by: alrra
+font/opentype  otf
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/.npmignore	(revision 484)
@@ -0,0 +1,2 @@
+node_modules
+.DS_Store
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/LICENSE.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/LICENSE.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/LICENSE.md	(revision 484)
@@ -0,0 +1,2 @@
+Copyright (c) 2010-2012 Robert Kieffer
+MIT License - http://opensource.org/licenses/mit-license.php
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/README.md	(revision 484)
@@ -0,0 +1,207 @@
+# node-uuid
+
+Simple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.
+
+Features:
+
+* Generate RFC4122 version 1 or version 4 UUIDs
+* Runs in node.js and all browsers.
+* Registered as a [ComponentJS](https://github.com/component/component) [component](https://github.com/component/component/wiki/Components) ('broofa/node-uuid').
+* Cryptographically strong random # generation on supporting platforms
+* 1.1K minified and gzip'ed  (Want something smaller?  Check this [crazy shit](https://gist.github.com/982883) out! )
+* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html)
+
+## Getting Started
+
+Install it in your browser:
+
+```html
+<script src="uuid.js"></script>
+```
+
+Or in node.js:
+
+```
+npm install node-uuid
+```
+
+```javascript
+var uuid = require('node-uuid');
+```
+
+Then create some ids ...
+
+```javascript
+// Generate a v1 (time-based) id
+uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
+
+// Generate a v4 (random) id
+uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'
+```
+
+## API
+
+### uuid.v1([`options` [, `buffer` [, `offset`]]])
+
+Generate and return a RFC4122 v1 (timestamp-based) UUID.
+
+* `options` - (Object) Optional uuid state to apply. Properties may include:
+
+  * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomly generated ID.  See note 1.
+  * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence.  Default: An internally maintained clockseq is used.
+  * `msecs` - (Number | Date) Time in milliseconds since unix Epoch.  Default: The current time is used.
+  * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.
+
+* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
+* `offset` - (Number) Starting index in `buffer` at which to begin writing.
+
+Returns `buffer`, if specified, otherwise the string form of the UUID
+
+Notes:
+
+1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.)
+
+Example: Generate string UUID with fully-specified options
+
+```javascript
+uuid.v1({
+  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
+  clockseq: 0x1234,
+  msecs: new Date('2011-11-01').getTime(),
+  nsecs: 5678
+});   // -> "710b962e-041c-11e1-9234-0123456789ab"
+```
+
+Example: In-place generation of two binary IDs
+
+```javascript
+// Generate two ids in an array
+var arr = new Array(32); // -> []
+uuid.v1(null, arr, 0);   // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
+uuid.v1(null, arr, 16);  // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15]
+
+// Optionally use uuid.unparse() to get stringify the ids
+uuid.unparse(buffer);    // -> '02a2ce90-1432-11e1-8558-0b488e4fc115'
+uuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115'
+```
+
+### uuid.v4([`options` [, `buffer` [, `offset`]]])
+
+Generate and return a RFC4122 v4 UUID.
+
+* `options` - (Object) Optional uuid state to apply. Properties may include:
+
+  * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values
+  * `rng` - (Function) Random # generator to use.  Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values.
+
+* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.
+* `offset` - (Number) Starting index in `buffer` at which to begin writing.
+
+Returns `buffer`, if specified, otherwise the string form of the UUID
+
+Example: Generate string UUID with fully-specified options
+
+```javascript
+uuid.v4({
+  random: [
+    0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,
+    0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36
+  ]
+});
+// -> "109156be-c4fb-41ea-b1b4-efe1671c5836"
+```
+
+Example: Generate two IDs in a single buffer
+
+```javascript
+var buffer = new Array(32); // (or 'new Buffer' in node.js)
+uuid.v4(null, buffer, 0);
+uuid.v4(null, buffer, 16);
+```
+
+### uuid.parse(id[, buffer[, offset]])
+### uuid.unparse(buffer[, offset])
+
+Parse and unparse UUIDs
+
+  * `id` - (String) UUID(-like) string
+  * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used
+  * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0
+
+Example parsing and unparsing a UUID string
+
+```javascript
+var bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> <Buffer 79 7f f0 43 11 eb 11 e1 80 d6 51 09 98 75 5d 10>
+var string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10'
+```
+
+### uuid.noConflict()
+
+(Browsers only) Set `uuid` property back to it's previous value.
+
+Returns the node-uuid object.
+
+Example:
+
+```javascript
+var myUuid = uuid.noConflict();
+myUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'
+```
+
+## Deprecated APIs
+
+Support for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version.
+
+### uuid([format [, buffer [, offset]]])
+
+uuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary).
+
+### uuid.BufferClass
+
+The class of container created when generating binary uuid data if no buffer argument is specified.  This is expected to go away, with no replacement API.
+
+## Testing
+
+In node.js
+
+```
+> cd test
+> node test.js
+```
+
+In Browser
+
+```
+open test/test.html
+```
+
+### Benchmarking
+
+Requires node.js
+
+```
+npm install uuid uuid-js
+node benchmark/benchmark.js
+```
+
+For a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark)
+
+For browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance).
+
+## Release notes
+
+### 1.4.0
+
+* Improved module context detection
+* Removed public RNG functions
+
+### 1.3.2
+
+* Improve tests and handling of v1() options (Issue #24)
+* Expose RNG option to allow for perf testing with different generators
+
+### 1.3.0
+
+* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!
+* Support for node.js crypto API
+* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/README.md	(revision 484)
@@ -0,0 +1,53 @@
+# node-uuid Benchmarks
+
+### Results
+
+To see the results of our benchmarks visit https://github.com/broofa/node-uuid/wiki/Benchmark
+
+### Run them yourself
+
+node-uuid comes with some benchmarks to measure performance of generating UUIDs. These can be run using node.js. node-uuid is being benchmarked against some other uuid modules, that are available through npm namely `uuid` and `uuid-js`.
+
+To prepare and run the benchmark issue;
+
+```
+npm install uuid uuid-js
+node benchmark/benchmark.js
+```
+
+You'll see an output like this one:
+
+```
+# v4
+nodeuuid.v4(): 854700 uuids/second
+nodeuuid.v4('binary'): 788643 uuids/second
+nodeuuid.v4('binary', buffer): 1336898 uuids/second
+uuid(): 479386 uuids/second
+uuid('binary'): 582072 uuids/second
+uuidjs.create(4): 312304 uuids/second
+
+# v1
+nodeuuid.v1(): 938086 uuids/second
+nodeuuid.v1('binary'): 683060 uuids/second
+nodeuuid.v1('binary', buffer): 1644736 uuids/second
+uuidjs.create(1): 190621 uuids/second
+```
+
+* The `uuid()` entries are for Nikhil Marathe's [uuid module](https://bitbucket.org/nikhilm/uuidjs) which is a wrapper around the native libuuid library.
+* The `uuidjs()` entries are for Patrick Negri's [uuid-js module](https://github.com/pnegri/uuid-js) which is a pure javascript implementation based on [UUID.js](https://github.com/LiosK/UUID.js) by LiosK.
+
+If you want to get more reliable results you can run the benchmark multiple times and write the output into a log file:
+
+```
+for i in {0..9}; do node benchmark/benchmark.js >> benchmark/bench_0.4.12.log; done;
+```
+
+If you're interested in how performance varies between different node versions, you can issue the above command multiple times.
+
+You can then use the shell script `bench.sh` provided in this directory to calculate the averages over all benchmark runs and draw a nice plot:
+
+```
+(cd benchmark/ && ./bench.sh)
+```
+
+This assumes you have [gnuplot](http://www.gnuplot.info/) and [ImageMagick](http://www.imagemagick.org/) installed. You'll find a nice `bench.png` graph in the `benchmark/` directory then.
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/bench.gnu	(revision 484)
@@ -0,0 +1,174 @@
+#!/opt/local/bin/gnuplot -persist
+#
+#    
+#    	G N U P L O T
+#    	Version 4.4 patchlevel 3
+#    	last modified March 2011
+#    	System: Darwin 10.8.0
+#    
+#    	Copyright (C) 1986-1993, 1998, 2004, 2007-2010
+#    	Thomas Williams, Colin Kelley and many others
+#    
+#    	gnuplot home:     http://www.gnuplot.info
+#    	faq, bugs, etc:   type "help seeking-assistance"
+#    	immediate help:   type "help"
+#    	plot window:      hit 'h'
+set terminal postscript eps noenhanced defaultplex \
+ leveldefault color colortext \
+ solid linewidth 1.2 butt noclip \
+ palfuncparam 2000,0.003 \
+ "Helvetica" 14 
+set output 'bench.eps'
+unset clip points
+set clip one
+unset clip two
+set bar 1.000000 front
+set border 31 front linetype -1 linewidth 1.000
+set xdata
+set ydata
+set zdata
+set x2data
+set y2data
+set timefmt x "%d/%m/%y,%H:%M"
+set timefmt y "%d/%m/%y,%H:%M"
+set timefmt z "%d/%m/%y,%H:%M"
+set timefmt x2 "%d/%m/%y,%H:%M"
+set timefmt y2 "%d/%m/%y,%H:%M"
+set timefmt cb "%d/%m/%y,%H:%M"
+set boxwidth
+set style fill  empty border
+set style rectangle back fc lt -3 fillstyle   solid 1.00 border lt -1
+set style circle radius graph 0.02, first 0, 0 
+set dummy x,y
+set format x "% g"
+set format y "% g"
+set format x2 "% g"
+set format y2 "% g"
+set format z "% g"
+set format cb "% g"
+set angles radians
+unset grid
+set key title ""
+set key outside left top horizontal Right noreverse enhanced autotitles columnhead nobox
+set key noinvert samplen 4 spacing 1 width 0 height 0 
+set key maxcolumns 2 maxrows 0
+unset label
+unset arrow
+set style increment default
+unset style line
+set style line 1  linetype 1 linewidth 2.000 pointtype 1 pointsize default pointinterval 0
+unset style arrow
+set style histogram clustered gap 2 title  offset character 0, 0, 0
+unset logscale
+set offsets graph 0.05, 0.15, 0, 0
+set pointsize 1.5
+set pointintervalbox 1
+set encoding default
+unset polar
+unset parametric
+unset decimalsign
+set view 60, 30, 1, 1
+set samples 100, 100
+set isosamples 10, 10
+set surface
+unset contour
+set clabel '%8.3g'
+set mapping cartesian
+set datafile separator whitespace
+unset hidden3d
+set cntrparam order 4
+set cntrparam linear
+set cntrparam levels auto 5
+set cntrparam points 5
+set size ratio 0 1,1
+set origin 0,0
+set style data points
+set style function lines
+set xzeroaxis linetype -2 linewidth 1.000
+set yzeroaxis linetype -2 linewidth 1.000
+set zzeroaxis linetype -2 linewidth 1.000
+set x2zeroaxis linetype -2 linewidth 1.000
+set y2zeroaxis linetype -2 linewidth 1.000
+set ticslevel 0.5
+set mxtics default
+set mytics default
+set mztics default
+set mx2tics default
+set my2tics default
+set mcbtics default
+set xtics border in scale 1,0.5 mirror norotate  offset character 0, 0, 0
+set xtics  norangelimit
+set xtics   ()
+set ytics border in scale 1,0.5 mirror norotate  offset character 0, 0, 0
+set ytics autofreq  norangelimit
+set ztics border in scale 1,0.5 nomirror norotate  offset character 0, 0, 0
+set ztics autofreq  norangelimit
+set nox2tics
+set noy2tics
+set cbtics border in scale 1,0.5 mirror norotate  offset character 0, 0, 0
+set cbtics autofreq  norangelimit
+set title "" 
+set title  offset character 0, 0, 0 font "" norotate
+set timestamp bottom 
+set timestamp "" 
+set timestamp  offset character 0, 0, 0 font "" norotate
+set rrange [ * : * ] noreverse nowriteback  # (currently [8.98847e+307:-8.98847e+307] )
+set autoscale rfixmin
+set autoscale rfixmax
+set trange [ * : * ] noreverse nowriteback  # (currently [-5.00000:5.00000] )
+set autoscale tfixmin
+set autoscale tfixmax
+set urange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
+set autoscale ufixmin
+set autoscale ufixmax
+set vrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
+set autoscale vfixmin
+set autoscale vfixmax
+set xlabel "" 
+set xlabel  offset character 0, 0, 0 font "" textcolor lt -1 norotate
+set x2label "" 
+set x2label  offset character 0, 0, 0 font "" textcolor lt -1 norotate
+set xrange [ * : * ] noreverse nowriteback  # (currently [-0.150000:3.15000] )
+set autoscale xfixmin
+set autoscale xfixmax
+set x2range [ * : * ] noreverse nowriteback  # (currently [0.00000:3.00000] )
+set autoscale x2fixmin
+set autoscale x2fixmax
+set ylabel "" 
+set ylabel  offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270
+set y2label "" 
+set y2label  offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270
+set yrange [ 0.00000 : 1.90000e+06 ] noreverse nowriteback  # (currently [:] )
+set autoscale yfixmin
+set autoscale yfixmax
+set y2range [ * : * ] noreverse nowriteback  # (currently [0.00000:1.90000e+06] )
+set autoscale y2fixmin
+set autoscale y2fixmax
+set zlabel "" 
+set zlabel  offset character 0, 0, 0 font "" textcolor lt -1 norotate
+set zrange [ * : * ] noreverse nowriteback  # (currently [-10.0000:10.0000] )
+set autoscale zfixmin
+set autoscale zfixmax
+set cblabel "" 
+set cblabel  offset character 0, 0, 0 font "" textcolor lt -1 rotate by -270
+set cbrange [ * : * ] noreverse nowriteback  # (currently [8.98847e+307:-8.98847e+307] )
+set autoscale cbfixmin
+set autoscale cbfixmax
+set zero 1e-08
+set lmargin  -1
+set bmargin  -1
+set rmargin  -1
+set tmargin  -1
+set pm3d explicit at s
+set pm3d scansautomatic
+set pm3d interpolate 1,1 flush begin noftriangles nohidden3d corners2color mean
+set palette positive nops_allcF maxcolors 0 gamma 1.5 color model RGB 
+set palette rgbformulae 7, 5, 15
+set colorbox default
+set colorbox vertical origin screen 0.9, 0.2, 0 size screen 0.05, 0.6, 0 front bdefault
+set loadpath 
+set fontpath 
+set fit noerrorvariables
+GNUTERM = "aqua"
+plot 'bench_results.txt' using 2:xticlabel(1) w lp lw 2, '' using 3:xticlabel(1) w lp lw 2, '' using 4:xticlabel(1) w lp lw 2, '' using 5:xticlabel(1) w lp lw 2, '' using 6:xticlabel(1) w lp lw 2, '' using 7:xticlabel(1) w lp lw 2, '' using 8:xticlabel(1) w lp lw 2, '' using 9:xticlabel(1) w lp lw 2
+#    EOF
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/bench.sh
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/bench.sh	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/bench.sh	(revision 484)
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# for a given node version run:
+# for i in {0..9}; do node benchmark.js >> bench_0.6.2.log; done;
+
+PATTERNS=('nodeuuid.v1()' "nodeuuid.v1('binary'," 'nodeuuid.v4()' "nodeuuid.v4('binary'," "uuid()" "uuid('binary')" 'uuidjs.create(1)' 'uuidjs.create(4)' '140byte')
+FILES=(node_uuid_v1_string node_uuid_v1_buf node_uuid_v4_string node_uuid_v4_buf libuuid_v4_string libuuid_v4_binary uuidjs_v1_string uuidjs_v4_string 140byte_es)
+INDICES=(2 3 2 3 2 2 2 2 2)
+VERSIONS=$( ls bench_*.log | sed -e 's/^bench_\([0-9\.]*\)\.log/\1/' | tr "\\n" " " )
+TMPJOIN="tmp_join"
+OUTPUT="bench_results.txt"
+
+for I in ${!FILES[*]}; do
+  F=${FILES[$I]}
+  P=${PATTERNS[$I]}
+  INDEX=${INDICES[$I]}
+  echo "version $F" > $F
+  for V in $VERSIONS; do
+    (VAL=$( grep "$P" bench_$V.log | LC_ALL=en_US awk '{ sum += $'$INDEX' } END { print sum/NR }' ); echo $V $VAL) >> $F
+  done
+  if [ $I == 0 ]; then
+    cat $F > $TMPJOIN
+  else
+    join $TMPJOIN $F > $OUTPUT
+    cp $OUTPUT $TMPJOIN
+  fi
+  rm $F
+done
+
+rm $TMPJOIN
+
+gnuplot bench.gnu
+convert -density 200 -resize 800x560 -flatten bench.eps bench.png
+rm bench.eps
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/benchmark-native.c	(revision 484)
@@ -0,0 +1,34 @@
+/*
+Test performance of native C UUID generation
+
+To Compile: cc -luuid benchmark-native.c -o benchmark-native
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <uuid/uuid.h>
+
+int main() {
+  uuid_t myid;
+  char buf[36+1];
+  int i;
+  struct timeval t;
+  double start, finish;
+
+  gettimeofday(&t, NULL);
+  start = t.tv_sec + t.tv_usec/1e6;
+
+  int n = 2e5;
+  for (i = 0; i < n; i++) {
+    uuid_generate(myid);
+    uuid_unparse(myid, buf);
+  }
+
+  gettimeofday(&t, NULL);
+  finish = t.tv_sec + t.tv_usec/1e6;
+  double dur = finish - start;
+
+  printf("%d uuids/sec", (int)(n/dur));
+  return 0;
+}
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/benchmark/benchmark.js	(revision 484)
@@ -0,0 +1,84 @@
+try {
+  var nodeuuid = require('../uuid');
+} catch (e) {
+  console.error('node-uuid require failed - skipping tests');
+}
+
+try {
+  var uuid = require('uuid');
+} catch (e) {
+  console.error('uuid require failed - skipping tests');
+}
+
+try {
+  var uuidjs = require('uuid-js');
+} catch (e) {
+  console.error('uuid-js require failed - skipping tests');
+}
+
+var N = 5e5;
+
+function rate(msg, t) {
+  console.log(msg + ': ' +
+    (N / (Date.now() - t) * 1e3 | 0) +
+    ' uuids/second');
+}
+
+console.log('# v4');
+
+// node-uuid - string form
+if (nodeuuid) {
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4();
+  rate('nodeuuid.v4() - using node.js crypto RNG', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4({rng: nodeuuid.mathRNG});
+  rate('nodeuuid.v4() - using Math.random() RNG', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary');
+  rate('nodeuuid.v4(\'binary\')', t);
+
+  var buffer = new nodeuuid.BufferClass(16);
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v4('binary', buffer);
+  rate('nodeuuid.v4(\'binary\', buffer)', t);
+}
+
+// libuuid - string form
+if (uuid) {
+  for (var i = 0, t = Date.now(); i < N; i++) uuid();
+  rate('uuid()', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) uuid('binary');
+  rate('uuid(\'binary\')', t);
+}
+
+// uuid-js - string form
+if (uuidjs) {
+  for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(4);
+  rate('uuidjs.create(4)', t);
+}
+
+// 140byte.es
+for (var i = 0, t = Date.now(); i < N; i++) 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(s,r){r=Math.random()*16|0;return (s=='x'?r:r&0x3|0x8).toString(16)});
+rate('140byte.es_v4', t);
+
+console.log('');
+console.log('# v1');
+
+// node-uuid - v1 string form
+if (nodeuuid) {
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1();
+  rate('nodeuuid.v1()', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary');
+  rate('nodeuuid.v1(\'binary\')', t);
+
+  var buffer = new nodeuuid.BufferClass(16);
+  for (var i = 0, t = Date.now(); i < N; i++) nodeuuid.v1('binary', buffer);
+  rate('nodeuuid.v1(\'binary\', buffer)', t);
+}
+
+// uuid-js - v1 string form
+if (uuidjs) {
+  for (var i = 0, t = Date.now(); i < N; i++) uuidjs.create(1);
+  rate('uuidjs.create(1)', t);
+}
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/component.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/component.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/component.json	(revision 484)
@@ -0,0 +1,18 @@
+{
+  "name": "node-uuid",
+  "repo": "broofa/node-uuid",
+  "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.",
+  "version": "1.4.0",
+  "author": "Robert Kieffer <robert@broofa.com>",
+  "contributors": [
+    {"name": "Christoph Tavan <dev@tavan.de>", "github": "https://github.com/ctavan"}
+  ],
+  "keywords": ["uuid", "guid", "rfc4122"],
+  "dependencies": {},
+  "development": {},
+  "main": "uuid.js",
+  "scripts": [
+    "uuid.js"
+  ],
+  "license": "MIT"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/package.json	(revision 484)
@@ -0,0 +1,35 @@
+{
+  "name": "node-uuid",
+  "description": "Rigorous implementation of RFC4122 (v1 and v4) UUIDs.",
+  "url": "http://github.com/broofa/node-uuid",
+  "keywords": [
+    "uuid",
+    "guid",
+    "rfc4122"
+  ],
+  "author": {
+    "name": "Robert Kieffer",
+    "email": "robert@broofa.com"
+  },
+  "contributors": [
+    {
+      "name": "Christoph Tavan",
+      "email": "dev@tavan.de"
+    }
+  ],
+  "lib": ".",
+  "main": "./uuid.js",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/broofa/node-uuid.git"
+  },
+  "version": "1.4.1",
+  "readme": "# node-uuid\n\nSimple, fast generation of [RFC4122](http://www.ietf.org/rfc/rfc4122.txt) UUIDS.\n\nFeatures:\n\n* Generate RFC4122 version 1 or version 4 UUIDs\n* Runs in node.js and all browsers.\n* Registered as a [ComponentJS](https://github.com/component/component) [component](https://github.com/component/component/wiki/Components) ('broofa/node-uuid').\n* Cryptographically strong random # generation on supporting platforms\n* 1.1K minified and gzip'ed  (Want something smaller?  Check this [crazy shit](https://gist.github.com/982883) out! )\n* [Annotated source code](http://broofa.github.com/node-uuid/docs/uuid.html)\n\n## Getting Started\n\nInstall it in your browser:\n\n```html\n<script src=\"uuid.js\"></script>\n```\n\nOr in node.js:\n\n```\nnpm install node-uuid\n```\n\n```javascript\nvar uuid = require('node-uuid');\n```\n\nThen create some ids ...\n\n```javascript\n// Generate a v1 (time-based) id\nuuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'\n\n// Generate a v4 (random) id\nuuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'\n```\n\n## API\n\n### uuid.v1([`options` [, `buffer` [, `offset`]]])\n\nGenerate and return a RFC4122 v1 (timestamp-based) UUID.\n\n* `options` - (Object) Optional uuid state to apply. Properties may include:\n\n  * `node` - (Array) Node id as Array of 6 bytes (per 4.1.6). Default: Randomly generated ID.  See note 1.\n  * `clockseq` - (Number between 0 - 0x3fff) RFC clock sequence.  Default: An internally maintained clockseq is used.\n  * `msecs` - (Number | Date) Time in milliseconds since unix Epoch.  Default: The current time is used.\n  * `nsecs` - (Number between 0-9999) additional time, in 100-nanosecond units. Ignored if `msecs` is unspecified. Default: internal uuid counter is used, as per 4.2.1.2.\n\n* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.\n* `offset` - (Number) Starting index in `buffer` at which to begin writing.\n\nReturns `buffer`, if specified, otherwise the string form of the UUID\n\nNotes:\n\n1. The randomly generated node id is only guaranteed to stay constant for the lifetime of the current JS runtime. (Future versions of this module may use persistent storage mechanisms to extend this guarantee.)\n\nExample: Generate string UUID with fully-specified options\n\n```javascript\nuuid.v1({\n  node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],\n  clockseq: 0x1234,\n  msecs: new Date('2011-11-01').getTime(),\n  nsecs: 5678\n});   // -> \"710b962e-041c-11e1-9234-0123456789ab\"\n```\n\nExample: In-place generation of two binary IDs\n\n```javascript\n// Generate two ids in an array\nvar arr = new Array(32); // -> []\nuuid.v1(null, arr, 0);   // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15]\nuuid.v1(null, arr, 16);  // -> [02 a2 ce 90 14 32 11 e1 85 58 0b 48 8e 4f c1 15 02 a3 1c b0 14 32 11 e1 85 58 0b 48 8e 4f c1 15]\n\n// Optionally use uuid.unparse() to get stringify the ids\nuuid.unparse(buffer);    // -> '02a2ce90-1432-11e1-8558-0b488e4fc115'\nuuid.unparse(buffer, 16) // -> '02a31cb0-1432-11e1-8558-0b488e4fc115'\n```\n\n### uuid.v4([`options` [, `buffer` [, `offset`]]])\n\nGenerate and return a RFC4122 v4 UUID.\n\n* `options` - (Object) Optional uuid state to apply. Properties may include:\n\n  * `random` - (Number[16]) Array of 16 numbers (0-255) to use in place of randomly generated values\n  * `rng` - (Function) Random # generator to use.  Set to one of the built-in generators - `uuid.mathRNG` (all platforms), `uuid.nodeRNG` (node.js only), `uuid.whatwgRNG` (WebKit only) - or a custom function that returns an array[16] of byte values.\n\n* `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written.\n* `offset` - (Number) Starting index in `buffer` at which to begin writing.\n\nReturns `buffer`, if specified, otherwise the string form of the UUID\n\nExample: Generate string UUID with fully-specified options\n\n```javascript\nuuid.v4({\n  random: [\n    0x10, 0x91, 0x56, 0xbe, 0xc4, 0xfb, 0xc1, 0xea,\n    0x71, 0xb4, 0xef, 0xe1, 0x67, 0x1c, 0x58, 0x36\n  ]\n});\n// -> \"109156be-c4fb-41ea-b1b4-efe1671c5836\"\n```\n\nExample: Generate two IDs in a single buffer\n\n```javascript\nvar buffer = new Array(32); // (or 'new Buffer' in node.js)\nuuid.v4(null, buffer, 0);\nuuid.v4(null, buffer, 16);\n```\n\n### uuid.parse(id[, buffer[, offset]])\n### uuid.unparse(buffer[, offset])\n\nParse and unparse UUIDs\n\n  * `id` - (String) UUID(-like) string\n  * `buffer` - (Array | Buffer) Array or buffer where UUID bytes are to be written. Default: A new Array or Buffer is used\n  * `offset` - (Number) Starting index in `buffer` at which to begin writing. Default: 0\n\nExample parsing and unparsing a UUID string\n\n```javascript\nvar bytes = uuid.parse('797ff043-11eb-11e1-80d6-510998755d10'); // -> <Buffer 79 7f f0 43 11 eb 11 e1 80 d6 51 09 98 75 5d 10>\nvar string = uuid.unparse(bytes); // -> '797ff043-11eb-11e1-80d6-510998755d10'\n```\n\n### uuid.noConflict()\n\n(Browsers only) Set `uuid` property back to it's previous value.\n\nReturns the node-uuid object.\n\nExample:\n\n```javascript\nvar myUuid = uuid.noConflict();\nmyUuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'\n```\n\n## Deprecated APIs\n\nSupport for the following v1.2 APIs is available in v1.3, but is deprecated and will be removed in the next major version.\n\n### uuid([format [, buffer [, offset]]])\n\nuuid() has become uuid.v4(), and the `format` argument is now implicit in the `buffer` argument. (i.e. if you specify a buffer, the format is assumed to be binary).\n\n### uuid.BufferClass\n\nThe class of container created when generating binary uuid data if no buffer argument is specified.  This is expected to go away, with no replacement API.\n\n## Testing\n\nIn node.js\n\n```\n> cd test\n> node test.js\n```\n\nIn Browser\n\n```\nopen test/test.html\n```\n\n### Benchmarking\n\nRequires node.js\n\n```\nnpm install uuid uuid-js\nnode benchmark/benchmark.js\n```\n\nFor a more complete discussion of node-uuid performance, please see the `benchmark/README.md` file, and the [benchmark wiki](https://github.com/broofa/node-uuid/wiki/Benchmark)\n\nFor browser performance [checkout the JSPerf tests](http://jsperf.com/node-uuid-performance).\n\n## Release notes\n\n### 1.4.0\n\n* Improved module context detection\n* Removed public RNG functions\n\n### 1.3.2\n\n* Improve tests and handling of v1() options (Issue #24)\n* Expose RNG option to allow for perf testing with different generators\n\n### 1.3.0\n\n* Support for version 1 ids, thanks to [@ctavan](https://github.com/ctavan)!\n* Support for node.js crypto API\n* De-emphasizing performance in favor of a) cryptographic quality PRNGs where available and b) more manageable code\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/broofa/node-uuid/issues"
+  },
+  "homepage": "https://github.com/broofa/node-uuid",
+  "_id": "node-uuid@1.4.1",
+  "_from": "node-uuid@~1.4.0"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/test/compare_v1.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/test/compare_v1.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/test/compare_v1.js	(revision 484)
@@ -0,0 +1,63 @@
+var assert = require('assert'),
+    nodeuuid = require('../uuid'),
+    uuidjs = require('uuid-js'),
+    libuuid = require('uuid').generate,
+    util = require('util'),
+    exec = require('child_process').exec,
+    os = require('os');
+
+// On Mac Os X / macports there's only the ossp-uuid package that provides uuid
+// On Linux there's uuid-runtime which provides uuidgen
+var uuidCmd = os.type() === 'Darwin' ? 'uuid -1' : 'uuidgen -t';
+
+function compare(ids) {
+  console.log(ids);
+  for (var i = 0; i < ids.length; i++) {
+    var id = ids[i].split('-');
+    id = [id[2], id[1], id[0]].join('');
+    ids[i] = id;
+  }
+  var sorted = ([].concat(ids)).sort();
+
+  if (sorted.toString() !== ids.toString()) {
+    console.log('Warning: sorted !== ids');
+  } else {
+    console.log('everything in order!');
+  }
+}
+
+// Test time order of v1 uuids
+var ids = [];
+while (ids.length < 10e3) ids.push(nodeuuid.v1());
+
+var max = 10;
+console.log('node-uuid:');
+ids = [];
+for (var i = 0; i < max; i++) ids.push(nodeuuid.v1());
+compare(ids);
+
+console.log('');
+console.log('uuidjs:');
+ids = [];
+for (var i = 0; i < max; i++) ids.push(uuidjs.create(1).toString());
+compare(ids);
+
+console.log('');
+console.log('libuuid:');
+ids = [];
+var count = 0;
+var last = function() {
+  compare(ids);
+}
+var cb = function(err, stdout, stderr) {
+  ids.push(stdout.substring(0, stdout.length-1));
+  count++;
+  if (count < max) {
+    return next();
+  }
+  last();
+};
+var next = function() {
+  exec(uuidCmd, cb);
+};
+next();
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/test/test.html
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/test/test.html	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/test/test.html	(revision 484)
@@ -0,0 +1,17 @@
+<html>
+  <head>
+    <style>
+      div {
+        font-family: monospace;
+        font-size: 8pt;
+      }
+      div.log {color: #444;}
+      div.warn {color: #550;}
+      div.error {color: #800; font-weight: bold;}
+    </style>
+    <script src="../uuid.js"></script>
+  </head>
+  <body>
+    <script src="./test.js"></script>
+  </body>
+</html>
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/test/test.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/test/test.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/test/test.js	(revision 484)
@@ -0,0 +1,228 @@
+if (!this.uuid) {
+  // node.js
+  uuid = require('../uuid');
+}
+
+//
+// x-platform log/assert shims
+//
+
+function _log(msg, type) {
+  type = type || 'log';
+
+  if (typeof(document) != 'undefined') {
+    document.write('<div class="' + type + '">' + msg.replace(/\n/g, '<br />') + '</div>');
+  }
+  if (typeof(console) != 'undefined') {
+    var color = {
+      log: '\033[39m',
+      warn: '\033[33m',
+      error: '\033[31m'
+    };
+    console[type](color[type] + msg + color.log);
+  }
+}
+
+function log(msg) {_log(msg, 'log');}
+function warn(msg) {_log(msg, 'warn');}
+function error(msg) {_log(msg, 'error');}
+
+function assert(res, msg) {
+  if (!res) {
+    error('FAIL: ' + msg);
+  } else {
+    log('Pass: ' + msg);
+  }
+}
+
+//
+// Unit tests
+//
+
+// Verify ordering of v1 ids created with explicit times
+var TIME = 1321644961388; // 2011-11-18 11:36:01.388-08:00
+
+function compare(name, ids) {
+  ids = ids.map(function(id) {
+    return id.split('-').reverse().join('-');
+  }).sort();
+  var sorted = ([].concat(ids)).sort();
+
+  assert(sorted.toString() == ids.toString(), name + ' have expected order');
+}
+
+// Verify ordering of v1 ids created using default behavior
+compare('uuids with current time', [
+  uuid.v1(),
+  uuid.v1(),
+  uuid.v1(),
+  uuid.v1(),
+  uuid.v1()
+]);
+
+// Verify ordering of v1 ids created with explicit times
+compare('uuids with time option', [
+  uuid.v1({msecs: TIME - 10*3600*1000}),
+  uuid.v1({msecs: TIME - 1}),
+  uuid.v1({msecs: TIME}),
+  uuid.v1({msecs: TIME + 1}),
+  uuid.v1({msecs: TIME + 28*24*3600*1000})
+]);
+
+assert(
+  uuid.v1({msecs: TIME}) != uuid.v1({msecs: TIME}),
+  'IDs created at same msec are different'
+);
+
+// Verify throw if too many ids created
+var thrown = false;
+try {
+  uuid.v1({msecs: TIME, nsecs: 10000});
+} catch (e) {
+  thrown = true;
+}
+assert(thrown, 'Exception thrown when > 10K ids created in 1 ms');
+
+// Verify clock regression bumps clockseq
+var uidt = uuid.v1({msecs: TIME});
+var uidtb = uuid.v1({msecs: TIME - 1});
+assert(
+  parseInt(uidtb.split('-')[3], 16) - parseInt(uidt.split('-')[3], 16) === 1,
+  'Clock regression by msec increments the clockseq'
+);
+
+// Verify clock regression bumps clockseq
+var uidtn = uuid.v1({msecs: TIME, nsecs: 10});
+var uidtnb = uuid.v1({msecs: TIME, nsecs: 9});
+assert(
+  parseInt(uidtnb.split('-')[3], 16) - parseInt(uidtn.split('-')[3], 16) === 1,
+  'Clock regression by nsec increments the clockseq'
+);
+
+// Verify explicit options produce expected id
+var id = uuid.v1({
+  msecs: 1321651533573,
+  nsecs: 5432,
+  clockseq: 0x385c,
+  node: [ 0x61, 0xcd, 0x3c, 0xbb, 0x32, 0x10 ]
+});
+assert(id == 'd9428888-122b-11e1-b85c-61cd3cbb3210', 'Explicit options produce expected id');
+
+// Verify adjacent ids across a msec boundary are 1 time unit apart
+var u0 = uuid.v1({msecs: TIME, nsecs: 9999});
+var u1 = uuid.v1({msecs: TIME + 1, nsecs: 0});
+
+var before = u0.split('-')[0], after = u1.split('-')[0];
+var dt = parseInt(after, 16) - parseInt(before, 16);
+assert(dt === 1, 'Ids spanning 1ms boundary are 100ns apart');
+
+//
+// Test parse/unparse
+//
+
+id = '00112233445566778899aabbccddeeff';
+assert(uuid.unparse(uuid.parse(id.substr(0,10))) ==
+  '00112233-4400-0000-0000-000000000000', 'Short parse');
+assert(uuid.unparse(uuid.parse('(this is the uuid -> ' + id + id)) ==
+  '00112233-4455-6677-8899-aabbccddeeff', 'Dirty parse');
+
+//
+// Perf tests
+//
+
+var generators = {
+  v1: uuid.v1,
+  v4: uuid.v4
+};
+
+var UUID_FORMAT = {
+  v1: /[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i,
+  v4: /[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i
+};
+
+var N = 1e4;
+
+// Get %'age an actual value differs from the ideal value
+function divergence(actual, ideal) {
+  return Math.round(100*100*(actual - ideal)/ideal)/100;
+}
+
+function rate(msg, t) {
+  log(msg + ': ' + (N / (Date.now() - t) * 1e3 | 0) + ' uuids\/second');
+}
+
+for (var version in generators) {
+  var counts = {}, max = 0;
+  var generator = generators[version];
+  var format = UUID_FORMAT[version];
+
+  log('\nSanity check ' + N + ' ' + version + ' uuids');
+  for (var i = 0, ok = 0; i < N; i++) {
+    id = generator();
+    if (!format.test(id)) {
+      throw Error(id + ' is not a valid UUID string');
+    }
+
+    if (id != uuid.unparse(uuid.parse(id))) {
+      assert(fail, id + ' is not a valid id');
+    }
+
+    // Count digits for our randomness check
+    if (version == 'v4') {
+      var digits = id.replace(/-/g, '').split('');
+      for (var j = digits.length-1; j >= 0; j--) {
+        var c = digits[j];
+        max = Math.max(max, counts[c] = (counts[c] || 0) + 1);
+      }
+    }
+  }
+
+  // Check randomness for v4 UUIDs
+  if (version == 'v4') {
+    // Limit that we get worried about randomness. (Purely empirical choice, this!)
+    var limit = 2*100*Math.sqrt(1/N);
+
+    log('\nChecking v4 randomness.  Distribution of Hex Digits (% deviation from ideal)');
+
+    for (var i = 0; i < 16; i++) {
+      var c = i.toString(16);
+      var bar = '', n = counts[c], p = Math.round(n/max*100|0);
+
+      // 1-3,5-8, and D-F: 1:16 odds over 30 digits
+      var ideal = N*30/16;
+      if (i == 4) {
+        // 4: 1:1 odds on 1 digit, plus 1:16 odds on 30 digits
+        ideal = N*(1 + 30/16);
+      } else if (i >= 8 && i <= 11) {
+        // 8-B: 1:4 odds on 1 digit, plus 1:16 odds on 30 digits
+        ideal = N*(1/4 + 30/16);
+      } else {
+        // Otherwise: 1:16 odds on 30 digits
+        ideal = N*30/16;
+      }
+      var d = divergence(n, ideal);
+
+      // Draw bar using UTF squares (just for grins)
+      var s = n/max*50 | 0;
+      while (s--) bar += '=';
+
+      assert(Math.abs(d) < limit, c + ' |' + bar + '| ' + counts[c] + ' (' + d + '% < ' + limit + '%)');
+    }
+  }
+}
+
+// Perf tests
+for (var version in generators) {
+  log('\nPerformance testing ' + version + ' UUIDs');
+  var generator = generators[version];
+  var buf = new uuid.BufferClass(16);
+
+  for (var i = 0, t = Date.now(); i < N; i++) generator();
+  rate('uuid.' + version + '()', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) generator('binary');
+  rate('uuid.' + version + '(\'binary\')', t);
+
+  for (var i = 0, t = Date.now(); i < N; i++) generator('binary', buf);
+  rate('uuid.' + version + '(\'binary\', buffer)', t);
+}
Index: Dev/trunk/src/node_modules/request/node_modules/node-uuid/uuid.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/node-uuid/uuid.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/node-uuid/uuid.js	(revision 484)
@@ -0,0 +1,245 @@
+//     uuid.js
+//
+//     Copyright (c) 2010-2012 Robert Kieffer
+//     MIT License - http://opensource.org/licenses/mit-license.php
+
+(function() {
+  var _global = this;
+
+  // Unique ID creation requires a high quality random # generator.  We feature
+  // detect to determine the best RNG source, normalizing to a function that
+  // returns 128-bits of randomness, since that's what's usually required
+  var _rng;
+
+  // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
+  //
+  // Moderately fast, high quality
+  if (typeof(require) == 'function') {
+    try {
+      var _rb = require('crypto').randomBytes;
+      _rng = _rb && function() {return _rb(16);};
+    } catch(e) {}
+  }
+
+  if (!_rng && _global.crypto && crypto.getRandomValues) {
+    // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
+    //
+    // Moderately fast, high quality
+    var _rnds8 = new Uint8Array(16);
+    _rng = function whatwgRNG() {
+      crypto.getRandomValues(_rnds8);
+      return _rnds8;
+    };
+  }
+
+  if (!_rng) {
+    // Math.random()-based (RNG)
+    //
+    // If all else fails, use Math.random().  It's fast, but is of unspecified
+    // quality.
+    var  _rnds = new Array(16);
+    _rng = function() {
+      for (var i = 0, r; i < 16; i++) {
+        if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
+        _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
+      }
+
+      return _rnds;
+    };
+  }
+
+  // Buffer class to use
+  var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array;
+
+  // Maps for number <-> hex string conversion
+  var _byteToHex = [];
+  var _hexToByte = {};
+  for (var i = 0; i < 256; i++) {
+    _byteToHex[i] = (i + 0x100).toString(16).substr(1);
+    _hexToByte[_byteToHex[i]] = i;
+  }
+
+  // **`parse()` - Parse a UUID into it's component bytes**
+  function parse(s, buf, offset) {
+    var i = (buf && offset) || 0, ii = 0;
+
+    buf = buf || [];
+    s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
+      if (ii < 16) { // Don't overflow!
+        buf[i + ii++] = _hexToByte[oct];
+      }
+    });
+
+    // Zero out remaining bytes if string was short
+    while (ii < 16) {
+      buf[i + ii++] = 0;
+    }
+
+    return buf;
+  }
+
+  // **`unparse()` - Convert UUID byte array (ala parse()) into a string**
+  function unparse(buf, offset) {
+    var i = offset || 0, bth = _byteToHex;
+    return  bth[buf[i++]] + bth[buf[i++]] +
+            bth[buf[i++]] + bth[buf[i++]] + '-' +
+            bth[buf[i++]] + bth[buf[i++]] + '-' +
+            bth[buf[i++]] + bth[buf[i++]] + '-' +
+            bth[buf[i++]] + bth[buf[i++]] + '-' +
+            bth[buf[i++]] + bth[buf[i++]] +
+            bth[buf[i++]] + bth[buf[i++]] +
+            bth[buf[i++]] + bth[buf[i++]];
+  }
+
+  // **`v1()` - Generate time-based UUID**
+  //
+  // Inspired by https://github.com/LiosK/UUID.js
+  // and http://docs.python.org/library/uuid.html
+
+  // random #'s we need to init node and clockseq
+  var _seedBytes = _rng();
+
+  // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
+  var _nodeId = [
+    _seedBytes[0] | 0x01,
+    _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
+  ];
+
+  // Per 4.2.2, randomize (14 bit) clockseq
+  var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
+
+  // Previous uuid creation time
+  var _lastMSecs = 0, _lastNSecs = 0;
+
+  // See https://github.com/broofa/node-uuid for API details
+  function v1(options, buf, offset) {
+    var i = buf && offset || 0;
+    var b = buf || [];
+
+    options = options || {};
+
+    var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
+
+    // UUID timestamps are 100 nano-second units since the Gregorian epoch,
+    // (1582-10-15 00:00).  JSNumbers aren't precise enough for this, so
+    // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
+    // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
+    var msecs = options.msecs != null ? options.msecs : new Date().getTime();
+
+    // Per 4.2.1.2, use count of uuid's generated during the current clock
+    // cycle to simulate higher resolution clock
+    var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
+
+    // Time since last uuid creation (in msecs)
+    var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
+
+    // Per 4.2.1.2, Bump clockseq on clock regression
+    if (dt < 0 && options.clockseq == null) {
+      clockseq = clockseq + 1 & 0x3fff;
+    }
+
+    // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
+    // time interval
+    if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
+      nsecs = 0;
+    }
+
+    // Per 4.2.1.2 Throw error if too many uuids are requested
+    if (nsecs >= 10000) {
+      throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
+    }
+
+    _lastMSecs = msecs;
+    _lastNSecs = nsecs;
+    _clockseq = clockseq;
+
+    // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
+    msecs += 12219292800000;
+
+    // `time_low`
+    var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
+    b[i++] = tl >>> 24 & 0xff;
+    b[i++] = tl >>> 16 & 0xff;
+    b[i++] = tl >>> 8 & 0xff;
+    b[i++] = tl & 0xff;
+
+    // `time_mid`
+    var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
+    b[i++] = tmh >>> 8 & 0xff;
+    b[i++] = tmh & 0xff;
+
+    // `time_high_and_version`
+    b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
+    b[i++] = tmh >>> 16 & 0xff;
+
+    // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
+    b[i++] = clockseq >>> 8 | 0x80;
+
+    // `clock_seq_low`
+    b[i++] = clockseq & 0xff;
+
+    // `node`
+    var node = options.node || _nodeId;
+    for (var n = 0; n < 6; n++) {
+      b[i + n] = node[n];
+    }
+
+    return buf ? buf : unparse(b);
+  }
+
+  // **`v4()` - Generate random UUID**
+
+  // See https://github.com/broofa/node-uuid for API details
+  function v4(options, buf, offset) {
+    // Deprecated - 'format' argument, as supported in v1.2
+    var i = buf && offset || 0;
+
+    if (typeof(options) == 'string') {
+      buf = options == 'binary' ? new BufferClass(16) : null;
+      options = null;
+    }
+    options = options || {};
+
+    var rnds = options.random || (options.rng || _rng)();
+
+    // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
+    rnds[6] = (rnds[6] & 0x0f) | 0x40;
+    rnds[8] = (rnds[8] & 0x3f) | 0x80;
+
+    // Copy bytes to buffer, if provided
+    if (buf) {
+      for (var ii = 0; ii < 16; ii++) {
+        buf[i + ii] = rnds[ii];
+      }
+    }
+
+    return buf || unparse(rnds);
+  }
+
+  // Export public API
+  var uuid = v4;
+  uuid.v1 = v1;
+  uuid.v4 = v4;
+  uuid.parse = parse;
+  uuid.unparse = unparse;
+  uuid.BufferClass = BufferClass;
+
+  if (typeof define === 'function' && define.amd) {
+    // Publish as AMD module
+    define(function() {return uuid;});
+  } else if (typeof(module) != 'undefined' && module.exports) {
+    // Publish as node.js module
+    module.exports = uuid;
+  } else {
+    // Publish as global (in browsers)
+    var _previousRoot = _global.uuid;
+
+    // **`noConflict()` - (browser only) to reset global 'uuid' var**
+    uuid.noConflict = function() {
+      _global.uuid = _previousRoot;
+      return uuid;
+    };
+
+    _global.uuid = uuid;
+  }
+}).call(this);
Index: Dev/trunk/src/node_modules/request/node_modules/oauth-sign/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/oauth-sign/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/oauth-sign/LICENSE	(revision 484)
@@ -0,0 +1,55 @@
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
Index: Dev/trunk/src/node_modules/request/node_modules/oauth-sign/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/oauth-sign/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/oauth-sign/README.md	(revision 484)
@@ -0,0 +1,4 @@
+oauth-sign
+==========
+
+OAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module. 
Index: Dev/trunk/src/node_modules/request/node_modules/oauth-sign/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/oauth-sign/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/oauth-sign/index.js	(revision 484)
@@ -0,0 +1,43 @@
+var crypto = require('crypto')
+  , qs = require('querystring')
+  ;
+
+function sha1 (key, body) {
+  return crypto.createHmac('sha1', key).update(body).digest('base64')
+}
+
+function rfc3986 (str) {
+  return encodeURIComponent(str)
+    .replace(/!/g,'%21')
+    .replace(/\*/g,'%2A')
+    .replace(/\(/g,'%28')
+    .replace(/\)/g,'%29')
+    .replace(/'/g,'%27')
+    ;
+}
+
+function hmacsign (httpMethod, base_uri, params, consumer_secret, token_secret) {
+  // adapted from https://dev.twitter.com/docs/auth/oauth and 
+  // https://dev.twitter.com/docs/auth/creating-signature
+
+  var querystring = Object.keys(params).sort().map(function(key){
+    // big WTF here with the escape + encoding but it's what twitter wants
+    return escape(rfc3986(key)) + "%3D" + escape(rfc3986(params[key]))
+  }).join('%26')
+
+  var base = [
+    httpMethod ? httpMethod.toUpperCase() : 'GET',
+    rfc3986(base_uri),
+    querystring
+  ].join('&')
+
+  var key = [
+    consumer_secret,
+    token_secret || ''
+  ].map(rfc3986).join('&')
+
+  return sha1(key, base)
+}
+
+exports.hmacsign = hmacsign
+exports.rfc3986 = rfc3986
Index: Dev/trunk/src/node_modules/request/node_modules/oauth-sign/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/oauth-sign/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/oauth-sign/package.json	(revision 484)
@@ -0,0 +1,31 @@
+{
+  "author": {
+    "name": "Mikeal Rogers",
+    "email": "mikeal.rogers@gmail.com",
+    "url": "http://www.futurealoof.com"
+  },
+  "name": "oauth-sign",
+  "description": "OAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module.",
+  "version": "0.3.0",
+  "repository": {
+    "url": "https://github.com/mikeal/oauth-sign"
+  },
+  "main": "index.js",
+  "dependencies": {},
+  "devDependencies": {},
+  "optionalDependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "scripts": {
+    "test": "node test.js"
+  },
+  "readme": "oauth-sign\n==========\n\nOAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module. \n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/mikeal/oauth-sign/issues"
+  },
+  "homepage": "https://github.com/mikeal/oauth-sign",
+  "_id": "oauth-sign@0.3.0",
+  "_from": "oauth-sign@~0.3.0"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/oauth-sign/test.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/oauth-sign/test.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/oauth-sign/test.js	(revision 484)
@@ -0,0 +1,49 @@
+var hmacsign = require('./index').hmacsign
+  , assert = require('assert')
+  , qs = require('querystring')
+  ;
+
+// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth
+
+var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', 
+  { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11'
+  , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g'
+  , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk'
+  , oauth_signature_method: 'HMAC-SHA1'
+  , oauth_timestamp: '1272323042'
+  , oauth_version: '1.0'
+  }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98")
+
+console.log(reqsign)
+console.log('8wUi7m5HFQy76nowoCThusfgB+Q=')
+assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=')
+
+var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token',
+  { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g'
+  , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8'
+  , oauth_signature_method: 'HMAC-SHA1'
+  , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc'
+  , oauth_timestamp: '1272323047'
+  , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY'
+  , oauth_version: '1.0'
+  }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA")
+  
+console.log(accsign)
+console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=')
+assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=')
+
+var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', 
+  { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g"
+  , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y"
+  , oauth_signature_method: "HMAC-SHA1"
+  , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw"
+  , oauth_timestamp: "1272325550"
+  , oauth_version: "1.0"
+  , status: 'setting up my twitter ç§ã®ãããããèš­å®ãã'
+  }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA")
+
+console.log(upsign)
+console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=')
+assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=')
+
+
Index: Dev/trunk/src/node_modules/request/node_modules/qs/.gitmodules
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/qs/.gitmodules	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/qs/.gitmodules	(revision 484)
@@ -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
Index: Dev/trunk/src/node_modules/request/node_modules/qs/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/qs/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/qs/.npmignore	(revision 484)
@@ -0,0 +1,7 @@
+test
+.travis.yml
+benchmark.js
+component.json
+examples.js
+History.md
+Makefile
Index: Dev/trunk/src/node_modules/request/node_modules/qs/Readme.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/qs/Readme.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/qs/Readme.md	(revision 484)
@@ -0,0 +1,58 @@
+# node-querystring
+
+  query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.
+
+## Installation
+
+    $ npm install qs
+
+## Examples
+
+```js
+var qs = require('qs');
+
+qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');
+// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }
+
+qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})
+// => user[name]=Tobi&user[email]=tobi%40learnboost.com
+```
+
+## Testing
+
+Install dev dependencies:
+
+    $ npm install -d
+
+and execute:
+
+    $ make test
+
+browser:
+
+    $ open test/browser/index.html
+
+## 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.
Index: Dev/trunk/src/node_modules/request/node_modules/qs/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/qs/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/qs/index.js	(revision 484)
@@ -0,0 +1,387 @@
+/**
+ * Object#toString() ref for stringify().
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Object#hasOwnProperty ref
+ */
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+/**
+ * Array#indexOf shim.
+ */
+
+var indexOf = typeof Array.prototype.indexOf === 'function'
+  ? function(arr, el) { return arr.indexOf(el); }
+  : function(arr, el) {
+      for (var i = 0; i < arr.length; i++) {
+        if (arr[i] === el) return i;
+      }
+      return -1;
+    };
+
+/**
+ * Array.isArray shim.
+ */
+
+var isArray = Array.isArray || function(arr) {
+  return toString.call(arr) == '[object Array]';
+};
+
+/**
+ * Object.keys shim.
+ */
+
+var objectKeys = Object.keys || function(obj) {
+  var ret = [];
+  for (var key in obj) ret.push(key);
+  return ret;
+};
+
+/**
+ * Array#forEach shim.
+ */
+
+var forEach = typeof Array.prototype.forEach === 'function'
+  ? function(arr, fn) { return arr.forEach(fn); }
+  : function(arr, fn) {
+      for (var i = 0; i < arr.length; i++) fn(arr[i]);
+    };
+
+/**
+ * Array#reduce shim.
+ */
+
+var reduce = function(arr, fn, initial) {
+  if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
+  var res = initial;
+  for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
+  return res;
+};
+
+/**
+ * Create a nullary object if possible
+ */
+
+function createObject() {
+  return Object.create
+    ? Object.create(null)
+    : {};
+}
+
+/**
+ * Cache non-integer test regexp.
+ */
+
+var isint = /^[0-9]+$/;
+
+function promote(parent, key) {
+  if (parent[key].length == 0) return parent[key] = createObject();
+  var t = createObject();
+  for (var i in parent[key]) {
+    if (hasOwnProperty.call(parent[key], i)) {
+      t[i] = parent[key][i];
+    }
+  }
+  parent[key] = t;
+  return t;
+}
+
+function parse(parts, parent, key, val) {
+  var part = parts.shift();
+  // end
+  if (!part) {
+    if (isArray(parent[key])) {
+      parent[key].push(val);
+    } else if ('object' == typeof parent[key]) {
+      parent[key] = val;
+    } else if ('undefined' == typeof parent[key]) {
+      parent[key] = val;
+    } else {
+      parent[key] = [parent[key], val];
+    }
+    // array
+  } else {
+    var obj = parent[key] = parent[key] || [];
+    if (']' == part) {
+      if (isArray(obj)) {
+        if ('' != val) obj.push(val);
+      } else if ('object' == typeof obj) {
+        obj[objectKeys(obj).length] = val;
+      } else {
+        obj = parent[key] = [parent[key], val];
+      }
+      // prop
+    } else if (~indexOf(part, ']')) {
+      part = part.substr(0, part.length - 1);
+      if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+      // key
+    } else {
+      if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
+      parse(parts, obj, part, val);
+    }
+  }
+}
+
+/**
+ * Merge parent key/val pair.
+ */
+
+function merge(parent, key, val){
+  if (~indexOf(key, ']')) {
+    var parts = key.split('[')
+      , len = parts.length
+      , last = len - 1;
+    parse(parts, parent, 'base', val);
+    // optimize
+  } else {
+    if (!isint.test(key) && isArray(parent.base)) {
+      var t = createObject();
+      for (var k in parent.base) t[k] = parent.base[k];
+      parent.base = t;
+    }
+    set(parent.base, key, val);
+  }
+
+  return parent;
+}
+
+/**
+ * Compact sparse arrays.
+ */
+
+function compact(obj) {
+  if ('object' != typeof obj) return obj;
+
+  if (isArray(obj)) {
+    var ret = [];
+
+    for (var i in obj) {
+      if (hasOwnProperty.call(obj, i)) {
+        ret.push(obj[i]);
+      }
+    }
+
+    return ret;
+  }
+
+  for (var key in obj) {
+    obj[key] = compact(obj[key]);
+  }
+
+  return obj;
+}
+
+/**
+ * Restore Object.prototype.
+ * see pull-request #58
+ */
+
+function restoreProto(obj) {
+  if (!Object.create) return obj;
+  if (isArray(obj)) return obj;
+  if (obj && 'object' != typeof obj) return obj;
+
+  for (var key in obj) {
+    if (hasOwnProperty.call(obj, key)) {
+      obj[key] = restoreProto(obj[key]);
+    }
+  }
+
+  obj.__proto__ = Object.prototype;
+  return obj;
+}
+
+/**
+ * Parse the given obj.
+ */
+
+function parseObject(obj){
+  var ret = { base: {} };
+
+  forEach(objectKeys(obj), function(name){
+    merge(ret, name, obj[name]);
+  });
+
+  return compact(ret.base);
+}
+
+/**
+ * Parse the given str.
+ */
+
+function parseString(str){
+  var ret = reduce(String(str).split('&'), function(ret, pair){
+    var eql = indexOf(pair, '=')
+      , brace = lastBraceInKey(pair)
+      , key = pair.substr(0, brace || eql)
+      , val = pair.substr(brace || eql, pair.length)
+      , val = val.substr(indexOf(val, '=') + 1, val.length);
+
+    // ?foo
+    if ('' == key) key = pair, val = '';
+    if ('' == key) return ret;
+
+    return merge(ret, decode(key), decode(val));
+  }, { base: createObject() }).base;
+
+  return restoreProto(compact(ret));
+}
+
+/**
+ * Parse the given query `str` or `obj`, returning an object.
+ *
+ * @param {String} str | {Object} obj
+ * @return {Object}
+ * @api public
+ */
+
+exports.parse = function(str){
+  if (null == str || '' == str) return {};
+  return 'object' == typeof str
+    ? parseObject(str)
+    : parseString(str);
+};
+
+/**
+ * Turn the given `obj` into a query string
+ *
+ * @param {Object} obj
+ * @return {String}
+ * @api public
+ */
+
+var stringify = exports.stringify = function(obj, prefix) {
+  if (isArray(obj)) {
+    return stringifyArray(obj, prefix);
+  } else if ('[object Object]' == toString.call(obj)) {
+    return stringifyObject(obj, prefix);
+  } else if ('string' == typeof obj) {
+    return stringifyString(obj, prefix);
+  } else {
+    return prefix + '=' + encodeURIComponent(String(obj));
+  }
+};
+
+/**
+ * Stringify the given `str`.
+ *
+ * @param {String} str
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyString(str, prefix) {
+  if (!prefix) throw new TypeError('stringify expects an object');
+  return prefix + '=' + encodeURIComponent(str);
+}
+
+/**
+ * Stringify the given `arr`.
+ *
+ * @param {Array} arr
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyArray(arr, prefix) {
+  var ret = [];
+  if (!prefix) throw new TypeError('stringify expects an object');
+  for (var i = 0; i < arr.length; i++) {
+    ret.push(stringify(arr[i], prefix + '[' + i + ']'));
+  }
+  return ret.join('&');
+}
+
+/**
+ * Stringify the given `obj`.
+ *
+ * @param {Object} obj
+ * @param {String} prefix
+ * @return {String}
+ * @api private
+ */
+
+function stringifyObject(obj, prefix) {
+  var ret = []
+    , keys = objectKeys(obj)
+    , key;
+
+  for (var i = 0, len = keys.length; i < len; ++i) {
+    key = keys[i];
+    if ('' == key) continue;
+    if (null == obj[key]) {
+      ret.push(encodeURIComponent(key) + '=');
+    } else {
+      ret.push(stringify(obj[key], prefix
+        ? prefix + '[' + encodeURIComponent(key) + ']'
+        : encodeURIComponent(key)));
+    }
+  }
+
+  return ret.join('&');
+}
+
+/**
+ * Set `obj`'s `key` to `val` respecting
+ * the weird and wonderful syntax of a qs,
+ * where "foo=bar&foo=baz" becomes an array.
+ *
+ * @param {Object} obj
+ * @param {String} key
+ * @param {String} val
+ * @api private
+ */
+
+function set(obj, key, val) {
+  var v = obj[key];
+  if (undefined === v) {
+    obj[key] = val;
+  } else if (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;
+  }
+}
+
+/**
+ * Decode `str`.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+function decode(str) {
+  try {
+    return decodeURIComponent(str.replace(/\+/g, ' '));
+  } catch (err) {
+    return str;
+  }
+}
Index: Dev/trunk/src/node_modules/request/node_modules/qs/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/qs/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/qs/package.json	(revision 484)
@@ -0,0 +1,38 @@
+{
+  "name": "qs",
+  "description": "querystring parser",
+  "version": "0.6.5",
+  "keywords": [
+    "query string",
+    "parser",
+    "component"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/visionmedia/node-querystring.git"
+  },
+  "devDependencies": {
+    "mocha": "*",
+    "expect.js": "*"
+  },
+  "scripts": {
+    "test": "make test"
+  },
+  "author": {
+    "name": "TJ Holowaychuk",
+    "email": "tj@vision-media.ca",
+    "url": "http://tjholowaychuk.com"
+  },
+  "main": "index",
+  "engines": {
+    "node": "*"
+  },
+  "readme": "# node-querystring\n\n  query string parser for node and the browser 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.\n\n## Installation\n\n    $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n    $ npm install -d\n\nand execute:\n\n    $ make test\n\nbrowser:\n\n    $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
+  "readmeFilename": "Readme.md",
+  "bugs": {
+    "url": "https://github.com/visionmedia/node-querystring/issues"
+  },
+  "homepage": "https://github.com/visionmedia/node-querystring",
+  "_id": "qs@0.6.5",
+  "_from": "qs@~0.6.0"
+}
Index: Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/LICENSE	(revision 484)
@@ -0,0 +1,55 @@
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
Index: Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/README.md
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/README.md	(revision 484)
@@ -0,0 +1,4 @@
+tunnel-agent
+============
+
+HTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.
Index: Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/index.js
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/index.js	(revision 484)
@@ -0,0 +1,227 @@
+'use strict'
+
+var net = require('net')
+  , tls = require('tls')
+  , http = require('http')
+  , https = require('https')
+  , events = require('events')
+  , assert = require('assert')
+  , util = require('util')
+  ;
+
+exports.httpOverHttp = httpOverHttp
+exports.httpsOverHttp = httpsOverHttp
+exports.httpOverHttps = httpOverHttps
+exports.httpsOverHttps = httpsOverHttps
+
+
+function httpOverHttp(options) {
+  var agent = new TunnelingAgent(options)
+  agent.request = http.request
+  return agent
+}
+
+function httpsOverHttp(options) {
+  var agent = new TunnelingAgent(options)
+  agent.request = http.request
+  agent.createSocket = createSecureSocket
+  return agent
+}
+
+function httpOverHttps(options) {
+  var agent = new TunnelingAgent(options)
+  agent.request = https.request
+  return agent
+}
+
+function httpsOverHttps(options) {
+  var agent = new TunnelingAgent(options)
+  agent.request = https.request
+  agent.createSocket = createSecureSocket
+  return agent
+}
+
+
+function TunnelingAgent(options) {
+  var self = this
+  self.options = options || {}
+  self.proxyOptions = self.options.proxy || {}
+  self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets
+  self.requests = []
+  self.sockets = []
+
+  self.on('free', function onFree(socket, host, port) {
+    for (var i = 0, len = self.requests.length; i < len; ++i) {
+      var pending = self.requests[i]
+      if (pending.host === host && pending.port === port) {
+        // Detect the request to connect same origin server,
+        // reuse the connection.
+        self.requests.splice(i, 1)
+        pending.request.onSocket(socket)
+        return
+      }
+    }
+    socket.destroy()
+    self.removeSocket(socket)
+  })
+}
+util.inherits(TunnelingAgent, events.EventEmitter)
+
+TunnelingAgent.prototype.addRequest = function addRequest(req, host, port) {
+  var self = this
+
+  if (self.sockets.length >= this.maxSockets) {
+    // We are over limit so we'll add it to the queue.
+    self.requests.push({host: host, port: port, request: req})
+    return
+  }
+
+  // If we are under maxSockets create a new one.
+  self.createSocket({host: host, port: port, request: req}, function(socket) {
+    socket.on('free', onFree)
+    socket.on('close', onCloseOrRemove)
+    socket.on('agentRemove', onCloseOrRemove)
+    req.onSocket(socket)
+
+    function onFree() {
+      self.emit('free', socket, host, port)
+    }
+
+    function onCloseOrRemove(err) {
+      self.removeSocket()
+      socket.removeListener('free', onFree)
+      socket.removeListener('close', onCloseOrRemove)
+      socket.removeListener('agentRemove', onCloseOrRemove)
+    }
+  })
+}
+
+TunnelingAgent.prototype.createSocket = function createSocket(options, cb) {
+  var self = this
+  var placeholder = {}
+  self.sockets.push(placeholder)
+
+  var connectOptions = mergeOptions({}, self.proxyOptions, 
+    { method: 'CONNECT'
+    , path: options.host + ':' + options.port
+    , agent: false
+    }
+  )
+  if (connectOptions.proxyAuth) {
+    connectOptions.headers = connectOptions.headers || {}
+    connectOptions.headers['Proxy-Authorization'] = 'Basic ' +
+        new Buffer(connectOptions.proxyAuth).toString('base64')
+  }
+
+  debug('making CONNECT request')
+  var connectReq = self.request(connectOptions)
+  connectReq.useChunkedEncodingByDefault = false // for v0.6
+  connectReq.once('response', onResponse) // for v0.6
+  connectReq.once('upgrade', onUpgrade)   // for v0.6
+  connectReq.once('connect', onConnect)   // for v0.7 or later
+  connectReq.once('error', onError)
+  connectReq.end()
+
+  function onResponse(res) {
+    // Very hacky. This is necessary to avoid http-parser leaks.
+    res.upgrade = true
+  }
+
+  function onUpgrade(res, socket, head) {
+    // Hacky.
+    process.nextTick(function() {
+      onConnect(res, socket, head)
+    })
+  }
+
+  function onConnect(res, socket, head) {
+    connectReq.removeAllListeners()
+    socket.removeAllListeners()
+
+    if (res.statusCode === 200) {
+      assert.equal(head.length, 0)
+      debug('tunneling connection has established')
+      self.sockets[self.sockets.indexOf(placeholder)] = socket
+      cb(socket)
+    } else {
+      debug('tunneling socket could not be established, statusCode=%d', res.statusCode)
+      var error = new Error('tunneling socket could not be established, ' + 'statusCode=' + res.statusCode)
+      error.code = 'ECONNRESET'
+      options.request.emit('error', error)
+      self.removeSocket(placeholder)
+    }
+  }
+
+  function onError(cause) {
+    connectReq.removeAllListeners()
+
+    debug('tunneling socket could not be established, cause=%s\n', cause.message, cause.stack)
+    var error = new Error('tunneling socket could not be established, ' + 'cause=' + cause.message)
+    error.code = 'ECONNRESET'
+    options.request.emit('error', error)
+    self.removeSocket(placeholder)
+  }
+}
+
+TunnelingAgent.prototype.removeSocket = function removeSocket(socket) {
+  var pos = this.sockets.indexOf(socket)
+  if (pos === -1) return
+  
+  this.sockets.splice(pos, 1)
+
+  var pending = this.requests.shift()
+  if (pending) {
+    // If we have pending requests and a socket gets closed a new one
+    // needs to be created to take over in the pool for the one that closed.
+    this.createSocket(pending, function(socket) {
+      pending.request.onSocket(socket)
+    })
+  }
+}
+
+function createSecureSocket(options, cb) {
+  var self = this
+  TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {
+    // 0 is dummy port for v0.6
+    var secureSocket = tls.connect(0, mergeOptions({}, self.options, 
+      { servername: options.host
+      , socket: socket
+      }
+    ))
+    cb(secureSocket)
+  })
+}
+
+
+function mergeOptions(target) {
+  for (var i = 1, len = arguments.length; i < len; ++i) {
+    var overrides = arguments[i]
+    if (typeof overrides === 'object') {
+      var keys = Object.keys(overrides)
+      for (var j = 0, keyLen = keys.length; j < keyLen; ++j) {
+        var k = keys[j]
+        if (overrides[k] !== undefined) {
+          target[k] = overrides[k]
+        }
+      }
+    }
+  }
+  return target
+}
+
+
+var debug
+if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) {
+  debug = function() {
+    var args = Array.prototype.slice.call(arguments)
+    if (typeof args[0] === 'string') {
+      args[0] = 'TUNNEL: ' + args[0]
+    } else {
+      args.unshift('TUNNEL:')
+    }
+    console.error.apply(console, args)
+  }
+} else {
+  debug = function() {}
+}
+exports.debug = debug // for test
Index: Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/node_modules/tunnel-agent/package.json	(revision 484)
@@ -0,0 +1,28 @@
+{
+  "author": {
+    "name": "Mikeal Rogers",
+    "email": "mikeal.rogers@gmail.com",
+    "url": "http://www.futurealoof.com"
+  },
+  "name": "tunnel-agent",
+  "description": "HTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.",
+  "version": "0.3.0",
+  "repository": {
+    "url": "https://github.com/mikeal/tunnel-agent"
+  },
+  "main": "index.js",
+  "dependencies": {},
+  "devDependencies": {},
+  "optionalDependencies": {},
+  "engines": {
+    "node": "*"
+  },
+  "readme": "tunnel-agent\n============\n\nHTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/mikeal/tunnel-agent/issues"
+  },
+  "homepage": "https://github.com/mikeal/tunnel-agent",
+  "_id": "tunnel-agent@0.3.0",
+  "_from": "tunnel-agent@~0.3.0"
+}
Index: Dev/trunk/src/node_modules/request/package.json
===================================================================
--- Dev/trunk/src/node_modules/request/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/request/package.json	(revision 484)
@@ -0,0 +1,48 @@
+{
+  "name": "request",
+  "description": "Simplified HTTP request client.",
+  "tags": [
+    "http",
+    "simple",
+    "util",
+    "utility"
+  ],
+  "version": "2.21.0",
+  "author": {
+    "name": "Mikeal Rogers",
+    "email": "mikeal.rogers@gmail.com"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/mikeal/request.git"
+  },
+  "bugs": {
+    "url": "http://github.com/mikeal/request/issues"
+  },
+  "engines": [
+    "node >= 0.8.0"
+  ],
+  "main": "index.js",
+  "dependencies": {
+    "qs": "~0.6.0",
+    "json-stringify-safe": "~4.0.0",
+    "forever-agent": "~0.5.0",
+    "tunnel-agent": "~0.3.0",
+    "http-signature": "~0.9.11",
+    "hawk": "~0.13.0",
+    "aws-sign": "~0.3.0",
+    "oauth-sign": "~0.3.0",
+    "cookie-jar": "~0.3.0",
+    "node-uuid": "~1.4.0",
+    "mime": "~1.2.9",
+    "form-data": "0.0.8"
+  },
+  "scripts": {
+    "test": "node tests/run.js"
+  },
+  "readme": "# Request -- Simplified HTTP request method\n\n## Install\n\n<pre>\n  npm install request\n</pre>\n\nOr from source:\n\n<pre>\n  git clone git://github.com/mikeal/request.git \n  cd request\n  npm link\n</pre>\n\n## Super simple to use\n\nRequest is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.\n\n```javascript\nvar request = require('request');\nrequest('http://www.google.com', function (error, response, body) {\n  if (!error && response.statusCode == 200) {\n    console.log(body) // Print the google web page.\n  }\n})\n```\n\n## Streaming\n\nYou can stream any response to a file stream.\n\n```javascript\nrequest('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))\n```\n\nYou can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers.\n\n```javascript\nfs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))\n```\n\nRequest can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers.\n\n```javascript\nrequest.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))\n```\n\nNow let's get fancy.\n\n```javascript\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    if (req.method === 'PUT') {\n      req.pipe(request.put('http://mysite.com/doodle.png'))\n    } else if (req.method === 'GET' || req.method === 'HEAD') {\n      request.get('http://mysite.com/doodle.png').pipe(resp)\n    } \n  }\n})\n```\n\nYou can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do:\n\n```javascript\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    var x = request('http://mysite.com/doodle.png')\n    req.pipe(x)\n    x.pipe(resp)\n  }\n})\n```\n\nAnd since pipe() returns the destination stream in node 0.5.x you can do one line proxying :)\n\n```javascript\nreq.pipe(request('http://mysite.com/doodle.png')).pipe(resp)\n```\n\nAlso, none of this new functionality conflicts with requests previous features, it just expands them.\n\n```javascript\nvar r = request.defaults({'proxy':'http://localproxy.com'})\n\nhttp.createServer(function (req, resp) {\n  if (req.url === '/doodle.png') {\n    r.get('http://google.com/doodle.png').pipe(resp)\n  }\n})\n```\nYou can still use intermediate proxies, the requests will still follow HTTP forwards, etc.\n\n## Forms\n\n`request` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. For `multipart/related` refer to the `multipart` API.\n\nUrl encoded forms are simple\n\n```javascript\nrequest.post('http://service.com/upload', {form:{key:'value'}})\n// or\nrequest.post('http://service.com/upload').form({key:'value'})\n```\n\nFor `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). You don't need to worry about piping the form object or setting the headers, `request` will handle that for you.\n\n```javascript\nvar r = request.post('http://service.com/upload')\nvar form = r.form()\nform.append('my_field', 'my_value')\nform.append('my_buffer', new Buffer([1, 2, 3]))\nform.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))\nform.append('remote_file', request('http://google.com/doodle.png'))\n```\n\n## HTTP Authentication\n\n```javascript\nrequest.auth('username', 'password', false).get('http://some.server.com/');\n// or\nrequest.get('http://some.server.com/', {\n  'auth': {\n    'user': 'username',\n    'pass': 'password',\n    'sendImmediately': false\n  }\n});\n```\n\nIf passed as an option, `auth` should be a hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional).  The method form takes parameters `auth(username, password, sendImmediately)`.\n\n`sendImmediately` defaults to true, which will cause a basic authentication header to be sent.  If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a 401 response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method).\n\nDigest authentication is supported, but it only works with `sendImmediately` set to `false` (otherwise `request` will send basic authentication on the initial request, which will probably cause the request to fail).\n\n## OAuth Signing\n\n```javascript\n// Twitter OAuth\nvar qs = require('querystring')\n  , oauth =\n    { callback: 'http://mysite.com/callback/'\n    , consumer_key: CONSUMER_KEY\n    , consumer_secret: CONSUMER_SECRET\n    }\n  , url = 'https://api.twitter.com/oauth/request_token'\n  ;\nrequest.post({url:url, oauth:oauth}, function (e, r, body) {\n  // Ideally, you would take the body in the response\n  // and construct a URL that a user clicks on (like a sign in button).\n  // The verifier is only available in the response after a user has \n  // verified with twitter that they are authorizing your app.\n  var access_token = qs.parse(body)\n    , oauth = \n      { consumer_key: CONSUMER_KEY\n      , consumer_secret: CONSUMER_SECRET\n      , token: access_token.oauth_token\n      , verifier: access_token.oauth_verifier\n      }\n    , url = 'https://api.twitter.com/oauth/access_token'\n    ;\n  request.post({url:url, oauth:oauth}, function (e, r, body) {\n    var perm_token = qs.parse(body)\n      , oauth = \n        { consumer_key: CONSUMER_KEY\n        , consumer_secret: CONSUMER_SECRET\n        , token: perm_token.oauth_token\n        , token_secret: perm_token.oauth_token_secret\n        }\n      , url = 'https://api.twitter.com/1/users/show.json?'\n      , params = \n        { screen_name: perm_token.screen_name\n        , user_id: perm_token.user_id\n        }\n      ;\n    url += qs.stringify(params)\n    request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {\n      console.log(user)\n    })\n  })\n})\n```\n\n\n\n### request(options, callback)\n\nThe first argument can be either a url or an options object. The only required option is uri, all others are optional.\n\n* `uri` || `url` - fully qualified uri or a parsed url object from url.parse()\n* `qs` - object containing querystring values to be appended to the uri\n* `method` - http method, defaults to GET\n* `headers` - http headers, defaults to {}\n* `body` - entity body for PATCH, POST and PUT requests. Must be buffer or string.\n* `form` - when passed an object this will set `body` but to a querystring representation of value and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no option a FormData instance is returned that will be piped to request.\n* `auth` - A hash containing values `user` || `username`, `password` || `pass`, and `sendImmediately` (optional).  See documentation above.\n* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.  Additionally, parses the response body as json.\n* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.\n* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.\n* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.\n* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.\n* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.\n* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets.\n* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool.\n* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request\t\n* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri.\n* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above.\n* `hawk` - Options for [Hawk signing](https://github.com/hueniverse/hawk). The `credentials` key must contain the necessary signing info, [see hawk docs for details](https://github.com/hueniverse/hawk#usage-example).\n* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option.\n* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)\n* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services)\n* `httpSignature` - Options for the [HTTP Signature Scheme](https://github.com/joyent/node-http-signature/blob/master/http_signing.md) using [Joyent's library](https://github.com/joyent/node-http-signature). The `keyId` and `key` properties must be specified. See the docs for other options.\n* `localAddress` - Local interface to bind for network connections.\n\n\nThe callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.\n\n## Convenience methods\n\nThere are also shorthand methods for different HTTP METHODs and some other conveniences.\n\n### request.defaults(options)  \n  \nThis method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.\n\n### request.put\n\nSame as request() but defaults to `method: \"PUT\"`.\n\n```javascript\nrequest.put(url)\n```\n\n### request.patch\n\nSame as request() but defaults to `method: \"PATCH\"`.\n\n```javascript\nrequest.patch(url)\n```\n\n### request.post\n\nSame as request() but defaults to `method: \"POST\"`.\n\n```javascript\nrequest.post(url)\n```\n\n### request.head\n\nSame as request() but defaults to `method: \"HEAD\"`.\n\n```javascript\nrequest.head(url)\n```\n\n### request.del\n\nSame as request() but defaults to `method: \"DELETE\"`.\n\n```javascript\nrequest.del(url)\n```\n\n### request.get\n\nAlias to normal request method for uniformity.\n\n```javascript\nrequest.get(url)\n```\n### request.cookie\n\nFunction that creates a new cookie.\n\n```javascript\nrequest.cookie('cookie_string_here')\n```\n### request.jar\n\nFunction that creates a new cookie jar.\n\n```javascript\nrequest.jar()\n```\n\n\n## Examples:\n\n```javascript\n  var request = require('request')\n    , rand = Math.floor(Math.random()*100000000).toString()\n    ;\n  request(\n    { method: 'PUT'\n    , uri: 'http://mikeal.iriscouch.com/testjs/' + rand\n    , multipart: \n      [ { 'content-type': 'application/json'\n        ,  body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})\n        }\n      , { body: 'I am an attachment' }\n      ] \n    }\n  , function (error, response, body) {\n      if(response.statusCode == 201){\n        console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)\n      } else {\n        console.log('error: '+ response.statusCode)\n        console.log(body)\n      }\n    }\n  )\n```\nCookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent).\n\n```javascript\nvar request = request.defaults({jar: false})\nrequest('http://www.google.com', function () {\n  request('http://images.google.com')\n})\n```\n\nIf you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option:\n\n```javascript\nvar j = request.jar()\nvar request = request.defaults({jar:j})\nrequest('http://www.google.com', function () {\n  request('http://images.google.com')\n})\n```\nOR\n\n```javascript\nvar j = request.jar()\nvar cookie = request.cookie('your_cookie_here')\nj.add(cookie)\nrequest({url: 'http://www.google.com', jar: j}, function () {\n  request('http://images.google.com')\n})\n```\n",
+  "readmeFilename": "README.md",
+  "homepage": "https://github.com/mikeal/request",
+  "_id": "request@2.21.0",
+  "_from": "request@2.21.0"
+}
Index: Dev/trunk/src/node_modules/request/tests/run.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/run.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/run.js	(revision 484)
@@ -0,0 +1,40 @@
+var spawn = require('child_process').spawn
+  , exitCode = 0
+  , timeout = 10000
+  , fs = require('fs')
+  ;
+
+fs.readdir(__dirname, function (e, files) {
+  if (e) throw e
+
+  var tests = files.filter(function (f) {return f.slice(0, 'test-'.length) === 'test-'})
+
+  var next = function () {
+    if (tests.length === 0) process.exit(exitCode);
+
+    var file = tests.shift()
+    console.log(file)
+    var proc = spawn('node', [ 'tests/' + file ])
+
+    var killed = false
+    var t = setTimeout(function () {
+      proc.kill()
+      exitCode += 1
+      console.error(file + ' timeout')
+      killed = true
+    }, timeout)
+
+    proc.stdout.pipe(process.stdout)
+    proc.stderr.pipe(process.stderr)
+    proc.on('exit', function (code) {
+      if (code && !killed) console.error(file + ' failed')
+      exitCode += code || 0
+      clearTimeout(t)
+      next()
+    })
+  }
+  next()
+    
+})
+
+
Index: Dev/trunk/src/node_modules/request/tests/server.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/server.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/server.js	(revision 484)
@@ -0,0 +1,90 @@
+var fs = require('fs')
+  , http = require('http')
+  , path = require('path')
+  , https = require('https')
+  , events = require('events')
+  , stream = require('stream')
+  , assert = require('assert')
+  ;
+
+exports.createServer =  function (port) {
+  port = port || 6767
+  var s = http.createServer(function (req, resp) {
+    s.emit(req.url, req, resp);
+  })
+  s.port = port
+  s.url = 'http://localhost:'+port
+  return s;
+}
+
+exports.createSSLServer = function(port, opts) {
+  port = port || 16767
+
+  var options = { 'key' : path.join(__dirname, 'ssl', 'test.key')
+                , 'cert': path.join(__dirname, 'ssl', 'test.crt')
+                }
+  if (opts) {
+    for (var i in opts) options[i] = opts[i]
+  }
+
+  for (var i in options) {
+    options[i] = fs.readFileSync(options[i])
+  }
+
+  var s = https.createServer(options, function (req, resp) {
+    s.emit(req.url, req, resp);
+  })
+  s.port = port
+  s.url = 'https://localhost:'+port
+  return s;
+}
+
+exports.createPostStream = function (text) {
+  var postStream = new stream.Stream();
+  postStream.writeable = true;
+  postStream.readable = true;
+  setTimeout(function () {postStream.emit('data', new Buffer(text)); postStream.emit('end')}, 0);
+  return postStream;
+}
+exports.createPostValidator = function (text, reqContentType) {
+  var l = function (req, resp) {
+    var r = '';
+    req.on('data', function (chunk) {r += chunk})
+    req.on('end', function () {
+      if (req.headers['content-type'] && req.headers['content-type'].indexOf('boundary=') >= 0) {
+        var boundary = req.headers['content-type'].split('boundary=')[1];
+        text = text.replace(/__BOUNDARY__/g, boundary);
+      }
+      if (r !== text) console.log(r, text);
+      assert.equal(r, text)
+      if (reqContentType) {
+        assert.ok(req.headers['content-type'])
+        assert.ok(~req.headers['content-type'].indexOf(reqContentType))
+      }
+      resp.writeHead(200, {'content-type':'text/plain'})
+      resp.write('OK')
+      resp.end()
+    })
+  }
+  return l;
+}
+exports.createGetResponse = function (text, contentType) {
+  var l = function (req, resp) {
+    contentType = contentType || 'text/plain'
+    resp.writeHead(200, {'content-type':contentType})
+    resp.write(text)
+    resp.end()
+  }
+  return l;
+}
+exports.createChunkResponse = function (chunks, contentType) {
+  var l = function (req, resp) {
+    contentType = contentType || 'text/plain'
+    resp.writeHead(200, {'content-type':contentType})
+    chunks.forEach(function (chunk) {
+      resp.write(chunk)
+    })
+    resp.end()
+  }
+  return l;
+}
Index: Dev/trunk/src/node_modules/request/tests/squid.conf
===================================================================
--- Dev/trunk/src/node_modules/request/tests/squid.conf	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/squid.conf	(revision 484)
@@ -0,0 +1,77 @@
+#
+# Recommended minimum configuration:
+#
+acl manager proto cache_object
+acl localhost src 127.0.0.1/32 ::1
+acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1
+
+# Example rule allowing access from your local networks.
+# Adapt to list your (internal) IP networks from where browsing
+# should be allowed
+acl localnet src 10.0.0.0/8	# RFC1918 possible internal network
+acl localnet src 172.16.0.0/12	# RFC1918 possible internal network
+acl localnet src 192.168.0.0/16	# RFC1918 possible internal network
+acl localnet src fc00::/7       # RFC 4193 local private network range
+acl localnet src fe80::/10      # RFC 4291 link-local (directly plugged) machines
+
+acl SSL_ports port 443
+acl Safe_ports port 80		# http
+acl Safe_ports port 21		# ftp
+acl Safe_ports port 443		# https
+acl Safe_ports port 70		# gopher
+acl Safe_ports port 210		# wais
+acl Safe_ports port 1025-65535	# unregistered ports
+acl Safe_ports port 280		# http-mgmt
+acl Safe_ports port 488		# gss-http
+acl Safe_ports port 591		# filemaker
+acl Safe_ports port 777		# multiling http
+acl CONNECT method CONNECT
+
+#
+# Recommended minimum Access Permission configuration:
+#
+# Only allow cachemgr access from localhost
+http_access allow manager localhost
+http_access deny manager
+
+# Deny requests to certain unsafe ports
+http_access deny !Safe_ports
+
+# Deny CONNECT to other than secure SSL ports
+#http_access deny CONNECT !SSL_ports
+
+# We strongly recommend the following be uncommented to protect innocent
+# web applications running on the proxy server who think the only
+# one who can access services on "localhost" is a local user
+#http_access deny to_localhost
+
+#
+# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
+#
+
+# Example rule allowing access from your local networks.
+# Adapt localnet in the ACL section to list your (internal) IP networks
+# from where browsing should be allowed
+http_access allow localnet
+http_access allow localhost
+
+# And finally deny all other access to this proxy
+http_access deny all
+
+# Squid normally listens to port 3128
+http_port 3128
+
+# We recommend you to use at least the following line.
+hierarchy_stoplist cgi-bin ?
+
+# Uncomment and adjust the following to add a disk cache directory.
+#cache_dir ufs /usr/local/var/cache 100 16 256
+
+# Leave coredumps in the first cache dir
+coredump_dir /usr/local/var/cache
+
+# Add any of your own refresh_pattern entries above these.
+refresh_pattern ^ftp:		1440	20%	10080
+refresh_pattern ^gopher:	1440	0%	1440
+refresh_pattern -i (/cgi-bin/|\?) 0	0%	0
+refresh_pattern .		0	20%	4320
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.cnf
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.cnf	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.cnf	(revision 484)
@@ -0,0 +1,20 @@
+[ req ]
+default_bits           = 1024
+days                   = 3650
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+output_password        = password
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = CA
+L                      = Oakland
+O                      = request
+OU                     = request Certificate Authority
+CN                     = requestCA
+emailAddress           = mikeal@mikealrogers.com
+
+[ req_attributes ]
+challengePassword              = password challenge
+
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.crt
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.crt	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.crt	(revision 484)
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICvTCCAiYCCQDn+P/MSbDsWjANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1
+ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG
+A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n
+ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGiMQswCQYD
+VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT
+B3JlcXVlc3QxJjAkBgNVBAsTHXJlcXVlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
+MRIwEAYDVQQDEwlyZXF1ZXN0Q0ExJjAkBgkqhkiG9w0BCQEWF21pa2VhbEBtaWtl
+YWxyb2dlcnMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7t9pQUAK4
+5XJYTI6NrF0n3G2HZsfN+rPYSVzzL8SuVyb1tHXos+vbPm3NKI4E8X1yVAXU8CjJ
+5SqXnp4DAypAhaseho81cbhk7LXUhFz78OvAa+OD+xTAEAnNQ8tGUr4VGyplEjfD
+xsBVuqV2j8GPNTftr+drOCFlqfAgMrBn4wIDAQABMA0GCSqGSIb3DQEBBQUAA4GB
+ADVdTlVAL45R+PACNS7Gs4o81CwSclukBu4FJbxrkd4xGQmurgfRrYYKjtqiopQm
+D7ysRamS3HMN9/VKq2T7r3z1PMHPAy7zM4uoXbbaTKwlnX4j/8pGPn8Ca3qHXYlo
+88L/OOPc6Di7i7qckS3HFbXQCTiULtxWmy97oEuTwrAj
+-----END CERTIFICATE-----
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.csr
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.csr	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.csr	(revision 484)
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICBjCCAW8CAQAwgaIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE
+BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEmMCQGA1UECxMdcmVxdWVzdCBD
+ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxEjAQBgNVBAMTCXJlcXVlc3RDQTEmMCQGCSqG
+SIb3DQEJARYXbWlrZWFsQG1pa2VhbHJvZ2Vycy5jb20wgZ8wDQYJKoZIhvcNAQEB
+BQADgY0AMIGJAoGBALu32lBQArjlclhMjo2sXSfcbYdmx836s9hJXPMvxK5XJvW0
+deiz69s+bc0ojgTxfXJUBdTwKMnlKpeengMDKkCFqx6GjzVxuGTstdSEXPvw68Br
+44P7FMAQCc1Dy0ZSvhUbKmUSN8PGwFW6pXaPwY81N+2v52s4IWWp8CAysGfjAgMB
+AAGgIzAhBgkqhkiG9w0BCQcxFBMScGFzc3dvcmQgY2hhbGxlbmdlMA0GCSqGSIb3
+DQEBBQUAA4GBAGJO7grHeVHXetjHEK8urIxdnvfB2qeZeObz4GPKIkqUurjr0rfj
+bA3EK1kDMR5aeQWR8RunixdM16Q6Ry0lEdLVWkdSwRN9dmirIHT9cypqnD/FYOia
+SdezZ0lUzXgmJIwRYRwB1KSMMocIf52ll/xC2bEGg7/ZAEuAyAgcZV3X
+-----END CERTIFICATE REQUEST-----
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.key
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.key	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.key	(revision 484)
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,C8B5887048377F02
+
+nyD5ZH0Wup2uWsDvurq5mKDaDrf8lvNn9w0SH/ZkVnfR1/bkwqrFriqJWvZNUG+q
+nS0iBYczsWLJnbub9a1zLOTENWUKVD5uqbC3aGHhnoUTNSa27DONgP8gHOn6JgR+
+GAKo01HCSTiVT4LjkwN337QKHnMP2fTzg+IoC/CigvMcq09hRLwU1/guq0GJKGwH
+gTxYNuYmQC4Tjh8vdS4liF+Ve/P3qPR2CehZrIOkDT8PHJBGQJRo4xGUIB7Tpk38
+VCk+UZ0JCS2coY8VkY/9tqFJp/ZnnQQVmaNbdRqg7ECKL+bXnNo7yjzmazPZmPe3
+/ShbE0+CTt7LrjCaQAxWbeDzqfo1lQfgN1LulTm8MCXpQaJpv7v1VhIhQ7afjMYb
+4thW/ypHPiYS2YJCAkAVlua9Oxzzh1qJoh8Df19iHtpd79Q77X/qf+1JvITlMu0U
+gi7yEatmQcmYNws1mtTC1q2DXrO90c+NZ0LK/Alse6NRL/xiUdjug2iHeTf/idOR
+Gg/5dSZbnnlj1E5zjSMDkzg6EHAFmHV4jYGSAFLEQgp4V3ZhMVoWZrvvSHgKV/Qh
+FqrAK4INr1G2+/QTd09AIRzfy3/j6yD4A9iNaOsEf9Ua7Qh6RcALRCAZTWR5QtEf
+dX+iSNJ4E85qXs0PqwkMDkoaxIJ+tmIRJY7y8oeylV8cfGAi8Soubt/i3SlR8IHC
+uDMas/2OnwafK3N7ODeE1i7r7wkzQkSHaEz0TrF8XRnP25jAICCSLiMdAAjKfxVb
+EvzsFSuAy3Jt6bU3hSLY9o4YVYKE+68ITMv9yNjvTsEiW+T+IbN34w==
+-----END RSA PRIVATE KEY-----
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.srl
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.srl	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/ca.srl	(revision 484)
@@ -0,0 +1,1 @@
+ADF62016AA40C9C3
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/server.cnf
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/server.cnf	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/server.cnf	(revision 484)
@@ -0,0 +1,19 @@
+[ req ]
+default_bits           = 1024
+days                   = 3650
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = CA
+L                      = Oakland
+O                      = request
+OU                     = testing
+CN                     = testing.request.mikealrogers.com
+emailAddress           = mikeal@mikealrogers.com
+
+[ req_attributes ]
+challengePassword              = password challenge
+
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/server.crt
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/server.crt	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/server.crt	(revision 484)
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICejCCAeMCCQCt9iAWqkDJwzANBgkqhkiG9w0BAQUFADCBojELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMRAwDgYDVQQKEwdyZXF1
+ZXN0MSYwJAYDVQQLEx1yZXF1ZXN0IENlcnRpZmljYXRlIEF1dGhvcml0eTESMBAG
+A1UEAxMJcmVxdWVzdENBMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlrZWFscm9n
+ZXJzLmNvbTAeFw0xMjAzMDEyMjUwNTZaFw0yMjAyMjcyMjUwNTZaMIGjMQswCQYD
+VQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNVBAcTB09ha2xhbmQxEDAOBgNVBAoT
+B3JlcXVlc3QxEDAOBgNVBAsTB3Rlc3RpbmcxKTAnBgNVBAMTIHRlc3RpbmcucmVx
+dWVzdC5taWtlYWxyb2dlcnMuY29tMSYwJAYJKoZIhvcNAQkBFhdtaWtlYWxAbWlr
+ZWFscm9nZXJzLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDgVl0jMumvOpmM
+20W5v9yhGgZj8hPhEQF/N7yCBVBn/rWGYm70IHC8T/pR5c0LkWc5gdnCJEvKWQjh
+DBKxZD8FAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEABShRkNgFbgs4vUWW9R9deNJj
+7HJoiTmvkmoOC7QzcYkjdgHbOxsSq3rBnwxsVjY9PAtPwBn0GRspOeG7KzKRgySB
+kb22LyrCFKbEOfKO/+CJc80ioK9zEPVjGsFMyAB+ftYRqM+s/4cQlTg/m89l01wC
+yapjN3RxZbInGhWR+jA=
+-----END CERTIFICATE-----
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/server.csr
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/server.csr	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/server.csr	(revision 484)
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBgjCCASwCAQAwgaMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UE
+BxMHT2FrbGFuZDEQMA4GA1UEChMHcmVxdWVzdDEQMA4GA1UECxMHdGVzdGluZzEp
+MCcGA1UEAxMgdGVzdGluZy5yZXF1ZXN0Lm1pa2VhbHJvZ2Vycy5jb20xJjAkBgkq
+hkiG9w0BCQEWF21pa2VhbEBtaWtlYWxyb2dlcnMuY29tMFwwDQYJKoZIhvcNAQEB
+BQADSwAwSAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg
+cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAaAjMCEGCSqGSIb3DQEJBzEU
+ExJwYXNzd29yZCBjaGFsbGVuZ2UwDQYJKoZIhvcNAQEFBQADQQBD3E5WekQzCEJw
+7yOcqvtPYIxGaX8gRKkYfLPoj3pm3GF5SGqtJKhylKfi89szHXgktnQgzff9FN+A
+HidVJ/3u
+-----END CERTIFICATE REQUEST-----
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/server.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/server.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/server.js	(revision 484)
@@ -0,0 +1,28 @@
+var fs = require("fs")
+var https = require("https")
+var options = { key: fs.readFileSync("./server.key")
+              , cert: fs.readFileSync("./server.crt") }
+
+var server = https.createServer(options, function (req, res) {
+  res.writeHead(200)
+  res.end()
+  server.close()
+})
+server.listen(1337)
+
+var ca = fs.readFileSync("./ca.crt")
+var agent = new https.Agent({ host: "localhost", port: 1337, ca: ca })
+
+https.request({ host: "localhost"
+              , method: "HEAD"
+              , port: 1337
+              , headers: { host: "testing.request.mikealrogers.com" }
+              , agent: agent
+              , ca: [ ca ]
+              , path: "/" }, function (res) {
+  if (res.client.authorized) {
+    console.log("node test: OK")
+  } else {
+    throw new Error(res.client.authorizationError)
+  }
+}).end()
Index: Dev/trunk/src/node_modules/request/tests/ssl/ca/server.key
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/ca/server.key	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/ca/server.key	(revision 484)
@@ -0,0 +1,9 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOwIBAAJBAOBWXSMy6a86mYzbRbm/3KEaBmPyE+ERAX83vIIFUGf+tYZibvQg
+cLxP+lHlzQuRZzmB2cIkS8pZCOEMErFkPwUCAwEAAQJAK+r8ZM2sze8s7FRo/ApB
+iRBtO9fCaIdJwbwJnXKo4RKwZDt1l2mm+fzZ+/QaQNjY1oTROkIIXmnwRvZWfYlW
+gQIhAPKYsG+YSBN9o8Sdp1DMyZ/rUifKX3OE6q9tINkgajDVAiEA7Ltqh01+cnt0
+JEnud/8HHcuehUBLMofeg0G+gCnSbXECIQCqDvkXsWNNLnS/3lgsnvH0Baz4sbeJ
+rjIpuVEeg8eM5QIgbu0+9JmOV6ybdmmiMV4yAncoF35R/iKGVHDZCAsQzDECIQDZ
+0jGz22tlo5YMcYSqrdD3U4sds1pwiAaWFRbCunoUJw==
+-----END RSA PRIVATE KEY-----
Index: Dev/trunk/src/node_modules/request/tests/ssl/npm-ca.crt
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/npm-ca.crt	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/npm-ca.crt	(revision 484)
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIChzCCAfACCQDauvz/KHp8ejANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQwwCgYDVQQKEwNucG0x
+IjAgBgNVBAsTGW5wbSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxDjAMBgNVBAMTBW5w
+bUNBMRcwFQYJKoZIhvcNAQkBFghpQGl6cy5tZTAeFw0xMTA5MDUwMTQ3MTdaFw0y
+MTA5MDIwMTQ3MTdaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNV
+BAcTB09ha2xhbmQxDDAKBgNVBAoTA25wbTEiMCAGA1UECxMZbnBtIENlcnRpZmlj
+YXRlIEF1dGhvcml0eTEOMAwGA1UEAxMFbnBtQ0ExFzAVBgkqhkiG9w0BCQEWCGlA
+aXpzLm1lMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLI4tIqPpRW+ACw9GE
+OgBlJZwK5f8nnKCLK629Pv5yJpQKs3DENExAyOgDcyaF0HD0zk8zTp+ZsLaNdKOz
+Gn2U181KGprGKAXP6DU6ByOJDWmTlY6+Ad1laYT0m64fERSpHw/hjD3D+iX4aMOl
+y0HdbT5m1ZGh6SJz3ZqxavhHLQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAC4ySDbC
+l7W1WpLmtLGEQ/yuMLUf6Jy/vr+CRp4h+UzL+IQpCv8FfxsYE7dhf/bmWTEupBkv
+yNL18lipt2jSvR3v6oAHAReotvdjqhxddpe5Holns6EQd1/xEZ7sB1YhQKJtvUrl
+ZNufy1Jf1r0ldEGeA+0ISck7s+xSh9rQD2Op
+-----END CERTIFICATE-----
Index: Dev/trunk/src/node_modules/request/tests/ssl/test.crt
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/test.crt	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/test.crt	(revision 484)
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICQzCCAawCCQCO/XWtRFck1jANBgkqhkiG9w0BAQUFADBmMQswCQYDVQQGEwJU
+SDEQMA4GA1UECBMHQmFuZ2tvazEOMAwGA1UEBxMFU2lsb20xGzAZBgNVBAoTElRo
+ZSBSZXF1ZXN0IE1vZHVsZTEYMBYGA1UEAxMPcmVxdWVzdC5leGFtcGxlMB4XDTEx
+MTIwMzAyMjkyM1oXDTIxMTEzMDAyMjkyM1owZjELMAkGA1UEBhMCVEgxEDAOBgNV
+BAgTB0Jhbmdrb2sxDjAMBgNVBAcTBVNpbG9tMRswGQYDVQQKExJUaGUgUmVxdWVz
+dCBNb2R1bGUxGDAWBgNVBAMTD3JlcXVlc3QuZXhhbXBsZTCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAwmctddZqlA48+NXs0yOy92DijcQV1jf87zMiYAIlNUto
+wghVbTWgJU5r0pdKrD16AptnWJTzKanhItEX8XCCPgsNkq1afgTtJP7rNkwu3xcj
+eIMkhJg/ay4ZnkbnhYdsii5VTU5prix6AqWRAhbkBgoA+iVyHyof8wvZyKBoFTMC
+AwEAATANBgkqhkiG9w0BAQUFAAOBgQB6BybMJbpeiABgihDfEVBcAjDoQ8gUMgwV
+l4NulugfKTDmArqnR9aPd4ET5jX5dkMP4bwCHYsvrcYDeWEQy7x5WWuylOdKhua4
+L4cEi2uDCjqEErIG3cc1MCOk6Cl6Ld6tkIzQSf953qfdEACRytOeUqLNQcrXrqeE
+c7U8F6MWLQ==
+-----END CERTIFICATE-----
Index: Dev/trunk/src/node_modules/request/tests/ssl/test.key
===================================================================
--- Dev/trunk/src/node_modules/request/tests/ssl/test.key	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/ssl/test.key	(revision 484)
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDCZy111mqUDjz41ezTI7L3YOKNxBXWN/zvMyJgAiU1S2jCCFVt
+NaAlTmvSl0qsPXoCm2dYlPMpqeEi0RfxcII+Cw2SrVp+BO0k/us2TC7fFyN4gySE
+mD9rLhmeRueFh2yKLlVNTmmuLHoCpZECFuQGCgD6JXIfKh/zC9nIoGgVMwIDAQAB
+AoGBALXFwfUf8vHTSmGlrdZS2AGFPvEtuvldyoxi9K5u8xmdFCvxnOcLsF2RsTHt
+Mu5QYWhUpNJoG+IGLTPf7RJdj/kNtEs7xXqWy4jR36kt5z5MJzqiK+QIgiO9UFWZ
+fjUb6oeDnTIJA9YFBdYi97MDuL89iU/UK3LkJN3hd4rciSbpAkEA+MCkowF5kSFb
+rkOTBYBXZfiAG78itDXN6DXmqb9XYY+YBh3BiQM28oxCeQYyFy6pk/nstnd4TXk6
+V/ryA2g5NwJBAMgRKTY9KvxJWbESeMEFe2iBIV0c26/72Amgi7ZKUCLukLfD4tLF
++WSZdmTbbqI1079YtwaiOVfiLm45Q/3B0eUCQAaQ/0eWSGE+Yi8tdXoVszjr4GXb
+G81qBi91DMu6U1It+jNfIba+MPsiHLcZJMVb4/oWBNukN7bD1nhwFWdlnu0CQQCf
+Is9WHkdvz2RxbZDxb8verz/7kXXJQJhx5+rZf7jIYFxqX3yvTNv3wf2jcctJaWlZ
+fVZwB193YSivcgt778xlAkEAprYUz3jczjF5r2hrgbizPzPDR94tM5BTO3ki2v3w
+kbf+j2g7FNAx6kZiVN8XwfLc8xEeUGiPKwtq3ddPDFh17w==
+-----END RSA PRIVATE KEY-----
Index: Dev/trunk/src/node_modules/request/tests/test-basic-auth.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-basic-auth.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-basic-auth.js	(revision 484)
@@ -0,0 +1,143 @@
+var assert = require('assert')
+  , http = require('http')
+  , request = require('../index')
+  ;
+
+var numBasicRequests = 0;
+
+var basicServer = http.createServer(function (req, res) {
+  console.error('Basic auth server: ', req.method, req.url);
+  numBasicRequests++;
+
+  var ok;
+
+  if (req.headers.authorization) {
+    if (req.headers.authorization == 'Basic ' + new Buffer('test:testing2').toString('base64')) {
+      ok = true;
+    } else if ( req.headers.authorization == 'Basic ' + new Buffer(':apassword').toString('base64')) {
+      ok = true;
+    } else {
+      // Bad auth header, don't send back WWW-Authenticate header
+      ok = false;
+    }
+  } else {
+    // No auth header, send back WWW-Authenticate header
+    ok = false;
+    res.setHeader('www-authenticate', 'Basic realm="Private"');
+  }
+
+  if (req.url == '/post/') {
+    var expectedContent = 'data_key=data_value';
+    req.on('data', function(data) {
+      assert.equal(data, expectedContent);
+      console.log('received request data: ' + data);
+    });
+    assert.equal(req.method, 'POST');
+    assert.equal(req.headers['content-length'], '' + expectedContent.length);
+    assert.equal(req.headers['content-type'], 'application/x-www-form-urlencoded; charset=utf-8');
+  }
+
+  if (ok) {
+    console.log('request ok');
+    res.end('ok');
+  } else {
+    console.log('status=401');
+    res.statusCode = 401;
+    res.end('401');
+  }
+});
+
+basicServer.listen(6767);
+
+var tests = [
+  function(next) {
+    request({
+      'method': 'GET',
+      'uri': 'http://localhost:6767/test/',
+      'auth': {
+        'user': 'test',
+        'pass': 'testing2',
+        'sendImmediately': false
+      }
+    }, function(error, res, body) {
+      assert.equal(res.statusCode, 200);
+      assert.equal(numBasicRequests, 2);
+      next();
+    });
+  },
+
+  function(next) {
+    // If we don't set sendImmediately = false, request will send basic auth
+    request({
+      'method': 'GET',
+      'uri': 'http://localhost:6767/test2/',
+      'auth': {
+        'user': 'test',
+        'pass': 'testing2'
+      }
+    }, function(error, res, body) {
+      assert.equal(res.statusCode, 200);
+      assert.equal(numBasicRequests, 3);
+      next();
+    });
+  },
+
+  function(next) {
+    request({
+      'method': 'GET',
+      'uri': 'http://test:testing2@localhost:6767/test2/'
+    }, function(error, res, body) {
+      assert.equal(res.statusCode, 200);
+      assert.equal(numBasicRequests, 4);
+      next();
+    });
+  },
+
+  function(next) {
+    request({
+      'method': 'POST',
+      'form': { 'data_key': 'data_value' },
+      'uri': 'http://localhost:6767/post/',
+      'auth': {
+        'user': 'test',
+        'pass': 'testing2',
+        'sendImmediately': false
+      }
+    }, function(error, res, body) {
+      assert.equal(res.statusCode, 200);
+      assert.equal(numBasicRequests, 6);
+      next();
+    });
+  },
+
+  function(next) {
+    assert.doesNotThrow( function() {
+      request({
+        'method': 'GET',
+        'uri': 'http://localhost:6767/allow_empty_user/',
+        'auth': {
+          'user': '',
+          'pass': 'apassword',
+          'sendImmediately': false
+        }
+      }, function(error, res, body ) {
+        assert.equal(res.statusCode, 200);
+        assert.equal(numBasicRequests, 8);
+        next();
+      });
+    })
+  }
+];
+
+function runTest(i) {
+  if (i < tests.length) {
+    tests[i](function() {
+      runTest(i + 1);
+    });
+  } else {
+    console.log('All tests passed');
+    basicServer.close();
+  }
+}
+
+runTest(0);
Index: Dev/trunk/src/node_modules/request/tests/test-body.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-body.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-body.js	(revision 484)
@@ -0,0 +1,122 @@
+var server = require('./server')
+  , events = require('events')
+  , stream = require('stream')
+  , assert = require('assert')
+  , request = require('../index')
+  ;
+
+var s = server.createServer();
+
+var tests =
+  { testGet :
+    { resp : server.createGetResponse("TESTING!")
+    , expectBody: "TESTING!"
+    }
+  , testGetChunkBreak :
+    { resp : server.createChunkResponse(
+      [ new Buffer([239])
+      , new Buffer([163])
+      , new Buffer([191])
+      , new Buffer([206])
+      , new Buffer([169])
+      , new Buffer([226])
+      , new Buffer([152])
+      , new Buffer([131])
+      ])
+    , expectBody: "ï£¿Î©â"
+    }
+  , testGetBuffer :
+    { resp : server.createGetResponse(new Buffer("TESTING!"))
+    , encoding: null
+    , expectBody: new Buffer("TESTING!")
+    }
+  , testGetEncoding :
+    { resp : server.createGetResponse(new Buffer('efa3bfcea9e29883', 'hex'))
+    , encoding: 'hex'
+    , expectBody: "efa3bfcea9e29883"
+    }
+  , testGetUTF8:
+     { resp: server.createGetResponse(new Buffer([0xEF, 0xBB, 0xBF, 226, 152, 131]))
+     , encoding: "utf8"
+     , expectBody: "â"
+     }
+  , testGetJSON :
+     { resp : server.createGetResponse('{"test":true}', 'application/json')
+     , json : true
+     , expectBody: {"test":true}
+     }
+  , testPutString :
+    { resp : server.createPostValidator("PUTTINGDATA")
+    , method : "PUT"
+    , body : "PUTTINGDATA"
+    }
+  , testPutBuffer :
+    { resp : server.createPostValidator("PUTTINGDATA")
+    , method : "PUT"
+    , body : new Buffer("PUTTINGDATA")
+    }
+  , testPutJSON :
+    { resp : server.createPostValidator(JSON.stringify({foo: 'bar'}))
+    , method: "PUT"
+    , json: {foo: 'bar'}
+    }
+  , testPutMultipart :
+    { resp: server.createPostValidator(
+        '--__BOUNDARY__\r\n' +
+        'content-type: text/html\r\n' +
+        '\r\n' +
+        '<html><body>Oh hi.</body></html>' +
+        '\r\n--__BOUNDARY__\r\n\r\n' +
+        'Oh hi.' +
+        '\r\n--__BOUNDARY__--'
+        )
+    , method: "PUT"
+    , multipart:
+      [ {'content-type': 'text/html', 'body': '<html><body>Oh hi.</body></html>'}
+      , {'body': 'Oh hi.'}
+      ]
+    }
+  , testPutMultipartPreambleCRLF :
+    { resp: server.createPostValidator(
+        '\r\n--__BOUNDARY__\r\n' +
+        'content-type: text/html\r\n' +
+        '\r\n' +
+        '<html><body>Oh hi.</body></html>' +
+        '\r\n--__BOUNDARY__\r\n\r\n' +
+        'Oh hi.' +
+        '\r\n--__BOUNDARY__--'
+        )
+    , method: "PUT"
+    , preambleCRLF: true
+    , multipart:
+      [ {'content-type': 'text/html', 'body': '<html><body>Oh hi.</body></html>'}
+      , {'body': 'Oh hi.'}
+      ]
+    }
+  }
+
+s.listen(s.port, function () {
+
+  var counter = 0
+
+  for (i in tests) {
+    (function () {
+      var test = tests[i]
+      s.on('/'+i, test.resp)
+      test.uri = s.url + '/' + i
+      request(test, function (err, resp, body) {
+        if (err) throw err
+        if (test.expectBody) {
+          assert.deepEqual(test.expectBody, body)
+        }
+        counter = counter - 1;
+        if (counter === 0) {
+          console.log(Object.keys(tests).length+" tests passed.")
+          s.close()
+        }
+      })
+      counter++
+    })()
+  }
+})
+
Index: Dev/trunk/src/node_modules/request/tests/test-defaults.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-defaults.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-defaults.js	(revision 484)
@@ -0,0 +1,129 @@
+var server = require('./server')
+  , assert = require('assert')
+  , request = require('../index')
+  ;
+
+var s = server.createServer();
+
+s.listen(s.port, function () {
+  var counter = 0;
+  s.on('/get', function (req, resp) {
+    assert.equal(req.headers.foo, 'bar');
+    assert.equal(req.method, 'GET')
+    resp.writeHead(200, {'Content-Type': 'text/plain'});
+    resp.end('TESTING!');
+  });
+
+  // test get(string, function)
+  request.defaults({headers:{foo:"bar"}})(s.url + '/get', function (e, r, b){
+    if (e) throw e;
+    assert.deepEqual("TESTING!", b);
+    counter += 1;
+  });
+
+  s.on('/post', function (req, resp) {
+    assert.equal(req.headers.foo, 'bar');
+    assert.equal(req.headers['content-type'], null);
+    assert.equal(req.method, 'POST')
+    resp.writeHead(200, {'Content-Type': 'application/json'});
+    resp.end(JSON.stringify({foo:'bar'}));
+  });
+
+  // test post(string, object, function)
+  request.defaults({headers:{foo:"bar"}}).post(s.url + '/post', {json: true}, function (e, r, b){
+    if (e) throw e;
+    assert.deepEqual('bar', b.foo);
+    counter += 1;
+  });
+
+  s.on('/patch', function (req, resp) {
+    assert.equal(req.headers.foo, 'bar');
+    assert.equal(req.headers['content-type'], null);
+    assert.equal(req.method, 'PATCH')
+    resp.writeHead(200, {'Content-Type': 'application/json'});
+    resp.end(JSON.stringify({foo:'bar'}));
+  });
+
+  // test post(string, object, function)
+  request.defaults({headers:{foo:"bar"}}).patch(s.url + '/patch', {json: true}, function (e, r, b){
+    if (e) throw e;
+    assert.deepEqual('bar', b.foo);
+    counter += 1;
+  });
+
+  s.on('/post-body', function (req, resp) {
+    assert.equal(req.headers.foo, 'bar');
+    assert.equal(req.headers['content-type'], 'application/json');
+    assert.equal(req.method, 'POST')
+    resp.writeHead(200, {'Content-Type': 'application/json'});
+    resp.end(JSON.stringify({foo:'bar'}));
+  });
+
+  // test post(string, object, function) with body
+  request.defaults({headers:{foo:"bar"}}).post(s.url + '/post-body', {json: true, body:{bar:"baz"}}, function (e, r, b){
+    if (e) throw e;
+    assert.deepEqual('bar', b.foo);
+    counter += 1;
+  });
+
+  s.on('/del', function (req, resp) {
+    assert.equal(req.headers.foo, 'bar');
+    assert.equal(req.method, 'DELETE')
+    resp.writeHead(200, {'Content-Type': 'application/json'});
+    resp.end(JSON.stringify({foo:'bar'}));
+  });
+
+  // test .del(string, function)
+  request.defaults({headers:{foo:"bar"}, json:true}).del(s.url + '/del', function (e, r, b){
+    if (e) throw e;
+    assert.deepEqual('bar', b.foo);
+    counter += 1;
+  });
+
+  s.on('/head', function (req, resp) {
+    assert.equal(req.headers.foo, 'bar');
+    assert.equal(req.method, 'HEAD')
+    resp.writeHead(200, {'Content-Type': 'text/plain'});
+    resp.end();
+  });
+
+  // test head.(object, function)
+  request.defaults({headers:{foo:"bar"}}).head({uri: s.url + '/head'}, function (e, r, b){
+    if (e) throw e;
+    counter += 1;
+  });
+
+  s.on('/get_custom', function(req, resp) {
+    assert.equal(req.headers.foo, 'bar');
+    assert.equal(req.headers.x, 'y');
+    resp.writeHead(200, {'Content-Type': 'text/plain'});
+    resp.end();
+  });
+
+  // test custom request handler function
+  var defaultRequest = request.defaults({
+    headers:{foo:"bar"}
+    , body: 'TESTING!'
+  }, function(uri, options, callback) {
+    var params = request.initParams(uri, options, callback);
+    options = params.options;
+    options.headers.x = 'y';
+
+    return request(params.uri, params.options, params.callback);
+  });
+
+  var msg = 'defaults test failed. head request should throw earlier';
+  assert.throws(function() {
+    defaultRequest.head(s.url + '/get_custom', function(e, r, b) {
+      throw new Error(msg);
+    });
+    counter+=1;
+  }, msg);
+
+  defaultRequest.get(s.url + '/get_custom', function(e, r, b) {
+    if(e) throw e;
+    counter += 1;
+    console.log(counter.toString() + " tests passed.");
+    s.close();
+  });
+})
Index: Dev/trunk/src/node_modules/request/tests/test-digest-auth.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-digest-auth.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-digest-auth.js	(revision 484)
@@ -0,0 +1,69 @@
+var assert = require('assert')
+  , http = require('http')
+  , request = require('../index')
+  ;
+
+// Test digest auth
+// Using header values captured from interaction with Apache
+
+var numDigestRequests = 0;
+
+var digestServer = http.createServer(function (req, res) {
+  console.error('Digest auth server: ', req.method, req.url);
+  numDigestRequests++;
+
+  var ok;
+
+  if (req.headers.authorization) {
+    if (req.headers.authorization == 'Digest username="test", realm="Private", nonce="WpcHS2/TBAA=dffcc0dbd5f96d49a5477166649b7c0ae3866a93", uri="/test/", qop="auth", response="54753ce37c10cb20b09b769f0bed730e", nc="1", cnonce=""') {
+      ok = true;
+    } else {
+      // Bad auth header, don't send back WWW-Authenticate header
+      ok = false;
+    }
+  } else {
+    // No auth header, send back WWW-Authenticate header
+    ok = false;
+    res.setHeader('www-authenticate', 'Digest realm="Private", nonce="WpcHS2/TBAA=dffcc0dbd5f96d49a5477166649b7c0ae3866a93", algorithm=MD5, qop="auth"');
+  }
+
+  if (ok) {
+    console.log('request ok');
+    res.end('ok');
+  } else {
+    console.log('status=401');
+    res.statusCode = 401;
+    res.end('401');
+  }
+});
+
+digestServer.listen(6767);
+
+request({
+  'method': 'GET',
+  'uri': 'http://localhost:6767/test/',
+  'auth': {
+    'user': 'test',
+    'pass': 'testing',
+    'sendImmediately': false
+  }
+}, function(error, response, body) {
+  assert.equal(response.statusCode, 200);
+  assert.equal(numDigestRequests, 2);
+
+  // If we don't set sendImmediately = false, request will send basic auth
+  request({
+    'method': 'GET',
+    'uri': 'http://localhost:6767/test/',
+    'auth': {
+      'user': 'test',
+      'pass': 'testing'
+    }
+  }, function(error, response, body) {
+    assert.equal(response.statusCode, 401);
+    assert.equal(numDigestRequests, 3);
+
+    console.log('All tests passed');
+    digestServer.close();
+  });
+});
Index: Dev/trunk/src/node_modules/request/tests/test-emptyBody.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-emptyBody.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-emptyBody.js	(revision 484)
@@ -0,0 +1,20 @@
+var request = require('../index')
+  , http = require('http')
+  , assert = require('assert')
+  ;
+
+var s = http.createServer(function (req, resp) {
+  resp.statusCode = 200
+  resp.end('')
+}).listen(8080, function () {
+  var r = request('http://localhost:8080', function (e, resp, body) {
+    assert.equal(resp.statusCode, 200)
+    assert.equal(body, "")
+
+    var r2 = request({ url: 'http://localhost:8080', json: {} }, function (e, resp, body) {
+	    assert.equal(resp.statusCode, 200)
+	    assert.equal(body, undefined)
+	    s.close()
+ 	 });
+  })
+})
Index: Dev/trunk/src/node_modules/request/tests/test-errors.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-errors.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-errors.js	(revision 484)
@@ -0,0 +1,37 @@
+var server = require('./server')
+  , events = require('events')
+  , assert = require('assert')
+  , request = require('../index')
+  ;
+
+var local = 'http://localhost:8888/asdf'
+
+try {
+  request({uri:local, body:{}})
+  assert.fail("Should have throw") 
+} catch(e) {
+  assert.equal(e.message, 'Argument error, options.body.')
+}
+
+try {
+  request({uri:local, multipart: 'foo'})
+  assert.fail("Should have throw")
+} catch(e) {
+  assert.equal(e.message, 'Argument error, options.multipart.')
+}
+
+try {
+  request({uri:local, multipart: [{}]})
+  assert.fail("Should have throw")
+} catch(e) {
+  assert.equal(e.message, 'Body attribute missing in multipart.')
+}
+
+try {
+  request(local, {multipart: [{}]})
+  assert.fail("Should have throw")
+} catch(e) {
+  assert.equal(e.message, 'Body attribute missing in multipart.')
+}
+
+console.log("All tests passed.")
Index: Dev/trunk/src/node_modules/request/tests/test-follow-all-303.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-follow-all-303.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-follow-all-303.js	(revision 484)
@@ -0,0 +1,30 @@
+var request = require('../index');
+var http = require('http');
+var requests = 0;
+var assert = require('assert');
+
+var server = http.createServer(function (req, res) {
+  console.error(req.method, req.url);
+  requests ++;
+
+  if (req.method === 'POST') {
+    console.error('send 303');
+    res.setHeader('location', req.url);
+    res.statusCode = 303;
+    res.end('try again, i guess\n');
+  } else {
+    console.error('send 200')
+    res.end('ok: ' + requests);
+  }
+});
+server.listen(6767);
+
+request.post({ url: 'http://localhost:6767/foo',
+               followAllRedirects: true,
+               form: { foo: 'bar' } }, function (er, req, body) {
+  if (er) throw er;
+  assert.equal(body, 'ok: 2');
+  assert.equal(requests, 2);
+  console.error('ok - ' + process.version);
+  server.close();
+});
Index: Dev/trunk/src/node_modules/request/tests/test-follow-all.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-follow-all.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-follow-all.js	(revision 484)
@@ -0,0 +1,35 @@
+var request = require('../index');
+var http = require('http');
+var requests = 0;
+var assert = require('assert');
+
+var server = http.createServer(function (req, res) {
+  requests ++;
+
+  // redirect everything 3 times, no matter what.
+  var c = req.headers.cookie;
+
+  if (!c) c = 0;
+  else c = +c.split('=')[1] || 0;
+
+  if (c > 3) {
+    res.end('ok: '+requests);
+    return;
+  }
+
+  res.setHeader('set-cookie', 'c=' + (c + 1));
+  res.setHeader('location', req.url);
+  res.statusCode = 302;
+  res.end('try again, i guess\n');
+});
+server.listen(6767);
+
+request.post({ url: 'http://localhost:6767/foo',
+               followAllRedirects: true,
+               form: { foo: 'bar' } }, function (er, req, body) {
+  if (er) throw er;
+  assert.equal(body, 'ok: 5');
+  assert.equal(requests, 5);
+  console.error('ok - ' + process.version);
+  server.close();
+});
Index: Dev/trunk/src/node_modules/request/tests/test-form.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-form.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-form.js	(revision 484)
@@ -0,0 +1,79 @@
+var assert = require('assert')
+var http = require('http');
+var path = require('path');
+var mime = require('mime');
+var request = require('../index');
+var fs = require('fs');
+
+var remoteFile = 'http://nodejs.org/images/logo.png';
+
+var FIELDS = [
+  {name: 'my_field', value: 'my_value'},
+  {name: 'my_buffer', value: new Buffer([1, 2, 3])},
+  {name: 'my_file', value: fs.createReadStream(__dirname + '/unicycle.jpg')},
+  {name: 'remote_file', value: request(remoteFile) }
+];
+
+var server = http.createServer(function(req, res) {
+
+  // temp workaround
+  var data = '';
+  req.setEncoding('utf8');
+
+  req.on('data', function(d) {
+    data += d;
+  });
+
+  req.on('end', function() {
+    // check for the fields' traces
+
+    // 1st field : my_field
+    var field = FIELDS.shift();
+    assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 );
+    assert.ok( data.indexOf(field.value) != -1 );
+
+    // 2nd field : my_buffer
+    var field = FIELDS.shift();
+    assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 );
+    assert.ok( data.indexOf(field.value) != -1 );
+
+    // 3rd field : my_file
+    var field = FIELDS.shift();
+    assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 );
+    assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 );
+    // check for unicycle.jpg traces
+    assert.ok( data.indexOf('2005:06:21 01:44:12') != -1 );
+    assert.ok( data.indexOf('Content-Type: '+mime.lookup(field.value.path) ) != -1 );
+
+    // 4th field : remote_file
+    var field = FIELDS.shift();
+    assert.ok( data.indexOf('form-data; name="'+field.name+'"') != -1 );
+    assert.ok( data.indexOf('; filename="'+path.basename(field.value.path)+'"') != -1 );
+    // check for http://nodejs.org/images/logo.png traces
+    assert.ok( data.indexOf('ImageReady') != -1 );
+    assert.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 );
+
+    res.writeHead(200);
+    res.end('done');
+
+  });
+
+
+});
+
+server.listen(8080, function() {
+
+  var req = request.post('http://localhost:8080/upload', function () {
+    server.close();
+  })
+  var form = req.form()
+  
+  FIELDS.forEach(function(field) {
+    form.append(field.name, field.value);
+  });
+
+});
+
+process.on('exit', function() {
+  assert.strictEqual(FIELDS.length, 0);
+});
Index: Dev/trunk/src/node_modules/request/tests/test-hawk.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-hawk.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-hawk.js	(revision 484)
@@ -0,0 +1,33 @@
+var createServer = require('http').createServer
+  , request = require('../index')
+  , hawk = require('hawk')
+  , assert = require('assert')
+  ;
+
+var server = createServer(function (req, resp) {
+  
+  var getCred = function (id, callback) {
+    assert.equal(id, 'dh37fgj492je')
+    var credentials = 
+      { key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn'
+      , algorithm: 'sha256'
+      , user: 'Steve'
+      }
+    return callback(null, credentials)
+  }
+
+  hawk.server.authenticate(req, getCred, {}, function (err, credentials, attributes) {
+    resp.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' })
+    resp.end(!err ? 'Hello ' + credentials.user : 'Shoosh!')
+  })
+  
+})
+
+server.listen(8080, function () {
+  var creds = {key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn', algorithm: 'sha256', id:'dh37fgj492je'}
+  request('http://localhost:8080', {hawk:{credentials:creds}}, function (e, r, b) {
+    assert.equal(200, r.statusCode)
+    assert.equal(b, 'Hello Steve')
+    server.close()
+  })
+})
Index: Dev/trunk/src/node_modules/request/tests/test-headers.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-headers.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-headers.js	(revision 484)
@@ -0,0 +1,52 @@
+var server = require('./server')
+  , assert = require('assert')
+  , request = require('../index')
+  , Cookie = require('cookie-jar')
+  , Jar = Cookie.Jar
+  , s = server.createServer()
+
+s.listen(s.port, function () {
+  var serverUri = 'http://localhost:' + s.port
+    , numTests = 0
+    , numOutstandingTests = 0
+
+  function createTest(requestObj, serverAssertFn) {
+    var testNumber = numTests;
+    numTests += 1;
+    numOutstandingTests += 1;
+    s.on('/' + testNumber, function (req, res) {
+      serverAssertFn(req, res);
+      res.writeHead(200);
+      res.end();
+    });
+    requestObj.url = serverUri + '/' + testNumber
+    request(requestObj, function (err, res, body) {
+      assert.ok(!err)
+      assert.equal(res.statusCode, 200)
+      numOutstandingTests -= 1
+      if (numOutstandingTests === 0) {
+        console.log(numTests + ' tests passed.')
+        s.close()
+      }
+    })
+  }
+
+  // Issue #125: headers.cookie shouldn't be replaced when a cookie jar isn't specified
+  createTest({headers: {cookie: 'foo=bar'}}, function (req, res) {
+    assert.ok(req.headers.cookie)
+    assert.equal(req.headers.cookie, 'foo=bar')
+  })
+
+  // Issue #125: headers.cookie + cookie jar
+  var jar = new Jar()
+  jar.add(new Cookie('quux=baz'));
+  createTest({jar: jar, headers: {cookie: 'foo=bar'}}, function (req, res) {
+    assert.ok(req.headers.cookie)
+    assert.equal(req.headers.cookie, 'foo=bar; quux=baz')
+  })
+
+  // There should be no cookie header when neither headers.cookie nor a cookie jar is specified
+  createTest({}, function (req, res) {
+    assert.ok(!req.headers.cookie)
+  })
+})
Index: Dev/trunk/src/node_modules/request/tests/test-http-signature.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-http-signature.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-http-signature.js	(revision 484)
@@ -0,0 +1,106 @@
+var createServer = require('http').createServer
+  , request = require('../index')
+  , httpSignature = require('http-signature')
+  , assert = require('assert')
+  ;
+
+var privateKeyPEMs = {}
+
+privateKeyPEMs['key-1'] =
+  '-----BEGIN RSA PRIVATE KEY-----\n' +
+  'MIIEpAIBAAKCAQEAzWSJl+Z9Bqv00FVL5N3+JCUoqmQPjIlya1BbeqQroNQ5yG1i\n' +
+  'VbYTTnMRa1zQtR6r2fNvWeg94DvxivxIG9diDMnrzijAnYlTLOl84CK2vOxkj5b6\n' +
+  '8zrLH9b/Gd6NOHsywo8IjvXvCeTfca5WUHcuVi2lT9VjygFs1ILG4RyeX1BXUumu\n' +
+  'Y8fzmposxLYdMxCqUTzAn0u9Saq2H2OVj5u114wS7OQPigu6G99dpn/iPHa3zBm8\n' +
+  '7baBWDbqZWRW0BP3K6eqq8sut1+NLhNW8ADPTdnO/SO+kvXy7fqd8atSn+HlQcx6\n' +
+  'tW42dhXf3E9uE7K78eZtW0KvfyNGAjsI1Fft2QIDAQABAoIBAG1exe3/LEBrPLfb\n' +
+  'U8iRdY0lxFvHYIhDgIwohC3wUdMYb5SMurpNdEZn+7Sh/fkUVgp/GKJViu1mvh52\n' +
+  'bKd2r52DwG9NQBQjVgkqY/auRYSglIPpr8PpYNSZlcneunCDGeqEY9hMmXc5Ssqs\n' +
+  'PQYoEKKPN+IlDTg6PguDgAfLR4IUvt9KXVvmB/SSgV9tSeTy35LECt1Lq3ozbUgu\n' +
+  '30HZI3U6/7H+X22Pxxf8vzBtzkg5rRCLgv+OeNPo16xMnqbutt4TeqEkxRv5rtOo\n' +
+  '/A1i9khBeki0OJAFJsE82qnaSZodaRsxic59VnN8sWBwEKAt87tEu5A3K3j4XSDU\n' +
+  '/avZxAECgYEA+pS3DvpiQLtHlaO3nAH6MxHRrREOARXWRDe5nUQuUNpS1xq9wte6\n' +
+  'DkFtba0UCvDLic08xvReTCbo9kH0y6zEy3zMpZuJlKbcWCkZf4S5miYPI0RTZtF8\n' +
+  'yps6hWqzYFSiO9hMYws9k4OJLxX0x3sLK7iNZ32ujcSrkPBSiBr0gxkCgYEA0dWl\n' +
+  '637K41AJ/zy0FP0syq+r4eIkfqv+/t6y2aQVUBvxJYrj9ci6XHBqoxpDV8lufVYj\n' +
+  'fUAfeI9/MZaWvQJRbnYLre0I6PJfLuCBIL5eflO77BGso165AF7QJZ+fwtgKv3zv\n' +
+  'ZX75eudCSS/cFo0po9hlbcLMT4B82zEkgT8E2MECgYEAnz+3/wrdOmpLGiyL2dff\n' +
+  '3GjsqmJ2VfY8z+niSrI0BSpbD11tT9Ct67VlCBjA7hsOH6uRfpd6/kaUMzzDiFVq\n' +
+  'VDAiFvV8QD6zNkwYalQ9aFvbrvwTTPrBpjl0vamMCiJ/YC0cjq1sGr2zh3sar1Ph\n' +
+  'S43kP+s97dcZeelhaiJHVrECgYEAsx61q/loJ/LDFeYzs1cLTVn4V7I7hQY9fkOM\n' +
+  'WM0AhInVqD6PqdfXfeFYpjJdGisQ7l0BnoGGW9vir+nkcyPvb2PFRIr6+B8tsU5j\n' +
+  '7BeVgjDoUfQkcrEBK5fEBtnj/ud9BUkY8oMZZBjVNLRuI7IMwZiPvMp0rcj4zAN/\n' +
+  'LfUlpgECgYArBvFcBxSkNAzR3Rtteud1YDboSKluRM37Ey5plrn4BS0DD0jm++aD\n' +
+  '0pG2Hsik000hibw92lCkzvvBVAqF8BuAcnPlAeYfsOaa97PGEjSKEN5bJVWZ9/om\n' +
+  '9FV1axotRN2XWlwrhixZLEaagkREXhgQc540FS5O8IaI2Vpa80Atzg==\n' +
+  '-----END RSA PRIVATE KEY-----'
+
+var publicKeyPEMs = {}
+
+publicKeyPEMs['key-1'] =
+  '-----BEGIN PUBLIC KEY-----\n' +
+  'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzWSJl+Z9Bqv00FVL5N3+\n' +
+  'JCUoqmQPjIlya1BbeqQroNQ5yG1iVbYTTnMRa1zQtR6r2fNvWeg94DvxivxIG9di\n' +
+  'DMnrzijAnYlTLOl84CK2vOxkj5b68zrLH9b/Gd6NOHsywo8IjvXvCeTfca5WUHcu\n' +
+  'Vi2lT9VjygFs1ILG4RyeX1BXUumuY8fzmposxLYdMxCqUTzAn0u9Saq2H2OVj5u1\n' +
+  '14wS7OQPigu6G99dpn/iPHa3zBm87baBWDbqZWRW0BP3K6eqq8sut1+NLhNW8ADP\n' +
+  'TdnO/SO+kvXy7fqd8atSn+HlQcx6tW42dhXf3E9uE7K78eZtW0KvfyNGAjsI1Fft\n' +
+  '2QIDAQAB\n' +
+  '-----END PUBLIC KEY-----'
+
+publicKeyPEMs['key-2'] =
+  '-----BEGIN PUBLIC KEY-----\n' +
+  'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqp04VVr9OThli9b35Omz\n' +
+  'VqSfWbsoQuRrgyWsrNRn3XkFmbWw4FzZwQ42OgGMzQ84Ta4d9zGKKQyFriTiPjPf\n' +
+  'xhhrsaJnDuybcpVhcr7UNKjSZ0S59tU3hpRiEz6hO+Nc/OSSLkvalG0VKrxOln7J\n' +
+  'LK/h3rNS/l6wDZ5S/KqsI6CYtV2ZLpn3ahLrizvEYNY038Qcm38qMWx+VJAvZ4di\n' +
+  'qqmW7RLIsLT59SWmpXdhFKnkYYGhxrk1Mwl22dBTJNY5SbriU5G3gWgzYkm8pgHr\n' +
+  '6CtrXch9ciJAcDJehPrKXNvNDOdUh8EW3fekNJerF1lWcwQg44/12v8sDPyfbaKB\n' +
+  'dQIDAQAB\n' +
+  '-----END PUBLIC KEY-----'
+
+var server = createServer(function (req, res) {
+  var parsed = httpSignature.parseRequest(req)
+  var publicKeyPEM = publicKeyPEMs[parsed.keyId]
+  var verified = httpSignature.verifySignature(parsed, publicKeyPEM)
+  res.writeHead(verified ? 200 : 400)
+  res.end()
+})
+
+server.listen(8080, function () {
+  function correctKeyTest(callback) {
+    var options = {
+      httpSignature: {
+        keyId: 'key-1',
+        key: privateKeyPEMs['key-1']
+      }
+    }
+    request('http://localhost:8080', options, function (e, r, b) {
+      assert.equal(200, r.statusCode)
+      callback()
+    })
+  }
+
+  function incorrectKeyTest(callback) {
+    var options = {
+      httpSignature: {
+        keyId: 'key-2',
+        key: privateKeyPEMs['key-1']
+      }
+    }
+    request('http://localhost:8080', options, function (e, r, b) {
+      assert.equal(400, r.statusCode)
+      callback()
+    })
+  }
+
+  var tests = [correctKeyTest, incorrectKeyTest]
+  var todo = tests.length;
+  for(var i = 0; i < tests.length; ++i) {
+    tests[i](function() {
+      if(!--todo) {
+        server.close()
+      }
+    })
+  }
+})
Index: Dev/trunk/src/node_modules/request/tests/test-httpModule.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-httpModule.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-httpModule.js	(revision 484)
@@ -0,0 +1,94 @@
+var http = require('http')
+  , https = require('https')
+  , server = require('./server')
+  , assert = require('assert')
+  , request = require('../index')
+
+
+var faux_requests_made = {'http':0, 'https':0}
+function wrap_request(name, module) {
+  // Just like the http or https module, but note when a request is made.
+  var wrapped = {}
+  Object.keys(module).forEach(function(key) {
+    var value = module[key];
+
+    if(key != 'request')
+      wrapped[key] = value;
+    else
+      wrapped[key] = function(options, callback) {
+        faux_requests_made[name] += 1
+        return value.apply(this, arguments)
+      }
+  })
+
+  return wrapped;
+}
+
+
+var faux_http = wrap_request('http', http)
+  , faux_https = wrap_request('https', https)
+  , plain_server = server.createServer()
+  , https_server = server.createSSLServer()
+
+
+plain_server.listen(plain_server.port, function() {
+  plain_server.on('/plain', function (req, res) {
+    res.writeHead(200)
+    res.end('plain')
+  })
+  plain_server.on('/to_https', function (req, res) {
+    res.writeHead(301, {'location':'https://localhost:'+https_server.port + '/https'})
+    res.end()
+  })
+
+  https_server.listen(https_server.port, function() {
+    https_server.on('/https', function (req, res) {
+      res.writeHead(200)
+      res.end('https')
+    })
+    https_server.on('/to_plain', function (req, res) {
+      res.writeHead(302, {'location':'http://localhost:'+plain_server.port + '/plain'})
+      res.end()
+    })
+
+    run_tests()
+    run_tests({})
+    run_tests({'http:':faux_http})
+    run_tests({'https:':faux_https})
+    run_tests({'http:':faux_http, 'https:':faux_https})
+  })
+})
+
+function run_tests(httpModules) {
+  var to_https = 'http://localhost:'+plain_server.port+'/to_https'
+  var to_plain = 'https://localhost:'+https_server.port+'/to_plain'
+
+  request(to_https, {'httpModules':httpModules, strictSSL:false}, function (er, res, body) {
+    if (er) throw er
+    assert.equal(body, 'https', 'Received HTTPS server body')
+    done()
+  })
+
+  request(to_plain, {'httpModules':httpModules, strictSSL:false}, function (er, res, body) {
+    if (er) throw er
+    assert.equal(body, 'plain', 'Received HTTPS server body')
+    done()
+  })
+}
+
+
+var passed = 0;
+function done() {
+  passed += 1
+  var expected = 10
+
+  if(passed == expected) {
+    plain_server.close()
+    https_server.close()
+
+    assert.equal(faux_requests_made.http, 4, 'Wrapped http module called appropriately')
+    assert.equal(faux_requests_made.https, 4, 'Wrapped https module called appropriately')
+
+    console.log((expected+2) + ' tests passed.')
+  }
+}
Index: Dev/trunk/src/node_modules/request/tests/test-https-strict.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-https-strict.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-https-strict.js	(revision 484)
@@ -0,0 +1,97 @@
+// a test where we validate the siguature of the keys
+// otherwise exactly the same as the ssl test
+
+var server = require('./server')
+  , assert = require('assert')
+  , request = require('../index')
+  , fs = require('fs')
+  , path = require('path')
+  , opts = { key: path.resolve(__dirname, 'ssl/ca/server.key')
+           , cert: path.resolve(__dirname, 'ssl/ca/server.crt') }
+  , s = server.createSSLServer(null, opts)
+  , caFile = path.resolve(__dirname, 'ssl/ca/ca.crt')
+  , ca = fs.readFileSync(caFile)
+
+var tests =
+  { testGet :
+    { resp : server.createGetResponse("TESTING!")
+    , expectBody: "TESTING!"
+    }
+  , testGetChunkBreak :
+    { resp : server.createChunkResponse(
+      [ new Buffer([239])
+      , new Buffer([163])
+      , new Buffer([191])
+      , new Buffer([206])
+      , new Buffer([169])
+      , new Buffer([226])
+      , new Buffer([152])
+      , new Buffer([131])
+      ])
+    , expectBody: "ï£¿Î©â"
+    }
+  , testGetJSON :
+    { resp : server.createGetResponse('{"test":true}', 'application/json')
+    , json : true
+    , expectBody: {"test":true}
+    }
+  , testPutString :
+    { resp : server.createPostValidator("PUTTINGDATA")
+    , method : "PUT"
+    , body : "PUTTINGDATA"
+    }
+  , testPutBuffer :
+    { resp : server.createPostValidator("PUTTINGDATA")
+    , method : "PUT"
+    , body : new Buffer("PUTTINGDATA")
+    }
+  , testPutJSON :
+    { resp : server.createPostValidator(JSON.stringify({foo: 'bar'}))
+    , method: "PUT"
+    , json: {foo: 'bar'}
+    }
+  , testPutMultipart :
+    { resp: server.createPostValidator(
+        '--__BOUNDARY__\r\n' +
+        'content-type: text/html\r\n' +
+        '\r\n' +
+        '<html><body>Oh hi.</body></html>' +
+        '\r\n--__BOUNDARY__\r\n\r\n' +
+        'Oh hi.' +
+        '\r\n--__BOUNDARY__--'
+        )
+    , method: "PUT"
+    , multipart:
+      [ {'content-type': 'text/html', 'body': '<html><body>Oh hi.</body></html>'}
+      , {'body': 'Oh hi.'}
+      ]
+    }
+  }
+
+s.listen(s.port, function () {
+
+  var counter = 0
+
+  for (i in tests) {
+    (function () {
+      var test = tests[i]
+      s.on('/'+i, test.resp)
+      test.uri = s.url + '/' + i
+      test.strictSSL = true
+      test.ca = ca
+      test.headers = { host: 'testing.request.mikealrogers.com' }
+      request(test, function (err, resp, body) {
+        if (err) throw err
+        if (test.expectBody) {
+          assert.deepEqual(test.expectBody, body)
+        }
+        counter = counter - 1;
+        if (counter === 0) {
+          console.log(Object.keys(tests).length+" tests passed.")
+          s.close()
+        }
+      })
+      counter++
+    })()
+  }
+})
Index: Dev/trunk/src/node_modules/request/tests/test-https.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-https.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-https.js	(revision 484)
@@ -0,0 +1,87 @@
+var server = require('./server')
+  , assert = require('assert')
+  , request = require('../index')
+
+var s = server.createSSLServer();
+
+var tests =
+  { testGet :
+    { resp : server.createGetResponse("TESTING!")
+    , expectBody: "TESTING!"
+    }
+  , testGetChunkBreak :
+    { resp : server.createChunkResponse(
+      [ new Buffer([239])
+      , new Buffer([163])
+      , new Buffer([191])
+      , new Buffer([206])
+      , new Buffer([169])
+      , new Buffer([226])
+      , new Buffer([152])
+      , new Buffer([131])
+      ])
+    , expectBody: "ï£¿Î©â"
+    }
+  , testGetJSON :
+    { resp : server.createGetResponse('{"test":true}', 'application/json')
+    , json : true
+    , expectBody: {"test":true}
+    }
+  , testPutString :
+    { resp : server.createPostValidator("PUTTINGDATA")
+    , method : "PUT"
+    , body : "PUTTINGDATA"
+    }
+  , testPutBuffer :
+    { resp : server.createPostValidator("PUTTINGDATA")
+    , method : "PUT"
+    , body : new Buffer("PUTTINGDATA")
+    }
+  , testPutJSON :
+    { resp : server.createPostValidator(JSON.stringify({foo: 'bar'}))
+    , method: "PUT"
+    , json: {foo: 'bar'}
+    }
+  , testPutMultipart :
+    { resp: server.createPostValidator(
+        '--__BOUNDARY__\r\n' +
+        'content-type: text/html\r\n' +
+        '\r\n' +
+        '<html><body>Oh hi.</body></html>' +
+        '\r\n--__BOUNDARY__\r\n\r\n' +
+        'Oh hi.' +
+        '\r\n--__BOUNDARY__--'
+        )
+    , method: "PUT"
+    , multipart:
+      [ {'content-type': 'text/html', 'body': '<html><body>Oh hi.</body></html>'}
+      , {'body': 'Oh hi.'}
+      ]
+    }
+  }
+
+s.listen(s.port, function () {
+
+  var counter = 0
+
+  for (i in tests) {
+    (function () {
+      var test = tests[i]
+      s.on('/'+i, test.resp)
+      test.uri = s.url + '/' + i
+      test.rejectUnauthorized = false
+      request(test, function (err, resp, body) {
+        if (err) throw err
+        if (test.expectBody) {
+          assert.deepEqual(test.expectBody, body)
+        }
+        counter = counter - 1;
+        if (counter === 0) {
+          console.log(Object.keys(tests).length+" tests passed.")
+          s.close()
+        }
+      })
+      counter++
+    })()
+  }
+})
Index: Dev/trunk/src/node_modules/request/tests/test-localAddress.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-localAddress.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-localAddress.js	(revision 484)
@@ -0,0 +1,15 @@
+var request = require('../index')
+  , assert = require('assert')
+  ;
+
+request.get({
+  uri: 'http://www.google.com', localAddress: '1.2.3.4' // some invalid address
+}, function(err, res) {
+  assert(!res) // asserting that no response received
+})
+
+request.get({
+  uri: 'http://www.google.com', localAddress: '127.0.0.1'
+}, function(err, res) {
+  assert(!res) // asserting that no response received
+})
Index: Dev/trunk/src/node_modules/request/tests/test-oauth.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-oauth.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-oauth.js	(revision 484)
@@ -0,0 +1,117 @@
+var hmacsign = require('oauth-sign').hmacsign
+  , assert = require('assert')
+  , qs = require('querystring')
+  , request = require('../index')
+  ;
+
+function getsignature (r) {
+  var sign
+  r.headers.Authorization.slice('OAuth '.length).replace(/,\ /g, ',').split(',').forEach(function (v) {
+    if (v.slice(0, 'oauth_signature="'.length) === 'oauth_signature="') sign = v.slice('oauth_signature="'.length, -1)
+  })
+  return decodeURIComponent(sign)
+}
+
+// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth
+
+var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', 
+  { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11'
+  , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g'
+  , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk'
+  , oauth_signature_method: 'HMAC-SHA1'
+  , oauth_timestamp: '1272323042'
+  , oauth_version: '1.0'
+  }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98")
+
+console.log(reqsign)
+console.log('8wUi7m5HFQy76nowoCThusfgB+Q=')
+assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=')
+
+var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token',
+  { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g'
+  , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8'
+  , oauth_signature_method: 'HMAC-SHA1'
+  , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc'
+  , oauth_timestamp: '1272323047'
+  , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY'
+  , oauth_version: '1.0'
+  }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA")
+  
+console.log(accsign)
+console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=')
+assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=')
+
+var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', 
+  { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g"
+  , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y"
+  , oauth_signature_method: "HMAC-SHA1"
+  , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw"
+  , oauth_timestamp: "1272325550"
+  , oauth_version: "1.0"
+  , status: 'setting up my twitter ç§ã®ãããããèš­å®ãã'
+  }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA")
+
+console.log(upsign)
+console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=')
+assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=')
+
+
+var rsign = request.post(
+  { url: 'https://api.twitter.com/oauth/request_token'
+  , oauth: 
+    { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11'
+    , consumer_key: 'GDdmIQH6jhtmLUypg82g'
+    , nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk'
+    , timestamp: '1272323042'
+    , version: '1.0'
+    , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98"
+    }
+  })
+
+setTimeout(function () {
+  console.log(getsignature(rsign))
+  assert.equal(reqsign, getsignature(rsign))
+})
+
+var raccsign = request.post(
+  { url: 'https://api.twitter.com/oauth/access_token'
+  , oauth:  
+    { consumer_key: 'GDdmIQH6jhtmLUypg82g'
+    , nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8'
+    , signature_method: 'HMAC-SHA1'
+    , token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc'
+    , timestamp: '1272323047'
+    , verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY'
+    , version: '1.0'
+    , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98"
+    , token_secret: "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA" 
+    }
+  })
+
+setTimeout(function () {
+  console.log(getsignature(raccsign))
+  assert.equal(accsign, getsignature(raccsign))
+}, 1) 
+
+var rupsign = request.post(
+  { url: 'http://api.twitter.com/1/statuses/update.json' 
+  , oauth: 
+    { consumer_key: "GDdmIQH6jhtmLUypg82g"
+    , nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y"
+    , signature_method: "HMAC-SHA1"
+    , token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw"
+    , timestamp: "1272325550"
+    , version: "1.0"
+    , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98"
+    , token_secret: "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA"
+    }
+  , form: {status: 'setting up my twitter ç§ã®ãããããèš­å®ãã'} 
+  })
+setTimeout(function () {
+  console.log(getsignature(rupsign))
+  assert.equal(upsign, getsignature(rupsign))
+}, 1)
+
+
+
+
Index: Dev/trunk/src/node_modules/request/tests/test-onelineproxy.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-onelineproxy.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-onelineproxy.js	(revision 484)
@@ -0,0 +1,46 @@
+var http = require('http')
+  , assert = require('assert')
+  , request = require('../index')
+  ;
+
+var server = http.createServer(function (req, resp) {
+  resp.statusCode = 200
+  if (req.url === '/get') {
+    assert.equal(req.method, 'GET')
+    resp.write('content')
+    resp.end()
+    return
+  }
+  if (req.url === '/put') {
+    var x = ''
+    assert.equal(req.method, 'PUT')
+    req.on('data', function (chunk) {
+      x += chunk
+    })
+    req.on('end', function () {
+      assert.equal(x, 'content')
+      resp.write('success')
+      resp.end()
+    })
+    return
+  }
+  if (req.url === '/proxy') {
+    assert.equal(req.method, 'PUT')
+    return req.pipe(request('http://localhost:8080/put')).pipe(resp)
+  }
+
+  if (req.url === '/test') {
+    return request('http://localhost:8080/get').pipe(request.put('http://localhost:8080/proxy')).pipe(resp)
+  }
+  throw new Error('Unknown url', req.url)
+}).listen(8080, function () {
+  request('http://localhost:8080/test', function (e, resp, body) {
+    if (e) throw e
+    if (resp.statusCode !== 200) throw new Error('statusCode not 200 ' + resp.statusCode)
+    assert.equal(body, 'success')
+    server.close()
+  })
+})
+
+
+
Index: Dev/trunk/src/node_modules/request/tests/test-params.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-params.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-params.js	(revision 484)
@@ -0,0 +1,93 @@
+var server = require('./server')
+  , assert = require('assert')
+  , request = require('../index')
+  ;
+
+var s = server.createServer();
+
+var tests =
+  { testGet :
+    { resp : server.createGetResponse("TESTING!")
+    , expectBody: "TESTING!"
+    }
+    , testGetChunkBreak :
+      { resp : server.createChunkResponse(
+        [ new Buffer([239])
+        , new Buffer([163])
+        , new Buffer([191])
+        , new Buffer([206])
+        , new Buffer([169])
+        , new Buffer([226])
+        , new Buffer([152])
+        , new Buffer([131])
+        ])
+      , expectBody: "ï£¿Î©â"
+      }
+    , testGetBuffer :
+      { resp : server.createGetResponse(new Buffer("TESTING!"))
+      , encoding: null
+      , expectBody: new Buffer("TESTING!")
+      }
+    , testGetJSON :
+       { resp : server.createGetResponse('{"test":true}', 'application/json')
+       , json : true
+       , expectBody: {"test":true}
+       }
+    , testPutString :
+      { resp : server.createPostValidator("PUTTINGDATA")
+      , method : "PUT"
+      , body : "PUTTINGDATA"
+      }
+    , testPutBuffer :
+      { resp : server.createPostValidator("PUTTINGDATA")
+      , method : "PUT"
+      , body : new Buffer("PUTTINGDATA")
+      }
+    , testPutJSON :
+      { resp : server.createPostValidator(JSON.stringify({foo: 'bar'}))
+      , method: "PUT"
+      , json: {foo: 'bar'}
+      }
+    , testPutMultipart :
+      { resp: server.createPostValidator(
+          '--__BOUNDARY__\r\n' +
+          'content-type: text/html\r\n' +
+          '\r\n' +
+          '<html><body>Oh hi.</body></html>' +
+          '\r\n--__BOUNDARY__\r\n\r\n' +
+          'Oh hi.' +
+          '\r\n--__BOUNDARY__--'
+          )
+      , method: "PUT"
+      , multipart:
+        [ {'content-type': 'text/html', 'body': '<html><body>Oh hi.</body></html>'}
+        , {'body': 'Oh hi.'}
+        ]
+      }
+  }
+
+s.listen(s.port, function () {
+
+  var counter = 0
+
+  for (i in tests) {
+    (function () {
+      var test = tests[i]
+      s.on('/'+i, test.resp)
+      //test.uri = s.url + '/' + i
+      request(s.url + '/' + i, test, function (err, resp, body) {
+        if (err) throw err
+        if (test.expectBody) {
+          assert.deepEqual(test.expectBody, body)
+        }
+        counter = counter - 1;
+        if (counter === 0) {
+          assert.notEqual(typeof test.callback, 'function')
+          console.log(1 + Object.keys(tests).length+" tests passed.")
+          s.close()
+        }
+      })
+      counter++
+    })()
+  }
+})
Index: Dev/trunk/src/node_modules/request/tests/test-piped-redirect.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-piped-redirect.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-piped-redirect.js	(revision 484)
@@ -0,0 +1,42 @@
+var http = require('http')
+  , assert = require('assert')
+  , request = require('../index')
+  ;
+
+var portOne = 8968
+  , portTwo = 8969
+  ;
+
+
+// server one
+var s1 = http.createServer(function (req, resp) {
+  if (req.url == '/original') {
+    resp.writeHeader(302, {'location': '/redirected'})
+    resp.end()
+  } else if (req.url == '/redirected') {
+    resp.writeHeader(200, {'content-type': 'text/plain'})
+    resp.write('OK')
+    resp.end()
+  }
+
+}).listen(portOne);
+
+
+// server two
+var s2 = http.createServer(function (req, resp) {
+  var x = request('http://localhost:'+portOne+'/original')
+  req.pipe(x)
+  x.pipe(resp)
+
+}).listen(portTwo, function () {
+  var r = request('http://localhost:'+portTwo+'/original', function (err, res, body) {
+    assert.equal(body, 'OK')
+
+    s1.close()
+    s2.close()
+  });
+
+  // it hangs, so wait a second :)
+  r.timeout = 1000;
+
+})
Index: Dev/trunk/src/node_modules/request/tests/test-pipes.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-pipes.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-pipes.js	(revision 484)
@@ -0,0 +1,216 @@
+var server = require('./server')
+  , events = require('events')
+  , stream = require('stream')
+  , assert = require('assert')
+  , fs = require('fs')
+  , request = require('../index')
+  , path = require('path')
+  , util = require('util')
+  ;
+
+var s = server.createServer(3453);
+
+function ValidationStream(str) {
+  this.str = str
+  this.buf = ''
+  this.on('data', function (data) {
+    this.buf += data
+  })
+  this.on('end', function () {
+    assert.equal(this.str, this.buf)
+  })
+  this.writable = true
+}
+util.inherits(ValidationStream, stream.Stream)
+ValidationStream.prototype.write = function (chunk) {
+  this.emit('data', chunk)
+}
+ValidationStream.prototype.end = function (chunk) {
+  if (chunk) emit('data', chunk)
+  this.emit('end')
+}
+
+s.listen(s.port, function () {
+  counter = 0;
+
+  var check = function () {
+    counter = counter - 1
+    if (counter === 0) {
+      console.log('All tests passed.')
+      setTimeout(function () {
+        process.exit();
+      }, 500)
+    }
+  }
+
+  // Test pipeing to a request object
+  s.once('/push', server.createPostValidator("mydata"));
+
+  var mydata = new stream.Stream();
+  mydata.readable = true
+
+  counter++
+  var r1 = request.put({url:'http://localhost:3453/push'}, function () {
+    check();
+  })
+  mydata.pipe(r1)
+
+  mydata.emit('data', 'mydata');
+  mydata.emit('end');
+
+  // Test pipeing to a request object with a json body
+  s.once('/push-json', server.createPostValidator("{\"foo\":\"bar\"}", "application/json"));
+
+  var mybodydata = new stream.Stream();
+  mybodydata.readable = true
+
+  counter++
+  var r2 = request.put({url:'http://localhost:3453/push-json',json:true}, function () {
+    check();
+  })
+  mybodydata.pipe(r2)
+
+  mybodydata.emit('data', JSON.stringify({foo:"bar"}));
+  mybodydata.emit('end');
+
+  // Test pipeing from a request object.
+  s.once('/pull', server.createGetResponse("mypulldata"));
+
+  var mypulldata = new stream.Stream();
+  mypulldata.writable = true
+
+  counter++
+  request({url:'http://localhost:3453/pull'}).pipe(mypulldata)
+
+  var d = '';
+
+  mypulldata.write = function (chunk) {
+    d += chunk;
+  }
+  mypulldata.end = function () {
+    assert.equal(d, 'mypulldata');
+    check();
+  };
+
+
+  s.on('/cat', function (req, resp) {
+    if (req.method === "GET") {
+      resp.writeHead(200, {'content-type':'text/plain-test', 'content-length':4});
+      resp.end('asdf')
+    } else if (req.method === "PUT") {
+      assert.equal(req.headers['content-type'], 'text/plain-test');
+      assert.equal(req.headers['content-length'], 4)
+      var validate = '';
+
+      req.on('data', function (chunk) {validate += chunk})
+      req.on('end', function () {
+        resp.writeHead(201);
+        resp.end();
+        assert.equal(validate, 'asdf');
+        check();
+      })
+    }
+  })
+  s.on('/pushjs', function (req, resp) {
+    if (req.method === "PUT") {
+      assert.equal(req.headers['content-type'], 'application/javascript');
+      check();
+    }
+  })
+  s.on('/catresp', function (req, resp) {
+    request.get('http://localhost:3453/cat').pipe(resp)
+  })
+  s.on('/doodle', function (req, resp) {
+    if (req.headers['x-oneline-proxy']) {
+      resp.setHeader('x-oneline-proxy', 'yup')
+    }
+    resp.writeHead('200', {'content-type':'image/jpeg'})
+    fs.createReadStream(path.join(__dirname, 'googledoodle.jpg')).pipe(resp)
+  })
+  s.on('/onelineproxy', function (req, resp) {
+    var x = request('http://localhost:3453/doodle')
+    req.pipe(x)
+    x.pipe(resp)
+  })
+
+  counter++
+  fs.createReadStream(__filename).pipe(request.put('http://localhost:3453/pushjs'))
+
+  counter++
+  request.get('http://localhost:3453/cat').pipe(request.put('http://localhost:3453/cat'))
+
+  counter++
+  request.get('http://localhost:3453/catresp', function (e, resp, body) {
+    assert.equal(resp.headers['content-type'], 'text/plain-test');
+    assert.equal(resp.headers['content-length'], 4)
+    check();
+  })
+
+  var doodleWrite = fs.createWriteStream(path.join(__dirname, 'test.jpg'))
+
+  counter++
+  request.get('http://localhost:3453/doodle').pipe(doodleWrite)
+
+  doodleWrite.on('close', function () {
+    assert.deepEqual(fs.readFileSync(path.join(__dirname, 'googledoodle.jpg')), fs.readFileSync(path.join(__dirname, 'test.jpg')))
+    check()
+  })
+
+  process.on('exit', function () {
+    fs.unlinkSync(path.join(__dirname, 'test.jpg'))
+  })
+
+  counter++
+  request.get({uri:'http://localhost:3453/onelineproxy', headers:{'x-oneline-proxy':'nope'}}, function (err, resp, body) {
+    assert.equal(resp.headers['x-oneline-proxy'], 'yup')
+    check()
+  })
+
+  s.on('/afterresponse', function (req, resp) {
+    resp.write('d')
+    resp.end()
+  })
+
+  counter++
+  var afterresp = request.post('http://localhost:3453/afterresponse').on('response', function () {
+    var v = new ValidationStream('d')
+    afterresp.pipe(v)
+    v.on('end', check)
+  })
+  
+  s.on('/forward1', function (req, resp) {
+   resp.writeHead(302, {location:'/forward2'})
+    resp.end()
+  })
+  s.on('/forward2', function (req, resp) {
+    resp.writeHead('200', {'content-type':'image/png'})
+    resp.write('d')
+    resp.end()
+  })
+  
+  counter++
+  var validateForward = new ValidationStream('d')
+  validateForward.on('end', check)
+  request.get('http://localhost:3453/forward1').pipe(validateForward)
+
+  // Test pipe options
+  s.once('/opts', server.createGetResponse('opts response'));
+
+  var optsStream = new stream.Stream();
+  optsStream.writable = true
+  
+  var optsData = '';
+  optsStream.write = function (buf) {
+    optsData += buf;
+    if (optsData === 'opts response') {
+      setTimeout(check, 10);
+    }
+  }
+
+  optsStream.end = function () {
+    assert.fail('end called')
+  };
+
+  counter++
+  request({url:'http://localhost:3453/opts'}).pipe(optsStream, { end : false })
+})
Index: Dev/trunk/src/node_modules/request/tests/test-pool.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-pool.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-pool.js	(revision 484)
@@ -0,0 +1,16 @@
+var request = require('../index')
+  , http = require('http')
+  , assert = require('assert')
+  ;
+
+var s = http.createServer(function (req, resp) {
+  resp.statusCode = 200;
+  resp.end('asdf');
+}).listen(8080, function () {
+  request({'url': 'http://localhost:8080', 'pool': false}, function (e, resp) {
+    var agent = resp.request.agent;
+    assert.strictEqual(typeof agent, 'boolean');
+    assert.strictEqual(agent, false);
+    s.close();
+  });
+});
Index: Dev/trunk/src/node_modules/request/tests/test-protocol-changing-redirect.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-protocol-changing-redirect.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-protocol-changing-redirect.js	(revision 484)
@@ -0,0 +1,61 @@
+var server = require('./server')
+  , assert = require('assert')
+  , request = require('../index')
+
+
+var s = server.createServer()
+var ss = server.createSSLServer()
+var sUrl = 'http://localhost:' + s.port
+var ssUrl = 'https://localhost:' + ss.port
+
+s.listen(s.port, bouncy(s, ssUrl))
+ss.listen(ss.port, bouncy(ss, sUrl))
+
+var hits = {}
+var expect = {}
+var pending = 0
+function bouncy (s, server) { return function () {
+
+  var redirs = { a: 'b'
+               , b: 'c'
+               , c: 'd'
+               , d: 'e'
+               , e: 'f'
+               , f: 'g'
+               , g: 'h'
+               , h: 'end' }
+
+  var perm = true
+  Object.keys(redirs).forEach(function (p) {
+    var t = redirs[p]
+
+    // switch type each time
+    var type = perm ? 301 : 302
+    perm = !perm
+    s.on('/' + p, function (req, res) {
+      res.writeHead(type, { location: server + '/' + t })
+      res.end()
+    })
+  })
+
+  s.on('/end', function (req, res) {
+    var h = req.headers['x-test-key']
+    hits[h] = true
+    pending --
+    if (pending === 0) done()
+  })
+}}
+
+for (var i = 0; i < 5; i ++) {
+  pending ++
+  var val = 'test_' + i
+  expect[val] = true
+  request({ url: (i % 2 ? sUrl : ssUrl) + '/a'
+          , headers: { 'x-test-key': val }
+          , rejectUnauthorized: false })
+}
+
+function done () {
+  assert.deepEqual(hits, expect)
+  process.exit(0)
+}
Index: Dev/trunk/src/node_modules/request/tests/test-proxy.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-proxy.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-proxy.js	(revision 484)
@@ -0,0 +1,39 @@
+var server = require('./server')
+  , events = require('events')
+  , stream = require('stream')
+  , assert = require('assert')
+  , fs = require('fs')
+  , request = require('../index')
+  , path = require('path')
+  , util = require('util')
+  ;
+
+var port = 6768
+  , called = false
+  , proxiedHost = 'google.com'
+  ;
+
+var s = server.createServer(port)
+s.listen(port, function () {
+  s.on('http://google.com/', function (req, res) {
+    called = true
+    assert.equal(req.headers.host, proxiedHost)
+    res.writeHeader(200)
+    res.end()
+  })
+  request ({
+    url: 'http://'+proxiedHost,
+    proxy: 'http://localhost:'+port
+    /*
+    //should behave as if these arguments where passed:
+    url: 'http://localhost:'+port,
+    headers: {host: proxiedHost}
+    //*/
+  }, function (err, res, body) {
+    s.close()
+  })
+})
+
+process.on('exit', function () {
+  assert.ok(called, 'the request must be made to the proxy server')
+})
Index: Dev/trunk/src/node_modules/request/tests/test-qs.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-qs.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-qs.js	(revision 484)
@@ -0,0 +1,42 @@
+var request = request = require('../index')
+  , assert = require('assert')
+  ;
+ 
+
+// Test adding a querystring
+var req1 = request.get({ uri: 'http://www.google.com', qs: { q : 'search' }})
+setTimeout(function() {
+	assert.equal('/?q=search', req1.path)
+}, 1)
+
+// Test replacing a querystring value
+var req2 = request.get({ uri: 'http://www.google.com?q=abc', qs: { q : 'search' }})
+setTimeout(function() {
+	assert.equal('/?q=search', req2.path)
+}, 1)
+
+// Test appending a querystring value to the ones present in the uri
+var req3 = request.get({ uri: 'http://www.google.com?x=y', qs: { q : 'search' }})
+setTimeout(function() {
+	assert.equal('/?x=y&q=search', req3.path)
+}, 1)
+
+// Test leaving a querystring alone
+var req4 = request.get({ uri: 'http://www.google.com?x=y'})
+setTimeout(function() {
+	assert.equal('/?x=y', req4.path)
+}, 1)
+
+// Test giving empty qs property
+var req5 = request.get({ uri: 'http://www.google.com', qs: {}})
+setTimeout(function(){
+	assert.equal('/', req5.path)
+}, 1)
+
+
+// Test modifying the qs after creating the request
+var req6 = request.get({ uri: 'http://www.google.com', qs: {}});
+req6.qs({ q: "test" });
+process.nextTick(function() {
+    assert.equal('/?q=test', req6.path);
+});
Index: Dev/trunk/src/node_modules/request/tests/test-redirect.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-redirect.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-redirect.js	(revision 484)
@@ -0,0 +1,155 @@
+var server = require('./server')
+  , assert = require('assert')
+  , request = require('../index')
+  , Cookie = require('cookie-jar')
+  , Jar = Cookie.Jar
+  ;
+
+var s = server.createServer()
+
+s.listen(s.port, function () {
+  var server = 'http://localhost:' + s.port;
+  var hits = {}
+  var passed = 0;
+
+  bouncer(301, 'temp')
+  bouncer(302, 'perm')
+  bouncer(302, 'nope')
+
+  function bouncer(code, label) {
+    var landing = label+'_landing';
+
+    s.on('/'+label, function (req, res) {
+      hits[label] = true;
+      res.writeHead(code, {
+        'location':server + '/'+landing,
+        'set-cookie': 'ham=eggs'
+      })
+      res.end()
+    })
+
+    s.on('/'+landing, function (req, res) {
+      if (req.method !== 'GET') { // We should only accept GET redirects
+        console.error("Got a non-GET request to the redirect destination URL");
+        res.writeHead(400);
+        res.end();
+        return;
+      }
+      // Make sure the cookie doesn't get included twice, see #139:
+      // Make sure cookies are set properly after redirect
+      assert.equal(req.headers.cookie, 'foo=bar; quux=baz; ham=eggs');
+      hits[landing] = true;
+      res.writeHead(200)
+      res.end(landing)
+    })
+  }
+
+  // Permanent bounce
+  var jar = new Jar()
+  jar.add(new Cookie('quux=baz'))
+  request({uri: server+'/perm', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) {
+    if (er) throw er
+    if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode)
+    assert.ok(hits.perm, 'Original request is to /perm')
+    assert.ok(hits.perm_landing, 'Forward to permanent landing URL')
+    assert.equal(body, 'perm_landing', 'Got permanent landing content')
+    passed += 1
+    done()
+  })
+  
+  // Temporary bounce
+  request({uri: server+'/temp', jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) {
+    if (er) throw er
+    if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode)
+    assert.ok(hits.temp, 'Original request is to /temp')
+    assert.ok(hits.temp_landing, 'Forward to temporary landing URL')
+    assert.equal(body, 'temp_landing', 'Got temporary landing content')
+    passed += 1
+    done()
+  })
+  
+  // Prevent bouncing.
+  request({uri:server+'/nope', jar: jar, headers: {cookie: 'foo=bar'}, followRedirect:false}, function (er, res, body) {
+    if (er) throw er
+    if (res.statusCode !== 302) throw new Error('Status is not 302: '+res.statusCode)
+    assert.ok(hits.nope, 'Original request to /nope')
+    assert.ok(!hits.nope_landing, 'No chasing the redirect')
+    assert.equal(res.statusCode, 302, 'Response is the bounce itself')
+    passed += 1
+    done()
+  })
+  
+  // Should not follow post redirects by default
+  request.post(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) {
+    if (er) throw er
+    if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode)
+    assert.ok(hits.temp, 'Original request is to /temp')
+    assert.ok(!hits.temp_landing, 'No chasing the redirect when post')
+    assert.equal(res.statusCode, 301, 'Response is the bounce itself')
+    passed += 1
+    done()
+  })
+  
+  // Should follow post redirects when followAllRedirects true
+  request.post({uri:server+'/temp', followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) {
+    if (er) throw er
+    if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode)
+    assert.ok(hits.temp, 'Original request is to /temp')
+    assert.ok(hits.temp_landing, 'Forward to temporary landing URL')
+    assert.equal(body, 'temp_landing', 'Got temporary landing content')
+    passed += 1
+    done()
+  })
+  
+  request.post({uri:server+'/temp', followAllRedirects:false, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) {
+    if (er) throw er
+    if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode)
+    assert.ok(hits.temp, 'Original request is to /temp')
+    assert.ok(!hits.temp_landing, 'No chasing the redirect')
+    assert.equal(res.statusCode, 301, 'Response is the bounce itself')
+    passed += 1
+    done()
+  })
+
+  // Should not follow delete redirects by default
+  request.del(server+'/temp', { jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) {
+    if (er) throw er
+    if (res.statusCode < 301) throw new Error('Status is not a redirect.')
+    assert.ok(hits.temp, 'Original request is to /temp')
+    assert.ok(!hits.temp_landing, 'No chasing the redirect when delete')
+    assert.equal(res.statusCode, 301, 'Response is the bounce itself')
+    passed += 1
+    done()
+  })
+  
+  // Should not follow delete redirects even if followRedirect is set to true
+  request.del(server+'/temp', { followRedirect: true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) {
+    if (er) throw er
+    if (res.statusCode !== 301) throw new Error('Status is not 301: '+res.statusCode)
+    assert.ok(hits.temp, 'Original request is to /temp')
+    assert.ok(!hits.temp_landing, 'No chasing the redirect when delete')
+    assert.equal(res.statusCode, 301, 'Response is the bounce itself')
+    passed += 1
+    done()
+  })
+  
+  // Should follow delete redirects when followAllRedirects true
+  request.del(server+'/temp', {followAllRedirects:true, jar: jar, headers: {cookie: 'foo=bar'}}, function (er, res, body) {
+    if (er) throw er
+    if (res.statusCode !== 200) throw new Error('Status is not 200: '+res.statusCode)
+    assert.ok(hits.temp, 'Original request is to /temp')
+    assert.ok(hits.temp_landing, 'Forward to temporary landing URL')
+    assert.equal(body, 'temp_landing', 'Got temporary landing content')
+    passed += 1
+    done()
+  })
+
+  var reqs_done = 0;
+  function done() {
+    reqs_done += 1;
+    if(reqs_done == 9) {
+      console.log(passed + ' tests passed.')
+      s.close()
+    }
+  }
+})
Index: Dev/trunk/src/node_modules/request/tests/test-s3.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-s3.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-s3.js	(revision 484)
@@ -0,0 +1,13 @@
+var request = require('../index')
+
+var r = request.get('https://log.curlybracecast.com.s3.amazonaws.com/', 
+  { aws: 
+    { key: 'AKIAI6KIQRRVMGK3WK5Q'
+    , secret: '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'
+    , bucket: 'log.curlybracecast.com'
+    }
+  }, function (e, resp, body) {
+    console.log(r.headers)
+    console.log(body)
+  }
+)
Index: Dev/trunk/src/node_modules/request/tests/test-timeout.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-timeout.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-timeout.js	(revision 484)
@@ -0,0 +1,87 @@
+var server = require('./server')
+  , events = require('events')
+  , stream = require('stream')
+  , assert = require('assert')
+  , request = require('../index')
+  ;
+
+var s = server.createServer();
+var expectedBody = "waited";
+var remainingTests = 5;
+
+s.listen(s.port, function () {
+  // Request that waits for 200ms
+  s.on('/timeout', function (req, resp) {
+    setTimeout(function(){
+      resp.writeHead(200, {'content-type':'text/plain'})
+      resp.write(expectedBody)
+      resp.end()
+    }, 200);
+  });
+
+  // Scenario that should timeout
+  var shouldTimeout = {
+    url: s.url + "/timeout",
+    timeout:100
+  }
+
+
+  request(shouldTimeout, function (err, resp, body) {
+    assert.equal(err.code, "ETIMEDOUT");
+    checkDone();
+  })
+
+
+  // Scenario that shouldn't timeout
+  var shouldntTimeout = {
+    url: s.url + "/timeout",
+    timeout:300
+  }
+
+  request(shouldntTimeout, function (err, resp, body) {
+    assert.equal(err, null);
+    assert.equal(expectedBody, body)
+    checkDone();
+  })
+
+  // Scenario with no timeout set, so shouldn't timeout
+  var noTimeout = {
+    url: s.url + "/timeout"
+  }
+
+  request(noTimeout, function (err, resp, body) {
+    assert.equal(err);
+    assert.equal(expectedBody, body)
+    checkDone();
+  })
+
+  // Scenario with a negative timeout value, should be treated a zero or the minimum delay
+  var negativeTimeout = {
+    url: s.url + "/timeout",
+    timeout:-1000
+  }
+
+  request(negativeTimeout, function (err, resp, body) {
+    assert.equal(err.code, "ETIMEDOUT");
+    checkDone();
+  })
+
+  // Scenario with a float timeout value, should be rounded by setTimeout anyway
+  var floatTimeout = {
+    url: s.url + "/timeout",
+    timeout: 100.76
+  }
+
+  request(floatTimeout, function (err, resp, body) {
+    assert.equal(err.code, "ETIMEDOUT");
+    checkDone();
+  })
+
+  function checkDone() {
+    if(--remainingTests == 0) {
+      s.close();
+      console.log("All tests passed.");
+    }
+  }
+})
+
Index: Dev/trunk/src/node_modules/request/tests/test-toJSON.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-toJSON.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-toJSON.js	(revision 484)
@@ -0,0 +1,14 @@
+var request = require('../index')
+  , http = require('http')
+  , assert = require('assert')
+  ;
+
+var s = http.createServer(function (req, resp) {
+  resp.statusCode = 200
+  resp.end('asdf')
+}).listen(8080, function () {
+  var r = request('http://localhost:8080', function (e, resp) {
+    assert.equal(JSON.parse(JSON.stringify(r)).response.statusCode, 200)
+    s.close()
+  })
+})
Index: Dev/trunk/src/node_modules/request/tests/test-tunnel.js
===================================================================
--- Dev/trunk/src/node_modules/request/tests/test-tunnel.js	(revision 484)
+++ Dev/trunk/src/node_modules/request/tests/test-tunnel.js	(revision 484)
@@ -0,0 +1,75 @@
+// test that we can tunnel a https request over an http proxy
+// keeping all the CA and whatnot intact.
+//
+// Note: this requires that squid is installed.
+// If the proxy fails to start, we'll just log a warning and assume success.
+
+var server = require('./server')
+  , assert = require('assert')
+  , request = require('../index')
+  , fs = require('fs')
+  , path = require('path')
+  , caFile = path.resolve(__dirname, 'ssl/npm-ca.crt')
+  , ca = fs.readFileSync(caFile)
+  , child_process = require('child_process')
+  , sqConf = path.resolve(__dirname, 'squid.conf')
+  , sqArgs = ['-f', sqConf, '-N', '-d', '5']
+  , proxy = 'http://localhost:3128'
+  , hadError = null
+
+var squid = child_process.spawn('squid', sqArgs);
+var ready = false
+
+squid.stderr.on('data', function (c) {
+  console.error('SQUIDERR ' + c.toString().trim().split('\n')
+               .join('\nSQUIDERR '))
+  ready = c.toString().match(/ready to serve requests|Accepting HTTP Socket connections/i)
+})
+
+squid.stdout.on('data', function (c) {
+  console.error('SQUIDOUT ' + c.toString().trim().split('\n')
+               .join('\nSQUIDOUT '))
+})
+
+squid.on('error', function (c) {
+  console.error('squid: error '+c)
+  if (c && !ready) {
+    notInstalled()
+    return
+  }
+})
+
+squid.on('exit', function (c) {
+  console.error('squid: exit '+c)
+  if (c && !ready) {
+    notInstalled()
+    return
+  }
+
+  if (c) {
+    hadError = hadError || new Error('Squid exited with '+c)
+  }
+  if (hadError) throw hadError
+})
+
+setTimeout(function F () {
+  if (!ready) return setTimeout(F, 100)
+  request({ uri: 'https://registry.npmjs.org/'
+          , proxy: 'http://localhost:3128'
+          , strictSSL: true
+          , ca: ca
+          , json: true }, function (er, body) {
+    hadError = er
+    console.log(er || typeof body)
+    if (!er) console.log("ok")
+    squid.kill('SIGKILL')
+  })
+}, 100)
+
+function notInstalled() {
+  console.error('squid must be installed to run this test.')
+  console.error('skipping this test. please install squid and run again if you need to test tunneling.')
+  c = null
+  hadError = null
+  process.exit(0)
+}
Index: Dev/trunk/src/node_modules/tv4/LICENSE.txt
===================================================================
--- Dev/trunk/src/node_modules/tv4/LICENSE.txt	(revision 484)
+++ Dev/trunk/src/node_modules/tv4/LICENSE.txt	(revision 484)
@@ -0,0 +1,8 @@
+/*
+Author: Geraint Luff and others
+Year: 2013
+
+This code is released into the "public domain" by its author(s).  Anybody may use, alter and distribute the code without restriction.  The author makes no guarantees, and takes no liability of any kind for use of this code.
+
+If you find a bug or make an improvement, it would be courteous to let the author know, but it is not compulsory.
+*/
Index: Dev/trunk/src/node_modules/tv4/README.md
===================================================================
--- Dev/trunk/src/node_modules/tv4/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/tv4/README.md	(revision 484)
@@ -0,0 +1,392 @@
+# Tiny Validator (for v4 JSON Schema)
+
+[![Build Status](https://secure.travis-ci.org/geraintluff/tv4.png?branch=master)](http://travis-ci.org/geraintluff/tv4) [![Dependency Status](https://gemnasium.com/geraintluff/tv4.png)](https://gemnasium.com/geraintluff/tv4) [![NPM version](https://badge.fury.io/js/tv4.png)](http://badge.fury.io/js/tv4)
+
+Use [json-schema](http://json-schema.org/) [draft v4](http://json-schema.org/latest/json-schema-core.html) to validate simple values and complex objects using a rich [validation vocabulary](http://json-schema.org/latest/json-schema-validation.html) ([examples](http://json-schema.org/examples.html)).
+
+There is support for `$ref` with JSON Pointer fragment paths (```other-schema.json#/properties/myKey```).
+
+## Usage 1: Simple validation
+
+```javascript
+var valid = tv4.validate(data, schema);
+```
+
+If validation returns ```false```, then an explanation of why validation failed can be found in ```tv4.error```.
+
+The error object will look something like:
+```json
+{
+    "code": 0,
+    "message": "Invalid type: string",
+    "dataPath": "/intKey",
+    "schemaKey": "/properties/intKey/type"
+}
+```
+
+The `"code"` property will refer to one of the values in `tv4.errorCodes` - in this case, `tv4.errorCodes.INVALID_TYPE`.
+
+To enable external schema to be referenced, you use:
+```javascript
+tv4.addSchema(url, schema);
+```
+
+If schemas are referenced (```$ref```) but not known, then validation will return ```true``` and the missing schema(s) will be listed in ```tv4.missing```. For more info see the API documentation below.
+
+## Usage 2: Multi-threaded validation
+
+Storing the error and missing schemas does not work well in multi-threaded environments, so there is an alternative syntax:
+
+```javascript
+var result = tv4.validateResult(data, schema);
+```
+
+The result will look something like:
+```json
+{
+    "valid": false,
+    "error": {...},
+    "missing": [...]
+}
+```
+
+## Usage 3: Multiple errors
+
+Normally, `tv4` stops when it encounters the first validation error.  However, you can collect an array of validation errors using:
+
+```javascript
+var result = tv4.validateMultiple(data, schema);
+```
+
+The result will look something like:
+```json
+{
+    "valid": false,
+    "errors": [
+        {...},
+        ...
+    ],
+    "missing": [...]
+}
+```
+
+## Asynchronous validation
+
+Support for asynchronous validation (where missing schemas are fetched) can be added by including an extra JavaScript file.  Currently, the only version requires jQuery (`tv4.async-jquery.js`), but the code is very short and should be fairly easy to modify for other libraries (such as MooTools).
+
+Usage:
+
+```javascript
+tv4.validate(data, schema, function (isValid, validationError) { ... });
+```
+
+`validationFailure` is simply taken from `tv4.error`.
+
+## Cyclical JavaScript objects
+
+While they don't occur in proper JSON, JavaScript does support self-referencing objects. Any of the above calls support an optional final argument, checkRecursive. If true, tv4 will handle self-referencing objects properly - this slows down validation slightly, but that's better than a hanging script.
+
+Consider this data, notice how both `a` and `b` refer to each other:
+
+```javascript
+var a = {};
+var b = { a: a };
+a.b = b;
+var aSchema = { properties: { b: { $ref: 'bSchema' }}};
+var bSchema = { properties: { a: { $ref: 'aSchema' }}};
+tv4.addSchema('aSchema', aSchema);
+tv4.addSchema('bSchema', bSchema);
+```
+
+If the final checkRecursive argument were missing, this would throw a "too much recursion" error. 
+
+To enable supprot for this pass `true` as additional argument to any of the regular validation methods: 
+
+```javascript
+tv4.validate(a, aSchema, true);
+tv4.validate(a, schema, asynchronousFunction, true);
+
+tv4.validateResult(data, aSchema, true); 
+tv4.validateMultiple(data, aSchema, true);
+```
+
+## API
+
+There are additional api commands available for more complex use-cases:
+
+##### addSchema(uri, schema)
+Pre-register a schema for reference by other schema and synchronous validation.
+
+````js
+tv4.addSchema('http://example.com/schema', { ... });
+````
+
+* `uri` the uri to identify this schema.
+* `schema` the schema object.
+
+Schemas that have their `id` property set can be added directly.
+
+````js
+tv4.addSchema({ ... });
+````
+
+##### getSchema(uri)
+
+Return a schema from the cache.
+
+* `uri` the uri of the schema (may contain a `#` fragment)
+
+````js
+var schema = tv4.getSchema('http://example.com/schema');
+````
+
+##### getSchemaMap()
+
+Return a shallow copy of the schema cache, mapping schema document URIs to schema objects.
+
+````
+var map = tv4.getSchemaMap();
+
+var schema = map[uri];
+````
+
+##### getSchemaUris(filter)
+
+Return an Array with known schema document URIs.
+
+* `filter` optional RegExp to filter URIs
+
+````
+var arr = tv4.getSchemaUris();
+
+// optional filter using a RegExp
+var arr = tv4.getSchemaUris(/^https?://example.com/);
+````
+
+##### getMissingUris(filter)
+
+Return an Array with schema document URIs that are used as `$ref` in known schemas but which currently have no associated schema data.
+
+Use this in combination with `tv4.addSchema(uri, schema)` to preload the cache for complete synchronous validation with.
+
+* `filter` optional RegExp to filter URIs
+
+````
+var arr = tv4.getMissingUris();
+
+// optional filter using a RegExp
+var arr = tv4.getMissingUris(/^https?://example.com/);
+````
+
+##### dropSchemas()
+
+Drop all known schema document URIs from the cache.
+
+````
+tv4.dropSchemas();
+````
+
+##### freshApi()
+
+Return a new tv4 instance with no shared state.
+
+````
+var otherTV4 = tv4.freshApi();
+````
+
+##### reset()
+
+Manually reset validation status from the simple `tv4.validate(data, schema)`. Although tv4 will self reset on each validation there are some implementation scenarios where this is useful.
+
+````
+tv4.reset();
+````
+
+##### language(code)
+
+Select the language map used for reporting.
+
+* `code` is a language code, like `'en'` or `'en-gb'`
+
+````
+tv4.language('en-gb');
+````
+
+##### addLanguage(code, map)
+
+Add a new language map for selection by `tv4.language(code)`
+
+* `code` is new language code
+* `map` is an object mapping error IDs or constant names (e.g. `103` or `"NUMBER_MAXIMUM"`) to language strings.
+
+````
+tv4.addLanguage('fr', { ... });
+
+// select for use
+tv4.language('fr')
+````
+
+##### addFormat(format, validationFunction)
+
+Add a custom format validator.
+
+* `format` is a string, corresponding to the `"format"` value in schemas.
+* `validationFunction` is a function that either returns:
+  * `null` (meaning no error)
+  * an error string (explaining the reason for failure)
+
+````
+tv4.addFormat('decimal-digits', function (data, schema) {
+	if (typeof data === 'string' && !/^[0-9]+$/.test(data)) {
+		return null;
+	}
+	return "must be string of decimal digits";
+});
+````
+
+Alternatively, multiple formats can be added at the same time using an object:
+````
+tv4.addFormat({
+	'my-format': function () {...},
+	'other-format': function () {...}
+});
+````
+
+## Demos
+
+### Basic usage
+<div class="content inline-demo" markdown="1" data-demo="demo1">
+<pre class="code" id="demo1">
+var schema = {
+	"items": {
+		"type": "boolean"
+	}
+};
+var data1 = [true, false];
+var data2 = [true, 123];
+
+alert("data 1: " + tv4.validate(data1, schema)); // true
+alert("data 2: " + tv4.validate(data2, schema)); // false
+alert("data 2 error: " + JSON.stringify(tv4.error, null, 4));
+</pre>
+</div>
+
+### Use of <code>$ref</code>
+<div class="content inline-demo" markdown="1" data-demo="demo2">
+<pre class="code" id="demo2">
+var schema = {
+	"type": "array",
+	"items": {"$ref": "#"}
+};
+var data1 = [[], [[]]];
+var data2 = [[], [true, []]];
+
+alert("data 1: " + tv4.validate(data1, schema)); // true
+alert("data 2: " + tv4.validate(data2, schema)); // false
+</pre>
+</div>
+
+### Missing schema
+<div class="content inline-demo" markdown="1" data-demo="demo3">
+<pre class="code" id="demo3">
+var schema = {
+	"type": "array",
+	"items": {"$ref": "http://example.com/schema" }
+};
+var data = [1, 2, 3];
+
+alert("Valid: " + tv4.validate(data, schema)); // true
+alert("Missing schemas: " + JSON.stringify(tv4.missing));
+</pre>
+</div>
+
+### Referencing remote schema
+<div class="content inline-demo" markdown="1" data-demo="demo4">
+<pre class="code" id="demo4">
+tv4.addSchema("http://example.com/schema", {
+	"definitions": {
+		"arrayItem": {"type": "boolean"}
+	}
+});
+var schema = {
+	"type": "array",
+	"items": {"$ref": "http://example.com/schema#/definitions/arrayItem" }
+};
+var data1 = [true, false, true];
+var data2 = [1, 2, 3];
+
+alert("data 1: " + tv4.validate(data1, schema)); // true
+alert("data 2: " + tv4.validate(data2, schema)); // false
+</pre>
+</div>
+
+## Supported platforms
+
+* Node.js
+* All modern browsers
+* IE >= 7
+
+## Installation
+
+You can manually download [`tv4.js`](https://raw.github.com/geraintluff/tv4/master/tv4.js) or the minified [`tv4.min.js`](https://raw.github.com/geraintluff/tv4/master/tv4.min.js) and include it in your html to create the global `tv4` variable.
+
+Alternately use it as a CommonJS module:
+
+````js
+var tv4 = require('tv4');
+````
+
+#### npm
+
+````
+$ npm install tv4
+````
+
+#### bower
+
+````
+$ bower install tv4
+````
+
+#### component.io
+
+````
+$ component install geraintluff/tv4
+````
+
+## Build and test
+
+You can rebuild and run the node and browser tests using node.js and [grunt](http://http://gruntjs.com/):
+
+Make sure you have the global grunt cli command:
+````
+$ npm install grunt-cli -g
+````
+
+Clone the git repos, open a shell in the root folder and install the development dependencies:
+
+````
+$ npm install
+````
+
+Rebuild and run the tests:
+````
+$ grunt
+````
+
+It will run a build and display one Spec-style report for the node.js and two Dot-style reports for both the plain and minified browser tests (via phantomJS). You can also use your own browser to manually run the suites by opening [`test/index.html`](http://geraintluff.github.io/tv4/test/index.html) and [`test/index-min.html`](http://geraintluff.github.io/tv4/test/index-min.html).
+
+## Contributing
+
+Pull-requests for fixes and expansions are welcome. Edit the partial files in `/source` and add your tests in a suitable suite or folder under `/test/tests` and run `grunt` to rebuild and run the test suite. Try to maintain an idiomatic coding style and add tests for any new features. It is recommend to discuss big changes in an Issue.
+
+## Packages using tv4
+
+* [chai-json-schema](http://chaijs.com/plugins/chai-json-schema) is a [Chai Assertion Library](http://chaijs.com) plugin to assert values against json-schema.
+* [grunt-tv4](http://www.github.com/Bartvds/grunt-tv4) is a plugin for [Grunt](http://http://gruntjs.com/) that uses tv4 to bulk validate json files.
+
+## License
+
+The code is available as "public domain", meaning that it is completely free to use, without any restrictions at all.  Read the full license [here](http://geraintluff.github.com/tv4/LICENSE.txt).
+
+It's also available under an [MIT license](http://jsonary.com/LICENSE.txt).
Index: Dev/trunk/src/node_modules/tv4/build/build.js
===================================================================
--- Dev/trunk/src/node_modules/tv4/build/build.js	(revision 484)
+++ Dev/trunk/src/node_modules/tv4/build/build.js	(revision 484)
@@ -0,0 +1,205 @@
+
+/**
+ * Require the given path.
+ *
+ * @param {String} path
+ * @return {Object} exports
+ * @api public
+ */
+
+function require(path, parent, orig) {
+  var resolved = require.resolve(path);
+
+  // lookup failed
+  if (null == resolved) {
+    orig = orig || path;
+    parent = parent || 'root';
+    var err = new Error('Failed to require "' + orig + '" from "' + parent + '"');
+    err.path = orig;
+    err.parent = parent;
+    err.require = true;
+    throw err;
+  }
+
+  var module = require.modules[resolved];
+
+  // perform real require()
+  // by invoking the module's
+  // registered function
+  if (!module.exports) {
+    module.exports = {};
+    module.client = module.component = true;
+    module.call(this, module.exports, require.relative(resolved), module);
+  }
+
+  return module.exports;
+}
+
+/**
+ * Registered modules.
+ */
+
+require.modules = {};
+
+/**
+ * Registered aliases.
+ */
+
+require.aliases = {};
+
+/**
+ * Resolve `path`.
+ *
+ * Lookup:
+ *
+ *   - PATH/index.js
+ *   - PATH.js
+ *   - PATH
+ *
+ * @param {String} path
+ * @return {String} path or null
+ * @api private
+ */
+
+require.resolve = function(path) {
+  if (path.charAt(0) === '/') path = path.slice(1);
+
+  var paths = [
+    path,
+    path + '.js',
+    path + '.json',
+    path + '/index.js',
+    path + '/index.json'
+  ];
+
+  for (var i = 0; i < paths.length; i++) {
+    var path = paths[i];
+    if (require.modules.hasOwnProperty(path)) return path;
+    if (require.aliases.hasOwnProperty(path)) return require.aliases[path];
+  }
+};
+
+/**
+ * Normalize `path` relative to the current path.
+ *
+ * @param {String} curr
+ * @param {String} path
+ * @return {String}
+ * @api private
+ */
+
+require.normalize = function(curr, path) {
+  var segs = [];
+
+  if ('.' != path.charAt(0)) return path;
+
+  curr = curr.split('/');
+  path = path.split('/');
+
+  for (var i = 0; i < path.length; ++i) {
+    if ('..' == path[i]) {
+      curr.pop();
+    } else if ('.' != path[i] && '' != path[i]) {
+      segs.push(path[i]);
+    }
+  }
+
+  return curr.concat(segs).join('/');
+};
+
+/**
+ * Register module at `path` with callback `definition`.
+ *
+ * @param {String} path
+ * @param {Function} definition
+ * @api private
+ */
+
+require.register = function(path, definition) {
+  require.modules[path] = definition;
+};
+
+/**
+ * Alias a module definition.
+ *
+ * @param {String} from
+ * @param {String} to
+ * @api private
+ */
+
+require.alias = function(from, to) {
+  if (!require.modules.hasOwnProperty(from)) {
+    throw new Error('Failed to alias "' + from + '", it does not exist');
+  }
+  require.aliases[to] = from;
+};
+
+/**
+ * Return a require function relative to the `parent` path.
+ *
+ * @param {String} parent
+ * @return {Function}
+ * @api private
+ */
+
+require.relative = function(parent) {
+  var p = require.normalize(parent, '..');
+
+  /**
+   * lastIndexOf helper.
+   */
+
+  function lastIndexOf(arr, obj) {
+    var i = arr.length;
+    while (i--) {
+      if (arr[i] === obj) return i;
+    }
+    return -1;
+  }
+
+  /**
+   * The relative require() itself.
+   */
+
+  function localRequire(path) {
+    var resolved = localRequire.resolve(path);
+    return require(resolved, parent, path);
+  }
+
+  /**
+   * Resolve relative to the parent.
+   */
+
+  localRequire.resolve = function(path) {
+    var c = path.charAt(0);
+    if ('/' == c) return path.slice(1);
+    if ('.' == c) return require.normalize(p, path);
+
+    // resolve deps by returning
+    // the dep in the nearest "deps"
+    // directory
+    var segs = parent.split('/');
+    var i = lastIndexOf(segs, 'deps') + 1;
+    if (!i) i = 0;
+    path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
+    return path;
+  };
+
+  /**
+   * Check if module is defined at `path`.
+   */
+
+  localRequire.exists = function(path) {
+    return require.modules.hasOwnProperty(localRequire.resolve(path));
+  };
+
+  return localRequire;
+};
+require.register("tv4/lang/de.js", Function("exports, require, module",
+"tv4.addLanguage('de',  {\n    INVALID_TYPE: \"UngÃŒltiger Typ: {type} (erwartet wurde: {expected})\",\n    ENUM_MISMATCH: \"Keine Ãbereinstimmung mit der AufzÃ€hlung (enum) fÃŒr: {value}\",\n    ANY_OF_MISSING: \"Daten stimmen nicht ÃŒberein mit einem der Schemas von \\\"anyOf\\\"\",\n    ONE_OF_MISSING: \"Daten stimmen nicht ÃŒberein mit einem der Schemas von \\\"oneOf\\\"\",\n    ONE_OF_MULTIPLE: \"Daten sind valid in Bezug auf mehreren Schemas von \\\"oneOf\\\": index {index1} und {index2}\",\n    NOT_PASSED: \"Daten stimmen mit dem \\\"not\\\" Schema ÃŒberein\",\n    // Numeric errors\n    NUMBER_MULTIPLE_OF: \"Wert {value} ist kein Vielfaches von {multipleOf}\",\n    NUMBER_MINIMUM: \"Wert {value} ist kleiner als das Minimum {minimum}\",\n    NUMBER_MINIMUM_EXCLUSIVE: \"Wert {value} ist gleich dem Exklusiven Minimum {minimum}\",\n    NUMBER_MAXIMUM: \"Wert {value} ist grÃ¶Ãer als das Maximum {maximum}\",\n    NUMBER_MAXIMUM_EXCLUSIVE: \"Wert {value} ist gleich dem Exklusiven Maximum {maximum}\",\n    // String errors\n    STRING_LENGTH_SHORT: \"Zeichenkette zu kurz ({length} chars), minimum {minimum}\",\n    STRING_LENGTH_LONG: \"Zeichenkette zu lang ({length} chars), maximum {maximum}\",\n    STRING_PATTERN: \"Zeichenkette entspricht nicht dem Muster: {pattern}\",\n    // Object errors\n    OBJECT_PROPERTIES_MINIMUM: \"Zu wenige Attribute definiert ({propertyCount}), minimum {minimum}\",\n    OBJECT_PROPERTIES_MAXIMUM: \"Zu viele Attribute definiert ({propertyCount}), maximum {maximum}\",\n    OBJECT_REQUIRED: \"Notwendiges Attribut fehlt: {key}\",\n    OBJECT_ADDITIONAL_PROPERTIES: \"ZusÃ€tzliche Attribute nicht erlaubt\",\n    OBJECT_DEPENDENCY_KEY: \"AbhÃ€ngigkeit fehlt - SchlÃŒssel nicht vorhanden: {missing} (wegen SchlÃŒssel: {key})\",\n    // Array errors\n    ARRAY_LENGTH_SHORT: \"Array zu kurz ({length}), minimum {minimum}\",\n    ARRAY_LENGTH_LONG: \"Array zu lang ({length}), maximum {maximum}\",\n    ARRAY_UNIQUE: \"Array EintrÃ€ge nicht eindeutig (Index {match1} und {match2})\",\n    ARRAY_ADDITIONAL_ITEMS: \"ZusÃ€tzliche EintrÃ€ge nicht erlaubt\"\n});\n//@ sourceURL=tv4/lang/de.js"
+));
+require.register("tv4/tv4.js", Function("exports, require, module",
+"/*\nAuthor: Geraint Luff and others\nYear: 2013\n\nThis code is released into the \"public domain\" by its author(s).  Anybody may use, alter and distribute the code without restriction.  The author makes no guarantees, and takes no liability of any kind for use of this code.\n\nIf you find a bug or make an improvement, it would be courteous to let the author know, but it is not compulsory.\n*/\n(function (global) {\n'use strict';\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2Fkeys\nif (!Object.keys) {\n\tObject.keys = (function () {\n\t\tvar hasOwnProperty = Object.prototype.hasOwnProperty,\n\t\t\thasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),\n\t\t\tdontEnums = [\n\t\t\t\t'toString',\n\t\t\t\t'toLocaleString',\n\t\t\t\t'valueOf',\n\t\t\t\t'hasOwnProperty',\n\t\t\t\t'isPrototypeOf',\n\t\t\t\t'propertyIsEnumerable',\n\t\t\t\t'constructor'\n\t\t\t],\n\t\t\tdontEnumsLength = dontEnums.length;\n\n\t\treturn function (obj) {\n\t\t\tif (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) {\n\t\t\t\tthrow new TypeError('Object.keys called on non-object');\n\t\t\t}\n\n\t\t\tvar result = [];\n\n\t\t\tfor (var prop in obj) {\n\t\t\t\tif (hasOwnProperty.call(obj, prop)) {\n\t\t\t\t\tresult.push(prop);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (hasDontEnumBug) {\n\t\t\t\tfor (var i=0; i < dontEnumsLength; i++) {\n\t\t\t\t\tif (hasOwnProperty.call(obj, dontEnums[i])) {\n\t\t\t\t\t\tresult.push(dontEnums[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\t})();\n}\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create\nif (!Object.create) {\n\tObject.create = (function(){\n\t\tfunction F(){}\n\n\t\treturn function(o){\n\t\t\tif (arguments.length !== 1) {\n\t\t\t\tthrow new Error('Object.create implementation only accepts one parameter.');\n\t\t\t}\n\t\t\tF.prototype = o;\n\t\t\treturn new F();\n\t\t};\n\t})();\n}\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2FisArray\nif(!Array.isArray) {\n\tArray.isArray = function (vArg) {\n\t\treturn Object.prototype.toString.call(vArg) === \"[object Array]\";\n\t};\n}\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2FindexOf\nif (!Array.prototype.indexOf) {\n\tArray.prototype.indexOf = function (searchElement /*, fromIndex */ ) {\n\t\tif (this === null) {\n\t\t\tthrow new TypeError();\n\t\t}\n\t\tvar t = Object(this);\n\t\tvar len = t.length >>> 0;\n\n\t\tif (len === 0) {\n\t\t\treturn -1;\n\t\t}\n\t\tvar n = 0;\n\t\tif (arguments.length > 1) {\n\t\t\tn = Number(arguments[1]);\n\t\t\tif (n !== n) { // shortcut for verifying if it's NaN\n\t\t\t\tn = 0;\n\t\t\t} else if (n !== 0 && n !== Infinity && n !== -Infinity) {\n\t\t\t\tn = (n > 0 || -1) * Math.floor(Math.abs(n));\n\t\t\t}\n\t\t}\n\t\tif (n >= len) {\n\t\t\treturn -1;\n\t\t}\n\t\tvar k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);\n\t\tfor (; k < len; k++) {\n\t\t\tif (k in t && t[k] === searchElement) {\n\t\t\t\treturn k;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t};\n}\n\n// Grungey Object.isFrozen hack\nif (!Object.isFrozen) {\n\tObject.isFrozen = function (obj) {\n\t\tvar key = \"tv4_test_frozen_key\";\n\t\twhile (obj.hasOwnProperty(key)) {\n\t\t\tkey += Math.random();\n\t\t}\n\t\ttry {\n\t\t\tobj[key] = true;\n\t\t\tdelete obj[key];\n\t\t\treturn false;\n\t\t} catch (e) {\n\t\t\treturn true;\n\t\t}\n\t};\n}\nvar ValidatorContext = function ValidatorContext(parent, collectMultiple, errorMessages, checkRecursive, trackUnknownProperties) {\n\tthis.missing = [];\n\tthis.missingMap = {};\n\tthis.formatValidators = parent ? Object.create(parent.formatValidators) : {};\n\tthis.schemas = parent ? Object.create(parent.schemas) : {};\n\tthis.collectMultiple = collectMultiple;\n\tthis.errors = [];\n\tthis.handleError = collectMultiple ? this.collectError : this.returnError;\n\tif (checkRecursive) {\n\t\tthis.checkRecursive = true;\n\t\tthis.scanned = [];\n\t\tthis.scannedFrozen = [];\n\t\tthis.scannedFrozenSchemas = [];\n\t\tthis.key = 'tv4_validation_id';\n\t}\n\tif (trackUnknownProperties) {\n\t\tthis.trackUnknownProperties = true;\n\t\tthis.knownPropertyPaths = {};\n\t\tthis.unknownPropertyPaths = {};\n\t}\n\tthis.errorMessages = errorMessages;\n};\nValidatorContext.prototype.createError = function (code, messageParams, dataPath, schemaPath, subErrors) {\n\tvar messageTemplate = this.errorMessages[code] || ErrorMessagesDefault[code];\n\tif (typeof messageTemplate !== 'string') {\n\t\treturn new ValidationError(code, \"Unknown error code \" + code + \": \" + JSON.stringify(messageParams), dataPath, schemaPath, subErrors);\n\t}\n\t// Adapted from Crockford's supplant()\n\tvar message = messageTemplate.replace(/\\{([^{}]*)\\}/g, function (whole, varName) {\n\t\tvar subValue = messageParams[varName];\n\t\treturn typeof subValue === 'string' || typeof subValue === 'number' ? subValue : whole;\n\t});\n\treturn new ValidationError(code, message, dataPath, schemaPath, subErrors);\n};\nValidatorContext.prototype.returnError = function (error) {\n\treturn error;\n};\nValidatorContext.prototype.collectError = function (error) {\n\tif (error) {\n\t\tthis.errors.push(error);\n\t}\n\treturn null;\n};\nValidatorContext.prototype.prefixErrors = function (startIndex, dataPath, schemaPath) {\n\tfor (var i = startIndex; i < this.errors.length; i++) {\n\t\tthis.errors[i] = this.errors[i].prefixWith(dataPath, schemaPath);\n\t}\n\treturn this;\n};\nValidatorContext.prototype.banUnknownProperties = function () {\n\tfor (var unknownPath in this.unknownPropertyPaths) {\n\t\tvar error = this.createError(ErrorCodes.UNKNOWN_PROPERTY, {path: unknownPath}, unknownPath, \"\");\n\t\tvar result = this.handleError(error);\n\t\tif (result) {\n\t\t\treturn result;\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.addFormat = function (format, validator) {\n\tif (typeof format === 'object') {\n\t\tfor (var key in format) {\n\t\t\tthis.addFormat(key, format[key]);\n\t\t}\n\t\treturn this;\n\t}\n\tthis.formatValidators[format] = validator;\n};\nValidatorContext.prototype.resolveRefs = function (schema, urlHistory) {\n\tif (schema['$ref'] !== undefined) {\n\t\turlHistory = urlHistory || {};\n\t\tif (urlHistory[schema['$ref']]) {\n\t\t\treturn this.createError(ErrorCodes.CIRCULAR_REFERENCE, {urls: Object.keys(urlHistory).join(', ')}, '', '');\n\t\t}\n\t\turlHistory[schema['$ref']] = true;\n\t\tschema = this.getSchema(schema['$ref'], urlHistory);\n\t}\n\treturn schema;\n};\nValidatorContext.prototype.getSchema = function (url, urlHistory) {\n\tvar schema;\n\tif (this.schemas[url] !== undefined) {\n\t\tschema = this.schemas[url];\n\t\treturn this.resolveRefs(schema, urlHistory);\n\t}\n\tvar baseUrl = url;\n\tvar fragment = \"\";\n\tif (url.indexOf('#') !== -1) {\n\t\tfragment = url.substring(url.indexOf(\"#\") + 1);\n\t\tbaseUrl = url.substring(0, url.indexOf(\"#\"));\n\t}\n\tif (typeof this.schemas[baseUrl] === 'object') {\n\t\tschema = this.schemas[baseUrl];\n\t\tvar pointerPath = decodeURIComponent(fragment);\n\t\tif (pointerPath === \"\") {\n\t\t\treturn this.resolveRefs(schema, urlHistory);\n\t\t} else if (pointerPath.charAt(0) !== \"/\") {\n\t\t\treturn undefined;\n\t\t}\n\t\tvar parts = pointerPath.split(\"/\").slice(1);\n\t\tfor (var i = 0; i < parts.length; i++) {\n\t\t\tvar component = parts[i].replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n\t\t\tif (schema[component] === undefined) {\n\t\t\t\tschema = undefined;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tschema = schema[component];\n\t\t}\n\t\tif (schema !== undefined) {\n\t\t\treturn this.resolveRefs(schema, urlHistory);\n\t\t}\n\t}\n\tif (this.missing[baseUrl] === undefined) {\n\t\tthis.missing.push(baseUrl);\n\t\tthis.missing[baseUrl] = baseUrl;\n\t\tthis.missingMap[baseUrl] = baseUrl;\n\t}\n};\nValidatorContext.prototype.searchSchemas = function (schema, url) {\n\tif (typeof schema.id === \"string\") {\n\t\tif (isTrustedUrl(url, schema.id)) {\n\t\t\tif (this.schemas[schema.id] === undefined) {\n\t\t\t\tthis.schemas[schema.id] = schema;\n\t\t\t}\n\t\t}\n\t}\n\tif (typeof schema === \"object\") {\n\t\tfor (var key in schema) {\n\t\t\tif (key !== \"enum\") {\n\t\t\t\tif (typeof schema[key] === \"object\") {\n\t\t\t\t\tthis.searchSchemas(schema[key], url);\n\t\t\t\t} else if (key === \"$ref\") {\n\t\t\t\t\tvar uri = getDocumentUri(schema[key]);\n\t\t\t\t\tif (uri && this.schemas[uri] === undefined && this.missingMap[uri] === undefined) {\n\t\t\t\t\t\tthis.missingMap[uri] = uri;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\nValidatorContext.prototype.addSchema = function (url, schema) {\n\t//overload\n\tif (typeof schema === 'undefined') {\n\t\tif (typeof url === 'object' && typeof url.id === 'string') {\n\t\t\tschema = url;\n\t\t\turl = schema.id;\n\t\t}\n\t\telse {\n\t\t\treturn;\n\t\t}\n\t}\n\tif (url = getDocumentUri(url) + \"#\") {\n\t\t// Remove empty fragment\n\t\turl = getDocumentUri(url);\n\t}\n\tthis.schemas[url] = schema;\n\tdelete this.missingMap[url];\n\tnormSchema(schema, url);\n\tthis.searchSchemas(schema, url);\n};\n\nValidatorContext.prototype.getSchemaMap = function () {\n\tvar map = {};\n\tfor (var key in this.schemas) {\n\t\tmap[key] = this.schemas[key];\n\t}\n\treturn map;\n};\n\nValidatorContext.prototype.getSchemaUris = function (filterRegExp) {\n\tvar list = [];\n\tfor (var key in this.schemas) {\n\t\tif (!filterRegExp || filterRegExp.test(key)) {\n\t\t\tlist.push(key);\n\t\t}\n\t}\n\treturn list;\n};\n\nValidatorContext.prototype.getMissingUris = function (filterRegExp) {\n\tvar list = [];\n\tfor (var key in this.missingMap) {\n\t\tif (!filterRegExp || filterRegExp.test(key)) {\n\t\t\tlist.push(key);\n\t\t}\n\t}\n\treturn list;\n};\n\nValidatorContext.prototype.dropSchemas = function () {\n\tthis.schemas = {};\n\tthis.reset();\n};\nValidatorContext.prototype.reset = function () {\n\tthis.missing = [];\n\tthis.missingMap = {};\n\tthis.errors = [];\n};\n\nValidatorContext.prototype.validateAll = function (data, schema, dataPathParts, schemaPathParts, dataPointerPath) {\n\tvar topLevel;\n\tschema = this.resolveRefs(schema);\n\tif (!schema) {\n\t\treturn null;\n\t} else if (schema instanceof ValidationError) {\n\t\tthis.errors.push(schema);\n\t\treturn schema;\n\t}\n\n\tif (this.checkRecursive && (typeof data) === 'object') {\n\t\ttopLevel = !this.scanned.length;\n\t\tif (data[this.key] && data[this.key].indexOf(schema) !== -1) { return null; }\n\t\tvar frozenIndex;\n\t\tif (Object.isFrozen(data)) {\n\t\t\tfrozenIndex = this.scannedFrozen.indexOf(data);\n\t\t\tif (frozenIndex !== -1 && this.scannedFrozenSchemas[frozenIndex].indexOf(schema) !== -1) { return null; }\n\t\t}\n\t\tthis.scanned.push(data);\n\t\tif (Object.isFrozen(data)) {\n\t\t\tif (frozenIndex === -1) {\n\t\t\t\tfrozenIndex = this.scannedFrozen.length;\n\t\t\t\tthis.scannedFrozen.push(data);\n\t\t\t\tthis.scannedFrozenSchemas.push([]);\n\t\t\t}\n\t\t\tthis.scannedFrozenSchemas[frozenIndex].push(schema);\n\t\t} else {\n\t\t\tif (!data[this.key]) {\n\t\t\t\ttry {\n\t\t\t\t\tObject.defineProperty(data, this.key, {\n\t\t\t\t\t\tvalue: [],\n\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\t//IE 7/8 workaround\n\t\t\t\t\tdata[this.key] = [];\n\t\t\t\t}\n\t\t\t}\n\t\t\tdata[this.key].push(schema);\n\t\t}\n\t}\n\n\tvar errorCount = this.errors.length;\n\tvar error = this.validateBasic(data, schema, dataPointerPath)\n\t\t|| this.validateNumeric(data, schema, dataPointerPath)\n\t\t|| this.validateString(data, schema, dataPointerPath)\n\t\t|| this.validateArray(data, schema, dataPointerPath)\n\t\t|| this.validateObject(data, schema, dataPointerPath)\n\t\t|| this.validateCombinations(data, schema, dataPointerPath)\n\t\t|| this.validateFormat(data, schema, dataPointerPath)\n\t\t|| null;\n\n\tif (topLevel) {\n\t\twhile (this.scanned.length) {\n\t\t\tvar item = this.scanned.pop();\n\t\t\tdelete item[this.key];\n\t\t}\n\t\tthis.scannedFrozen = [];\n\t\tthis.scannedFrozenSchemas = [];\n\t}\n\n\tif (error || errorCount !== this.errors.length) {\n\t\twhile ((dataPathParts && dataPathParts.length) || (schemaPathParts && schemaPathParts.length)) {\n\t\t\tvar dataPart = (dataPathParts && dataPathParts.length) ? \"\" + dataPathParts.pop() : null;\n\t\t\tvar schemaPart = (schemaPathParts && schemaPathParts.length) ? \"\" + schemaPathParts.pop() : null;\n\t\t\tif (error) {\n\t\t\t\terror = error.prefixWith(dataPart, schemaPart);\n\t\t\t}\n\t\t\tthis.prefixErrors(errorCount, dataPart, schemaPart);\n\t\t}\n\t}\n\n\treturn this.handleError(error);\n};\nValidatorContext.prototype.validateFormat = function (data, schema) {\n\tif (typeof schema.format !== 'string' || !this.formatValidators[schema.format]) {\n\t\treturn null;\n\t}\n\tvar errorMessage = this.formatValidators[schema.format].call(null, data, schema);\n\tif (typeof errorMessage === 'string' || typeof errorMessage === 'number') {\n\t\treturn this.createError(ErrorCodes.FORMAT_CUSTOM, {message: errorMessage}).prefixWith(null, \"format\");\n\t} else if (errorMessage && typeof errorMessage === 'object') {\n\t\treturn this.createError(ErrorCodes.FORMAT_CUSTOM, {message: errorMessage.message || \"?\"}, errorMessage.dataPath || null, errorMessage.schemaPath || \"/format\");\n\t}\n\treturn null;\n};\n\nfunction recursiveCompare(A, B) {\n\tif (A === B) {\n\t\treturn true;\n\t}\n\tif (typeof A === \"object\" && typeof B === \"object\") {\n\t\tif (Array.isArray(A) !== Array.isArray(B)) {\n\t\t\treturn false;\n\t\t} else if (Array.isArray(A)) {\n\t\t\tif (A.length !== B.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tfor (var i = 0; i < A.length; i++) {\n\t\t\t\tif (!recursiveCompare(A[i], B[i])) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tvar key;\n\t\t\tfor (key in A) {\n\t\t\t\tif (B[key] === undefined && A[key] !== undefined) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (key in B) {\n\t\t\t\tif (A[key] === undefined && B[key] !== undefined) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (key in A) {\n\t\t\t\tif (!recursiveCompare(A[key], B[key])) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nValidatorContext.prototype.validateBasic = function validateBasic(data, schema, dataPointerPath) {\n\tvar error;\n\tif (error = this.validateType(data, schema, dataPointerPath)) {\n\t\treturn error.prefixWith(null, \"type\");\n\t}\n\tif (error = this.validateEnum(data, schema, dataPointerPath)) {\n\t\treturn error.prefixWith(null, \"type\");\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateType = function validateType(data, schema) {\n\tif (schema.type === undefined) {\n\t\treturn null;\n\t}\n\tvar dataType = typeof data;\n\tif (data === null) {\n\t\tdataType = \"null\";\n\t} else if (Array.isArray(data)) {\n\t\tdataType = \"array\";\n\t}\n\tvar allowedTypes = schema.type;\n\tif (typeof allowedTypes !== \"object\") {\n\t\tallowedTypes = [allowedTypes];\n\t}\n\n\tfor (var i = 0; i < allowedTypes.length; i++) {\n\t\tvar type = allowedTypes[i];\n\t\tif (type === dataType || (type === \"integer\" && dataType === \"number\" && (data % 1 === 0))) {\n\t\t\treturn null;\n\t\t}\n\t}\n\treturn this.createError(ErrorCodes.INVALID_TYPE, {type: dataType, expected: allowedTypes.join(\"/\")});\n};\n\nValidatorContext.prototype.validateEnum = function validateEnum(data, schema) {\n\tif (schema[\"enum\"] === undefined) {\n\t\treturn null;\n\t}\n\tfor (var i = 0; i < schema[\"enum\"].length; i++) {\n\t\tvar enumVal = schema[\"enum\"][i];\n\t\tif (recursiveCompare(data, enumVal)) {\n\t\t\treturn null;\n\t\t}\n\t}\n\treturn this.createError(ErrorCodes.ENUM_MISMATCH, {value: (typeof JSON !== 'undefined') ? JSON.stringify(data) : data});\n};\n\nValidatorContext.prototype.validateNumeric = function validateNumeric(data, schema, dataPointerPath) {\n\treturn this.validateMultipleOf(data, schema, dataPointerPath)\n\t\t|| this.validateMinMax(data, schema, dataPointerPath)\n\t\t|| null;\n};\n\nValidatorContext.prototype.validateMultipleOf = function validateMultipleOf(data, schema) {\n\tvar multipleOf = schema.multipleOf || schema.divisibleBy;\n\tif (multipleOf === undefined) {\n\t\treturn null;\n\t}\n\tif (typeof data === \"number\") {\n\t\tif (data % multipleOf !== 0) {\n\t\t\treturn this.createError(ErrorCodes.NUMBER_MULTIPLE_OF, {value: data, multipleOf: multipleOf});\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateMinMax = function validateMinMax(data, schema) {\n\tif (typeof data !== \"number\") {\n\t\treturn null;\n\t}\n\tif (schema.minimum !== undefined) {\n\t\tif (data < schema.minimum) {\n\t\t\treturn this.createError(ErrorCodes.NUMBER_MINIMUM, {value: data, minimum: schema.minimum}).prefixWith(null, \"minimum\");\n\t\t}\n\t\tif (schema.exclusiveMinimum && data === schema.minimum) {\n\t\t\treturn this.createError(ErrorCodes.NUMBER_MINIMUM_EXCLUSIVE, {value: data, minimum: schema.minimum}).prefixWith(null, \"exclusiveMinimum\");\n\t\t}\n\t}\n\tif (schema.maximum !== undefined) {\n\t\tif (data > schema.maximum) {\n\t\t\treturn this.createError(ErrorCodes.NUMBER_MAXIMUM, {value: data, maximum: schema.maximum}).prefixWith(null, \"maximum\");\n\t\t}\n\t\tif (schema.exclusiveMaximum && data === schema.maximum) {\n\t\t\treturn this.createError(ErrorCodes.NUMBER_MAXIMUM_EXCLUSIVE, {value: data, maximum: schema.maximum}).prefixWith(null, \"exclusiveMaximum\");\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateString = function validateString(data, schema, dataPointerPath) {\n\treturn this.validateStringLength(data, schema, dataPointerPath)\n\t\t|| this.validateStringPattern(data, schema, dataPointerPath)\n\t\t|| null;\n};\n\nValidatorContext.prototype.validateStringLength = function validateStringLength(data, schema) {\n\tif (typeof data !== \"string\") {\n\t\treturn null;\n\t}\n\tif (schema.minLength !== undefined) {\n\t\tif (data.length < schema.minLength) {\n\t\t\treturn this.createError(ErrorCodes.STRING_LENGTH_SHORT, {length: data.length, minimum: schema.minLength}).prefixWith(null, \"minLength\");\n\t\t}\n\t}\n\tif (schema.maxLength !== undefined) {\n\t\tif (data.length > schema.maxLength) {\n\t\t\treturn this.createError(ErrorCodes.STRING_LENGTH_LONG, {length: data.length, maximum: schema.maxLength}).prefixWith(null, \"maxLength\");\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateStringPattern = function validateStringPattern(data, schema) {\n\tif (typeof data !== \"string\" || schema.pattern === undefined) {\n\t\treturn null;\n\t}\n\tvar regexp = new RegExp(schema.pattern);\n\tif (!regexp.test(data)) {\n\t\treturn this.createError(ErrorCodes.STRING_PATTERN, {pattern: schema.pattern}).prefixWith(null, \"pattern\");\n\t}\n\treturn null;\n};\nValidatorContext.prototype.validateArray = function validateArray(data, schema, dataPointerPath) {\n\tif (!Array.isArray(data)) {\n\t\treturn null;\n\t}\n\treturn this.validateArrayLength(data, schema, dataPointerPath)\n\t\t|| this.validateArrayUniqueItems(data, schema, dataPointerPath)\n\t\t|| this.validateArrayItems(data, schema, dataPointerPath)\n\t\t|| null;\n};\n\nValidatorContext.prototype.validateArrayLength = function validateArrayLength(data, schema) {\n\tvar error;\n\tif (schema.minItems !== undefined) {\n\t\tif (data.length < schema.minItems) {\n\t\t\terror = (this.createError(ErrorCodes.ARRAY_LENGTH_SHORT, {length: data.length, minimum: schema.minItems})).prefixWith(null, \"minItems\");\n\t\t\tif (this.handleError(error)) {\n\t\t\t\treturn error;\n\t\t\t}\n\t\t}\n\t}\n\tif (schema.maxItems !== undefined) {\n\t\tif (data.length > schema.maxItems) {\n\t\t\terror = (this.createError(ErrorCodes.ARRAY_LENGTH_LONG, {length: data.length, maximum: schema.maxItems})).prefixWith(null, \"maxItems\");\n\t\t\tif (this.handleError(error)) {\n\t\t\t\treturn error;\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateArrayUniqueItems = function validateArrayUniqueItems(data, schema) {\n\tif (schema.uniqueItems) {\n\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\tfor (var j = i + 1; j < data.length; j++) {\n\t\t\t\tif (recursiveCompare(data[i], data[j])) {\n\t\t\t\t\tvar error = (this.createError(ErrorCodes.ARRAY_UNIQUE, {match1: i, match2: j})).prefixWith(null, \"uniqueItems\");\n\t\t\t\t\tif (this.handleError(error)) {\n\t\t\t\t\t\treturn error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateArrayItems = function validateArrayItems(data, schema, dataPointerPath) {\n\tif (schema.items === undefined) {\n\t\treturn null;\n\t}\n\tvar error, i;\n\tif (Array.isArray(schema.items)) {\n\t\tfor (i = 0; i < data.length; i++) {\n\t\t\tif (i < schema.items.length) {\n\t\t\t\tif (error = this.validateAll(data[i], schema.items[i], [i], [\"items\", i], dataPointerPath + \"/\" + i)) {\n\t\t\t\t\treturn error;\n\t\t\t\t}\n\t\t\t} else if (schema.additionalItems !== undefined) {\n\t\t\t\tif (typeof schema.additionalItems === \"boolean\") {\n\t\t\t\t\tif (!schema.additionalItems) {\n\t\t\t\t\t\terror = (this.createError(ErrorCodes.ARRAY_ADDITIONAL_ITEMS, {})).prefixWith(\"\" + i, \"additionalItems\");\n\t\t\t\t\t\tif (this.handleError(error)) {\n\t\t\t\t\t\t\treturn error;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (error = this.validateAll(data[i], schema.additionalItems, [i], [\"additionalItems\"], dataPointerPath + \"/\" + i)) {\n\t\t\t\t\treturn error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (i = 0; i < data.length; i++) {\n\t\t\tif (error = this.validateAll(data[i], schema.items, [i], [\"items\"], dataPointerPath + \"/\" + i)) {\n\t\t\t\treturn error;\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateObject = function validateObject(data, schema, dataPointerPath) {\n\tif (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n\t\treturn null;\n\t}\n\treturn this.validateObjectMinMaxProperties(data, schema, dataPointerPath)\n\t\t|| this.validateObjectRequiredProperties(data, schema, dataPointerPath)\n\t\t|| this.validateObjectProperties(data, schema, dataPointerPath)\n\t\t|| this.validateObjectDependencies(data, schema, dataPointerPath)\n\t\t|| null;\n};\n\nValidatorContext.prototype.validateObjectMinMaxProperties = function validateObjectMinMaxProperties(data, schema) {\n\tvar keys = Object.keys(data);\n\tvar error;\n\tif (schema.minProperties !== undefined) {\n\t\tif (keys.length < schema.minProperties) {\n\t\t\terror = this.createError(ErrorCodes.OBJECT_PROPERTIES_MINIMUM, {propertyCount: keys.length, minimum: schema.minProperties}).prefixWith(null, \"minProperties\");\n\t\t\tif (this.handleError(error)) {\n\t\t\t\treturn error;\n\t\t\t}\n\t\t}\n\t}\n\tif (schema.maxProperties !== undefined) {\n\t\tif (keys.length > schema.maxProperties) {\n\t\t\terror = this.createError(ErrorCodes.OBJECT_PROPERTIES_MAXIMUM, {propertyCount: keys.length, maximum: schema.maxProperties}).prefixWith(null, \"maxProperties\");\n\t\t\tif (this.handleError(error)) {\n\t\t\t\treturn error;\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateObjectRequiredProperties = function validateObjectRequiredProperties(data, schema) {\n\tif (schema.required !== undefined) {\n\t\tfor (var i = 0; i < schema.required.length; i++) {\n\t\t\tvar key = schema.required[i];\n\t\t\tif (data[key] === undefined) {\n\t\t\t\tvar error = this.createError(ErrorCodes.OBJECT_REQUIRED, {key: key}).prefixWith(null, \"\" + i).prefixWith(null, \"required\");\n\t\t\t\tif (this.handleError(error)) {\n\t\t\t\t\treturn error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateObjectProperties = function validateObjectProperties(data, schema, dataPointerPath) {\n\tvar error;\n\tfor (var key in data) {\n\t\tvar keyPointerPath = dataPointerPath + \"/\" + key.replace(/~/g, '~0').replace(/\\//g, '~1');\n\t\tvar foundMatch = false;\n\t\tif (schema.properties !== undefined && schema.properties[key] !== undefined) {\n\t\t\tfoundMatch = true;\n\t\t\tif (error = this.validateAll(data[key], schema.properties[key], [key], [\"properties\", key], keyPointerPath)) {\n\t\t\t\treturn error;\n\t\t\t}\n\t\t}\n\t\tif (schema.patternProperties !== undefined) {\n\t\t\tfor (var patternKey in schema.patternProperties) {\n\t\t\t\tvar regexp = new RegExp(patternKey);\n\t\t\t\tif (regexp.test(key)) {\n\t\t\t\t\tfoundMatch = true;\n\t\t\t\t\tif (error = this.validateAll(data[key], schema.patternProperties[patternKey], [key], [\"patternProperties\", patternKey], keyPointerPath)) {\n\t\t\t\t\t\treturn error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!foundMatch) {\n\t\t\tif (schema.additionalProperties !== undefined) {\n\t\t\t\tif (this.trackUnknownProperties) {\n\t\t\t\t\tthis.knownPropertyPaths[keyPointerPath] = true;\n\t\t\t\t\tdelete this.unknownPropertyPaths[keyPointerPath];\n\t\t\t\t}\n\t\t\t\tif (typeof schema.additionalProperties === \"boolean\") {\n\t\t\t\t\tif (!schema.additionalProperties) {\n\t\t\t\t\t\terror = this.createError(ErrorCodes.OBJECT_ADDITIONAL_PROPERTIES, {}).prefixWith(key, \"additionalProperties\");\n\t\t\t\t\t\tif (this.handleError(error)) {\n\t\t\t\t\t\t\treturn error;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (error = this.validateAll(data[key], schema.additionalProperties, [key], [\"additionalProperties\"], keyPointerPath)) {\n\t\t\t\t\t\treturn error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (this.trackUnknownProperties && !this.knownPropertyPaths[keyPointerPath]) {\n\t\t\t\tthis.unknownPropertyPaths[keyPointerPath] = true;\n\t\t\t}\n\t\t} else if (this.trackUnknownProperties) {\n\t\t\tthis.knownPropertyPaths[keyPointerPath] = true;\n\t\t\tdelete this.unknownPropertyPaths[keyPointerPath];\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateObjectDependencies = function validateObjectDependencies(data, schema, dataPointerPath) {\n\tvar error;\n\tif (schema.dependencies !== undefined) {\n\t\tfor (var depKey in schema.dependencies) {\n\t\t\tif (data[depKey] !== undefined) {\n\t\t\t\tvar dep = schema.dependencies[depKey];\n\t\t\t\tif (typeof dep === \"string\") {\n\t\t\t\t\tif (data[dep] === undefined) {\n\t\t\t\t\t\terror = this.createError(ErrorCodes.OBJECT_DEPENDENCY_KEY, {key: depKey, missing: dep}).prefixWith(null, depKey).prefixWith(null, \"dependencies\");\n\t\t\t\t\t\tif (this.handleError(error)) {\n\t\t\t\t\t\t\treturn error;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (Array.isArray(dep)) {\n\t\t\t\t\tfor (var i = 0; i < dep.length; i++) {\n\t\t\t\t\t\tvar requiredKey = dep[i];\n\t\t\t\t\t\tif (data[requiredKey] === undefined) {\n\t\t\t\t\t\t\terror = this.createError(ErrorCodes.OBJECT_DEPENDENCY_KEY, {key: depKey, missing: requiredKey}).prefixWith(null, \"\" + i).prefixWith(null, depKey).prefixWith(null, \"dependencies\");\n\t\t\t\t\t\t\tif (this.handleError(error)) {\n\t\t\t\t\t\t\t\treturn error;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (error = this.validateAll(data, dep, [], [\"dependencies\", depKey], dataPointerPath)) {\n\t\t\t\t\t\treturn error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateCombinations = function validateCombinations(data, schema, dataPointerPath) {\n\treturn this.validateAllOf(data, schema, dataPointerPath)\n\t\t|| this.validateAnyOf(data, schema, dataPointerPath)\n\t\t|| this.validateOneOf(data, schema, dataPointerPath)\n\t\t|| this.validateNot(data, schema, dataPointerPath)\n\t\t|| null;\n};\n\nValidatorContext.prototype.validateAllOf = function validateAllOf(data, schema, dataPointerPath) {\n\tif (schema.allOf === undefined) {\n\t\treturn null;\n\t}\n\tvar error;\n\tfor (var i = 0; i < schema.allOf.length; i++) {\n\t\tvar subSchema = schema.allOf[i];\n\t\tif (error = this.validateAll(data, subSchema, [], [\"allOf\", i], dataPointerPath)) {\n\t\t\treturn error;\n\t\t}\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateAnyOf = function validateAnyOf(data, schema, dataPointerPath) {\n\tif (schema.anyOf === undefined) {\n\t\treturn null;\n\t}\n\tvar errors = [];\n\tvar startErrorCount = this.errors.length;\n\tvar oldUnknownPropertyPaths, oldKnownPropertyPaths;\n\tif (this.trackUnknownProperties) {\n\t\toldUnknownPropertyPaths = this.unknownPropertyPaths;\n\t\toldKnownPropertyPaths = this.knownPropertyPaths;\n\t}\n\tvar errorAtEnd = true;\n\tfor (var i = 0; i < schema.anyOf.length; i++) {\n\t\tif (this.trackUnknownProperties) {\n\t\t\tthis.unknownPropertyPaths = {};\n\t\t\tthis.knownPropertyPaths = {};\n\t\t}\n\t\tvar subSchema = schema.anyOf[i];\n\n\t\tvar errorCount = this.errors.length;\n\t\tvar error = this.validateAll(data, subSchema, [], [\"anyOf\", i], dataPointerPath);\n\n\t\tif (error === null && errorCount === this.errors.length) {\n\t\t\tthis.errors = this.errors.slice(0, startErrorCount);\n\n\t\t\tif (this.trackUnknownProperties) {\n\t\t\t\tfor (var knownKey in this.knownPropertyPaths) {\n\t\t\t\t\toldKnownPropertyPaths[knownKey] = true;\n\t\t\t\t\tdelete oldUnknownPropertyPaths[knownKey];\n\t\t\t\t}\n\t\t\t\tfor (var unknownKey in this.unknownPropertyPaths) {\n\t\t\t\t\tif (!oldKnownPropertyPaths[unknownKey]) {\n\t\t\t\t\t\toldUnknownPropertyPaths[unknownKey] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// We need to continue looping so we catch all the property definitions, but we don't want to return an error\n\t\t\t\terrorAtEnd = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\treturn null;\n\t\t}\n\t\tif (error) {\n\t\t\terrors.push(error.prefixWith(null, \"\" + i).prefixWith(null, \"anyOf\"));\n\t\t}\n\t}\n\tif (this.trackUnknownProperties) {\n\t\tthis.unknownPropertyPaths = oldUnknownPropertyPaths;\n\t\tthis.knownPropertyPaths = oldKnownPropertyPaths;\n\t}\n\tif (errorAtEnd) {\n\t\terrors = errors.concat(this.errors.slice(startErrorCount));\n\t\tthis.errors = this.errors.slice(0, startErrorCount);\n\t\treturn this.createError(ErrorCodes.ANY_OF_MISSING, {}, \"\", \"/anyOf\", errors);\n\t}\n};\n\nValidatorContext.prototype.validateOneOf = function validateOneOf(data, schema, dataPointerPath) {\n\tif (schema.oneOf === undefined) {\n\t\treturn null;\n\t}\n\tvar validIndex = null;\n\tvar errors = [];\n\tvar startErrorCount = this.errors.length;\n\tvar oldUnknownPropertyPaths, oldKnownPropertyPaths;\n\tif (this.trackUnknownProperties) {\n\t\toldUnknownPropertyPaths = this.unknownPropertyPaths;\n\t\toldKnownPropertyPaths = this.knownPropertyPaths;\n\t}\n\tfor (var i = 0; i < schema.oneOf.length; i++) {\n\t\tif (this.trackUnknownProperties) {\n\t\t\tthis.unknownPropertyPaths = {};\n\t\t\tthis.knownPropertyPaths = {};\n\t\t}\n\t\tvar subSchema = schema.oneOf[i];\n\n\t\tvar errorCount = this.errors.length;\n\t\tvar error = this.validateAll(data, subSchema, [], [\"oneOf\", i], dataPointerPath);\n\n\t\tif (error === null && errorCount === this.errors.length) {\n\t\t\tif (validIndex === null) {\n\t\t\t\tvalidIndex = i;\n\t\t\t} else {\n\t\t\t\tthis.errors = this.errors.slice(0, startErrorCount);\n\t\t\t\treturn this.createError(ErrorCodes.ONE_OF_MULTIPLE, {index1: validIndex, index2: i}, \"\", \"/oneOf\");\n\t\t\t}\n\t\t\tif (this.trackUnknownProperties) {\n\t\t\t\tfor (var knownKey in this.knownPropertyPaths) {\n\t\t\t\t\toldKnownPropertyPaths[knownKey] = true;\n\t\t\t\t\tdelete oldUnknownPropertyPaths[knownKey];\n\t\t\t\t}\n\t\t\t\tfor (var unknownKey in this.unknownPropertyPaths) {\n\t\t\t\t\tif (!oldKnownPropertyPaths[unknownKey]) {\n\t\t\t\t\t\toldUnknownPropertyPaths[unknownKey] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (error) {\n\t\t\terrors.push(error.prefixWith(null, \"\" + i).prefixWith(null, \"oneOf\"));\n\t\t}\n\t}\n\tif (this.trackUnknownProperties) {\n\t\tthis.unknownPropertyPaths = oldUnknownPropertyPaths;\n\t\tthis.knownPropertyPaths = oldKnownPropertyPaths;\n\t}\n\tif (validIndex === null) {\n\t\terrors = errors.concat(this.errors.slice(startErrorCount));\n\t\tthis.errors = this.errors.slice(0, startErrorCount);\n\t\treturn this.createError(ErrorCodes.ONE_OF_MISSING, {}, \"\", \"/oneOf\", errors);\n\t} else {\n\t\tthis.errors = this.errors.slice(0, startErrorCount);\n\t}\n\treturn null;\n};\n\nValidatorContext.prototype.validateNot = function validateNot(data, schema, dataPointerPath) {\n\tif (schema.not === undefined) {\n\t\treturn null;\n\t}\n\tvar oldErrorCount = this.errors.length;\n\tvar oldUnknownPropertyPaths, oldKnownPropertyPaths;\n\tif (this.trackUnknownProperties) {\n\t\toldUnknownPropertyPaths = this.unknownPropertyPaths;\n\t\toldKnownPropertyPaths = this.knownPropertyPaths;\n\t\tthis.unknownPropertyPaths = {};\n\t\tthis.knownPropertyPaths = {};\n\t}\n\tvar error = this.validateAll(data, schema.not, null, null, dataPointerPath);\n\tvar notErrors = this.errors.slice(oldErrorCount);\n\tthis.errors = this.errors.slice(0, oldErrorCount);\n\tif (this.trackUnknownProperties) {\n\t\tthis.unknownPropertyPaths = oldUnknownPropertyPaths;\n\t\tthis.knownPropertyPaths = oldKnownPropertyPaths;\n\t}\n\tif (error === null && notErrors.length === 0) {\n\t\treturn this.createError(ErrorCodes.NOT_PASSED, {}, \"\", \"/not\");\n\t}\n\treturn null;\n};\n\n// parseURI() and resolveUrl() are from https://gist.github.com/1088850\n//   -  released as public domain by author (\"Yaffle\") - see comments on gist\n\nfunction parseURI(url) {\n\tvar m = String(url).replace(/^\\s+|\\s+$/g, '').match(/^([^:\\/?#]+:)?(\\/\\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\\/?#]*)(?::(\\d*))?))?([^?#]*)(\\?[^#]*)?(#[\\s\\S]*)?/);\n\t// authority = '//' + user + ':' + pass '@' + hostname + ':' port\n\treturn (m ? {\n\t\thref     : m[0] || '',\n\t\tprotocol : m[1] || '',\n\t\tauthority: m[2] || '',\n\t\thost     : m[3] || '',\n\t\thostname : m[4] || '',\n\t\tport     : m[5] || '',\n\t\tpathname : m[6] || '',\n\t\tsearch   : m[7] || '',\n\t\thash     : m[8] || ''\n\t} : null);\n}\n\nfunction resolveUrl(base, href) {// RFC 3986\n\n\tfunction removeDotSegments(input) {\n\t\tvar output = [];\n\t\tinput.replace(/^(\\.\\.?(\\/|$))+/, '')\n\t\t\t.replace(/\\/(\\.(\\/|$))+/g, '/')\n\t\t\t.replace(/\\/\\.\\.$/, '/../')\n\t\t\t.replace(/\\/?[^\\/]*/g, function (p) {\n\t\t\t\tif (p === '/..') {\n\t\t\t\t\toutput.pop();\n\t\t\t\t} else {\n\t\t\t\t\toutput.push(p);\n\t\t\t\t}\n\t\t});\n\t\treturn output.join('').replace(/^\\//, input.charAt(0) === '/' ? '/' : '');\n\t}\n\n\thref = parseURI(href || '');\n\tbase = parseURI(base || '');\n\n\treturn !href || !base ? null : (href.protocol || base.protocol) +\n\t\t(href.protocol || href.authority ? href.authority : base.authority) +\n\t\tremoveDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) +\n\t\t(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +\n\t\thref.hash;\n}\n\nfunction getDocumentUri(uri) {\n\treturn uri.split('#')[0];\n}\nfunction normSchema(schema, baseUri) {\n\tif (baseUri === undefined) {\n\t\tbaseUri = schema.id;\n\t} else if (typeof schema.id === \"string\") {\n\t\tbaseUri = resolveUrl(baseUri, schema.id);\n\t\tschema.id = baseUri;\n\t}\n\tif (typeof schema === \"object\") {\n\t\tif (Array.isArray(schema)) {\n\t\t\tfor (var i = 0; i < schema.length; i++) {\n\t\t\t\tnormSchema(schema[i], baseUri);\n\t\t\t}\n\t\t} else if (typeof schema['$ref'] === \"string\") {\n\t\t\tschema['$ref'] = resolveUrl(baseUri, schema['$ref']);\n\t\t} else {\n\t\t\tfor (var key in schema) {\n\t\t\t\tif (key !== \"enum\") {\n\t\t\t\t\tnormSchema(schema[key], baseUri);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar ErrorCodes = {\n\tINVALID_TYPE: 0,\n\tENUM_MISMATCH: 1,\n\tANY_OF_MISSING: 10,\n\tONE_OF_MISSING: 11,\n\tONE_OF_MULTIPLE: 12,\n\tNOT_PASSED: 13,\n\t// Numeric errors\n\tNUMBER_MULTIPLE_OF: 100,\n\tNUMBER_MINIMUM: 101,\n\tNUMBER_MINIMUM_EXCLUSIVE: 102,\n\tNUMBER_MAXIMUM: 103,\n\tNUMBER_MAXIMUM_EXCLUSIVE: 104,\n\t// String errors\n\tSTRING_LENGTH_SHORT: 200,\n\tSTRING_LENGTH_LONG: 201,\n\tSTRING_PATTERN: 202,\n\t// Object errors\n\tOBJECT_PROPERTIES_MINIMUM: 300,\n\tOBJECT_PROPERTIES_MAXIMUM: 301,\n\tOBJECT_REQUIRED: 302,\n\tOBJECT_ADDITIONAL_PROPERTIES: 303,\n\tOBJECT_DEPENDENCY_KEY: 304,\n\t// Array errors\n\tARRAY_LENGTH_SHORT: 400,\n\tARRAY_LENGTH_LONG: 401,\n\tARRAY_UNIQUE: 402,\n\tARRAY_ADDITIONAL_ITEMS: 403,\n\t// Format errors\n\tFORMAT_CUSTOM: 500,\n\t// Schema structure\n\tCIRCULAR_REFERENCE: 500,\n\t// Non-standard validation options\n\tUNKNOWN_PROPERTY: 1000\n};\nvar ErrorMessagesDefault = {\n\tINVALID_TYPE: \"invalid type: {type} (expected {expected})\",\n\tENUM_MISMATCH: \"No enum match for: {value}\",\n\tANY_OF_MISSING: \"Data does not match any schemas from \\\"anyOf\\\"\",\n\tONE_OF_MISSING: \"Data does not match any schemas from \\\"oneOf\\\"\",\n\tONE_OF_MULTIPLE: \"Data is valid against more than one schema from \\\"oneOf\\\": indices {index1} and {index2}\",\n\tNOT_PASSED: \"Data matches schema from \\\"not\\\"\",\n\t// Numeric errors\n\tNUMBER_MULTIPLE_OF: \"Value {value} is not a multiple of {multipleOf}\",\n\tNUMBER_MINIMUM: \"Value {value} is less than minimum {minimum}\",\n\tNUMBER_MINIMUM_EXCLUSIVE: \"Value {value} is equal to exclusive minimum {minimum}\",\n\tNUMBER_MAXIMUM: \"Value {value} is greater than maximum {maximum}\",\n\tNUMBER_MAXIMUM_EXCLUSIVE: \"Value {value} is equal to exclusive maximum {maximum}\",\n\t// String errors\n\tSTRING_LENGTH_SHORT: \"String is too short ({length} chars), minimum {minimum}\",\n\tSTRING_LENGTH_LONG: \"String is too long ({length} chars), maximum {maximum}\",\n\tSTRING_PATTERN: \"String does not match pattern: {pattern}\",\n\t// Object errors\n\tOBJECT_PROPERTIES_MINIMUM: \"Too few properties defined ({propertyCount}), minimum {minimum}\",\n\tOBJECT_PROPERTIES_MAXIMUM: \"Too many properties defined ({propertyCount}), maximum {maximum}\",\n\tOBJECT_REQUIRED: \"Missing required property: {key}\",\n\tOBJECT_ADDITIONAL_PROPERTIES: \"Additional properties not allowed\",\n\tOBJECT_DEPENDENCY_KEY: \"Dependency failed - key must exist: {missing} (due to key: {key})\",\n\t// Array errors\n\tARRAY_LENGTH_SHORT: \"Array is too short ({length}), minimum {minimum}\",\n\tARRAY_LENGTH_LONG: \"Array is too long ({length}), maximum {maximum}\",\n\tARRAY_UNIQUE: \"Array items are not unique (indices {match1} and {match2})\",\n\tARRAY_ADDITIONAL_ITEMS: \"Additional items not allowed\",\n\t// Format errors\n\tFORMAT_CUSTOM: \"Format validation failed ({message})\",\n\t// Schema structure\n\tCIRCULAR_REFERENCE: \"Circular $refs: {urls}\",\n\t// Non-standard validation options\n\tUNKNOWN_PROPERTY: \"Unknown property (not in schema)\"\n};\n\nfunction ValidationError(code, message, dataPath, schemaPath, subErrors) {\n\tif (code === undefined) {\n\t\tthrow new Error (\"No code supplied for error: \"+ message);\n\t}\n\tthis.code = code;\n\tthis.message = message;\n\tthis.dataPath = dataPath || \"\";\n\tthis.schemaPath = schemaPath || \"\";\n\tthis.subErrors = subErrors || null;\n}\nValidationError.prototype = new Error();\nValidationError.prototype.prefixWith = function (dataPrefix, schemaPrefix) {\n\tif (dataPrefix !== null) {\n\t\tdataPrefix = dataPrefix.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n\t\tthis.dataPath = \"/\" + dataPrefix + this.dataPath;\n\t}\n\tif (schemaPrefix !== null) {\n\t\tschemaPrefix = schemaPrefix.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n\t\tthis.schemaPath = \"/\" + schemaPrefix + this.schemaPath;\n\t}\n\tif (this.subErrors !== null) {\n\t\tfor (var i = 0; i < this.subErrors.length; i++) {\n\t\t\tthis.subErrors[i].prefixWith(dataPrefix, schemaPrefix);\n\t\t}\n\t}\n\treturn this;\n};\n\nfunction isTrustedUrl(baseUrl, testUrl) {\n\tif(testUrl.substring(0, baseUrl.length) === baseUrl){\n\t\tvar remainder = testUrl.substring(baseUrl.length);\n\t\tif ((testUrl.length > 0 && testUrl.charAt(baseUrl.length - 1) === \"/\")\n\t\t\t|| remainder.charAt(0) === \"#\"\n\t\t\t|| remainder.charAt(0) === \"?\") {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nvar languages = {};\nfunction createApi(language) {\n\tvar globalContext = new ValidatorContext();\n\tvar currentLanguage = language || 'en';\n\tvar api = {\n\t\taddFormat: function () {\n\t\t\tglobalContext.addFormat.apply(globalContext, arguments);\n\t\t},\n\t\tlanguage: function (code) {\n\t\t\tif (!code) {\n\t\t\t\treturn currentLanguage;\n\t\t\t}\n\t\t\tif (!languages[code]) {\n\t\t\t\tcode = code.split('-')[0]; // fall back to base language\n\t\t\t}\n\t\t\tif (languages[code]) {\n\t\t\t\tcurrentLanguage = code;\n\t\t\t\treturn code; // so you can tell if fall-back has happened\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\taddLanguage: function (code, messageMap) {\n\t\t\tvar key;\n\t\t\tfor (key in ErrorCodes) {\n\t\t\t\tif (messageMap[key] && !messageMap[ErrorCodes[key]]) {\n\t\t\t\t\tmessageMap[ErrorCodes[key]] = messageMap[key];\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar rootCode = code.split('-')[0];\n\t\t\tif (!languages[rootCode]) { // use for base language if not yet defined\n\t\t\t\tlanguages[code] = messageMap;\n\t\t\t\tlanguages[rootCode] = messageMap;\n\t\t\t} else {\n\t\t\t\tlanguages[code] = Object.create(languages[rootCode]);\n\t\t\t\tfor (key in messageMap) {\n\t\t\t\t\tif (typeof languages[rootCode][key] === 'undefined') {\n\t\t\t\t\t\tlanguages[rootCode][key] = messageMap[key];\n\t\t\t\t\t}\n\t\t\t\t\tlanguages[code][key] = messageMap[key];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\t\tfreshApi: function (language) {\n\t\t\tvar result = createApi();\n\t\t\tif (language) {\n\t\t\t\tresult.language(language);\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\tvalidate: function (data, schema, checkRecursive, banUnknownProperties) {\n\t\t\tvar context = new ValidatorContext(globalContext, false, languages[currentLanguage], checkRecursive, banUnknownProperties);\n\t\t\tif (typeof schema === \"string\") {\n\t\t\t\tschema = {\"$ref\": schema};\n\t\t\t}\n\t\t\tcontext.addSchema(\"\", schema);\n\t\t\tvar error = context.validateAll(data, schema, null, null, \"\");\n\t\t\tif (!error && banUnknownProperties) {\n\t\t\t\terror = context.banUnknownProperties();\n\t\t\t}\n\t\t\tthis.error = error;\n\t\t\tthis.missing = context.missing;\n\t\t\tthis.valid = (error === null);\n\t\t\treturn this.valid;\n\t\t},\n\t\tvalidateResult: function () {\n\t\t\tvar result = {};\n\t\t\tthis.validate.apply(result, arguments);\n\t\t\treturn result;\n\t\t},\n\t\tvalidateMultiple: function (data, schema, checkRecursive, banUnknownProperties) {\n\t\t\tvar context = new ValidatorContext(globalContext, true, languages[currentLanguage], checkRecursive, banUnknownProperties);\n\t\t\tif (typeof schema === \"string\") {\n\t\t\t\tschema = {\"$ref\": schema};\n\t\t\t}\n\t\t\tcontext.addSchema(\"\", schema);\n\t\t\tcontext.validateAll(data, schema, null, null, \"\");\n\t\t\tif (banUnknownProperties) {\n\t\t\t\tcontext.banUnknownProperties();\n\t\t\t}\n\t\t\tvar result = {};\n\t\t\tresult.errors = context.errors;\n\t\t\tresult.missing = context.missing;\n\t\t\tresult.valid = (result.errors.length === 0);\n\t\t\treturn result;\n\t\t},\n\t\taddSchema: function () {\n\t\t\treturn globalContext.addSchema.apply(globalContext, arguments);\n\t\t},\n\t\tgetSchema: function () {\n\t\t\treturn globalContext.getSchema.apply(globalContext, arguments);\n\t\t},\n\t\tgetSchemaMap: function () {\n\t\t\treturn globalContext.getSchemaMap.apply(globalContext, arguments);\n\t\t},\n\t\tgetSchemaUris: function () {\n\t\t\treturn globalContext.getSchemaUris.apply(globalContext, arguments);\n\t\t},\n\t\tgetMissingUris: function () {\n\t\t\treturn globalContext.getMissingUris.apply(globalContext, arguments);\n\t\t},\n\t\tdropSchemas: function () {\n\t\t\tglobalContext.dropSchemas.apply(globalContext, arguments);\n\t\t},\n\t\treset: function () {\n\t\t\tglobalContext.reset();\n\t\t\tthis.error = null;\n\t\t\tthis.missing = [];\n\t\t\tthis.valid = true;\n\t\t},\n\t\tmissing: [],\n\t\terror: null,\n\t\tvalid: true,\n\t\tnormSchema: normSchema,\n\t\tresolveUrl: resolveUrl,\n\t\tgetDocumentUri: getDocumentUri,\n\t\terrorCodes: ErrorCodes\n\t};\n\treturn api;\n}\n\nvar tv4 = createApi();\ntv4.addLanguage('en-gb', ErrorMessagesDefault);\n\n//legacy property\ntv4.tv4 = tv4;\n\nif (typeof module !== 'undefined' && module.exports){\n\tmodule.exports = tv4;\n}\nelse {\n\tglobal.tv4 = tv4;\n}\n\n})(this);\n\n//@ sourceMappingURL=tv4.js.map//@ sourceURL=tv4/tv4.js"
+));
+require.alias("tv4/tv4.js", "tv4/index.js");
+
Index: Dev/trunk/src/node_modules/tv4/lang/de.js
===================================================================
--- Dev/trunk/src/node_modules/tv4/lang/de.js	(revision 484)
+++ Dev/trunk/src/node_modules/tv4/lang/de.js	(revision 484)
@@ -0,0 +1,29 @@
+tv4.addLanguage('de',  {
+    INVALID_TYPE: "UngÃŒltiger Typ: {type} (erwartet wurde: {expected})",
+    ENUM_MISMATCH: "Keine Ãbereinstimmung mit der AufzÃ€hlung (enum) fÃŒr: {value}",
+    ANY_OF_MISSING: "Daten stimmen nicht ÃŒberein mit einem der Schemas von \"anyOf\"",
+    ONE_OF_MISSING: "Daten stimmen nicht ÃŒberein mit einem der Schemas von \"oneOf\"",
+    ONE_OF_MULTIPLE: "Daten sind valid in Bezug auf mehreren Schemas von \"oneOf\": index {index1} und {index2}",
+    NOT_PASSED: "Daten stimmen mit dem \"not\" Schema ÃŒberein",
+    // Numeric errors
+    NUMBER_MULTIPLE_OF: "Wert {value} ist kein Vielfaches von {multipleOf}",
+    NUMBER_MINIMUM: "Wert {value} ist kleiner als das Minimum {minimum}",
+    NUMBER_MINIMUM_EXCLUSIVE: "Wert {value} ist gleich dem Exklusiven Minimum {minimum}",
+    NUMBER_MAXIMUM: "Wert {value} ist grÃ¶Ãer als das Maximum {maximum}",
+    NUMBER_MAXIMUM_EXCLUSIVE: "Wert {value} ist gleich dem Exklusiven Maximum {maximum}",
+    // String errors
+    STRING_LENGTH_SHORT: "Zeichenkette zu kurz ({length} chars), minimum {minimum}",
+    STRING_LENGTH_LONG: "Zeichenkette zu lang ({length} chars), maximum {maximum}",
+    STRING_PATTERN: "Zeichenkette entspricht nicht dem Muster: {pattern}",
+    // Object errors
+    OBJECT_PROPERTIES_MINIMUM: "Zu wenige Attribute definiert ({propertyCount}), minimum {minimum}",
+    OBJECT_PROPERTIES_MAXIMUM: "Zu viele Attribute definiert ({propertyCount}), maximum {maximum}",
+    OBJECT_REQUIRED: "Notwendiges Attribut fehlt: {key}",
+    OBJECT_ADDITIONAL_PROPERTIES: "ZusÃ€tzliche Attribute nicht erlaubt",
+    OBJECT_DEPENDENCY_KEY: "AbhÃ€ngigkeit fehlt - SchlÃŒssel nicht vorhanden: {missing} (wegen SchlÃŒssel: {key})",
+    // Array errors
+    ARRAY_LENGTH_SHORT: "Array zu kurz ({length}), minimum {minimum}",
+    ARRAY_LENGTH_LONG: "Array zu lang ({length}), maximum {maximum}",
+    ARRAY_UNIQUE: "Array EintrÃ€ge nicht eindeutig (Index {match1} und {match2})",
+    ARRAY_ADDITIONAL_ITEMS: "ZusÃ€tzliche EintrÃ€ge nicht erlaubt"
+});
Index: Dev/trunk/src/node_modules/tv4/package.json
===================================================================
--- Dev/trunk/src/node_modules/tv4/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/tv4/package.json	(revision 484)
@@ -0,0 +1,69 @@
+{
+  "name": "tv4",
+  "version": "1.0.11",
+  "author": {
+    "name": "Geraint Luff"
+  },
+  "description": "A public domain JSON Schema validator for JavaScript",
+  "keywords": [
+    "json-schema",
+    "schema",
+    "validator",
+    "tv4"
+  ],
+  "maintainers": [
+    {
+      "name": "Geraint Luff",
+      "email": "luffgd@gmail.com",
+      "url": "https://github.com/geraintluff/"
+    }
+  ],
+  "main": "tv4.js",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/geraintluff/tv4.git"
+  },
+  "license:": [
+    {
+      "type": "Public Domain",
+      "url": "http://geraintluff.github.io/tv4/LICENSE.txt"
+    },
+    {
+      "type": "MIT",
+      "url": "http://jsonary.com/LICENSE.txt"
+    }
+  ],
+  "devDependencies": {
+    "grunt": "~0.4.1",
+    "grunt-contrib-clean": "~0.4.1",
+    "grunt-contrib-jshint": "~0.6.2",
+    "mocha": "~1.11.0",
+    "grunt-mocha": "~0.4",
+    "grunt-mocha-test": "~0.5.0",
+    "grunt-cli": "~0.1.9",
+    "grunt-contrib-uglify": "~0.2.2",
+    "grunt-contrib-copy": "~0.4.1",
+    "proclaim": "1.4",
+    "mocha-unfunk-reporter": "~0.2",
+    "jshint-path-reporter": "~0.1",
+    "grunt-concat-sourcemap": "~0.2",
+    "source-map-support": "~0.1",
+    "grunt-markdown": "~0.3.0",
+    "grunt-component": "~0.1.4",
+    "grunt-push-release": "~0.1.1"
+  },
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "test": "grunt test"
+  },
+  "readme": "# Tiny Validator (for v4 JSON Schema)\n\n[![Build Status](https://secure.travis-ci.org/geraintluff/tv4.png?branch=master)](http://travis-ci.org/geraintluff/tv4) [![Dependency Status](https://gemnasium.com/geraintluff/tv4.png)](https://gemnasium.com/geraintluff/tv4) [![NPM version](https://badge.fury.io/js/tv4.png)](http://badge.fury.io/js/tv4)\n\nUse [json-schema](http://json-schema.org/) [draft v4](http://json-schema.org/latest/json-schema-core.html) to validate simple values and complex objects using a rich [validation vocabulary](http://json-schema.org/latest/json-schema-validation.html) ([examples](http://json-schema.org/examples.html)).\n\nThere is support for `$ref` with JSON Pointer fragment paths (```other-schema.json#/properties/myKey```).\n\n## Usage 1: Simple validation\n\n```javascript\nvar valid = tv4.validate(data, schema);\n```\n\nIf validation returns ```false```, then an explanation of why validation failed can be found in ```tv4.error```.\n\nThe error object will look something like:\n```json\n{\n    \"code\": 0,\n    \"message\": \"Invalid type: string\",\n    \"dataPath\": \"/intKey\",\n    \"schemaKey\": \"/properties/intKey/type\"\n}\n```\n\nThe `\"code\"` property will refer to one of the values in `tv4.errorCodes` - in this case, `tv4.errorCodes.INVALID_TYPE`.\n\nTo enable external schema to be referenced, you use:\n```javascript\ntv4.addSchema(url, schema);\n```\n\nIf schemas are referenced (```$ref```) but not known, then validation will return ```true``` and the missing schema(s) will be listed in ```tv4.missing```. For more info see the API documentation below.\n\n## Usage 2: Multi-threaded validation\n\nStoring the error and missing schemas does not work well in multi-threaded environments, so there is an alternative syntax:\n\n```javascript\nvar result = tv4.validateResult(data, schema);\n```\n\nThe result will look something like:\n```json\n{\n    \"valid\": false,\n    \"error\": {...},\n    \"missing\": [...]\n}\n```\n\n## Usage 3: Multiple errors\n\nNormally, `tv4` stops when it encounters the first validation error.  However, you can collect an array of validation errors using:\n\n```javascript\nvar result = tv4.validateMultiple(data, schema);\n```\n\nThe result will look something like:\n```json\n{\n    \"valid\": false,\n    \"errors\": [\n        {...},\n        ...\n    ],\n    \"missing\": [...]\n}\n```\n\n## Asynchronous validation\n\nSupport for asynchronous validation (where missing schemas are fetched) can be added by including an extra JavaScript file.  Currently, the only version requires jQuery (`tv4.async-jquery.js`), but the code is very short and should be fairly easy to modify for other libraries (such as MooTools).\n\nUsage:\n\n```javascript\ntv4.validate(data, schema, function (isValid, validationError) { ... });\n```\n\n`validationFailure` is simply taken from `tv4.error`.\n\n## Cyclical JavaScript objects\n\nWhile they don't occur in proper JSON, JavaScript does support self-referencing objects. Any of the above calls support an optional final argument, checkRecursive. If true, tv4 will handle self-referencing objects properly - this slows down validation slightly, but that's better than a hanging script.\n\nConsider this data, notice how both `a` and `b` refer to each other:\n\n```javascript\nvar a = {};\nvar b = { a: a };\na.b = b;\nvar aSchema = { properties: { b: { $ref: 'bSchema' }}};\nvar bSchema = { properties: { a: { $ref: 'aSchema' }}};\ntv4.addSchema('aSchema', aSchema);\ntv4.addSchema('bSchema', bSchema);\n```\n\nIf the final checkRecursive argument were missing, this would throw a \"too much recursion\" error. \n\nTo enable supprot for this pass `true` as additional argument to any of the regular validation methods: \n\n```javascript\ntv4.validate(a, aSchema, true);\ntv4.validate(a, schema, asynchronousFunction, true);\n\ntv4.validateResult(data, aSchema, true); \ntv4.validateMultiple(data, aSchema, true);\n```\n\n## API\n\nThere are additional api commands available for more complex use-cases:\n\n##### addSchema(uri, schema)\nPre-register a schema for reference by other schema and synchronous validation.\n\n````js\ntv4.addSchema('http://example.com/schema', { ... });\n````\n\n* `uri` the uri to identify this schema.\n* `schema` the schema object.\n\nSchemas that have their `id` property set can be added directly.\n\n````js\ntv4.addSchema({ ... });\n````\n\n##### getSchema(uri)\n\nReturn a schema from the cache.\n\n* `uri` the uri of the schema (may contain a `#` fragment)\n\n````js\nvar schema = tv4.getSchema('http://example.com/schema');\n````\n\n##### getSchemaMap()\n\nReturn a shallow copy of the schema cache, mapping schema document URIs to schema objects.\n\n````\nvar map = tv4.getSchemaMap();\n\nvar schema = map[uri];\n````\n\n##### getSchemaUris(filter)\n\nReturn an Array with known schema document URIs.\n\n* `filter` optional RegExp to filter URIs\n\n````\nvar arr = tv4.getSchemaUris();\n\n// optional filter using a RegExp\nvar arr = tv4.getSchemaUris(/^https?://example.com/);\n````\n\n##### getMissingUris(filter)\n\nReturn an Array with schema document URIs that are used as `$ref` in known schemas but which currently have no associated schema data.\n\nUse this in combination with `tv4.addSchema(uri, schema)` to preload the cache for complete synchronous validation with.\n\n* `filter` optional RegExp to filter URIs\n\n````\nvar arr = tv4.getMissingUris();\n\n// optional filter using a RegExp\nvar arr = tv4.getMissingUris(/^https?://example.com/);\n````\n\n##### dropSchemas()\n\nDrop all known schema document URIs from the cache.\n\n````\ntv4.dropSchemas();\n````\n\n##### freshApi()\n\nReturn a new tv4 instance with no shared state.\n\n````\nvar otherTV4 = tv4.freshApi();\n````\n\n##### reset()\n\nManually reset validation status from the simple `tv4.validate(data, schema)`. Although tv4 will self reset on each validation there are some implementation scenarios where this is useful.\n\n````\ntv4.reset();\n````\n\n##### language(code)\n\nSelect the language map used for reporting.\n\n* `code` is a language code, like `'en'` or `'en-gb'`\n\n````\ntv4.language('en-gb');\n````\n\n##### addLanguage(code, map)\n\nAdd a new language map for selection by `tv4.language(code)`\n\n* `code` is new language code\n* `map` is an object mapping error IDs or constant names (e.g. `103` or `\"NUMBER_MAXIMUM\"`) to language strings.\n\n````\ntv4.addLanguage('fr', { ... });\n\n// select for use\ntv4.language('fr')\n````\n\n##### addFormat(format, validationFunction)\n\nAdd a custom format validator.\n\n* `format` is a string, corresponding to the `\"format\"` value in schemas.\n* `validationFunction` is a function that either returns:\n  * `null` (meaning no error)\n  * an error string (explaining the reason for failure)\n\n````\ntv4.addFormat('decimal-digits', function (data, schema) {\n\tif (typeof data === 'string' && !/^[0-9]+$/.test(data)) {\n\t\treturn null;\n\t}\n\treturn \"must be string of decimal digits\";\n});\n````\n\nAlternatively, multiple formats can be added at the same time using an object:\n````\ntv4.addFormat({\n\t'my-format': function () {...},\n\t'other-format': function () {...}\n});\n````\n\n## Demos\n\n### Basic usage\n<div class=\"content inline-demo\" markdown=\"1\" data-demo=\"demo1\">\n<pre class=\"code\" id=\"demo1\">\nvar schema = {\n\t\"items\": {\n\t\t\"type\": \"boolean\"\n\t}\n};\nvar data1 = [true, false];\nvar data2 = [true, 123];\n\nalert(\"data 1: \" + tv4.validate(data1, schema)); // true\nalert(\"data 2: \" + tv4.validate(data2, schema)); // false\nalert(\"data 2 error: \" + JSON.stringify(tv4.error, null, 4));\n</pre>\n</div>\n\n### Use of <code>$ref</code>\n<div class=\"content inline-demo\" markdown=\"1\" data-demo=\"demo2\">\n<pre class=\"code\" id=\"demo2\">\nvar schema = {\n\t\"type\": \"array\",\n\t\"items\": {\"$ref\": \"#\"}\n};\nvar data1 = [[], [[]]];\nvar data2 = [[], [true, []]];\n\nalert(\"data 1: \" + tv4.validate(data1, schema)); // true\nalert(\"data 2: \" + tv4.validate(data2, schema)); // false\n</pre>\n</div>\n\n### Missing schema\n<div class=\"content inline-demo\" markdown=\"1\" data-demo=\"demo3\">\n<pre class=\"code\" id=\"demo3\">\nvar schema = {\n\t\"type\": \"array\",\n\t\"items\": {\"$ref\": \"http://example.com/schema\" }\n};\nvar data = [1, 2, 3];\n\nalert(\"Valid: \" + tv4.validate(data, schema)); // true\nalert(\"Missing schemas: \" + JSON.stringify(tv4.missing));\n</pre>\n</div>\n\n### Referencing remote schema\n<div class=\"content inline-demo\" markdown=\"1\" data-demo=\"demo4\">\n<pre class=\"code\" id=\"demo4\">\ntv4.addSchema(\"http://example.com/schema\", {\n\t\"definitions\": {\n\t\t\"arrayItem\": {\"type\": \"boolean\"}\n\t}\n});\nvar schema = {\n\t\"type\": \"array\",\n\t\"items\": {\"$ref\": \"http://example.com/schema#/definitions/arrayItem\" }\n};\nvar data1 = [true, false, true];\nvar data2 = [1, 2, 3];\n\nalert(\"data 1: \" + tv4.validate(data1, schema)); // true\nalert(\"data 2: \" + tv4.validate(data2, schema)); // false\n</pre>\n</div>\n\n## Supported platforms\n\n* Node.js\n* All modern browsers\n* IE >= 7\n\n## Installation\n\nYou can manually download [`tv4.js`](https://raw.github.com/geraintluff/tv4/master/tv4.js) or the minified [`tv4.min.js`](https://raw.github.com/geraintluff/tv4/master/tv4.min.js) and include it in your html to create the global `tv4` variable.\n\nAlternately use it as a CommonJS module:\n\n````js\nvar tv4 = require('tv4');\n````\n\n#### npm\n\n````\n$ npm install tv4\n````\n\n#### bower\n\n````\n$ bower install tv4\n````\n\n#### component.io\n\n````\n$ component install geraintluff/tv4\n````\n\n## Build and test\n\nYou can rebuild and run the node and browser tests using node.js and [grunt](http://http://gruntjs.com/):\n\nMake sure you have the global grunt cli command:\n````\n$ npm install grunt-cli -g\n````\n\nClone the git repos, open a shell in the root folder and install the development dependencies:\n\n````\n$ npm install\n````\n\nRebuild and run the tests:\n````\n$ grunt\n````\n\nIt will run a build and display one Spec-style report for the node.js and two Dot-style reports for both the plain and minified browser tests (via phantomJS). You can also use your own browser to manually run the suites by opening [`test/index.html`](http://geraintluff.github.io/tv4/test/index.html) and [`test/index-min.html`](http://geraintluff.github.io/tv4/test/index-min.html).\n\n## Contributing\n\nPull-requests for fixes and expansions are welcome. Edit the partial files in `/source` and add your tests in a suitable suite or folder under `/test/tests` and run `grunt` to rebuild and run the test suite. Try to maintain an idiomatic coding style and add tests for any new features. It is recommend to discuss big changes in an Issue.\n\n## Packages using tv4\n\n* [chai-json-schema](http://chaijs.com/plugins/chai-json-schema) is a [Chai Assertion Library](http://chaijs.com) plugin to assert values against json-schema.\n* [grunt-tv4](http://www.github.com/Bartvds/grunt-tv4) is a plugin for [Grunt](http://http://gruntjs.com/) that uses tv4 to bulk validate json files.\n\n## License\n\nThe code is available as \"public domain\", meaning that it is completely free to use, without any restrictions at all.  Read the full license [here](http://geraintluff.github.com/tv4/LICENSE.txt).\n\nIt's also available under an [MIT license](http://jsonary.com/LICENSE.txt).\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/geraintluff/tv4/issues"
+  },
+  "homepage": "https://github.com/geraintluff/tv4",
+  "_id": "tv4@1.0.11",
+  "_from": "tv4@"
+}
Index: Dev/trunk/src/node_modules/tv4/tv4.async-jquery.js
===================================================================
--- Dev/trunk/src/node_modules/tv4/tv4.async-jquery.js	(revision 484)
+++ Dev/trunk/src/node_modules/tv4/tv4.async-jquery.js	(revision 484)
@@ -0,0 +1,34 @@
+// Provides support for asynchronous validation (fetching schemas) using jQuery
+// Callback is optional third argument to tv4.validate() - if not present, synchronous operation
+//     callback(result, error);
+if (typeof (tv4.asyncValidate) === 'undefined') {
+	tv4.syncValidate = tv4.validate;
+	tv4.validate = function (data, schema, callback, checkRecursive) {
+		if (typeof (callback) === 'undefined') {
+			return this.syncValidate(data, schema, checkRecursive);
+		} else {
+			return this.asyncValidate(data, schema, callback, checkRecursive);
+		}
+	};
+	tv4.asyncValidate = function (data, schema, callback, checkRecursive) {
+		var $ = jQuery;
+		var result = tv4.validate(data, schema, checkRecursive);
+		if (!tv4.missing.length) {
+			callback(result, tv4.error);
+		} else {
+			// Make a request for each missing schema
+			var missingSchemas = $.map(tv4.missing, function (schemaUri) {
+				return $.getJSON(schemaUri).success(function (fetchedSchema) {
+					tv4.addSchema(schemaUri, fetchedSchema);
+				}).error(function () {
+					// If there's an error, just use an empty schema
+					tv4.addSchema(schemaUri, {});
+				});
+			});
+			// When all requests done, try again
+			$.when.apply($, missingSchemas).done(function () {
+				var result = tv4.asyncValidate(data, schema, callback, checkRecursive);
+			});
+		}
+	};
+}
Index: Dev/trunk/src/node_modules/tv4/tv4.js
===================================================================
--- Dev/trunk/src/node_modules/tv4/tv4.js	(revision 484)
+++ Dev/trunk/src/node_modules/tv4/tv4.js	(revision 484)
@@ -0,0 +1,1268 @@
+/*
+Author: Geraint Luff and others
+Year: 2013
+
+This code is released into the "public domain" by its author(s).  Anybody may use, alter and distribute the code without restriction.  The author makes no guarantees, and takes no liability of any kind for use of this code.
+
+If you find a bug or make an improvement, it would be courteous to let the author know, but it is not compulsory.
+*/
+(function (global) {
+'use strict';
+
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2Fkeys
+if (!Object.keys) {
+	Object.keys = (function () {
+		var hasOwnProperty = Object.prototype.hasOwnProperty,
+			hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
+			dontEnums = [
+				'toString',
+				'toLocaleString',
+				'valueOf',
+				'hasOwnProperty',
+				'isPrototypeOf',
+				'propertyIsEnumerable',
+				'constructor'
+			],
+			dontEnumsLength = dontEnums.length;
+
+		return function (obj) {
+			if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) {
+				throw new TypeError('Object.keys called on non-object');
+			}
+
+			var result = [];
+
+			for (var prop in obj) {
+				if (hasOwnProperty.call(obj, prop)) {
+					result.push(prop);
+				}
+			}
+
+			if (hasDontEnumBug) {
+				for (var i=0; i < dontEnumsLength; i++) {
+					if (hasOwnProperty.call(obj, dontEnums[i])) {
+						result.push(dontEnums[i]);
+					}
+				}
+			}
+			return result;
+		};
+	})();
+}
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
+if (!Object.create) {
+	Object.create = (function(){
+		function F(){}
+
+		return function(o){
+			if (arguments.length !== 1) {
+				throw new Error('Object.create implementation only accepts one parameter.');
+			}
+			F.prototype = o;
+			return new F();
+		};
+	})();
+}
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2FisArray
+if(!Array.isArray) {
+	Array.isArray = function (vArg) {
+		return Object.prototype.toString.call(vArg) === "[object Array]";
+	};
+}
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2FindexOf
+if (!Array.prototype.indexOf) {
+	Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
+		if (this === null) {
+			throw new TypeError();
+		}
+		var t = Object(this);
+		var len = t.length >>> 0;
+
+		if (len === 0) {
+			return -1;
+		}
+		var n = 0;
+		if (arguments.length > 1) {
+			n = Number(arguments[1]);
+			if (n !== n) { // shortcut for verifying if it's NaN
+				n = 0;
+			} else if (n !== 0 && n !== Infinity && n !== -Infinity) {
+				n = (n > 0 || -1) * Math.floor(Math.abs(n));
+			}
+		}
+		if (n >= len) {
+			return -1;
+		}
+		var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+		for (; k < len; k++) {
+			if (k in t && t[k] === searchElement) {
+				return k;
+			}
+		}
+		return -1;
+	};
+}
+
+// Grungey Object.isFrozen hack
+if (!Object.isFrozen) {
+	Object.isFrozen = function (obj) {
+		var key = "tv4_test_frozen_key";
+		while (obj.hasOwnProperty(key)) {
+			key += Math.random();
+		}
+		try {
+			obj[key] = true;
+			delete obj[key];
+			return false;
+		} catch (e) {
+			return true;
+		}
+	};
+}
+var ValidatorContext = function ValidatorContext(parent, collectMultiple, errorMessages, checkRecursive, trackUnknownProperties) {
+	this.missing = [];
+	this.missingMap = {};
+	this.formatValidators = parent ? Object.create(parent.formatValidators) : {};
+	this.schemas = parent ? Object.create(parent.schemas) : {};
+	this.collectMultiple = collectMultiple;
+	this.errors = [];
+	this.handleError = collectMultiple ? this.collectError : this.returnError;
+	if (checkRecursive) {
+		this.checkRecursive = true;
+		this.scanned = [];
+		this.scannedFrozen = [];
+		this.scannedFrozenSchemas = [];
+		this.key = 'tv4_validation_id';
+	}
+	if (trackUnknownProperties) {
+		this.trackUnknownProperties = true;
+		this.knownPropertyPaths = {};
+		this.unknownPropertyPaths = {};
+	}
+	this.errorMessages = errorMessages;
+};
+ValidatorContext.prototype.createError = function (code, messageParams, dataPath, schemaPath, subErrors) {
+	var messageTemplate = this.errorMessages[code] || ErrorMessagesDefault[code];
+	if (typeof messageTemplate !== 'string') {
+		return new ValidationError(code, "Unknown error code " + code + ": " + JSON.stringify(messageParams), dataPath, schemaPath, subErrors);
+	}
+	// Adapted from Crockford's supplant()
+	var message = messageTemplate.replace(/\{([^{}]*)\}/g, function (whole, varName) {
+		var subValue = messageParams[varName];
+		return typeof subValue === 'string' || typeof subValue === 'number' ? subValue : whole;
+	});
+	return new ValidationError(code, message, dataPath, schemaPath, subErrors);
+};
+ValidatorContext.prototype.returnError = function (error) {
+	return error;
+};
+ValidatorContext.prototype.collectError = function (error) {
+	if (error) {
+		this.errors.push(error);
+	}
+	return null;
+};
+ValidatorContext.prototype.prefixErrors = function (startIndex, dataPath, schemaPath) {
+	for (var i = startIndex; i < this.errors.length; i++) {
+		this.errors[i] = this.errors[i].prefixWith(dataPath, schemaPath);
+	}
+	return this;
+};
+ValidatorContext.prototype.banUnknownProperties = function () {
+	for (var unknownPath in this.unknownPropertyPaths) {
+		var error = this.createError(ErrorCodes.UNKNOWN_PROPERTY, {path: unknownPath}, unknownPath, "");
+		var result = this.handleError(error);
+		if (result) {
+			return result;
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.addFormat = function (format, validator) {
+	if (typeof format === 'object') {
+		for (var key in format) {
+			this.addFormat(key, format[key]);
+		}
+		return this;
+	}
+	this.formatValidators[format] = validator;
+};
+ValidatorContext.prototype.resolveRefs = function (schema, urlHistory) {
+	if (schema['$ref'] !== undefined) {
+		urlHistory = urlHistory || {};
+		if (urlHistory[schema['$ref']]) {
+			return this.createError(ErrorCodes.CIRCULAR_REFERENCE, {urls: Object.keys(urlHistory).join(', ')}, '', '');
+		}
+		urlHistory[schema['$ref']] = true;
+		schema = this.getSchema(schema['$ref'], urlHistory);
+	}
+	return schema;
+};
+ValidatorContext.prototype.getSchema = function (url, urlHistory) {
+	var schema;
+	if (this.schemas[url] !== undefined) {
+		schema = this.schemas[url];
+		return this.resolveRefs(schema, urlHistory);
+	}
+	var baseUrl = url;
+	var fragment = "";
+	if (url.indexOf('#') !== -1) {
+		fragment = url.substring(url.indexOf("#") + 1);
+		baseUrl = url.substring(0, url.indexOf("#"));
+	}
+	if (typeof this.schemas[baseUrl] === 'object') {
+		schema = this.schemas[baseUrl];
+		var pointerPath = decodeURIComponent(fragment);
+		if (pointerPath === "") {
+			return this.resolveRefs(schema, urlHistory);
+		} else if (pointerPath.charAt(0) !== "/") {
+			return undefined;
+		}
+		var parts = pointerPath.split("/").slice(1);
+		for (var i = 0; i < parts.length; i++) {
+			var component = parts[i].replace(/~1/g, "/").replace(/~0/g, "~");
+			if (schema[component] === undefined) {
+				schema = undefined;
+				break;
+			}
+			schema = schema[component];
+		}
+		if (schema !== undefined) {
+			return this.resolveRefs(schema, urlHistory);
+		}
+	}
+	if (this.missing[baseUrl] === undefined) {
+		this.missing.push(baseUrl);
+		this.missing[baseUrl] = baseUrl;
+		this.missingMap[baseUrl] = baseUrl;
+	}
+};
+ValidatorContext.prototype.searchSchemas = function (schema, url) {
+	if (typeof schema.id === "string") {
+		if (isTrustedUrl(url, schema.id)) {
+			if (this.schemas[schema.id] === undefined) {
+				this.schemas[schema.id] = schema;
+			}
+		}
+	}
+	if (typeof schema === "object") {
+		for (var key in schema) {
+			if (key !== "enum") {
+				if (typeof schema[key] === "object") {
+					this.searchSchemas(schema[key], url);
+				} else if (key === "$ref") {
+					var uri = getDocumentUri(schema[key]);
+					if (uri && this.schemas[uri] === undefined && this.missingMap[uri] === undefined) {
+						this.missingMap[uri] = uri;
+					}
+				}
+			}
+		}
+	}
+};
+ValidatorContext.prototype.addSchema = function (url, schema) {
+	//overload
+	if (typeof schema === 'undefined') {
+		if (typeof url === 'object' && typeof url.id === 'string') {
+			schema = url;
+			url = schema.id;
+		}
+		else {
+			return;
+		}
+	}
+	if (url = getDocumentUri(url) + "#") {
+		// Remove empty fragment
+		url = getDocumentUri(url);
+	}
+	this.schemas[url] = schema;
+	delete this.missingMap[url];
+	normSchema(schema, url);
+	this.searchSchemas(schema, url);
+};
+
+ValidatorContext.prototype.getSchemaMap = function () {
+	var map = {};
+	for (var key in this.schemas) {
+		map[key] = this.schemas[key];
+	}
+	return map;
+};
+
+ValidatorContext.prototype.getSchemaUris = function (filterRegExp) {
+	var list = [];
+	for (var key in this.schemas) {
+		if (!filterRegExp || filterRegExp.test(key)) {
+			list.push(key);
+		}
+	}
+	return list;
+};
+
+ValidatorContext.prototype.getMissingUris = function (filterRegExp) {
+	var list = [];
+	for (var key in this.missingMap) {
+		if (!filterRegExp || filterRegExp.test(key)) {
+			list.push(key);
+		}
+	}
+	return list;
+};
+
+ValidatorContext.prototype.dropSchemas = function () {
+	this.schemas = {};
+	this.reset();
+};
+ValidatorContext.prototype.reset = function () {
+	this.missing = [];
+	this.missingMap = {};
+	this.errors = [];
+};
+
+ValidatorContext.prototype.validateAll = function (data, schema, dataPathParts, schemaPathParts, dataPointerPath) {
+	var topLevel;
+	schema = this.resolveRefs(schema);
+	if (!schema) {
+		return null;
+	} else if (schema instanceof ValidationError) {
+		this.errors.push(schema);
+		return schema;
+	}
+
+	if (this.checkRecursive && (typeof data) === 'object') {
+		topLevel = !this.scanned.length;
+		if (data[this.key] && data[this.key].indexOf(schema) !== -1) { return null; }
+		var frozenIndex;
+		if (Object.isFrozen(data)) {
+			frozenIndex = this.scannedFrozen.indexOf(data);
+			if (frozenIndex !== -1 && this.scannedFrozenSchemas[frozenIndex].indexOf(schema) !== -1) { return null; }
+		}
+		this.scanned.push(data);
+		if (Object.isFrozen(data)) {
+			if (frozenIndex === -1) {
+				frozenIndex = this.scannedFrozen.length;
+				this.scannedFrozen.push(data);
+				this.scannedFrozenSchemas.push([]);
+			}
+			this.scannedFrozenSchemas[frozenIndex].push(schema);
+		} else {
+			if (!data[this.key]) {
+				try {
+					Object.defineProperty(data, this.key, {
+						value: [],
+						configurable: true
+					});
+				} catch (e) {
+					//IE 7/8 workaround
+					data[this.key] = [];
+				}
+			}
+			data[this.key].push(schema);
+		}
+	}
+
+	var errorCount = this.errors.length;
+	var error = this.validateBasic(data, schema, dataPointerPath)
+		|| this.validateNumeric(data, schema, dataPointerPath)
+		|| this.validateString(data, schema, dataPointerPath)
+		|| this.validateArray(data, schema, dataPointerPath)
+		|| this.validateObject(data, schema, dataPointerPath)
+		|| this.validateCombinations(data, schema, dataPointerPath)
+		|| this.validateFormat(data, schema, dataPointerPath)
+		|| null;
+
+	if (topLevel) {
+		while (this.scanned.length) {
+			var item = this.scanned.pop();
+			delete item[this.key];
+		}
+		this.scannedFrozen = [];
+		this.scannedFrozenSchemas = [];
+	}
+
+	if (error || errorCount !== this.errors.length) {
+		while ((dataPathParts && dataPathParts.length) || (schemaPathParts && schemaPathParts.length)) {
+			var dataPart = (dataPathParts && dataPathParts.length) ? "" + dataPathParts.pop() : null;
+			var schemaPart = (schemaPathParts && schemaPathParts.length) ? "" + schemaPathParts.pop() : null;
+			if (error) {
+				error = error.prefixWith(dataPart, schemaPart);
+			}
+			this.prefixErrors(errorCount, dataPart, schemaPart);
+		}
+	}
+
+	return this.handleError(error);
+};
+ValidatorContext.prototype.validateFormat = function (data, schema) {
+	if (typeof schema.format !== 'string' || !this.formatValidators[schema.format]) {
+		return null;
+	}
+	var errorMessage = this.formatValidators[schema.format].call(null, data, schema);
+	if (typeof errorMessage === 'string' || typeof errorMessage === 'number') {
+		return this.createError(ErrorCodes.FORMAT_CUSTOM, {message: errorMessage}).prefixWith(null, "format");
+	} else if (errorMessage && typeof errorMessage === 'object') {
+		return this.createError(ErrorCodes.FORMAT_CUSTOM, {message: errorMessage.message || "?"}, errorMessage.dataPath || null, errorMessage.schemaPath || "/format");
+	}
+	return null;
+};
+
+function recursiveCompare(A, B) {
+	if (A === B) {
+		return true;
+	}
+	if (typeof A === "object" && typeof B === "object") {
+		if (Array.isArray(A) !== Array.isArray(B)) {
+			return false;
+		} else if (Array.isArray(A)) {
+			if (A.length !== B.length) {
+				return false;
+			}
+			for (var i = 0; i < A.length; i++) {
+				if (!recursiveCompare(A[i], B[i])) {
+					return false;
+				}
+			}
+		} else {
+			var key;
+			for (key in A) {
+				if (B[key] === undefined && A[key] !== undefined) {
+					return false;
+				}
+			}
+			for (key in B) {
+				if (A[key] === undefined && B[key] !== undefined) {
+					return false;
+				}
+			}
+			for (key in A) {
+				if (!recursiveCompare(A[key], B[key])) {
+					return false;
+				}
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+ValidatorContext.prototype.validateBasic = function validateBasic(data, schema, dataPointerPath) {
+	var error;
+	if (error = this.validateType(data, schema, dataPointerPath)) {
+		return error.prefixWith(null, "type");
+	}
+	if (error = this.validateEnum(data, schema, dataPointerPath)) {
+		return error.prefixWith(null, "type");
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateType = function validateType(data, schema) {
+	if (schema.type === undefined) {
+		return null;
+	}
+	var dataType = typeof data;
+	if (data === null) {
+		dataType = "null";
+	} else if (Array.isArray(data)) {
+		dataType = "array";
+	}
+	var allowedTypes = schema.type;
+	if (typeof allowedTypes !== "object") {
+		allowedTypes = [allowedTypes];
+	}
+
+	for (var i = 0; i < allowedTypes.length; i++) {
+		var type = allowedTypes[i];
+		if (type === dataType || (type === "integer" && dataType === "number" && (data % 1 === 0))) {
+			return null;
+		}
+	}
+	return this.createError(ErrorCodes.INVALID_TYPE, {type: dataType, expected: allowedTypes.join("/")});
+};
+
+ValidatorContext.prototype.validateEnum = function validateEnum(data, schema) {
+	if (schema["enum"] === undefined) {
+		return null;
+	}
+	for (var i = 0; i < schema["enum"].length; i++) {
+		var enumVal = schema["enum"][i];
+		if (recursiveCompare(data, enumVal)) {
+			return null;
+		}
+	}
+	return this.createError(ErrorCodes.ENUM_MISMATCH, {value: (typeof JSON !== 'undefined') ? JSON.stringify(data) : data});
+};
+
+ValidatorContext.prototype.validateNumeric = function validateNumeric(data, schema, dataPointerPath) {
+	return this.validateMultipleOf(data, schema, dataPointerPath)
+		|| this.validateMinMax(data, schema, dataPointerPath)
+		|| null;
+};
+
+ValidatorContext.prototype.validateMultipleOf = function validateMultipleOf(data, schema) {
+	var multipleOf = schema.multipleOf || schema.divisibleBy;
+	if (multipleOf === undefined) {
+		return null;
+	}
+	if (typeof data === "number") {
+		if (data % multipleOf !== 0) {
+			return this.createError(ErrorCodes.NUMBER_MULTIPLE_OF, {value: data, multipleOf: multipleOf});
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateMinMax = function validateMinMax(data, schema) {
+	if (typeof data !== "number") {
+		return null;
+	}
+	if (schema.minimum !== undefined) {
+		if (data < schema.minimum) {
+			return this.createError(ErrorCodes.NUMBER_MINIMUM, {value: data, minimum: schema.minimum}).prefixWith(null, "minimum");
+		}
+		if (schema.exclusiveMinimum && data === schema.minimum) {
+			return this.createError(ErrorCodes.NUMBER_MINIMUM_EXCLUSIVE, {value: data, minimum: schema.minimum}).prefixWith(null, "exclusiveMinimum");
+		}
+	}
+	if (schema.maximum !== undefined) {
+		if (data > schema.maximum) {
+			return this.createError(ErrorCodes.NUMBER_MAXIMUM, {value: data, maximum: schema.maximum}).prefixWith(null, "maximum");
+		}
+		if (schema.exclusiveMaximum && data === schema.maximum) {
+			return this.createError(ErrorCodes.NUMBER_MAXIMUM_EXCLUSIVE, {value: data, maximum: schema.maximum}).prefixWith(null, "exclusiveMaximum");
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateString = function validateString(data, schema, dataPointerPath) {
+	return this.validateStringLength(data, schema, dataPointerPath)
+		|| this.validateStringPattern(data, schema, dataPointerPath)
+		|| null;
+};
+
+ValidatorContext.prototype.validateStringLength = function validateStringLength(data, schema) {
+	if (typeof data !== "string") {
+		return null;
+	}
+	if (schema.minLength !== undefined) {
+		if (data.length < schema.minLength) {
+			return this.createError(ErrorCodes.STRING_LENGTH_SHORT, {length: data.length, minimum: schema.minLength}).prefixWith(null, "minLength");
+		}
+	}
+	if (schema.maxLength !== undefined) {
+		if (data.length > schema.maxLength) {
+			return this.createError(ErrorCodes.STRING_LENGTH_LONG, {length: data.length, maximum: schema.maxLength}).prefixWith(null, "maxLength");
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateStringPattern = function validateStringPattern(data, schema) {
+	if (typeof data !== "string" || schema.pattern === undefined) {
+		return null;
+	}
+	var regexp = new RegExp(schema.pattern);
+	if (!regexp.test(data)) {
+		return this.createError(ErrorCodes.STRING_PATTERN, {pattern: schema.pattern}).prefixWith(null, "pattern");
+	}
+	return null;
+};
+ValidatorContext.prototype.validateArray = function validateArray(data, schema, dataPointerPath) {
+	if (!Array.isArray(data)) {
+		return null;
+	}
+	return this.validateArrayLength(data, schema, dataPointerPath)
+		|| this.validateArrayUniqueItems(data, schema, dataPointerPath)
+		|| this.validateArrayItems(data, schema, dataPointerPath)
+		|| null;
+};
+
+ValidatorContext.prototype.validateArrayLength = function validateArrayLength(data, schema) {
+	var error;
+	if (schema.minItems !== undefined) {
+		if (data.length < schema.minItems) {
+			error = (this.createError(ErrorCodes.ARRAY_LENGTH_SHORT, {length: data.length, minimum: schema.minItems})).prefixWith(null, "minItems");
+			if (this.handleError(error)) {
+				return error;
+			}
+		}
+	}
+	if (schema.maxItems !== undefined) {
+		if (data.length > schema.maxItems) {
+			error = (this.createError(ErrorCodes.ARRAY_LENGTH_LONG, {length: data.length, maximum: schema.maxItems})).prefixWith(null, "maxItems");
+			if (this.handleError(error)) {
+				return error;
+			}
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateArrayUniqueItems = function validateArrayUniqueItems(data, schema) {
+	if (schema.uniqueItems) {
+		for (var i = 0; i < data.length; i++) {
+			for (var j = i + 1; j < data.length; j++) {
+				if (recursiveCompare(data[i], data[j])) {
+					var error = (this.createError(ErrorCodes.ARRAY_UNIQUE, {match1: i, match2: j})).prefixWith(null, "uniqueItems");
+					if (this.handleError(error)) {
+						return error;
+					}
+				}
+			}
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateArrayItems = function validateArrayItems(data, schema, dataPointerPath) {
+	if (schema.items === undefined) {
+		return null;
+	}
+	var error, i;
+	if (Array.isArray(schema.items)) {
+		for (i = 0; i < data.length; i++) {
+			if (i < schema.items.length) {
+				if (error = this.validateAll(data[i], schema.items[i], [i], ["items", i], dataPointerPath + "/" + i)) {
+					return error;
+				}
+			} else if (schema.additionalItems !== undefined) {
+				if (typeof schema.additionalItems === "boolean") {
+					if (!schema.additionalItems) {
+						error = (this.createError(ErrorCodes.ARRAY_ADDITIONAL_ITEMS, {})).prefixWith("" + i, "additionalItems");
+						if (this.handleError(error)) {
+							return error;
+						}
+					}
+				} else if (error = this.validateAll(data[i], schema.additionalItems, [i], ["additionalItems"], dataPointerPath + "/" + i)) {
+					return error;
+				}
+			}
+		}
+	} else {
+		for (i = 0; i < data.length; i++) {
+			if (error = this.validateAll(data[i], schema.items, [i], ["items"], dataPointerPath + "/" + i)) {
+				return error;
+			}
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateObject = function validateObject(data, schema, dataPointerPath) {
+	if (typeof data !== "object" || data === null || Array.isArray(data)) {
+		return null;
+	}
+	return this.validateObjectMinMaxProperties(data, schema, dataPointerPath)
+		|| this.validateObjectRequiredProperties(data, schema, dataPointerPath)
+		|| this.validateObjectProperties(data, schema, dataPointerPath)
+		|| this.validateObjectDependencies(data, schema, dataPointerPath)
+		|| null;
+};
+
+ValidatorContext.prototype.validateObjectMinMaxProperties = function validateObjectMinMaxProperties(data, schema) {
+	var keys = Object.keys(data);
+	var error;
+	if (schema.minProperties !== undefined) {
+		if (keys.length < schema.minProperties) {
+			error = this.createError(ErrorCodes.OBJECT_PROPERTIES_MINIMUM, {propertyCount: keys.length, minimum: schema.minProperties}).prefixWith(null, "minProperties");
+			if (this.handleError(error)) {
+				return error;
+			}
+		}
+	}
+	if (schema.maxProperties !== undefined) {
+		if (keys.length > schema.maxProperties) {
+			error = this.createError(ErrorCodes.OBJECT_PROPERTIES_MAXIMUM, {propertyCount: keys.length, maximum: schema.maxProperties}).prefixWith(null, "maxProperties");
+			if (this.handleError(error)) {
+				return error;
+			}
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateObjectRequiredProperties = function validateObjectRequiredProperties(data, schema) {
+	if (schema.required !== undefined) {
+		for (var i = 0; i < schema.required.length; i++) {
+			var key = schema.required[i];
+			if (data[key] === undefined) {
+				var error = this.createError(ErrorCodes.OBJECT_REQUIRED, {key: key}).prefixWith(null, "" + i).prefixWith(null, "required");
+				if (this.handleError(error)) {
+					return error;
+				}
+			}
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateObjectProperties = function validateObjectProperties(data, schema, dataPointerPath) {
+	var error;
+	for (var key in data) {
+		var keyPointerPath = dataPointerPath + "/" + key.replace(/~/g, '~0').replace(/\//g, '~1');
+		var foundMatch = false;
+		if (schema.properties !== undefined && schema.properties[key] !== undefined) {
+			foundMatch = true;
+			if (error = this.validateAll(data[key], schema.properties[key], [key], ["properties", key], keyPointerPath)) {
+				return error;
+			}
+		}
+		if (schema.patternProperties !== undefined) {
+			for (var patternKey in schema.patternProperties) {
+				var regexp = new RegExp(patternKey);
+				if (regexp.test(key)) {
+					foundMatch = true;
+					if (error = this.validateAll(data[key], schema.patternProperties[patternKey], [key], ["patternProperties", patternKey], keyPointerPath)) {
+						return error;
+					}
+				}
+			}
+		}
+		if (!foundMatch) {
+			if (schema.additionalProperties !== undefined) {
+				if (this.trackUnknownProperties) {
+					this.knownPropertyPaths[keyPointerPath] = true;
+					delete this.unknownPropertyPaths[keyPointerPath];
+				}
+				if (typeof schema.additionalProperties === "boolean") {
+					if (!schema.additionalProperties) {
+						error = this.createError(ErrorCodes.OBJECT_ADDITIONAL_PROPERTIES, {}).prefixWith(key, "additionalProperties");
+						if (this.handleError(error)) {
+							return error;
+						}
+					}
+				} else {
+					if (error = this.validateAll(data[key], schema.additionalProperties, [key], ["additionalProperties"], keyPointerPath)) {
+						return error;
+					}
+				}
+			} else if (this.trackUnknownProperties && !this.knownPropertyPaths[keyPointerPath]) {
+				this.unknownPropertyPaths[keyPointerPath] = true;
+			}
+		} else if (this.trackUnknownProperties) {
+			this.knownPropertyPaths[keyPointerPath] = true;
+			delete this.unknownPropertyPaths[keyPointerPath];
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateObjectDependencies = function validateObjectDependencies(data, schema, dataPointerPath) {
+	var error;
+	if (schema.dependencies !== undefined) {
+		for (var depKey in schema.dependencies) {
+			if (data[depKey] !== undefined) {
+				var dep = schema.dependencies[depKey];
+				if (typeof dep === "string") {
+					if (data[dep] === undefined) {
+						error = this.createError(ErrorCodes.OBJECT_DEPENDENCY_KEY, {key: depKey, missing: dep}).prefixWith(null, depKey).prefixWith(null, "dependencies");
+						if (this.handleError(error)) {
+							return error;
+						}
+					}
+				} else if (Array.isArray(dep)) {
+					for (var i = 0; i < dep.length; i++) {
+						var requiredKey = dep[i];
+						if (data[requiredKey] === undefined) {
+							error = this.createError(ErrorCodes.OBJECT_DEPENDENCY_KEY, {key: depKey, missing: requiredKey}).prefixWith(null, "" + i).prefixWith(null, depKey).prefixWith(null, "dependencies");
+							if (this.handleError(error)) {
+								return error;
+							}
+						}
+					}
+				} else {
+					if (error = this.validateAll(data, dep, [], ["dependencies", depKey], dataPointerPath)) {
+						return error;
+					}
+				}
+			}
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateCombinations = function validateCombinations(data, schema, dataPointerPath) {
+	return this.validateAllOf(data, schema, dataPointerPath)
+		|| this.validateAnyOf(data, schema, dataPointerPath)
+		|| this.validateOneOf(data, schema, dataPointerPath)
+		|| this.validateNot(data, schema, dataPointerPath)
+		|| null;
+};
+
+ValidatorContext.prototype.validateAllOf = function validateAllOf(data, schema, dataPointerPath) {
+	if (schema.allOf === undefined) {
+		return null;
+	}
+	var error;
+	for (var i = 0; i < schema.allOf.length; i++) {
+		var subSchema = schema.allOf[i];
+		if (error = this.validateAll(data, subSchema, [], ["allOf", i], dataPointerPath)) {
+			return error;
+		}
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateAnyOf = function validateAnyOf(data, schema, dataPointerPath) {
+	if (schema.anyOf === undefined) {
+		return null;
+	}
+	var errors = [];
+	var startErrorCount = this.errors.length;
+	var oldUnknownPropertyPaths, oldKnownPropertyPaths;
+	if (this.trackUnknownProperties) {
+		oldUnknownPropertyPaths = this.unknownPropertyPaths;
+		oldKnownPropertyPaths = this.knownPropertyPaths;
+	}
+	var errorAtEnd = true;
+	for (var i = 0; i < schema.anyOf.length; i++) {
+		if (this.trackUnknownProperties) {
+			this.unknownPropertyPaths = {};
+			this.knownPropertyPaths = {};
+		}
+		var subSchema = schema.anyOf[i];
+
+		var errorCount = this.errors.length;
+		var error = this.validateAll(data, subSchema, [], ["anyOf", i], dataPointerPath);
+
+		if (error === null && errorCount === this.errors.length) {
+			this.errors = this.errors.slice(0, startErrorCount);
+
+			if (this.trackUnknownProperties) {
+				for (var knownKey in this.knownPropertyPaths) {
+					oldKnownPropertyPaths[knownKey] = true;
+					delete oldUnknownPropertyPaths[knownKey];
+				}
+				for (var unknownKey in this.unknownPropertyPaths) {
+					if (!oldKnownPropertyPaths[unknownKey]) {
+						oldUnknownPropertyPaths[unknownKey] = true;
+					}
+				}
+				// We need to continue looping so we catch all the property definitions, but we don't want to return an error
+				errorAtEnd = false;
+				continue;
+			}
+
+			return null;
+		}
+		if (error) {
+			errors.push(error.prefixWith(null, "" + i).prefixWith(null, "anyOf"));
+		}
+	}
+	if (this.trackUnknownProperties) {
+		this.unknownPropertyPaths = oldUnknownPropertyPaths;
+		this.knownPropertyPaths = oldKnownPropertyPaths;
+	}
+	if (errorAtEnd) {
+		errors = errors.concat(this.errors.slice(startErrorCount));
+		this.errors = this.errors.slice(0, startErrorCount);
+		return this.createError(ErrorCodes.ANY_OF_MISSING, {}, "", "/anyOf", errors);
+	}
+};
+
+ValidatorContext.prototype.validateOneOf = function validateOneOf(data, schema, dataPointerPath) {
+	if (schema.oneOf === undefined) {
+		return null;
+	}
+	var validIndex = null;
+	var errors = [];
+	var startErrorCount = this.errors.length;
+	var oldUnknownPropertyPaths, oldKnownPropertyPaths;
+	if (this.trackUnknownProperties) {
+		oldUnknownPropertyPaths = this.unknownPropertyPaths;
+		oldKnownPropertyPaths = this.knownPropertyPaths;
+	}
+	for (var i = 0; i < schema.oneOf.length; i++) {
+		if (this.trackUnknownProperties) {
+			this.unknownPropertyPaths = {};
+			this.knownPropertyPaths = {};
+		}
+		var subSchema = schema.oneOf[i];
+
+		var errorCount = this.errors.length;
+		var error = this.validateAll(data, subSchema, [], ["oneOf", i], dataPointerPath);
+
+		if (error === null && errorCount === this.errors.length) {
+			if (validIndex === null) {
+				validIndex = i;
+			} else {
+				this.errors = this.errors.slice(0, startErrorCount);
+				return this.createError(ErrorCodes.ONE_OF_MULTIPLE, {index1: validIndex, index2: i}, "", "/oneOf");
+			}
+			if (this.trackUnknownProperties) {
+				for (var knownKey in this.knownPropertyPaths) {
+					oldKnownPropertyPaths[knownKey] = true;
+					delete oldUnknownPropertyPaths[knownKey];
+				}
+				for (var unknownKey in this.unknownPropertyPaths) {
+					if (!oldKnownPropertyPaths[unknownKey]) {
+						oldUnknownPropertyPaths[unknownKey] = true;
+					}
+				}
+			}
+		} else if (error) {
+			errors.push(error.prefixWith(null, "" + i).prefixWith(null, "oneOf"));
+		}
+	}
+	if (this.trackUnknownProperties) {
+		this.unknownPropertyPaths = oldUnknownPropertyPaths;
+		this.knownPropertyPaths = oldKnownPropertyPaths;
+	}
+	if (validIndex === null) {
+		errors = errors.concat(this.errors.slice(startErrorCount));
+		this.errors = this.errors.slice(0, startErrorCount);
+		return this.createError(ErrorCodes.ONE_OF_MISSING, {}, "", "/oneOf", errors);
+	} else {
+		this.errors = this.errors.slice(0, startErrorCount);
+	}
+	return null;
+};
+
+ValidatorContext.prototype.validateNot = function validateNot(data, schema, dataPointerPath) {
+	if (schema.not === undefined) {
+		return null;
+	}
+	var oldErrorCount = this.errors.length;
+	var oldUnknownPropertyPaths, oldKnownPropertyPaths;
+	if (this.trackUnknownProperties) {
+		oldUnknownPropertyPaths = this.unknownPropertyPaths;
+		oldKnownPropertyPaths = this.knownPropertyPaths;
+		this.unknownPropertyPaths = {};
+		this.knownPropertyPaths = {};
+	}
+	var error = this.validateAll(data, schema.not, null, null, dataPointerPath);
+	var notErrors = this.errors.slice(oldErrorCount);
+	this.errors = this.errors.slice(0, oldErrorCount);
+	if (this.trackUnknownProperties) {
+		this.unknownPropertyPaths = oldUnknownPropertyPaths;
+		this.knownPropertyPaths = oldKnownPropertyPaths;
+	}
+	if (error === null && notErrors.length === 0) {
+		return this.createError(ErrorCodes.NOT_PASSED, {}, "", "/not");
+	}
+	return null;
+};
+
+// parseURI() and resolveUrl() are from https://gist.github.com/1088850
+//   -  released as public domain by author ("Yaffle") - see comments on gist
+
+function parseURI(url) {
+	var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
+	// authority = '//' + user + ':' + pass '@' + hostname + ':' port
+	return (m ? {
+		href     : m[0] || '',
+		protocol : m[1] || '',
+		authority: m[2] || '',
+		host     : m[3] || '',
+		hostname : m[4] || '',
+		port     : m[5] || '',
+		pathname : m[6] || '',
+		search   : m[7] || '',
+		hash     : m[8] || ''
+	} : null);
+}
+
+function resolveUrl(base, href) {// RFC 3986
+
+	function removeDotSegments(input) {
+		var output = [];
+		input.replace(/^(\.\.?(\/|$))+/, '')
+			.replace(/\/(\.(\/|$))+/g, '/')
+			.replace(/\/\.\.$/, '/../')
+			.replace(/\/?[^\/]*/g, function (p) {
+				if (p === '/..') {
+					output.pop();
+				} else {
+					output.push(p);
+				}
+		});
+		return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
+	}
+
+	href = parseURI(href || '');
+	base = parseURI(base || '');
+
+	return !href || !base ? null : (href.protocol || base.protocol) +
+		(href.protocol || href.authority ? href.authority : base.authority) +
+		removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) +
+		(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
+		href.hash;
+}
+
+function getDocumentUri(uri) {
+	return uri.split('#')[0];
+}
+function normSchema(schema, baseUri) {
+	if (baseUri === undefined) {
+		baseUri = schema.id;
+	} else if (typeof schema.id === "string") {
+		baseUri = resolveUrl(baseUri, schema.id);
+		schema.id = baseUri;
+	}
+	if (typeof schema === "object") {
+		if (Array.isArray(schema)) {
+			for (var i = 0; i < schema.length; i++) {
+				normSchema(schema[i], baseUri);
+			}
+		} else if (typeof schema['$ref'] === "string") {
+			schema['$ref'] = resolveUrl(baseUri, schema['$ref']);
+		} else {
+			for (var key in schema) {
+				if (key !== "enum") {
+					normSchema(schema[key], baseUri);
+				}
+			}
+		}
+	}
+}
+
+var ErrorCodes = {
+	INVALID_TYPE: 0,
+	ENUM_MISMATCH: 1,
+	ANY_OF_MISSING: 10,
+	ONE_OF_MISSING: 11,
+	ONE_OF_MULTIPLE: 12,
+	NOT_PASSED: 13,
+	// Numeric errors
+	NUMBER_MULTIPLE_OF: 100,
+	NUMBER_MINIMUM: 101,
+	NUMBER_MINIMUM_EXCLUSIVE: 102,
+	NUMBER_MAXIMUM: 103,
+	NUMBER_MAXIMUM_EXCLUSIVE: 104,
+	// String errors
+	STRING_LENGTH_SHORT: 200,
+	STRING_LENGTH_LONG: 201,
+	STRING_PATTERN: 202,
+	// Object errors
+	OBJECT_PROPERTIES_MINIMUM: 300,
+	OBJECT_PROPERTIES_MAXIMUM: 301,
+	OBJECT_REQUIRED: 302,
+	OBJECT_ADDITIONAL_PROPERTIES: 303,
+	OBJECT_DEPENDENCY_KEY: 304,
+	// Array errors
+	ARRAY_LENGTH_SHORT: 400,
+	ARRAY_LENGTH_LONG: 401,
+	ARRAY_UNIQUE: 402,
+	ARRAY_ADDITIONAL_ITEMS: 403,
+	// Format errors
+	FORMAT_CUSTOM: 500,
+	// Schema structure
+	CIRCULAR_REFERENCE: 500,
+	// Non-standard validation options
+	UNKNOWN_PROPERTY: 1000
+};
+var ErrorMessagesDefault = {
+	INVALID_TYPE: "invalid type: {type} (expected {expected})",
+	ENUM_MISMATCH: "No enum match for: {value}",
+	ANY_OF_MISSING: "Data does not match any schemas from \"anyOf\"",
+	ONE_OF_MISSING: "Data does not match any schemas from \"oneOf\"",
+	ONE_OF_MULTIPLE: "Data is valid against more than one schema from \"oneOf\": indices {index1} and {index2}",
+	NOT_PASSED: "Data matches schema from \"not\"",
+	// Numeric errors
+	NUMBER_MULTIPLE_OF: "Value {value} is not a multiple of {multipleOf}",
+	NUMBER_MINIMUM: "Value {value} is less than minimum {minimum}",
+	NUMBER_MINIMUM_EXCLUSIVE: "Value {value} is equal to exclusive minimum {minimum}",
+	NUMBER_MAXIMUM: "Value {value} is greater than maximum {maximum}",
+	NUMBER_MAXIMUM_EXCLUSIVE: "Value {value} is equal to exclusive maximum {maximum}",
+	// String errors
+	STRING_LENGTH_SHORT: "String is too short ({length} chars), minimum {minimum}",
+	STRING_LENGTH_LONG: "String is too long ({length} chars), maximum {maximum}",
+	STRING_PATTERN: "String does not match pattern: {pattern}",
+	// Object errors
+	OBJECT_PROPERTIES_MINIMUM: "Too few properties defined ({propertyCount}), minimum {minimum}",
+	OBJECT_PROPERTIES_MAXIMUM: "Too many properties defined ({propertyCount}), maximum {maximum}",
+	OBJECT_REQUIRED: "Missing required property: {key}",
+	OBJECT_ADDITIONAL_PROPERTIES: "Additional properties not allowed",
+	OBJECT_DEPENDENCY_KEY: "Dependency failed - key must exist: {missing} (due to key: {key})",
+	// Array errors
+	ARRAY_LENGTH_SHORT: "Array is too short ({length}), minimum {minimum}",
+	ARRAY_LENGTH_LONG: "Array is too long ({length}), maximum {maximum}",
+	ARRAY_UNIQUE: "Array items are not unique (indices {match1} and {match2})",
+	ARRAY_ADDITIONAL_ITEMS: "Additional items not allowed",
+	// Format errors
+	FORMAT_CUSTOM: "Format validation failed ({message})",
+	// Schema structure
+	CIRCULAR_REFERENCE: "Circular $refs: {urls}",
+	// Non-standard validation options
+	UNKNOWN_PROPERTY: "Unknown property (not in schema)"
+};
+
+function ValidationError(code, message, dataPath, schemaPath, subErrors) {
+	if (code === undefined) {
+		throw new Error ("No code supplied for error: "+ message);
+	}
+	this.code = code;
+	this.message = message;
+	this.dataPath = dataPath || "";
+	this.schemaPath = schemaPath || "";
+	this.subErrors = subErrors || null;
+}
+ValidationError.prototype = new Error();
+ValidationError.prototype.prefixWith = function (dataPrefix, schemaPrefix) {
+	if (dataPrefix !== null) {
+		dataPrefix = dataPrefix.replace(/~/g, "~0").replace(/\//g, "~1");
+		this.dataPath = "/" + dataPrefix + this.dataPath;
+	}
+	if (schemaPrefix !== null) {
+		schemaPrefix = schemaPrefix.replace(/~/g, "~0").replace(/\//g, "~1");
+		this.schemaPath = "/" + schemaPrefix + this.schemaPath;
+	}
+	if (this.subErrors !== null) {
+		for (var i = 0; i < this.subErrors.length; i++) {
+			this.subErrors[i].prefixWith(dataPrefix, schemaPrefix);
+		}
+	}
+	return this;
+};
+
+function isTrustedUrl(baseUrl, testUrl) {
+	if(testUrl.substring(0, baseUrl.length) === baseUrl){
+		var remainder = testUrl.substring(baseUrl.length);
+		if ((testUrl.length > 0 && testUrl.charAt(baseUrl.length - 1) === "/")
+			|| remainder.charAt(0) === "#"
+			|| remainder.charAt(0) === "?") {
+			return true;
+		}
+	}
+	return false;
+}
+
+var languages = {};
+function createApi(language) {
+	var globalContext = new ValidatorContext();
+	var currentLanguage = language || 'en';
+	var api = {
+		addFormat: function () {
+			globalContext.addFormat.apply(globalContext, arguments);
+		},
+		language: function (code) {
+			if (!code) {
+				return currentLanguage;
+			}
+			if (!languages[code]) {
+				code = code.split('-')[0]; // fall back to base language
+			}
+			if (languages[code]) {
+				currentLanguage = code;
+				return code; // so you can tell if fall-back has happened
+			}
+			return false;
+		},
+		addLanguage: function (code, messageMap) {
+			var key;
+			for (key in ErrorCodes) {
+				if (messageMap[key] && !messageMap[ErrorCodes[key]]) {
+					messageMap[ErrorCodes[key]] = messageMap[key];
+				}
+			}
+			var rootCode = code.split('-')[0];
+			if (!languages[rootCode]) { // use for base language if not yet defined
+				languages[code] = messageMap;
+				languages[rootCode] = messageMap;
+			} else {
+				languages[code] = Object.create(languages[rootCode]);
+				for (key in messageMap) {
+					if (typeof languages[rootCode][key] === 'undefined') {
+						languages[rootCode][key] = messageMap[key];
+					}
+					languages[code][key] = messageMap[key];
+				}
+			}
+			return this;
+		},
+		freshApi: function (language) {
+			var result = createApi();
+			if (language) {
+				result.language(language);
+			}
+			return result;
+		},
+		validate: function (data, schema, checkRecursive, banUnknownProperties) {
+			var context = new ValidatorContext(globalContext, false, languages[currentLanguage], checkRecursive, banUnknownProperties);
+			if (typeof schema === "string") {
+				schema = {"$ref": schema};
+			}
+			context.addSchema("", schema);
+			var error = context.validateAll(data, schema, null, null, "");
+			if (!error && banUnknownProperties) {
+				error = context.banUnknownProperties();
+			}
+			this.error = error;
+			this.missing = context.missing;
+			this.valid = (error === null);
+			return this.valid;
+		},
+		validateResult: function () {
+			var result = {};
+			this.validate.apply(result, arguments);
+			return result;
+		},
+		validateMultiple: function (data, schema, checkRecursive, banUnknownProperties) {
+			var context = new ValidatorContext(globalContext, true, languages[currentLanguage], checkRecursive, banUnknownProperties);
+			if (typeof schema === "string") {
+				schema = {"$ref": schema};
+			}
+			context.addSchema("", schema);
+			context.validateAll(data, schema, null, null, "");
+			if (banUnknownProperties) {
+				context.banUnknownProperties();
+			}
+			var result = {};
+			result.errors = context.errors;
+			result.missing = context.missing;
+			result.valid = (result.errors.length === 0);
+			return result;
+		},
+		addSchema: function () {
+			return globalContext.addSchema.apply(globalContext, arguments);
+		},
+		getSchema: function () {
+			return globalContext.getSchema.apply(globalContext, arguments);
+		},
+		getSchemaMap: function () {
+			return globalContext.getSchemaMap.apply(globalContext, arguments);
+		},
+		getSchemaUris: function () {
+			return globalContext.getSchemaUris.apply(globalContext, arguments);
+		},
+		getMissingUris: function () {
+			return globalContext.getMissingUris.apply(globalContext, arguments);
+		},
+		dropSchemas: function () {
+			globalContext.dropSchemas.apply(globalContext, arguments);
+		},
+		reset: function () {
+			globalContext.reset();
+			this.error = null;
+			this.missing = [];
+			this.valid = true;
+		},
+		missing: [],
+		error: null,
+		valid: true,
+		normSchema: normSchema,
+		resolveUrl: resolveUrl,
+		getDocumentUri: getDocumentUri,
+		errorCodes: ErrorCodes
+	};
+	return api;
+}
+
+var tv4 = createApi();
+tv4.addLanguage('en-gb', ErrorMessagesDefault);
+
+//legacy property
+tv4.tv4 = tv4;
+
+if (typeof module !== 'undefined' && module.exports){
+	module.exports = tv4;
+}
+else {
+	global.tv4 = tv4;
+}
+
+})(this);
+
+//@ sourceMappingURL=tv4.js.map
Index: Dev/trunk/src/node_modules/underscore/.npmignore
===================================================================
--- Dev/trunk/src/node_modules/underscore/.npmignore	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/.npmignore	(revision 484)
@@ -0,0 +1,4 @@
+test/
+Rakefile
+docs/
+raw/
Index: Dev/trunk/src/node_modules/underscore/.travis.yml
===================================================================
--- Dev/trunk/src/node_modules/underscore/.travis.yml	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/.travis.yml	(revision 484)
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+  - 0.8
+notifications:
+  email: false
Index: Dev/trunk/src/node_modules/underscore/CNAME
===================================================================
--- Dev/trunk/src/node_modules/underscore/CNAME	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/CNAME	(revision 484)
@@ -0,0 +1,1 @@
+underscorejs.org
Index: Dev/trunk/src/node_modules/underscore/CONTRIBUTING.md
===================================================================
--- Dev/trunk/src/node_modules/underscore/CONTRIBUTING.md	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/CONTRIBUTING.md	(revision 484)
@@ -0,0 +1,9 @@
+## How to contribute to Underscore.js
+
+* Before you open a ticket or send a pull request, [search](https://github.com/documentcloud/underscore/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one.
+
+* Before sending a pull request for a feature, be sure to have [tests](http://underscorejs.org/test/).
+
+* Use the same coding style as the rest of the [codebase](https://github.com/documentcloud/underscore/blob/master/underscore.js).
+
+* In your pull request, do not add documentation or re-build the minified `underscore-min.js` file. We'll do those things before cutting a new release.
Index: Dev/trunk/src/node_modules/underscore/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/underscore/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/LICENSE	(revision 484)
@@ -0,0 +1,22 @@
+Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud
+
+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.
Index: Dev/trunk/src/node_modules/underscore/README.md
===================================================================
--- Dev/trunk/src/node_modules/underscore/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/README.md	(revision 484)
@@ -0,0 +1,19 @@
+                       __
+                      /\ \                                                         __
+     __  __    ___    \_\ \     __   _ __   ____    ___    ___   _ __    __       /\_\    ____
+    /\ \/\ \ /' _ `\  /'_  \  /'__`\/\  __\/ ,__\  / ___\ / __`\/\  __\/'__`\     \/\ \  /',__\
+    \ \ \_\ \/\ \/\ \/\ \ \ \/\  __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\  __/  __  \ \ \/\__, `\
+     \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
+      \/___/  \/_/\/_/\/__,_ /\/____/ \/_/ \/___/  \/____/\/___/  \/_/ \/____/\/_//\ \_\ \/___/
+                                                                                  \ \____/
+                                                                                   \/___/
+
+Underscore.js is a utility-belt library for JavaScript that provides
+support for the usual functional suspects (each, map, reduce, filter...)
+without extending any core JavaScript objects.
+
+For Docs, License, Tests, and pre-packed downloads, see:
+http://underscorejs.org
+
+Many thanks to our contributors:
+https://github.com/documentcloud/underscore/contributors
Index: Dev/trunk/src/node_modules/underscore/index.html
===================================================================
--- Dev/trunk/src/node_modules/underscore/index.html	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/index.html	(revision 484)
@@ -0,0 +1,2467 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+  <meta http-equiv="X-UA-Compatible" content="chrome=1" />
+  <meta name="viewport" content="width=device-width" />
+  <link rel="canonical" href="http://underscorejs.org" />
+  <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
+  <title>Underscore.js</title>
+  <style>
+    body {
+      font-size: 14px;
+      line-height: 22px;
+      background: #f4f4f4 url(docs/images/background.png);
+      color: #000;
+      font-family: Helvetica Neue, Helvetica, Arial;
+    }
+    .interface {
+      font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important;
+    }
+    div#sidebar {
+      background: #fff;
+      position: fixed;
+      top: 0; left: 0; bottom: 0;
+      width: 200px;
+      overflow-y: auto;
+      overflow-x: hidden;
+      -webkit-overflow-scrolling: touch;
+      padding: 15px 0 30px 30px;
+      border-right: 1px solid #bbb;
+      box-shadow: 0 0 20px #ccc; -webkit-box-shadow: 0 0 20px #ccc; -moz-box-shadow: 0 0 20px #ccc;
+    }
+    a.toc_title, a.toc_title:visited {
+      display: block;
+      color: black;
+      font-weight: bold;
+      margin-top: 15px;
+    }
+      a.toc_title:hover {
+        text-decoration: underline;
+      }
+      #sidebar .version {
+        font-size: 10px;
+        font-weight: normal;
+      }
+    ul.toc_section {
+      font-size: 11px;
+      line-height: 14px;
+      margin: 5px 0 0 0;
+      padding-left: 0px;
+      list-style-type: none;
+      font-family: Lucida Grande;
+    }
+      .toc_section li {
+        cursor: pointer;
+        margin: 0 0 3px 0;
+      }
+        .toc_section li a {
+          text-decoration: none;
+          color: black;
+        }
+          .toc_section li a:hover {
+            text-decoration: underline;
+          }
+    div.container {
+      width: 550px;
+      margin: 40px 0 50px 260px;
+    }
+    img#logo {
+      width: 396px;
+      height: 69px;
+    }
+    div.warning {
+      margin-top: 15px;
+      font: bold 11px Arial;
+      color: #770000;
+    }
+    p {
+      margin: 20px 0;
+      width: 550px;
+    }
+    a, a:visited {
+      color: #444;
+    }
+    a:active, a:hover {
+      color: #000;
+    }
+    h1, h2, h3, h4, h5, h6 {
+      padding-top: 20px;
+    }
+      h2 {
+        font-size: 20px;
+      }
+    b.header {
+      font-size: 16px;
+      line-height: 30px;
+    }
+    span.alias {
+      font-size: 14px;
+      font-style: italic;
+      margin-left: 20px;
+    }
+    table, tr, td {
+      margin: 0; padding: 0;
+    }
+      td {
+        padding: 2px 12px 2px 0;
+      }
+      table .rule {
+        height: 1px;
+        background: #ccc;
+        margin: 5px 0;
+      }
+    ul {
+      list-style-type: circle;
+      padding: 0 0 0 20px;
+    }
+      li {
+        width: 500px;
+        margin-bottom: 10px;
+      }
+      code, pre, tt {
+        font-family: Monaco, Consolas, "Lucida Console", monospace;
+        font-size: 12px;
+        line-height: 18px;
+        font-style: normal;
+      }
+        tt {
+          padding: 0px 3px;
+          background: #fff;
+          border: 1px solid #ddd;
+          zoom: 1;
+        }
+        code {
+          margin-left: 20px;
+        }
+        pre {
+          font-size: 12px;
+          padding: 2px 0 2px 15px;
+          border-left: 5px solid #bbb;
+          margin: 0px 0 30px;
+        }
+    @media only screen and (-webkit-min-device-pixel-ratio: 1.5) and (max-width: 640px),
+          only screen and (-o-min-device-pixel-ratio: 3/2) and (max-width: 640px),
+          only screen and (min-device-pixel-ratio: 1.5) and (max-width: 640px) {
+      img {
+        max-width: 100%;
+      }
+      div#sidebar {
+        -webkit-overflow-scrolling: initial;
+        position: relative;
+        width: 90%;
+        height: 120px;
+        left: 0;
+        top: -7px;
+        padding: 10px 0 10px 30px;
+        border: 0;
+      }
+      img#logo {
+        width: auto;
+        height: auto;
+      }
+      div.container {
+        margin: 0;
+        width: 100%;
+      }
+      p, div.container ul {
+        max-width: 98%;
+        overflow-x: scroll;
+      }
+      pre {
+        overflow: scroll;
+      }
+    }
+  </style>
+</head>
+<body>
+
+  <div id="sidebar" class="interface">
+
+    <a class="toc_title" href="#">
+      Underscore.js <span class="version">(1.4.4)</span>
+    </a>
+    <ul class="toc_section">
+      <li>&raquo; <a href="http://github.com/documentcloud/underscore">GitHub Repository</a></li>
+      <li>&raquo; <a href="docs/underscore.html">Annotated Source</a></li>
+    </ul>
+
+    <a class="toc_title" href="#">
+      Introduction
+    </a>
+
+    <a class="toc_title" href="#collections">
+      Collections
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#each">each</a></li>
+      <li>- <a href="#map">map</a></li>
+      <li>- <a href="#reduce">reduce</a></li>
+      <li>- <a href="#reduceRight">reduceRight</a></li>
+      <li>- <a href="#find">find</a></li>
+      <li>- <a href="#filter">filter</a></li>
+      <li>- <a href="#where">where</a></li>
+      <li>- <a href="#findWhere">findWhere</a></li>
+      <li>- <a href="#reject">reject</a></li>
+      <li>- <a href="#every">every</a></li>
+      <li>- <a href="#some">some</a></li>
+      <li>- <a href="#contains">contains</a></li>
+      <li>- <a href="#invoke">invoke</a></li>
+      <li>- <a href="#pluck">pluck</a></li>
+      <li>- <a href="#max">max</a></li>
+      <li>- <a href="#min">min</a></li>
+      <li>- <a href="#sortBy">sortBy</a></li>
+      <li>- <a href="#groupBy">groupBy</a></li>
+      <li>- <a href="#countBy">countBy</a></li>
+      <li>- <a href="#shuffle">shuffle</a></li>
+      <li>- <a href="#toArray">toArray</a></li>
+      <li>- <a href="#size">size</a></li>
+    </ul>
+
+    <a class="toc_title" href="#arrays">
+      Arrays
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#first">first</a></li>
+      <li>- <a href="#initial">initial</a></li>
+      <li>- <a href="#last">last</a></li>
+      <li>- <a href="#rest">rest</a></li>
+      <li>- <a href="#compact">compact</a></li>
+      <li>- <a href="#flatten">flatten</a></li>
+      <li>- <a href="#without">without</a></li>
+      <li>- <a href="#union">union</a></li>
+      <li>- <a href="#intersection">intersection</a></li>
+      <li>- <a href="#difference">difference</a></li>
+      <li>- <a href="#uniq">uniq</a></li>
+      <li>- <a href="#zip">zip</a></li>
+      <li>- <a href="#object">object</a></li>
+      <li>- <a href="#indexOf">indexOf</a></li>
+      <li>- <a href="#lastIndexOf">lastIndexOf</a></li>
+      <li>- <a href="#sortedIndex">sortedIndex</a></li>
+      <li>- <a href="#range">range</a></li>
+    </ul>
+
+    <a class="toc_title" href="#functions">
+      Functions
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#bind">bind</a></li>
+      <li>- <a href="#bindAll">bindAll</a></li>
+      <li>- <a href="#partial">partial</a></li>
+      <li>- <a href="#memoize">memoize</a></li>
+      <li>- <a href="#delay">delay</a></li>
+      <li>- <a href="#defer">defer</a></li>
+      <li>- <a href="#throttle">throttle</a></li>
+      <li>- <a href="#debounce">debounce</a></li>
+      <li>- <a href="#once">once</a></li>
+      <li>- <a href="#after">after</a></li>
+      <li>- <a href="#wrap">wrap</a></li>
+      <li>- <a href="#compose">compose</a></li>
+    </ul>
+
+    <a class="toc_title" href="#objects">
+      Objects
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#keys">keys</a></li>
+      <li>- <a href="#values">values</a></li>
+      <li>- <a href="#pairs">pairs</a></li>
+      <li>- <a href="#invert">invert</a></li>
+      <li>- <a href="#object-functions">functions</a></li>
+      <li>- <a href="#extend">extend</a></li>
+      <li>- <a href="#pick">pick</a></li>
+      <li>- <a href="#omit">omit</a></li>
+      <li>- <a href="#defaults">defaults</a></li>
+      <li>- <a href="#clone">clone</a></li>
+      <li>- <a href="#tap">tap</a></li>
+      <li>- <a href="#has">has</a></li>
+      <li>- <a href="#isEqual">isEqual</a></li>
+      <li>- <a href="#isEmpty">isEmpty</a></li>
+      <li>- <a href="#isElement">isElement</a></li>
+      <li>- <a href="#isArray">isArray</a></li>
+      <li>- <a href="#isObject">isObject</a></li>
+      <li>- <a href="#isArguments">isArguments</a></li>
+      <li>- <a href="#isFunction">isFunction</a></li>
+      <li>- <a href="#isString">isString</a></li>
+      <li>- <a href="#isNumber">isNumber</a></li>
+      <li>- <a href="#isFinite">isFinite</a></li>
+      <li>- <a href="#isBoolean">isBoolean</a></li>
+      <li>- <a href="#isDate">isDate</a></li>
+      <li>- <a href="#isRegExp">isRegExp</a></li>
+      <li>- <a href="#isNaN">isNaN</a></li>
+      <li>- <a href="#isNull">isNull</a></li>
+      <li>- <a href="#isUndefined">isUndefined</a></li>
+    </ul>
+
+    <a class="toc_title" href="#utility">
+      Utility
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#noConflict">noConflict</a></li>
+      <li>- <a href="#identity">identity</a></li>
+      <li>- <a href="#times">times</a></li>
+      <li>- <a href="#random">random</a></li>
+      <li>- <a href="#mixin">mixin</a></li>
+      <li>- <a href="#uniqueId">uniqueId</a></li>
+      <li>- <a href="#escape">escape</a></li>
+      <li>- <a href="#unescape">unescape</a></li>
+      <li>- <a href="#result">result</a></li>
+      <li>- <a href="#template">template</a></li>
+    </ul>
+
+    <a class="toc_title" href="#chaining">
+      Chaining
+    </a>
+    <ul class="toc_section">
+      <li>- <a href="#chain">chain</a></li>
+      <li>- <a href="#value">value</a></li>
+    </ul>
+
+    <a class="toc_title" href="#links">
+      Links
+    </a>
+
+    <a class="toc_title" href="#changelog">
+      Change Log
+    </a>
+
+  </div>
+
+  <div class="container">
+
+    <p id="introduction">
+      <img id="logo" src="docs/images/underscore.png" alt="Underscore.js" />
+    </p>
+
+    <p>
+      <a href="http://github.com/documentcloud/underscore/">Underscore</a> is a
+      utility-belt library for JavaScript that provides a lot of the
+      functional programming support that you would expect in
+      <a href="http://prototypejs.org/doc/latest/">Prototype.js</a>
+      (or <a href="http://www.ruby-doc.org/core/classes/Enumerable.html">Ruby</a>),
+      but without extending any of the built-in JavaScript objects. It's the
+      tie to go along with <a href="http://docs.jquery.com">jQuery</a>'s tux,
+      and <a href="http://backbonejs.org">Backbone.js</a>'s suspenders.
+    </p>
+
+    <p>
+      Underscore provides 80-odd functions that support both the usual
+      functional suspects: <b>map</b>, <b>select</b>, <b>invoke</b> &mdash;
+      as well as more specialized helpers: function binding, javascript
+      templating, deep equality testing, and so on. It delegates to built-in
+      functions, if present, so modern browsers will use the
+      native implementations of <b>forEach</b>, <b>map</b>, <b>reduce</b>,
+      <b>filter</b>, <b>every</b>, <b>some</b> and <b>indexOf</b>.
+    </p>
+
+    <p>
+      A complete <a href="test/">Test &amp; Benchmark Suite</a>
+      is included for your perusal.
+    </p>
+
+    <p>
+      You may also read through the <a href="docs/underscore.html">annotated source code</a>.
+    </p>
+
+    <p>
+      The project is
+      <a href="http://github.com/documentcloud/underscore/">hosted on GitHub</a>.
+      You can report bugs and discuss features on the
+      <a href="http://github.com/documentcloud/underscore/issues">issues page</a>,
+      on Freenode in the <tt>#documentcloud</tt> channel,
+      or send tweets to <a href="http://twitter.com/documentcloud">@documentcloud</a>.
+    </p>
+
+    <p>
+      <i>Underscore is an open-source component of <a href="http://documentcloud.org/">DocumentCloud</a>.</i>
+    </p>
+
+    <h2>Downloads <i style="padding-left: 12px; font-size:12px;">(Right-click, and use "Save As")</i></h2>
+
+    <table>
+      <tr>
+        <td><a href="underscore.js">Development Version (1.4.4)</a></td>
+        <td><i>40kb, Uncompressed with Plentiful Comments</i></td>
+      </tr>
+      <tr>
+        <td><a href="underscore-min.js">Production Version (1.4.4)</a></td>
+        <td><i>4kb, Minified and Gzipped</i></td>
+      </tr>
+      <tr>
+        <td colspan="2"><div class="rule"></div></td>
+      </tr>
+      <tr>
+        <td><a href="https://raw.github.com/documentcloud/underscore/master/underscore.js">Edge Version</a></td>
+        <td><i>Unreleased, current <tt>master</tt>, use at your own risk</i></td>
+      </tr>
+    </table>
+
+    <div id="documentation">
+
+      <h2 id="collections">Collection Functions (Arrays or Objects)</h2>
+
+      <p id="each">
+        <b class="header">each</b><code>_.each(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>forEach</b></span>
+        <br />
+        Iterates over a <b>list</b> of elements, yielding each in turn to an <b>iterator</b>
+        function. The <b>iterator</b> is bound to the <b>context</b> object, if one is
+        passed. Each invocation of <b>iterator</b> is called with three arguments:
+        <tt>(element, index, list)</tt>. If <b>list</b> is a JavaScript object, <b>iterator</b>'s
+        arguments will be <tt>(value, key, list)</tt>. Delegates to the native
+        <b>forEach</b> function if it exists.
+      </p>
+      <pre>
+_.each([1, 2, 3], alert);
+=&gt; alerts each number in turn...
+_.each({one : 1, two : 2, three : 3}, alert);
+=&gt; alerts each number value in turn...</pre>
+
+      <p id="map">
+        <b class="header">map</b><code>_.map(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>collect</b></span>
+        <br />
+        Produces a new array of values by mapping each value in <b>list</b>
+        through a transformation function (<b>iterator</b>). If the native <b>map</b> method
+        exists, it will be used instead. If <b>list</b> is a JavaScript object,
+        <b>iterator</b>'s arguments will be <tt>(value, key, list)</tt>.
+      </p>
+      <pre>
+_.map([1, 2, 3], function(num){ return num * 3; });
+=&gt; [3, 6, 9]
+_.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
+=&gt; [3, 6, 9]</pre>
+
+      <p id="reduce">
+        <b class="header">reduce</b><code>_.reduce(list, iterator, memo, [context])</code>
+        <span class="alias">Aliases: <b>inject, foldl</b></span>
+        <br />
+        Also known as <b>inject</b> and <b>foldl</b>, <b>reduce</b> boils down a
+        <b>list</b> of values into a single value. <b>Memo</b> is the initial state
+        of the reduction, and each successive step of it should be returned by
+        <b>iterator</b>. The iterator is passed four arguments: the <tt>memo</tt>,
+        then the <tt>value</tt> and <tt>index</tt> (or key) of the iteration,
+        and finally a reference to the entire <tt>list</tt>.
+      </p>
+      <pre>
+var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
+=&gt; 6
+</pre>
+
+      <p id="reduceRight">
+        <b class="header">reduceRight</b><code>_.reduceRight(list, iterator, memo, [context])</code>
+        <span class="alias">Alias: <b>foldr</b></span>
+        <br />
+        The right-associative version of <b>reduce</b>. Delegates to the
+        JavaScript 1.8 version of <b>reduceRight</b>, if it exists. <b>Foldr</b>
+        is not as useful in JavaScript as it would be in a language with lazy
+        evaluation.
+      </p>
+      <pre>
+var list = [[0, 1], [2, 3], [4, 5]];
+var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+=&gt; [4, 5, 2, 3, 0, 1]
+</pre>
+
+      <p id="find">
+        <b class="header">find</b><code>_.find(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>detect</b></span>
+        <br />
+        Looks through each value in the <b>list</b>, returning the first one that
+        passes a truth test (<b>iterator</b>). The function returns as
+        soon as it finds an acceptable element, and doesn't traverse the
+        entire list.
+      </p>
+      <pre>
+var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=&gt; 2
+</pre>
+
+      <p id="filter">
+        <b class="header">filter</b><code>_.filter(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>select</b></span>
+        <br />
+        Looks through each value in the <b>list</b>, returning an array of all
+        the values that pass a truth test (<b>iterator</b>). Delegates to the
+        native <b>filter</b> method, if it exists.
+      </p>
+      <pre>
+var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=&gt; [2, 4, 6]
+</pre>
+
+      <p id="where">
+        <b class="header">where</b><code>_.where(list, properties)</code>
+        <br />
+        Looks through each value in the <b>list</b>, returning an array of all
+        the values that contain all of the key-value pairs listed in <b>properties</b>.
+      </p>
+      <pre>
+_.where(listOfPlays, {author: "Shakespeare", year: 1611});
+=&gt; [{title: "Cymbeline", author: "Shakespeare", year: 1611},
+    {title: "The Tempest", author: "Shakespeare", year: 1611}]
+</pre>
+
+      <p id="findWhere">
+        <b class="header">findWhere</b><code>_.findWhere(list, properties)</code>
+        <br />
+        Looks through the <b>list</b> and returns the <i>first</i> value that matches
+        all of the key-value pairs listed in <b>properties</b>.
+      </p>
+      <pre>
+_.findWhere(publicServicePulitzers, {newsroom: "The New York Times"});
+=&gt; {year: 1918, newsroom: "The New York Times",
+  reason: "For its public service in publishing in full so many official reports,
+  documents and speeches by European statesmen relating to the progress and
+  conduct of the war."}
+</pre>
+
+      <p id="reject">
+        <b class="header">reject</b><code>_.reject(list, iterator, [context])</code>
+        <br />
+        Returns the values in <b>list</b> without the elements that the truth
+        test (<b>iterator</b>) passes. The opposite of <b>filter</b>.
+      </p>
+      <pre>
+var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=&gt; [1, 3, 5]
+</pre>
+
+      <p id="every">
+        <b class="header">every</b><code>_.every(list, iterator, [context])</code>
+        <span class="alias">Alias: <b>all</b></span>
+        <br />
+        Returns <i>true</i> if all of the values in the <b>list</b> pass the <b>iterator</b>
+        truth test. Delegates to the native method <b>every</b>, if present.
+      </p>
+      <pre>
+_.every([true, 1, null, 'yes'], _.identity);
+=&gt; false
+</pre>
+
+      <p id="some">
+        <b class="header">some</b><code>_.some(list, [iterator], [context])</code>
+        <span class="alias">Alias: <b>any</b></span>
+        <br />
+        Returns <i>true</i> if any of the values in the <b>list</b> pass the
+        <b>iterator</b> truth test. Short-circuits and stops traversing the list
+        if a true element is found. Delegates to the native method <b>some</b>,
+        if present.
+      </p>
+      <pre>
+_.some([null, 0, 'yes', false]);
+=&gt; true
+</pre>
+
+      <p id="contains">
+        <b class="header">contains</b><code>_.contains(list, value)</code>
+        <span class="alias">Alias: <b>include</b></span>
+        <br />
+        Returns <i>true</i> if the <b>value</b> is present in the <b>list</b>.
+        Uses <b>indexOf</b> internally, if <b>list</b> is an Array.
+      </p>
+      <pre>
+_.contains([1, 2, 3], 3);
+=&gt; true
+</pre>
+
+      <p id="invoke">
+        <b class="header">invoke</b><code>_.invoke(list, methodName, [*arguments])</code>
+        <br />
+        Calls the method named by <b>methodName</b> on each value in the <b>list</b>.
+        Any extra arguments passed to <b>invoke</b> will be forwarded on to the
+        method invocation.
+      </p>
+      <pre>
+_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+=&gt; [[1, 5, 7], [1, 2, 3]]
+</pre>
+
+      <p id="pluck">
+        <b class="header">pluck</b><code>_.pluck(list, propertyName)</code>
+        <br />
+        A convenient version of what is perhaps the most common use-case for
+        <b>map</b>: extracting a list of property values.
+      </p>
+      <pre>
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.pluck(stooges, 'name');
+=&gt; ["moe", "larry", "curly"]
+</pre>
+
+      <p id="max">
+        <b class="header">max</b><code>_.max(list, [iterator], [context])</code>
+        <br />
+        Returns the maximum value in <b>list</b>. If <b>iterator</b> is passed,
+        it will be used on each value to generate the criterion by which the
+        value is ranked.
+      </p>
+      <pre>
+var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
+_.max(stooges, function(stooge){ return stooge.age; });
+=&gt; {name : 'curly', age : 60};
+</pre>
+
+      <p id="min">
+        <b class="header">min</b><code>_.min(list, [iterator], [context])</code>
+        <br />
+        Returns the minimum value in <b>list</b>. If <b>iterator</b> is passed,
+        it will be used on each value to generate the criterion by which the
+        value is ranked.
+      </p>
+      <pre>
+var numbers = [10, 5, 100, 2, 1000];
+_.min(numbers);
+=&gt; 2
+</pre>
+
+      <p id="sortBy">
+        <b class="header">sortBy</b><code>_.sortBy(list, iterator, [context])</code>
+        <br />
+        Returns a sorted copy of <b>list</b>, ranked in ascending order by the
+        results of running each value through <b>iterator</b>. Iterator may
+        also be the string name of the property to sort by (eg. <tt>length</tt>).
+      </p>
+      <pre>
+_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
+=&gt; [5, 4, 6, 3, 1, 2]
+</pre>
+
+      <p id="groupBy">
+        <b class="header">groupBy</b><code>_.groupBy(list, iterator, [context])</code>
+        <br />
+        Splits a collection into sets, grouped by the result of running each
+        value through <b>iterator</b>. If <b>iterator</b> is a string instead of
+        a function, groups by the property named by <b>iterator</b> on each of
+        the values.
+      </p>
+      <pre>
+_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
+=&gt; {1: [1.3], 2: [2.1, 2.4]}
+
+_.groupBy(['one', 'two', 'three'], 'length');
+=&gt; {3: ["one", "two"], 5: ["three"]}
+</pre>
+
+      <p id="countBy">
+        <b class="header">countBy</b><code>_.countBy(list, iterator, [context])</code>
+        <br />
+        Sorts a list into groups and returns a count for the number of objects
+        in each group.
+        Similar to <tt>groupBy</tt>, but instead of returning a list of values,
+        returns a count for the number of values in that group.
+      </p>
+      <pre>
+_.countBy([1, 2, 3, 4, 5], function(num) {
+  return num % 2 == 0 ? 'even' : 'odd';
+});
+=&gt; {odd: 3, even: 2}
+</pre>
+
+      <p id="shuffle">
+        <b class="header">shuffle</b><code>_.shuffle(list)</code>
+        <br />
+        Returns a shuffled copy of the <b>list</b>, using a version of the
+        <a href="http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle</a>.
+      </p>
+      <pre>
+_.shuffle([1, 2, 3, 4, 5, 6]);
+=&gt; [4, 1, 6, 3, 5, 2]
+</pre>
+
+      <p id="toArray">
+        <b class="header">toArray</b><code>_.toArray(list)</code>
+        <br />
+        Converts the <b>list</b> (anything that can be iterated over), into a
+        real Array. Useful for transmuting the <b>arguments</b> object.
+      </p>
+      <pre>
+(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+=&gt; [2, 3, 4]
+</pre>
+
+      <p id="size">
+        <b class="header">size</b><code>_.size(list)</code>
+        <br />
+        Return the number of values in the <b>list</b>.
+      </p>
+      <pre>
+_.size({one : 1, two : 2, three : 3});
+=&gt; 3
+</pre>
+
+      <h2 id="arrays">Array Functions</h2>
+
+      <p>
+        <i>
+          Note: All array functions will also work on the <b>arguments</b> object.
+          However, Underscore functions are not designed to work on "sparse" arrays.
+        </i>
+      </p>
+
+      <p id="first">
+        <b class="header">first</b><code>_.first(array, [n])</code>
+        <span class="alias">Alias: <b>head</b>, <b>take</b></span>
+        <br />
+        Returns the first element of an <b>array</b>. Passing <b>n</b> will
+        return the first <b>n</b> elements of the array.
+      </p>
+      <pre>
+_.first([5, 4, 3, 2, 1]);
+=&gt; 5
+</pre>
+
+      <p id="initial">
+        <b class="header">initial</b><code>_.initial(array, [n])</code>
+        <br />
+        Returns everything but the last entry of the array. Especially useful on
+        the arguments object. Pass <b>n</b> to exclude the last <b>n</b> elements
+        from the result.
+      </p>
+      <pre>
+_.initial([5, 4, 3, 2, 1]);
+=&gt; [5, 4, 3, 2]
+</pre>
+
+      <p id="last">
+        <b class="header">last</b><code>_.last(array, [n])</code>
+        <br />
+        Returns the last element of an <b>array</b>. Passing <b>n</b> will return
+        the last <b>n</b> elements of the array.
+      </p>
+      <pre>
+_.last([5, 4, 3, 2, 1]);
+=&gt; 1
+</pre>
+
+      <p id="rest">
+        <b class="header">rest</b><code>_.rest(array, [index])</code>
+        <span class="alias">Alias: <b>tail, drop</b></span>
+        <br />
+        Returns the <b>rest</b> of the elements in an array. Pass an <b>index</b>
+        to return the values of the array from that index onward.
+      </p>
+      <pre>
+_.rest([5, 4, 3, 2, 1]);
+=&gt; [4, 3, 2, 1]
+</pre>
+
+      <p id="compact">
+        <b class="header">compact</b><code>_.compact(array)</code>
+        <br />
+        Returns a copy of the <b>array</b> with all falsy values removed.
+        In JavaScript, <i>false</i>, <i>null</i>, <i>0</i>, <i>""</i>,
+        <i>undefined</i> and <i>NaN</i> are all falsy.
+      </p>
+      <pre>
+_.compact([0, 1, false, 2, '', 3]);
+=&gt; [1, 2, 3]
+</pre>
+
+      <p id="flatten">
+        <b class="header">flatten</b><code>_.flatten(array, [shallow])</code>
+        <br />
+        Flattens a nested <b>array</b> (the nesting can be to any depth). If you
+        pass <b>shallow</b>, the array will only be flattened a single level.
+      </p>
+      <pre>
+_.flatten([1, [2], [3, [[4]]]]);
+=&gt; [1, 2, 3, 4];
+
+_.flatten([1, [2], [3, [[4]]]], true);
+=&gt; [1, 2, 3, [[4]]];
+</pre>
+
+      <p id="without">
+        <b class="header">without</b><code>_.without(array, [*values])</code>
+        <br />
+        Returns a copy of the <b>array</b> with all instances of the <b>values</b>
+        removed.
+      </p>
+      <pre>
+_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+=&gt; [2, 3, 4]
+</pre>
+
+      <p id="union">
+        <b class="header">union</b><code>_.union(*arrays)</code>
+        <br />
+        Computes the union of the passed-in <b>arrays</b>: the list of unique items,
+        in order, that are present in one or more of the <b>arrays</b>.
+      </p>
+      <pre>
+_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=&gt; [1, 2, 3, 101, 10]
+</pre>
+
+      <p id="intersection">
+        <b class="header">intersection</b><code>_.intersection(*arrays)</code>
+        <br />
+        Computes the list of values that are the intersection of all the <b>arrays</b>.
+        Each value in the result is present in each of the <b>arrays</b>.
+      </p>
+      <pre>
+_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+=&gt; [1, 2]
+</pre>
+
+      <p id="difference">
+        <b class="header">difference</b><code>_.difference(array, *others)</code>
+        <br />
+        Similar to <b>without</b>, but returns the values from <b>array</b> that
+        are not present in the <b>other</b> arrays.
+      </p>
+      <pre>
+_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+=&gt; [1, 3, 4]
+</pre>
+
+      <p id="uniq">
+        <b class="header">uniq</b><code>_.uniq(array, [isSorted], [iterator])</code>
+        <span class="alias">Alias: <b>unique</b></span>
+        <br />
+        Produces a duplicate-free version of the <b>array</b>, using <i>===</i> to test
+        object equality. If you know in advance that the <b>array</b> is sorted,
+        passing <i>true</i> for <b>isSorted</b> will run a much faster algorithm.
+        If you want to compute unique items based on a transformation, pass an
+        <b>iterator</b> function.
+      </p>
+      <pre>
+_.uniq([1, 2, 1, 3, 1, 4]);
+=&gt; [1, 2, 3, 4]
+</pre>
+
+      <p id="zip">
+        <b class="header">zip</b><code>_.zip(*arrays)</code>
+        <br />
+        Merges together the values of each of the <b>arrays</b> with the
+        values at the corresponding position. Useful when you have separate
+        data sources that are coordinated through matching array indexes.
+        If you're working with a matrix of nested arrays, <b>zip.apply</b>
+        can transpose the matrix in a similar fashion.
+      </p>
+      <pre>
+_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
+=&gt; [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]
+</pre>
+
+      <p id="object">
+        <b class="header">object</b><code>_.object(list, [values])</code>
+        <br />
+        Converts arrays into objects. Pass either a single list of
+        <tt>[key, value]</tt> pairs, or a list of keys, and a list of values.
+      </p>
+      <pre>
+_.object(['moe', 'larry', 'curly'], [30, 40, 50]);
+=&gt; {moe: 30, larry: 40, curly: 50}
+
+_.object([['moe', 30], ['larry', 40], ['curly', 50]]);
+=&gt; {moe: 30, larry: 40, curly: 50}
+</pre>
+
+      <p id="indexOf">
+        <b class="header">indexOf</b><code>_.indexOf(array, value, [isSorted])</code>
+        <br />
+        Returns the index at which <b>value</b> can be found in the <b>array</b>,
+        or <i>-1</i> if value is not present in the <b>array</b>. Uses the native
+        <b>indexOf</b> function unless it's missing. If you're working with a
+        large array, and you know that the array is already sorted, pass <tt>true</tt>
+        for <b>isSorted</b> to use a faster binary search ... or, pass a number as
+        the third argument in order to look for the first matching value in the
+        array after the given index.
+      </p>
+      <pre>
+_.indexOf([1, 2, 3], 2);
+=&gt; 1
+</pre>
+
+      <p id="lastIndexOf">
+        <b class="header">lastIndexOf</b><code>_.lastIndexOf(array, value, [fromIndex])</code>
+        <br />
+        Returns the index of the last occurrence of <b>value</b> in the <b>array</b>,
+        or <i>-1</i> if value is not present. Uses the native <b>lastIndexOf</b>
+        function if possible. Pass <b>fromIndex</b> to start your search at a
+        given index.
+      </p>
+      <pre>
+_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+=&gt; 4
+</pre>
+
+      <p id="sortedIndex">
+        <b class="header">sortedIndex</b><code>_.sortedIndex(list, value, [iterator], [context])</code>
+        <br />
+        Uses a binary search to determine the index at which the <b>value</b>
+        <i>should</i> be inserted into the <b>list</b> in order to maintain the <b>list</b>'s
+        sorted order. If an <b>iterator</b> is passed, it will be used to compute
+        the sort ranking of each value, including the <b>value</b> you pass.
+      </p>
+      <pre>
+_.sortedIndex([10, 20, 30, 40, 50], 35);
+=&gt; 3
+</pre>
+
+      <p id="range">
+        <b class="header">range</b><code>_.range([start], stop, [step])</code>
+        <br />
+        A function to create flexibly-numbered lists of integers, handy for
+        <tt>each</tt> and <tt>map</tt> loops. <b>start</b>, if omitted, defaults
+        to <i>0</i>; <b>step</b> defaults to <i>1</i>. Returns a list of integers
+        from <b>start</b> to <b>stop</b>, incremented (or decremented) by <b>step</b>,
+        exclusive.
+      </p>
+      <pre>
+_.range(10);
+=&gt; [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+_.range(1, 11);
+=&gt; [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+_.range(0, 30, 5);
+=&gt; [0, 5, 10, 15, 20, 25]
+_.range(0, -10, -1);
+=&gt; [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+_.range(0);
+=&gt; []
+</pre>
+
+      <h2 id="functions">Function (uh, ahem) Functions</h2>
+
+      <p id="bind">
+        <b class="header">bind</b><code>_.bind(function, object, [*arguments])</code>
+        <br />
+        Bind a <b>function</b> to an <b>object</b>, meaning that whenever
+        the function is called, the value of <i>this</i> will be the <b>object</b>.
+        Optionally, pass <b>arguments</b> to the <b>function</b> to pre-fill them,
+        also known as <b>partial application</b>.
+      </p>
+      <pre>
+var func = function(greeting){ return greeting + ': ' + this.name };
+func = _.bind(func, {name : 'moe'}, 'hi');
+func();
+=&gt; 'hi: moe'
+</pre>
+
+      <p id="bindAll">
+        <b class="header">bindAll</b><code>_.bindAll(object, [*methodNames])</code>
+        <br />
+        Binds a number of methods on the <b>object</b>, specified by
+        <b>methodNames</b>, to be run in the context of that object whenever they
+        are invoked. Very handy for binding functions that are going to be used
+        as event handlers, which would otherwise be invoked with a fairly useless
+        <i>this</i>. If no <b>methodNames</b> are provided, all of the object's
+        function properties will be bound to it.
+      </p>
+      <pre>
+var buttonView = {
+  label   : 'underscore',
+  onClick : function(){ alert('clicked: ' + this.label); },
+  onHover : function(){ console.log('hovering: ' + this.label); }
+};
+_.bindAll(buttonView);
+jQuery('#underscore_button').bind('click', buttonView.onClick);
+=&gt; When the button is clicked, this.label will have the correct value...
+</pre>
+
+      <p id="partial">
+        <b class="header">partial</b><code>_.partial(function, [*arguments])</code>
+        <br />
+        Partially apply a function by filling in any number of its arguments,
+        <i>without</i> changing its dynamic <tt>this</tt> value. A close cousin
+        of <a href="#bind">bind</a>.
+      </p>
+      <pre>
+var add = function(a, b) { return a + b; };
+add5 = _.partial(add, 5);
+add5(10);
+=&gt; 15
+</pre>
+
+      <p id="memoize">
+        <b class="header">memoize</b><code>_.memoize(function, [hashFunction])</code>
+        <br />
+        Memoizes a given <b>function</b> by caching the computed result. Useful
+        for speeding up slow-running computations. If passed an optional
+        <b>hashFunction</b>, it will be used to compute the hash key for storing
+        the result, based on the arguments to the original function. The default
+        <b>hashFunction</b> just uses the first argument to the memoized function
+        as the key.
+      </p>
+      <pre>
+var fibonacci = _.memoize(function(n) {
+  return n &lt; 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+});
+</pre>
+
+      <p id="delay">
+        <b class="header">delay</b><code>_.delay(function, wait, [*arguments])</code>
+        <br />
+        Much like <b>setTimeout</b>, invokes <b>function</b> after <b>wait</b>
+        milliseconds. If you pass the optional <b>arguments</b>, they will be
+        forwarded on to the <b>function</b> when it is invoked.
+      </p>
+      <pre>
+var log = _.bind(console.log, console);
+_.delay(log, 1000, 'logged later');
+=&gt; 'logged later' // Appears after one second.
+</pre>
+
+      <p id="defer">
+        <b class="header">defer</b><code>_.defer(function, [*arguments])</code>
+        <br />
+        Defers invoking the <b>function</b> until the current call stack has cleared,
+        similar to using <b>setTimeout</b> with a delay of 0. Useful for performing
+        expensive computations or HTML rendering in chunks without blocking the UI thread
+        from updating. If you pass the optional <b>arguments</b>, they will be
+        forwarded on to the <b>function</b> when it is invoked.
+      </p>
+      <pre>
+_.defer(function(){ alert('deferred'); });
+// Returns from the function before the alert runs.
+</pre>
+
+      <p id="throttle">
+        <b class="header">throttle</b><code>_.throttle(function, wait)</code>
+        <br />
+        Creates and returns a new, throttled version of the passed function,
+        that, when invoked repeatedly, will only actually call the original function
+        at most once per every <b>wait</b>
+        milliseconds. Useful for rate-limiting events that occur faster than you
+        can keep up with.
+      </p>
+      <pre>
+var throttled = _.throttle(updatePosition, 100);
+$(window).scroll(throttled);
+</pre>
+
+      <p id="debounce">
+        <b class="header">debounce</b><code>_.debounce(function, wait, [immediate])</code>
+        <br />
+        Creates and returns a new debounced version of the passed function that
+        will postpone its execution until after
+        <b>wait</b> milliseconds have elapsed since the last time it
+        was invoked. Useful for implementing behavior that should only happen
+        <i>after</i> the input has stopped arriving. For example: rendering a
+        preview of a Markdown comment, recalculating a layout after the window
+        has stopped being resized, and so on.
+      </p>
+
+      <p>
+        Pass <tt>true</tt> for the <b>immediate</b> parameter to cause
+        <b>debounce</b> to trigger the function on the leading instead of the
+        trailing edge of the <b>wait</b> interval. Useful in circumstances like
+        preventing accidental double-clicks on a "submit" button from firing a
+        second time.
+      </p>
+
+      <pre>
+var lazyLayout = _.debounce(calculateLayout, 300);
+$(window).resize(lazyLayout);
+</pre>
+
+      <p id="once">
+        <b class="header">once</b><code>_.once(function)</code>
+        <br />
+        Creates a version of the function that can only be called one time.
+        Repeated calls to the modified function will have no effect, returning
+        the value from the original call. Useful for initialization functions,
+        instead of having to set a boolean flag and then check it later.
+      </p>
+      <pre>
+var initialize = _.once(createApplication);
+initialize();
+initialize();
+// Application is only created once.
+</pre>
+
+      <p id="after">
+        <b class="header">after</b><code>_.after(count, function)</code>
+        <br />
+        Creates a version of the function that will only be run after first
+        being called <b>count</b> times. Useful for grouping asynchronous responses,
+        where you want to be sure that all the async calls have finished, before
+        proceeding.
+      </p>
+      <pre>
+var renderNotes = _.after(notes.length, render);
+_.each(notes, function(note) {
+  note.asyncSave({success: renderNotes});
+});
+// renderNotes is run once, after all notes have saved.
+</pre>
+
+      <p id="wrap">
+        <b class="header">wrap</b><code>_.wrap(function, wrapper)</code>
+        <br />
+        Wraps the first <b>function</b> inside of the <b>wrapper</b> function,
+        passing it as the first argument. This allows the <b>wrapper</b> to
+        execute code before and after the <b>function</b> runs, adjust the arguments,
+        and execute it conditionally.
+      </p>
+      <pre>
+var hello = function(name) { return "hello: " + name; };
+hello = _.wrap(hello, function(func) {
+  return "before, " + func("moe") + ", after";
+});
+hello();
+=&gt; 'before, hello: moe, after'
+</pre>
+
+      <p id="compose">
+        <b class="header">compose</b><code>_.compose(*functions)</code>
+        <br />
+        Returns the composition of a list of <b>functions</b>, where each function
+        consumes the return value of the function that follows. In math terms,
+        composing the functions <i>f()</i>, <i>g()</i>, and <i>h()</i> produces
+        <i>f(g(h()))</i>.
+      </p>
+      <pre>
+var greet    = function(name){ return "hi: " + name; };
+var exclaim  = function(statement){ return statement + "!"; };
+var welcome = _.compose(exclaim, greet);
+welcome('moe');
+=&gt; 'hi: moe!'
+</pre>
+
+      <h2 id="objects">Object Functions</h2>
+
+      <p id="keys">
+        <b class="header">keys</b><code>_.keys(object)</code>
+        <br />
+        Retrieve all the names of the <b>object</b>'s properties.
+      </p>
+      <pre>
+_.keys({one : 1, two : 2, three : 3});
+=&gt; ["one", "two", "three"]
+</pre>
+
+      <p id="values">
+        <b class="header">values</b><code>_.values(object)</code>
+        <br />
+        Return all of the values of the <b>object</b>'s properties.
+      </p>
+      <pre>
+_.values({one : 1, two : 2, three : 3});
+=&gt; [1, 2, 3]
+</pre>
+
+      <p id="pairs">
+        <b class="header">pairs</b><code>_.pairs(object)</code>
+        <br />
+        Convert an object into a list of <tt>[key, value]</tt> pairs.
+      </p>
+      <pre>
+_.pairs({one: 1, two: 2, three: 3});
+=&gt; [["one", 1], ["two", 2], ["three", 3]]
+</pre>
+
+      <p id="invert">
+        <b class="header">invert</b><code>_.invert(object)</code>
+        <br />
+        Returns a copy of the <b>object</b> where the keys have become the values
+        and the values the keys. For this to work, all of your object's values
+        should be unique and string serializable.
+      </p>
+      <pre>
+_.invert({Moe: "Moses", Larry: "Louis", Curly: "Jerome"});
+=&gt; {Moses: "Moe", Louis: "Larry", Jerome: "Curly"};
+</pre>
+
+      <p id="object-functions">
+        <b class="header">functions</b><code>_.functions(object)</code>
+        <span class="alias">Alias: <b>methods</b></span>
+        <br />
+        Returns a sorted list of the names of every method in an object &mdash;
+        that is to say, the name of every function property of the object.
+      </p>
+      <pre>
+_.functions(_);
+=&gt; ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ...
+</pre>
+
+      <p id="extend">
+        <b class="header">extend</b><code>_.extend(destination, *sources)</code>
+        <br />
+        Copy all of the properties in the <b>source</b> objects over to the
+        <b>destination</b> object, and return the <b>destination</b> object.
+        It's in-order, so the last source will override properties of the same
+        name in previous arguments.
+      </p>
+      <pre>
+_.extend({name : 'moe'}, {age : 50});
+=&gt; {name : 'moe', age : 50}
+</pre>
+
+      <p id="pick">
+        <b class="header">pick</b><code>_.pick(object, *keys)</code>
+        <br />
+        Return a copy of the <b>object</b>, filtered to only have values for
+        the whitelisted <b>keys</b> (or array of valid keys).
+      </p>
+      <pre>
+_.pick({name : 'moe', age: 50, userid : 'moe1'}, 'name', 'age');
+=&gt; {name : 'moe', age : 50}
+</pre>
+
+      <p id="omit">
+        <b class="header">omit</b><code>_.omit(object, *keys)</code>
+        <br />
+        Return a copy of the <b>object</b>, filtered to omit the blacklisted
+        <b>keys</b> (or array of keys).
+      </p>
+      <pre>
+_.omit({name : 'moe', age : 50, userid : 'moe1'}, 'userid');
+=&gt; {name : 'moe', age : 50}
+</pre>
+
+      <p id="defaults">
+        <b class="header">defaults</b><code>_.defaults(object, *defaults)</code>
+        <br />
+        Fill in null and undefined properties in <b>object</b> with values from the
+        <b>defaults</b> objects, and return the <b>object</b>. As soon as the
+        property is filled, further defaults will have no effect.
+      </p>
+      <pre>
+var iceCream = {flavor : "chocolate"};
+_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
+=&gt; {flavor : "chocolate", sprinkles : "lots"}
+</pre>
+
+      <p id="clone">
+        <b class="header">clone</b><code>_.clone(object)</code>
+        <br />
+        Create a shallow-copied clone of the <b>object</b>. Any nested objects
+        or arrays will be copied by reference, not duplicated.
+      </p>
+      <pre>
+_.clone({name : 'moe'});
+=&gt; {name : 'moe'};
+</pre>
+
+      <p id="tap">
+        <b class="header">tap</b><code>_.tap(object, interceptor)</code>
+        <br />
+        Invokes <b>interceptor</b> with the <b>object</b>, and then returns <b>object</b>.
+        The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
+      </p>
+      <pre>
+_.chain([1,2,3,200])
+  .filter(function(num) { return num % 2 == 0; })
+  .tap(alert)
+  .map(function(num) { return num * num })
+  .value();
+=&gt; // [2, 200] (alerted)
+=&gt; [4, 40000]
+</pre>
+
+      <p id="has">
+        <b class="header">has</b><code>_.has(object, key)</code>
+        <br />
+        Does the object contain the given key? Identical to
+        <tt>object.hasOwnProperty(key)</tt>, but uses a safe reference to the
+        <tt>hasOwnProperty</tt> function, in case it's been
+        <a href="http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/">overridden accidentally</a>.
+      </p>
+      <pre>
+_.has({a: 1, b: 2, c: 3}, "b");
+=&gt; true
+</pre>
+
+      <p id="isEqual">
+        <b class="header">isEqual</b><code>_.isEqual(object, other)</code>
+        <br />
+        Performs an optimized deep comparison between the two objects, to determine
+        if they should be considered equal.
+      </p>
+      <pre>
+var moe   = {name : 'moe', luckyNumbers : [13, 27, 34]};
+var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
+moe == clone;
+=&gt; false
+_.isEqual(moe, clone);
+=&gt; true
+</pre>
+
+      <p id="isEmpty">
+        <b class="header">isEmpty</b><code>_.isEmpty(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> contains no values.
+      </p>
+      <pre>
+_.isEmpty([1, 2, 3]);
+=&gt; false
+_.isEmpty({});
+=&gt; true
+</pre>
+
+      <p id="isElement">
+        <b class="header">isElement</b><code>_.isElement(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a DOM element.
+      </p>
+      <pre>
+_.isElement(jQuery('body')[0]);
+=&gt; true
+</pre>
+
+      <p id="isArray">
+        <b class="header">isArray</b><code>_.isArray(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is an Array.
+      </p>
+      <pre>
+(function(){ return _.isArray(arguments); })();
+=&gt; false
+_.isArray([1,2,3]);
+=&gt; true
+</pre>
+
+      <p id="isObject">
+        <b class="header">isObject</b><code>_.isObject(value)</code>
+        <br />
+        Returns <i>true</i> if <b>value</b> is an Object. Note that JavaScript
+        arrays and functions are objects, while (normal) strings and numbers are not.
+      </p>
+      <pre>
+_.isObject({});
+=&gt; true
+_.isObject(1);
+=&gt; false
+</pre>
+
+      <p id="isArguments">
+        <b class="header">isArguments</b><code>_.isArguments(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is an Arguments object.
+      </p>
+      <pre>
+(function(){ return _.isArguments(arguments); })(1, 2, 3);
+=&gt; true
+_.isArguments([1,2,3]);
+=&gt; false
+</pre>
+
+      <p id="isFunction">
+        <b class="header">isFunction</b><code>_.isFunction(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a Function.
+      </p>
+      <pre>
+_.isFunction(alert);
+=&gt; true
+</pre>
+
+      <p id="isString">
+        <b class="header">isString</b><code>_.isString(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a String.
+      </p>
+      <pre>
+_.isString("moe");
+=&gt; true
+</pre>
+
+      <p id="isNumber">
+        <b class="header">isNumber</b><code>_.isNumber(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a Number (including <tt>NaN</tt>).
+      </p>
+      <pre>
+_.isNumber(8.4 * 5);
+=&gt; true
+</pre>
+
+      <p id="isFinite">
+        <b class="header">isFinite</b><code>_.isFinite(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a finite Number.
+      </p>
+      <pre>
+_.isFinite(-101);
+=&gt; true
+
+_.isFinite(-Infinity);
+=&gt; false
+</pre>
+
+      <p id="isBoolean">
+        <b class="header">isBoolean</b><code>_.isBoolean(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is either <i>true</i> or <i>false</i>.
+      </p>
+      <pre>
+_.isBoolean(null);
+=&gt; false
+</pre>
+
+      <p id="isDate">
+        <b class="header">isDate</b><code>_.isDate(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a Date.
+      </p>
+      <pre>
+_.isDate(new Date());
+=&gt; true
+</pre>
+
+      <p id="isRegExp">
+        <b class="header">isRegExp</b><code>_.isRegExp(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is a RegExp.
+      </p>
+      <pre>
+_.isRegExp(/moe/);
+=&gt; true
+</pre>
+
+      <p id="isNaN">
+        <b class="header">isNaN</b><code>_.isNaN(object)</code>
+        <br />
+        Returns <i>true</i> if <b>object</b> is <i>NaN</i>.<br /> Note: this is not
+        the same as the native <b>isNaN</b> function, which will also return
+        true if the variable is <i>undefined</i>.
+      </p>
+      <pre>
+_.isNaN(NaN);
+=&gt; true
+isNaN(undefined);
+=&gt; true
+_.isNaN(undefined);
+=&gt; false
+</pre>
+
+      <p id="isNull">
+        <b class="header">isNull</b><code>_.isNull(object)</code>
+        <br />
+        Returns <i>true</i> if the value of <b>object</b> is <i>null</i>.
+      </p>
+      <pre>
+_.isNull(null);
+=&gt; true
+_.isNull(undefined);
+=&gt; false
+</pre>
+
+      <p id="isUndefined">
+        <b class="header">isUndefined</b><code>_.isUndefined(value)</code>
+        <br />
+        Returns <i>true</i> if <b>value</b> is <i>undefined</i>.
+      </p>
+      <pre>
+_.isUndefined(window.missingVariable);
+=&gt; true
+</pre>
+
+      <h2 id="utility">Utility Functions</h2>
+
+      <p id="noConflict">
+        <b class="header">noConflict</b><code>_.noConflict()</code>
+        <br />
+        Give control of the "_" variable back to its previous owner. Returns
+        a reference to the <b>Underscore</b> object.
+      </p>
+      <pre>
+var underscore = _.noConflict();</pre>
+
+      <p id="identity">
+        <b class="header">identity</b><code>_.identity(value)</code>
+        <br />
+        Returns the same value that is used as the argument. In math:
+        <tt>f(x) = x</tt><br />
+        This function looks useless, but is used throughout Underscore as
+        a default iterator.
+      </p>
+      <pre>
+var moe = {name : 'moe'};
+moe === _.identity(moe);
+=&gt; true</pre>
+
+      <p id="times">
+        <b class="header">times</b><code>_.times(n, iterator, [context])</code>
+        <br />
+        Invokes the given iterator function <b>n</b> times. Each invocation of
+        <b>iterator</b> is called with an <tt>index</tt> argument.
+        <br />
+        <i>Note: this example uses the <a href="#chaining">chaining syntax</a></i>.
+      </p>
+      <pre>
+_(3).times(function(n){ genie.grantWishNumber(n); });</pre>
+
+      <p id="random">
+        <b class="header">random</b><code>_.random(min, max)</code>
+        <br />
+        Returns a random integer between <b>min</b> and <b>max</b>, inclusive.
+        If you only pass one argument, it will return a number between <tt>0</tt>
+        and that number.
+      </p>
+      <pre>
+_.random(0, 100);
+=&gt; 42</pre>
+
+      <p id="mixin">
+        <b class="header">mixin</b><code>_.mixin(object)</code>
+        <br />
+        Allows you to extend Underscore with your own utility functions. Pass
+        a hash of <tt>{name: function}</tt> definitions to have your functions
+        added to the Underscore object, as well as the OOP wrapper.
+      </p>
+      <pre>
+_.mixin({
+  capitalize : function(string) {
+    return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
+  }
+});
+_("fabio").capitalize();
+=&gt; "Fabio"
+</pre>
+
+      <p id="uniqueId">
+        <b class="header">uniqueId</b><code>_.uniqueId([prefix])</code>
+        <br />
+        Generate a globally-unique id for client-side models or DOM elements
+        that need one. If <b>prefix</b> is passed, the id will be appended to it.
+      </p>
+      <pre>
+_.uniqueId('contact_');
+=&gt; 'contact_104'</pre>
+
+      <p id="escape">
+        <b class="header">escape</b><code>_.escape(string)</code>
+        <br />
+        Escapes a string for insertion into HTML, replacing
+        <tt>&amp;</tt>, <tt>&lt;</tt>, <tt>&gt;</tt>, <tt>&quot;</tt>, <tt>&#x27;</tt>, and <tt>&#x2F;</tt> characters.
+      </p>
+      <pre>
+_.escape('Curly, Larry &amp; Moe');
+=&gt; "Curly, Larry &amp;amp; Moe"</pre>
+
+      <p id="unescape">
+        <b class="header">unescape</b><code>_.unescape(string)</code>
+        <br />
+        The opposite of <a href="#escape"><b>escape</b></a>, replaces
+        <tt>&amp;amp;</tt>, <tt>&amp;lt;</tt>, <tt>&amp;gt;</tt>,
+        <tt>&amp;quot;</tt>, <tt>&amp;#x27;</tt>, and <tt>&amp;#x2F;</tt>
+        with their unescaped counterparts.
+      </p>
+      <pre>
+_.unescape('Curly, Larry &amp;amp; Moe');
+=&gt; "Curly, Larry &amp; Moe"</pre>
+
+      <p id="result">
+        <b class="header">result</b><code>_.result(object, property)</code>
+        <br />
+        If the value of the named property is a function then invoke it; otherwise, return it.
+      </p>
+      <pre>
+var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
+_.result(object, 'cheese');
+=&gt; "crumpets"
+_.result(object, 'stuff');
+=&gt; "nonsense"</pre>
+
+      <p id="template">
+        <b class="header">template</b><code>_.template(templateString, [data], [settings])</code>
+        <br />
+        Compiles JavaScript templates into functions that can be evaluated
+        for rendering. Useful for rendering complicated bits of HTML from JSON
+        data sources. Template functions can both interpolate variables, using
+        <tt>&lt;%= &hellip; %&gt;</tt>, as well as execute arbitrary JavaScript code, with
+        <tt>&lt;% &hellip; %&gt;</tt>. If you wish to interpolate a value, and have
+        it be HTML-escaped, use <tt>&lt;%- &hellip; %&gt;</tt> When you evaluate a template function, pass in a
+        <b>data</b> object that has properties corresponding to the template's free
+        variables. If you're writing a one-off, you can pass the <b>data</b>
+        object as the second parameter to <b>template</b> in order to render
+        immediately instead of returning a template function.  The <b>settings</b> argument
+        should be a hash containing any <tt>_.templateSettings</tt> that should be overridden.
+      </p>
+
+      <pre>
+var compiled = _.template("hello: &lt;%= name %&gt;");
+compiled({name : 'moe'});
+=&gt; "hello: moe"
+
+var list = "&lt;% _.each(people, function(name) { %&gt; &lt;li&gt;&lt;%= name %&gt;&lt;/li&gt; &lt;% }); %&gt;";
+_.template(list, {people : ['moe', 'curly', 'larry']});
+=&gt; "&lt;li&gt;moe&lt;/li&gt;&lt;li&gt;curly&lt;/li&gt;&lt;li&gt;larry&lt;/li&gt;"
+
+var template = _.template("&lt;b&gt;&lt;%- value %&gt;&lt;/b&gt;");
+template({value : '&lt;script&gt;'});
+=&gt; "&lt;b&gt;&amp;lt;script&amp;gt;&lt;/b&gt;"</pre>
+
+      <p>
+        You can also use <tt>print</tt> from within JavaScript code.  This is
+        sometimes more convenient than using <tt>&lt;%= ... %&gt;</tt>.
+      </p>
+
+      <pre>
+var compiled = _.template("&lt;% print('Hello ' + epithet); %&gt;");
+compiled({epithet: "stooge"});
+=&gt; "Hello stooge."</pre>
+
+      <p>
+        If ERB-style delimiters aren't your cup of tea, you can change Underscore's
+        template settings to use different symbols to set off interpolated code.
+        Define an <b>interpolate</b> regex to match expressions that should be
+        interpolated verbatim, an <b>escape</b> regex to match expressions that should
+        be inserted after being HTML escaped, and an <b>evaluate</b> regex to match
+        expressions that should be evaluated without insertion into the resulting
+        string. You may define or omit any combination of the three.
+        For example, to perform
+        <a href="http://github.com/janl/mustache.js#readme">Mustache.js</a>
+        style templating:
+      </p>
+
+      <pre>
+_.templateSettings = {
+  interpolate : /\{\{(.+?)\}\}/g
+};
+
+var template = _.template("Hello {{ name }}!");
+template({name : "Mustache"});
+=&gt; "Hello Mustache!"</pre>
+
+      <p>
+        By default, <b>template</b> places the values from your data in the local scope
+        via the <tt>with</tt> statement.  However, you can specify a single variable name
+        with the <b>variable</b> setting. This can significantly improve the speed
+        at which a template is able to render.
+      </p>
+
+      <pre>
+_.template("Using 'with': <%= data.answer %>", {answer: 'no'}, {variable: 'data'});
+=&gt; "Using 'with': no"</pre>
+
+      <p>
+        Precompiling your templates can be a big help when debugging errors you can't
+        reproduce.  This is because precompiled templates can provide line numbers and
+        a stack trace, something that is not possible when compiling templates on the client.
+        The <b>source</b> property is available on the compiled template
+        function for easy precompilation.
+      </p>
+
+      <pre>&lt;script&gt;
+  JST.project = <%= _.template(jstText).source %>;
+&lt;/script&gt;</pre>
+
+
+      <h2 id="chaining">Chaining</h2>
+
+      <p>
+        You can use Underscore in either an object-oriented or a functional style,
+        depending on your preference. The following two lines of code are
+        identical ways to double a list of numbers.
+      </p>
+
+    <pre>
+_.map([1, 2, 3], function(n){ return n * 2; });
+_([1, 2, 3]).map(function(n){ return n * 2; });</pre>
+
+      <p>
+        Calling <tt>chain</tt> will cause all future method calls to return
+        wrapped objects. When you've finished the computation, use
+        <tt>value</tt> to retrieve the final value. Here's an example of chaining
+        together a <b>map/flatten/reduce</b>, in order to get the word count of
+        every word in a song.
+      </p>
+
+<pre>
+var lyrics = [
+  {line : 1, words : "I'm a lumberjack and I'm okay"},
+  {line : 2, words : "I sleep all night and I work all day"},
+  {line : 3, words : "He's a lumberjack and he's okay"},
+  {line : 4, words : "He sleeps all night and he works all day"}
+];
+
+_.chain(lyrics)
+  .map(function(line) { return line.words.split(' '); })
+  .flatten()
+  .reduce(function(counts, word) {
+    counts[word] = (counts[word] || 0) + 1;
+    return counts;
+  }, {})
+  .value();
+
+=&gt; {lumberjack : 2, all : 4, night : 2 ... }</pre>
+
+      <p>
+        In addition, the
+        <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/prototype">Array prototype's methods</a>
+        are proxied through the chained Underscore object, so you can slip a
+        <tt>reverse</tt> or a <tt>push</tt> into your chain, and continue to
+        modify the array.
+      </p>
+
+      <p id="chain">
+        <b class="header">chain</b><code>_.chain(obj)</code>
+        <br />
+        Returns a wrapped object. Calling methods on this object will continue
+        to return wrapped objects until <tt>value</tt> is used.
+      </p>
+      <pre>
+var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
+var youngest = _.chain(stooges)
+  .sortBy(function(stooge){ return stooge.age; })
+  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
+  .first()
+  .value();
+=&gt; "moe is 21"
+</pre>
+
+      <p id="value">
+        <b class="header">value</b><code>_(obj).value()</code>
+        <br />
+        Extracts the value of a wrapped object.
+      </p>
+      <pre>
+_([1, 2, 3]).value();
+=&gt; [1, 2, 3]
+</pre>
+
+      <h2 id="links">Links &amp; Suggested Reading</h2>
+
+      <p>
+        The Underscore documentation is also available in
+        <a href="http://learning.github.com/underscore/">Simplified Chinese</a>.
+      </p>
+
+      <p>
+        <a href="http://mirven.github.com/underscore.lua/">Underscore.lua</a>,
+        a Lua port of the functions that are applicable in both languages.
+        Includes OOP-wrapping and chaining.
+        (<a href="http://github.com/mirven/underscore.lua">source</a>)
+      </p>
+
+      <p>
+        <a href="http://underscorem.org">Underscore.m</a>, an Objective-C port
+        of many of the Underscore.js functions, using a syntax that encourages
+        chaining.
+        (<a href="https://github.com/robb/Underscore.m">source</a>)
+      </p>
+
+      <p>
+        <a href="http://kmalakoff.github.com/_.m/">_.m</a>, an alternative
+        Objective-C port that tries to stick a little closer to the original
+        Underscore.js API.
+        (<a href="https://github.com/kmalakoff/_.m">source</a>)
+      </p>
+
+      <p>
+        <a href="http://brianhaveri.github.com/Underscore.php/">Underscore.php</a>,
+        a PHP port of the functions that are applicable in both languages.
+        Includes OOP-wrapping and chaining.
+        (<a href="http://github.com/brianhaveri/Underscore.php">source</a>)
+      </p>
+
+      <p>
+        <a href="http://vti.github.com/underscore-perl/">Underscore-perl</a>,
+        a Perl port of many of the Underscore.js functions,
+        aimed at on Perl hashes and arrays.
+        (<a href="https://github.com/vti/underscore-perl/">source</a>)
+      </p>
+
+      <p>
+        <a href="http://russplaysguitar.github.com/UnderscoreCF/">Underscore.cfc</a>,
+        a Coldfusion port of many of the Underscore.js functions.
+        (<a href="https://github.com/russplaysguitar/underscorecf">source</a>)
+      </p>
+
+      <p>
+        <a href="https://github.com/edtsech/underscore.string">Underscore.string</a>,
+        an Underscore extension that adds functions for string-manipulation:
+        <tt>trim</tt>, <tt>startsWith</tt>, <tt>contains</tt>, <tt>capitalize</tt>,
+        <tt>reverse</tt>, <tt>sprintf</tt>, and more.
+      </p>
+
+      <p>
+        Ruby's <a href="http://ruby-doc.org/core/classes/Enumerable.html">Enumerable</a> module.
+      </p>
+
+      <p>
+        <a href="http://www.prototypejs.org/">Prototype.js</a>, which provides
+        JavaScript with collection functions in the manner closest to Ruby's Enumerable.
+      </p>
+
+      <p>
+        Oliver Steele's
+        <a href="http://osteele.com/sources/javascript/functional/">Functional JavaScript</a>,
+        which includes comprehensive higher-order function support as well as string lambdas.
+      </p>
+
+      <p>
+        Michael Aufreiter's <a href="http://github.com/michael/data">Data.js</a>,
+        a data manipulation + persistence library for JavaScript.
+      </p>
+
+      <p>
+        Python's <a href="http://docs.python.org/library/itertools.html">itertools</a>.
+      </p>
+
+      <h2 id="changelog">Change Log</h2>
+
+      <p>
+        <b class="header">1.4.4</b> &mdash; <small><i>Jan. 30, 2013</i></small> &mdash; <a href="https://github.com/documentcloud/underscore/compare/1.4.3...1.4.4">Diff</a><br />
+        <ul>
+          <li>
+            Added <tt>_.findWhere</tt>, for finding the first element in a list
+            that matches a particular set of keys and values.
+          </li>
+          <li>
+            Added <tt>_.partial</tt>, for partially applying a function <i>without</i>
+            changing its dynamic reference to <tt>this</tt>.
+          </li>
+          <li>
+            Simplified <tt>bind</tt> by removing some edge cases involving
+            constructor functions. In short: don't <tt>_.bind</tt> your
+            constructors.
+          </li>
+          <li>
+            A minor optimization to <tt>invoke</tt>.
+          </li>
+          <li>
+            Fix bug in the minified version due to the minifier incorrectly
+            optimizing-away <tt>isFunction</tt>.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.4.3</b> &mdash; <small><i>Dec. 4, 2012</i></small> &mdash; <a href="https://github.com/documentcloud/underscore/compare/1.4.2...1.4.3">Diff</a><br />
+        <ul>
+          <li>
+            Improved Underscore compatibility with Adobe's JS engine that can be
+            used to script Illustrator, Photoshop, and friends.
+          </li>
+          <li>
+            Added a default <tt>_.identity</tt> iterator to <tt>countBy</tt> and
+            <tt>groupBy</tt>.
+          </li>
+          <li>
+            The <tt>uniq</tt> function can now take <tt>array, iterator, context</tt>
+            as the argument list.
+          </li>
+          <li>
+            The <tt>times</tt> function now returns the mapped array of iterator
+            results.
+          </li>
+          <li>
+            Simplified and fixed bugs in <tt>throttle</tt>.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.4.2</b> &mdash; <small><i>Oct. 1, 2012</i></small> &mdash; <a href="https://github.com/documentcloud/underscore/compare/1.4.1...1.4.2">Diff</a><br />
+        <ul>
+          <li>
+            For backwards compatibility, returned to pre-1.4.0 behavior when
+            passing <tt>null</tt> to iteration functions. They now become no-ops
+            again.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.4.1</b> &mdash; <small><i>Oct. 1, 2012</i></small> &mdash; <a href="https://github.com/documentcloud/underscore/compare/1.4.0...1.4.1">Diff</a><br />
+        <ul>
+          <li>
+            Fixed a 1.4.0 regression in the <tt>lastIndexOf</tt> function.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.4.0</b> &mdash; <small><i>Sept. 27, 2012</i></small>  &mdash; <a href="https://github.com/documentcloud/underscore/compare/1.3.3...1.4.0">Diff</a><br />
+        <ul>
+          <li>
+            Added a <tt>pairs</tt> function, for turning a JavaScript object
+            into <tt>[key, value]</tt> pairs ... as well as an <tt>object</tt>
+            function, for converting an array of <tt>[key, value]</tt> pairs
+            into an object.
+          </li>
+          <li>
+            Added a <tt>countBy</tt> function, for counting the number of objects
+            in a list that match a certain criteria.
+          </li>
+          <li>
+            Added an <tt>invert</tt> function, for performing a simple inversion
+            of the keys and values in an object.
+          </li>
+          <li>
+            Added a <tt>where</tt> function, for easy cases of filtering a list
+            for objects with specific values.
+          </li>
+          <li>
+            Added an <tt>omit</tt> function, for filtering an object to remove
+            certain keys.
+          </li>
+          <li>
+            Added a <tt>random</tt> function, to return a random number in a
+            given range.
+          </li>
+          <li>
+            <tt>_.debounce</tt>'d functions now return their last updated value,
+            just like <tt>_.throttle</tt>'d functions do.
+          </li>
+          <li>
+            The <tt>sortBy</tt> function now runs a stable sort algorithm.
+          </li>
+          <li>
+            Added the optional <tt>fromIndex</tt> option to <tt>indexOf</tt> and
+            <tt>lastIndexOf</tt>.
+          </li>
+          <li>
+            "Sparse" arrays are no longer supported in Underscore iteration
+            functions. Use a <tt>for</tt> loop instead (or better yet, an object).
+          </li>
+          <li>
+            The <tt>min</tt> and <tt>max</tt> functions may now be called on
+            <i>very</i> large arrays.
+          </li>
+          <li>
+            Interpolation in templates now represents <tt>null</tt> and
+            <tt>undefined</tt> as the empty string.
+          </li>
+          <li>
+            <del>Underscore iteration functions no longer accept <tt>null</tt> values
+            as a no-op argument. You'll get an early error instead.</del>
+          </li>
+          <li>
+            A number of edge-cases fixes and tweaks, which you can spot in the
+            <a href="https://github.com/documentcloud/underscore/compare/1.3.3...1.4.0">diff</a>.
+            Depending on how you're using Underscore, <b>1.4.0</b> may be more
+            backwards-incompatible than usual &mdash; please test when you upgrade.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.3.3</b> &mdash; <small><i>April 10, 2012</i></small><br />
+        <ul>
+          <li>
+            Many improvements to <tt>_.template</tt>, which now provides the
+            <tt>source</tt> of the template function as a property, for potentially
+            even more efficient pre-compilation on the server-side. You may now
+            also set the <tt>variable</tt> option when creating a template,
+            which will cause your passed-in data to be made available under the
+            variable you named, instead of using a <tt>with</tt> statement &mdash;
+            significantly improving the speed of rendering the template.
+          </li>
+          <li>
+            Added the <tt>pick</tt> function, which allows you to filter an
+            object literal with a whitelist of allowed property names.
+          </li>
+          <li>
+            Added the <tt>result</tt> function, for convenience when working
+            with APIs that allow either functions or raw properties.
+          </li>
+          <li>
+            Added the <tt>isFinite</tt> function, because sometimes knowing that
+            a value is a number just ain't quite enough.
+          </li>
+          <li>
+            The <tt>sortBy</tt> function may now also be passed the string name
+            of a property to use as the sort order on each object.
+          </li>
+          <li>
+            Fixed <tt>uniq</tt> to work with sparse arrays.
+          </li>
+          <li>
+            The <tt>difference</tt> function now performs a shallow flatten
+            instead of a deep one when computing array differences.
+          </li>
+          <li>
+            The <tt>debounce</tt> function now takes an <tt>immediate</tt>
+            parameter, which will cause the callback to fire on the leading
+            instead of the trailing edge.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.3.1</b> &mdash; <small><i>Jan. 23, 2012</i></small><br />
+        <ul>
+          <li>
+            Added an <tt>_.has</tt> function, as a safer way to use <tt>hasOwnProperty</tt>.
+          </li>
+          <li>
+            Added <tt>_.collect</tt> as an alias for <tt>_.map</tt>. Smalltalkers, rejoice.
+          </li>
+          <li>
+            Reverted an old change so that <tt>_.extend</tt> will correctly copy
+            over keys with undefined values again.
+          </li>
+          <li>
+            Bugfix to stop escaping slashes within interpolations in <tt>_.template</tt>.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.3.0</b> &mdash; <small><i>Jan. 11, 2012</i></small><br />
+        <ul>
+          <li>
+            Removed AMD (RequireJS) support from Underscore. If you'd like to use
+            Underscore with RequireJS, you can load it as a normal script, wrap
+            or patch your copy, or download a forked version.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.2.4</b> &mdash; <small><i>Jan. 4, 2012</i></small><br />
+        <ul>
+          <li>
+            You now can (and probably should, as it's simpler)
+            write <tt>_.chain(list)</tt>
+            instead of <tt>_(list).chain()</tt>.
+          </li>
+          <li>
+            Fix for escaped characters in Underscore templates, and for supporting
+            customizations of <tt>_.templateSettings</tt> that only define one or
+            two of the required regexes.
+          </li>
+          <li>
+            Fix for passing an array as the first argument to an <tt>_.wrap</tt>'d function.
+          </li>
+          <li>
+            Improved compatibility with ClojureScript, which adds a <tt>call</tt>
+            function to <tt>String.prototype</tt>.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.2.3</b> &mdash; <small><i>Dec. 7, 2011</i></small><br />
+        <ul>
+          <li>
+            Dynamic scope is now preserved for compiled <tt>_.template</tt> functions,
+            so you can use the value of <tt>this</tt> if you like.
+          </li>
+          <li>
+            Sparse array support of <tt>_.indexOf</tt>, <tt>_.lastIndexOf</tt>.
+          </li>
+          <li>
+            Both <tt>_.reduce</tt> and <tt>_.reduceRight</tt> can now be passed an
+            explicitly <tt>undefined</tt> value. (There's no reason why you'd
+            want to do this.)
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.2.2</b> &mdash; <small><i>Nov. 14, 2011</i></small><br />
+        <ul>
+          <li>
+            Continued tweaks to <tt>_.isEqual</tt> semantics. Now JS primitives are
+            considered equivalent to their wrapped versions, and arrays are compared
+            by their numeric properties only <small>(#351)</small>.
+          </li>
+          <li>
+            <tt>_.escape</tt> no longer tries to be smart about not double-escaping
+            already-escaped HTML entities. Now it just escapes regardless <small>(#350)</small>.
+          </li>
+          <li>
+            In <tt>_.template</tt>, you may now leave semicolons out of evaluated
+            statements if you wish: <tt>&lt;% }) %&gt;</tt> <small>(#369)</small>.
+          </li>
+          <li>
+            <tt>_.after(callback, 0)</tt> will now trigger the callback immediately,
+            making "after" easier to use with asynchronous APIs <small>(#366)</small>.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.2.1</b> &mdash; <small><i>Oct. 24, 2011</i></small><br />
+        <ul>
+          <li>
+            Several important bug fixes for <tt>_.isEqual</tt>, which should now
+            do better on mutated Arrays, and on non-Array objects with
+            <tt>length</tt> properties. <small>(#329)</small>
+          </li>
+          <li>
+            <b>jrburke</b> contributed Underscore exporting for AMD module loaders,
+            and <b>tonylukasavage</b> for Appcelerator Titanium.
+            <small>(#335, #338)</small>
+          </li>
+          <li>
+            You can now <tt>_.groupBy(list, 'property')</tt> as a shortcut for
+            grouping values by a particular common property.
+          </li>
+          <li>
+            <tt>_.throttle</tt>'d functions now fire immediately upon invocation,
+            and are rate-limited thereafter <small>(#170, #266)</small>.
+          </li>
+          <li>
+            Most of the <tt>_.is[Type]</tt> checks no longer ducktype.
+          </li>
+          <li>
+            The <tt>_.bind</tt> function now also works on constructors, a-la
+            ES5 ... but you would never want to use <tt>_.bind</tt> on a
+            constructor function.
+          </li>
+          <li>
+            <tt>_.clone</tt> no longer wraps non-object types in Objects.
+          </li>
+          <li>
+            <tt>_.find</tt> and <tt>_.filter</tt> are now the preferred names for
+            <tt>_.detect</tt> and <tt>_.select</tt>.
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.2.0</b> &mdash; <small><i>Oct. 5, 2011</i></small><br />
+        <ul>
+          <li>
+            The <tt>_.isEqual</tt> function now
+            supports true deep equality comparisons, with checks for cyclic structures,
+            thanks to Kit Cambridge.
+          </li>
+          <li>
+            Underscore templates now support HTML escaping interpolations, using
+            <tt>&lt;%- ... %&gt;</tt> syntax.
+          </li>
+          <li>
+            Ryan Tenney contributed <tt>_.shuffle</tt>, which uses a modified
+            Fisher-Yates to give you a shuffled copy of an array.
+          </li>
+          <li>
+            <tt>_.uniq</tt> can now be passed an optional iterator, to determine by
+            what criteria an object should be considered unique.
+          </li>
+          <li>
+            <tt>_.last</tt> now takes an optional argument which will return the last
+            N elements of the list.
+          </li>
+          <li>
+            A new <tt>_.initial</tt> function was added, as a mirror of <tt>_.rest</tt>,
+            which returns all the initial values of a list (except the last N).
+          </li>
+        </ul>
+      </p>
+
+      <p>
+        <b class="header">1.1.7</b> &mdash; <small><i>July 13, 2011</i></small><br />
+        Added <tt>_.groupBy</tt>, which aggregates a collection into groups of like items.
+        Added <tt>_.union</tt> and <tt>_.difference</tt>, to complement the
+        (re-named) <tt>_.intersection</tt>.
+        Various improvements for support of sparse arrays.
+        <tt>_.toArray</tt> now returns a clone, if directly passed an array.
+        <tt>_.functions</tt> now also returns the names of functions that are present
+        in the prototype chain.
+      </p>
+
+      <p>
+        <b class="header">1.1.6</b> &mdash; <small><i>April 18, 2011</i></small><br />
+        Added <tt>_.after</tt>, which will return a function that only runs after
+        first being called a specified number of times.
+        <tt>_.invoke</tt> can now take a direct function reference.
+        <tt>_.every</tt> now requires an iterator function to be passed, which
+        mirrors the ECMA5 API.
+        <tt>_.extend</tt> no longer copies keys when the value is undefined.
+        <tt>_.bind</tt> now errors when trying to bind an undefined value.
+      </p>
+
+      <p>
+        <b class="header">1.1.5</b> &mdash; <small><i>Mar 20, 2011</i></small><br />
+        Added an <tt>_.defaults</tt> function, for use merging together JS objects
+        representing default options.
+        Added an <tt>_.once</tt> function, for manufacturing functions that should
+        only ever execute a single time.
+        <tt>_.bind</tt> now delegates to the native ECMAScript 5 version,
+        where available.
+        <tt>_.keys</tt> now throws an error when used on non-Object values, as in
+        ECMAScript 5.
+        Fixed a bug with <tt>_.keys</tt> when used over sparse arrays.
+      </p>
+
+      <p>
+        <b class="header">1.1.4</b> &mdash; <small><i>Jan 9, 2011</i></small><br />
+        Improved compliance with ES5's Array methods when passing <tt>null</tt>
+        as a value. <tt>_.wrap</tt> now correctly sets <tt>this</tt> for the
+        wrapped function. <tt>_.indexOf</tt> now takes an optional flag for
+        finding the insertion index in an array that is guaranteed to already
+        be sorted. Avoiding the use of <tt>.callee</tt>, to allow <tt>_.isArray</tt>
+        to work properly in ES5's strict mode.
+      </p>
+
+      <p>
+        <b class="header">1.1.3</b> &mdash; <small><i>Dec 1, 2010</i></small><br />
+        In CommonJS, Underscore may now be required with just: <br />
+        <tt>var _ = require("underscore")</tt>.
+        Added <tt>_.throttle</tt> and <tt>_.debounce</tt> functions.
+        Removed <tt>_.breakLoop</tt>, in favor of an ECMA5-style un-<i>break</i>-able
+        each implementation &mdash; this removes the try/catch, and you'll now have
+        better stack traces for exceptions that are thrown within an Underscore iterator.
+        Improved the <b>isType</b> family of functions for better interoperability
+        with Internet Explorer host objects.
+        <tt>_.template</tt> now correctly escapes backslashes in templates.
+        Improved <tt>_.reduce</tt> compatibility with the ECMA5 version:
+        if you don't pass an initial value, the first item in the collection is used.
+        <tt>_.each</tt> no longer returns the iterated collection, for improved
+        consistency with ES5's <tt>forEach</tt>.
+      </p>
+
+      <p>
+        <b class="header">1.1.2</b><br />
+        Fixed <tt>_.contains</tt>, which was mistakenly pointing at
+        <tt>_.intersect</tt> instead of <tt>_.include</tt>, like it should
+        have been. Added <tt>_.unique</tt> as an alias for <tt>_.uniq</tt>.
+      </p>
+
+      <p>
+        <b class="header">1.1.1</b><br />
+        Improved the speed of <tt>_.template</tt>, and its handling of multiline
+        interpolations. Ryan Tenney contributed optimizations to many Underscore
+        functions. An annotated version of the source code is now available.
+      </p>
+
+      <p>
+        <b class="header">1.1.0</b><br />
+        The method signature of <tt>_.reduce</tt> has been changed to match
+        the ECMAScript 5 signature, instead of the Ruby/Prototype.js version.
+        This is a backwards-incompatible change. <tt>_.template</tt> may now be
+        called with no arguments, and preserves whitespace. <tt>_.contains</tt>
+        is a new alias for <tt>_.include</tt>.
+      </p>
+
+      <p>
+        <b class="header">1.0.4</b><br />
+        <a href="http://themoell.com/">Andri MÃ¶ll</a> contributed the <tt>_.memoize</tt>
+        function, which can be used to speed up expensive repeated computations
+        by caching the results.
+      </p>
+
+      <p>
+        <b class="header">1.0.3</b><br />
+        Patch that makes <tt>_.isEqual</tt> return <tt>false</tt> if any property
+        of the compared object has a <tt>NaN</tt> value. Technically the correct
+        thing to do, but of questionable semantics. Watch out for NaN comparisons.
+      </p>
+
+      <p>
+        <b class="header">1.0.2</b><br />
+        Fixes <tt>_.isArguments</tt> in recent versions of Opera, which have
+        arguments objects as real Arrays.
+      </p>
+
+      <p>
+        <b class="header">1.0.1</b><br />
+        Bugfix for <tt>_.isEqual</tt>, when comparing two objects with the same
+        number of undefined keys, but with different names.
+      </p>
+
+      <p>
+        <b class="header">1.0.0</b><br />
+        Things have been stable for many months now, so Underscore is now
+        considered to be out of beta, at <b>1.0</b>. Improvements since <b>0.6</b>
+        include <tt>_.isBoolean</tt>, and the ability to have <tt>_.extend</tt>
+        take multiple source objects.
+      </p>
+
+      <p>
+        <b class="header">0.6.0</b><br />
+        Major release. Incorporates a number of
+        <a href="http://github.com/ratbeard">Mile Frawley's</a> refactors for
+        safer duck-typing on collection functions, and cleaner internals. A new
+        <tt>_.mixin</tt> method that allows you to extend Underscore with utility
+        functions of your own. Added <tt>_.times</tt>, which works the same as in
+        Ruby or Prototype.js. Native support for ECMAScript 5's <tt>Array.isArray</tt>,
+        and <tt>Object.keys</tt>.
+      </p>
+
+      <p>
+        <b class="header">0.5.8</b><br />
+        Fixed Underscore's collection functions to work on
+        <a href="https://developer.mozilla.org/En/DOM/NodeList">NodeLists</a> and
+        <a href="https://developer.mozilla.org/En/DOM/HTMLCollection">HTMLCollections</a>
+        once more, thanks to
+        <a href="http://github.com/jmtulloss">Justin Tulloss</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.7</b><br />
+        A safer implementation of <tt>_.isArguments</tt>, and a
+        faster <tt>_.isNumber</tt>,<br />thanks to
+        <a href="http://jedschmidt.com/">Jed Schmidt</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.6</b><br />
+        Customizable delimiters for <tt>_.template</tt>, contributed by
+        <a href="http://github.com/iamnoah">Noah Sloan</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.5</b><br />
+        Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object.
+      </p>
+
+      <p>
+        <b class="header">0.5.4</b><br />
+        Fix for multiple single quotes within a template string for
+        <tt>_.template</tt>. See:
+        <a href="http://www.west-wind.com/Weblog/posts/509108.aspx">Rick Strahl's blog post</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.2</b><br />
+        New implementations of <tt>isArray</tt>, <tt>isDate</tt>, <tt>isFunction</tt>,
+        <tt>isNumber</tt>, <tt>isRegExp</tt>, and <tt>isString</tt>, thanks to
+        a suggestion from
+        <a href="http://www.broofa.com/">Robert Kieffer</a>.
+        Instead of doing <tt>Object#toString</tt>
+        comparisons, they now check for expected properties, which is less safe,
+        but more than an order of magnitude faster. Most other Underscore
+        functions saw minor speed improvements as a result.
+        <a href="http://dolzhenko.org/">Evgeniy Dolzhenko</a>
+        contributed <tt>_.tap</tt>,
+        <a href="http://ruby-doc.org/core-1.9/classes/Object.html#M000191">similar to Ruby 1.9's</a>,
+        which is handy for injecting side effects (like logging) into chained calls.
+      </p>
+
+      <p>
+        <b class="header">0.5.1</b><br />
+        Added an <tt>_.isArguments</tt> function. Lots of little safety checks
+        and optimizations contributed by
+        <a href="http://github.com/iamnoah/">Noah Sloan</a> and
+        <a href="http://themoell.com/">Andri MÃ¶ll</a>.
+      </p>
+
+      <p>
+        <b class="header">0.5.0</b><br />
+        <b>[API Changes]</b> <tt>_.bindAll</tt> now takes the context object as
+        its first parameter. If no method names are passed, all of the context
+        object's methods are bound to it, enabling chaining and easier binding.
+        <tt>_.functions</tt> now takes a single argument and returns the names
+        of its Function properties. Calling <tt>_.functions(_)</tt> will get you
+        the previous behavior.
+        Added <tt>_.isRegExp</tt> so that <tt>isEqual</tt> can now test for RegExp equality.
+        All of the "is" functions have been shrunk down into a single definition.
+        <a href="http://github.com/grayrest/">Karl Guertin</a> contributed patches.
+      </p>
+
+      <p>
+        <b class="header">0.4.7</b><br />
+        Added <tt>isDate</tt>, <tt>isNaN</tt>, and <tt>isNull</tt>, for completeness.
+        Optimizations for <tt>isEqual</tt> when checking equality between Arrays
+        or Dates. <tt>_.keys</tt> is now <small><i><b>25%&ndash;2X</b></i></small> faster (depending on your
+        browser) which speeds up the functions that rely on it, such as <tt>_.each</tt>.
+      </p>
+
+      <p>
+        <b class="header">0.4.6</b><br />
+        Added the <tt>range</tt> function, a port of the
+        <a href="http://docs.python.org/library/functions.html#range">Python
+        function of the same name</a>, for generating flexibly-numbered lists
+        of integers. Original patch contributed by
+        <a href="http://github.com/kylichuku">Kirill Ishanov</a>.
+      </p>
+
+      <p>
+        <b class="header">0.4.5</b><br />
+        Added <tt>rest</tt> for Arrays and arguments objects, and aliased
+        <tt>first</tt> as <tt>head</tt>, and <tt>rest</tt> as <tt>tail</tt>,
+        thanks to <a href="http://github.com/lukesutton/">Luke Sutton</a>'s patches.
+        Added tests ensuring that all Underscore Array functions also work on
+        <i>arguments</i> objects.
+      </p>
+
+      <p>
+        <b class="header">0.4.4</b><br />
+        Added <tt>isString</tt>, and <tt>isNumber</tt>, for consistency. Fixed
+        <tt>_.isEqual(NaN, NaN)</tt> to return <i>true</i> (which is debatable).
+      </p>
+
+      <p>
+        <b class="header">0.4.3</b><br />
+        Started using the native <tt>StopIteration</tt> object in browsers that support it.
+        Fixed Underscore setup for CommonJS environments.
+      </p>
+
+      <p>
+        <b class="header">0.4.2</b><br />
+        Renamed the unwrapping function to <tt>value</tt>, for clarity.
+      </p>
+
+      <p>
+        <b class="header">0.4.1</b><br />
+        Chained Underscore objects now support the Array prototype methods, so
+        that you can perform the full range of operations on a wrapped array
+        without having to break your chain. Added a <tt>breakLoop</tt> method
+        to <b>break</b> in the middle of any Underscore iteration. Added an
+        <tt>isEmpty</tt> function that works on arrays and objects.
+      </p>
+
+      <p>
+        <b class="header">0.4.0</b><br />
+        All Underscore functions can now be called in an object-oriented style,
+        like so: <tt>_([1, 2, 3]).map(...);</tt>. Original patch provided by
+        <a href="http://macournoyer.com/">Marc-AndrÃ© Cournoyer</a>.
+        Wrapped objects can be chained through multiple
+        method invocations. A <a href="#object-functions"><tt>functions</tt></a> method
+        was added, providing a sorted list of all the functions in Underscore.
+      </p>
+
+      <p>
+        <b class="header">0.3.3</b><br />
+        Added the JavaScript 1.8 function <tt>reduceRight</tt>. Aliased it
+        as <tt>foldr</tt>, and aliased <tt>reduce</tt> as <tt>foldl</tt>.
+      </p>
+
+      <p>
+        <b class="header">0.3.2</b><br />
+        Now runs on stock <a href="http://www.mozilla.org/rhino/">Rhino</a>
+        interpreters with: <tt>load("underscore.js")</tt>.
+        Added <a href="#identity"><tt>identity</tt></a> as a utility function.
+      </p>
+
+      <p>
+        <b class="header">0.3.1</b><br />
+        All iterators are now passed in the original collection as their third
+        argument, the same as JavaScript 1.6's <b>forEach</b>. Iterating over
+        objects is now called with <tt>(value, key, collection)</tt>, for details
+        see <a href="#each"><tt>_.each</tt></a>.
+      </p>
+
+      <p>
+        <b class="header">0.3.0</b><br />
+        Added <a href="http://github.com/dmitryBaranovskiy">Dmitry Baranovskiy</a>'s
+        comprehensive optimizations, merged in
+        <a href="http://github.com/kriskowal/">Kris Kowal</a>'s patches to make Underscore
+        <a href="http://wiki.commonjs.org/wiki/CommonJS">CommonJS</a> and
+        <a href="http://narwhaljs.org/">Narwhal</a> compliant.
+      </p>
+
+      <p>
+        <b class="header">0.2.0</b><br />
+        Added <tt>compose</tt> and <tt>lastIndexOf</tt>, renamed <tt>inject</tt> to
+        <tt>reduce</tt>, added aliases for <tt>inject</tt>, <tt>filter</tt>,
+        <tt>every</tt>, <tt>some</tt>, and <tt>forEach</tt>.
+      </p>
+
+      <p>
+        <b class="header">0.1.1</b><br />
+        Added <tt>noConflict</tt>, so that the "Underscore" object can be assigned to
+        other variables.
+      </p>
+
+      <p>
+        <b class="header">0.1.0</b><br />
+        Initial release of Underscore.js.
+      </p>
+
+      <p>
+        <a href="http://documentcloud.org/" title="A DocumentCloud Project" style="background:none;">
+          <img src="http://jashkenas.s3.amazonaws.com/images/a_documentcloud_project.png" alt="A DocumentCloud Project" />
+        </a>
+      </p>
+
+    </div>
+
+  </div>
+
+  <!-- Include Underscore, so you can play with it in the console. -->
+  <script type="text/javascript" src="underscore.js"></script>
+
+</body>
+</html>
Index: Dev/trunk/src/node_modules/underscore/index.js
===================================================================
--- Dev/trunk/src/node_modules/underscore/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/index.js	(revision 484)
@@ -0,0 +1,1 @@
+module.exports = require('./underscore');
Index: Dev/trunk/src/node_modules/underscore/package.json
===================================================================
--- Dev/trunk/src/node_modules/underscore/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/package.json	(revision 484)
@@ -0,0 +1,35 @@
+{
+  "name": "underscore",
+  "description": "JavaScript's functional programming helper library.",
+  "homepage": "http://underscorejs.org",
+  "keywords": [
+    "util",
+    "functional",
+    "server",
+    "client",
+    "browser"
+  ],
+  "author": {
+    "name": "Jeremy Ashkenas",
+    "email": "jeremy@documentcloud.org"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/documentcloud/underscore.git"
+  },
+  "main": "underscore.js",
+  "version": "1.4.4",
+  "devDependencies": {
+    "phantomjs": "0.2.2"
+  },
+  "scripts": {
+    "test": "phantomjs test/vendor/runner.js test/index.html?noglobals=true"
+  },
+  "readme": "                       __\n                      /\\ \\                                                         __\n     __  __    ___    \\_\\ \\     __   _ __   ____    ___    ___   _ __    __       /\\_\\    ____\n    /\\ \\/\\ \\ /' _ `\\  /'_  \\  /'__`\\/\\  __\\/ ,__\\  / ___\\ / __`\\/\\  __\\/'__`\\     \\/\\ \\  /',__\\\n    \\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\/\\  __/\\ \\ \\//\\__, `\\/\\ \\__//\\ \\ \\ \\ \\ \\//\\  __/  __  \\ \\ \\/\\__, `\\\n     \\ \\____/\\ \\_\\ \\_\\ \\___,_\\ \\____\\\\ \\_\\\\/\\____/\\ \\____\\ \\____/\\ \\_\\\\ \\____\\/\\_\\ _\\ \\ \\/\\____/\n      \\/___/  \\/_/\\/_/\\/__,_ /\\/____/ \\/_/ \\/___/  \\/____/\\/___/  \\/_/ \\/____/\\/_//\\ \\_\\ \\/___/\n                                                                                  \\ \\____/\n                                                                                   \\/___/\n\nUnderscore.js is a utility-belt library for JavaScript that provides\nsupport for the usual functional suspects (each, map, reduce, filter...)\nwithout extending any core JavaScript objects.\n\nFor Docs, License, Tests, and pre-packed downloads, see:\nhttp://underscorejs.org\n\nMany thanks to our contributors:\nhttps://github.com/documentcloud/underscore/contributors\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/documentcloud/underscore/issues"
+  },
+  "_id": "underscore@1.4.4",
+  "_from": "underscore@"
+}
Index: Dev/trunk/src/node_modules/underscore/underscore-min.js
===================================================================
--- Dev/trunk/src/node_modules/underscore/underscore-min.js	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/underscore-min.js	(revision 484)
@@ -0,0 +1,1 @@
+(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index<t.index?-1:1}),"value")};var F=function(n,t,r,e){var u={},i=k(t||w.identity);return A(n,function(t,a){var o=i.call(r,t,a,n);e(u,o,t)}),u};w.groupBy=function(n,t,r){return F(n,t,r,function(n,t,r){(w.has(n,t)?n[t]:n[t]=[]).push(r)})},w.countBy=function(n,t,r){return F(n,t,r,function(n,t){w.has(n,t)||(n[t]=0),n[t]++})},w.sortedIndex=function(n,t,r,e){r=null==r?w.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n","	":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);
Index: Dev/trunk/src/node_modules/underscore/underscore.js
===================================================================
--- Dev/trunk/src/node_modules/underscore/underscore.js	(revision 484)
+++ Dev/trunk/src/node_modules/underscore/underscore.js	(revision 484)
@@ -0,0 +1,1226 @@
+//     Underscore.js 1.4.4
+//     http://underscorejs.org
+//     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+//     Underscore may be freely distributed under the MIT license.
+
+(function() {
+
+  // Baseline setup
+  // --------------
+
+  // Establish the root object, `window` in the browser, or `global` on the server.
+  var root = this;
+
+  // Save the previous value of the `_` variable.
+  var previousUnderscore = root._;
+
+  // Establish the object that gets returned to break out of a loop iteration.
+  var breaker = {};
+
+  // Save bytes in the minified (but not gzipped) version:
+  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+  // Create quick reference variables for speed access to core prototypes.
+  var push             = ArrayProto.push,
+      slice            = ArrayProto.slice,
+      concat           = ArrayProto.concat,
+      toString         = ObjProto.toString,
+      hasOwnProperty   = ObjProto.hasOwnProperty;
+
+  // All **ECMAScript 5** native function implementations that we hope to use
+  // are declared here.
+  var
+    nativeForEach      = ArrayProto.forEach,
+    nativeMap          = ArrayProto.map,
+    nativeReduce       = ArrayProto.reduce,
+    nativeReduceRight  = ArrayProto.reduceRight,
+    nativeFilter       = ArrayProto.filter,
+    nativeEvery        = ArrayProto.every,
+    nativeSome         = ArrayProto.some,
+    nativeIndexOf      = ArrayProto.indexOf,
+    nativeLastIndexOf  = ArrayProto.lastIndexOf,
+    nativeIsArray      = Array.isArray,
+    nativeKeys         = Object.keys,
+    nativeBind         = FuncProto.bind;
+
+  // Create a safe reference to the Underscore object for use below.
+  var _ = function(obj) {
+    if (obj instanceof _) return obj;
+    if (!(this instanceof _)) return new _(obj);
+    this._wrapped = obj;
+  };
+
+  // Export the Underscore object for **Node.js**, with
+  // backwards-compatibility for the old `require()` API. If we're in
+  // the browser, add `_` as a global object via a string identifier,
+  // for Closure Compiler "advanced" mode.
+  if (typeof exports !== 'undefined') {
+    if (typeof module !== 'undefined' && module.exports) {
+      exports = module.exports = _;
+    }
+    exports._ = _;
+  } else {
+    root._ = _;
+  }
+
+  // Current version.
+  _.VERSION = '1.4.4';
+
+  // Collection Functions
+  // --------------------
+
+  // The cornerstone, an `each` implementation, aka `forEach`.
+  // Handles objects with the built-in `forEach`, arrays, and raw objects.
+  // Delegates to **ECMAScript 5**'s native `forEach` if available.
+  var each = _.each = _.forEach = function(obj, iterator, context) {
+    if (obj == null) return;
+    if (nativeForEach && obj.forEach === nativeForEach) {
+      obj.forEach(iterator, context);
+    } else if (obj.length === +obj.length) {
+      for (var i = 0, l = obj.length; i < l; i++) {
+        if (iterator.call(context, obj[i], i, obj) === breaker) return;
+      }
+    } else {
+      for (var key in obj) {
+        if (_.has(obj, key)) {
+          if (iterator.call(context, obj[key], key, obj) === breaker) return;
+        }
+      }
+    }
+  };
+
+  // Return the results of applying the iterator to each element.
+  // Delegates to **ECMAScript 5**'s native `map` if available.
+  _.map = _.collect = function(obj, iterator, context) {
+    var results = [];
+    if (obj == null) return results;
+    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+    each(obj, function(value, index, list) {
+      results[results.length] = iterator.call(context, value, index, list);
+    });
+    return results;
+  };
+
+  var reduceError = 'Reduce of empty array with no initial value';
+
+  // **Reduce** builds up a single result from a list of values, aka `inject`,
+  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
+  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
+    var initial = arguments.length > 2;
+    if (obj == null) obj = [];
+    if (nativeReduce && obj.reduce === nativeReduce) {
+      if (context) iterator = _.bind(iterator, context);
+      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+    }
+    each(obj, function(value, index, list) {
+      if (!initial) {
+        memo = value;
+        initial = true;
+      } else {
+        memo = iterator.call(context, memo, value, index, list);
+      }
+    });
+    if (!initial) throw new TypeError(reduceError);
+    return memo;
+  };
+
+  // The right-associative version of reduce, also known as `foldr`.
+  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
+  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+    var initial = arguments.length > 2;
+    if (obj == null) obj = [];
+    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+      if (context) iterator = _.bind(iterator, context);
+      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+    }
+    var length = obj.length;
+    if (length !== +length) {
+      var keys = _.keys(obj);
+      length = keys.length;
+    }
+    each(obj, function(value, index, list) {
+      index = keys ? keys[--length] : --length;
+      if (!initial) {
+        memo = obj[index];
+        initial = true;
+      } else {
+        memo = iterator.call(context, memo, obj[index], index, list);
+      }
+    });
+    if (!initial) throw new TypeError(reduceError);
+    return memo;
+  };
+
+  // Return the first value which passes a truth test. Aliased as `detect`.
+  _.find = _.detect = function(obj, iterator, context) {
+    var result;
+    any(obj, function(value, index, list) {
+      if (iterator.call(context, value, index, list)) {
+        result = value;
+        return true;
+      }
+    });
+    return result;
+  };
+
+  // Return all the elements that pass a truth test.
+  // Delegates to **ECMAScript 5**'s native `filter` if available.
+  // Aliased as `select`.
+  _.filter = _.select = function(obj, iterator, context) {
+    var results = [];
+    if (obj == null) return results;
+    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+    each(obj, function(value, index, list) {
+      if (iterator.call(context, value, index, list)) results[results.length] = value;
+    });
+    return results;
+  };
+
+  // Return all the elements for which a truth test fails.
+  _.reject = function(obj, iterator, context) {
+    return _.filter(obj, function(value, index, list) {
+      return !iterator.call(context, value, index, list);
+    }, context);
+  };
+
+  // Determine whether all of the elements match a truth test.
+  // Delegates to **ECMAScript 5**'s native `every` if available.
+  // Aliased as `all`.
+  _.every = _.all = function(obj, iterator, context) {
+    iterator || (iterator = _.identity);
+    var result = true;
+    if (obj == null) return result;
+    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+    each(obj, function(value, index, list) {
+      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+    });
+    return !!result;
+  };
+
+  // Determine if at least one element in the object matches a truth test.
+  // Delegates to **ECMAScript 5**'s native `some` if available.
+  // Aliased as `any`.
+  var any = _.some = _.any = function(obj, iterator, context) {
+    iterator || (iterator = _.identity);
+    var result = false;
+    if (obj == null) return result;
+    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+    each(obj, function(value, index, list) {
+      if (result || (result = iterator.call(context, value, index, list))) return breaker;
+    });
+    return !!result;
+  };
+
+  // Determine if the array or object contains a given value (using `===`).
+  // Aliased as `include`.
+  _.contains = _.include = function(obj, target) {
+    if (obj == null) return false;
+    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+    return any(obj, function(value) {
+      return value === target;
+    });
+  };
+
+  // Invoke a method (with arguments) on every item in a collection.
+  _.invoke = function(obj, method) {
+    var args = slice.call(arguments, 2);
+    var isFunc = _.isFunction(method);
+    return _.map(obj, function(value) {
+      return (isFunc ? method : value[method]).apply(value, args);
+    });
+  };
+
+  // Convenience version of a common use case of `map`: fetching a property.
+  _.pluck = function(obj, key) {
+    return _.map(obj, function(value){ return value[key]; });
+  };
+
+  // Convenience version of a common use case of `filter`: selecting only objects
+  // containing specific `key:value` pairs.
+  _.where = function(obj, attrs, first) {
+    if (_.isEmpty(attrs)) return first ? null : [];
+    return _[first ? 'find' : 'filter'](obj, function(value) {
+      for (var key in attrs) {
+        if (attrs[key] !== value[key]) return false;
+      }
+      return true;
+    });
+  };
+
+  // Convenience version of a common use case of `find`: getting the first object
+  // containing specific `key:value` pairs.
+  _.findWhere = function(obj, attrs) {
+    return _.where(obj, attrs, true);
+  };
+
+  // Return the maximum element or (element-based computation).
+  // Can't optimize arrays of integers longer than 65,535 elements.
+  // See: https://bugs.webkit.org/show_bug.cgi?id=80797
+  _.max = function(obj, iterator, context) {
+    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
+      return Math.max.apply(Math, obj);
+    }
+    if (!iterator && _.isEmpty(obj)) return -Infinity;
+    var result = {computed : -Infinity, value: -Infinity};
+    each(obj, function(value, index, list) {
+      var computed = iterator ? iterator.call(context, value, index, list) : value;
+      computed >= result.computed && (result = {value : value, computed : computed});
+    });
+    return result.value;
+  };
+
+  // Return the minimum element (or element-based computation).
+  _.min = function(obj, iterator, context) {
+    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
+      return Math.min.apply(Math, obj);
+    }
+    if (!iterator && _.isEmpty(obj)) return Infinity;
+    var result = {computed : Infinity, value: Infinity};
+    each(obj, function(value, index, list) {
+      var computed = iterator ? iterator.call(context, value, index, list) : value;
+      computed < result.computed && (result = {value : value, computed : computed});
+    });
+    return result.value;
+  };
+
+  // Shuffle an array.
+  _.shuffle = function(obj) {
+    var rand;
+    var index = 0;
+    var shuffled = [];
+    each(obj, function(value) {
+      rand = _.random(index++);
+      shuffled[index - 1] = shuffled[rand];
+      shuffled[rand] = value;
+    });
+    return shuffled;
+  };
+
+  // An internal function to generate lookup iterators.
+  var lookupIterator = function(value) {
+    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
+  };
+
+  // Sort the object's values by a criterion produced by an iterator.
+  _.sortBy = function(obj, value, context) {
+    var iterator = lookupIterator(value);
+    return _.pluck(_.map(obj, function(value, index, list) {
+      return {
+        value : value,
+        index : index,
+        criteria : iterator.call(context, value, index, list)
+      };
+    }).sort(function(left, right) {
+      var a = left.criteria;
+      var b = right.criteria;
+      if (a !== b) {
+        if (a > b || a === void 0) return 1;
+        if (a < b || b === void 0) return -1;
+      }
+      return left.index < right.index ? -1 : 1;
+    }), 'value');
+  };
+
+  // An internal function used for aggregate "group by" operations.
+  var group = function(obj, value, context, behavior) {
+    var result = {};
+    var iterator = lookupIterator(value || _.identity);
+    each(obj, function(value, index) {
+      var key = iterator.call(context, value, index, obj);
+      behavior(result, key, value);
+    });
+    return result;
+  };
+
+  // Groups the object's values by a criterion. Pass either a string attribute
+  // to group by, or a function that returns the criterion.
+  _.groupBy = function(obj, value, context) {
+    return group(obj, value, context, function(result, key, value) {
+      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
+    });
+  };
+
+  // Counts instances of an object that group by a certain criterion. Pass
+  // either a string attribute to count by, or a function that returns the
+  // criterion.
+  _.countBy = function(obj, value, context) {
+    return group(obj, value, context, function(result, key) {
+      if (!_.has(result, key)) result[key] = 0;
+      result[key]++;
+    });
+  };
+
+  // Use a comparator function to figure out the smallest index at which
+  // an object should be inserted so as to maintain order. Uses binary search.
+  _.sortedIndex = function(array, obj, iterator, context) {
+    iterator = iterator == null ? _.identity : lookupIterator(iterator);
+    var value = iterator.call(context, obj);
+    var low = 0, high = array.length;
+    while (low < high) {
+      var mid = (low + high) >>> 1;
+      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
+    }
+    return low;
+  };
+
+  // Safely convert anything iterable into a real, live array.
+  _.toArray = function(obj) {
+    if (!obj) return [];
+    if (_.isArray(obj)) return slice.call(obj);
+    if (obj.length === +obj.length) return _.map(obj, _.identity);
+    return _.values(obj);
+  };
+
+  // Return the number of elements in an object.
+  _.size = function(obj) {
+    if (obj == null) return 0;
+    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
+  };
+
+  // Array Functions
+  // ---------------
+
+  // Get the first element of an array. Passing **n** will return the first N
+  // values in the array. Aliased as `head` and `take`. The **guard** check
+  // allows it to work with `_.map`.
+  _.first = _.head = _.take = function(array, n, guard) {
+    if (array == null) return void 0;
+    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+  };
+
+  // Returns everything but the last entry of the array. Especially useful on
+  // the arguments object. Passing **n** will return all the values in
+  // the array, excluding the last N. The **guard** check allows it to work with
+  // `_.map`.
+  _.initial = function(array, n, guard) {
+    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+  };
+
+  // Get the last element of an array. Passing **n** will return the last N
+  // values in the array. The **guard** check allows it to work with `_.map`.
+  _.last = function(array, n, guard) {
+    if (array == null) return void 0;
+    if ((n != null) && !guard) {
+      return slice.call(array, Math.max(array.length - n, 0));
+    } else {
+      return array[array.length - 1];
+    }
+  };
+
+  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+  // Especially useful on the arguments object. Passing an **n** will return
+  // the rest N values in the array. The **guard**
+  // check allows it to work with `_.map`.
+  _.rest = _.tail = _.drop = function(array, n, guard) {
+    return slice.call(array, (n == null) || guard ? 1 : n);
+  };
+
+  // Trim out all falsy values from an array.
+  _.compact = function(array) {
+    return _.filter(array, _.identity);
+  };
+
+  // Internal implementation of a recursive `flatten` function.
+  var flatten = function(input, shallow, output) {
+    each(input, function(value) {
+      if (_.isArray(value)) {
+        shallow ? push.apply(output, value) : flatten(value, shallow, output);
+      } else {
+        output.push(value);
+      }
+    });
+    return output;
+  };
+
+  // Return a completely flattened version of an array.
+  _.flatten = function(array, shallow) {
+    return flatten(array, shallow, []);
+  };
+
+  // Return a version of the array that does not contain the specified value(s).
+  _.without = function(array) {
+    return _.difference(array, slice.call(arguments, 1));
+  };
+
+  // Produce a duplicate-free version of the array. If the array has already
+  // been sorted, you have the option of using a faster algorithm.
+  // Aliased as `unique`.
+  _.uniq = _.unique = function(array, isSorted, iterator, context) {
+    if (_.isFunction(isSorted)) {
+      context = iterator;
+      iterator = isSorted;
+      isSorted = false;
+    }
+    var initial = iterator ? _.map(array, iterator, context) : array;
+    var results = [];
+    var seen = [];
+    each(initial, function(value, index) {
+      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
+        seen.push(value);
+        results.push(array[index]);
+      }
+    });
+    return results;
+  };
+
+  // Produce an array that contains the union: each distinct element from all of
+  // the passed-in arrays.
+  _.union = function() {
+    return _.uniq(concat.apply(ArrayProto, arguments));
+  };
+
+  // Produce an array that contains every item shared between all the
+  // passed-in arrays.
+  _.intersection = function(array) {
+    var rest = slice.call(arguments, 1);
+    return _.filter(_.uniq(array), function(item) {
+      return _.every(rest, function(other) {
+        return _.indexOf(other, item) >= 0;
+      });
+    });
+  };
+
+  // Take the difference between one array and a number of other arrays.
+  // Only the elements present in just the first array will remain.
+  _.difference = function(array) {
+    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
+    return _.filter(array, function(value){ return !_.contains(rest, value); });
+  };
+
+  // Zip together multiple lists into a single array -- elements that share
+  // an index go together.
+  _.zip = function() {
+    var args = slice.call(arguments);
+    var length = _.max(_.pluck(args, 'length'));
+    var results = new Array(length);
+    for (var i = 0; i < length; i++) {
+      results[i] = _.pluck(args, "" + i);
+    }
+    return results;
+  };
+
+  // Converts lists into objects. Pass either a single array of `[key, value]`
+  // pairs, or two parallel arrays of the same length -- one of keys, and one of
+  // the corresponding values.
+  _.object = function(list, values) {
+    if (list == null) return {};
+    var result = {};
+    for (var i = 0, l = list.length; i < l; i++) {
+      if (values) {
+        result[list[i]] = values[i];
+      } else {
+        result[list[i][0]] = list[i][1];
+      }
+    }
+    return result;
+  };
+
+  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
+  // we need this function. Return the position of the first occurrence of an
+  // item in an array, or -1 if the item is not included in the array.
+  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+  // If the array is large and already in sort order, pass `true`
+  // for **isSorted** to use binary search.
+  _.indexOf = function(array, item, isSorted) {
+    if (array == null) return -1;
+    var i = 0, l = array.length;
+    if (isSorted) {
+      if (typeof isSorted == 'number') {
+        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
+      } else {
+        i = _.sortedIndex(array, item);
+        return array[i] === item ? i : -1;
+      }
+    }
+    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
+    for (; i < l; i++) if (array[i] === item) return i;
+    return -1;
+  };
+
+  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
+  _.lastIndexOf = function(array, item, from) {
+    if (array == null) return -1;
+    var hasIndex = from != null;
+    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
+      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
+    }
+    var i = (hasIndex ? from : array.length);
+    while (i--) if (array[i] === item) return i;
+    return -1;
+  };
+
+  // Generate an integer Array containing an arithmetic progression. A port of
+  // the native Python `range()` function. See
+  // [the Python documentation](http://docs.python.org/library/functions.html#range).
+  _.range = function(start, stop, step) {
+    if (arguments.length <= 1) {
+      stop = start || 0;
+      start = 0;
+    }
+    step = arguments[2] || 1;
+
+    var len = Math.max(Math.ceil((stop - start) / step), 0);
+    var idx = 0;
+    var range = new Array(len);
+
+    while(idx < len) {
+      range[idx++] = start;
+      start += step;
+    }
+
+    return range;
+  };
+
+  // Function (ahem) Functions
+  // ------------------
+
+  // Create a function bound to a given object (assigning `this`, and arguments,
+  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+  // available.
+  _.bind = function(func, context) {
+    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+    var args = slice.call(arguments, 2);
+    return function() {
+      return func.apply(context, args.concat(slice.call(arguments)));
+    };
+  };
+
+  // Partially apply a function by creating a version that has had some of its
+  // arguments pre-filled, without changing its dynamic `this` context.
+  _.partial = function(func) {
+    var args = slice.call(arguments, 1);
+    return function() {
+      return func.apply(this, args.concat(slice.call(arguments)));
+    };
+  };
+
+  // Bind all of an object's methods to that object. Useful for ensuring that
+  // all callbacks defined on an object belong to it.
+  _.bindAll = function(obj) {
+    var funcs = slice.call(arguments, 1);
+    if (funcs.length === 0) funcs = _.functions(obj);
+    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+    return obj;
+  };
+
+  // Memoize an expensive function by storing its results.
+  _.memoize = function(func, hasher) {
+    var memo = {};
+    hasher || (hasher = _.identity);
+    return function() {
+      var key = hasher.apply(this, arguments);
+      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+    };
+  };
+
+  // Delays a function for the given number of milliseconds, and then calls
+  // it with the arguments supplied.
+  _.delay = function(func, wait) {
+    var args = slice.call(arguments, 2);
+    return setTimeout(function(){ return func.apply(null, args); }, wait);
+  };
+
+  // Defers a function, scheduling it to run after the current call stack has
+  // cleared.
+  _.defer = function(func) {
+    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+  };
+
+  // Returns a function, that, when invoked, will only be triggered at most once
+  // during a given window of time.
+  _.throttle = function(func, wait) {
+    var context, args, timeout, result;
+    var previous = 0;
+    var later = function() {
+      previous = new Date;
+      timeout = null;
+      result = func.apply(context, args);
+    };
+    return function() {
+      var now = new Date;
+      var remaining = wait - (now - previous);
+      context = this;
+      args = arguments;
+      if (remaining <= 0) {
+        clearTimeout(timeout);
+        timeout = null;
+        previous = now;
+        result = func.apply(context, args);
+      } else if (!timeout) {
+        timeout = setTimeout(later, remaining);
+      }
+      return result;
+    };
+  };
+
+  // Returns a function, that, as long as it continues to be invoked, will not
+  // be triggered. The function will be called after it stops being called for
+  // N milliseconds. If `immediate` is passed, trigger the function on the
+  // leading edge, instead of the trailing.
+  _.debounce = function(func, wait, immediate) {
+    var timeout, result;
+    return function() {
+      var context = this, args = arguments;
+      var later = function() {
+        timeout = null;
+        if (!immediate) result = func.apply(context, args);
+      };
+      var callNow = immediate && !timeout;
+      clearTimeout(timeout);
+      timeout = setTimeout(later, wait);
+      if (callNow) result = func.apply(context, args);
+      return result;
+    };
+  };
+
+  // Returns a function that will be executed at most one time, no matter how
+  // often you call it. Useful for lazy initialization.
+  _.once = function(func) {
+    var ran = false, memo;
+    return function() {
+      if (ran) return memo;
+      ran = true;
+      memo = func.apply(this, arguments);
+      func = null;
+      return memo;
+    };
+  };
+
+  // Returns the first function passed as an argument to the second,
+  // allowing you to adjust arguments, run code before and after, and
+  // conditionally execute the original function.
+  _.wrap = function(func, wrapper) {
+    return function() {
+      var args = [func];
+      push.apply(args, arguments);
+      return wrapper.apply(this, args);
+    };
+  };
+
+  // Returns a function that is the composition of a list of functions, each
+  // consuming the return value of the function that follows.
+  _.compose = function() {
+    var funcs = arguments;
+    return function() {
+      var args = arguments;
+      for (var i = funcs.length - 1; i >= 0; i--) {
+        args = [funcs[i].apply(this, args)];
+      }
+      return args[0];
+    };
+  };
+
+  // Returns a function that will only be executed after being called N times.
+  _.after = function(times, func) {
+    if (times <= 0) return func();
+    return function() {
+      if (--times < 1) {
+        return func.apply(this, arguments);
+      }
+    };
+  };
+
+  // Object Functions
+  // ----------------
+
+  // Retrieve the names of an object's properties.
+  // Delegates to **ECMAScript 5**'s native `Object.keys`
+  _.keys = nativeKeys || function(obj) {
+    if (obj !== Object(obj)) throw new TypeError('Invalid object');
+    var keys = [];
+    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
+    return keys;
+  };
+
+  // Retrieve the values of an object's properties.
+  _.values = function(obj) {
+    var values = [];
+    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
+    return values;
+  };
+
+  // Convert an object into a list of `[key, value]` pairs.
+  _.pairs = function(obj) {
+    var pairs = [];
+    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
+    return pairs;
+  };
+
+  // Invert the keys and values of an object. The values must be serializable.
+  _.invert = function(obj) {
+    var result = {};
+    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
+    return result;
+  };
+
+  // Return a sorted list of the function names available on the object.
+  // Aliased as `methods`
+  _.functions = _.methods = function(obj) {
+    var names = [];
+    for (var key in obj) {
+      if (_.isFunction(obj[key])) names.push(key);
+    }
+    return names.sort();
+  };
+
+  // Extend a given object with all the properties in passed-in object(s).
+  _.extend = function(obj) {
+    each(slice.call(arguments, 1), function(source) {
+      if (source) {
+        for (var prop in source) {
+          obj[prop] = source[prop];
+        }
+      }
+    });
+    return obj;
+  };
+
+  // Return a copy of the object only containing the whitelisted properties.
+  _.pick = function(obj) {
+    var copy = {};
+    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+    each(keys, function(key) {
+      if (key in obj) copy[key] = obj[key];
+    });
+    return copy;
+  };
+
+   // Return a copy of the object without the blacklisted properties.
+  _.omit = function(obj) {
+    var copy = {};
+    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+    for (var key in obj) {
+      if (!_.contains(keys, key)) copy[key] = obj[key];
+    }
+    return copy;
+  };
+
+  // Fill in a given object with default properties.
+  _.defaults = function(obj) {
+    each(slice.call(arguments, 1), function(source) {
+      if (source) {
+        for (var prop in source) {
+          if (obj[prop] == null) obj[prop] = source[prop];
+        }
+      }
+    });
+    return obj;
+  };
+
+  // Create a (shallow-cloned) duplicate of an object.
+  _.clone = function(obj) {
+    if (!_.isObject(obj)) return obj;
+    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+  };
+
+  // Invokes interceptor with the obj, and then returns obj.
+  // The primary purpose of this method is to "tap into" a method chain, in
+  // order to perform operations on intermediate results within the chain.
+  _.tap = function(obj, interceptor) {
+    interceptor(obj);
+    return obj;
+  };
+
+  // Internal recursive comparison function for `isEqual`.
+  var eq = function(a, b, aStack, bStack) {
+    // Identical objects are equal. `0 === -0`, but they aren't identical.
+    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
+    if (a === b) return a !== 0 || 1 / a == 1 / b;
+    // A strict comparison is necessary because `null == undefined`.
+    if (a == null || b == null) return a === b;
+    // Unwrap any wrapped objects.
+    if (a instanceof _) a = a._wrapped;
+    if (b instanceof _) b = b._wrapped;
+    // Compare `[[Class]]` names.
+    var className = toString.call(a);
+    if (className != toString.call(b)) return false;
+    switch (className) {
+      // Strings, numbers, dates, and booleans are compared by value.
+      case '[object String]':
+        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+        // equivalent to `new String("5")`.
+        return a == String(b);
+      case '[object Number]':
+        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
+        // other numeric values.
+        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+      case '[object Date]':
+      case '[object Boolean]':
+        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+        // millisecond representations. Note that invalid dates with millisecond representations
+        // of `NaN` are not equivalent.
+        return +a == +b;
+      // RegExps are compared by their source patterns and flags.
+      case '[object RegExp]':
+        return a.source == b.source &&
+               a.global == b.global &&
+               a.multiline == b.multiline &&
+               a.ignoreCase == b.ignoreCase;
+    }
+    if (typeof a != 'object' || typeof b != 'object') return false;
+    // Assume equality for cyclic structures. The algorithm for detecting cyclic
+    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+    var length = aStack.length;
+    while (length--) {
+      // Linear search. Performance is inversely proportional to the number of
+      // unique nested structures.
+      if (aStack[length] == a) return bStack[length] == b;
+    }
+    // Add the first object to the stack of traversed objects.
+    aStack.push(a);
+    bStack.push(b);
+    var size = 0, result = true;
+    // Recursively compare objects and arrays.
+    if (className == '[object Array]') {
+      // Compare array lengths to determine if a deep comparison is necessary.
+      size = a.length;
+      result = size == b.length;
+      if (result) {
+        // Deep compare the contents, ignoring non-numeric properties.
+        while (size--) {
+          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
+        }
+      }
+    } else {
+      // Objects with different constructors are not equivalent, but `Object`s
+      // from different frames are.
+      var aCtor = a.constructor, bCtor = b.constructor;
+      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
+                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
+        return false;
+      }
+      // Deep compare objects.
+      for (var key in a) {
+        if (_.has(a, key)) {
+          // Count the expected number of properties.
+          size++;
+          // Deep compare each member.
+          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
+        }
+      }
+      // Ensure that both objects contain the same number of properties.
+      if (result) {
+        for (key in b) {
+          if (_.has(b, key) && !(size--)) break;
+        }
+        result = !size;
+      }
+    }
+    // Remove the first object from the stack of traversed objects.
+    aStack.pop();
+    bStack.pop();
+    return result;
+  };
+
+  // Perform a deep comparison to check if two objects are equal.
+  _.isEqual = function(a, b) {
+    return eq(a, b, [], []);
+  };
+
+  // Is a given array, string, or object empty?
+  // An "empty" object has no enumerable own-properties.
+  _.isEmpty = function(obj) {
+    if (obj == null) return true;
+    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+    for (var key in obj) if (_.has(obj, key)) return false;
+    return true;
+  };
+
+  // Is a given value a DOM element?
+  _.isElement = function(obj) {
+    return !!(obj && obj.nodeType === 1);
+  };
+
+  // Is a given value an array?
+  // Delegates to ECMA5's native Array.isArray
+  _.isArray = nativeIsArray || function(obj) {
+    return toString.call(obj) == '[object Array]';
+  };
+
+  // Is a given variable an object?
+  _.isObject = function(obj) {
+    return obj === Object(obj);
+  };
+
+  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
+  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
+    _['is' + name] = function(obj) {
+      return toString.call(obj) == '[object ' + name + ']';
+    };
+  });
+
+  // Define a fallback version of the method in browsers (ahem, IE), where
+  // there isn't any inspectable "Arguments" type.
+  if (!_.isArguments(arguments)) {
+    _.isArguments = function(obj) {
+      return !!(obj && _.has(obj, 'callee'));
+    };
+  }
+
+  // Optimize `isFunction` if appropriate.
+  if (typeof (/./) !== 'function') {
+    _.isFunction = function(obj) {
+      return typeof obj === 'function';
+    };
+  }
+
+  // Is a given object a finite number?
+  _.isFinite = function(obj) {
+    return isFinite(obj) && !isNaN(parseFloat(obj));
+  };
+
+  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+  _.isNaN = function(obj) {
+    return _.isNumber(obj) && obj != +obj;
+  };
+
+  // Is a given value a boolean?
+  _.isBoolean = function(obj) {
+    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
+  };
+
+  // Is a given value equal to null?
+  _.isNull = function(obj) {
+    return obj === null;
+  };
+
+  // Is a given variable undefined?
+  _.isUndefined = function(obj) {
+    return obj === void 0;
+  };
+
+  // Shortcut function for checking if an object has a given property directly
+  // on itself (in other words, not on a prototype).
+  _.has = function(obj, key) {
+    return hasOwnProperty.call(obj, key);
+  };
+
+  // Utility Functions
+  // -----------------
+
+  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+  // previous owner. Returns a reference to the Underscore object.
+  _.noConflict = function() {
+    root._ = previousUnderscore;
+    return this;
+  };
+
+  // Keep the identity function around for default iterators.
+  _.identity = function(value) {
+    return value;
+  };
+
+  // Run a function **n** times.
+  _.times = function(n, iterator, context) {
+    var accum = Array(n);
+    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
+    return accum;
+  };
+
+  // Return a random integer between min and max (inclusive).
+  _.random = function(min, max) {
+    if (max == null) {
+      max = min;
+      min = 0;
+    }
+    return min + Math.floor(Math.random() * (max - min + 1));
+  };
+
+  // List of HTML entities for escaping.
+  var entityMap = {
+    escape: {
+      '&': '&amp;',
+      '<': '&lt;',
+      '>': '&gt;',
+      '"': '&quot;',
+      "'": '&#x27;',
+      '/': '&#x2F;'
+    }
+  };
+  entityMap.unescape = _.invert(entityMap.escape);
+
+  // Regexes containing the keys and values listed immediately above.
+  var entityRegexes = {
+    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
+    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
+  };
+
+  // Functions for escaping and unescaping strings to/from HTML interpolation.
+  _.each(['escape', 'unescape'], function(method) {
+    _[method] = function(string) {
+      if (string == null) return '';
+      return ('' + string).replace(entityRegexes[method], function(match) {
+        return entityMap[method][match];
+      });
+    };
+  });
+
+  // If the value of the named property is a function then invoke it;
+  // otherwise, return it.
+  _.result = function(object, property) {
+    if (object == null) return null;
+    var value = object[property];
+    return _.isFunction(value) ? value.call(object) : value;
+  };
+
+  // Add your own custom functions to the Underscore object.
+  _.mixin = function(obj) {
+    each(_.functions(obj), function(name){
+      var func = _[name] = obj[name];
+      _.prototype[name] = function() {
+        var args = [this._wrapped];
+        push.apply(args, arguments);
+        return result.call(this, func.apply(_, args));
+      };
+    });
+  };
+
+  // Generate a unique integer id (unique within the entire client session).
+  // Useful for temporary DOM ids.
+  var idCounter = 0;
+  _.uniqueId = function(prefix) {
+    var id = ++idCounter + '';
+    return prefix ? prefix + id : id;
+  };
+
+  // By default, Underscore uses ERB-style template delimiters, change the
+  // following template settings to use alternative delimiters.
+  _.templateSettings = {
+    evaluate    : /<%([\s\S]+?)%>/g,
+    interpolate : /<%=([\s\S]+?)%>/g,
+    escape      : /<%-([\s\S]+?)%>/g
+  };
+
+  // When customizing `templateSettings`, if you don't want to define an
+  // interpolation, evaluation or escaping regex, we need one that is
+  // guaranteed not to match.
+  var noMatch = /(.)^/;
+
+  // Certain characters need to be escaped so that they can be put into a
+  // string literal.
+  var escapes = {
+    "'":      "'",
+    '\\':     '\\',
+    '\r':     'r',
+    '\n':     'n',
+    '\t':     't',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
+
+  // JavaScript micro-templating, similar to John Resig's implementation.
+  // Underscore templating handles arbitrary delimiters, preserves whitespace,
+  // and correctly escapes quotes within interpolated code.
+  _.template = function(text, data, settings) {
+    var render;
+    settings = _.defaults({}, settings, _.templateSettings);
+
+    // Combine delimiters into one regular expression via alternation.
+    var matcher = new RegExp([
+      (settings.escape || noMatch).source,
+      (settings.interpolate || noMatch).source,
+      (settings.evaluate || noMatch).source
+    ].join('|') + '|$', 'g');
+
+    // Compile the template source, escaping string literals appropriately.
+    var index = 0;
+    var source = "__p+='";
+    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+      source += text.slice(index, offset)
+        .replace(escaper, function(match) { return '\\' + escapes[match]; });
+
+      if (escape) {
+        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+      }
+      if (interpolate) {
+        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+      }
+      if (evaluate) {
+        source += "';\n" + evaluate + "\n__p+='";
+      }
+      index = offset + match.length;
+      return match;
+    });
+    source += "';\n";
+
+    // If a variable is not specified, place data values in local scope.
+    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+    source = "var __t,__p='',__j=Array.prototype.join," +
+      "print=function(){__p+=__j.call(arguments,'');};\n" +
+      source + "return __p;\n";
+
+    try {
+      render = new Function(settings.variable || 'obj', '_', source);
+    } catch (e) {
+      e.source = source;
+      throw e;
+    }
+
+    if (data) return render(data, _);
+    var template = function(data) {
+      return render.call(this, data, _);
+    };
+
+    // Provide the compiled function source as a convenience for precompilation.
+    template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
+
+    return template;
+  };
+
+  // Add a "chain" function, which will delegate to the wrapper.
+  _.chain = function(obj) {
+    return _(obj).chain();
+  };
+
+  // OOP
+  // ---------------
+  // If Underscore is called as a function, it returns a wrapped object that
+  // can be used OO-style. This wrapper holds altered versions of all the
+  // underscore functions. Wrapped objects may be chained.
+
+  // Helper function to continue chaining intermediate results.
+  var result = function(obj) {
+    return this._chain ? _(obj).chain() : obj;
+  };
+
+  // Add all of the Underscore functions to the wrapper object.
+  _.mixin(_);
+
+  // Add all mutator Array functions to the wrapper.
+  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+    var method = ArrayProto[name];
+    _.prototype[name] = function() {
+      var obj = this._wrapped;
+      method.apply(obj, arguments);
+      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
+      return result.call(this, obj);
+    };
+  });
+
+  // Add all accessor Array functions to the wrapper.
+  each(['concat', 'join', 'slice'], function(name) {
+    var method = ArrayProto[name];
+    _.prototype[name] = function() {
+      return result.call(this, method.apply(this._wrapped, arguments));
+    };
+  });
+
+  _.extend(_.prototype, {
+
+    // Start chaining a wrapped Underscore object.
+    chain: function() {
+      this._chain = true;
+      return this;
+    },
+
+    // Extracts the result from a wrapped and chained object.
+    value: function() {
+      return this._wrapped;
+    }
+
+  });
+
+}).call(this);
Index: Dev/trunk/src/node_modules/ya-csv/CHANGELOG.md
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/CHANGELOG.md	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/CHANGELOG.md	(revision 484)
@@ -0,0 +1,13 @@
+0.1.3
+
+ - `CsvReader` - BUGFIX: last column was not passed to the `data` listener
+ - `CsvWriter` - `null` string written as an empty field rather than throwing an exception
+ - executable `reshuffle` script to strip and/or reorder columns of a CSV stream on stdin
+
+0.1.1 - 0.1.2
+
+ - package.json added
+
+0.1.0 
+
+ - minimal implementation
Index: Dev/trunk/src/node_modules/ya-csv/LICENSE
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/LICENSE	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/LICENSE	(revision 484)
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Pavel Kolesnikov
+
+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.
Index: Dev/trunk/src/node_modules/ya-csv/README.md
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/README.md	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/README.md	(revision 484)
@@ -0,0 +1,92 @@
+# ya-csv
+
+Event based CSV parser and writer for Node.js suitable for processing large CSV streams.
+
+    // A simple echo program:
+    var csv = require('ya-csv');
+
+    var reader = csv.createCsvStreamReader(process.openStdin());
+    var writer = csv.createCsvStreamWriter(process.stdout);
+
+    reader.addListener('data', function(data) {
+        writer.writeRecord(data);
+    });
+
+## Installation
+
+    npm install ya-csv
+
+Current version requires at least Node.js v0.2.3 and it's tested with Node.js v0.4.12, 0.6.11 and 0.7.5. Hope it works with the other versions in between too.
+
+## Features
+
+ - event based, suitable for processing big CSV streams
+ - configurable separator, quote and escape characters (comma, double-quote and double-quote by default)
+ - ignores lines starting with configurable comment character (off by default)
+ - supports memory-only streaming
+
+## More examples
+
+Echo first column of the `data.csv` file:
+
+    // equivalent of csv.createCsvFileReader('data.csv') 
+    var reader = csv.createCsvFileReader('data.csv', {
+        'separator': ',',
+        'quote': '"',
+        'escape': '"',       
+        'comment': '',
+    });
+    var writer = new csv.CsvWriter(process.stdout);
+    reader.addListener('data', function(data) {
+        writer.writeRecord([ data[0] ]);
+    });
+
+Return data in objects rather than arrays: either by grabbing the column names form the header row (first row is not passed to the `data` listener):
+
+    var reader = csv.createCsvFileReader('data.csv', { columnsFromHeader: true });
+    reader.addListener('data', function(data) {
+        // supposing there are so named columns in the source file
+        sys.puts(data.col1 + " ... " + data.col2);
+    });
+
+... or by providing column names from the client code (first row is passed to the `data` listener in this case):
+
+    var reader = csv.createCsvFileReader('data.csv');
+    reader.setColumnNames([ 'col1', 'col2' ]);
+    reader.addListener('data', function(data) {
+        sys.puts(data.col1 + " ... " + data.col2);
+    });
+
+Note `reader.setColumnNames()` resets the column names so next invocation of the `data` listener will again receive the data in an array rather than an object.
+
+Convert the `/etc/passwd` file to comma separated format, drop commented lines and dump the results to the standard output:
+
+    var reader = csv.createCsvFileReader('/etc/passwd', {
+        'separator': ':',
+        'quote': '"',
+        'escape': '"',
+        'comment': '#',
+    });
+    var writer = new csv.CsvWriter(process.stdout);
+    reader.addListener('data', function(data) {
+        writer.writeRecord(data);
+    });
+
+Parsing an upload as the data comes in, using node-formidable:
+
+    upload_form.onPart = function(part) {
+        if (!part.filename) { upload_form.handlePart(part); return }
+
+        var reader = csv.createCsvFileReader({'comment': '#'});
+        reader.addListener('data', function(data) {
+            saveRecord(data);
+        });
+
+        part.on('data', function(buffer) {
+            // Pipe incoming data into the reader.
+            reader.parse(buffer);
+        });
+        part.on('end', function() {
+            reader.end()
+        }
+    }
Index: Dev/trunk/src/node_modules/ya-csv/TODO.md
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/TODO.md	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/TODO.md	(revision 484)
@@ -0,0 +1,13 @@
+# ya-csv TODO list
+
+Must have:
+
+ - test coverage
+ - get a CSV record as a hash
+ - don't quote every field unless explicitly stated
+
+Sometimes later:
+
+ - CSV manipulation utilities
+ - distinguish `null` and empty string by quoting
+ - support for invalid CSV streams (unescaped quotes within fields etc)
Index: Dev/trunk/src/node_modules/ya-csv/bin/reshuffle.js
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/bin/reshuffle.js	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/bin/reshuffle.js	(revision 484)
@@ -0,0 +1,25 @@
+var csv = require('../lib/ya-csv'),
+    sys = require('sys');
+
+var reader = csv.createCsvStreamReader(process.openStdin(), { columnsFromHeader: true });
+var writer = csv.createCsvStreamWriter(process.stdout);
+
+if (process.argv.length < 3) {
+    sys.error("Usage: " + process.argv[0] + " " + process.argv[1] + " <output columns>");
+    process.exit(1);
+}
+
+var outColumns = [];
+for (var i = 2; i < process.argv.length; i++) {
+    outColumns.push(process.argv[i]);
+}
+
+writer.writeRecord(outColumns);
+reader.addListener('data', function(data) {
+    var out = [];
+    for (var i = 0; i < outColumns.length; i++) {
+        col = outColumns[i];
+        out[i] = data[col];
+    }
+    writer.writeRecord(out);
+});
Index: Dev/trunk/src/node_modules/ya-csv/lib/ya-csv.js
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/lib/ya-csv.js	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/lib/ya-csv.js	(revision 484)
@@ -0,0 +1,336 @@
+var sys;
+try {
+  sys    = require('util'); 
+} catch (e) {
+  sys    = require('sys');
+}
+var events = require('events'),
+    fs     = require('fs');
+
+var csv = exports;
+
+/**
+ * Provides Base CSV Reading capabilities
+ * @class CsvReader
+ * @extends EventEmitter
+ */
+
+/**
+ * The constructor
+ * @constructor
+ * @param readStream {ReadStread} An instance of the ReadStream Cl
+ * @param options {Object} optional paramaters for the reader <br/>
+ *     - separator {String}
+ *     - quote {String}
+ *     - escape {String}
+ *     - comment {String}
+ *     - columnNames {Boolean}
+ *     - columnsFromHeader {Boolean}
+ *     - nestedQuotes {Boolean}
+ */
+var CsvReader = csv.CsvReader = function(readStream, options) {
+    var self = this;
+    _setOptions(self, options);
+
+    self.parsingStatus = {
+        rows:          0,
+        openRecord:    [],
+        openField:     '',
+        lastChar:      '',
+        quotedField:   false,
+        commentedLine: false
+    };
+
+    if (readStream) {
+        readStream.addListener('data', this.parse.bind(this));
+        readStream.addListener('error', this.emit.bind(this, 'error'));
+        readStream.addListener('end', this.end.bind(this));
+
+
+        /**
+         * Pauses the readStream
+         * @method pause
+         * @return {ReadStream} the readstream instance
+         */
+        self.pause = function(){
+            readStream.pause();
+            return self;
+        }
+
+        /**
+         * Resumes the readStream
+         * @method resume
+         * @return {ReadStream} the readstream instance
+         */
+        self.resume = function(){
+            readStream.resume();
+            return self;
+        }
+
+        /**
+         * Closes the readStream
+         * @method destroy
+         * @return {ReadStream} the readstream instance
+         */
+        self.destoy = function(){
+            readStream.destroy();
+            return self;
+        }
+
+        /**
+         * Closes the readStream when its file stream has been drained
+         * @method destroySoon
+         * @return {ReadStream} the readstream instance
+         */
+        self.destroySoon = function(){
+            readstream.destroy();
+            return self;
+        }
+    }
+
+};
+sys.inherits(CsvReader, events.EventEmitter);
+
+/**
+ * Parses incoming data as a readable CSV file
+ * @method parse
+ * @param data {Array} Array of values to parse from the incommin file
+ */
+CsvReader.prototype.parse = function(data) {
+    var ps = this.parsingStatus;
+    if (ps.openRecord.length == 0) {
+        if (data.charCodeAt(0) === 0xFEFF) {
+            data = data.slice(1);
+        }
+    }
+    for (var i = 0; i < data.length; i++) {
+        var c = data.charAt(i);
+        switch (c) {
+            // escape and separator may be the same char, typically '"'
+            case this.escapechar:
+            case this.quotechar:
+                if (ps.commentedLine) break;
+                var isEscape = false;
+                if (c === this.escapechar) {
+                    var nextChar = data.charAt(i + 1);
+                    if (this._isEscapable(nextChar)) {
+                        this._addCharacter(nextChar);
+                        i++;
+                        isEscape = true;
+                    }
+                }
+                if (!isEscape && (c === this.quotechar)) {
+                    if (ps.openField && !ps.quotedField) {
+                        ps.quotedField = true;
+                        break;
+                    }
+                    if (ps.quotedField) {
+                        // closing quote should be followed by separator unless the nested quotes option is set
+                        var nextChar = data.charAt(i + 1);
+                        if (nextChar && nextChar != '\r' && nextChar != '\n' && nextChar !== this.separator && this.nestedQuotes != true) {
+                            throw new Error("separator expected after a closing quote; found " + nextChar);
+                        } else {
+                            ps.quotedField = false;
+                        }
+                    } else if (ps.openField === '') {
+                        ps.quotedField = true;
+                    }
+                }
+                break;
+            case this.separator:
+                if (ps.commentedLine) break;
+                if (ps.quotedField) {
+                    this._addCharacter(c);
+                } else {
+                    this._addField();
+                }
+                break;
+            case '\n':
+                // handle CRLF sequence
+                if (!ps.quotedField && (ps.lastChar === '\r')) {
+                    break;
+                }
+            case '\r':
+                if (ps.commentedLine) {
+                    ps.commentedLine = false;
+                } else if (ps.quotedField) {
+                    this._addCharacter(c);
+                } else {
+                    this._addField();
+                    this._addRecord();
+                }
+                break;
+            case this.commentchar:
+                if (ps.commentedLine) break;
+                if (ps.openRecord.length === 0 && ps.openField === '' && !ps.quotedField) {
+                    ps.commentedLine = true;
+                } else {
+                    this._addCharacter(c);
+                }
+            default:
+                if (ps.commentedLine) break;
+                this._addCharacter(c);
+        }
+        ps.lastChar = c;
+    }
+};
+
+
+CsvReader.prototype.end = function() {
+    var ps = this.parsingStatus;
+    if (ps.quotedField) {
+        this.emit('error', new Error('Input stream ended but closing quotes expected'));
+    } else {
+        // dump open record
+        if (ps.openField) {
+            this._addField();
+        }
+        if (ps.openRecord.length > 0) {
+            this._addRecord();
+        }
+        this.emit('end');
+    }
+}
+CsvReader.prototype._isEscapable = function(c) {
+    if ((c === this.escapechar) || (c === this.quotechar)) {
+        return true;
+    }
+    return false;
+};
+
+CsvReader.prototype._addCharacter = function(c) {
+    this.parsingStatus.openField += c;
+};
+
+CsvReader.prototype._addField = function() {
+    var ps = this.parsingStatus;
+    ps.openRecord.push(ps.openField);
+    ps.openField = '';
+    ps.quotedField = false;
+};
+
+CsvReader.prototype.setColumnNames = function(names) {
+    this.columnNames = names;
+};
+
+CsvReader.prototype._addRecord = function() {
+    var ps = this.parsingStatus;
+    if (this.columnsFromHeader && ps.rows === 0) {
+        this.setColumnNames(ps.openRecord);
+    } else if (this.columnNames != null && this.columnNames.length > 0) {
+        var objResult = {};
+        for (var i = 0; i < this.columnNames.length; i++) {
+            objResult[this.columnNames[i]] = ps.openRecord[i];
+        }
+        this.emit('data', objResult);
+    } else {
+        this.emit('data', ps.openRecord);
+    }
+    ps.rows++;
+    ps.openRecord = [];
+    ps.openField = '';
+    ps.quotedField = false;
+};
+
+csv.createCsvFileReader = function(path, options) {
+    options = options || {};
+    var readStream = fs.createReadStream(path, {
+        'flags': options.flags || 'r'
+    });
+    readStream.setEncoding(options.encoding || 'utf8');
+    return new CsvReader(readStream, options);
+};
+
+csv.createCsvStreamReader = function(readStream, options) {
+    if (options === undefined && typeof readStream === 'object') {
+        options = readStream;
+        readStream = undefined;
+    }
+    options = options || {};
+    if (readStream) readStream.setEncoding(options.encoding || 'utf8');
+    return new CsvReader(readStream, options);
+};
+
+var CsvWriter = csv.CsvWriter = function(writeStream, options) {
+    var self = this;
+    self.writeStream = writeStream;
+    options = options || {};
+    _setOptions(self, options);
+    self.encoding = options.encoding || 'utf8';
+
+    if (typeof writeStream.setEncoding === 'function') {
+        writeStream.setEncoding(self.encoding);
+    }
+
+    writeStream.addListener('drain', this.emit.bind(this, 'drain'));
+    writeStream.addListener('error', this.emit.bind(this, 'error'));
+    writeStream.addListener('close', this.emit.bind(this, 'close'));
+};
+sys.inherits(CsvWriter, events.EventEmitter);
+
+CsvWriter.prototype.writeRecord = function(rec) {
+    if (!rec) return; // ignore empty records
+    if (!Array.isArray(rec)) {
+        throw new Error("CsvWriter.writeRecord only takes an array as an argument");
+    }
+    _writeArray(this, rec);
+};
+
+function _writeArray(writer, arr) {
+    var out = [];
+    for (var i = 0; i < arr.length; i++) {
+        if (i != 0) out.push(writer.separator);
+        out.push(writer.quotechar);
+        _appendField(out, writer, arr[i]);
+        out.push(writer.quotechar);
+    }
+    out.push("\r\n");
+    writer.writeStream.write(out.join(''), this.encoding);
+};
+
+function _appendField(outArr, writer, field) {
+    // Make sure field is a string
+    if(typeof(field) !== 'string') {
+      // We are not interested in outputting "null" or "undefined"
+      if(typeof(field) !== 'undefined' && field !== null) {
+        field = String(field);
+      } else {
+        outArr.push('');
+        return;
+      }
+    }
+
+    for (var i = 0; i < field.length; i++) {
+        if (field.charAt(i) === writer.quotechar || field.charAt(i) === writer.escapechar) {
+            outArr.push(writer.escapechar);
+        }
+        outArr.push(field.charAt(i));
+    }
+};
+
+csv.createCsvFileWriter = function(path, options) {
+    options = options || {'flags': 'w'};
+    var writeStream = fs.createWriteStream(path, {
+        'flags': options.flags || 'w'
+    });
+    return new CsvWriter(writeStream, options);
+};
+
+csv.createCsvStreamWriter = function(writeStream, options) {
+    return new CsvWriter(writeStream, options);
+};
+
+// ===============
+// =   utils     =
+// ===============
+
+function _setOptions(obj, options) {
+    options = options || {};
+    obj.separator   = options.separator   || ',';
+    obj.quotechar   = options.quote       || '"';
+    obj.escapechar  = options.escape      || '"';
+    obj.commentchar = options.comment     || '';
+    obj.columnNames = options.columnNames || [];
+    obj.columnsFromHeader = options.columnsFromHeader || false;
+    obj.nestedQuotes = options.nestedQuotes || false;
+};
Index: Dev/trunk/src/node_modules/ya-csv/package.json
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/package.json	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/package.json	(revision 484)
@@ -0,0 +1,47 @@
+{
+  "name": "ya-csv",
+  "description": "CSV parser and generator for Node.js",
+  "version": "0.9.2",
+  "keywords": [
+    "node",
+    "csv",
+    "parser"
+  ],
+  "author": {
+    "name": "Pavel Kolesnikov",
+    "email": "pavel.kolesnikov@gmail.com"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "https://raw.github.com/koles/ya-csv/master/LICENSE"
+    }
+  ],
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/koles/ya-csv"
+  },
+  "bugs": {
+    "url": "http://github.com/koles/ya-csv/issues"
+  },
+  "directories": {
+    "lib": "./lib",
+    "test": "./test"
+  },
+  "bin": {
+    "csv-reshuffle": "./bin/reshuffle.js"
+  },
+  "dependencies": {},
+  "engines": {
+    "node": ">=0.2.3"
+  },
+  "main": "lib/ya-csv",
+  "readme": "# ya-csv\n\nEvent based CSV parser and writer for Node.js suitable for processing large CSV streams.\n\n    // A simple echo program:\n    var csv = require('ya-csv');\n\n    var reader = csv.createCsvStreamReader(process.openStdin());\n    var writer = csv.createCsvStreamWriter(process.stdout);\n\n    reader.addListener('data', function(data) {\n        writer.writeRecord(data);\n    });\n\n## Installation\n\n    npm install ya-csv\n\nCurrent version requires at least Node.js v0.2.3 and it's tested with Node.js v0.4.12, 0.6.11 and 0.7.5. Hope it works with the other versions in between too.\n\n## Features\n\n - event based, suitable for processing big CSV streams\n - configurable separator, quote and escape characters (comma, double-quote and double-quote by default)\n - ignores lines starting with configurable comment character (off by default)\n - supports memory-only streaming\n\n## More examples\n\nEcho first column of the `data.csv` file:\n\n    // equivalent of csv.createCsvFileReader('data.csv') \n    var reader = csv.createCsvFileReader('data.csv', {\n        'separator': ',',\n        'quote': '\"',\n        'escape': '\"',       \n        'comment': '',\n    });\n    var writer = new csv.CsvWriter(process.stdout);\n    reader.addListener('data', function(data) {\n        writer.writeRecord([ data[0] ]);\n    });\n\nReturn data in objects rather than arrays: either by grabbing the column names form the header row (first row is not passed to the `data` listener):\n\n    var reader = csv.createCsvFileReader('data.csv', { columnsFromHeader: true });\n    reader.addListener('data', function(data) {\n        // supposing there are so named columns in the source file\n        sys.puts(data.col1 + \" ... \" + data.col2);\n    });\n\n... or by providing column names from the client code (first row is passed to the `data` listener in this case):\n\n    var reader = csv.createCsvFileReader('data.csv');\n    reader.setColumnNames([ 'col1', 'col2' ]);\n    reader.addListener('data', function(data) {\n        sys.puts(data.col1 + \" ... \" + data.col2);\n    });\n\nNote `reader.setColumnNames()` resets the column names so next invocation of the `data` listener will again receive the data in an array rather than an object.\n\nConvert the `/etc/passwd` file to comma separated format, drop commented lines and dump the results to the standard output:\n\n    var reader = csv.createCsvFileReader('/etc/passwd', {\n        'separator': ':',\n        'quote': '\"',\n        'escape': '\"',\n        'comment': '#',\n    });\n    var writer = new csv.CsvWriter(process.stdout);\n    reader.addListener('data', function(data) {\n        writer.writeRecord(data);\n    });\n\nParsing an upload as the data comes in, using node-formidable:\n\n    upload_form.onPart = function(part) {\n        if (!part.filename) { upload_form.handlePart(part); return }\n\n        var reader = csv.createCsvFileReader({'comment': '#'});\n        reader.addListener('data', function(data) {\n            saveRecord(data);\n        });\n\n        part.on('data', function(buffer) {\n            // Pipe incoming data into the reader.\n            reader.parse(buffer);\n        });\n        part.on('end', function() {\n            reader.end()\n        }\n    }\n",
+  "readmeFilename": "README.md",
+  "_id": "ya-csv@0.9.2",
+  "dist": {
+    "shasum": "088ddf523ca066bbe654146100cf70030d9f6779"
+  },
+  "_from": "ya-csv@",
+  "_resolved": "https://registry.npmjs.org/ya-csv/-/ya-csv-0.9.2.tgz"
+}
Index: Dev/trunk/src/node_modules/ya-csv/test/echo.js
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/test/echo.js	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/test/echo.js	(revision 484)
@@ -0,0 +1,34 @@
+var csv  = require('../lib/ya-csv'),
+    sys  = require('sys');
+
+sys.debug('start');
+
+if (process.argv.length < 3) {
+    sys.error("Usage: node " + process.argv[1] + " <csv file>");
+    process.exit(1);
+}
+
+var file = process.argv[2];
+
+var csvIn = csv.createCsvFileReader(file, {
+    'separator': ',',
+    'quote':   '"',
+    'comment': '#',
+});
+var csvOut = new csv.CsvWriter(process.stdout, {
+    'encoding': 'utf8'        
+});
+
+var lines   = 0;
+var columns = 0;
+
+csvIn.addListener('end', function() {
+    sys.debug('end');
+    sys.debug(columns + ' columns, ' + lines + ' lines');
+});
+
+csvIn.addListener('data', function(data) {
+    lines++;
+    columns += data.length;
+    csvOut.writeRecord(data);
+});
Index: Dev/trunk/src/node_modules/ya-csv/test/index.js
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/test/index.js	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/test/index.js	(revision 484)
@@ -0,0 +1,39 @@
+var sys;
+try {
+  sys    = require('util'); 
+} catch (e) {
+  sys    = require('sys');
+}
+
+var csv    = require('../lib/ya-csv'),
+    assert = require('assert');
+
+var testFile = __dirname + '/crazy.csv';
+var expectedRows = 7;
+var expectedColsPerRow = 4;
+
+var csvInNoOptions = csv.createCsvFileReader(testFile);
+var csvIn = csv.createCsvFileReader(testFile, {
+    'separator': ',',
+    'quote':   '"',
+    'comment': '#',
+});
+var csvOutNoOptions = csv.createCsvFileWriter('/dev/null');
+var csvOut = csv.createCsvFileWriter('/dev/null', { 'encoding': 'utf8' });
+
+var lines   = 0;
+var columns = 0;
+
+csvIn.addListener('end', function() {
+    assert.strictEqual(expectedRows, lines, "Wrong number of records");
+    sys.debug(columns + ' columns, ' + lines + ' lines');
+});
+
+csvIn.addListener('data', function(data) {
+    lines++;
+    data.push(1);
+    csvOut.writeRecord(data);
+    assert.strictEqual(expectedColsPerRow + 1, data.length,
+        "Wrong number of fields per record in record #" + lines);
+    columns += data.length;
+});
Index: Dev/trunk/src/node_modules/ya-csv/test/perl-csv-test.pl
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/test/perl-csv-test.pl	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/test/perl-csv-test.pl	(revision 484)
@@ -0,0 +1,32 @@
+#!/usr/bin/perl -w
+
+use Text::CSV_XS;
+
+my %CSV_OPTS_IN = (
+    'binary'        => 1,
+    'quote_char'    => '"',
+    'escape_char'   => '"',
+);
+my %CSV_OPTS_OUT = %CSV_OPTS_IN;
+$CSV_OPTS_OUT{'always_quote'} = 1;
+
+my $CSV_IN  = Text::CSV_XS->new(\%CSV_OPTS_IN)  or die "" . Text::CSV_XS->error_diag;
+
+sub main() {
+    my $start = localtime;
+    print "$start\n";
+    my $fh = *STDIN;
+
+    until ($CSV_IN->eof) {
+        my $hr = $CSV_IN->getline($fh) or do {
+            last if $CSV_IN->eof;
+            die "CSV_IN getline error: " . Text::CSV_XS->error_diag;
+        };
+        my $a = 0;
+    }
+
+    my $end = localtime;
+    print "$end\n";
+}
+
+main();
Index: Dev/trunk/src/node_modules/ya-csv/test/stream.js
===================================================================
--- Dev/trunk/src/node_modules/ya-csv/test/stream.js	(revision 484)
+++ Dev/trunk/src/node_modules/ya-csv/test/stream.js	(revision 484)
@@ -0,0 +1,45 @@
+var csv  = require('../lib/ya-csv'),
+    sys  = require('sys'),
+    fs = require('fs');
+
+sys.debug('start');
+
+if (process.argv.length < 3) {
+    sys.error("Usage: node " + process.argv[1] + " <csv file>");
+    process.exit(1);
+}
+
+var csvIn = csv.createCsvStreamReader({
+    'separator': ',',
+    'quote':   '"',
+    'comment': '#'
+});
+
+var lines   = 0;
+var columns = 0;
+
+csvIn.addListener('end', function() {
+    sys.debug('end');
+    sys.debug(columns + ' columns, ' + lines + ' lines');
+});
+
+csvIn.addListener('error', function(e) {
+    sys.debug('error');
+    sys.debug(e);
+});
+
+csvIn.addListener('data', function(data) {
+    lines++;
+    columns += data.length;
+});
+
+var file = process.argv[2];
+var fileIn = fs.createReadStream(file, {flags: 'r', bufferSize: 10});
+fileIn.setEncoding('utf8');
+fileIn.on('data', function(data) {
+  sys.debug(data);
+  csvIn.parse(data);
+});
+fileIn.on('end', function(data) {
+  csvIn.end();
+});
