Comparing version 1.5.3 to 1.5.4
{ | ||
"version": "0.1.0", | ||
// List of configurations. Add new configurations or edit existing ones. | ||
// ONLY "node" and "mono" are supported, change "type" to switch. | ||
"configurations": [ | ||
{ | ||
// Name of configuration; appears in the launch configuration drop down menu. | ||
"name": "Launch app.js", | ||
// Type of configuration. Possible values: "node", "mono". | ||
"type": "node", | ||
// Workspace relative or absolute path to the program. | ||
"program": "app.js", | ||
// Automatically stop program after launch. | ||
"stopOnEntry": true, | ||
// Command line arguments passed to the program. | ||
"args": [], | ||
// Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace. | ||
"cwd": ".", | ||
// Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH. | ||
"runtimeExecutable": null, | ||
// Optional arguments passed to the runtime executable. | ||
"runtimeArguments": [], | ||
// Environment variables passed to the program. | ||
"env": { }, | ||
// Use JavaScript source maps (if they exist). | ||
"sourceMaps": false | ||
}, | ||
{ | ||
"name": "Attach", | ||
"type": "node", | ||
// TCP/IP address. Default is "localhost". | ||
"address": "localhost", | ||
// Port to attach to. | ||
"port": 5858, | ||
"sourceMaps": false | ||
} | ||
] | ||
} | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": "Launch", | ||
"type": "node", | ||
"request": "launch", | ||
"program": "${workspaceRoot}/jsftp.js", | ||
"stopOnEntry": false, | ||
"args": [], | ||
"cwd": "${workspaceRoot}", | ||
"preLaunchTask": null, | ||
"runtimeExecutable": null, | ||
"runtimeArgs": [ | ||
"--nolazy" | ||
], | ||
"env": { | ||
"NODE_ENV": "development" | ||
}, | ||
"externalConsole": false, | ||
"sourceMaps": false, | ||
"outDir": null | ||
}, | ||
{ | ||
"name": "Attach", | ||
"type": "node", | ||
"request": "attach", | ||
"port": 5858, | ||
"address": "localhost", | ||
"restart": false, | ||
"sourceMaps": false, | ||
"outDir": null, | ||
"localRoot": "${workspaceRoot}", | ||
"remoteRoot": null | ||
} | ||
] | ||
} |
262
lib/jsftp.js
@@ -29,3 +29,3 @@ /* vim:set ts=2 sw=2 sts=2 expandtab */ | ||
var IDLE_TIME = 30000; | ||
var NOOP = function() {}; | ||
var NOOP = function() { }; | ||
var COMMANDS = [ | ||
@@ -35,6 +35,6 @@ // Commands without parameters | ||
// Commands with one or more parameters | ||
'cwd', 'dele', 'list', 'mdtm', 'mkd', 'mode', 'nlst', 'pass', 'retr', 'rmd', | ||
'rnfr', 'rnto', 'site', 'stat', 'stor', 'type', 'user', 'xrmd', 'opts', | ||
'appe', 'cwd', 'dele', 'list', 'mdtm', 'mkd', 'mode', 'nlst', 'pass', 'retr', 'rmd', | ||
'rnfr', 'rnto', 'site', 'stat', 'stor', 'type', 'user', 'xrmd', 'opts', 'rest', | ||
// Extended features | ||
'chmod', 'size' | ||
'chmod', 'size', 'mlst', 'mlsdt', | ||
]; | ||
@@ -44,22 +44,21 @@ | ||
marks: [125, 150], | ||
ignore: 226 | ||
ignore: 226, | ||
}; | ||
// Regular Expressions | ||
var RE_PASV = /([-\d]+,[-\d]+,[-\d]+,[-\d]+),([-\d]+),([-\d]+)/; | ||
var FTP_NEWLINE = /\r\n|\n/; | ||
function getPasvPort(text, callback) { | ||
function getPasvPort(text) { | ||
var match = RE_PASV.exec(text); | ||
if (!match) { | ||
return callback(new Error('Bad passive host/port combination')); | ||
return null; | ||
} | ||
callback(null, { | ||
return { | ||
host: match[1].replace(/,/g, '.'), | ||
port: (parseInt(match[2], 10) & 255) * 256 + (parseInt(match[3], 10) & 255) | ||
}); | ||
port: (parseInt(match[2], 10) & 255) * 256 + (parseInt(match[3], 10) & 255), | ||
}; | ||
} | ||
function runCmd(cmd) { | ||
function runCmd() { | ||
var callback = NOOP; | ||
@@ -78,29 +77,28 @@ var args = [].slice.call(arguments); | ||
var Ftp = module.exports = function(cfg) { | ||
var self = this; | ||
Object.keys(cfg).forEach(function(option) { | ||
self[option] = self[option] || cfg[option]; | ||
}); | ||
EventEmitter.call(this); | ||
this.host = cfg.host || 'localhost'; | ||
this.port = cfg.port || FTP_PORT; | ||
this.user = cfg.user || 'anonymous'; | ||
this.pass = cfg.pass || '@anonymous'; | ||
// True if the server doesn't support the `stat` command. Since listing a | ||
// directory or retrieving file properties is quite a common operation, it is | ||
// more efficient to avoid the round-trip to the server. | ||
this.useList = false; | ||
this.port = this.port || FTP_PORT; | ||
this.useList = cfg.useList || false; | ||
this.commandQueue = []; | ||
EventEmitter.call(this); | ||
var self = this; | ||
// Generate generic methods from parameter names. they can easily be | ||
// overriden if we need special behavior. they accept any parameters given, | ||
// it is the responsability of the user to validate the parameters. | ||
this.raw = function() { return runCmd.apply(self, arguments); }; | ||
// it is the responsibility of the user to validate the parameters. | ||
this.raw = function() { | ||
return runCmd.apply(self, arguments); | ||
}; | ||
COMMANDS.forEach(function(cmd) { | ||
self.raw[cmd] = runCmd.bind(self, cmd); | ||
}); | ||
COMMANDS.forEach(function(cmd) { self.raw[cmd] = runCmd.bind(self, cmd); }); | ||
this.on('data', dbgResponse); | ||
this.on('data', function(data) { | ||
if (self.debugMode) | ||
self.emit('jsftp_debug', 'response', data || {}); | ||
}); | ||
this._createSocket(this.port, this.host); | ||
@@ -111,8 +109,2 @@ }; | ||
Ftp.prototype.setDebugMode = function(debugOn) { | ||
console.warn('`setDebugMode` is deprecated and will be removed in the ' + | ||
'future. For debugging, set the DEBUG env variable to 1.'); | ||
this.debugMode = (debugOn !== false); | ||
}; | ||
Ftp.prototype.reemit = function(event) { | ||
@@ -123,5 +115,2 @@ var self = this; | ||
debug('event:' + event, data || {}); | ||
if (self.debugMode) { | ||
self.emit('jsftp_debug', 'event:' + event, data || {}); | ||
} | ||
}; | ||
@@ -152,3 +141,3 @@ }; | ||
dbgResponse(data.text); | ||
self.parseResponse.call(self, data); | ||
self.parseResponse(data); | ||
}); | ||
@@ -159,4 +148,8 @@ this.pipeline.on('error', this.reemit('error')); | ||
Ftp.prototype.parseResponse = function(response) { | ||
if (this.commandQueue.length === 0) return; | ||
if ([220].indexOf(response.code) > -1) return; | ||
if (this.commandQueue.length === 0) { | ||
return; | ||
} | ||
if ([220].indexOf(response.code) > -1) { | ||
return; | ||
} | ||
@@ -167,3 +160,3 @@ var next = this.commandQueue[0].callback; | ||
if (!next.expectsMark || | ||
next.expectsMark.marks.indexOf(response.code) === -1) { | ||
next.expectsMark.marks.indexOf(response.code) === -1) { | ||
return; | ||
@@ -192,3 +185,5 @@ } | ||
Ftp.prototype.send = function(command) { | ||
if (!command) return; | ||
if (!command) { | ||
return; | ||
} | ||
@@ -198,5 +193,3 @@ dbgCommand(command); | ||
if (this.debugMode) { | ||
this.emit('jsftp_debug', 'user_command', command); | ||
} | ||
dbgCommand(command); | ||
}; | ||
@@ -239,6 +232,6 @@ | ||
action: action, | ||
callback: callback | ||
callback: callback, | ||
}; | ||
if (this.authenticated || /feat|syst|user|pass/.test(action)) { | ||
if (this.authenticated || /^(feat|syst|user|pass)/.test(action)) { | ||
this.commandQueue.push(cmd); | ||
@@ -298,4 +291,8 @@ this.nextCmd(); | ||
return featureLines | ||
.map(function(feat) { return feat.trim().toLowerCase(); }) | ||
.filter(function(feat) { return !!feat; }); | ||
.map(function(feat) { | ||
return feat.trim().toLowerCase(); | ||
}) | ||
.filter(function(feat) { | ||
return !!feat; | ||
}); | ||
}; | ||
@@ -337,4 +334,8 @@ | ||
if (!user) user = 'anonymous'; | ||
if (!pass) pass = '@anonymous'; | ||
if (!user) { | ||
user = 'anonymous'; | ||
} | ||
if (!pass) { | ||
pass = '@anonymous'; | ||
} | ||
@@ -348,3 +349,2 @@ this.authenticating = true; | ||
} | ||
self.raw.pass(pass, function(err, res) { | ||
@@ -377,3 +377,5 @@ self.authenticating = false; | ||
this.raw.type(type, function(err, data) { | ||
if (!err) self.type = type; | ||
if (!err) { | ||
self.type = type; | ||
} | ||
@@ -400,33 +402,39 @@ callback(err, data); | ||
self.getPasvSocket(function(err, socket) { | ||
if (err) return callback(err); | ||
self.getPasvSocket(function(err, socket) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
socket.setEncoding('utf8'); | ||
socket.on('data', function(data) { | ||
listing += data; | ||
}); | ||
socket.setEncoding('utf8'); | ||
socket.on('data', function(data) { | ||
listing += data; | ||
}); | ||
self.pasvTimeout.call(self, socket, callback); | ||
self.pasvTimeout(socket, callback); | ||
socket.once('close', function(err) { callback(err, listing); }); | ||
socket.once('error', callback); | ||
socket.once('close', function(err) { | ||
callback(err, listing); | ||
}); | ||
socket.once('error', callback); | ||
function cmdCallback(err, res) { | ||
if (err) return callback(err); | ||
function cmdCallback(err, res) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
var isExpectedMark = expectedMarks.marks.some(function(mark) { | ||
return mark === res.code; | ||
}); | ||
var isExpectedMark = expectedMarks.marks.some(function(mark) { | ||
return mark === res.code; | ||
}); | ||
if (!isExpectedMark) { | ||
callback(new Error( | ||
'Expected marks ' + expectedMarks.toString() + ' instead of: ' + | ||
res.text)); | ||
} | ||
if (!isExpectedMark) { | ||
callback(new Error( | ||
'Expected marks ' + expectedMarks.toString() + ' instead of: ' + | ||
res.text)); | ||
} | ||
} | ||
cmdCallback.expectsMark = expectedMarks; | ||
cmdCallback.expectsMark = expectedMarks; | ||
self.execute('list ' + (path || ''), cmdCallback); | ||
}); | ||
self.execute('list ' + (path || ''), cmdCallback); | ||
}); | ||
}; | ||
@@ -439,4 +447,3 @@ | ||
total: data.totalSize || 0, | ||
transferred: data.socket[ | ||
data.action === 'get' ? 'bytesRead' : 'bytesWritten'] | ||
transferred: data.socket[data.action === 'get' ? 'bytesRead' : 'bytesWritten'] | ||
}); | ||
@@ -487,3 +494,2 @@ }; | ||
socket.pipe(writeStream); | ||
socket.resume(); | ||
}; | ||
@@ -508,3 +514,5 @@ } | ||
this.getPasvSocket(function(err, socket) { | ||
if (err) return cmdCallback(err); | ||
if (err) { | ||
return cmdCallback(err); | ||
} | ||
@@ -518,3 +526,3 @@ socket.on('error', function(err) { | ||
self.pasvTimeout.call(self, socket, cmdCallback); | ||
self.pasvTimeout(socket, cmdCallback); | ||
socket.pause(); | ||
@@ -565,4 +573,5 @@ | ||
self.getPutSocket(to, function(err, socket) { | ||
if (err) return; | ||
from.pipe(socket); | ||
if (!err) { | ||
from.pipe(socket); | ||
} | ||
}, callback); | ||
@@ -573,3 +582,5 @@ } | ||
this.getPutSocket(to, function(err, socket) { | ||
if (!err) socket.end(from); | ||
if (!err) { | ||
socket.end(from); | ||
} | ||
}, callback); | ||
@@ -579,3 +590,3 @@ } else if (typeof from === 'string') { | ||
if (err && err.code === 'ENOENT') { | ||
return callback(new Error('Local file doesn\'t exist.')); | ||
return callback(new Error("Local file doesn't exist.")); | ||
} | ||
@@ -614,3 +625,5 @@ | ||
this.getPasvSocket(function(err, socket) { | ||
if (err) return _callback(err); | ||
if (err) { | ||
return _callback(err); | ||
} | ||
socket.on('close', doneCallback); | ||
@@ -620,3 +633,5 @@ socket.on('error', doneCallback); | ||
var putCallback = once(function putCallback(err, res) { | ||
if (err) return _callback(err); | ||
if (err) { | ||
return _callback(err); | ||
} | ||
@@ -626,3 +641,3 @@ // Mark 150 indicates that the 'STOR' socket is ready to receive data. | ||
if (res.code === 125 || res.code === 150) { | ||
self.pasvTimeout.call(self, socket, doneCallback); | ||
self.pasvTimeout(socket, doneCallback); | ||
return _callback(null, socket); | ||
@@ -640,3 +655,3 @@ } | ||
Ftp.prototype.pasvTimeout = function(socket, cb) { | ||
Ftp.prototype.pasvTimeout = function(socket, callback) { | ||
var self = this; | ||
@@ -647,3 +662,3 @@ socket.once('timeout', function() { | ||
socket.end(); | ||
cb(new Error('Passive socket timeout')); | ||
callback(new Error('Passive socket timeout')); | ||
}); | ||
@@ -657,18 +672,18 @@ }; | ||
this.execute('pasv', function(err, res) { | ||
if (err) return callback(err); | ||
if (err) { | ||
return callback(err); | ||
} | ||
getPasvPort(res.text, function(err, options) { | ||
if (err) return callback(err); | ||
var options = getPasvPort(res.text); | ||
if (!options) { | ||
return callback(new Error('Bad passive host/port combination')); | ||
} | ||
var socket = self._pasvSocket = Net.createConnection(options); | ||
socket.setTimeout(self.timeout || TIMEOUT); | ||
socket.once('connect', function() { | ||
self._pasvSocket = socket; | ||
}); | ||
socket.once('close', function() { | ||
self._pasvSocket = undefined; | ||
}); | ||
var socket = self._pasvSocket = Net.createConnection(options); | ||
socket.setTimeout(self.timeout || TIMEOUT); | ||
socket.once('close', function() { | ||
self._pasvSocket = undefined; | ||
}); | ||
callback(null, socket); | ||
}); | ||
callback(null, socket); | ||
}); | ||
@@ -706,14 +721,18 @@ }; | ||
function entriesToList(err, entries) { | ||
if (err) return callback(err); | ||
if (err) { | ||
return callback(err); | ||
} | ||
ListingParser.parseFtpEntries(entries.text || entries, function(err, files) { | ||
if (err) return callback(err); | ||
if (err) { | ||
return callback(err); | ||
} | ||
files.forEach(function(file) { | ||
// Normalize UTF8 doing canonical decomposition, followed by | ||
// canonical Composition | ||
file.name = unorm.nfc(file.name); | ||
}); | ||
callback(null, files); | ||
files.forEach(function(file) { | ||
// Normalize UTF8 doing canonical decomposition, followed by | ||
// canonical Composition | ||
file.name = unorm.nfc(file.name); | ||
}); | ||
callback(null, files); | ||
}); | ||
} | ||
@@ -730,8 +749,8 @@ | ||
// trips to the server to check. | ||
if ((err && (err.code === 502 || err.code === 500)) || | ||
(self.system && self.system.indexOf('hummingbird') > -1)) | ||
// Not sure if the 'hummingbird' system check ^^^ is still | ||
// necessary. If they support any standards, the 500 error | ||
// should have us covered. Let's leave it for now. | ||
{ | ||
var errored = (err && (err.code === 502 || err.code === 500)); | ||
var isHummingbird = self.system && self.system.indexOf('hummingbird') > -1; | ||
if (errored || isHummingbird) { | ||
// Not sure if the 'hummingbird' system check ^^^ is still | ||
// necessary. If they support any standards, the 500 error | ||
// should have us covered. Let's leave it for now. | ||
self.useList = true; | ||
@@ -749,7 +768,6 @@ self.list(filePath, entriesToList); | ||
this.raw.rnfr(from, function(err) { | ||
if (err) return callback(err); | ||
self.raw.rnto(to, function(err, res) { | ||
callback(err, res); | ||
}); | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.raw.rnto(to, callback); | ||
}); | ||
@@ -756,0 +774,0 @@ }; |
{ | ||
"name": "jsftp", | ||
"id": "jsftp", | ||
"version": "1.5.3", | ||
"version": "1.5.4", | ||
"description": "A sane FTP client implementation for NodeJS", | ||
@@ -24,19 +24,20 @@ "keywords": [ | ||
"dependencies": { | ||
"debug": "2.2.0", | ||
"event-stream": "3.1.7", | ||
"ftp-response-parser": "1.0.0", | ||
"once": "1.3.0", | ||
"parse-listing": "1.1.3", | ||
"unorm": "1.4.1" | ||
"debug": "^2.2.0", | ||
"event-stream": "^3.1.7", | ||
"ftp-response-parser": "^1.0.1", | ||
"once": "^1.3.3", | ||
"parse-listing": "^1.1.3", | ||
"unorm": "^1.4.1" | ||
}, | ||
"devDependencies": { | ||
"concat-stream": "1.5.0", | ||
"concat-stream": "^1.5.0", | ||
"ftp-test-server": "0.0.2", | ||
"istanbul": "0.3.22", | ||
"mocha": "1.21.4", | ||
"ftpd": "^0.2.15", | ||
"istanbul": "^0.3.22", | ||
"mocha": "^1.21.4", | ||
"mocha-istanbul": "0.2.0", | ||
"rimraf": "2.2.8", | ||
"sinon": "1.17.1" | ||
"rimraf": "^2.2.8", | ||
"sinon": "^1.17.1" | ||
}, | ||
"main": "./jsftp.js", | ||
"main": "lib/jsftp.js", | ||
"engines": { | ||
@@ -49,8 +50,3 @@ "node": ">=0.10" | ||
}, | ||
"licenses": [ | ||
{ | ||
"type": "MIT", | ||
"url": "https://github.com/sergi/jsftp/blob/master/LICENSE" | ||
} | ||
] | ||
"license": "MIT" | ||
} |
@@ -1,9 +0,15 @@ | ||
jsftp [![Build Status](https://secure.travis-ci.org/sergi/jsftp.png)](http://travis-ci.org/sergi/jsftp) <a href="http://flattr.com/thing/1452098/" target="_blank"><img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a> | ||
===== | ||
# jsftp [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![js-semistandard-style][semistandard-image]][semistandard-url] | ||
[travis-image]: https://img.shields.io/travis/sergi/jsftp.svg?style=flat | ||
[travis-url]: https://travis-ci.org/sergi/jsftp | ||
[npm-image]: https://img.shields.io/npm/v/jsftp.svg?style=flat | ||
[npm-url]: https://npmjs.org/package/jsftp | ||
[downloads-image]: https://img.shields.io/npm/dm/jsftp.svg?style=flat | ||
[downloads-url]: https://npmjs.org/package/jsftp | ||
[semistandard-image]: https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg?style=flat-square | ||
[semistandard-url]: https://github.com/Flet/semistandard | ||
A client FTP library for NodeJS that focuses on correctness, clarity | ||
and conciseness. It doesn't get in the way and plays nice with streaming APIs. | ||
[![NPM](https://nodei.co/npm/jsftp.png)](https://nodei.co/npm/jsftp/) | ||
Starting it up | ||
@@ -219,3 +225,3 @@ -------------- | ||
Ftp.setDebugMode(true); // Debug Mode on | ||
Ftp.setDebugMode(false; // Debug mode off | ||
Ftp.setDebugMode(false); // Debug mode off | ||
``` | ||
@@ -222,0 +228,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
282
3
2
47661
8
12
696
+ Addeddebug@2.6.9(transitive)
+ Addedevent-stream@3.3.5(transitive)
+ Addedftp-response-parser@1.0.1(transitive)
+ Addedmap-stream@0.0.7(transitive)
+ Addedms@2.0.0(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedsplit@1.0.1(transitive)
+ Addedstream-combiner@0.2.2(transitive)
+ Addedunorm@1.6.0(transitive)
+ Addedwrappy@1.0.2(transitive)
- Removeddebug@2.2.0(transitive)
- Removedevent-stream@3.1.7(transitive)
- Removedftp-response-parser@1.0.0(transitive)
- Removedmap-stream@0.1.0(transitive)
- Removedms@0.7.1(transitive)
- Removedonce@1.3.0(transitive)
- Removedsplit@0.2.10(transitive)
- Removedstream-combiner@0.0.4(transitive)
- Removedunorm@1.4.1(transitive)
Updateddebug@^2.2.0
Updatedevent-stream@^3.1.7
Updatedftp-response-parser@^1.0.1
Updatedonce@^1.3.3
Updatedparse-listing@^1.1.3
Updatedunorm@^1.4.1