Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ Instantiates a Connect server, setting up Superstatic middleware, port, host, de
* `errorPage` - A file path to a custom error page. Defaults to [Superstatic's error page](https://github.com/firebase/superstatic/blob/master/lib/assets/not_found.html).
* `debug` - A boolean value that tells Superstatic to show or hide network logging in the console. Defaults to `false`.
* `compression` - A boolean value that tells Superstatic to serve gzip/deflate compressed responses based on the request Accept-Encoding header and the response Content-Type header. Defaults to `false`.
* `symlink` - A boolean value that tells Superstatic to resolve and show also `symlink` files. Defaults to `false` to prevent `path traversal attacks`.
* `gzip` **[DEPRECATED]** - A boolean value which is now equivalent in behavior to `compression`. Defaults to `false`.

## Providers
Expand Down
6 changes: 6 additions & 0 deletions lib/cli/flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ module.exports = function(cli, options, ready) {
done();
});

cli.flag('--symlink')
.handler(function(shouldEnableSymlink, done) {
cli.set('symlink', shouldEnableSymlink);
done();
});

cli.flag('--gzip')
.handler(function(shouldCompress, done) {
cli.set('compression', shouldCompress);
Expand Down
2 changes: 2 additions & 0 deletions lib/cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var CONFIG_FILENAME = ['superstatic.json', 'firebase.json'];
var ENV_FILENAME = '.env.json';
var DEBUG = false;
var LIVE = false;
var SYMLINK = false;

var env;
try {
Expand All @@ -35,6 +36,7 @@ module.exports = function() {
cli.set('env', env);
cli.set('debug', DEBUG);
cli.set('live', LIVE);
cli.set('symlink', SYMLINK);

// If no commands matched, the user probably
// wants to run a server
Expand Down
5 changes: 3 additions & 2 deletions lib/cli/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ module.exports = function(cli, imports, ready) {
var compression = cli.get('compression');
var env = cli.get('env');
var live = cli.get('live');

var symlink = cli.get('symlink');
var workingDirectory = data[0];

var options = {
Expand All @@ -30,7 +30,8 @@ module.exports = function(cli, imports, ready) {
compression: compression,
debug: debug,
env: env,
live: live
live: live,
symlink: symlink
};

cli.set('options', options);
Expand Down
17 changes: 15 additions & 2 deletions lib/providers/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ var pathjoin = require('join-path');
var RSVP = require('rsvp');
var _ = require('lodash');

var statPromise = RSVP.denodeify(fs.stat);
var statPromise = RSVP.denodeify(fs.lstat);
var multiStat = function(paths) {
var pathname = paths.shift();
return statPromise(pathname).then(function(stat) {
stat.isSymb = stat.isSymbolicLink();
stat.path = pathname;
return stat;
}, function(err) {
Expand All @@ -30,6 +31,8 @@ module.exports = function(options) {
var etagCache = {};
var cwd = options.cwd || process.cwd();
var publicPaths = options.public || ['.'];
var symlink = options.symlink;

if (!_.isArray(publicPaths)) {
publicPaths = [publicPaths];
}
Expand Down Expand Up @@ -79,8 +82,18 @@ module.exports = function(options) {
});

return multiStat(fullPathnames).then(function(stat) {
foundPath = stat.path;
result.modified = stat.mtime.getTime();

if (!symlink) {
// Symlinks removed by default
if(stat.isSymb) {
return RSVP.reject({code: 'EINVAL'});
}

}

foundPath = stat.path;

result.size = stat.size;
return _fetchEtag(stat.path, stat);
}).then(function(etag) {
Expand Down
1 change: 1 addition & 0 deletions lib/responder.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var Responder = function(req, res, options) {
this.config = options.config || {};
this.rewriters = options.rewriters || {};
this.compressor = options.compressor;
this.symlink = options.symlink;
};

Responder.prototype.isNotModified = function(stats) {
Expand Down
7 changes: 5 additions & 2 deletions lib/superstatic.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ var superstatic = function(spec) {

// Set up provider
var provider = spec.provider ? promiseback(spec.provider, 2) : fsProvider(_.extend({
cwd: cwd // default current working directory
cwd: cwd, // default current working directory
symlink: spec.symlink // symlink
}, config));

// Select compression middleware
Expand All @@ -55,13 +56,15 @@ var superstatic = function(spec) {
compressor = null;
}


// Setup helpers
router.use(function(req, res, next) {
res.superstatic = new Responder(req, res, {
provider: provider,
config: config,
compressor: compressor,
rewriters: spec.rewriters
rewriters: spec.rewriters,
symlink: spec.symlink
});

next();
Expand Down