This commit is contained in:
arnaucode
2017-02-03 08:56:51 +01:00
parent c4b7414770
commit 112745d6fa
1585 changed files with 450241 additions and 0 deletions

19
www/node_modules/ecstatic/.npmignore generated vendored Normal file
View File

@@ -0,0 +1,19 @@
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
node_modules
npm-debug.log
# Unicode filenames cause jenkins to barf when cleaning up workspaces
# See: https://github.com/jfhbrook/node-ecstatic/issues/128
test

8
www/node_modules/ecstatic/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,8 @@
language: node_js
sudo: false
node_js:
- 0.12
- 0.10
- 4.0
- 4.1
- 4.2

84
www/node_modules/ecstatic/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,84 @@
2015/05/10 Version 1.4.1
- Compare if-modified-since header against server-generated last-modified header rather than raw mtime
2015/12/22 Version 1.4.0
- Add ability to specify custom mimetypes via a JSON blob (on the CLI)
- Started test suite around CLI options parsing
- Workaround for egregious v8 bug around date parsing throwing during modified-since checks
2015/11/15 Version 1.3.1
- Add recent contributors to CONTRIBUTORS.md
- Document showDotFiles in main options example
2015/11/14 Version 1.3.0
- opts.showDotFiles allows hiding dot files
2015/11/03 Version 1.2.0
- opts.cache supports function argument
2015/10/03 Version 1.1.3
- Add CORS=false to defaults
2015/10/02 Version 1.1.2
- Properly handle defaults in CLI args
2015/10/02 Version 1.1.1
- Properly handle boolean CLI args
2015/10/01 Version 1.1.0
- Adds support for responding to OPTIONS headers
- Adds support for setting custom headers
- Adds cors convenience setting
2015/09/22 Version 1.0.1
- Use encodeURIComponent when creating links in showdir
2015/09/14 Version 1.0.0
- Optional support for weak Etags and weak Etag *comparison*, useful for cases
where one is running ecstatic with gzip behind an nginx proxy (these will
likely be turned ON by default in a following major version)
- As a bin, respects process.env.PORT when binding to a port
- Directory listings encode pathnames, etc
- Default status pages return html instead of text/plain
- Contributors are listed in CONTRIBUTORS.md, referenced by LICENSE.txt
2015/05/22 Version 0.8.0
- Add ability to define custom mime-types, inline or with Apache .types file
- Test against express ^4.12.3 and union ^0.4.4
- Run tests with tap ^1.0.3
- Fix newline asserts to work with windows
- Add license attribute to package.json
- Elaborate contribution guidelines
2015/05/09 Version 0.7.6
- Fix double encoding in directory listings
2015/05/07 Version 0.7.5
- Fix HTML reflection vulnerability in certain error handlers
2015/04/17 Version 0.7.4
- Fix sort ordering in directory listings
2015/04/13 Version 0.7.3
- Close fstream if/when res closes, fixes potential fd leak
2015/04/05 Version 0.7.2
- Correctly handle req.statusCode in recursive calls; do not inherit upstream res.statusCode
2015/03/27 Version 0.7.1
- Treat ENOTDIR as 404 (same as ENOENT)
2015/03/18 Version 0.7.0
- Add support for specifying default content-type (as an alternative to application/octet-stream)
- Use url-join for autoIndex route, fixes windows problems
2015/03/01 Version 0.6.1
- Fix handleError fall-through with directory listings
2015/02/16 Version 0.6.0
- Fix for pathname decoding in windows
- Fix for hrefs in directory listings
- Add ability to turn off setting of Server header
- Remove extraneous call to res.end (handled by stream pipe)
- Remove tests from npm package due to jenkins bug
- Start a ChangeLog.md

86
www/node_modules/ecstatic/CONTRIBUTING.md generated vendored Normal file
View File

