diff --git a/lib/ftpd.js b/lib/ftpd.js index 4b6dd17..7e35e8b 100644 --- a/lib/ftpd.js +++ b/lib/ftpd.js @@ -24,8 +24,16 @@ var starttls = require('./starttls'); - maybe just for milesplit's use? */ -function pathEscape(text) { - text = text.replace(/\"/g, '""'); +function pathEscape(text) { + text = text.replace(/\"/g, '""').replace('\\', '/'); + var slashIndex = text.indexOf("/"); + + // Format path output for client + if(slashIndex != -1) + text = text.substring(slashIndex, text.length); + else + text = "/"; + return text; } @@ -36,7 +44,7 @@ function withCwd(cwd, path) { if (firstChar === '/' || firstChar === pathModule.sep) { cwd = pathModule.sep; } - path = pathModule.join(pathModule.sep, cwd, path); + path = pathModule.join(cwd, path); return path; } @@ -494,7 +502,7 @@ FtpConnection.prototype._command_AUTH = function(commandArg) { * Change working directory to parent directory * @return {FtpConnection} this */ -FtpConnection.prototype._command_CDUP = function () { +FtpConnection.prototype._command_CDUP = function () { var pathServer = pathModule.dirname(this.cwd); var pathEscaped = pathEscape(pathServer); this.cwd = pathServer; @@ -509,7 +517,13 @@ FtpConnection.prototype._command_CDUP = function () { */ FtpConnection.prototype._command_CWD = function (pathRequest) { var pathServer = withCwd(this.cwd, pathRequest); - var pathFs = pathModule.join(this.root, pathServer); + + // Prevent user from getting upper to his virtual root + if((pathRequest === '..') && (pathServer === '.')) + pathServer = this.cwd; + + var pathFs = pathModule.join(this.root, pathServer); + var pathEscaped = pathEscape(pathServer); this.fs.stat(pathFs, function (err, stats) { if (err) { @@ -530,6 +544,7 @@ FtpConnection.prototype._command_DELE = function(commandArg) { var self = this; var filename = withCwd(self.cwd, commandArg); + self.fs.unlink(pathModule.join(self.root, filename), function(err) { if (err) { self._logIf(0, "Error deleting file: " + filename + ", " + err); @@ -564,6 +579,7 @@ FtpConnection.prototype._command_FEAT = function(commandArg) { FtpConnection.prototype._command_MDTM = function (file) { file = withCwd(this.cwd, file); file = pathModule.join(this.root, file); + this.fs.stat(file, function (err, stats) { if (err) { this.respond("550 File unavailable"); @@ -610,6 +626,7 @@ FtpConnection.prototype._LIST = function(commandArg, detailed, cmd) { var dir = withCwd(self.cwd, dirname); glob.setMaxStatsAtOnce(self.server.options.maxStatsAtOnce); + glob.glob(pathModule.join(self.root, dir), self.fs, function(err, files) { if (err) { self._logIf(0, "While sending file list, reading directory: " + err); @@ -775,6 +792,7 @@ FtpConnection.prototype._listFiles = function(fileInfos, detailed, cmd) { FtpConnection.prototype._command_MKD = function (pathRequest) { var pathServer = withCwd(this.cwd, pathRequest); var pathEscaped = pathEscape(pathServer); + var pathFs = pathModule.join(this.root, pathServer); this.fs.mkdir(pathFs, 0755, function (err) { if (err) { @@ -1485,13 +1503,13 @@ FtpConnection.prototype._command_PASS = function (password) { } function setCwd(cwd) { function setRoot(root) { - self.root = root; + self.root = root; self.fs = userFsModule || fsModule; self.respond('230 User logged in, proceed.'); } self.cwd = cwd; - if (self.server.getRoot.length <= 1) { + if (self.server.getRoot.length <= 1) { setRoot(self.server.getRoot(self)); } else { @@ -1499,7 +1517,7 @@ FtpConnection.prototype._command_PASS = function (password) { if (err) { panic(err, 'getRoot'); } - else { + else { setRoot(root); } }); @@ -1514,7 +1532,7 @@ FtpConnection.prototype._command_PASS = function (password) { if (err) { panic(err, 'getInitialCwd'); } - else { + else { setCwd(withCwd(cwd)); } }); diff --git a/package.json b/package.json index 6aaf3b9..2dc2ea7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ftpd", - "version": "0.2.11", + "version": "0.2.12", "description": "Node FTP Server", "main": "./lib/ftpd.js", "scripts": { @@ -48,6 +48,10 @@ { "name": "asylumfunk", "url": "https://github.com/asylumfunk" + }, + { + "name": "fabiengb", + "url": "https://github.com/fabiengb" } ], "license": "BSD-2-Clause",