Comparing version 0.5.4 to 0.5.5
@@ -41,4 +41,4 @@ #! /usr/bin/env node | ||
try { | ||
decodeURI(req.url); // check validity of url | ||
var pathname = decodeURI(parsed.pathname); | ||
decodeURIComponent(req.url); // check validity of url | ||
var pathname = decodePathname(parsed.pathname); | ||
} | ||
@@ -72,2 +72,67 @@ catch (err) { | ||
function statFile() { | ||
fs.stat(file, function (err, stat) { | ||
if (err && err.code === 'ENOENT') { | ||
if (req.statusCode == 404) { | ||
// This means we're already trying ./404.html | ||
status[404](res, next); | ||
} | ||
else if (defaultExt && !path.extname(parsed.pathname).length) { | ||
// | ||
// If no file extension is specified and there is a default extension | ||
// try that before rendering 404.html. | ||
// | ||
middleware({ | ||
url: parsed.pathname + '.' + defaultExt + ((parsed.search)? parsed.search:'') | ||
}, res, next); | ||
} | ||
else { | ||
// Try for ./404.html | ||
middleware({ | ||
url: (handleError ? ('/' + path.join(baseDir, '404.' + defaultExt)) : req.url), | ||
statusCode: 404 // Override the response status code | ||
}, 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: path.join(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 | ||
@@ -79,69 +144,10 @@ if (opts.gzip && shouldCompress(req)) { | ||
return serve(stat); | ||
} else { | ||
statFile(); | ||
} | ||
}); | ||
} else { | ||
statFile(); | ||
} | ||
fs.stat(file, function (err, stat) { | ||
if (err && err.code === 'ENOENT') { | ||
if (req.statusCode == 404) { | ||
// This means we're already trying ./404.html | ||
status[404](res, next); | ||
} | ||
else if (defaultExt && !path.extname(parsed.pathname).length) { | ||
// | ||
// If no file extension is specified and there is a default extension | ||
// try that before rendering 404.html. | ||
// | ||
middleware({ | ||
url: parsed.pathname + '.' + defaultExt + ((parsed.search)? parsed.search:'') | ||
}, res, next); | ||
} | ||
else { | ||
// Try for ./404.html | ||
middleware({ | ||
url: (handleError ? ('/' + path.join(baseDir, '404.' + defaultExt)) : req.url), | ||
statusCode: 404 // Override the response status code | ||
}, 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: path.join(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); | ||
} | ||
}); | ||
function serve(stat) { | ||
@@ -235,3 +241,18 @@ // Do a MIME lookup, fall back to octet-stream and handle gzip | ||
if(!module.parent) { | ||
// See: https://github.com/jesusabdullah/node-ecstatic/issues/109 | ||
function decodePathname(pathname) { | ||
var pieces = pathname.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 http = require('http'), | ||
@@ -242,3 +263,3 @@ opts = require('minimist')(process.argv.slice(2)), | ||
if(opts.help || opts.h) { | ||
if (opts.help || opts.h) { | ||
var u = console.error; | ||
@@ -245,0 +266,0 @@ u('usage: ecstatic [dir] {options} --port PORT'); |
var ecstatic = require('../ecstatic'), | ||
fs = require('fs'), | ||
path = require('path'), | ||
ent = require('ent'), | ||
he = require('he'), | ||
etag = require('./etag'), | ||
@@ -21,3 +21,3 @@ url = require('url'), | ||
var parsed = url.parse(req.url), | ||
pathname = decodeURI(parsed.pathname), | ||
pathname = decodeURIComponent(parsed.pathname), | ||
dir = path.normalize( | ||
@@ -47,8 +47,11 @@ path.join(root, | ||
sortByIsDirectory(files, function (errs, dirs, files) { | ||
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 (errs.length > 0) { | ||
return status[500](res, next, { error: errs[0] }); | ||
} | ||
// if it makes sense to, add a .. link | ||
@@ -61,6 +64,6 @@ if (path.resolve(dir, '..').slice(0, root.length) == root) { | ||
dirs.unshift([ '..', s ]); | ||
render(dirs, files); | ||
render(dirs, files, lolwuts); | ||
}); | ||
} | ||
render(dirs, files); | ||
render(dirs, files, lolwuts); | ||
}); | ||
@@ -84,3 +87,3 @@ | ||
if (err) { | ||
errs.push(err); | ||
errs.push([file, err]); | ||
} | ||
@@ -101,14 +104,16 @@ else if (s.isDirectory()) { | ||
function render(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"> \ | ||
<title>Index of ' + pathname +'</title> \ | ||
</head> \ | ||
<body> \ | ||
<h1>Index of ' + pathname + '</h1>\n'; | ||
var html = [ | ||
'<!doctype html>', | ||
'<html>', | ||
' <head>', | ||
' <meta charset="utf-8">', | ||
' <title>Index of ' + pathname +'</title>', | ||
' </head>', | ||
' <body>', | ||
'<h1>Index of ' + pathname + '</h1>' | ||
].join('\n') + '\n'; | ||
@@ -120,3 +125,3 @@ html += '<table>'; | ||
// render a row given a [name, stat] tuple | ||
var isDir = file[1].isDirectory(); | ||
var isDir = file[1].isDirectory && file[1].isDirectory(); | ||
var href = | ||
@@ -131,3 +136,3 @@ parsed.pathname.replace(/\/$/, '') + | ||
var displayName = ent.encode(file[0]) + ((isDir)? '/':''); | ||
var displayName = he.encode(file[0]) + ((isDir)? '/':''); | ||
@@ -142,4 +147,5 @@ // TODO: use stylessheets? | ||
dirs.sort(function (a, b) { return b[0] - a[0]; } ).forEach(writeRow); | ||
dirs.sort(function (a, b) { return b[0] - a[0]; }).forEach(writeRow); | ||
files.sort(function (a, b) { return b.toString().localeCompare(a.toString()); }).forEach(writeRow); | ||
lolwuts.sort(function (a, b) { return b[0] - a[0] }).forEach(writeRow); | ||
@@ -151,3 +157,3 @@ html += '</table>\n'; | ||
'server running @ ' + | ||
ent.encode(req.headers.host || '') + '</address>\n' + | ||
he.encode(req.headers.host || '') + '</address>\n' + | ||
'</body></html>' | ||
@@ -167,2 +173,7 @@ ; | ||
function permsToString(stat) { | ||
if (!stat.isDirectory || !stat.mode) { | ||
return '???!!!???'; | ||
} | ||
var dir = stat.isDirectory() ? 'd' : '-', | ||
@@ -190,3 +201,3 @@ mode = stat.mode.toString(8); | ||
function sizeToString(stat, humanReadable, si) { | ||
if (stat.isDirectory()) { | ||
if (stat.isDirectory && stat.isDirectory()) { | ||
return ''; | ||
@@ -199,7 +210,7 @@ } | ||
if(!humanReadable || bytes < threshold) { | ||
if (!humanReadable || bytes < threshold) { | ||
return bytes + 'B'; | ||
} | ||
var units = ['k','M','G','T','P','E','Z','Y']; | ||
var units = [ 'k','M','G','T','P','E','Z','Y' ]; | ||
var u = -1; | ||
@@ -210,3 +221,7 @@ do { | ||
} while (bytes >= threshold); | ||
return bytes.toFixed(1)+units[u]; | ||
var b = bytes.toFixed(1); | ||
if (isNaN(b)) b = '??'; | ||
return b + units[u]; | ||
} |
@@ -29,3 +29,3 @@ // not modified | ||
res.setHeader('allow', (opts && opts.allow) || 'GET, HEAD'); | ||
res.end(); | ||
res.end(); | ||
} | ||
@@ -32,0 +32,0 @@ }; |
@@ -5,3 +5,3 @@ { | ||
"description": "A simple static file server middleware that works with both Express and Flatiron", | ||
"version": "0.5.4", | ||
"version": "0.5.5", | ||
"homepage": "https://github.com/jesusabdullah/node-ecstatic", | ||
@@ -26,4 +26,4 @@ "repository": { | ||
"dependencies": { | ||
"he": "~0.4.1", | ||
"mime": "1.2.x", | ||
"ent": "0.0.x", | ||
"minimist": "~0.0.5" | ||
@@ -30,0 +30,0 @@ }, |
@@ -0,1 +1,4 @@ | ||
var fs = require('fs'), | ||
path = require('path'); | ||
module.exports = { | ||
@@ -84,3 +87,4 @@ 'a.txt' : { | ||
file: 'compress/foo.js.gz', | ||
headers: {'accept-encoding': 'compress, gzip'} | ||
headers: {'accept-encoding': 'compress, gzip'}, | ||
body: fs.readFileSync(path.join(__dirname, 'public', 'compress', 'foo.js.gz'), 'utf8') | ||
}, | ||
@@ -108,2 +112,5 @@ // no accept-encoding of gzip, so serve regular file | ||
body: '<h1>404</h1>\n' | ||
}, | ||
'containsSymlink/': { | ||
code: 200 | ||
} | ||
@@ -110,0 +117,0 @@ }; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
240397
44
1197
10
12
+ Addedhe@~0.4.1
+ Addedhe@0.4.1(transitive)
- Removedent@0.0.x
- Removedent@0.0.8(transitive)
- Removedpunycode@1.4.1(transitive)