@@ -0,0 +1,86 @@
# Contributing Guidelines
## Code of Conduct
This is probably way overkill, but this is by far my most active project in
terms of contributions, and somewhere along the way I was convinced that it
was a good idea to have this in place sooner rather than later:
I want to provide a safe, healthy environment for all contributors/participants
regardless of gender, sexual orientation, disability, race, religion, etc.
As such, I don't tolerate harassment of participants in any form. In particular
this applies to my issues tracker, but also to any other means of communication
associated with this project that might come up. Anyone who violates these
basic rules may be sanctioned/banned/have-their-comments-deleted/etc by my
discretion.
Glad we cleared that up.
## Branching
Before working on your fix/feature/whatever, you should create a new branch to
work on. Do something like:
```sh
$ git checkout -b 'my-sweet-new-pull-request'
```
## Please Please Please Start With A Test
ecstatic has some pretty gnarly branching/logic underneath. Tests are extremely
important because they (a) prove that your feature/fix works, and (b) avoid
regressions in the future. Even if your patch is problematic enough to not be
merged, a test will still be very helpful for confirming any future fix.
I won't reject your patch outright if it's missing new tests, but it sure
helps!
## Code Style
Ecstatic's code base follows a relatively consistent style. The closer your
patch blends in with the status quo, the better.
A few PROTIPS off the top of my head:
1. Variables don't need to all be declared at the top, BUT variable *blocks*
should do the whole one-var, tons-of-commas thing.
2. Look at how spacing is done around conditionals and functions. Do it like
that.
3. `else`'s and similar should be on the line *after* the preceding bracket.
We can refine this as the need arises.
## A Few Other Minor Guidelines
1. Keep your pull requests on-topic. A pull request purporting to tackle A
shouldn't also have commits changing B and C. Feel free to make separate pull
requests. For instance: A pull request should generally only update
dependencies when doing so is required to add the feature or fix the bug. This
feature can, of course, consist of updating dependencies.
2. I prefer maintaining the changelog and package.json version myself. This is
because I try to make a single commit for a tagged release contain all
changelog additions and the version bump, and this breaks down when there are
interstitial commits making updates to either.
3. In case you were wondering about dependencies, you may find this helpful:
[![dependencies status](https://david-dm.org/jfhbrook/node-ecstatic.svg)](https://david-dm.org/jfhbrook/node-ecstatic)
4. Please add yourself to CONTRIBUTORS.md if you haven't done so! Fill in as
much as makes you comfortable.
## Pull Request
Make a pull request against master with your new branch. Explain briefly what
the patch does to the code, along with any concerns.
(If you don't have a description, it's hard for me to put the changes in
context. That makes it more difficult for me to merge!)
## Keep It Moving
I don't always notice new PRs, and sometimes I will forget to follow up on
them. If this happens to you, you can bump the PR thread or find me on
IRC or twitter.
## LAST RULE
HAVE FUN :v :v

57
www/node_modules/ecstatic/CONTRIBUTORS.md generated vendored Normal file
View File

@@ -0,0 +1,57 @@
General format is: contributor, github handle, email. In some cases, the
contributor field is an organization instead of an actual person---this is for
cases where the work was done on behalf of the organization, ie as part of
their job. In others, no contributor field and/or email is shown---this is
because this list was partially (mostly) reconstructed from github commit
information and the person's real life name and email are unknown.
Listed in no particular order:
* Joshua Holbrook @jfhbrook <josh.holbrook@gmail.com>
* Jon Ege Ronnenberg @dotnetCarpenter <jon.ronnenberg@gmail.com>
* James Halliday @substack <substack@gmail.com>
* Jonah Ruiz @jonahoffline <jonah@pixelhipsters.com>
* Jacob Burden @jekrb <Jacob.JW.Burden@gmail.com>
* @leesei
* @SirAnthony
* Frank Mecklenburg @yfr <mecklenburg@ubilabs.net>
* @curimit <curimit@gmail.com>
* Dominic Tarr @dominictarr
* Chew Choon Keat @choonkeat <choonkeat@gmail.com>
* Lars Kappert @webpro <lars@webpro.nl>
* Alan Reyes @KuttKatrea <kutt@katrea.net>
* Colin Fallon @colinf
* Charlie Robbins @indexzero
* Ville Salonen @VilleSalonen
* Tom Steele @tomsteele <thomasjsteele@gmail.com>
* Maciej Małecki @mmalecki <me@mmalecki.com>
* Chris Bannister @Zariel <c.bannister@gmail.com>
* Shinnosuke Watanabe @shinnn <snnskwtnb@gmail.com>
* Adam Brady @SomeoneWeird <adam@boxxen.org>
* Christian Howe @coderarity
* Arnaud @amelon
* Gilad Peleg @pgilad <giladp007@gmail.com>
* Brad Dunbar @braddunbar <dunbarb2@gmail.com>
* Google Inc. via Jeremy Banks @jre-g <jre@google.com>
* @sundippatel
* Arjan van Wijk @ThaNarie <thanarie@gmail.com>
* Mathias Buus @mafintosh <mathiasbuus@gmail.com>
* Farrin Reid @blakmatrix <blakmatrix@gmail.com>
* Tõnis Tiigi @tonistiigi <tonistiigi@gmail.com>
* Maksim Lin @maks <maks@manichord.com>
* Jan Nicklas @jantimon
* David Cox @losttime <losttime.shuffle@gmail.com>
* Bill Ticehurst @billti <billti@hotmail.com>
* Vincent Voyer @vvo <vincent.voyer@gmail.com>
* @helloyou2012 <helloyou2012@gmail.com>
* Domenic Denicola @domenic <d@domenic.me>
* Maxim Ivanov @redbaron <ivanov.maxim@gmail.com>
* Oliver Joseph Ash @OliverJAsh <oliverjash@gmail.com>
* Benjamin Tan @d10 <demoneaux@gmail.com>
* D Scott Boyce @scobo
* Zach Bruggerman @remixz <mail@bruggie.com>
* Mathias Bynens @mathiasbynens
* Chris Lee @clee <clee@mg8.org>
* Josh Duff @TehShrike
* Cam Wiegert @camwiegert <cam@camwiegert.com>
* Josh Gillies @joshgillies <github@joshgilli.es>

22
www/node_modules/ecstatic/LICENSE.txt generated vendored Normal file
View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2013-2015 Joshua Holbrook and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

220
www/node_modules/ecstatic/README.md generated vendored Normal file
View File

@@ -0,0 +1,220 @@
# Ecstatic [![build status](https://secure.travis-ci.org/jfhbrook/node-ecstatic.png)](http://travis-ci.org/jfhbrook/node-ecstatic)
![](http://imgur.com/vhub5.png)
A simple static file server middleware. Use it with a raw http server or
express/connect!
# Examples:
## express 3.0.x
``` js
var http = require('http');
var express = require('express');
var ecstatic = require('ecstatic');
var app = express();
app.use(ecstatic({ root: __dirname + '/public' }));
http.createServer(app).listen(8080);
console.log('Listening on :8080');
```
## stock http server
``` js
var http = require('http');
var ecstatic = require('ecstatic');
http.createServer(
ecstatic({ root: __dirname + '/public' })
).listen(8080);
console.log('Listening on :8080');
```
### fall through
To allow fall through to your custom routes:
```js
ecstatic({ root: __dirname + '/public', handleError: false })
```
# API:
## ecstatic(opts);
Pass ecstatic an options hash, and it will return your middleware!
```js
var opts = {
root : __dirname + '/public',
port : 8000,
baseDir : '/',
cache : 3600,
showDir : true,
showDotfiles : true,
autoIndex : false,
humanReadable : true,
headers : {},
si : false,
defaultExt : 'html',
gzip : false,
serverHeader : true,
contentType : 'application/octet-stream',
mimeTypes : undefined,
handleOptionsMethod: false
}
```
If `opts` is a string, the string is assigned to the root folder and all other
options are set to their defaults.
### `opts.root`
`opts.root` is the directory you want to serve up.
### `opts.port`
`opts.port` is the port you want ecstatic to listen to. Defaults to 8000.
### `opts.baseDir`
`opts.baseDir` is `/` by default, but can be changed to allow your static files
to be served off a specific route. For example, if `opts.baseDir === "blog"`
and `opts.root = "./public"`, requests for `localhost:8080/blog/index.html` will
resolve to `./public/index.html`.
### `opts.cache`
Customize cache control with `opts.cache` , if it is a number then it will set max-age in seconds.
Other wise it will pass through directly to cache-control. Time defaults to 3600 s (ie, 1 hour).
If it is a function, it will be executed on every request, and passed the pathname. Whatever it returns, string or number, will be used as the cache control header like above.
### `opts.showDir`
Turn **off** directory listings with `opts.showDir === false`. Defaults to **true**.
### `opts.showDotfiles`
Exclude dotfiles from directory listings with `opts.showDotfiles === false`. Defaults to **true**.
### `opts.humanReadable`
If showDir is enabled, add human-readable file sizes. Defaults to **true**.
Aliases are `humanreadable` and `human-readable`.
### `opts.headers`
Set headers on every response. `opts.headers` can be an object mapping string
header names to string header values, a colon (:) separated string, or an array
of colon separated strings.
`opts.H` and `opts.header` are aliased to `opts.headers` so that you can use
`-H` and `--header` options to set headers on the command-line like curl:
``` sh
$ ecstatic ./public -p 5000 -H 'Access-Control-Allow-Origin: *'
```
### `opts.si`
If showDir and humanReadable are enabled, print file sizes with base 1000 instead
of base 1024. Name is inferred from cli options for `ls`. Aliased to `index`, the
equivalent option in Apache.
### `opts.autoIndex`
Serve `/path/index.html` when `/path/` is requested.
Turn **off** autoIndexing with `opts.autoIndex === false`. Defaults to **true**.
### `opts.defaultExt`
Turn on default file extensions with `opts.defaultExt`. If `opts.defaultExt` is
true, it will default to `html`. For example if you want a request to `/a-file`
to resolve to `./public/a-file.html`, set this to `true`. If you want
`/a-file` to resolve to `./public/a-file.json` instead, set `opts.defaultExt` to
`json`.
### `opts.gzip`
Set `opts.gzip === true` in order to turn on "gzip mode," wherein ecstatic will
serve `./public/some-file.js.gz` in place of `./public/some-file.js` when the
gzipped version exists and ecstatic determines that the behavior is appropriate.
### `opts.serverHeader`
Set `opts.serverHeader` to false in order to turn off setting the `Server` header
on all responses served by ecstatic.
### `opts.contentType`
Set `opts.contentType` in order to change default Content-Type header value.
Defaults to **application/octet-stream**.
### `opts.mimeTypes`
Add new or override one or more mime-types. This affects the HTTP Content-Type header.
Can either be a path to a [`.types`](http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types) file or an object hash of type(s).
ecstatic({ mimeType: { 'mime-type': ['file_extension', 'file_extension'] } })
### `opts.handleError`
Turn **off** handleErrors to allow fall-through with `opts.handleError === false`, Defaults to **true**.
### `opts.weakEtags`
Set `opts.weakEtags` to true in order to generate weak etags instead of strong etags. Defaults to **false**. See `opts.weakCompare` as well.
### `opts.weakCompare`
Turn **on** weakCompare to allow the weak comparison function for etag validation. Defaults to **false**.
See https://www.ietf.org/rfc/rfc2616.txt Section 13.3.3 for more details.
### `opts.handleOptionsMethod`
Set handleOptionsMethod to true in order to respond to 'OPTIONS' calls with any standard/set headers. Defaults to **false**. Useful for hacking up CORS support.
### `opts.cors`
This is a **convenience** setting which turns on `handleOptionsMethod` and sets the headers **Access-Control-Allow-Origin: \*** and **Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since**. This *should* be enough to quickly make cross-origin resource sharing work between development APIs. More advanced usage can come either from overriding these headers with the headers argument, or by using the `handleOptionsMethod` flag and then setting headers "manually." Alternately, just do it in your app using separate middlewares/abstractions.
Defaults to **false**.
## middleware(req, res, next);
This works more or less as you'd expect.
### ecstatic.showDir(folder);
This returns another middleware which will attempt to show a directory view. Turning on auto-indexing is roughly equivalent to adding this middleware after an ecstatic middleware with autoindexing disabled.
### `ecstatic` command
to start a standalone static http server,
run `npm install -g ecstatic` and then run `ecstatic [dir?] [options] --port PORT`
all options work as above, passed in [optimist](https://github.com/substack/node-optimist) style.
`port` defaults to `8000`. If a `dir` or `--root dir` argument is not passed, ecsatic will
serve the current dir. Ecstatic also respects the PORT environment variable.
# Tests:
Ecstatic has a fairly extensive test suite. You can run it with:
```sh
$ npm test
```
# Contribute:
Without outside contributions, ecstatic would wither and die! Before
contributing, take a quick look at the contributing guidelines in
[./CONTRIBUTING.md](./CONTRIBUTING.md) . They're relatively painless, I promise.
For Windows users, it is especially important to read the [./CONTRIBUTING.md](./CONTRIBUTING.md)
section as you can **not** clone ecstatic without changing some settings in git.
# License:
MIT. See LICENSE.txt. For contributors, see CONTRIBUTORS.md

10
www/node_modules/ecstatic/example/core.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
var http = require('http');
var ecstatic = require('../lib/ecstatic')({
root: __dirname + '/public',
showDir: true,
autoIndex: true
});
http.createServer(ecstatic).listen(8080);
console.log('Listening on :8080');

12
www/node_modules/ecstatic/example/express.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
var express = require('express');
var ecstatic = require('../lib/ecstatic');
var http = require('http');
var app = express();
app.use(ecstatic({
root: __dirname + '/public',
showdir : true
}));
http.createServer(app).listen(8080);
console.log('Listening on :8080');

View File

@@ -0,0 +1 @@
<b>boop!</b>

1
www/node_modules/ecstatic/example/public/hello.txt generated vendored Normal file
View File

@@ -0,0 +1 @@
Hello world!

View File

@@ -0,0 +1 @@
hello cruel world!

BIN
www/node_modules/ecstatic/example/public/turtle.png generated vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

10
www/node_modules/ecstatic/example/union.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
var union = require('union');
var ecstatic = require('../');
union.createServer({
before: [
ecstatic(__dirname + '/public')
]
}).listen(8080);
console.log('Listening on :8080');

371
www/node_modules/ecstatic/lib/ecstatic.js generated vendored Executable file
View File

@@ -0,0 +1,371 @@
#! /usr/bin/env node
var path = require('path'),
fs = require('fs'),
url = require('url'),
mime = require('mime'),
urlJoin = require('url-join'),
showDir = require('./ecstatic/showdir'),
version = JSON.parse(
fs.readFileSync(__dirname + '/../package.json').toString()
).version,
status = require('./ecstatic/status-handlers'),
generateEtag = require('./ecstatic/etag'),
optsParser = require('./ecstatic/opts');
var ecstatic = module.exports = function (dir, options) {
if (typeof dir !== 'string') {
options = dir;
dir = options.root;
}
var root = path.join(path.resolve(dir), '/'),
opts = optsParser(options),
cache = opts.cache,
autoIndex = opts.autoIndex,
baseDir = opts.baseDir,
defaultExt = opts.defaultExt,
handleError = opts.handleError,
headers = opts.headers,
serverHeader = opts.serverHeader,
weakEtags = opts.weakEtags,
handleOptionsMethod = opts.handleOptionsMethod;
opts.root = dir;
if (defaultExt && /^\./.test(defaultExt)) defaultExt = defaultExt.replace(/^\./, '');
// Support hashes and .types files in mimeTypes @since 0.8
if (opts.mimeTypes) {
try {
// You can pass a JSON blob here---useful for CLI use
opts.mimeTypes = JSON.parse(opts.mimeTypes);
} catch (e) {}
if (typeof opts.mimeTypes === 'string') {
mime.load(opts.mimeTypes);
}
else if (typeof opts.mimeTypes === 'object') {
mime.define(opts.mimeTypes);
}
}
return function middleware (req, res, next) {
// Strip any null bytes from the url
while(req.url.indexOf('%00') !== -1) {
req.url = req.url.replace(/\%00/g, '');
}
// Figure out the path for the file from the given url
var parsed = url.parse(req.url);
try {
decodeURIComponent(req.url); // check validity of url
var pathname = decodePathname(parsed.pathname);
}
catch (err) {
return status[400](res, next, { error: err });
}
var file = path.normalize(
path.join(root,
path.relative(
path.join('/', baseDir),
pathname
)
)
),
gzipped = file + '.gz';
if(serverHeader !== false) {
// Set common headers.
res.setHeader('server', 'ecstatic-'+version);
}
Object.keys(headers).forEach(function (key) {
res.setHeader(key, headers[key])
})
if (req.method === 'OPTIONS' && handleOptionsMethod) {
return res.end();
}
// TODO: This check is broken, which causes the 403 on the
// expected 404.
if (file.slice(0, root.length) !== root) {
return status[403](res, next);
}
if (req.method && (req.method !== 'GET' && req.method !== 'HEAD' )) {
return status[405](res, next);
}
function statFile() {
fs.stat(file, function (err, stat) {
if (err && (err.code === 'ENOENT' || err.code === 'ENOTDIR')) {
if (req.statusCode == 404) {
// This means we're already trying ./404.html and can not find it.
// So send plain text response with 404 status code
status[404](res, next);
}
else if (!path.extname(parsed.pathname).length && defaultExt) {
// If there is no file extension in the path and we have a default
// extension try filename and default extension combination before rendering 404.html.
middleware({
url: parsed.pathname + '.' + defaultExt + ((parsed.search)? parsed.search:'')
}, res, next);
}
else {
// Try to serve default ./404.html
middleware({
url: (handleError ? ('/' + path.join(baseDir, '404.' + defaultExt)) : req.url),
statusCode: 404
}, res, next);
}
}
else if (err) {
status[500](res, next, { error: err });
}
else if (stat.isDirectory()) {
// 302 to / if necessary
if (!parsed.pathname.match(/\/$/)) {
res.statusCode = 302;
res.setHeader('location', parsed.pathname + '/' +
(parsed.query? ('?' + parsed.query):'')
);
return res.end();
}
if (autoIndex) {
return middleware({
url: urlJoin(encodeURIComponent(pathname), '/index.' + defaultExt)
}, res, function (err) {
if (err) {
return status[500](res, next, { error: err });
}
if (opts.showDir) {
return showDir(opts, stat)(req, res);
}
return status[403](res, next);
});
}
if (opts.showDir) {
return showDir(opts, stat)(req, res);
}
status[404](res, next);
}
else {
serve(stat);
}
});
}
// Look for a gzipped file if this is turned on
if (opts.gzip && shouldCompress(req)) {
fs.stat(gzipped, function (err, stat) {
if (!err && stat.isFile()) {
file = gzipped;
return serve(stat);
} else {
statFile();
}
});
} else {
statFile();
}
function serve(stat) {
// Do a MIME lookup, fall back to octet-stream and handle gzip
// special case.
var defaultType = opts.contentType || 'application/octet-stream',
contentType = mime.lookup(file, defaultType),
charSet;
if (contentType) {
charSet = mime.charsets.lookup(contentType, 'utf-8');
if (charSet) {
contentType += '; charset=' + charSet;
}
}
if (path.extname(file) === '.gz') {
res.setHeader('Content-Encoding', 'gzip');
// strip gz ending and lookup mime type
contentType = mime.lookup(path.basename(file, ".gz"), defaultType);
}
var range = (req.headers && req.headers['range']);
if (range) {
var total = stat.size;
var parts = range.replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];
var start = parseInt(partialstart, 10);
var end = Math.min(total-1, partialend ? parseInt(partialend, 10) : total-1);
var chunksize = (end-start)+1;
if (start > end || isNaN(start) || isNaN(end)) {
return status['416'](res, next);
}
var fstream = fs.createReadStream(file, {start: start, end: end});
fstream.on('error', function (err) {
status['500'](res, next, { error: err });
});
res.on('close', function () {
fstream.destroy();
});
res.writeHead(206, {
'Content-Range': 'bytes ' + start + '-' + end + '/' + total,
'Accept-Ranges': 'bytes',
'Content-Length': chunksize,
'Content-Type': contentType
});
fstream.pipe(res);
return;
}
// TODO: Helper for this, with default headers.
var lastModified = (new Date(stat.mtime)).toUTCString(),
etag = generateEtag(stat, weakEtags);
res.setHeader('last-modified', lastModified);
res.setHeader('etag', etag);
if (typeof cache === 'function') {
var requestSpecificCache = cache(pathname);
if (typeof requestSpecificCache === 'number') {
requestSpecificCache = 'max-age=' + requestSpecificCache;
}
res.setHeader('cache-control', requestSpecificCache);
} else {
res.setHeader('cache-control', cache);
}
// Return a 304 if necessary
if (shouldReturn304(req, lastModified, etag)) {
return status[304](res, next);
}
res.setHeader('content-length', stat.size);
res.setHeader('content-type', contentType);
// set the response statusCode if we have a request statusCode.
// This only can happen if we have a 404 with some kind of 404.html
// In all other cases where we have a file we serve the 200
res.statusCode = req.statusCode || 200;
if (req.method === "HEAD") {
return res.end();
}
var stream = fs.createReadStream(file);
stream.pipe(res);
stream.on('error', function (err) {
status['500'](res, next, { error: err });
});
}
function shouldReturn304(req, serverLastModified, serverEtag) {
if (!req || !req.headers) {
return false;
}
var clientModifiedSince = req.headers['if-modified-since'],
clientEtag = req.headers['if-none-match'];
if (!clientModifiedSince && !clientEtag) {
// Client did not provide any conditional caching headers
return false;
}
if (clientModifiedSince) {
// Catch "illegal access" dates that will crash v8
// https://github.com/jfhbrook/node-ecstatic/pull/179
try {
var clientModifiedDate = new Date(Date.parse(clientModifiedSince));
}
catch (err) { return false }
if (clientModifiedDate.toString() === 'Invalid Date') {
return false;
}
// If the client's copy is older than the server's, don't return 304
if (clientModifiedDate < new Date(serverLastModified)) {
return false;
}
}
if (clientEtag) {
// Do a strong or weak etag comparison based on setting
// https://www.ietf.org/rfc/rfc2616.txt Section 13.3.3
if (opts.weakCompare && clientEtag !== serverEtag
&& clientEtag !== ('W/' + serverEtag) && ('W/' + clientEtag) !== serverEtag) {
return false;
} else if (!opts.weakCompare && (clientEtag !== serverEtag || clientEtag.indexOf('W/') === 0)) {
return false;
}
}
return true;
}
};
};
ecstatic.version = version;
ecstatic.showDir = showDir;
// Check to see if we should try to compress a file with gzip.
function shouldCompress(req) {
var headers = req.headers;
return headers && headers['accept-encoding'] &&
headers['accept-encoding']
.split(",")
.some(function (el) {
return ['*','compress', 'gzip', 'deflate'].indexOf(el) != -1;
})
;
}
// See: https://github.com/jesusabdullah/node-ecstatic/issues/109
function decodePathname(pathname) {
var pieces = pathname.replace(/\\/g,"/").split('/');
return pieces.map(function (piece) {
piece = decodeURIComponent(piece);
if (process.platform === 'win32' && /\\/.test(piece)) {
throw new Error('Invalid forward slash character');
}
return piece;
}).join('/');
}
if (!module.parent) {
var defaults = require('./ecstatic/defaults.json')
var http = require('http'),
opts = require('minimist')(process.argv.slice(2), {
alias: require('./ecstatic/aliases.json'),
default: defaults,
boolean: Object.keys(defaults).filter(function (key) {
return typeof defaults[key] === 'boolean'
})
}),
envPORT = parseInt(process.env.PORT, 10),
port = envPORT > 1024 && envPORT <= 65536 ? envPORT : opts.port || opts.p || 8000,
dir = opts.root || opts._[0] || process.cwd();
if (opts.help || opts.h) {
var u = console.error;
u('usage: ecstatic [dir] {options} --port PORT');
u('see https://npm.im/ecstatic for more docs');
return;
}
http.createServer(ecstatic(dir, opts))
.listen(port, function () {
console.log('ecstatic serving ' + dir + ' at http://0.0.0.0:' + port);
});
}

34
www/node_modules/ecstatic/lib/ecstatic/aliases.json generated vendored Normal file
View File

@@ -0,0 +1,34 @@
{
"autoIndex": [ "autoIndex", "autoindex" ],
"showDir": [ "showDir", "showdir" ],
"showDotfiles": ["showDotfiles", "showdotfiles"],
"humanReadable": [ "humanReadable", "humanreadable", "human-readable" ],
"si": [ "si", "index" ],
"handleError": [ "handleError", "handleerror" ],
"cors": [ "cors", "CORS" ],
"headers": [ "H", "header", "headers" ],
"serverHeader": [ "serverHeader", "serverheader", "server-header" ],
"contentType": [ "contentType", "contenttype", "content-type" ],
"mimeType": [
"mimetype",
"mimetypes",
"mimeType",
"mimeTypes",
"mime-type",
"mime-types",
"mime-Type",
"mime-Types"
],
"weakEtags": [ "weakEtags", "weaketags", "weak-etags" ],
"weakCompare": [
"weakcompare",
"weakCompare",
"weak-compare",
"weak-Compare"
],
"handleOptionsMethod": [
"handleOptionsMethod",
"handleoptionsmethod",
"handle-options-method"
]
}

17
www/node_modules/ecstatic/lib/ecstatic/defaults.json generated vendored Normal file
View File

@@ -0,0 +1,17 @@
{
"autoIndex": true,
"showDir": true,
"showDotfiles": true,
"humanReadable": true,
"si": false,
"cache": "max-age=3600",
"cors": false,
"gzip": false,
"defaultExt": ".html",
"handleError": true,
"serverHeader": true,
"contentType": "application/octet-stream",
"weakEtags": false,
"weakCompare": false,
"handleOptionsMethod": false
}

7
www/node_modules/ecstatic/lib/ecstatic/etag.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
module.exports = function (stat, weakEtag) {
var etag = '"' + [stat.ino, stat.size, JSON.stringify(stat.mtime)].join('-') + '"';
if (weakEtag) {
etag = 'W/' + etag;
}
return etag;
}

180
www/node_modules/ecstatic/lib/ecstatic/opts.js generated vendored Normal file
View File

@@ -0,0 +1,180 @@
// This is so you can have options aliasing and defaults in one place.
var defaults = require('./defaults.json');
var aliases = require('./aliases.json')
module.exports = function (opts) {
var autoIndex = defaults.autoIndex,
showDir = defaults.showDir,
showDotfiles = defaults.showDotfiles,
humanReadable = defaults.humanReadable,
si = defaults.si,
cache = defaults.cache,
gzip = defaults.gzip,
defaultExt = defaults.defaultExt,
handleError = defaults.handleError,
headers = {},
serverHeader = defaults.serverHeader,
contentType = defaults.contentType,
mimeTypes,
weakEtags = defaults.weakEtags,
weakCompare = defaults.weakCompare,
handleOptionsMethod = defaults.handleOptionsMethod;
function isDeclared(k) {
return typeof opts[k] !== 'undefined' && opts[k] !== null;
}
if (opts) {
aliases.autoIndex.some(function (k) {
if (isDeclared(k)) {
autoIndex = opts[k];
return true;
}
});
aliases.showDir.some(function (k) {
if (isDeclared(k)) {
showDir = opts[k];
return true;
}
});
aliases.showDotfiles.some(function (k) {
if (isDeclared(k)) {
showDotfiles = opts[k];
return true;
}
});
aliases.humanReadable.some(function (k) {
if (isDeclared(k)) {
humanReadable = opts[k];
return true;
}
});
aliases.si.some(function (k) {
if (isDeclared(k)) {
si = opts[k];
return true;
}
});
if (opts.defaultExt && typeof opts.defaultExt === 'string') {
defaultExt = opts.defaultExt;
}
if (typeof opts.cache !== 'undefined' && opts.cache !== null) {
if (typeof opts.cache === 'string') {
cache = opts.cache;
}
else if (typeof opts.cache === 'number') {
cache = 'max-age=' + opts.cache;
}
else if (typeof opts.cache === 'function') {
cache = opts.cache
}
}
if (typeof opts.gzip !== 'undefined' && opts.gzip !== null) {
gzip = opts.gzip;
}
aliases.handleError.some(function (k) {
if (isDeclared(k)) {
handleError = opts[k];
return true;
}
});
aliases.cors.forEach(function(k) {
if (isDeclared(k) && k) {
handleOptionsMethod = true;
headers['Access-Control-Allow-Origin'] = '*';
headers['Access-Control-Allow-Headers'] = 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since';
}
});
aliases.headers.forEach(function (k) {
if (!isDeclared(k)) return;
if (Array.isArray(opts[k])) {
opts[k].forEach(setHeader);
}
else if (opts[k] && typeof opts[k] === 'object') {
Object.keys(opts[k]).forEach(function (key) {
headers[key] = opts[k][key];
});
}
else setHeader(opts[k]);
function setHeader (str) {
var m = /^(.+?)\s*:\s*(.*)$/.exec(str)
if (!m) headers[str] = true
else headers[m[1]] = m[2]
}
});
aliases.serverHeader.some(function (k) {
if (isDeclared(k)) {
serverHeader = opts[k];
return true;
}
});
aliases.contentType.some(function (k) {
if (isDeclared(k)) {
contentType = opts[k];
return true;
}
});
aliases.mimeType.some(function (k) {
if (isDeclared(k)) {
mimeTypes = opts[k];
return true;
}
});
aliases.weakEtags.some(function (k) {
if (isDeclared(k)) {
weakEtags = opts[k];
return true;
}
});
aliases.weakCompare.some(function (k) {
if (isDeclared(k)) {
weakCompare = opts[k];
return true;
}
});
aliases.handleOptionsMethod.some(function (k) {
if (isDeclared(k)) {
handleOptionsMethod = handleOptionsMethod || opts[k];
return true;
}
});
}
return {
cache: cache,
autoIndex: autoIndex,
showDir: showDir,
showDotfiles: showDotfiles,
humanReadable: humanReadable,
si: si,
defaultExt: defaultExt,
baseDir: (opts && opts.baseDir) || '/',
gzip: gzip,
handleError: handleError,
headers: headers,
serverHeader: serverHeader,
contentType: contentType,
mimeTypes: mimeTypes,
weakEtags: weakEtags,
weakCompare: weakCompare,
handleOptionsMethod: handleOptionsMethod
};
};

224
www/node_modules/ecstatic/lib/ecstatic/showdir.js generated vendored Normal file
View File

@@ -0,0 +1,224 @@
var ecstatic = require('../ecstatic'),
fs = require('fs'),
path = require('path'),
he = require('he'),
etag = require('./etag'),
url = require('url'),
status = require('./status-handlers');
module.exports = function (opts, stat) {
// opts are parsed by opts.js, defaults already applied
var cache = opts.cache,
root = path.resolve(opts.root),
baseDir = opts.baseDir,
humanReadable = opts.humanReadable,
handleError = opts.handleError,
showDotfiles = opts.showDotfiles,
si = opts.si,
weakEtags = opts.weakEtags;
return function middleware (req, res, next) {
// Figure out the path for the file from the given url
var parsed = url.parse(req.url),
pathname = decodeURIComponent(parsed.pathname),
dir = path.normalize(
path.join(root,
path.relative(
path.join('/', baseDir),
pathname
)
)
);
fs.stat(dir, function (err, stat) {
if (err) {
return handleError ? status[500](res, next, { error: err }) : next();
}
// files are the listing of dir
fs.readdir(dir, function (err, files) {
if (err) {
return handleError ? status[500](res, next, { error: err }) : next();
}
// Optionally exclude dotfiles from directory listing.
if (!showDotfiles) {
files = files.filter(function(filename){
return filename.slice(0,1) !== '.';
});
}
res.setHeader('content-type', 'text/html');
res.setHeader('etag', etag(stat, weakEtags));
res.setHeader('last-modified', (new Date(stat.mtime)).toUTCString());
res.setHeader('cache-control', cache);
sortByIsDirectory(files, function (lolwuts, dirs, files) {
// It's possible to get stat errors for all sorts of reasons here.
// Unfortunately, our two choices are to either bail completely,
// or just truck along as though everything's cool. In this case,
// I decided to just tack them on as "??!?" items along with dirs
// and files.
//
// Whatever.
// if it makes sense to, add a .. link
if (path.resolve(dir, '..').slice(0, root.length) == root) {
return fs.stat(path.join(dir, '..'), function (err, s) {
if (err) {
return handleError ? status[500](res, next, { error: err }) : next();
}
dirs.unshift([ '..', s ]);
render(dirs, files, lolwuts);
});
}
render(dirs, files, lolwuts);
});
function sortByIsDirectory(paths, cb) {
// take the listing file names in `dir`
// returns directory and file array, each entry is
// of the array a [name, stat] tuple
var pending = paths.length,
errs = [],
dirs = [],
files = [];
if (!pending) {
return cb(errs, dirs, files);
}
paths.forEach(function (file) {
fs.stat(path.join(dir, file), function (err, s) {
if (err) {
errs.push([file, err]);
}
else if (s.isDirectory()) {
dirs.push([file, s]);
}
else {
files.push([file, s]);
}
if (--pending === 0) {
cb(errs, dirs, files);
}
});
});
}
function render(dirs, files, lolwuts) {
// each entry in the array is a [name, stat] tuple
// TODO: use stylessheets?
var html = [
'<!doctype html>',
'<html>',
' <head>',
' <meta charset="utf-8">',
' <meta name="viewport" content="width=device-width">',
' <title>Index of ' + he.encode(pathname) +'</title>',
' </head>',
' <body>',
'<h1>Index of ' + he.encode(pathname) + '</h1>'
].join('\n') + '\n';
html += '<table>';
var failed = false;
var writeRow = function (file, i) {
// render a row given a [name, stat] tuple
var isDir = file[1].isDirectory && file[1].isDirectory();
var href = parsed.pathname.replace(/\/$/, '') + '/' + encodeURIComponent(file[0]);
// append trailing slash and query for dir entry
if (isDir) {
href += '/' + he.encode((parsed.search)? parsed.search:'');
}
var displayName = he.encode(file[0]) + ((isDir)? '/':'');
// TODO: use stylessheets?
html += '<tr>' +
'<td><code>(' + permsToString(file[1]) + ')</code></td>' +
'<td style="text-align: right; padding-left: 1em"><code>' + sizeToString(file[1], humanReadable, si) + '</code></td>' +
'<td style="padding-left: 1em"><a href="' + href + '">' + displayName + '</a></td>' +
'</tr>\n';
};
dirs.sort(function (a, b) { return a[0].toString().localeCompare(b[0].toString()); }).forEach(writeRow);
files.sort(function (a, b) { return a.toString().localeCompare(b.toString()); }).forEach(writeRow);
lolwuts.sort(function (a, b) { return a[0].toString().localeCompare(b[0].toString()); }).forEach(writeRow);
html += '</table>\n';
html += '<br><address>Node.js ' +
process.version +
'/ <a href="https://github.com/jfhbrook/node-ecstatic">ecstatic</a> ' +
'server running @ ' +
he.encode(req.headers.host || '') + '</address>\n' +
'</body></html>'
;
if (!failed) {
res.writeHead(200, { "Content-Type": "text/html" });
res.end(html);
}
}
});
});
};
};
function permsToString(stat) {
if (!stat.isDirectory || !stat.mode) {
return '???!!!???';
}
var dir = stat.isDirectory() ? 'd' : '-',
mode = stat.mode.toString(8);
return dir + mode.slice(-3).split('').map(function (n) {
return [
'---',
'--x',
'-w-',
'-wx',
'r--',
'r-x',
'rw-',
'rwx'
][parseInt(n, 10)];
}).join('');
}
// given a file's stat, return the size of it in string
// humanReadable: (boolean) whether to result is human readable
// si: (boolean) whether to use si (1k = 1000), otherwise 1k = 1024
// adopted from http://stackoverflow.com/a/14919494/665507
function sizeToString(stat, humanReadable, si) {
if (stat.isDirectory && stat.isDirectory()) {
return '';
}
var sizeString = '';
var bytes = stat.size;
var threshold = si ? 1000 : 1024;
if (!humanReadable || bytes < threshold) {
return bytes + 'B';
}
var units = [ 'k','M','G','T','P','E','Z','Y' ];
var u = -1;
do {
bytes /= threshold;
++u;
} while (bytes >= threshold);
var b = bytes.toFixed(1);
if (isNaN(b)) b = '??';
return b + units[u];
}

View File

@@ -0,0 +1,104 @@
var he = require('he');
// not modified
exports['304'] = function (res, next) {
res.statusCode = 304;
res.end();
};
// access denied
exports['403'] = function (res, next) {
res.statusCode = 403;
if (typeof next === "function") {
next();
}
else {
if (res.writable) {
res.setHeader('content-type', 'text/plain');
res.end('ACCESS DENIED');
}
}
};
// disallowed method
exports['405'] = function (res, next, opts) {
res.statusCode = 405;
if (typeof next === "function") {
next();
}
else {
res.setHeader('allow', (opts && opts.allow) || 'GET, HEAD');
res.end();
}
};
// not found
exports['404'] = function (res, next) {
res.statusCode = 404;
if (typeof next === "function") {
next();
}
else {
if (res.writable) {
res.setHeader('content-type', 'text/plain');
res.end('File not found. :(');
}
}
};
exports['416'] = function (res, next) {
res.statusCode = 416;
if (typeof next === "function") {
next();
}
else {
if (res.writable) {
res.setHeader('content-type', 'text/plain');
res.end('Requested range not satisfiable');
}
}
};
// flagrant error
exports['500'] = function (res, next, opts) {
res.statusCode = 500;
res.setHeader('content-type', 'text/html');
var error = String(opts.error.stack || opts.error || "No specified error"),
html = [
'<!doctype html>',
'<html>',
' <head>',
' <meta charset="utf-8">',
' <title>500 Internal Server Error</title>',
' </head>',
' <body>',
' <p>',
' ' + he.encode(error),
' </p>',
' </body>',
'</html>'
].join('\n') + '\n';
res.end(html);
};
// bad request
exports['400'] = function (res, next, opts) {
res.statusCode = 400;
res.setHeader('content-type', 'text/html');
var error = opts && opts.error ? String(opts.error) : 'Malformed request.',
html = [
'<!doctype html>',
'<html>',
' <head>',
' <meta charset="utf-8">',
' <title>400 Bad Request</title>',
' </head>',
' <body>',
' <p>',
' ' + he.encode(error),
' </p>',
' </body>',
'</html>'
].join('\n') + '\n';
res.end(html);
};

111
www/node_modules/ecstatic/package.json generated vendored Normal file
View File

@@ -0,0 +1,111 @@
{
"_args": [
[
{
"raw": "ecstatic@^1.4.0",
"scope": null,
"escapedName": "ecstatic",
"name": "ecstatic",
"rawSpec": "^1.4.0",
"spec": ">=1.4.0 <2.0.0",
"type": "range"
},
"/home/nau/MEGA/CODI/githubRepos/colspace/www/node_modules/http-server"
]
],
"_from": "ecstatic@>=1.4.0 <2.0.0",
"_id": "ecstatic@1.4.1",
"_inCache": true,
"_location": "/ecstatic",
"_nodeVersion": "4.2.1",
"_npmOperationalInternal": {
"host": "packages-16-east.internal.npmjs.com",
"tmp": "tmp/ecstatic-1.4.1.tgz_1462924279598_0.48026969679631293"
},
"_npmUser": {
"name": "jfhbrook",
"email": "josh.holbrook@gmail.com"
},
"_npmVersion": "2.14.16",
"_phantomChildren": {},
"_requested": {
"raw": "ecstatic@^1.4.0",
"scope": null,
"escapedName": "ecstatic",
"name": "ecstatic",
"rawSpec": "^1.4.0",
"spec": ">=1.4.0 <2.0.0",
"type": "range"
},
"_requiredBy": [
"/http-server"
],
"_resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-1.4.1.tgz",
"_shasum": "32cb7b6fa2e290d58668674d115e8f0c3d567d6a",
"_shrinkwrap": null,
"_spec": "ecstatic@^1.4.0",
"_where": "/home/nau/MEGA/CODI/githubRepos/colspace/www/node_modules/http-server",
"author": {
"name": "Joshua Holbrook",
"email": "josh@nodejitsu.com",
"url": "http://jesusabdullah.net"
},
"bin": {
"ecstatic": "./lib/ecstatic.js"
},
"bugs": {
"url": "https://github.com/jfhbrook/node-ecstatic/issues"
},
"dependencies": {
"he": "^0.5.0",
"mime": "^1.2.11",
"minimist": "^1.1.0",
"url-join": "^1.0.0"
},
"description": "A simple static file server middleware that works with both Express and Flatiron",
"devDependencies": {
"eol": "^0.2.0",
"express": "^4.12.3",
"mkdirp": "^0.5.0",
"request": "^2.49.0",
"tap": "^5.7.0"
},
"directories": {},
"dist": {
"shasum": "32cb7b6fa2e290d58668674d115e8f0c3d567d6a",
"tarball": "https://registry.npmjs.org/ecstatic/-/ecstatic-1.4.1.tgz"
},
"gitHead": "70751198635509a156ad1564296625fc753af89f",
"homepage": "https://github.com/jfhbrook/node-ecstatic",
"keywords": [
"static",
"web",
"server",
"files",
"mime",
"middleware"
],
"license": "MIT",
"main": "./lib/ecstatic.js",
"maintainers": [
{
"name": "jesusabdullah",
"email": "josh.holbrook@gmail.com"
},
{
"name": "jfhbrook",
"email": "josh.holbrook@gmail.com"
}
],
"name": "ecstatic",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/jfhbrook/node-ecstatic.git"
},
"scripts": {
"test": "tap test/*.js"
},
"version": "1.4.1"
}

7
www/node_modules/ecstatic/test.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
var fs = require('fs');
var stat = fs.statSync('./package.json'); // or some other file
console.log(stat.mtime);
console.log('' + stat.mtime);
console.log(JSON.stringify(stat.mtime));