Comparing version 1.1.1 to 1.2.0
@@ -13,6 +13,8 @@ /* vim:set ts=2 sw=2 sts=2 expandtab */ | ||
var es = require("event-stream"); | ||
var responseHandler = require("./response"); | ||
var ResponseParser = require("ftp-response-parser"); | ||
var ListingParser = require("parse-listing"); | ||
var Utils = require("./utils"); | ||
var util = require("util"); | ||
var fs = require("fs"); | ||
var once = require("once"); | ||
@@ -50,13 +52,2 @@ var FTP_PORT = 21; | ||
function once(fn) { | ||
var returnValue, called = false; | ||
return function() { | ||
if (!called) { | ||
called = true; | ||
returnValue = fn.apply(this, arguments); | ||
} | ||
return returnValue; | ||
}; | ||
} | ||
var Ftp = module.exports = function(cfg) { | ||
@@ -78,3 +69,3 @@ "use strict"; | ||
this.cmdBuffer_ = []; | ||
this.responseHandler = responseHandler(); | ||
this.resParser = new ResponseParser(); | ||
@@ -114,6 +105,3 @@ // Generate generic methods from parameter names. they can easily be | ||
Ftp.prototype._createStreams = function(socket) { | ||
this.pipeline = es.pipeline( | ||
socket, | ||
es.split(), | ||
es.mapSync(this.responseHandler)); | ||
this.pipeline = es.pipeline(socket, this.resParser); | ||
@@ -123,3 +111,3 @@ var self = this; | ||
self.emit('data', data); | ||
self.parseResponse.call(self, data) | ||
self.parseResponse.call(self, data); | ||
}); | ||
@@ -137,3 +125,3 @@ this.pipeline.on("error", this.reemit("error")); | ||
var next = this.cmdBuffer_[0][1]; | ||
if (Utils.isMark(data.code)) { | ||
if (data.isMark) { | ||
// If we receive a Mark and it is not expected, we ignore | ||
@@ -208,3 +196,2 @@ // that command | ||
var self = this; | ||
function executeCmd() { | ||
@@ -235,7 +222,4 @@ self.cmdBuffer_.push([action, callback]); | ||
Ftp.prototype.parse = function(response, command) { | ||
// In FTP every response code above 399 means error in some way. | ||
// Since the RFC is not respected by many servers, we are going to | ||
// overgeneralize and consider every value above 399 as an error. | ||
var err = null; | ||
if (response.code > 399) { | ||
if (response.isError) { | ||
err = new Error(response.text || "Unknown FTP error."); | ||
@@ -280,14 +264,11 @@ err.code = response.code; | ||
var self = this; | ||
if (!this.features) | ||
this.raw.feat(function(err, response) { | ||
self.features = err ? [] : self._parseFeats(response.text); | ||
self.raw.syst(function(err, res) { | ||
if (!err && res.code === 215) | ||
self.system = res.text.toLowerCase(); | ||
this.raw.feat(function(err, response) { | ||
self.features = err ? [] : self._parseFeats(response.text); | ||
self.raw.syst(function(err, res) { | ||
if (!err && res.code === 215) | ||
self.system = res.text.toLowerCase(); | ||
callback(null, self.features); | ||
}); | ||
callback(null, self.features); | ||
}); | ||
else | ||
callback(null, self.features); | ||
}); | ||
}; | ||
@@ -464,3 +445,3 @@ | ||
if (res.code === 150) | ||
if (res.code === 125 || res.code === 150) | ||
callback(null, socket); | ||
@@ -542,3 +523,3 @@ else | ||
// Anything else is not relevant. | ||
if (res.code === 150) { | ||
if (res.code === 125 || res.code === 150) { | ||
socket.on('close', doneCallback); | ||
@@ -609,3 +590,4 @@ socket.on('error', doneCallback); | ||
} | ||
callback(null, Utils.parseEntry(entries.text || entries)); | ||
ListingParser.parseFtpEntries(entries.text || entries, callback); | ||
} | ||
@@ -612,0 +594,0 @@ |
@@ -1,74 +0,2 @@ | ||
var Parser = require("parse-listing"); | ||
var async = require("async"); | ||
var RE_RES = /^(\d\d\d)\s(.*)/; | ||
var RE_MULTI = /^(\d\d\d)-/; | ||
var RE_SERVER_RESPONSE = /^(\d\d\d)(.*)/; | ||
var Utils = module.exports = { | ||
// Codes from 100 to 200 are FTP marks | ||
isMark: function(code) { | ||
code = parseInt(code, 10); | ||
return code > 100 && code < 200; | ||
}, | ||
/** | ||
* Parse raw output of a file listing, trying in to clean up broken listings in | ||
* the process | ||
* @param {String} listing Raw file listing coming from a 'list' or 'stat' | ||
* @returns {Object[]} | ||
*/ | ||
parseEntry: function(listing) { | ||
var t, parsedEntry; | ||
var i = 0; | ||
var parsed = []; | ||
var splitEntries = listing.split(/\r\n|\n/); | ||
async.eachSeries(splitEntries, function(entry, next) { | ||
function _next() { | ||
i += 1; | ||
next(); | ||
} | ||
// Some servers include an official code-multiline sign at the beginning of | ||
// every string. We must strip it if that's the case. | ||
if (RE_MULTI.test(entry)) | ||
entry = entry.substr(3); | ||
entry = entry.trim(); | ||
// Filter file-listing results from 'STAT' command, since they include | ||
// server responses before and after the file listing. | ||
// Issue: https://github.com/sergi/jsftp/issues/3 | ||
if (RE_SERVER_RESPONSE.test(entry) || | ||
RE_RES.test(entry) || RE_MULTI.test(entry)) { | ||
return _next(); | ||
} | ||
parsedEntry = Parser.parseEntry(entry); | ||
if (parsedEntry === null) { | ||
if (splitEntries[i + 1]) { | ||
t = Parser.parseEntry(entry + splitEntries[i + 1]); | ||
if (t !== null) { | ||
splitEntries[i + 1] = entry + splitEntries[i + 1]; | ||
return _next(); | ||
} | ||
} | ||
if (splitEntries[i - 1] && parsed.length > 0) { | ||
t = Parser.parseEntry(splitEntries[i - 1] + entry); | ||
if (t !== null) { | ||
parsed[parsed.length - 1] = t; | ||
} | ||
} | ||
} | ||
else { | ||
if (parsedEntry) | ||
parsed.push(parsedEntry) | ||
} | ||
_next(); | ||
}); | ||
return parsed; | ||
}, | ||
getPasvPort: function(text) { | ||
@@ -100,3 +28,3 @@ var RE_PASV = /([-\d]+,[-\d]+,[-\d]+,[-\d]+),([-\d]+),([-\d]+)/; | ||
} | ||
} | ||
}; | ||
{ | ||
"name": "jsftp", | ||
"id": "jsftp", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"description": "A sane FTP client implementation for NodeJS", | ||
@@ -18,4 +18,4 @@ "keywords": [ "ftp", "protocol", "files", "server", "client", "async" ], | ||
"event-stream": "~3.0.14", | ||
"parse-listing": "~1.0.0", | ||
"async": "~0.2.9" | ||
"parse-listing": "~1.1.0", | ||
"once": "~1.3.0" | ||
}, | ||
@@ -22,0 +22,0 @@ "devDependencies": { |
@@ -26,3 +26,3 @@ 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> | ||
pass: "1234" // defaults to "@anonymous" | ||
}; | ||
}); | ||
``` | ||
@@ -172,3 +172,3 @@ | ||
```javascript | ||
ftp.get('remote/file.txt, 'local/file.txt, function(hadErr) { | ||
ftp.get('remote/file.txt', 'local/file.txt', function(hadErr) { | ||
if (hadErr) | ||
@@ -175,0 +175,0 @@ console.error('There was an error retrieving the file.'); |
@@ -148,3 +148,4 @@ /* | ||
code: 150, | ||
text: "150 File status okay; about to open data connection." | ||
text: "150 File status okay; about to open data connection.", | ||
isMark: true | ||
}; | ||
@@ -167,3 +168,4 @@ | ||
code: 150, | ||
text: "150 File status okay; about to open data connection." | ||
text: "150 File status okay; about to open data connection.", | ||
isMark: true | ||
}; | ||
@@ -200,7 +202,9 @@ | ||
code: 150, | ||
text: "150 File status okay; about to open data connection." | ||
text: "150 File status okay; about to open data connection.", | ||
isMark: true | ||
}; | ||
var data2 = { | ||
code: 226, | ||
text: "226 Transfer complete." | ||
text: "226 Transfer complete.", | ||
isMark: false | ||
}; | ||
@@ -210,3 +214,5 @@ | ||
["retr fakefile.txt", cb], | ||
["list /", function() {}] | ||
["list /", | ||
function() {} | ||
] | ||
]; | ||
@@ -237,15 +243,2 @@ ftp.parse = sinon.spy(); | ||
it("test getFeatures", function(next) { | ||
ftp.getFeatures(function(err, feats) { | ||
assert.ok(Array.isArray(feats)); | ||
assert.ok(Array.isArray(ftp.features)); | ||
assert.ok(ftp.system.length > 0); | ||
var feat = ftp.features[0]; | ||
assert.ok(ftp.hasFeat(feat)); | ||
assert.equal(false, ftp.hasFeat("madeup-feat")); | ||
next(); | ||
}); | ||
}); | ||
it("test print working directory", function(next) { | ||
@@ -289,22 +282,2 @@ ftp.raw.pwd(function(err, res) { | ||
it("test listing with bad line breaks", function(next) { | ||
var badStr = "\ | ||
213-Status follows:\r\n\ | ||
-rw-r--r-- 1 0 0 105981956 Dec 20 18:07 GAT\r\n\ | ||
SBY.MPG\r\n\ | ||
-rw-r--r-- 1 0 0 74450948 Jan 17 18:16 GIJO.MPG\r\n\ | ||
drwxr-xr-x 3 0 0 4096 Apr 16 2011 bourd\n\ | ||
arie\r\n\ | ||
drwxr-xr-x 2 0 0 4096 Apr 16 2011 denton\r\n\ | ||
213 End of status"; | ||
var entries = Utils.parseEntry(badStr); | ||
assert.equal("GATSBY.MPG", entries[0].name); | ||
assert.equal("GIJO.MPG", entries[1].name); | ||
assert.equal("bourdarie", entries[2].name); | ||
assert.equal("denton", entries[3].name); | ||
next(); | ||
}); | ||
it("test passive listing of current directory", function(next) { | ||
@@ -698,3 +671,3 @@ ftp.list(remoteCWD, function(err, res) { | ||
ftp.ls(paths[1], function showFile(err, res1) { | ||
assert.ok(!!err); | ||
assert.ok( !! err); | ||
processed += 1; | ||
@@ -701,0 +674,0 @@ if (processed === 2) next(); |
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
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
175876
31
1603
+ Addedonce@~1.3.0
+ Addedonce@1.3.3(transitive)
+ Addedparse-listing@1.1.3(transitive)
+ Addedwrappy@1.0.2(transitive)
- Removedasync@~0.2.9
- Removedasync@0.2.10(transitive)
- Removedparse-listing@1.0.1(transitive)
Updatedparse-listing@~1.1.0