From 0f0ef9ab2420f93bf4c08e16d1b97ebdf68b2abd Mon Sep 17 00:00:00 2001 From: "JK (Explorer-GUI)" Date: Tue, 30 Oct 2012 16:04:05 +0100 Subject: [PATCH] Bugfixing (Adding semicolon to fight against dynamical semicolon inseratation, Handeling windows paths in filepath(), Adding debugging logs) --- lib/paperboy.js | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/lib/paperboy.js b/lib/paperboy.js index b19c41f..6a0bc8d 100644 --- a/lib/paperboy.js +++ b/lib/paperboy.js @@ -5,13 +5,10 @@ var path = require('path'); exports.filepath = function (webroot, url) { - // Unescape URL to prevent security holes - url = decodeURIComponent(url); - // Append index.html if path ends with '/' - fp = path.normalize(path.join(webroot, (url.match(/\/$/)=='/') ? url+'index.html' : url)); - // Sanitize input, make sure people can't use .. to get above webroot - if (webroot[webroot.length - 1] !== '/') webroot += '/'; - if (fp.substr(0, webroot.length) != webroot) + fp = path.normalize(path.join(webroot, (url === '/') ? 'index.html' : url)); + //console.log('\nfilepath: ', fp, '\nsubstr: ', fp.substr(0,webroot.length + 1), '\n'); + //Sanitize input, make sure people can't use .. to get above webroot + if (fp.substr(0,webroot.length + 1) != path.normalize(webroot + '/')) return(['Permission Denied', null]); else return([null, fp]); @@ -20,16 +17,17 @@ exports.filepath = function (webroot, url) { exports.streamFile = function (filepath, headerFields, stat, res, req, emitter) { var emitter = new events.EventEmitter(), - extension = filepath.split('.').pop(), + extension = filepath.split('.').slice(-1), contentType = exports.contentTypes[extension] || 'application/octet-stream', charset = exports.charsets[contentType]; process.nextTick( function() { + if (charset) contentType += '; charset=' + charset; headerFields['Content-Type'] = contentType; - var etag = '"' + stat.ino + '-' + stat.size + '-' + Date.parse(stat.mtime) +'"'; + etag = '"' + stat.ino + '-' + stat.size + '-' + Date.parse(stat.mtime) +'"'; headerFields['ETag'] = etag; var statCode; @@ -50,7 +48,7 @@ exports.streamFile = function (filepath, headerFields, stat, res, req, emitter) res.writeHead(statCode, headerFields); //If we sent a 304, skip sending a body - if (statCode == 304 || req.method === 'HEAD') { + if (statCode == 304) { res.end(); emitter.emit("success", statCode); } @@ -110,22 +108,14 @@ exports.deliver = function (webroot, req, res) { }; process.nextTick(function() { - // Create default error and otherwise callbacks if none were given. - errorCallback = errorCallback || function(statCode) { - res.writeHead(statCode, {'Content-Type': 'text/html'}); - res.end("

HTTP " + statCode + "

"); - }; - otherwiseCallback = otherwiseCallback || function() { - res.writeHead(404, {'Content-Type': 'text/html'}); - res.end("

HTTP 404 File not found

"); - }; - + //console.log('fpRes: ', fpRes, '\nfpErr: ', fpErr, '\nwebroot: ', webroot); //If file is in a directory outside of the webroot, deny the request if (fpErr) { statCode = 403; if (beforeCallback) beforeCallback(); - errorCallback(403, 'Forbidden'); + if (errorCallback) + errorCallback(403, 'Forbidden'); } else { fs.stat(filepath, function (err, stat) { @@ -137,7 +127,7 @@ exports.deliver = function (webroot, req, res) { otherwiseCallback(exactErr); } else { //The before callback can abort the transfer by returning false - var cancel = beforeCallback && (beforeCallback() === false); + cancel = beforeCallback && (beforeCallback() === false); if (cancel && otherwiseCallback) { otherwiseCallback(); } @@ -194,7 +184,6 @@ exports.contentTypes = { "hqx": "application/mac-binhex40", "html": "text/html", "ice": "x-conference/x-cooltalk", - "ico": "image/x-icon", "ief": "image/ief", "igs": "model/iges", "ips": "application/x-ipscript", @@ -211,7 +200,6 @@ exports.contentTypes = { "m": "text/plain", "m3u": "audio/x-mpegurl", "man": "application/x-troff-man", - "manifest": "text/cache-manifest", "me": "application/x-troff-me", "midi": "audio/midi", "mif": "application/x-mif", @@ -263,7 +251,6 @@ exports.contentTypes = { "stp": "application/STEP", "sv4cpio": "application/x-sv4cpio", "sv4crc": "application/x-sv4crc", - "svg": "image/svg+xml", "swf": "application/x-shockwave-flash", "tar": "application/x-tar", "tcl": "application/x-tcl",