Compare commits

...

11 Commits

Author SHA1 Message Date
Douglas Christopher Wilson
838ee4cc02 1.4.1 2014-10-15 23:22:23 -04:00
Douglas Christopher Wilson
f332e6e576 deps: accepts@~1.1.2 2014-10-15 23:21:53 -04:00
Douglas Christopher Wilson
b866f9690a deps: mocha@~1.21.5 2014-10-15 23:20:50 -04:00
Douglas Christopher Wilson
ac94303941 1.4.0 2014-10-03 12:02:53 -04:00
Evgenus
cececc8c2e Add dir argument to filter function
fixes #11
closes #18
2014-10-03 11:45:59 -04:00
Evgenus
5e050a7d23 Support using tokens multiple times
closes #19
2014-10-03 11:17:30 -04:00
Douglas Christopher Wilson
5731ebee6b 1.3.1 2014-10-01 11:36:15 -04:00
Douglas Christopher Wilson
c6b9d3bdbf docs: fix non-https badge 2014-10-01 11:29:54 -04:00
Douglas Christopher Wilson
4686c18e1d deps: supertest@~0.14.0 2014-10-01 11:07:38 -04:00
Douglas Christopher Wilson
8a06bb7e19 deps: accepts@~1.1.1 2014-10-01 11:05:24 -04:00
Douglas Christopher Wilson
effbe1a4b0 Fix incorrect 403 on Windows and Node.js 0.11
fixes #17
2014-10-01 11:05:11 -04:00
6 changed files with 81 additions and 17 deletions

View File

@@ -1,3 +1,24 @@
1.4.1 / 2014-10-15
==================
* deps: accepts@~1.1.2
- Fix error when media type has invalid parameter
- deps: negotiator@0.4.9
1.4.0 / 2014-10-03
==================
* Add `dir` argument to `filter` function
* Support using tokens multiple times
1.3.1 / 2014-10-01
==================
* Fix incorrect 403 on Windows and Node.js 0.11
* deps: accepts@~1.1.1
- deps: mime-types@~2.0.2
- deps: negotiator@0.4.8
1.3.0 / 2014-09-20
==================

View File

@@ -35,7 +35,11 @@ Serve index accepts these properties in the options object.
##### filter
Apply this filter function to files. Defaults to `false`.
Apply this filter function to files. Defaults to `false`. The `filter` function
is called for each file, with the signature `filter(filename, index, files, dir)`
where `filename` is the name of the file, `index` is the array index, `files` is
the array of files and `dir` is the absolute path the file is located (and thus,
the directory the listing is for).
##### hidden
@@ -117,7 +121,7 @@ are created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/).
[travis-url]: https://travis-ci.org/expressjs/serve-index
[coveralls-image]: https://img.shields.io/coveralls/expressjs/serve-index.svg?style=flat
[coveralls-url]: https://coveralls.io/r/expressjs/serve-index?branch=master
[downloads-image]: http://img.shields.io/npm/dm/serve-index.svg?style=flat
[downloads-image]: https://img.shields.io/npm/dm/serve-index.svg?style=flat
[downloads-url]: https://npmjs.org/package/serve-index
[gittip-image]: https://img.shields.io/gittip/dougwilson.svg?style=flat
[gittip-url]: https://www.gittip.com/dougwilson/

View File

