Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

jsftp

Package Overview
Dependencies
Maintainers
1
Versions
84
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsftp - npm Package Compare versions

Comparing version 0.4.6 to 0.4.7

test/mockup_test.js

363

lib/jsftp.js

@@ -36,4 +36,38 @@ /*

var Ftp = module.exports = function(cfg) {
"use strict";
var Emitter = function() { EventEmitter.call(this); };
Util.inherits(Emitter, EventEmitter);
// Set up some properties used all around
this.emitter = new Emitter();
this.raw = {};
// This variable will be 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.pasvCallBuffer = [];
for (var option in cfg)
if (!this[option]) this[option] = cfg[option];
this.port = this.port || FTP_PORT;
COMMANDS.forEach(this._generateCmd.bind(this));
if (DEBUG_MODE) {
var self = this;
["command", "response", "connect", "reconnect", "disconnect"].forEach(function(event) {
self.emitter.on(event, self.log);
});
}
this._createSocket(this.port, this.host);
this._createStreams.call(this, this.socket);
};
// Queue function that maintains an ordered queue of streams.
var queue = function queue() {
Ftp.queue = function() {
var next;

@@ -57,77 +91,87 @@ var buffer = slice.call(arguments);

return stream;
};
}
// Enqueues an `element` in the `stream` object, which has to be a reference to
// a queue.
var enqueue = function enqueue(stream, element) {
stream._update.apply(null, slice.call(arguments, 1));
};
// Codes from 100 to 200 are FTP marks
var isMark = function isMark(code) {
Ftp.isMark = function(code) {
return code > 100 && code < 200;
};
var Ftp = module.exports = function(cfg) {
"use strict";
Ftp.parseEntry = function(entries) {
return entries.split(/\r\n|\n/)
.map(function(entry) {
return Parser.entryParser(entry.replace("\n", ""));
})
// Flatten the array
.filter(function(value){ return !!value; });
};
var Emitter = function() { EventEmitter.call(this); };
Util.inherits(Emitter, EventEmitter);
this.emitter = new Emitter();
Ftp.getPasvPort = function(text) {
var match = RE_PASV.exec(text);
if (!match) return false;
this.raw = {};
this.options = cfg;
// This variable will be 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.pasvCallBuffer = [];
return (parseInt(match[1], 10) & 255) * 256 + (parseInt(match[2], 10) & 255);
};
if (cfg) {
this.onError = cfg.onError;
this.onTimeout = cfg.onTimeout;
this.onConnect = cfg.onConnect;
}
var self = this;
var cmdfn = function(action, callback) {
// check whether the ftp user is authenticated at the moment of the
// enqueing. ideally this should happen in the `push` method, just
// before writing to the socket, but that would be complicated,
// since we would have to 'unshift' the auth chain into the queue
// or play the raw auth commands (that is, without enqueuing in
// order to not mess up the queue order. ideally, that would be
// built into the queue object. all this explanation to justify a
// slight slopiness in the code flow.
var authAndEnqueue = function() {
var isAuthCmd = /feat|user|pass/.test(action);
if (!self.authenticated && !isAuthCmd) {
self.auth(self.options.user, self.options.pass, function() {
enqueue(self.cmdQueue, [action, callback]);
});
}
else {
enqueue(self.cmdQueue, [action, callback]);
}
(function() {
this._createStreams = function(_socket) {
var self = this;
// Stream of incoming data from the FTP server.
var input = function(next, stop) {
_socket.on("connect", self.onConnect || function(){});
_socket.on("data", next);
_socket.on("end", stop);
_socket.on("error", stop);
_socket.on("close", stop);
};
if (self.socket && self.socket.writable) {
authAndEnqueue();
}
else if (!self.connecting) {
self.authenticated = false;
self._createSocket(self.port, self.host, function(_socket) {
createStreams(_socket);
authAndEnqueue();
var cmd;
this.cmdQueue = Ftp.queue();
(this.nextCmd = function nextCmd() {
S.head(self.cmdQueue)(function(obj) {
cmd(obj, self.nextCmd);
self.push(obj[0]);
});
}
})();
var parse = this.parse.bind(this);
// Zips (as in array zipping) commands with responses. This creates
// a stream that keeps yielding command/response pairs as soon as each pair
// becomes available.
S.zip(
// We ignore FTP marks for now. They don't convey useful
// information. A more elegant solution should be found in the
// future.
S.filter(function(x) { return !Ftp.isMark(x.code); },
self.serverResponse(input)),
// Stream of FTP commands from the client.
S.append(S.list(null), function(next, stop) { cmd = next; })
)
(parse, function() { self.emitter.emit("disconnect", "disconnect"); });
};
// generate generic methods from parameter names. they can easily be
/**
* Writes a new command to the server.
*
* @param {String} command Command to write in the FTP socket
* @returns void
*/
this.push = function(command) {
if (!command || typeof command !== "string")
return;
this.socket.write(command + "\r\n");
this.emitter.emit("command", this._sanitize(command));
};
this.enqueue = function enqueue() {
this.cmdQueue._update.apply(null, slice.call(arguments));
};
// 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.
COMMANDS.forEach(function(cmd) {
this._generateCmd = function(cmd) {
var self = this;
cmd = cmd.toLowerCase();
self.raw[cmd] = function() {
this.raw[cmd] = function() {
var callback;

@@ -137,82 +181,45 @@ var completeCmd = cmd;

var args = slice.call(arguments);
if (typeof args[args.length - 1] === "function")
callback = args.pop();
if (args.length)
completeCmd += " " + args.join(" ");
completeCmd += " " + args.join(" ");
}
cmdfn(completeCmd, callback || function(){});
self._enqueueCmd(completeCmd.trim(), callback || function(){});
};
});
if (DEBUG_MODE) {
this.emitter.on("command", this._log);
this.emitter.on("response", this._log);
this.emitter.on("connect", this._log);
this.emitter.on("reconnect", this._log);
this.emitter.on("disconnect", this._log);
}
this.host = cfg.host;
this.port = cfg.port || FTP_PORT;
this._createSocket(this.port, this.host);
// Writes a new command to the server, but before that it pushes the
// command into `cmds` list. This command will get paired with its response
// once that one is received
this.push = function(command, callback) {
if (!command || typeof command !== "string")
return;
this.socket.write(command + "\r\n");
self.emitter.emit("command", this._sanitize(command));
};
var createStreams;
(createStreams = function(_socket) {
var cmd;
// Stream of incoming data from the FTP server.
var input = function(next, stop) {
_socket.on("connect", self.onConnect || function(){});
_socket.on("data", next);
_socket.on("end", stop);
_socket.on("error", stop);
_socket.on("close", stop);
};
self.cmdQueue = queue();
(self.nextCmd = function nextCmd() {
S.head(self.cmdQueue)(function(obj) {
cmd(obj, self.nextCmd);
self.push(obj[0], obj[1] || function(){});
this._enqueueCmd = function(action, callback) {
if (this.socket && this.socket.writable) {
this._authAndEnqueue(action, callback);
}
else if (!this.connecting) {
var self = this;
this.authenticated = false;
this._createSocket(this.port, this.host, function(_socket) {
self._createStreams(_socket);
self._authAndEnqueue(action, callback);
});
})();
}
};
// check whether the ftp user is authenticated at the moment of the
// enqueing. ideally this should happen in the `push` method, just
// before writing to the socket, but that would be complicated,
// since we would have to 'unshift' the auth chain into the queue
// or play the raw auth commands (that is, without enqueuing in
// order to not mess up the queue order. ideally, that would be
// built into the queue object. all this explanation to justify a
// slight slopiness in the code flow.
this._authAndEnqueue = function(action, callback) {
var isAuthCmd = /feat|user|pass/.test(action);
if (!this.authenticated && !isAuthCmd) {
var self = this;
this.auth(this.user, this.pass, function() {
self.enqueue([action, callback]);
});
}
else {
this.enqueue([action, callback]);
}
};
// Zips (as in array zipping) commands with responses. This creates
// a stream that keeps yielding command/response pairs as soon as each pair
// becomes available.
var tasks = S.zip(
S.filter(function(x) {
// We ignore FTP marks for now. They don't convey useful
// information. A more elegant solution should be found in the
// future.
return !isMark(x.code);
},
self.serverResponse(input)
),
S.append(S.list(null), function(next, stop) {
// Stream of FTP commands from the client.
cmd = next;
})
);
tasks(self.parse.bind(self), function(err) {
self.emitter.emit("disconnect", "disconnect");
});
})(this.socket);
};
(function() {
this.addCmdListener = function(listener, action) {

@@ -266,4 +273,5 @@ this.emitter.on(action || "command", listener);

var code;
if (simpleRes) {
var code = parseInt(simpleRes[1], 10);
code = parseInt(simpleRes[1], 10);

@@ -314,3 +322,3 @@ if (buffer.length) {

* together. That is, each time that there is a round trip of actions
* between the client and the server. The `exp` param contains an array
* between the client and the server. The `action` param contains an array
* with the response from the server as a first element (text) and an array

@@ -336,3 +344,3 @@ * with the command executed and the callback (if any) as the second

// overgeneralize and consider every value above 399 as an error.
else if (ftpResponse && ftpResponse.code > 399) {
else if (ftpResponse.code > 399) {
var err = new Error(ftpResponse.text || "Unknown FTP error.");

@@ -369,4 +377,3 @@ err.code = ftpResponse.code;

this._sanitize = function(cmd) {
if (!cmd)
return;
if (!cmd) return;

@@ -380,2 +387,8 @@ var _cmd = cmd.slice(0, 5);

/**
* Returns true if the current server has the requested feature. False otherwise.
*
* @param {String} Feature to look for
* @returns {Boolean} Whether the current server has the feature
*/
this.hasFeat = function(feature) {

@@ -391,11 +404,7 @@ return this.features.indexOf(feature.toLowerCase()) > -1;

*/
this._parseFeats = function(featResult) {
var features = featResult.split(RE_NL);
if (features.length) {
// Ignore header and footer
features = features.slice(1, -1).map(function(feature) {
return /^\s*(\w*)\s*/.exec(feature)[1].trim().toLowerCase();
});
}
return features;
this._parseFeats = function(features) {
// Ignore header and footer
return features.split(RE_NL).slice(1, -1).map(function(feat) {
return (/^\s*(\w*)\s*/).exec(feat)[1].trim().toLowerCase();
});
};

@@ -425,15 +434,14 @@

*/
this.pendingRequests = [];
this.pending = []; // Pending requests
this.auth = function(user, pass, callback) {
var self = this;
this.pendingRequests.push(callback);
this.pending.push(callback);
function notifyAll(err, res) {
var cb;
while (cb = self.pendingRequests.shift())
while (cb = self.pending.shift())
cb(err, res);
}
if (this.authenticating)
return;
if (this.authenticating) return;

@@ -509,7 +517,5 @@ if (!user) user = "anonymous";

var match = RE_PASV.exec(res.text);
if (!match)
return callback("PASV: Bad port");
var port = Ftp.getPasvPort(res.text);
if (port === false) return callback(new Error("PASV: Bad port"));
var port = (parseInt(match[1], 10) & 255) * 256 + (parseInt(match[2], 10) & 255);
var socket = Net.createConnection(port, self.host);

@@ -524,6 +530,4 @@ // On each one of the events below we want to move on to the

self.raw.type("I", function(err, res) {
enqueue(self.cmdQueue, ["pasv", doPasv]);
});
}
self.raw.type("I", function() { self.enqueue(["pasv", doPasv]); });
};

@@ -555,3 +559,3 @@ // If there is a passive call happening, we put the requested passive

var cmdQueue = this.cmdQueue;
var self = this;
this.getPassiveSocket(function(err, socket) {

@@ -561,3 +565,3 @@ if (err) return callback(err);

concatStream(null, socket, callback);
enqueue(cmdQueue, ["list " + filePath]);
self.enqueue(["list " + filePath]);
});

@@ -567,8 +571,8 @@ };

this.get = function(filePath, callback) {
var cmdQueue = this.cmdQueue;
var self = this;
this.getPassiveSocket(function(err, socket) {
if (err) callback(err);
if (err) return callback(err);
concatStream(null, socket, callback);
enqueue(cmdQueue, ["retr " + filePath]);
self.enqueue(["retr " + filePath]);
});

@@ -580,3 +584,3 @@ };

this.getPassiveSocket(function(err, socket) {
if (err) callback(err);
if (err) return callback(err);
// Pause the socket to avoid data streaming before there are any

@@ -588,3 +592,3 @@ // listeners to it. We'll let the API consumer resume it.

callback(null, socket);
enqueue(self.cmdQueue, ["retr " + path]);
self.enqueue(["retr " + path]);
});

@@ -594,6 +598,7 @@ };

this.put = function(filepath, buffer, callback) {
var cmdQueue = this.cmdQueue;
var self = this;
this.getPassiveSocket(function(err, socket) {
if (err) { callback(err); }
enqueue(cmdQueue, ["stor " + filepath]);
if (err) return callback(err);
self.enqueue(["stor " + filepath]);
setTimeout(function() {

@@ -614,4 +619,4 @@ if (socket && socket.writable) {

this.getPassiveSocket(function(err, socket) {
if (err) callback(err);
enqueue(self.cmdQueue, ["stor " + filepath]);
if (err) return callback(err);
self.enqueue(["stor " + filepath]);
setTimeout(function() {

@@ -652,4 +657,3 @@ callback(null, socket);

var entriesToList = function(err, entries) {
if (err)
return callback(err);
if (err) return callback(err);

@@ -659,11 +663,3 @@ if (entries instanceof Buffer)

callback(null,
(entries.text || entries)
.split(/\r\n|\n/)
.map(function(entry) {
return Parser.entryParser(entry.replace("\n", ""));
})
// Flatten the array
.filter(function(value){ return !!value; })
);
callback(null, Ftp.parseEntry(entries.text || entries));
};

@@ -700,4 +696,3 @@

self.raw.rnfr(from, function(err, res) {
if (err)
return callback(err);
if (err) return callback(err);

@@ -739,3 +734,3 @@ self.raw.rnto(to, function(err, res) { callback(err, res); });

function concatStream(err, socket, callback) {
if (err) callback(err);
if (err) return callback(err);

@@ -742,0 +737,0 @@ var pieces = [];

{
"name": "jsftp",
"id": "jsftp",
"version": "0.4.6",
"version": "0.4.7",
"description": "A sane FTP client implementation for NodeJS",

@@ -6,0 +6,0 @@ "keywords": [ "ftp", "protocol", "files", "server", "client", "async" ],

jsftp [![Build Status](https://secure.travis-ci.org/sergi/jsftp.png)](http://travis-ci.org/sergi/jsftp)
=====
jsftp is a client FTP module for NodeJS that focuses on correctness, clarity and conciseness. It doesn't get in the middle of the user intentions.
jsftp is a client FTP library for NodeJS that focuses on correctness, clarity and conciseness. It doesn't get in the middle of the user intentions.

@@ -15,3 +15,3 @@ jsftp gives the user access to all the raw commands of FTP in form of methods in the `Ftp` object. It also provides several convenience methods for actions that require complex chains of commands (e.g. uploading and retrieving files). When commands succeed they always pass the response of the server to the callback, in the form of an object that contains two properties: `code`, which is the response code of the FTP operation, and `text`, which is the complete text of the response.

if (err)
throw err;
return console.error(err);

@@ -27,3 +27,3 @@ console.log("Bye!");

if (err)
throw err;
return console.error(err);

@@ -41,11 +41,7 @@ console.log(data.text); // Presenting the FTP response text to the user

// Initialize some common variables
var user = "johndoe";
var pass = "12345";
var ftp = new Ftp({
host: "myhost.com",
user: user,
port: 3334, // The port defaults to 21
pass: pass
user: "johndoe",
port: 3334, // Defaults to 21
pass: "12345"
});

@@ -58,7 +54,7 @@

// `ftp.get` is a convenience method. In this case, it hides the actual
// `ftp.get` is a convenience method. In this case, it hides the actual
// complexity of setting up passive mode and retrieving files.
ftp.get("/folder/file.ext", function(err, data) {
if (err)
console.error(err);
if (err)
return console.error(err);

@@ -72,4 +68,4 @@ // Do something with the buffer

ftp.raw.quit(function(err, res) {
if (err)
console.error(err);
if (err)
return console.error(err);

@@ -83,3 +79,3 @@ console.log("FTP session finalized! See you soon!");

if (err)
console.error(err);
return console.error(err);

@@ -92,3 +88,3 @@ console.log(data.text);

if (err)
console.error(err);
return console.error(err);

@@ -183,3 +179,3 @@ console.log(data.text);

Please note that for now the unit tests require python because the FTP server
used is written in python. In the future this dependency will not be there.
used is written in python.

@@ -191,2 +187,1 @@

See LICENSE.

@@ -1,2 +0,1 @@

#!/usr/bin/env node
/*

@@ -15,3 +14,2 @@ * @package jsftp

var Ftp = require("../");
var Parser = require('../lib/ftpParser');
var Path = require("path");

@@ -34,529 +32,2 @@

describe("jsftp file listing parser", function() {
it("test ftp unix LIST responses", function() {
var str = "211-Status of /:\r\n\
drwx--x--- 10 mrclash adm 4096 Aug 9 14:48 .\r\n\
drwx--x--- 10 mrclash adm 4096 Aug 9 14:48 ..\r\n\
-rw-r--r-- 1 mrclash pg223090 260 Mar 25 2008 .alias\r\n\
-rw------- 1 mrclash pg223090 2219 Sep 5 2010 .bash_history\r\n\
-rw-r--r-- 1 mrclash pg223090 55 Mar 25 2008 .bashrc\r\n\
drwx------ 2 mrclash pg223090 4096 Aug 9 14:39 .ssh\r\n\
-rw-r--r-- 1 mrclash pg223090 18 Aug 8 13:06 Cloud9 FTP connection test.\r\n\
-rwxr-xr-x 1 mrclash pg223090 68491314 Jan 22 2009 Documents.zip\r\n\
-rwxr-xr-x 1 mrclash pg223090 141 Nov 1 2008 EcPxMptYISIdOSjS.XFV.Q--.html\r\n\
dr-xr-x--- 7 mrclash dhapache 4096 May 29 07:47 logs\r\n\
drwxr-xr-x 7 mrclash pg223090 4096 Aug 9 14:48 re-alpine.git\r\n\
-rwxr-xr-x 1 mrclash pg223090 312115 Jan 22 2009 restaurants.csv\r\n\
drwxr-xr-x 12 mrclash pg223090 4096 Jul 24 02:42 sergimansilla.com\r\n\
drwxr-xr-x 10 mrclash pg223090 4096 Aug 3 2009 svn\r\n\
-rwxr-xr-x 1 mrclash pg223090 76 Aug 9 14:47 sync-alpine.sh\r\n\
drwxr-xr-x 2 mrclash pg223090 4096 Aug 4 10:00 test_c9\r\n\
-rw-r--r-- 1 mrclash pg223090 4 Aug 4 09:11 testfile.txt\r\n\
211 End of status";
var unixEntries = [
{
//line: "-rw-r--r-- 1 mrclash pg223090 260 Mar 25 2008 .alias",
type: 0,
size: 260,
name: ".alias",
time: +new Date("Mar 25 2008"),
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : false,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : false,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : false
},
{
//line: "-rw------- 1 mrclash pg223090 2219 Sep 5 2010 .bash_history",
type: 0,
size: 2219,
name: ".bash_history",
time: +new Date("Sep 5 2010"),
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : false,
groupReadPerm : false,
groupWritePerm : false,
groupExecPerm : false,
otherReadPerm : false,
otherWritePerm : false,
otherExecPerm : false
},
{
type: 0,
size: 55,
name: ".bashrc",
time: +new Date("Mar 25 2008"),
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : false,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : false,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : false
},
{
type: 1,
size: 4096,
name: ".ssh",
time: +new Date("Aug 9 14:39 " + new Date().getFullYear()),
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : true,
groupReadPerm : false,
groupWritePerm : false,
groupExecPerm : false,
otherReadPerm : false,
otherWritePerm : false,
otherExecPerm : false
},
{
type: 0,
size: 18,
name: "Cloud9 FTP connection test.",
time: +new Date("Aug 8 13:06 " + new Date().getFullYear()),
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : false,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : false,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : false
},
{
type: 0,
size: 68491314,
name: "Documents.zip",
time: +new Date("Jan 22 2009"),
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : true,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : true,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : true
},
{
type: 0,
size: 141,
name: "EcPxMptYISIdOSjS.XFV.Q--.html",
time: +new Date("Nov 1 2008"),
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : true,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : true,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : true
},
{
type: 1,
size: 4096,
name: "logs",
time: +new Date("May 29 07:47 " + new Date().getFullYear()),
owner: "mrclash",
group: "dhapache",
userReadPerm : true,
userWritePerm : false,
userExecPerm : true,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : true,
otherReadPerm : false,
otherWritePerm : false,
otherExecPerm : false
},
{
type: 1,
size: 4096,
name: "re-alpine.git",
time: +new Date("Aug 9 14:48 " + new Date().getFullYear()),
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : true,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : true,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : true
},
{
type: 0,
size: 312115,
time: +new Date("Jan 22 2009"),
name: "restaurants.csv",
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : true,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : true,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : true
},
{
type: 1,
size: 4096,
time: +new Date("Jul 24 02:42 " + new Date().getFullYear()),
name: "sergimansilla.com",
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : true,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : true,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : true
},
{
type: 1,
size: 4096,
time: +new Date("Aug 3 2009"),
name: "svn",
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : true,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : true,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : true
},
{
type: 0,
size: 76,
time: +new Date("Aug 9 14:47 " + new Date().getFullYear()),
name: "sync-alpine.sh",
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : true,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : true,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : true
},
{
type: 1,
size: 4096,
time: +new Date("Aug 4 10:00 " + new Date().getFullYear()),
name: "test_c9",
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : true,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : true,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : true
},
{
type: 0,
size: 4,
time: +new Date("Aug 4 09:11 " + new Date().getFullYear()),
name: "testfile.txt",
owner: "mrclash",
group: "pg223090",
userReadPerm : true,
userWritePerm : true,
userExecPerm : false,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : false,
otherReadPerm : true,
otherWritePerm : false,
otherExecPerm : false
}
];
var str2 = "211-Status of /www/userName/test:\
211-drwxr-x--- 2 userName alternc 4096 Aug 22 03:45 .\r\n\
211-drwxr-x--- 5 userName alternc 4096 Aug 22 03:45 ..\r\n\
211--rw-r----- 1 userName alternc 460 Aug 22 03:45 test1\r\n\
211--rw-r----- 1 userName alternc 560 Aug 22 03:47 test2\r\n\
211 End of status";
var unixEntries2 = [
{
//line: "-rw-r--r-- 1 mrclash pg223090 260 Mar 25 2008 .alias",
type: 0,
size: 460,
name: "test1",
time: +new Date("Aug 22 03:45 " + new Date().getFullYear()),
owner: "userName",
group: "alternc",
userReadPerm : true,
userWritePerm : true,
userExecPerm : false,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : false,
otherReadPerm : false,
otherWritePerm : false,
otherExecPerm : false
},
{
//line: "-rw-r--r-- 1 mrclash pg223090 260 Mar 25 2008 .alias",
type: 0,
size: 560,
name: "test2",
time: +new Date("Aug 22 03:47 " + new Date().getFullYear()),
owner: "userName",
group: "alternc",
userReadPerm : true,
userWritePerm : true,
userExecPerm : false,
groupReadPerm : true,
groupWritePerm : false,
groupExecPerm : false,
otherReadPerm : false,
otherWritePerm : false,
otherExecPerm : false
}
]
str
.split(/\r\n/)
.map(function(entry) {
return Parser.entryParser(entry.replace("\n", ""));
})
// Flatten the array
.filter(function(value){ return !!value; })
.forEach(function(entry, i) {
assert.equal(unixEntries[i].type, entry.type);
assert.equal(unixEntries[i].size, entry.size);
assert.equal(unixEntries[i].name, entry.name);
assert.equal(unixEntries[i].time, entry.time);
assert.equal(unixEntries[i].owner, entry.owner);
assert.equal(unixEntries[i].group, entry.group);
assert.equal(unixEntries[i].userReadPerm, entry.userPermissions.read);
assert.equal(unixEntries[i].userWritePerm, entry.userPermissions.write);
assert.equal(unixEntries[i].userExecPerm, entry.userPermissions.exec);
assert.equal(unixEntries[i].groupReadPerm, entry.groupPermissions.read);
assert.equal(unixEntries[i].groupWritePerm, entry.groupPermissions.write);
assert.equal(unixEntries[i].groupExecPerm, entry.groupPermissions.exec);
assert.equal(unixEntries[i].otherReadPerm, entry.otherPermissions.read);
assert.equal(unixEntries[i].otherWritePerm, entry.otherPermissions.write);
assert.equal(unixEntries[i].otherExecPerm, entry.otherPermissions.exec);
});
str2
.split(/\r\n/)
.map(function(entry) {
return Parser.entryParser(entry.replace("\n", ""));
})
// Flatten the array
.filter(function(value){ return !!value; })
.forEach(function(entry, i) {
assert.equal(unixEntries2[i].type, entry.type);
assert.equal(unixEntries2[i].size, entry.size);
assert.equal(unixEntries2[i].name, entry.name);
assert.equal(unixEntries2[i].time, entry.time);
assert.equal(unixEntries2[i].owner, entry.owner);
assert.equal(unixEntries2[i].group, entry.group);
assert.equal(unixEntries2[i].userReadPerm, entry.userPermissions.read);
assert.equal(unixEntries2[i].userWritePerm, entry.userPermissions.write);
assert.equal(unixEntries2[i].userExecPerm, entry.userPermissions.exec);
assert.equal(unixEntries2[i].groupReadPerm, entry.groupPermissions.read);
assert.equal(unixEntries2[i].groupWritePerm, entry.groupPermissions.write);
assert.equal(unixEntries2[i].groupExecPerm, entry.groupPermissions.exec);
assert.equal(unixEntries2[i].otherReadPerm, entry.otherPermissions.read);
assert.equal(unixEntries2[i].otherWritePerm, entry.otherPermissions.write);
assert.equal(unixEntries2[i].otherExecPerm, entry.otherPermissions.exec);
});
});
it("test ftp windows/DOS LIST responses" , function() {
var dosEntries = [
{
line: '04-27-00 09:09PM <DIR> licensed',
type: 1,
size: 0,
time: +(new Date("04-27-00 09:09 PM")),
name: 'licensed',
},
{
line: '11-18-03 10:16AM <DIR> pub',
type: 1,
size: 0,
time: +(new Date("11-18-03 10:16 AM")),
name: 'pub',
},
{
line: '04-14-99 03:47PM 589 readme.htm',
type: 0,
size: 589,
time: +(new Date("04-14-99 03:47 PM")),
name: 'readme.htm'
}
];
dosEntries.forEach(function(entry) {
var result = Parser.entryParser(entry.line);
assert.equal(result.type, entry.type);
assert.equal(result.size, entry.size);
assert.equal(result.name, entry.name);
assert.equal(result.time, entry.time);
});
});
/*
* We are not supporting MLSx commands yet
*
* http://rfc-ref.org/RFC-TEXTS/3659/chapter7.html
* http://www.rhinosoft.com/newsletter/NewsL2005-07-06.asp?prod=rs
*
"test parse MLSD command lines" : function(next) {
var lines = [
{
line: "Type=file;Size=17709913;Modify=20050502182143; Choices.mp3",
Type: "file",
Size: "17709913",
Modify: "20050502182143",
name: "Choices.mp3"
},
{
line: "Type=cdir;Perm=el;Unique=keVO1+ZF4; test",
type: "file",
perm: "el",
},
{
line: "Type=pdir;Perm=e;Unique=keVO1+d?3; .."
}
];
//"Type=cdir;Perm=el;Unique=keVO1+ZF4; test",
//"Type=pdir;Perm=e;Unique=keVO1+d?3; ..",
//"Type=OS.unix=slink:/foobar;Perm=;Unique=keVO1+4G4; foobar",
//"Type=OS.unix=chr-13/29;Perm=;Unique=keVO1+5G4; device",
//"Type=OS.unix=blk-11/108;Perm=;Unique=keVO1+6G4; block",
//"Type=file;Perm=awr;Unique=keVO1+8G4; writable",
//"Type=dir;Perm=cpmel;Unique=keVO1+7G4; promiscuous",
//"Type=dir;Perm=;Unique=keVO1+1t2; no-exec",
//"Type=file;Perm=r;Unique=keVO1+EG4; two words",
//"Type=file;Perm=r;Unique=keVO1+IH4; leading space",
//"Type=file;Perm=r;Unique=keVO1+1G4; file1",
//"Type=dir;Perm=cpmel;Unique=keVO1+7G4; incoming",
//"Type=file;Perm=r;Unique=keVO1+1G4; file2",
//"Type=file;Perm=r;Unique=keVO1+1G4; file3",
//"Type=file;Perm=r;Unique=keVO1+1G4; file4",
var parsed = Parser.parseMList(line);
assert.equal("file", parsed.Type);
assert.equal("17709913", parsed.Size);
assert.equal("20050502182143", parsed.Modify);
assert.equal("Choices.mp3", parsed.name);
next();
}
*/
})
describe("jsftp test suite", function() {

@@ -610,3 +81,2 @@ var ftp;

it("test initialize", function(next) {
assert.equal(ftp.options, FTPCredentials);
assert.equal(ftp.host, FTPCredentials.host);

@@ -802,3 +272,3 @@ assert.equal(ftp.port, FTPCredentials.port);

function handler() { counter++;};
function handler() { counter++; };
});

@@ -811,3 +281,3 @@

var parent, pathDir, path;
var path = remoteCWD + "/" + file1;
var path = remoteCWD + "/" + file1;

@@ -881,4 +351,4 @@ ftp.put(path, new Buffer("test"), function(err, res) {

function handler(err, res) {
assert.ok(!err);
if (++count == 6)
assert.ok(!err, err);
if (++count == 2)
next();

@@ -885,0 +355,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc