From b603f2404c73feacb1cc9a104d9b77a1ab1221b9 Mon Sep 17 00:00:00 2001 From: Stuiart Stent Date: Thu, 14 Feb 2013 08:18:17 -0500 Subject: [PATCH] little css --- app.js | 5 +- node_modules/gzippo/.npmignore | 13 + node_modules/gzippo/.travis.yml | 4 + node_modules/gzippo/CHANGELOG | 5 + node_modules/gzippo/README.md | 70 + node_modules/gzippo/index.js | 3 + node_modules/gzippo/lib/compress.js | 139 ++ node_modules/gzippo/lib/fileAsset.js | 61 + node_modules/gzippo/lib/memory.js | 103 ++ node_modules/gzippo/lib/staticGzip.js | 289 ++++ node_modules/gzippo/lib/store.js | 11 + node_modules/gzippo/lib/storeStream.js | 119 ++ .../gzippo/node_modules/send/.npmignore | 4 + .../gzippo/node_modules/send/History.md | 25 + .../gzippo/node_modules/send/Makefile | 8 + .../gzippo/node_modules/send/Readme.md | 123 ++ .../gzippo/node_modules/send/index.js | 2 + .../gzippo/node_modules/send/lib/send.js | 473 ++++++ .../gzippo/node_modules/send/lib/utils.js | 47 + .../send/node_modules/debug/.npmignore | 4 + .../send/node_modules/debug/History.md | 62 + .../send/node_modules/debug/Readme.md | 115 ++ .../send/node_modules/debug/component.json | 9 + .../send/node_modules/debug/debug.js | 124 ++ .../send/node_modules/debug/example/app.js | 19 + .../node_modules/debug/example/browser.html | 24 + .../node_modules/debug/example/wildcards.js | 10 + .../send/node_modules/debug/example/worker.js | 22 + .../send/node_modules/debug/index.js | 5 + .../send/node_modules/debug/lib/debug.js | 134 ++ .../send/node_modules/debug/package.json | 43 + .../send/node_modules/fresh/.npmignore | 1 + .../send/node_modules/fresh/Makefile | 7 + .../send/node_modules/fresh/Readme.md | 32 + .../send/node_modules/fresh/index.js | 49 + .../send/node_modules/fresh/package.json | 29 + .../send/node_modules/mime/LICENSE | 19 + .../send/node_modules/mime/README.md | 63 + .../send/node_modules/mime/mime.js | 104 ++ .../send/node_modules/mime/package.json | 41 + .../send/node_modules/mime/test.js | 55 + .../send/node_modules/mime/types/mime.types | 1510 +++++++++++++++++ .../send/node_modules/mime/types/node.types | 65 + .../send/node_modules/range-parser/.npmignore | 1 + .../send/node_modules/range-parser/History.md | 15 + .../send/node_modules/range-parser/Makefile | 7 + .../send/node_modules/range-parser/Readme.md | 28 + .../send/node_modules/range-parser/index.js | 49 + .../node_modules/range-parser/package.json | 29 + .../gzippo/node_modules/send/package.json | 40 + node_modules/gzippo/package.json | 44 + .../test/fixtures/index_test/index.html | 14 + .../gzippo/test/fixtures/js/nestedTest.js | 0 .../space the final frontier/tomg.co.png | Bin 0 -> 1421 bytes node_modules/gzippo/test/fixtures/test.js | 1 + .../gzippo/test/fixtures/test.js.gzip | Bin 0 -> 35 bytes node_modules/gzippo/test/fixtures/tomg.co.png | Bin 0 -> 1421 bytes node_modules/gzippo/test/fixtures/user.gzip | Bin 0 -> 69 bytes node_modules/gzippo/test/fixtures/user.json | 4 + node_modules/gzippo/test/fixtures/utf8.gz | 0 node_modules/gzippo/test/fixtures/utf8.txt | 32 + node_modules/gzippo/test/fixtures/utf8.txt.gz | Bin 0 -> 2031 bytes node_modules/gzippo/test/prefexTest.js | 88 + node_modules/gzippo/test/prefix.test.js | 67 + node_modules/gzippo/test/request.js | 51 + node_modules/gzippo/test/staticGzipTest.js | 180 ++ node_modules/gzippo/test/test-static.js | 203 +++ public/images/BlankBody.js | 1230 ++++++++++++++ public/images/BlankBody.svgz | Bin 0 -> 43392 bytes public/javascripts/scripts.js | 18 +- public/stylesheets/style.css | 16 +- views/workouts/filters.jade | 43 +- views/workouts/recent.jade | 5 +- 73 files changed, 6191 insertions(+), 24 deletions(-) create mode 100644 node_modules/gzippo/.npmignore create mode 100644 node_modules/gzippo/.travis.yml create mode 100644 node_modules/gzippo/CHANGELOG create mode 100644 node_modules/gzippo/README.md create mode 100644 node_modules/gzippo/index.js create mode 100644 node_modules/gzippo/lib/compress.js create mode 100644 node_modules/gzippo/lib/fileAsset.js create mode 100644 node_modules/gzippo/lib/memory.js create mode 100644 node_modules/gzippo/lib/staticGzip.js create mode 100644 node_modules/gzippo/lib/store.js create mode 100644 node_modules/gzippo/lib/storeStream.js create mode 100644 node_modules/gzippo/node_modules/send/.npmignore create mode 100644 node_modules/gzippo/node_modules/send/History.md create mode 100644 node_modules/gzippo/node_modules/send/Makefile create mode 100644 node_modules/gzippo/node_modules/send/Readme.md create mode 100644 node_modules/gzippo/node_modules/send/index.js create mode 100644 node_modules/gzippo/node_modules/send/lib/send.js create mode 100644 node_modules/gzippo/node_modules/send/lib/utils.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/.npmignore create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/History.md create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/Readme.md create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/component.json create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/debug.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/example/app.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/example/browser.html create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/example/wildcards.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/example/worker.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/index.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/lib/debug.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/debug/package.json create mode 100644 node_modules/gzippo/node_modules/send/node_modules/fresh/.npmignore create mode 100644 node_modules/gzippo/node_modules/send/node_modules/fresh/Makefile create mode 100644 node_modules/gzippo/node_modules/send/node_modules/fresh/Readme.md create mode 100644 node_modules/gzippo/node_modules/send/node_modules/fresh/index.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/fresh/package.json create mode 100644 node_modules/gzippo/node_modules/send/node_modules/mime/LICENSE create mode 100644 node_modules/gzippo/node_modules/send/node_modules/mime/README.md create mode 100644 node_modules/gzippo/node_modules/send/node_modules/mime/mime.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/mime/package.json create mode 100644 node_modules/gzippo/node_modules/send/node_modules/mime/test.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/mime/types/mime.types create mode 100644 node_modules/gzippo/node_modules/send/node_modules/mime/types/node.types create mode 100644 node_modules/gzippo/node_modules/send/node_modules/range-parser/.npmignore create mode 100644 node_modules/gzippo/node_modules/send/node_modules/range-parser/History.md create mode 100644 node_modules/gzippo/node_modules/send/node_modules/range-parser/Makefile create mode 100644 node_modules/gzippo/node_modules/send/node_modules/range-parser/Readme.md create mode 100644 node_modules/gzippo/node_modules/send/node_modules/range-parser/index.js create mode 100644 node_modules/gzippo/node_modules/send/node_modules/range-parser/package.json create mode 100644 node_modules/gzippo/node_modules/send/package.json create mode 100644 node_modules/gzippo/package.json create mode 100644 node_modules/gzippo/test/fixtures/index_test/index.html create mode 100644 node_modules/gzippo/test/fixtures/js/nestedTest.js create mode 100644 node_modules/gzippo/test/fixtures/space the final frontier/tomg.co.png create mode 100644 node_modules/gzippo/test/fixtures/test.js create mode 100644 node_modules/gzippo/test/fixtures/test.js.gzip create mode 100644 node_modules/gzippo/test/fixtures/tomg.co.png create mode 100644 node_modules/gzippo/test/fixtures/user.gzip create mode 100644 node_modules/gzippo/test/fixtures/user.json create mode 100644 node_modules/gzippo/test/fixtures/utf8.gz create mode 100644 node_modules/gzippo/test/fixtures/utf8.txt create mode 100644 node_modules/gzippo/test/fixtures/utf8.txt.gz create mode 100644 node_modules/gzippo/test/prefexTest.js create mode 100644 node_modules/gzippo/test/prefix.test.js create mode 100644 node_modules/gzippo/test/request.js create mode 100644 node_modules/gzippo/test/staticGzipTest.js create mode 100644 node_modules/gzippo/test/test-static.js create mode 100644 public/images/BlankBody.js create mode 100644 public/images/BlankBody.svgz diff --git a/app.js b/app.js index 4881c8f..e92a5b2 100644 --- a/app.js +++ b/app.js @@ -12,11 +12,13 @@ var dbURL = 'mongodb://localhost/database'; var db = require('mongoose').connect(dbURL); var qs = require('qs'); var MongoStore = require('connect-mongo')(express); +var gzippo = require('gzippo'); // Configuration app.configure(function(){ app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); + app.use(express.compress()); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.cookieParser('my secret string')); @@ -34,7 +36,8 @@ app.configure(function(){ next(); }); app.set('port', 3000); - app.use(express.static(__dirname + '/public')); + //app.use(express.static(__dirname + '/public')); + app.use(gzippo.staticGzip(__dirname + '/public', {contentTypeMatch: /text|javascript|json|svg/})); app.use(app.router); }); diff --git a/node_modules/gzippo/.npmignore b/node_modules/gzippo/.npmignore new file mode 100644 index 0000000..73c7def --- /dev/null +++ b/node_modules/gzippo/.npmignore @@ -0,0 +1,13 @@ +node_modules/* +.DS_STORE +*.swp +*.monitor +nodemon-ignore +.*.sw[a-z] +*.un~i +.DS_Store +Icon? +._* +.Spotlight-V100 +.Trashes +bench/* diff --git a/node_modules/gzippo/.travis.yml b/node_modules/gzippo/.travis.yml new file mode 100644 index 0000000..895dbd3 --- /dev/null +++ b/node_modules/gzippo/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.8 diff --git a/node_modules/gzippo/CHANGELOG b/node_modules/gzippo/CHANGELOG new file mode 100644 index 0000000..ed0b1ae --- /dev/null +++ b/node_modules/gzippo/CHANGELOG @@ -0,0 +1,5 @@ +Changes from version 0.1 to 0.2: + +`clientMaxAge` now defaults to 0. +Zlib Deflate support +Gzippo should now support external stores, gridfs, redis etc... \ No newline at end of file diff --git a/node_modules/gzippo/README.md b/node_modules/gzippo/README.md new file mode 100644 index 0000000..0ff89b5 --- /dev/null +++ b/node_modules/gzippo/README.md @@ -0,0 +1,70 @@ +# gzippo [![Build Status](https://secure.travis-ci.org/tomgco/gzippo.png?branch=master)](https://secure.travis-ci.org/tomgco/gzippo) + +gzippo pronounced `g-zippo` is a gzip middleware for Connect / expressjs using node-compress for better performace, in node 0.6 and up will be using the new zlib api. + +gzippo currently only supports only gzipping static content files however a release is in progress to introduce streaming support. + +## Notice + +Please note that gzippo@0.0.X branch will only be tested for nodejs 0.4, where the soon to be released gzippo@0.1.X will work for node 0.6 + +## Installation + + $ npm install gzippo + +### Usage +#### Static Gzip + +In your express/connect server setup, use as follows: + + var gzippo = require('gzippo'); + + //Replace the static provider with gzippo's + //app.use(express.static(__dirname + '/public')); + app.use(gzippo.staticGzip(__dirname + '/public')); + +Options: + +- `contentTypeMatch` - A regular expression tested against the Content-Type header to determine whether the response should be gzipped or not. The default value is `/text|javascript|json/`. +- `maxAge` - cache-control max-age directive, defaulting to 1 day +- `clientMaxAge` - browser cache-control max-age directive, defaulting to 1 week +- `prefix` - A url prefix. If you want all your static content in a root path such as /resource/. Any url paths not matching will be ignored + +Currently the gzipped version is created and stored in memory. This is not final and was done to get a working version +up and about. + +Gzippo now uses the native Zlib support found in node >= 0.6 + +#### Streaming Gzip + +Starting in Connect 2.X Expressjs has the ability to use a streaming gzip module provided natively by connect. As this 2.X branch is not currently stable I have back ported the compress.js component into gzippo. + + app.use(gzippo.staticGzip(__dirname + '/public')); + app.use(gzippo.compress()); + +This has no caching and is currently unsupported as it will be included in a future connect 1.X release, up until then compress.js will be included in gzippo. + +## License + +(The MIT License) + +Copyright (c) 2011 Tom Gallacher <> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/gzippo/index.js b/node_modules/gzippo/index.js new file mode 100644 index 0000000..3115e5a --- /dev/null +++ b/node_modules/gzippo/index.js @@ -0,0 +1,3 @@ +exports.staticGzip = require('./lib/staticGzip.js'); +exports.compress = require('./lib/compress.js'); +exports.Store = require('./lib/store.js'); \ No newline at end of file diff --git a/node_modules/gzippo/lib/compress.js b/node_modules/gzippo/lib/compress.js new file mode 100644 index 0000000..68d16c4 --- /dev/null +++ b/node_modules/gzippo/lib/compress.js @@ -0,0 +1,139 @@ + +/*! + * 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){ + var type = res.getHeader('Content-Type') || ''; + return type.match(/json|text|javascript/); +}; + +/** + * 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){ + * var type = res.getHeader('Content-Type') || ''; + * return type.match(/json|text|javascript/); + * }; + * + * 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) { + var options = options || {} + , names = Object.keys(exports.methods) + , filter = options.filter || exports.filter; + + return function(req, res, next){ + var accept = req.headers['accept-encoding'] + , write = res.write + , end = res.end + , stream + , method; + + // vary + res.setHeader('Vary', 'Accept-Encoding'); + + // proxy + + res.write = function(chunk, encoding){ + if (!this.headerSent) this._implicitHeader(); + return stream + ? stream.write(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(){ + // 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); + }); + }); + + next(); + }; +} \ No newline at end of file diff --git a/node_modules/gzippo/lib/fileAsset.js b/node_modules/gzippo/lib/fileAsset.js new file mode 100644 index 0000000..0e2d6aa --- /dev/null +++ b/node_modules/gzippo/lib/fileAsset.js @@ -0,0 +1,61 @@ +var FileAsset = module.exports = function FileAsset(name, options) { + options = options || {}; + this._maxAge = options.maxAge || 86400000; + this._mtime = options.mtime || new Date(); + + this._fileName = name; + this._ctime = +Date.now(); + this.fileContents = []; + this.fileContentsLength = 0; +}; + +/** + * Prototype. + */ + +FileAsset.prototype = { + set maxAge(maxAge) { + this._maxAge = maxAge; + }, + + get maxAge() { + return this._maxAge; + }, + + get mtime() { + return this._mtime; + }, + + get isExpired() { + return (this._ctime + this._maxAge) < +Date.now(); + }, + + get name() { + return this._fileName; + }, + + get content() { + // var file = Buffer(this.fileContentsLength); + // var pos = 0; + // for (var i = 0; i < this.fileContents.length; i++) { + // // this.fileContents[i] = this.fileContents[i].toString(); + // // buffer.copy(file, pos); + // // pos += buffer.length; + // } + + return this.fileContents; + }, + + get length() { + return this.fileContentsLength; + }, + + get data() { + return { + expires: this._expires, + mtime: this._mtime, + content: this.content, + length: this.fileContentsLength + }; + } +}; diff --git a/node_modules/gzippo/lib/memory.js b/node_modules/gzippo/lib/memory.js new file mode 100644 index 0000000..0349ef8 --- /dev/null +++ b/node_modules/gzippo/lib/memory.js @@ -0,0 +1,103 @@ + +/*! + * gzippo - MemoryStore + * + * MIT Licensed + */ + +var Store = require('./store'), + util = require('util'); + +/** + * new `MemoryStore`. + * + * @api public + */ + +var MemoryStore = module.exports = function MemoryStore() { + Store.call(this); + this.assets = {}; +}; + +util.inherits(MemoryStore, Store); + +/** + * Attempt to fetch an asset by its filename - `file`. + * + * @param {String} fileName + * @param {Function} cb + * @api public + */ + +MemoryStore.prototype.get = function(fileName, cb) { + var that = this; + process.nextTick(function(){ + var expires, + asset = that.assets[fileName]; + if (asset) { + // expires = (typeof asset.expires === 'string') ? + // +Date.parse(asset.expires) : + // asset.expires; + // if (!expires || +Date.now() < expires) { + cb(null, asset); + // } else { + // that.purgeFile(file, cb); + // } + } else { + cb(); + } + }); +}; + +/** + * + * @param {FileAsset} asset + * @param {Function} cb + * @api public + */ + +MemoryStore.prototype.set = function(asset, cb) { + var that = this; + process.nextTick(function() { + that.assets[asset.name] = asset.data; + if(cb instanceof Function) cb(); + }); +}; + +/** + * purge the cache + * + * @param {Function} cb + * @api public + */ + +MemoryStore.prototype.purge = function(cb){ + this.assets = {}; + if(cb instanceof Function) cb(); +}; + +/** + * purge the an item from thecache + * + * @param {FileAsset} asset + * @param {Function} cb + * @api public + */ + +MemoryStore.prototype.purgeFile = function(asset, cb){ + process.nextTick(function() { + delete this.assets[asset.name]; + if(cb instanceof Function) cb(); + }); +}; + +/** + * Fetch number of cached files. + * + * @param {Function} fn + * @api public + */ + +MemoryStore.prototype.length = function(cb){ + cb(null, Object.keys(this.assets).length); +}; \ No newline at end of file diff --git a/node_modules/gzippo/lib/staticGzip.js b/node_modules/gzippo/lib/staticGzip.js new file mode 100644 index 0000000..43f9dae --- /dev/null +++ b/node_modules/gzippo/lib/staticGzip.js @@ -0,0 +1,289 @@ +/*! + * Tom Gallacher + * + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +// Commented out as I think that connect is avalible from within express... +// try { + // var staticMiddleware = require('connect').static; + +// } catch (e) { +// staticMiddleware = require('express').static; +// } + +var fs = require('fs'), + parse = require('url').parse, + path = require('path'), + zlib = require('zlib'), + MemoryStore = require('./memory'), + StoreStream = require('./storeStream'), + FileAsset = require('./fileAsset'), + send = require('send'), + mime = send.mime + ; + +/** + * Strip `Content-*` headers from `res`. + * + * @param {ServerResponse} res + * @api public + */ + +var removeContentHeaders = function(res){ + Object.keys(res._headers).forEach(function(field){ + if (0 === field.indexOf('content')) { + res.removeHeader(field); + } + }); +}; + +/** + * Supported content-encoding methods. + */ + +var methods = { + gzip: zlib.createGzip, + deflate: zlib.createDeflate +}; + +/** + * Default filter function. + */ + +exports.filter = function(req, res){ + var type = res.getHeader('Content-Type') || ''; + return type.match(/json|text|javascript/); +}; + +/** + * Parse the `req` url with memoization. + * + * @param {ServerRequest} req + * @return {Object} + * @api private + */ + +var parseUrl = function(req){ + var parsed = req._parsedUrl; + if (parsed && parsed.href == req.url) { + return parsed; + } else { + return req._parsedUrl = parse(req.url); + } +}; + +/** + * By default gzip's static's that match the given regular expression /text|javascript|json/ + * and then serves them with Connects static provider, denoted by the given `dirPath`. + * + * Options: + * + * - `maxAge` how long gzippo should cache gziped assets, defaulting to 1 day + * - `clientMaxAge` client cache-control max-age directive, defaulting to 0; 604800000 is one week. + * - `contentTypeMatch` - A regular expression tested against the Content-Type header to determine whether the response + * should be gzipped or not. The default value is `/text|javascript|json/`. + * - `prefix` - A url prefix. If you want all your static content in a root path such as /resource/. Any url paths not matching will be ignored + * + * Examples: + * + * connect.createServer( + * connect.staticGzip(__dirname + '/public/'); + * ); + * + * connect.createServer( + * connect.staticGzip(__dirname + '/public/', {maxAge: 86400000}); + * ); + * + * @param {String} path + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function staticGzip(dirPath, options){ + options = options || {}; + + var maxAge = options.maxAge || 86400000, + contentTypeMatch = options.contentTypeMatch || /text|javascript|json/, + clientMaxAge = options.clientMaxAge || 604800000, + prefix = options.prefix || '', + names = Object.keys(methods), + compressionOptions = options.compression || {}, + store = options.store || new MemoryStore(); + + if (!dirPath) throw new Error('You need to provide the directory to your static content.'); + if (!contentTypeMatch.test) throw new Error('contentTypeMatch: must be a regular expression.'); + + dirPath = path.normalize(dirPath); + + return function(req, res, next) { + var acceptEncoding = req.headers['accept-encoding'] || '', + url, + filename, + contentType, + charset, + method; + + function pass(name) { + send(req, url.substring(prefix.length)) + .maxage(clientMaxAge || 0) + .root(dirPath) + .pipe(res) + ; + } + + function setHeaders(stat, asset) { + res.setHeader('Content-Type', contentType); + res.setHeader('Content-Encoding', method); + res.setHeader('Vary', 'Accept-Encoding'); + // if cache version is avalible then add this. + if (asset) { + // res.setHeader('Content-Length', asset.length); + res.setHeader('ETag', '"' + asset.length + '-' + Number(asset.mtime) + '"'); + res.setHeader('Last-Modified', asset.mtime.toUTCString()); + } + res.setHeader('Date', new Date().toUTCString()); + res.setHeader('Expires', new Date(Date.now() + clientMaxAge).toUTCString()); + res.setHeader('Cache-Control', 'public, max-age=' + (clientMaxAge / 1000)); + } + + // function gzipAndSend(filename, gzipName, mtime) { + // gzippo(filename, charset, function(gzippedData) { + // gzippoCache[gzipName] = { + // 'ctime': Date.now(), + // 'mtime': mtime, + // 'content': gzippedData + // }; + // sendGzipped(gzippoCache[gzipName]); + // }); + // } + + function forbidden(res) { + var body = 'Forbidden'; + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Content-Length', body.length); + res.statusCode = 403; + res.end(body); + } + + if (req.method !== 'GET' && req.method !== 'HEAD') { + return next(); + } + + url = decodeURI(parseUrl(req).pathname); + + // Allow a url path prefix + if (url.substring(0, prefix.length) !== prefix) { + return next(); + } + + filename = path.normalize(path.join(dirPath, url.substring(prefix.length))); + // malicious path + if (0 != filename.indexOf(dirPath)){ + return forbidden(res); + } + + // directory index file support + if (filename.substr(-1) === '/') filename += 'index.html'; + + + contentType = mime.lookup(filename); + charset = mime.charsets.lookup(contentType, 'UTF-8'); + contentType = contentType + (charset ? '; charset=' + charset : ''); + + // default to gzip + if ('*' == acceptEncoding.trim()) method = 'gzip'; + + // compression method + if (!method) { + for (var i = 0, len = names.length; i < len; ++i) { + if (~acceptEncoding.indexOf(names[i])) { + method = names[i]; + break; + } + } + } + + if (!method) return pass(filename); + + fs.stat(filename, function(err, stat) { + + if (err) { + return next(); + } + + if (stat.isDirectory()) { + return next(); + } + + if (!contentTypeMatch.test(contentType)) { + return pass(filename); + } + + // superceeded by if (!method) return; + // if (!~acceptEncoding.indexOf('gzip')) { + // return pass(filename); + // } + + var base = path.basename(filename), + dir = path.dirname(filename), + gzipName = path.join(dir, base + '.gz'); + + var sendGzipped = function(filename) { + var stream = fs.createReadStream(filename); + + req.on('close', stream.destroy.bind(stream)); + + var storeStream = new StoreStream(store, filename, { + mtime: stat.mtime, + maxAge: options.maxAge + }); + + var compressionStream = methods[method](options.compression); + + stream.pipe(compressionStream).pipe(storeStream).pipe(res); + + stream.on('error', function(err){ + if (res.headerSent) { + console.error(err.stack); + req.destroy(); + } else { + next(err); + } + }); + }; + + store.get(decodeURI(filename), function(err, asset) { + setHeaders(stat, asset); + if (err) { + // handle error + + } else if (!asset) { + sendGzipped(decodeURI(filename)); + } else if ((asset.mtime < stat.mtime) || asset.isExpired) { + sendGzipped(decodeURI(filename)); + } + else if (req.headers['if-modified-since'] && asset && + // Optimisation: new Date().getTime is 90% faster that Date.parse() + +stat.mtime <= new Date(req.headers['if-modified-since']).getTime()) { + removeContentHeaders(res); + res.statusCode = 304; + return res.end(); + } + else { + // StoreReadStream to pipe to res. + // console.log("hit: " + filename + " length: " + asset.length); + for (var i = 0; i < asset.content.length; i++) { + res.write(asset.content[i], 'binary'); + } + res.end(); + } + }); + }); + }; +}; diff --git a/node_modules/gzippo/lib/store.js b/node_modules/gzippo/lib/store.js new file mode 100644 index 0000000..2550aff --- /dev/null +++ b/node_modules/gzippo/lib/store.js @@ -0,0 +1,11 @@ +var util = require('util'); + +/* + * gzippo - store + * Copyright(c) 2012 Tom Gallacher + * MIT Licensed + */ + +var Store = module.exports = function Store(options) { + if (!(this instanceof Store)) return new Store(options); +}; diff --git a/node_modules/gzippo/lib/storeStream.js b/node_modules/gzippo/lib/storeStream.js new file mode 100644 index 0000000..96205ad --- /dev/null +++ b/node_modules/gzippo/lib/storeStream.js @@ -0,0 +1,119 @@ +var util = require('util'), + stream = require('stream'), + FileAsset = require('./fileAsset'); + +/* + * gzippo - StoreStream + * Copyright(c) 2012 Tom Gallacher + * MIT Licensed + */ + +var StoreStream = module.exports = function StoreStream(store, fileName, options) { + if (!(this instanceof StoreStream)) return new StoreStream(store, options); + options = options || {}; + + this._queue = []; + this._processing = false; + this._ended = false; + this.readable = true; + this.writable = true; + + this._asset = new FileAsset(fileName, options); + this._store = store; +}; + +util.inherits(StoreStream, stream.Stream); + +StoreStream.prototype.write = function write(chunk, cb) { + if (this._ended) { + return this.emit('error', new Error('Cannot write after end')); + } + + if (arguments.length === 1 && typeof chunk === 'function') { + cb = chunk; + chunk = null; + } + + if (!chunk) { + chunk = null; + } else if (typeof chunk === 'string') { + chunk = new Buffer(chunk); + } else if (!Buffer.isBuffer(chunk)) { + return this.emit('error', new Error('Invalid argument')); + } + + + var empty = this._queue.length === 0; + + this._queue.push([chunk, cb]); + this._process(); + if (!empty) { + this._needDrain = true; + } + return empty; +}; + +StoreStream.prototype.flush = function flush(cb) { + return this.write(cb); +}; + +StoreStream.prototype.end = function end(chunk, cb) { + var self = this; + this._ending = true; + var ret = this.write(chunk, function() { + self.emit('end'); + process.nextTick(function() { + self._store.set(self._asset); + }); + if (cb) cb(); + }); + this._ended = true; + return ret; +}; + +StoreStream.prototype._process = function() { + var self = this; + if (this._processing || this._paused) return; + + if (this._queue.length === 0) { + if (this._needDrain) { + this._needDrain = false; + this.emit('drain'); + } + // nothing to do, waiting for more data at this point. + return; + } + + var req = this._queue.shift(); + var cb = req.pop(); + var chunk = req.pop(); + + if (this._ending && this._queue.length === 0) { + this._flush = true; + } + + if (chunk !== null) { + self.emit('data', chunk); + this._asset.fileContents.push(chunk); + } + + // finished with the chunk. + self._processing = false; + if (cb) cb(); + self._process(); +}; + +StoreStream.prototype.destory = function() { + this._paused = true; + StoreStream.prototype.end.call(this); +}; + +StoreStream.prototype.pause = function() { + this._paused = true; + this.emit('pause'); +}; + +StoreStream.prototype.resume = function() { + this._paused = false; + this._process(); +}; diff --git a/node_modules/gzippo/node_modules/send/.npmignore b/node_modules/gzippo/node_modules/send/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/gzippo/node_modules/send/History.md b/node_modules/gzippo/node_modules/send/History.md new file mode 100644 index 0000000..20c5319 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/History.md @@ -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 diff --git a/node_modules/gzippo/node_modules/send/Makefile b/node_modules/gzippo/node_modules/send/Makefile new file mode 100644 index 0000000..a9dcfd5 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/Makefile @@ -0,0 +1,8 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec \ + --bail + +.PHONY: test \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/Readme.md b/node_modules/gzippo/node_modules/send/Readme.md new file mode 100644 index 0000000..85171a9 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/Readme.md @@ -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 <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/index.js b/node_modules/gzippo/node_modules/send/index.js new file mode 100644 index 0000000..f17158d --- /dev/null +++ b/node_modules/gzippo/node_modules/send/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/send'); \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/lib/send.js b/node_modules/gzippo/node_modules/send/lib/send.js new file mode 100644 index 0000000..de72146 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/lib/send.js @@ -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()); +}; diff --git a/node_modules/gzippo/node_modules/send/lib/utils.js b/node_modules/gzippo/node_modules/send/lib/utils.js new file mode 100644 index 0000000..950e5a2 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/lib/utils.js @@ -0,0 +1,47 @@ + +/** + * Return an ETag in the form of `"-"` + * 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, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +}; \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/.npmignore b/node_modules/gzippo/node_modules/send/node_modules/debug/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/History.md b/node_modules/gzippo/node_modules/send/node_modules/debug/History.md new file mode 100644 index 0000000..f023269 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/History.md @@ -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 diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/Readme.md b/node_modules/gzippo/node_modules/send/node_modules/debug/Readme.md new file mode 100644 index 0000000..15ee501 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/Readme.md @@ -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 <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/component.json b/node_modules/gzippo/node_modules/send/node_modules/debug/component.json new file mode 100644 index 0000000..4ad0971 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/component.json @@ -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": {} +} diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/debug.js b/node_modules/gzippo/node_modules/send/node_modules/debug/debug.js new file mode 100644 index 0000000..e47ba5b --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/debug.js @@ -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); diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/example/app.js b/node_modules/gzippo/node_modules/send/node_modules/debug/example/app.js new file mode 100644 index 0000000..05374d9 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/example/app.js @@ -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'); \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/example/browser.html b/node_modules/gzippo/node_modules/send/node_modules/debug/example/browser.html new file mode 100644 index 0000000..7510eee --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/example/browser.html @@ -0,0 +1,24 @@ + + + debug() + + + + + + + diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/example/wildcards.js b/node_modules/gzippo/node_modules/send/node_modules/debug/example/wildcards.js new file mode 100644 index 0000000..1fdac20 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/example/wildcards.js @@ -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') \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/example/worker.js b/node_modules/gzippo/node_modules/send/node_modules/debug/example/worker.js new file mode 100644 index 0000000..7f6d288 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/example/worker.js @@ -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(); \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/index.js b/node_modules/gzippo/node_modules/send/node_modules/debug/index.js new file mode 100644 index 0000000..e02c13b --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/index.js @@ -0,0 +1,5 @@ +if ('undefined' == typeof window) { + module.exports = require('./lib/debug'); +} else { + module.exports = require('./debug'); +} diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/lib/debug.js b/node_modules/gzippo/node_modules/send/node_modules/debug/lib/debug.js new file mode 100644 index 0000000..0b07aa1 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/lib/debug.js @@ -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; +} diff --git a/node_modules/gzippo/node_modules/send/node_modules/debug/package.json b/node_modules/gzippo/node_modules/send/node_modules/debug/package.json new file mode 100644 index 0000000..79ee14f --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/debug/package.json @@ -0,0 +1,43 @@ +{ + "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" + } + }, + "_id": "debug@0.7.2", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.21", + "_nodeVersion": "v0.6.18", + "_defaultsLoaded": true, + "dist": { + "shasum": "22ebd8ee1bf8378ea8da9c8b27d4e0de4bfc2845" + }, + "_from": "debug@*" +} diff --git a/node_modules/gzippo/node_modules/send/node_modules/fresh/.npmignore b/node_modules/gzippo/node_modules/send/node_modules/fresh/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/fresh/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/gzippo/node_modules/send/node_modules/fresh/Makefile b/node_modules/gzippo/node_modules/send/node_modules/fresh/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/fresh/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/fresh/Readme.md b/node_modules/gzippo/node_modules/send/node_modules/fresh/Readme.md new file mode 100644 index 0000000..273130d --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/fresh/Readme.md @@ -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 +``` \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/fresh/index.js b/node_modules/gzippo/node_modules/send/node_modules/fresh/index.js new file mode 100644 index 0000000..b2f4d41 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/fresh/index.js @@ -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); +} \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/fresh/package.json b/node_modules/gzippo/node_modules/send/node_modules/fresh/package.json new file mode 100644 index 0000000..7cf9eb6 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/fresh/package.json @@ -0,0 +1,29 @@ +{ + "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": "*" + }, + "_id": "fresh@0.1.0", + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.21", + "_nodeVersion": "v0.6.18", + "_defaultsLoaded": true, + "dist": { + "shasum": "7dbe9f8603e489758d42d5a694cae0602fba8ed4" + }, + "_from": "fresh@0.1.0" +} diff --git a/node_modules/gzippo/node_modules/send/node_modules/mime/LICENSE b/node_modules/gzippo/node_modules/send/node_modules/mime/LICENSE new file mode 100644 index 0000000..451fc45 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/gzippo/node_modules/send/node_modules/mime/README.md b/node_modules/gzippo/node_modules/send/node_modules/mime/README.md new file mode 100644 index 0000000..d8b66a8 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/mime/README.md @@ -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. diff --git a/node_modules/gzippo/node_modules/send/node_modules/mime/mime.js b/node_modules/gzippo/node_modules/send/node_modules/mime/mime.js new file mode 100644 index 0000000..1e00585 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/mime/mime.js @@ -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; diff --git a/node_modules/gzippo/node_modules/send/node_modules/mime/package.json b/node_modules/gzippo/node_modules/send/node_modules/mime/package.json new file mode 100644 index 0000000..f12c803 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/mime/package.json @@ -0,0 +1,41 @@ +{ + "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": "git://github.com/broofa/node-mime.git", + "type": "git" + }, + "version": "1.2.6", + "_id": "mime@1.2.6", + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.21", + "_nodeVersion": "v0.6.18", + "_defaultsLoaded": true, + "dist": { + "shasum": "e66b214a4c2f94dc15ce22f0bda388b216bf0370" + }, + "_from": "mime@1.2.6" +} diff --git a/node_modules/gzippo/node_modules/send/node_modules/mime/test.js b/node_modules/gzippo/node_modules/send/node_modules/mime/test.js new file mode 100644 index 0000000..cbad034 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/mime/test.js @@ -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'); diff --git a/node_modules/gzippo/node_modules/send/node_modules/mime/types/mime.types b/node_modules/gzippo/node_modules/send/node_modules/mime/types/mime.types new file mode 100644 index 0000000..b3cae2e --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/mime/types/mime.types @@ -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 . +# +# 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 diff --git a/node_modules/gzippo/node_modules/send/node_modules/mime/types/node.types b/node_modules/gzippo/node_modules/send/node_modules/mime/types/node.types new file mode 100644 index 0000000..b7fe8c0 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/mime/types/node.types @@ -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 diff --git a/node_modules/gzippo/node_modules/send/node_modules/range-parser/.npmignore b/node_modules/gzippo/node_modules/send/node_modules/range-parser/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/range-parser/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/gzippo/node_modules/send/node_modules/range-parser/History.md b/node_modules/gzippo/node_modules/send/node_modules/range-parser/History.md new file mode 100644 index 0000000..82df7b1 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/range-parser/History.md @@ -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` diff --git a/node_modules/gzippo/node_modules/send/node_modules/range-parser/Makefile b/node_modules/gzippo/node_modules/send/node_modules/range-parser/Makefile new file mode 100644 index 0000000..8e8640f --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/range-parser/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --reporter spec \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/range-parser/Readme.md b/node_modules/gzippo/node_modules/send/node_modules/range-parser/Readme.md new file mode 100644 index 0000000..b2a67fe --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/range-parser/Readme.md @@ -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 +``` \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/range-parser/index.js b/node_modules/gzippo/node_modules/send/node_modules/range-parser/index.js new file mode 100644 index 0000000..9b0f7a8 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/range-parser/index.js @@ -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; +}; \ No newline at end of file diff --git a/node_modules/gzippo/node_modules/send/node_modules/range-parser/package.json b/node_modules/gzippo/node_modules/send/node_modules/range-parser/package.json new file mode 100644 index 0000000..73af2a2 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/node_modules/range-parser/package.json @@ -0,0 +1,29 @@ +{ + "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": "*" + }, + "_id": "range-parser@0.0.4", + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.21", + "_nodeVersion": "v0.6.18", + "_defaultsLoaded": true, + "dist": { + "shasum": "aefe40cc8e78149013af07fe2c75ddfcd0ef2a4b" + }, + "_from": "range-parser@0.0.4" +} diff --git a/node_modules/gzippo/node_modules/send/package.json b/node_modules/gzippo/node_modules/send/package.json new file mode 100644 index 0000000..cd05932 --- /dev/null +++ b/node_modules/gzippo/node_modules/send/package.json @@ -0,0 +1,40 @@ +{ + "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", + "_id": "send@0.1.0", + "optionalDependencies": {}, + "engines": { + "node": "*" + }, + "_engineSupported": true, + "_npmVersion": "1.1.21", + "_nodeVersion": "v0.6.18", + "_defaultsLoaded": true, + "_from": "send@*" +} diff --git a/node_modules/gzippo/package.json b/node_modules/gzippo/package.json new file mode 100644 index 0000000..c08b0df --- /dev/null +++ b/node_modules/gzippo/package.json @@ -0,0 +1,44 @@ +{ + "name": "gzippo", + "version": "0.2.0", + "author": { + "name": "Tom Gallacher" + }, + "description": "Gzip middleware for Connect using the native zlib library in node >= 0.6", + "homepage": "http://www.tomg.co/gzippo", + "repository": { + "type": "git", + "url": "git://github.com/tomgco/gzippo.git" + }, + "keywords": [ + "compression", + "gzip", + "compress" + ], + "engines": { + "node": ">= 0.5 < 0.9" + }, + "scripts": { + "test": "mocha" + }, + "main": "./index.js", + "dependencies": { + "send": "*" + }, + "devDependencies": { + "should": "*", + "connect": "~2", + "express": "~3", + "mocha": "*" + }, + "_id": "gzippo@0.2.0", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.21", + "_nodeVersion": "v0.6.18", + "_defaultsLoaded": true, + "dist": { + "shasum": "da568f98101358ca6c3a8297f79102a20c2a309e" + }, + "_from": "gzippo" +} diff --git a/node_modules/gzippo/test/fixtures/index_test/index.html b/node_modules/gzippo/test/fixtures/index_test/index.html new file mode 100644 index 0000000..7309727 --- /dev/null +++ b/node_modules/gzippo/test/fixtures/index_test/index.html @@ -0,0 +1,14 @@ + + + Index Test + +

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+ + \ No newline at end of file diff --git a/node_modules/gzippo/test/fixtures/js/nestedTest.js b/node_modules/gzippo/test/fixtures/js/nestedTest.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/gzippo/test/fixtures/space the final frontier/tomg.co.png b/node_modules/gzippo/test/fixtures/space the final frontier/tomg.co.png new file mode 100644 index 0000000000000000000000000000000000000000..90f3938ec58ccc54faaa408499a24f0a20b02aa8 GIT binary patch literal 1421 zcmV;81#kD*y!rY0 z($dnbtgPbV;sELS+yDRo32;bRa{vGf5&!@T5&_cPe*6Fc0338hSaefwW^{L9a%BKP zWN%_+AVz6&Wp{6KYjYq&Q#En5<2C>Q02OpaSad^jWnpw_Z*Cw|X>DZyGB7VVFEKGS zXsSj400ebOL_t(oh1Hndnxh~LhFu-3;2&+RW2>{fbN@HFY7$5Q`}EnJIoO;`&0u&5 z9|6q9X1DS`vTRYirT#b0O0PDlHvG@h?zRMO1MV>j)Eou+V&?XiIV+Upu;A7KS_kfc zteuVneJS&3Ghu}Q(dd8 z7h;^$kY&=O0^Poa*=4!Y+V$FbB@nYnsnfp?Hu69|m8}3jwkic^zE7bH0zi- z4z!A;J1)}K_k644{mF3efbRVLDw&ad_rWB0tdh1U%9!~~uEqNtV;rblro#gL=(RIj zJNHNK-TmW$d5)z@No*rNrx#YwX{*6NFV?oZ=9ZI0PQtCPX=WRUcQX|01)f^QOhjGG zoC@?JvV#tgwSFX-wba3Gi^x4N7rY$|N(*Lq5;gqL9wD2~H}?lVRMwJvNUgz6bS%=S zIkSdc8Fmo(-H2C{fes9{Y}ZM7?0ESm-2t?mZ&OuQ(4n_@=A82r1?yGtt2GiH=?=xzcx2>Sjiv#47WwSYQt!xiY>ZFwMC%+Hts zF4}xTH`F_O$Q;BKl~=n_?d7b4Ntn~j6zE%-&pf4aAUDpu9gonh^^aMEw>t+je(edvZj=~CUlT8;R$|QkxV5Zqd-T@xJkQ=mIG`ry;y`G=gOTo z__U04Lxzt&BV9d%s}=l~yB#!jD_sU!8yAfEb7jbJICvPUa3?f9gt+s~o3`#U8-e+> z=I}>@7p|E^nrW-t#{zdpk|&`vp9000N?wzvwU3F0pji^3OFVSy{BDf-s7Tu=j(k(c zm5y~~R-V|Ip9IA|)p=_J5`3EZ^aadRIs(%yZB``O8x%gersS4xh1)%)ocTqCB$9yk zqQq-TnXpU1T-rDg))>Rt5|^lb0){^D-ph@7(7w!b z1YN;;{FKmp;?^0iFJ2qJTwe=Mbs;vGD48L%xJ!;oP@fxG78P4xoAGZ2{gu1}8%qy~ z+f`}aey_mIENlAMKyjH=Q0w7~dGb0v!o4yaiJCCd%)V}HG@fmzzHhS4?ft>Mb+e1P bI+6DeuSt@_+vJwK00000NkvXXu0mjf1$4Cp literal 0 HcmV?d00001 diff --git a/node_modules/gzippo/test/fixtures/test.js b/node_modules/gzippo/test/fixtures/test.js new file mode 100644 index 0000000..a6f4e06 --- /dev/null +++ b/node_modules/gzippo/test/fixtures/test.js @@ -0,0 +1 @@ +alert("hello"); \ No newline at end of file diff --git a/node_modules/gzippo/test/fixtures/test.js.gzip b/node_modules/gzippo/test/fixtures/test.js.gzip new file mode 100644 index 0000000000000000000000000000000000000000..7eed1582c07c17c7f9da00b5681c13cd6501634f GIT binary patch literal 35 mcmb2|=3oE=X74kex>^?lPI;U?c{2Rc7B+_N%>ldlfpP${jte>f literal 0 HcmV?d00001 diff --git a/node_modules/gzippo/test/fixtures/tomg.co.png b/node_modules/gzippo/test/fixtures/tomg.co.png new file mode 100644 index 0000000000000000000000000000000000000000..90f3938ec58ccc54faaa408499a24f0a20b02aa8 GIT binary patch literal 1421 zcmV;81#kD*y!rY0 z($dnbtgPbV;sELS+yDRo32;bRa{vGf5&!@T5&_cPe*6Fc0338hSaefwW^{L9a%BKP zWN%_+AVz6&Wp{6KYjYq&Q#En5<2C>Q02OpaSad^jWnpw_Z*Cw|X>DZyGB7VVFEKGS zXsSj400ebOL_t(oh1Hndnxh~LhFu-3;2&+RW2>{fbN@HFY7$5Q`}EnJIoO;`&0u&5 z9|6q9X1DS`vTRYirT#b0O0PDlHvG@h?zRMO1MV>j)Eou+V&?XiIV+Upu;A7KS_kfc zteuVneJS&3Ghu}Q(dd8 z7h;^$kY&=O0^Poa*=4!Y+V$FbB@nYnsnfp?Hu69|m8}3jwkic^zE7bH0zi- z4z!A;J1)}K_k644{mF3efbRVLDw&ad_rWB0tdh1U%9!~~uEqNtV;rblro#gL=(RIj zJNHNK-TmW$d5)z@No*rNrx#YwX{*6NFV?oZ=9ZI0PQtCPX=WRUcQX|01)f^QOhjGG zoC@?JvV#tgwSFX-wba3Gi^x4N7rY$|N(*Lq5;gqL9wD2~H}?lVRMwJvNUgz6bS%=S zIkSdc8Fmo(-H2C{fes9{Y}ZM7?0ESm-2t?mZ&OuQ(4n_@=A82r1?yGtt2GiH=?=xzcx2>Sjiv#47WwSYQt!xiY>ZFwMC%+Hts zF4}xTH`F_O$Q;BKl~=n_?d7b4Ntn~j6zE%-&pf4aAUDpu9gonh^^aMEw>t+je(edvZj=~CUlT8;R$|QkxV5Zqd-T@xJkQ=mIG`ry;y`G=gOTo z__U04Lxzt&BV9d%s}=l~yB#!jD_sU!8yAfEb7jbJICvPUa3?f9gt+s~o3`#U8-e+> z=I}>@7p|E^nrW-t#{zdpk|&`vp9000N?wzvwU3F0pji^3OFVSy{BDf-s7Tu=j(k(c zm5y~~R-V|Ip9IA|)p=_J5`3EZ^aadRIs(%yZB``O8x%gersS4xh1)%)ocTqCB$9yk zqQq-TnXpU1T-rDg))>Rt5|^lb0){^D-ph@7(7w!b z1YN;;{FKmp;?^0iFJ2qJTwe=Mbs;vGD48L%xJ!;oP@fxG78P4xoAGZ2{gu1}8%qy~ z+f`}aey_mIENlAMKyjH=Q0w7~dGb0v!o4yaiJCCd%)V}HG@fmzzHhS4?ft>Mb+e1P bI+6DeuSt@_+vJwK00000NkvXXu0mjf1$4Cp literal 0 HcmV?d00001 diff --git a/node_modules/gzippo/test/fixtures/user.gzip b/node_modules/gzippo/test/fixtures/user.gzip new file mode 100644 index 0000000000000000000000000000000000000000..b7322699428adbc59efacc6934f7229054b4108e GIT binary patch literal 69 zcmb2|=3oE==GD(0g`Dy};~TmuC_wAvd0+oCCp~@6dFTdRV)UA_Tun56TEo**r%!*K X@bs(E=S!ca?#N=C^)TeA15h^rpioltmOAe>Yk*K>=(`w42hPpzNQPU4dwYa7b+mcPU$x?Q;@(F7)QD@!+ zopy8-jT0kxO1NZ+_x}Om*+U3Mld9>H6R8#}x253If-J^tviLZ)Bk~jlLWCzO7xa+G z$Vrdh?Obg{LP8n!=e06x1o>LTBzw0rPi6xGkC_O~nhJ<{)bDE3g{pUNW6q=`$-VO9 zTeD%4S!EU*9(mi900N}sEGYM1nBIvI8aZwX%!k&4cfyL?s9LL-h{Vu0d zoOvD-IL6608=A}#*Y@I~LGXe`6YsYkOCy#;0LKODokR zhlkVE z*tWIVHjlZ+>))riwyQMy+p%AK2>^(+oEKAN}83Ld8&i940&jF+B7;+ zlMx51Zqp=dj*OG=>N2w6ArAaD@hhQb2x>`?qJUcvpkE=!s+BLMxHU|zbFytS&*D@o z*|Go}H3eqdWfTD83OQ3kGDLTUnv)S$!>FZnwQ`}(CC-WZ1btziw#>FJ{k|HK>6&%q zpE+nDvrJF=_-HYBVZ$@~i0L`uc|*;ke;lJrIOnz{Z~9`=EF-Qqb1Wp!=p{!4ggj`F;4bdrY9EB6o zg=46TfVF8v!*wLfqDFqUx%5Y>G;#dQ*ng5eDdBOz1fie?vlTSJ`xL?kv)m4`>PLjX9hnHwvXoMXm;>suun%fkFFiv7#tp5AM6}0 z9L0lIGJPLg)BTj^GIGh3i^ zJKZ9@&t*%LEoPl`C%Z=JUUoa(NPEMNY&M%o*VFy%dUiE^lf@sF(^vT1O%Ku@rJLzG zrLVL3^f28@-%@rXUC+L({+qr#@7Lz=1K^jyUN1H8q`Sv~GoS8Kb{(jlY$m&!#V08J zI$a;9bU!_SdMMw`7P6ZVFLeNa5ggt?)gBb?X1BAM-%z%c-KthjMbc*az0Pl7<1P$Z zFMr?&wU7nx(sCF*WD{d^w*)Trfg^lz2nyG-TUiGLda&;;L_p&@mS(}Idx+j&A|>hbNF~o0*}T7G+d^37ybY;oy2-p< z)SX_EWxvq zd=#?T6SzYBm7^b`6Do4Vv?5nXv(ea6Z4tyL8zufxcWc)%y_bCk=; zP?{%RDCz+A%@&6ee%b7Cw5ewKfQacK)fF7Fiix7op?;6{hxuIghCgGfdCa_QVEjL| z1zMEEiesLH0!zN~EHtrF>!-@Rkfh98G&-`)PqL(dt-$PJLRiPl^ALP2vud7U#0>8d z?eeJPQMs?pW(jN^OYTMhW;OE*_ypC;*#I*Lf(riauc+h^^ZJi)3!4*Be~Tq+7COOs z4qK-tDE}t^n(~MF{rn%4ck}1@Bg((eSMwk8d-)T}zrw}?!t#&#)BIb?pXER0%lTc( zpX4i)e+Qu@%9rvx`Q!3JiKxQEGB004-1>mmRE literal 0 HcmV?d00001 diff --git a/node_modules/gzippo/test/prefexTest.js b/node_modules/gzippo/test/prefexTest.js new file mode 100644 index 0000000..e54bd26 --- /dev/null +++ b/node_modules/gzippo/test/prefexTest.js @@ -0,0 +1,88 @@ + +/** + * Module dependencies. + */ + +var staticProvider, + assert = require('assert'), + should = require('should'), + http = require('http'), + gzippo = require('../'); + +try { + staticProvider = require('connect'); +} catch (e) { + staticProvider = require('express'); +} + +/** + * Path to ./test/fixtures/ + */ + +var fixturesPath = __dirname + '/fixtures'; + +module.exports = { + 'requesting without a prefix succeeds': function() { + var app = staticProvider.createServer( + gzippo.staticGzip(fixturesPath) + ); + + assert.response(app, + { + url: '/user.json', + headers: { + 'Accept-Encoding':"gzip" + } + }, + function(res){ + var gzippedData = res.body; + res.statusCode.should.equal(200); + res.headers.should.have.property('content-type', 'application/json; charset=UTF-8'); + res.headers.should.have.property('content-length', '69'); + res.headers.should.have.property('content-encoding', 'gzip'); + } + ); + }, + 'requesting with a prefix succeeds': function() { + var app = staticProvider.createServer( + gzippo.staticGzip(fixturesPath, { prefix: '/resource' }) + ); + + assert.response(app, + { + url: '/resource/user.json', + headers: { + 'Accept-Encoding':"gzip" + } + }, + function(res){ + var gzippedData = res.body; + res.statusCode.should.equal(200); + res.headers.should.have.property('content-type', 'application/json; charset=UTF-8'); + res.headers.should.have.property('content-length', '69'); + res.headers.should.have.property('content-encoding', 'gzip'); + } + ); + }, + 'requesting with a / prefix succeeds': function() { + var app = staticProvider.createServer( + gzippo.staticGzip(fixturesPath, { prefix: '/'}) + ); + + assert.response(app, + { + url: '/user.json', + headers: { + 'Accept-Encoding':"gzip" + } + }, + function(res){ + var gzippedData = res.body; + res.statusCode.should.equal(200); + res.headers.should.have.property('content-type', 'application/json; charset=UTF-8'); + res.headers.should.have.property('content-length', '69'); + res.headers.should.have.property('content-encoding', 'gzip'); + } + ); + } +}; diff --git a/node_modules/gzippo/test/prefix.test.js b/node_modules/gzippo/test/prefix.test.js new file mode 100644 index 0000000..32dc09f --- /dev/null +++ b/node_modules/gzippo/test/prefix.test.js @@ -0,0 +1,67 @@ +var assert = require('assert') + , http = require('http') + , fs = require('fs') + , connect = require('connect') + , join = require('path').join + , gzippo = require('../') + ; +var fixtures = join(__dirname, 'fixtures') + , port = 32124 + , app + , request + ; + +// read a fixture file synchronously +function file(name) { + return fs.readFileSync(join(fixtures, name)); +} + +describe('gzippo.statisGzip (with prefix)', function() { + + it('should successfully serve a .json file with a path prefix', function(done) { + var app = connect.createServer(); + app.use(gzippo.staticGzip(fixtures, { prefix: '/foo' })); + request = require('./request')({ port: port + 5 }); + + app.listen(port + 5, function() { + request('/foo/user.json', { 'Accept-Encoding': 'gzip' }, + function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + + assert.equal(res.headers['content-type'], 'application/json; charset=UTF-8'); + assert.equal(data.length, '69'); + assert.equal(res.headers['content-encoding'], 'gzip'); + + assert.deepEqual(data, file('user.gzip')); + + done(); + } + ); + }); + }); + + it('should serve files as expected with a / prefix', function(done) { + var app = connect.createServer(); + app.use(gzippo.staticGzip(fixtures, { prefix: '/' })); + request = require('./request')({ port: port + 6}); + + app.listen(port + 6, function() { + request('/user.json', { 'Accept-Encoding': 'gzip' }, + function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + + assert.equal(res.headers['content-type'], 'application/json; charset=UTF-8'); + assert.equal(data.length, '69'); + assert.equal(res.headers['content-encoding'], 'gzip'); + + assert.deepEqual(data, file('user.gzip')); + + done(); + } + ); + }); + }); + +}); diff --git a/node_modules/gzippo/test/request.js b/node_modules/gzippo/test/request.js new file mode 100644 index 0000000..6edd12c --- /dev/null +++ b/node_modules/gzippo/test/request.js @@ -0,0 +1,51 @@ +var http = require('http') + ; + +var port; +// basic request mocking function +module.exports = function (options) { + port = options.port || 32123; + return request; +}; + +var request = function(path, headers, callback) { + var options = { + host: '127.0.0.1', + port: port, + path: path, + headers: headers || {}, + method: 'GET' + }; + + var req = http.request(options, function(res) { + var buffers = [] + , total = 0; + + res.on('data', function(buf) { + buffers.push(buf); + total += buf.length; + }); + + res.on('end', function() { + var data = new Buffer(total) + , offset = 0; + + for (var i = 0; i < buffers.length; i++) { + buffers[i].copy(data, offset); + offset += buffers[i].length; + } + + callback(null, res, data); + }); + + res.on('error', function(err) { + callback(err); + }); + }); + + req.on('error', function(err) { + callback(err); + }); + + req.end(); +}; \ No newline at end of file diff --git a/node_modules/gzippo/test/staticGzipTest.js b/node_modules/gzippo/test/staticGzipTest.js new file mode 100644 index 0000000..9e1a4e7 --- /dev/null +++ b/node_modules/gzippo/test/staticGzipTest.js @@ -0,0 +1,180 @@ + +/** + * Module dependencies. + */ + +var staticProvider, + assert = require('assert'), + should = require('should'), + http = require('http'), + gzippo = require('../'), + crypto = require('crypto'), + fs = require('fs'), + shasum = crypto.createHash('sha1'); + +try { + staticProvider = require('connect'); +} catch (e) { + staticProvider = require('express'); +} + +/** + * Path to ./test/fixtures/ + */ + +var fixturesPath = __dirname + '/fixtures'; + +function getApp() { + return staticProvider.createServer(gzippo.staticGzip(fixturesPath, {clientMaxAge: 604800000})); +} + +module.exports = { + 'requesting gzipped json file succeeds': function() { + assert.response(getApp(), + { + url: '/user.json', + headers: { + 'Accept-Encoding':"gzip" + } + }, + function(res){ + var gzippedData = res.body; + assert.response(getApp(), { url: '/user.gzip' }, function(res) { + assert.equal(gzippedData, res.body, "Data is not gzipped"); + }); + res.statusCode.should.equal(200); + res.headers.should.have.property('content-type', 'application/json; charset=UTF-8'); + // res.headers.should.have.property('content-length', '69'); + res.headers.should.have.property('content-encoding', 'gzip'); + } + ); + }, + 'requesting gzipped js file succeeds': function() { + assert.response(getApp(), + { + url: '/test.js', + headers: { + 'Accept-Encoding':"gzip" + } + }, + function(res){ + var gzippedData = res.body; + assert.response(getApp(), { url: '/test.js.gzip' }, function(res) { + assert.equal(gzippedData, res.body, "Data is not gzipped"); + }); + + res.statusCode.should.equal(200); + res.headers.should.have.property('content-type', 'application/javascript; charset=UTF-8'); + res.headers.should.have.property('content-length', '35'); + res.headers.should.have.property('content-encoding', 'gzip'); + } + ); + }, + 'requesting js file without gzip succeeds': function() { + assert.response(getApp(), + { + url: '/test.js' + }, + function(res){ + var gzippedData = res.body; + + fs.readFile(fixturesPath + '/test.js', function (err, data) { + if (err) throw err; + assert.equal(gzippedData, data, "Data returned does not match file data on filesystem"); + }); + + res.statusCode.should.equal(200); + res.headers.should.have.property('content-length', '15'); + } + ); + }, + 'requesting gzipped utf-8 file succeeds': function() { + assert.response(getApp(), + { + url: '/utf8.txt', + headers: { + 'Accept-Encoding':"gzip" + } + }, + function(res){ + var gzippedData = res.body; + assert.response(getApp(), { url: '/utf8.txt.gz' }, function(res) { + assert.equal(gzippedData, res.body, "Data is not gzipped"); + }); + + res.statusCode.should.equal(200); + res.headers.should.have.property('content-type', 'text/plain; charset=UTF-8'); + res.headers.should.have.property('content-length', '2031'); + res.headers.should.have.property('content-encoding', 'gzip'); + } + ); + }, + 'requesting gzipped utf-8 file returns 304': function() { + assert.response(getApp(), + { + url: '/utf8.txt', + headers: { + 'Accept-Encoding': "gzip" + } + }, + function(res) { + res.statusCode.should.equal(200); + assert.response(getApp(), + { + url: '/utf8.txt', + headers: { + 'Accept-Encoding': "gzip", + 'If-Modified-Since': res.headers['last-modified'] + } + }, + function(res2) { + res2.statusCode.should.equal(304); + } + ); + } + ); + }, + 'requesting gzipped utf-8 file returns 200': function() { + assert.response(getApp(), + { + url: '/utf8.txt', + headers: { + 'Accept-Encoding': "gzip" + } + }, + function(res) { + res.statusCode.should.equal(200); + } + ); + }, + 'ensuring max age is set on resources which are passed to the default static content provider': function() { + assert.response(getApp(), + { + url: '/tomg.co.png' + }, + function(res) { + res.headers.should.have.property('cache-control', 'public, max-age=604800'); + } + ); + }, + 'Ensuring that when viewing a directory a redirect works correctly': function() { + assert.response(getApp(), + { + url: '/js' + }, + function(res) { + res.statusCode.should.not.equal(301); + } + ); + }, + 'ensuring that gzippo works with a space in a static content path': function() { + assert.response(getApp(), + { + url: '/space%20the%20final%20frontier/tomg.co.png' + }, + function(res) { + res.statusCode.should.not.equal(404); + } + ); + } +}; diff --git a/node_modules/gzippo/test/test-static.js b/node_modules/gzippo/test/test-static.js new file mode 100644 index 0000000..61ae164 --- /dev/null +++ b/node_modules/gzippo/test/test-static.js @@ -0,0 +1,203 @@ +var assert = require('assert') + , fs = require('fs') + , express = require('express') + , join = require('path').join + , gzippo = require('../') + ; + +var fixtures = join(__dirname, 'fixtures') + , port = 32123 + , app + , request = require('./request')({ port: port }) + ; + +// builds a `request` callback which asserts that the response's statusCode is +// what we expect +function statusCode(expected, callback) { + return function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, expected); + + callback(); + }; +} + + +// read a fixture file synchronously +function file(name) { + return fs.readFileSync(join(fixtures, name)); +} + + +describe('gzippo.staticGzip', function() { + + app = express(); + app.use(gzippo.staticGzip(fixtures)); + app.use(app.router); + app.listen(port); + + // set up a new server for each test + // beforeEach(function(done) { + // }); + + // afterEach(function() { + // app.exit(); + // }); + + + it('should gzip static .json file', function(done) { + request('/user.json', { 'Accept-Encoding': 'gzip' }, + function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + assert.equal(res.headers['content-type'], 'application/json; charset=UTF-8'); + assert.equal(data.length, '69'); + assert.equal(res.headers['content-encoding'], 'gzip'); + + assert.deepEqual(data, file('user.gzip')); + + done(); + } + ); + }); + + // it('should get a route', function(done) { + // request('/', { }, + // function(err, res, data) { + // console.log(data.toString()); + // if (err) throw err; + // assert.equal(res.statusCode, 200); + + // assert.deepEqual(data, 'ok'); + + // done(); + // } + // ); + // }); + + it('should gzip static .js file', function(done) { + request('/test.js', { 'Accept-Encoding': 'gzip' }, + function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + + assert.equal(res.headers['content-type'], 'application/javascript; charset=UTF-8'); + assert.equal(data.length, '35'); + assert.equal(res.headers['content-encoding'], 'gzip'); + + assert.deepEqual(data, file('test.js.gzip')); + + done(); + } + ); + }); + + + it('should serve a .js file uncompressed when the accept-encoding header has not been set', function(done) { + request('/test.js', {}, function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + assert.equal(data.length, '15'); + assert.deepEqual(data, file('test.js')); + + done(); + }); + }); + + + it('should successfully gzip a utf-8 file', function(done) { + request('/utf8.txt', { 'Accept-Encoding': 'gzip' }, + function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + + assert.equal(res.headers['content-type'], 'text/plain; charset=UTF-8'); + assert.equal(data.length, '2031'); + assert.equal(res.headers['content-encoding'], 'gzip'); + + assert.deepEqual(data, file('utf8.txt.gz')); + + done(); + } + ); + }); + + + it('should cache a previously gzipped utf-8 file (and respond with a 304 Not Modified)', function(done) { + request('/utf8.txt', { 'Accept-Encoding': 'gzip' }, + function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + + var headers = { + 'Accept-Encoding': 'gzip', + 'If-Modified-Since': res.headers['last-modified'] + }; + + request('/utf8.txt', headers, statusCode(304, done)); + } + ); + }); + + + it('should set max age resources which are passed to the default static content provider', function(done) { + request('/tomg.co.png', {}, + function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + assert.notEqual(res.headers['cache-control'].indexOf('max-age=604800'), -1); + + done(); + } + ); + }); + + + it('should allow normal traversal', function(done) { + request('/nom/../tomg.co.png', {}, + function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + assert.deepEqual(data, file('tomg.co.png')); + + done(); + } + ); + }); + + it('should redirect on directories', function(done) { + request('/js', {}, statusCode(301, done)); + }); + + it('should work for paths containing URI-encoded spaces', function(done) { + request('/space%20the%20final%20frontier/tomg.co.png', { 'Accept-Encoding': 'gzip' }, statusCode(200, done)); + }); + + + it('should not let the user access files outside of the static directory (urlencoded)', function(done) { + request('/../test-static.js', { 'Accept-Encoding': 'gzip' }, statusCode(403, done)); + }); + + + it('should not let the user access files outside of the static directory', function(done) { + request('/%2e%2e/test-static.js', { 'Accept-Encoding': 'gzip' }, statusCode(403, done)); + }); + + it('should not let the user access files from root of file system', function(done) { + request('/etc/password', { 'Accept-Encoding': 'gzip' }, statusCode(404, done)); + }); + + + it('should serve index.html for directories (if found)', function(done) { + request('/index_test/', { 'Accept-Encoding': 'gzip' }, + function(err, res, data) { + if (err) throw err; + assert.equal(res.statusCode, 200); + // assert.equal(res.headers['content-length'], '616'); + + done(); + } + ); + }); + +}); \ No newline at end of file diff --git a/public/images/BlankBody.js b/public/images/BlankBody.js new file mode 100644 index 0000000..89efa60 --- /dev/null +++ b/public/images/BlankBody.js @@ -0,0 +1,1230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/BlankBody.svgz b/public/images/BlankBody.svgz new file mode 100644 index 0000000000000000000000000000000000000000..e424d610a9721000f58a20f6e65d3e58e617f824 GIT binary patch literal 43392 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 z zj*_u38FhwcJ2K!-xq@z^0Agq|^;Iwr;=ze;2-ZNbHSuP9)DsPIVd1MB(CE~6I#03b zWqz5HeVtNyoOi*vJL8#zxGJZsV%wZdP&BFxqGg*_SfTUdJ-a0CuI&cG2j@mlI`L*6LzB&tLJ&MpYz@9pu;tIBA;)yopmG>zN<#yRJ zvp?6Vx<$jC-^q(Z*)Sj^b$hGpm(ktCpx^^BhOfG-gg{ zS0_{w+;RI-!TlG3h{9a2b#|qyHhR#pxyx3C>zo*C*zbMMa}n*F+wH6sj4KcV9fyly zJ70xJc2MTT9sWdUn^JU+q=O`l5ooDh!a{0mLr{Ao3Jrapu6|yqr1pXU_O*WDt*1qa zuHHS-{0KZs$!?iYt{QQYs2IhKE2n$l4^B{*h?0)zGRLIDaunde-DIN}b>__4)elsV zb(6$cWK%hRiY`!jX2K11sur%P$#V{;nm8N9K6}gbD!)KSI%ayS!pi{Fw@PX!9LyKf(@z?Wlo%@!?xoF?tCO_e9z6)1%2LpfvIa@8 z)bXSd)bAfC&K))UHB92lEvWW9Kd?jjBsk_ib11PxU)$`avxj)crr_I|f7AdWmUSfuWx{BMdDE%w{ioOv|W_YBxJ{emtBbWw&qS zU3!~T&~d1Pfu)C1*VUKnsfn?ybDW7WPRXXgmzmxjJ6tZD>Ow;8<%YLahO6x~Gbqw#x0rSC;_xxl7dvvoqPi=A1hSkDy7 zw=EVCQKAD9sRQlImx>N^!_-wuI%THqAqfmV;0R>vA1M#*L>Q(3UL znxwcr?-jIWV%Av3I!iz~3gc9Roy{6C^6csfWxtw3U3b(j(d9a6gLhu};3 zB-1TiBxFFE?RoT-nWd8IcR(WVbw_zpqUK)kGCNNUo&CLL_&KV`&!iFU6kjUh`aJ&^ zgN!mY`9Xl>@}lJLGS*Y=SpgX4r8-0az3g(%GhsVS8PBm4N|@X1zdKM_b(WZy7DH>p z0R|A|t7#@=&+lSl)A{Nh_L?S>gX|f?i7GFxA2UNIUbRL+n(0a8 zNy$EJL7=KheGXlg<5{a!u0-jjLC&siSg;MZYn?`Bd1Ygk+s0%NntD}S6@O>}x!yMI zG|s`I8fMyDq&q!D#TFr{XtbTODj3n_HlocC5iW;Q%c_&NA`q!1Wvq-18r)$8{FciyCKxy)2=yxW_qu-JiV7?wF7ULGt*5OwYxN(#e(yXs?_c&ww+MQoVZJ=fq@G%{~V;x4$ zm50W-XRp$u`m2u^llA1cCHHHYe88mLB!zc_XiaB|fgysk@ecq`j$5OZPBx%MjnoPiDSgs><@ z`(%zPS=ksaAiKypT%$N-_Q>+c{D_evv8ap`hdao5OVmd{WO=(OVRaZI)10_r&361U z(nDudhwR9VB0`4RS9DKr2R5O{TXrhxgJDK3?aCp8is98!L^>m~CHTKCg5cj$tAWqM z6g}WP)?%aAIVG)IHZGHP;KkUmr|gRxX`PcSExXe0wCNkza1PzvWck~IQpbu3uULU)wfAXG3_lZ9kU6da zf(n0HbKjoUDCs^uKZyiD{c8D+~22iEM^N;ySg{5X;fOqW~iD7M_OFd}@^6x5Jw0cu;tn6(f?vET}189LiNs z=jAEkP+;OX;|DDcbxc7Utami@Mrzj7!lK`0MIFmBNfC!b@*vn>%lnb6YprO+1S{y6 zI(jrnykQCb=evJ6%$4>dsvCD<_F;8sP5s(K=*f0dNy45tXE4gI(u[?^06I9fT_ zWz@BV#H9$o)Y))Hr$gCsuHKi71__1&k`Ez8` z%A~t?rt<9ldL%LbkS*aL`J`t`Fy;bw3Jc91CK*q=%p?R}NOV3Pkjg{9ILN?<>PmY+ zt=sbEDPK>0#3Sj$_#`Kc@{D(%H{1JEZ)l}bC7)Ej=Qc+J30aAdo_*r?p_ARB$R>efG$HN!{d^chm!%YMRi=$N?1_h*o zc%MUoQUH!|8BXesygk%%W}m?=074-C)Om;3pbYnP1vaTLhDeeg7fN9Ot|O6SkbbnUEQ zSrXc2@K295S`aE25$uFM$If;LkNQwgHp*Lwm{HhTv+M1pPHyaqdc3=It-J+r`AqwM zI4cCzyh4q1Wfb(uoHD;GZXbD?C9{0$t`8gSBd=~%*qaqPm7v<5SG=Q9Ke5tNw|deK zXgf@WU{;kT%fx0@Hses^W1;P^@#ZwuHEX+gEUD`$!kt0*Yzire{$O|8?pHnXtDGV1 zI7p?Uf}_bGi+!V8<>O@y0;Fo_fQ4;{z+j8Xl*_$ttYNS#mwn7L5Eo(xWQN}MEt{+p zq_2v&q|D|bCR0-NZ-XBR_p0WEG`mDm4=SFna6{J)&m*Utgwp_u3LylN@I;_PD_vNv zn%kLN6t9!&LU`*z#%T167?s6WET+$hOQ!**oRgxm_Zqto^H!FRMVFpNqNJ!p+iWAm z#ta6bJ=c4I(s9sq#A#Y$vlfqfoO!vhwM{FY|V}_DXE>_Ze>N}Ywtt71sZcK4{RCG zD(fM3U5k@0oaXzu7n6jzTik~{@0i_S>YPIrNd-ExG{BA!$z#xOX5-EEi<3FowKQ;r%3H}66d~|y3R)GMOBdlcI<@GImP=u zAhW9;P=&Edh6u57lCtZ=BxT{lZhBR=--~DIk`y(N-EGJ}dp6eWSyD?-WVDM!g2FF?WW~KWBIFxVo%+MFGkj8TWXCDQ0{L8fzJ6 z(zd|iS!jSOX^9UYf+P9Y^3qGBDXBld*^KK*xbtIYq*Fwzq3G5teI-|X8ri`c|MQ>M zmtFy@TorF1rc0}u8N_OVnaNW zZe4qO9>2$$jgK0~ee3rw(@3>FC!8-LmjO8t9KAikn&4sS=S%5;90;nZ%r#aL$t9X5|`=j_{-L$5QzvZOXL4W{-v;S{xHh!;lA>U8pe~-sxoxaNKPkuV!;elY!okYJsvR0h|Q@H9E|e3JCUTQ?(Pa$ z@!~I1*LTbElZgyey?H1s6Et6QWD2^xRuwxF2ppI9ObLW{^ia#1Ltp00uVJwPbi-nc zPOHd*LydJM{R|C>y^$qdA!cyZ-#p^$k^h!TfmZB?5-GR?%pXXj;AQM zi{D+Uk=_6MWg62ke-BEHuE-xyX?#XsxUBCY)M&Zl4~R70_WAqJY2>Q@fJWo}h4JU# zMW&JW{9cL1*QB2BpwdWm@cR`Sb4Pv;B8@;me@LJ)Go9~KqtTw6KcLSz*Y5j}Xe8SF z1M-aXFnk{hja<_oP-jd>_uT~=U)Db?&X@q>ch+Y#NB;xbjA_NbUwOuNza?X?mH6RQ z%wHap-}eKFm}hSIoE=<2jkotrn$Q_SJb+?gMGzR=5z#D9qKLSb)y!0AH1?}r*L^heAVdiVclob}5D9e=24 z*00|8LkzRF`tw80vVK{Az){wKne6xK8XcAexO0t7_vWp2=#XyKz-u^zkdex z_cwp~HY&e=1htUHcOE}|)5?GU1nTd9`n0RLLz^l`tPnPeP1SEI#nb~Lo;|UoD}8x# zq?y>$9hyAo2N;fXl=tN1+m^C;u(eAvYbN|6Z&PJtQE{^jwM>#Kj~P6wMFv814B3e> z=yL8u)31V96ey&P#-jkTLc(^NU)VsvtS(1iZzKsU(Gl)lzFDKoqH4~fTd;%YME#`@ zt&%M$8Krn2LVy;aI;+v9G?MPwm=-(G0f37=i>ee1`ZA4bB7YdEO18%*#v+O!!Un-b zLnzvfXL}r@R2Sd@t9V24VbhrJSkpY)>oij2Kxh zMVar3#yByOYO7PE)LfBhGpcju?6f5t-W0M}CWNz_qS@1{f`s#B-MbPIS5--0(DXpg|>2e zs#m3`0%wVbk+jj=k$wUpjS@c0>?9d)G@9#;$xpkW0Vn=ER4q{T#`J`Tr+Nh~A5PYt zbav}9l3C;c+0UI)&R0eq$xq1=)=XCbD*lAcxIGnrfDh>II-WH>uCRR!8J(3rU&G_ z`&Bsk$?PE?qJ*|9yx}+?&^m!XtjG?;b8fcJC9w;44mYV$hhe=dB1v^3$ZnK16%?s= znRn8yBUP3lPptW3EP8{M?m6V!?$Gefdffg-tNtBJovA1loU0z}c;m%7<2sID)B zyUm7MC0)r8_u~#3Bw#1Rw9fgV%MDK8Z@RluA8Fr(k_pz76{_^yx0hMdRt!j?#zOph zWL2-|W>rQZZO)|;0LVPMVG|D3Ygs^>^dq=Y4W8bJel+mLs z+M5kM2TfSZ+xRT#bcaI3+a6VO4;h6Z%uloi9yAM*+(fi;-f5nrq=%Y`NMk6Va}q%m zrTGnrl0+o1}mDOqcU}G4Ml0SQUvPl7F~?!OPA(+jcw}S zl_WSP?kt~?$XQVxRk0k9fq}ZePDRI6c9rTLMNYS+rhe181SPBw9mT|t>`cahI;Cor zLG?WBst7bELaRx+8@L}H!j34|IcdxX+3-VXc*}toM?~X1wd%a<876zMG^Om1-2u1+ zl=V*aL}v7-CqUq)Mi0Efnyvfli5d|oiAbhyQ@~;I$T6O#6_x&!jYz&@lJ{+X<6z8v zrKY5+Us9`Vmen&6KaKm)CQphi# zp=(;|)Wj-?StcNlQQF0jn7(U&*g6R2W?RgfxhMv3I0(Xn02yDWCY_}SrIyqJV4Y6Iv$v1^pf|2;(OkYS*N^C< zY{E@%T}e{og1UNr^+t_DCl6i1&iNi2ILYKSa?tU!2lRano+Qm?*pFXm8E^`P2o@^M zsFnlfK1GJ(LGy84DgDQ6bziYf`L&_eHJ%Boe4;c#DMdm6A?IYL3u*0EE{Hm-xKIdj z^qCS#sE7R#rL#!e90kLEP#&No{}$@Hq3jt|tIe70=t^GRKFS~Jdjf}WqIP9*_en+9 zdFkbxD5UOJ$z~p|SsjB@*%cBn;Z46UA||?lV=ASZ(<_D6oz)S8)IbL6iixIGPz`!93dDpw_Lcmrd;M{nN?S=xh<;?y zhH+nj+68U8`>M2+I@_ky#1eJ^L}zbzaBU;}LS!pSPVr^PhgvQ>S36|U57mV4#j9rH z-JZ$fg_zj(#Ld_=;G zbx*F)rb!17t(k(bPnLV1$Q?b8JCNT+hK8~%+dKe<$QIUZwL9~5>|WfKbBjarG+5Q= zW2%$H)_=_M-P&fa4kXfP^5v#y*Rcdb=1m1=$V~2MbHYWb&GBO`Wwb^Tfi854Rjh})Z`PSq{7o%9z zim|!j;n^L~00#;}d|k@ zs#?k_urUl|IYw(%JoE@MSin3*rO8tI1 zd_44j6InkX#NN33n+3cU^o+WGWOyM#H(Mj<{>lm|Qo;g-;h%vs9tLjL>xV7EGXh@; z9TOC(^5?LWJ2fTBVTiy!@f9=Nq3A9-coRdg=|}Iae{iAHJHreJ4v6`z#8PE5Q}#32 zZ0goT8`5MZSnlPF|A4wj_I@)6b#1qq!k7PN+>*TAkwrYbIxoC2zLacqJpP*c1E%AD`&onw7!C5tk>9xZE(}_Nw{Qjt8Kl zQ)mR;^-aSIWW&{%RRV>c83+R3px0T7vaJXUM?~Kyq_?a&??G;&K)YS#1=>=xPY8GA z_(s4Nn?Dn-jbI{=YFveC05o`>hXrwIoOZWSyucyWp^TNJOjJ?#`5pp_W!6*G@<|-} zaijL#mH}%4KmmlZ328gjQeo#;6JY!+pm8vE-a5qCwQPy8Kb{zS%Xl;Kda#0t*JJS} zhJ02FD~Rxz9nnd&DKMIopMs_*_dDtgsF&$P)@)14iqG<@ z;xjP39i%Y`WZ|}()uYEvaXtt3A7cqY*$lO~fJA z{vNYVT^%r`<{QdAQDvPqL`{^4O@vbLzM_Bnbu}{Eoh;}umeQFiCxLWUHp_O4U0KXJ zrjfrZr1~lgJ@j+3T}E+uMolNXI&_H?CQ8@ig9ClXBMY~YzDZz|N?<8&)zxCOHX9Bo zh;>M9ieLmR5|42*fE<@1f147It;;76eLrYA64F-8m;I?wofIGN(^Z8E1$j9I1P@wD8|GSv#1QQPc)q&&ajoTo09QR1_K6 zgk$EfXLhKYq)hjrllTTO+BOOOI3UZbZYM|9TC|!O!K%x3N{>Klb}U=xvR_v%Zn7R$ zY=CU8uqOrfyN^Fxp(#~SMu?$06bRD4Wj4LcuCapf#j5C9&F-{i&3??m<2=?QSzNPd zv8RH(EkVWB3OpoIwKsT#1d$c_g1E07)6xxa`G$NQzP2?ORu4L)JbaoD;|3^qoa_K-m=0^P59A&qtE`A7^B@{Gmc__H%n%&<%o#w3s5$q82_*wL;cDLj`O5{(nH zW&Ni)4A~m!%i%?s8O6;%P(;IZGWb$N8%6ns;Z;_mDYT@9B1u zBRyH}mmDN(o7pWmz7yg&Vm;_kIRQea~S`D2n}QrOK5Q*O6_SnQcM%8I}YS2+6VLGt%h@9wCn0ZmAY7z?G z1{D$R!D@ZEX~)eGHoG9S~g}f=WehOi;h3no|y=TB?H`Ew}5yn_3FTpmR=QP$Yfm9YL%`>nt3fQ-nv;Q4)Kqqa?XusSMziK9%mmm0Tr4`MIAvq= z$7_QIhu{qG@;dbc$no63mEUaMfVehDCg*BoQ_|4v_QPxxAUC=jVsrKR=v1USi5b_N zO{KKFrIj%WeKK@>eo2CX6J~U%Byi4B#zB~p>qTZFX}v{J7usfv4~o_7I-%7>Il1Zb zZ0tB7lgg;Q+7(MQY7JJgAg*X;K$2CQm8BqY7bWAX(P_2TZ^TAf#LkSGDQ|yrvBY<5 z>pC42=Qx-txV>4RsoACdxVtJG5mwa{xBXN>sfTjSoUsQ6^5eNP#Nx1l@A@f91=muC z(|WVQTClT|c^{E`peluU)k%j?jKe8P%h5FRuxUo)-XF7MtkREiN<%|Ja>31PPC8JS znFg=N-NjRwQ>HX%Oj9T781w@vYfxV5hwR#p?7J|%1Es1f|A2Ad!s0-~?Wd&9;58S! zlaM*P<1=U$iXS_U?@R@u*x1qNgqK8y6*CvuawGDH_ybYZ@iEZi^SaY)5(>tBNX2IZ z(d&oluPCr8Zcr%xO+?{wSi|9&>iCuty zQS6&#ef+#YErv;IZVs+x3+GfOP-x5!Ga~JO4kPO9F)>#AvkqF~2F0W7cdIq^1#Xxm4WC$EpX)(+j+)tftMXkFf}U#{tO3>b~btXr`pieVPY zJC#6n5Tifq?s9eb%&A6GW%Syx<`wLLqfjxYV`5m8Y_WkQo`rtcF=q!(_h1~Mbe7$r zhq}Yt6Pxc+TH#D6ebs2iKOO%qTGA|`9ttdE3kA4ZHX<+U?8$!28891jLN(ZqfFaw- z$L@r_o*?;@>6TSwI=+hj6D^T+E~i>Q+x-aJnw|YbFn0pyB5!Se zPvNO6kGD<;l4sjQq!JOrbUX6gLb8*>QoI0oVu}|4C*MSWXFiCbS+Y=EYEJ=QEv~n0 z2bhkVV`{NfOJ|M830;{b2|2P?d%uMq9_y|1Fe^mnm{aGWh*Z3iH*q`phhHM1$U zm{Zpw!t70Tj)&?T+*LM@Kjt}bUdYIy0T#U&@WS>KVR80#rMKZO96LzXa58l_9}`7M zI>AulfQhAr(Zc0W@$S)+ys*NR6rn{eGqo9_ovXHq93EDho(*}DH1-sEP>}YSB^_eJ z*()pQBdKD`WT>8v$?mDf6<}YV1hC{_E)>@|TTm-neaw#i6x_&>1gvba1(owxm4w=I zJxVf*8zhk=beyws(IVuW5yP|!h!RLVsYcN3=UXNR@ie1CfcV_X$M7~G>VEBY2f4)0 zK}-oMT#O%i>y4(1YR&*th{h4$OkIfe?~>{ugpPs|D7m=8MO-pF)PruD#F6t=wv6N+ z=4T}*-9i3uqrKWdH(2hZNH*a>_h1V0V4%8?uXElVQotV{O13*@Q$I;iG)PR>K!x^O zqDn=gCcA-SEx}+2FXhO1`RmS_RJEE@-*U3JB;;39v9e12(71ycOqBMvk4avD>bH^Z zs-`4Ao_*_aU$ZwAE-Xa%Bm2&v3_CiP5_P4yEOo_-{5~?yiUVuOERLvoN=2>DYB2yt z&XwPIJ(6R-<~+rR@z!*Tc=zLOifM8>pclbXux0V+P--Z{S?dttiuu;q2BtjNXKY4T zN774!YqB4TaxFOqjwAoH}>y;zW?OE{^_6m`7b{G=4bEz$LC*s z@#FXZ~AgTWIxdQUc1yY*H=R3c_3&z;rM zhN-Of!#UI`y=N#&yb*Gle8=~eM@zJ%>aa}%>mPdJ9EG^ zZ&N}viTj!Ou5(Z|UfZ4pgo>wtXs|6|&IFqypskyM2j5Jxt_1NIYqFzm8F0P&1e95{`)Pnosbbqxb|74$8- z$dO|(3aq(;7)50a%5!9SPI%ZDU0)F|-IyW1qt{++vDcMb#v3`6J-&j#LkP{%tO08; z_u^$s*RAcIH`Y>{G>%28T*Q_8S*aSB3Y{1Xg>x9xmm}hh91i&cy8tC%mpEv^S$Bk^s50*x?J}am5Ess}k@%6vd zEtysrSif+2^@Ypx3wJcJZO=xO#CfM7rr(h?;U4lexXYd0TJSI-CJoLoh!)H%x;Ejh0`^_zeJoCqLs{gm{t`fxncos3}6 zKxbp}b2uG66Iu>BfklyLrg zHcQ3)91Jh!o76>3O>Z?`rjGq#iFbKA0Ta!10wkJuh2@pJXKi0V4LCPBE&fB9cE!(9K_*t>fz9|5giT1E^x74HA8utO8Akm zU9R^FJ~u}GZb$!OW%k$q*WS78NOELndffu}4h62=d(6!3y3j%@jb;{H2|a6pisrP4 zNs$ebt(kfIiSvKQ%pJ4rAN4%9Xpr*Qtcu70f;6?1q?C`k1d?4 zAtA$cl$0y&JHgu`C;@FvtV^;WaM_i#WbZi888qzcQJ3Mn2?UK%fzw$ImE0lQAVg~m1gBNfPdhLVgvBZ0(XOvYcZ?=C5REQW z6t0djdgl>hJHO$)H+h-RT8c~cnAvVBhmGS8Q|i6>Si&#V?>Ii zB$-1SoPw#Y`$y8~=?#J`-mY}IEzeEUTM2JO4zdL@NTfp3=gK;xTH6KK(3*%oD?^+al8`d>JrtfXiHPr3hl6P==(J>DOHmX}+FhO#M<}FMY zcUN1Jq4*+$YHIMOMvU$aj(x8VMhK=*-Tb4a*#k}{)6#{}i7 zrpVBMzpDlrBk4e#5wa+w=}?=6e?zH!98%=N(%Ogy*+-+-y|7^(1+mwxIwMv_a$;fx zQ#JQdW6ZGeR_=SGtT?@ijeF=KQP{Sg%&AzTAEY8PCXN1AqpzT8Lki-&1^2?#Opgwt zwDKl+&qdY?EdX3Jr{oOYsQXH;j<)h|H%uu=N^nCfV-flVIIIw_MIZLt*_9`ciYgnN zob1zJ>n#9$a>to{&bRtNd~sXmv6S*)z}vt_0bf1+{d|(=l<&zowu79O4icIRsh@)y zZ_Pn=)1U^qc=&^;L>+4N;(eGHL`Yp|x?K|rmlM^3 z(536=YWB%yJ2sLJfv2T3wJrkcU*m@J{oIeAJ!;GAp^ z+17AzrmH(A2Qle`!{}={K{$-CuUVe--&BaIUK67@xs0hG*2uu4pT=`6Vhd9C*qMB5 z4UJAh=wRgpwhWL)$I6&ZF-YpyW;sySnmi~Q-G7)HT5Ti(|$-tR!R{l-Rn zUpCs-zfA&%1F|We>REQyXIhNuA^^8-k?irjk1UD_ufDlQgkFhqQvZgj@RGEldma3cCjK(lQyN*;w;m}8k zctl4st&8LFIpC^VOvnl&05MzqCDSQa?32H8LEx^==@%YW^NX{~f-6)BP|%di zOp*xZJVo3fGz1vAA83gRj2>JI91X4Qyp|3FuBG`$g-0V%;p9XiRb^8>qNuZdxD}HQ zj-opty|yBo@+OiBc#k6G*q|~t%c-dp05bY2$~MdbRCYe9-8VguIVwE4_8du+0)y5% zKu)B3fDnOO$J_xY4Rh>?sv0C{VcA}=lZ+0sn1xH}I7&;exKe*qqo@vFzqE=}v;s%u zD3MY_bIV`OLKHN#H-ejT>P$zV#<~)1trNR*qHf!%o6d?JKPpF%gvDvg% z#oFR^Tfsu7^$Zqx->z~i`k&vuqxXCK;R`7pZy{{~_;2?zfa>5(L_A&Zaa$&RPa2Lx zl9b~Fvq~L-fi`q#&%z}voZ8tOsX!V#{A6e+ct}Qq{T7@FSap2SFdU6SMG>rc(rsf2 zogEwHx6Tem_nbm$J5M3nHJn1Uce+k3XgOlx#d*E>`(yTdqO;b^d1vt@aRoZvR5Z)s zY*MzPnLFLVXFEPJTF}Xh$}H&+R;i5=m0~Q+skSg~-k4X|)`G7U{0s=OjLn9+>6LLH z;`MGeNJmM7W?%9>I#@+Pnh z`tMz?hfVq`P4YNPZ@g#7#~K@Cp;H)vNR}o!@>X|{d%D9!2#^XbBb0?1{5luIg!2oM zZ;o;B2mlEVN)$341iFOZiq4b-Gw=}czmx3lGuh3$%Tw{hMl(sPGNTHsae#nb{DL5weW+}mnuyTNS zhlWh~SSdts^%~kd{UF)X7@gAtoQiK2J$>p!1k`2%p>|_-D(Vh@qM)w|p|!x=&^87L z*%1^!_F0Bi5d}s$oG`PVKPbw+gj4^=ol4Y1lJw zWG5=d{Z8U>NM)ZiFY?OX27q-f+~gY32xxfjFxvx1N8bzc6h)GD^K$l8*ZG;~Jkf89 zpnR*T=&ZD;NQOnQPiuGB;-uTrB6v3UjJNY%62#U#QrBdS!8Gz#$CX*yR5gHz4%z*PllT(#`OHYkyxzr6FK{e(g) zT|f6y*@HW#0EKV~>b_#6SE<;SD@T#+Y|PF;a_s4Lwi%&(63MsKW#j}#lMfN8fhLTG zRo7Et61BwAtQsw2JT-)DZV_L&3($DHl%ZHfL1C4G_uE-o@ZY0Tgre(ukdgr-jV!an zml^$j4XQULC`leCl69b2MC%LaZ=4i9Yzo| z`ek+n!L;b_sk&$^%GrWc?M!4*G=V*b#8LEF8rn0UV6z(`2iG6#&H~KnooYRZSag8c zZx+<+Vjm!T1b@FW`+AA9z2=RZblO0KiOy4ZG?DpkbB;wCTj`f#T3H?GvdwrAG^t@_ z;N9pxzS>b*o|@3PJs49aHJf#cG8c2(Y-Q&TGtQTp`G)9I|84cXt81e8)mjB6D87Qd zx1q7(Wz94~rh-T#9P8^J&WhLk7GR^|yX$P~gB)u^04_v)J)Z9n zJH+9VucY?3tNV$lJ+11fK@n%EY<4pSRD4B5qVhi#rOO%>B9 zieMzf+zsk3iW-GtS<@XDqB7frvzaW(`g)RSLx|n-kJWPPQMrmDi(&$h56;Srv-ecHX>oE^jq!WZP6H$# zA9zTU-sJH`T_1Y-(IP@mt{%2&J6~k=A*-t6P%yCasIQk67J@PiiCE$eF?e-k>DRT)rQx~OV& zC#io_umT>5lThS1eYMl@EdfY^7`0N-Fb=*StIWqC1 z2B&GFG-w%+)vB9Pd~ZA27D+u+x7d%iTB?2HwB7G_PiFqhpBBLPkKh0N=Z9~v!Q_V@ zfB5d}PvL#95z~_Xtpxch?<@Jw*qCcwlKHQ;m;Uy!EfoOxq4tru{;!v4U}_7rKi9y938TE@$Qyo_O{e> z0?1tSVDymcbv<35w-o|KVR5q`Z6Otc&i!imL~{K8+lT-B?xXDZoB6x{`O%5R8atRh z+_>uKa~5ysTKX5)%O_lQ+*D_6GICsQtYj{n1wX{25ml!Of#=#%HXe);HZZxwW*xgo zDWO>0L<}1MFwpUQWe=`gsCgq3U^mgBNu;qN0$;z{M29(y?(xj# zqs#fC%J{L1PMP1;{vZd;MV-t2bkR{aSE}%jdFUu9K|tIRms3(COVS4PQVE3t%(l)HFn1(Qv8vL&Yi6d z@J@ZkPub|Sm6b#^vKU9X0`u7}gpi<5Hf?k?0z1Zs7u5Ci5x>Mo2SWun(t(Sjy8xtB zGpktSqqEup8HXAEJqKM3AK|y=+WHu@Ynk>dBw} zjoWdUGPbo+sl+xGT^4UxO<~f#u%J#v5 z`*FefFP}fKlQH$D?As;$N^#!wfjBSs8ExMAKu~FSdEOg+UTG#0bf!2j2G;iej7Yl# zBz*xqs?Mv{rw1mjULB{OQ0T=m)mxU+(k0x>^U}Iq2l!gLH$0Gv5a6*ggFA)Z?G)%e z5a?Bt-a!{k6_Shld|I8CArIb<_v*YeA#jCWf{VIrcM`q8SRT{o6>yFqmAsXvQj94S z3cVD#^MG!`X=?V@@aS}zUQ~LQL~r>>qW4y#7gOd(HG2J8PwDhZq!)M`2%jx{QlpoH z^J9(P#?d}^FMU-g=C0FAQxJ^RjVw`GI&zb|?;^c!1MQQ=by)dYAxxgBYdPs$3{(7d z_5V&jFl+nai1C>Z?4AweRRJ3*# zpf1xP1zlVB5h-77MX2)UvZPz*dcLF@;A?3@R!1|1rRS?1L#u?eL2t>fW?^sHXTx_% z`OcJ}(Y)I}tL96WowOSc{GFQbTR$J}Z-*g1D3CQ)@)eepmegL=e- z#cUkdtv-cLTt`>=A^_0v^Rr3LM%Tu5+qB$d^V<)Pg9W`W0`##Yu=xlyvM1@8}CJVbpQ#fG(~w;(77mYmME{_9oJOyROLNR zRbF-ks0m13hsWdKUXlZ+XYeUf6(CW}l{0&vXSS#TS_Rt-q~N^4;a-pHF*uv*kd%r2 zjIt_1t9J+PT^r}N`2O$T{>RV1{Pg_~e|n?f|Uf@1!u5qkXkww(K z*4SpUd$?4)3!PD7XoU{NSczSjCtT9>7pO{;&r!@p)N)=xn5Kg}=$aNF*#ZKVt$Wb!WcHGDf2p}QVTw`|33sQs!OsHU(r~pEVE$2%T zsV^xsTVq$?j3CPiY$Ubb5kd-rQX%IM1m@?klZ2I}s1?EA91%~j)qP#^Iip^7zZ@US zQJ+}Tqp7VO?e4dJ!87ZSyVLcnj4H9LGH2|%r+zQ)6^ZL76p8c2Gtj2C$e|`)3er72 zBt>&RbEvR^OyCsDL(CVE0If1O?3uV#sdVx_CHIHiA6=Hpl4l?~)b%~8jWvsAE!Mk?cKTZAZQ!z$Y~t7xknZ)?Cbu=Z zolO%g`4G&eG?whXmMmfUWO>@n%4FnUo2N6dj~p?QpNor<6A(-M4bqLQ`kK zI+W6Ttnv;PO(01AYlXOhDX3Zvjb^x7?^Oa|$Tl24)l;-5b5?p8R|bfd$yBh2lUbJ_t12Dj7eCGB1lEnHW5Za&{E0qS;Lz!g^@+e+MpV&ZFCFYZe8yR+Sj{9u$$OHNF;5hTqIR{E%&slwK)Q0MMr@2h42oMJ2Jkh-CD zQ~{z)kzxIH51`30mr)cCM9i&RPrCmZ2ySymyDglGAzgLJ8@VTNkf?OqC))rQP|$v3 z&Y2B%W;IIhT**MHXh_FyuUqUF)JI&b#Bw#oBlSD9NVI%dP%1GIMr_HyP)F=CrwtVi z>YOG(X10>+;++uI;vQV;go5CDLA$-QX;2a_h=TY_v(h=scnPW=l7+~J*>^S-k4DJr z-~*$BT@E4L5;oJ-r_Y-#r*$Y=9%j2{LM?o@Y+v=foSLXUTWKc<0D3{NAXa3+tJP&i zM#1&deze$ixAq>W#34k{GYH2%-#BtaEFIz{+i!+P;N~ zTE~@SHiA46BC-`=B)bSd*0Vb}lXXs6{7S14QBEv{2OVMugCOf6wIE%Iga(Y%MM9JR znP@832sdztCB)5?yCna6eP#)<4ZS`$aUjQbL8fgr!znmIe$bxPfXM{5v;?y}9qb=9 zHT0Sl=ZNA=d+)>BHKsIKy~^tAbm%&K56!TTimIFRkh(Ao$NTGTzHW+bbcqYwPlj;0 z{wT+^yGQldsrLLOkwO%6VOXj=S40wluc(|JnvL4@CcEysFNvZi33e^1xIDaHhp`}&*MgMmmL_DbiD zhfWimexB0$Fe|?35FL5KsL^2?w2FSERb3t!nj&xT|QW-wX!(&A!yuDpu3!O_ogL$bQ-VU~t zg$m9ngLamseVt_vw9z*?v90i6=CLSbnnj*@8QrrJFCWAb(DbGsw%0f@WEGI|!2V4GhKzWh2p7@%k9ibdvPsidZEf<6oqQw6%RM+hxAIR5smpez zF5Y;@5&|Qp;v8InMa)PO}KmlTmVTkDT*S&I{8(|x0S@jddb$9g>_+x__btcg2^SN4Q3NJ zixr_G){)L*m=iWn5RMlWJs~Aj#OzFZJn4%<;)Js8L+VfG$lqqAZa!d`C zYR|XLsBBT5NBG``l~&wem%lRlyL<4#kB?3=U*O)`gSWLDEWFR`0ci=WFOzicD(Ufj zeX$U(^JrM&AfrY7mo7>Ww_ru6u8Fm&bPU&H?AKkPTj}?IySe|z)EBg4k6b_=czSB` zRA!t=#5k6lTGm17Kd=C_m(}huW^>oRJ6J{Tdcw2lrih={&F|()vYyQS9eQ+&{L^<2 zzx??9A0Mfn?6=R&EQ`(hnw$cvAh)8T$V5jf1yLnQ2@8p7E#x9*Syn47Y8rR!J`#=5&={xLY_>}3AqD&prNEG~Y#D^aokfq9hGbr@JIcitW#S_Y|26(z=J-2Fc_w#s zIW+{p6kS~z5J*avt2ciXf1NLN%)`VM5fob0Hqz5Qj`VQ-l^#lP&?1T`+1Y41is`g= z(t7(USw)zAbt}(jY?pQ;(kqD2ft0o?%goKdtHRdMcTr}j*?Xt4t7^#N&en!kKZm3W zSUcPOQhF@B_=~bwTPv9PY3VB~*(1qiN}KBh-FN zQ_(#M=rnN7G?f1h0;AKGL-S;ZAb7s~_uVJY5(QMNP+fj4M!1^(@)F!X2>w!2H(MQ1 zM`Ny);$V)T$jNZoke$j8UtB+?s{tAkwEZRtk$X|JQXR@NbXGwp(H?E*<#Z6BDE zY^d)oYZ7L@0eT=*K@#(fp<^Vh!n;*A&)}zF5vV@Mxy_^WQPk*2ZlPB-1@MqzI|ae^ zER(4$|Fju(rtFAi^i6UW%Jk2d3d|{Fbq9ReTC&owcgz>{{mObYF#qHCm+wBNwtaK{ z?rwqSzbY;p6I?~aLLyei!*$}`vV0ot5nAO_A^|}xVn!G^UJse)1f>yk7Sn(SNX=Ba zZdU}slRHg#Zgjg)N=n+qJ-Pp#bfO+CPq*%iNj?@8l{PSwQh>Ba#BfSUV?2RCah)Tv zr6LekIN!F|Cn7ugcpmtj1SJKKyQZh_E&Q0OSg+D#u^+9KVP;a2P`bT=k42-GcvRQa z!8CL5VyWxCJ>jQ=_BjyYPF2p#eFuAo$dcWG)n@@uMZM)1-n5XMaDJ4kJLaTKZ&W(f z_K`Nph5A`zC^0=7^-GRJPtpcnu&p&N!VHr(OyRk!yE#_O%@v-4fRjk@CRQH(1*;W? zbkXEwWBYBWT6QO!`@8q(e*5QZR{HHv|MAF<^WQ!63uc*0oFo=^rZj6GA5G+EMBUYv;S7-+p}d@m5+CKtaGYR6%)2X~tb6rW5+SHsmg zc7VDN?gLxb#0=;KBA~%;@VGimgrF*6IVahadJGJ}-=hGeuE`V)*l?bgzV2JIIIeLf!{FzwnRIe24XUF^ zU0H;MBkQ48LpZ$OS_In3>_}nVT|?MbsP071Vdmb7E#cn+4L8`{w4l{ku%K`l1G4GeBYWzRCs zuN#3Kao99}o6@%}xT%$YAQjWCyIA6`VYR(Sdn)sB(L{38u;&)RrI>#=GnL?(3O8DA zat-Y-D2XgyRAF2W@<7(9Gb(c{uw9@)kXSftDE#V^p_M{Af2|`=M%^i4KYebs1i>Am zO5&7k$w|8imDGI9&@4#i%K9p(YTL>!1tlOD-X{^Yt1Ayr)@ta%yk9~;e01i2Sp>F9 z5}*@R)0#~C9(4(qu7;4oEgDu#q`2CluD?z|LSCkh7U z@`npAO5H?Hy?Sq%#*}#iRPQZfu^w?ba|;A>-!AU{WTtQ3l8+1B&*pHOQUStP14xe8 zo$=FqJDp8C#ri3NTG?rBg07*Uo_c?JKbG;mOsZhY7skKG-RLX`Vc9fXsqow50Uq0W zfVtuFh%ix>-=2?vZ~XQo&q_L%>qmZjYf&kWcEdfznNJz+N!G~7!cI_|mUo_Z2On7HL0CLeMR_c=BiL9X${ypT=4`6idz-acmzkg9_a6iG+r zO~i;W4pg>`iD%xIJ6{B#zt5F@@64xS!=3q1EZBlG91m22-I;HO!>8Q&!1|-}p4ZkQ zR{+^o8W{6F{R`4gi;ivkU9Y*yoXfQdwzW;x`hLC`G1HTuEkIWw`#w0Wc1r zz05KXk!L*n24~%Vo^`TjsiJ&yYzVTfkZyCk4#k>-7t2}H0xG938oPd!>&imK42d(D zlZkvZw!5R8@h;vWa51wd34DT?No>ng5O6xZHaH(M_W)DR^&yEjCrs{$@PuhvcxEy_ z-NChFpQ{C_?}@`DD7q4}j!;jpwv}E@b3$cxxK?TFpget(t4)JK)!fRKf>s7pT~GX? z3OTqA1yKh)4d`l;LM|;2?G(L4*1-`Mt2hH(>Zzl8Ernx~1&pszrhnDW8_X;;V8`bf zxBXTN=o1cxGktIuLoY(t*87Buq5DzTpSp7~yv)ZiEeubd1r_od|Ehshj^x>UbUI0K zY_mQ!-+-~#CtM7*zoJ_!DMa&!fDodV65)J z>2R3WG&)o@=thSpE1FVTWwl!!V&WTdca0d)z))f;fSAb%@AVw#fVO>R%8hg5eM(8a4>=WHG}Qg(?^}8@#PJOqlj&#l;*gh$Uu8j4u@YS27!8g4dWoZ9N)$f zhLSQYTd;m-F_*x>dmV>2;MsYgCCB|n%aTrzgoh+>gO5I79^Syv;?O%# z^+dRgoT%Key22?mKRwdeh^H_ZUyD2q-Ny9~8%BpxHAS6J$TXD7EJ&F(WS?ltp*#_E z`!M$n;iS{zIZr?iB{~CK{1C9`({d~g-8GD74}XvGia9AS6T*<>p+h?e7AO^Rp2c+8#klG8}Wxju)Z zPX#iR_eVPQimVlB3b#Om06f%uAqBBdT-NoF;_xw&;;RP=xX}_;1AlJ0jR~b$J6L{; z>X*2-Y+gz>2yq5v0kRt`o@)bmX?B;r>Y7ULuXjK!Ig4%9rnjFZSZcA(s08=1@3Hdj z4=)jCQ##buje@N#JWt8dbCU=bKNsi#<(!SuZ^OTawdoRqce$@O3e)-8F-XU`3iKb8 zdJU2{Y^eM`yY_%f>g-tlR)rgTF8g{eK3U^00A2(04BBDESscI)IH{fX^$v(7PQn7p zj-esqb!z;!u<0lY5Y6$9xX(kD=kLc`Br{;VX$(xE1~t07hB z>ke8xg^HaL5;Wo&(2_hcfZdZfRYNX^Bpx-6_t{uXwNHuhB9CYFI4nB2DBdMFV;Z{l z@Pu-kX>ciX#?pp=9@}aHGy2w+Mkr>7~y6_;q)KItr>vJ55p$dr8O`Jia!Vwn;+IV820M3287%Nxh? zEH#dT(de!d{pRJIkf~tE9Zsr#7w^l`S;iForpe)ByJZ@$N0z4;!$`5wRd9>4h>zxf`AH{ato-{Xfj-{Uvm<2T>q zH{ato-{Uvm<2T>qH{WBucm4M_-{Uvm<2T>qH{ato-{Uvm<2T>qH{av^|2N;`cXv+2 z=gjSSF2u9b|S&vpq`?0&)__#ChOwI;zUd3f9) zcxDeT=@ESKH0`tgz`F3WErMxCY;zLuDSP1g4PU?^_*c3EJA~&Y41zfXK5q^@zu-&y z1HbzOTMJ0#tB|$GP+yO$#kiBtsV(&zQng--sijo&m55s8_pip&x}0C?H>YV`W*+$p zEUn9LPtxLnz8Xi1%Jh{eS}cnfVraelgkTou$ZP6lov^i6kjnxbwuRSF%ToICN@7`R zBWmxyj#d_+x7U-(Vp+bTQWhP~zm-rH&F($Cj!u?$b;93DCTjs%UPC2Ihuv$5WGVms z+h}C58(vW&>k?j7AxlN-s|jTN_WD>~ERXf>1BqFkw@=B--mJ;zE6jeGx-5O|mk^k} z%$5BaaarBbFVUBM_hm}z6Z7<{Lh3g)$gAk6zpjk>Z?2+#39m1re!c9w4;;?uWW21q znWwf-7@WP7xtTA;C;ZKx<83z6=g-=ky@a)yFN-JK&DeM^;cPZ%!k;rY)74(q*odlmn&%UoBlX+Ne%`;zWs?>@G{`P;eRI51Jc=eIM#`7#e2yFmw_)^02m z+U1(h7sm;ztY0t3gmg-gqJgms7Bj4WA;%}TR=01r9%n zc7vT;6i^5>QkWdyC-6jBOlsmg7IPxAYbZH=C50mdrV#!JAtl zvenhu9`LGZp$o2(e5|)pe5aQW8o7Xu)JR}JVO+r@QrQCf+To&^2NjEL!tOiM5#8fC znU)>fKBpeAKM;n=AT2WNIXvzybE-6BWvNb0s&TUtoLoGp4818}BwsW@Q3()iG)h{>oI;NE%d2C`O`{BaH0zxb=YAl zS8!-_XtO$h^F})QEKDikb##+B`>@5Yw{oQBBA+7vFl>npVl^BNW!k70U=bAK3Rx(d z=r%x*RwF*zp!9lZ5dB1u^tFbhYe=CVpQy6HD(5hQPULwq>&pL0?6|%=#ro zG}WRxQ59Jhw8xApEN>=!1Bmx1mqX~x07_wFtr_iBGoTqnVq*v)I0b@9G^(i+%D5i5 z5kGIkif(qEssYlGQvKk3)rp&hjJ1x$4e_d|=7WsarFWpjv03W@pL=5PIEuE+Fdm92 z=2$nRS-Lnid+E<9W`Gye-Ac@|R}VuRV+%M*Aa{DI*Uu^zc870_vNg`?R<2(UM3@oe1KhJoM`<&+Nh>h2#DNngKd{jo8ro|^ zu{x{UXJQd*n64JECPV_7iK!&KGMtfE{Mc?Voszn-*X(529dP!k-Bb0rm_e)Xj#-?& zChD}M+4*EBu^^kiXj8p=2xOZJX6(X`aoA!ik03JPt|ESB0Gc7g_NXyeQ=i!S(#`*V znM<>xZmdqg0qtFU(CBmO_qHT0Z;UyrJAVx-!WZW(|E~`gqL${JC;bF-p>JU+YIU`N z0~h$&QQE_jAF?D%W}a1z6A|db6xid@4Yb-6H=B1eED6M+9?;(&eBu{rfdar&`V#^D z>{CH)68aF+&h%R}_)!H8*;XGc3z!|WsIRMK7FGJ-jIdQC(noiaW4jbV!w=1FBdBWV z{Bow>rZGJ@9cXn!6t6=l)y!a_kehcad$0d83le)hO3}qQ4noM??bibth9};N4j_WS znsOc-uL<=XSP9ji83%`|lAcJ&Y|G|?TM_Z(=<7%Ts~ufKkl6_s^f+~+q6Dj>Dif-AVnT+c{N(|0k z4lm(c&n1earvwziIBhdaH@ezjHcL8$`#)^%t1E5uN<%|(u>niaqaBX-%^M$hk%I7( zQ)HItj`}slVf1kG4)p0V_i~#()*M|5=;Fi~OJHplpD7L`+?EwVkLvZ?5X`s)AsXyQ zt2^yS`(Sqq;<`doxc+%|HiM>OH4FgnY7v-8vkj!y0jfh@bKV_Dv(>>I#M?TE6W|RU z=)wTtF&fLZ4)iFv4UT+=IH$Rh)#U9qIS4*CWzwkasH|4@^?u*^R_Y; zq(A81GG1)j13;R~%8wmMOCGf?wW*3%H)2K2MJSX45v0j$wv~__&g_J`kXTBjS=(K1 z2lNv%378F>5F}}np~3P&Jm1uK-Sf?~&3rRB;)%=^@l7&UjSp7pnj9j$ffliWgwm4% zI#4H;q#)D=YN~|~c^6AN(h_L{FI!v6p62y~%d5F+KWOZ6=8?tEym<&y0)m6L%-%wt z+KejxI3h(00j6XHf=(x$-*AYx;4(=Ak*-;36sCrdmoxK4hM$dMPa{fB0u(_Ew4DXt%pEDm!~=RWQCx$en3nlv6GavWCBQBke?WIPs9f6=`O5xSzFQ zUYGz?n&5pYH1#%3VB;zGFV%Y*W#-~Z!K(YehiP$l5R+7bAH-&VZhR{wS&;J87Sxua zf_4xx&U*C3UE!DUo9b{_f@oK$yY>lT#|4JY0JaMHS{;^)j@to? zF|`|5mpilr`Jh>$G+^dfO^Q3-_^{(`_C4(Q@xBKkkK>Vnca7AC(D2-IMW51pG22Zq zW?Q|O;Gml7&5GT75acnLf>gy$azv?N5PYm=Bn)p2Nt%_ph^5ilu@cskQIF{X=%;#8 z430!NT`bXyO%v|gR~EK0iJkw_{iR7??f@A_GLqdKxhblB)LhyA8^cxZ-OfEZTm zp9UpKlJ>NmTWb%H92l_U@DLo7U8?ZX)7gS^mLu%~>F9RmsjClUb)Oc&HiIV;GS?jB z{k0h2AgaSCrJMb%fj~3dmRY;soUfLVjV5Gsv{C~eKoVNg;089S9K&>Jg1BK~CCwtj z81#jF+-MJ$aQM{Cnlxq2jX^HgA`PMI+P2SmsJ_t;XMKZqU?8%QtZHxJJVLRA;AiGp zRBHK5)wNS~g$Y(sE^Ez;=KP;)1-IW;aP*=KVP?=5TOy3W8O(b%I5b+c5iYEZkgDa&zbHdBu&3a4Ic zcUvS%Q99EKED;o0x5^!UdZ`(00fgM*HY+$wAeBQ!iI-Sy<=AFHVmX0l)mZ3@xu=Z8 zP6{Z}sI#$w9?`T@YeO|!uhdKy*{w+le%BfX?e}7$+k36>(&NjkVg#GQ?1WVOhS6YG z0vJeMq3@(mEO@#QmjKUIko#0kTa&6%+EhMY8AT%|yTcOPvO8`ICXuOp@C3w;yED7L zOtqybp`|3<*UB(?zJ^{j0AvGp0m|K@WAZdYP3*xq zlFsTRaU{>A@FJa5AP#xvQZ8+8pG>E%9Y$5+BAU%w08(eLXDpkBl)r~&yehi`910L_ zu$iC@GOAEREiD;Y<1fW3N^wjOth10N%%3;r&+p9^yqWo47eCs5G;(e?81i=ayi}7O zB1bblU-(lpI~^f$u2k1kD2k`-Tp=Kzvzo|CL$U}%>^ zrw;$U`nhQEc7s}^eL*d}AEWPaQaVv$NJvVF?PW8?c@^C-M}aHViYn&R)h2{(Kt=Qn zT)TFcC)F0cSBJRtXmjURXu0B_Wijr0Mm%1qquAt`ReVt;&1$sufWquRVeC{FX&nPH z{%HYGqa4U@UvepuZKBJOFYDk*AEfypB+q+WSXNi|Y;$*6*PH%zN9yZ-*=Zf#dfCsY zMqi+ol^s>|LjZjp<($)ZBnqTzj#jh@?*nvFJ2Fi~Xwn#KXe(EP;?>n?>2xa5N81q- zIA8wztRe-BSMyZuTonoEI{3@WVoF6QkXkG%mYq3~r~ZT@cF>7Jp=h)F@3U56q?Iw9+E;8z-^lVH~UC^n`$x$Dd+^PLY_I%59S6!0uYG^ za^RbR+#T-Y0^(MILH}R?rds&DC?PeFmsVd%`d^4mpnwLBC_*F{i}?_mP|{aI6Ha|H z3yw{?R|=ZvOFQ6G$O0HSBF$D+zuqp#tKF|DEwWn!ceJ%6T`z4NYw%^)nQL<7IANrT zd4A{YqCnc2nIW}jcS;M8UI@eshUvap1ior4(rvW`Xf>(5jcg9c5RG@x@JLf0d!^EX7{HQ}@aPDEsgQZnBHav8||;xAh->y`k){Fq2(lbNY09c!r4Ey?~GGukn!eq5VtP$m(uCVIe!ax-Z}& z`=t)D6!CXogv%S~z6}+r8>{V<9)xr2pTm^srPxBT0e*yAx0LcLY03$1wA^-pY literal 0 HcmV?d00001 diff --git a/public/javascripts/scripts.js b/public/javascripts/scripts.js index e77c8fe..d559e6a 100644 --- a/public/javascripts/scripts.js +++ b/public/javascripts/scripts.js @@ -40,12 +40,14 @@ $(document).ready(function() { // settings: {width: '10cm', height: '5cm'}, // Additional settings for SVG element // initPath: ''}); - + $('span.SVGBODY').empty().load("/images/BlankBody.svg", function(){ + //$("button").button(); + }); var colors = "0f0 0ff f60 f0f 00f f00".split(' '), i=0; - $(document).on('click', 'g',(function() { + $(document).on('click', '.SVGBODYFilter g',(function() { console.log('click ' + this.id); $(this).children('path').css("fill",'#'+colors[i++%colors.length] +''); }) @@ -143,6 +145,9 @@ $(document).ready(function() { var id = $(this).attr('value'); $('div#Rightpane').empty().load("/workouts/"+ id + "/recent/", function(){ $("button").button(); + $('span.SVGBODY').empty().load("/images/BlankBody.svg", function(){ + //$("button").button(); + }); }); $('div#Leftpane').empty().load("/users/"+ id + "/sidebar", function(){ $("button").button(); @@ -154,6 +159,10 @@ $(document).ready(function() { var id = $(this).attr('value'); $('div#Rightpane').empty().load(id); $('div#Leftpane').empty().load("/workouts/filters", function(){ + $('span.SVGBODYFilter').empty().load("/images/BlankBody.svg", function(){ + //$("button").button(); + }); + PopulateExerciseList(originalExerciselist); $("ul#exercises").sortable({ items: "> li", @@ -170,7 +179,6 @@ $(document).ready(function() { }); $("button").button(); - $(document).on('click', 'path#F_x5F_Pectorals', function(){alert('hello2');}); }); $("#top").delegate("button.home-link", "click",function() { @@ -180,6 +188,10 @@ $(document).ready(function() { var id = $(this).attr('value'); $('div#Rightpane').empty().load("/workouts/"+ id + "/recent/", function(){ $("button").button(); + console.log('here'); + $('span.SVGBODY').empty().load("/images/BlankBody.svg", function(){ + //$("button").button(); + }); }); $('div#Leftpane').empty().load("/users/"+ id + "/sidebar", function(){ $("button").button(); diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 9de13be..2d2b969 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -1,5 +1,5 @@ body { - padding: 50px; + xxpadding: 50px; font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; } @@ -15,6 +15,11 @@ list-style-type: none; list-style-type: none; } + +.labelli { +height : 30px; +} + .floatright { float: right; } @@ -23,6 +28,12 @@ list-style-type: none; clear: right; } +li.floatleft { + display: block; + float: none; + overflow: hidden; +} + .floatleft { display: block; float: left; @@ -32,12 +43,15 @@ list-style-type: none; #Leftpane { display: block; float: left; + xxxwidth: 190px; + overflow: hidden; } #Rightpane { display: block; float: left; + overflow: hidden; } #userphoto { diff --git a/views/workouts/filters.jade b/views/workouts/filters.jade index a4b8a83..bc8b1c7 100644 --- a/views/workouts/filters.jade +++ b/views/workouts/filters.jade @@ -2,21 +2,30 @@ h1 New workout div#filters h3 Filters - label Search - input#searchbox (type="text", placeholder="Type here....") - label Free Weights - input.filter(type="checkbox", checked=true, value="Free Weights") - label Bodyweight - input.filter(type="checkbox", checked=true, value="Bodyweight") - label Exercise Machines - input.filter(type="checkbox", checked=true, value='Exercise Machine') - label Kettlebells - input.filter(type="checkbox", checked=true, value='Kettlebells') - label Cardio - input.filter(type="checkbox", checked=true, value='Cardio') - div - object(data='/images/BlankBody.svg', id='BlankBodyFilter', type='image/svg+xml') + div.floatleftx + label Search + input#searchbox (type="text", placeholder="Type here....") + span(class="SVGBODYFilter floatleft") + span.floatleft + ul + li.labelli + label Free Weights + input.filter(type="checkbox", checked=true, value="Free Weights") + li.labelli + label Bodyweight + input.filter(type="checkbox", checked=true, value="Bodyweight") + li.labelli + label Exercise Machines + input.filter(type="checkbox", checked=true, value='Exercise Machine') + li.labelli + label Kettlebells + input.filter(type="checkbox", checked=true, value='Kettlebells') + li.labelli + label Cardio + input.filter(type="checkbox", checked=true, value='Cardio') -h3 Exercises (dynamically loaded from database) -ul#exerciselist - li Unpopulated + +div.floatleft + h3 Exercises (dynamically loaded from database) + ul#exerciselist + li Unpopulated diff --git a/views/workouts/recent.jade b/views/workouts/recent.jade index 4f14fc6..4fbeff3 100644 --- a/views/workouts/recent.jade +++ b/views/workouts/recent.jade @@ -9,6 +9,7 @@ h3 Recent workouts: ol each split in element.splits li Reps: #{split.reps} Weight: #{split.weight} - span(class="floatleft") - include ../../public/images/BlankBody.svg + span(class="floatleft SVGBODY") + //include ../../public/images/BlankBody.svg + span(class="clearright") - }); \ No newline at end of file