@@ -79,8 +79,9 @@ exports = module.exports = function serveIndex(root, options){
// root required
if (!root) throw new TypeError('serveIndex() root path required');
// resolve root to absolute
// resolve root to absolute and normalize
root = resolve(root);
root = normalize(root + sep);
var hidden = options.hidden
, icons = options.icons
@@ -102,21 +103,24 @@ exports = module.exports = function serveIndex(root, options){
// parse URLs
var url = parseUrl(req);
var originalUrl = parseUrl.original(req);
var dir = decodeURIComponent(url.pathname);
var originalDir = decodeURIComponent(originalUrl.pathname);
var dir = decodeURIComponent(url.pathname)
, path = normalize(join(root, dir))
, originalDir = decodeURIComponent(originalUrl.pathname)
var showUp = resolve(path) !== root;
// join / normalize from root dir
var path = normalize(join(root, dir));
// null byte(s), bad request
if (~path.indexOf('\0')) return next(createError(400));
// malicious path
if (path.substr(0, root.length) !== root) {
if ((path + sep).substr(0, root.length) !== root) {
debug('malicious path "%s"', path);
return next(createError(403));
}
// determine ".." display
var showUp = normalize(resolve(path) + sep) !== root;
// check if we have a directory
debug('stat "%s"', path);
fs.stat(path, function(err, stat){
@@ -138,7 +142,9 @@ exports = module.exports = function serveIndex(root, options){
fs.readdir(path, function(err, files){
if (err) return next(err);
if (!hidden) files = removeHidden(files);
if (filter) files = files.filter(filter);
if (filter) files = files.filter(function(filename, index, list) {
return filter(filename, index, list, path);
});
files.sort();
// content-negotiation
@@ -168,10 +174,10 @@ exports.html = function(req, res, files, next, dir, showUp, icons, path, view, t
files.sort(fileSort);
if (showUp) files.unshift({ name: '..' });
str = str
.replace('{style}', style.concat(iconStyle(files, icons)))
.replace('{files}', html(files, dir, icons, view))
.replace('{directory}', dir)
.replace('{linked-path}', htmlPath(dir));
.replace(/\{style\}/g, style.concat(iconStyle(files, icons)))
.replace(/\{files\}/g, html(files, dir, icons, view))
.replace(/\{directory\}/g, dir)
.replace(/\{linked-path\}/g, htmlPath(dir));
var buf = new Buffer(str, 'utf8');
res.setHeader('Content-Type', 'text/html; charset=utf-8');

View File

@@ -1,12 +1,12 @@
{
"name": "serve-index",
"description": "Serve directory listings",
"version": "1.3.0",
"version": "1.4.1",
"author": "Douglas Christopher Wilson <doug@somethingdoug.com>",
"license": "MIT",
"repository": "expressjs/serve-index",
"dependencies": {
"accepts": "~1.1.0",
"accepts": "~1.1.2",
"batch": "0.5.1",
"debug": "~2.0.0",
"mime-types": "~2.0.1",
@@ -14,9 +14,9 @@
},
"devDependencies": {
"istanbul": "0.3.2",
"mocha": "~1.21.1",
"mocha": "~1.21.5",
"should": "~4.0.0",
"supertest": "~0.13.0"
"supertest": "~0.14.0"
},
"files": [
"public/",

View File

@@ -6,6 +6,7 @@
</head>
<body class="directory">
<h1>This is the test template</h1>
<h2>directory {directory}</h2>
<div id="wrapper">
<h1>{linked-path}</h1>
{files}

View File

@@ -264,6 +264,26 @@ describe('serveIndex(root)', function () {
done()
});
});
it('should filter directory paths', function (done) {
var seen = false
var server = createServer(fixtures, {'filter': filter})
function filter(name, index, list, dir) {
if (path.normalize(dir) === path.normalize(path.join(fixtures, '/users'))) {
seen = true
}
return true
}
request(server)
.get('/users')
.expect(200, function (err, res) {
if (err) return done(err)
seen.should.be.true
done()
});
});
});
describe('with "icons" option', function () {
@@ -506,6 +526,18 @@ describe('serveIndex(root)', function () {
.set('Accept', 'text/html')
.expect(200, /ul#files/, done)
});
it('should list directory twice', function (done) {
request(server)
.get('/users/')
.set('Accept', 'text/html')
.expect(function (res) {
var occurances = res.text.match(/directory \/users\//g)
if (occurances && occurances.length === 2) return
throw new Error('directory not listed twice')
})
.expect(200, done)
});
});
describe('when setting a custom stylesheet', function () {