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

@icetee/ftp

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@icetee/ftp - npm Package Compare versions

Comparing version 0.3.15 to 1.0.0

.editorconfig

45

lib/connection.js

@@ -1,21 +0,23 @@

var fs = require('fs'),
tls = require('tls'),
zlib = require('zlib'),
Socket = require('net').Socket,
EventEmitter = require('events').EventEmitter,
inherits = require('util').inherits,
inspect = require('util').inspect,
StringDecoder = require('string_decoder').StringDecoder;
const fs = require('fs');
const tls = require('tls');
const zlib = require('zlib');
const XRegExp = require('xregexp');
var Parser = require('./parser');
var XRegExp = require('xregexp').XRegExp;
const { Socket } = require('net');
const { EventEmitter } = require('events');
const { inherits, inspect } = require('util');
const { StringDecoder } = require('string_decoder');
var REX_TIMEVAL = XRegExp.cache('^(?<year>\\d{4})(?<month>\\d{2})(?<date>\\d{2})(?<hour>\\d{2})(?<minute>\\d{2})(?<second>\\d+)(?:.\\d+)?$'),
RE_PASV = /([\d]+),([\d]+),([\d]+),([\d]+),([-\d]+),([-\d]+)/,
RE_EPSV = /([\d]+)/,
RE_EOL = /\r?\n/g,
RE_WD = /"(.+)"(?: |$)/,
RE_SYST = /^([^ ]+)(?: |$)/;
const Parser = require('./parser');
const {
REX_TIMEVAL,
RE_PASV,
RE_EPSV,
RE_EOL,
RE_WD,
RE_SYST,
RETVAL,
} = require('./expressions');
var /*TYPE = {
const /* TYPE = {
SYNTAX: 0,

@@ -28,10 +30,3 @@ INFO: 1,

},*/
RETVAL = {
PRELIM: 1,
OK: 2,
WAITING: 3,
ERR_TEMP: 4,
ERR_PERM: 5
},
/*ERRORS = {
/* ERRORS = {
421: 'Service not available, closing control connection',

@@ -38,0 +33,0 @@ 425: 'Can\'t open data connection',

@@ -1,244 +0,251 @@

var WritableStream = require('stream').Writable
|| require('readable-stream').Writable,
inherits = require('util').inherits,
inspect = require('util').inspect;
/* eslint prefer-destructuring: ["error", {VariableDeclarator: {object: true}}] */
var XRegExp = require('xregexp').XRegExp;
const XRegExp = require('xregexp');
const WritableStream = require('stream').Writable;
const { EventEmitter } = require('events');
const { inherits, inspect } = require('util');
const {
REX_LISTUNIX,
REX_LISTMSDOS,
RE_ENTRY_TOTAL,
RE_RES_END,
RE_EOL,
RE_DASH,
RE_SEP,
RE_EQ,
MONTHS,
} = require('./expressions');
var REX_LISTUNIX = XRegExp.cache('^(?<type>[\\-ld])(?<permission>([\\-r][\\-w][\\-xstT]){3})(?<acl>(\\+))?\\s+(?<inodes>\\d+)\\s+(?<owner>\\S+)\\s+(?<group>\\S+)\\s+(?<size>\\d+)\\s+(?<timestamp>((?<month1>\\w{3})\\s+(?<date1>\\d{1,2})\\s+(?<hour>\\d{1,2}):(?<minute>\\d{2}))|((?<month2>\\w{3})\\s+(?<date2>\\d{1,2})\\s+(?<year>\\d{4})))\\s+(?<name>.+)$'),
REX_LISTMSDOS = XRegExp.cache('^(?<month>\\d{2})(?:\\-|\\/)(?<date>\\d{2})(?:\\-|\\/)(?<year>\\d{2,4})\\s+(?<hour>\\d{2}):(?<minute>\\d{2})\\s{0,1}(?<ampm>[AaMmPp]{1,2})\\s+(?:(?<size>\\d+)|(?<isdir>\\<DIR\\>))\\s+(?<name>.+)$'),
RE_ENTRY_TOTAL = /^total/,
RE_RES_END = /(?:^|\r?\n)(\d{3}) [^\r\n]*\r?\n/,
RE_EOL = /\r?\n/g,
RE_DASH = /\-/g,
RE_SEP = /;/g,
RE_EQ = /=/;
class Parser extends EventEmitter {
constructor(options) {
super();
if (!(this instanceof Parser)) return new Parser(options);
var MONTHS = {
jan: 1, feb: 2, mar: 3, apr: 4, may: 5, jun: 6,
jul: 7, aug: 8, sep: 9, oct: 10, nov: 11, dec: 12
};
WritableStream.call(this);
function Parser(options) {
if (!(this instanceof Parser))
return new Parser(options);
WritableStream.call(this);
this.buffer = '';
this.debug = options.debug;
}
this._buffer = '';
this._debug = options.debug;
}
inherits(Parser, WritableStream);
static parseFeat(text) {
const lines = text.split(RE_EOL);
lines.shift(); // initial response line
lines.pop(); // final response line
Parser.prototype._write = function(chunk, encoding, cb) {
var m, code, reRmLeadCode, rest = '', debug = this._debug;
for (let i = 0, len = lines.length; i < len; ++i) {
lines[i] = lines[i].trim();
}
this._buffer += chunk.toString('binary');
return lines;
}
while (m = RE_RES_END.exec(this._buffer)) {
// support multiple terminating responses in the buffer
rest = this._buffer.substring(m.index + m[0].length);
if (rest.length)
this._buffer = this._buffer.substring(0, m.index + m[0].length);
write(chunk, encoding, cb) {
let m;
let code;
let reRmLeadCode;
let rest = '';
debug&&debug('[parser] < ' + inspect(this._buffer));
this.buffer += chunk.toString('binary');
// we have a terminating response line
code = parseInt(m[1], 10);
while (RE_RES_END.exec(this.buffer) !== null) {
m = RE_RES_END.exec(this.buffer);
// support multiple terminating responses in the buffer
rest = this.buffer.substring(m.index + m[0].length);
// RFC 959 does not require each line in a multi-line response to begin
// with '<code>-', but many servers will do this.
//
// remove this leading '<code>-' (or '<code> ' from last line) from each
// line in the response ...
reRmLeadCode = '(^|\\r?\\n)';
reRmLeadCode += m[1];
reRmLeadCode += '(?: |\\-)';
reRmLeadCode = new RegExp(reRmLeadCode, 'g');
var text = this._buffer.replace(reRmLeadCode, '$1').trim();
this._buffer = rest;
if (rest.length) {
this.buffer = this.buffer.substring(0, m.index + m[0].length);
}
debug&&debug('[parser] Response: code=' + code + ', buffer=' + inspect(text));
this.emit('response', code, text);
if (this.debug) console.error(`[parser] < ${inspect(this.buffer)}`);
// We have a terminating response line
code = parseInt(m[1], 10);
// RFC 959 does not require each line in a multi-line response to begin
// with '<code>-', but many servers will do this.
//
// remove this leading '<code>-' (or '<code> ' from last line) from each
// line in the response ...
reRmLeadCode = '(^|\\r?\\n)';
reRmLeadCode += m[1];
reRmLeadCode += '(?: |\\-)';
reRmLeadCode = new RegExp(reRmLeadCode, 'g');
const text = this.buffer.replace(reRmLeadCode, '$1').trim();
this.buffer = rest;
if (this.debug) console.error(`[parser] Response: code=${code}, buffer=${inspect(text)}`);
this.emit('response', code, text);
}
if (typeof cb === 'function') {
cb();
}
}
cb();
};
static parseListEntry(line) {
let ret = null;
let info;
let month;
let day;
let year;
let hour;
let mins;
const retUnix = XRegExp.exec(line, REX_LISTUNIX);
const retMsdos = XRegExp.exec(line, REX_LISTMSDOS);
Parser.parseFeat = function(text) {
var lines = text.split(RE_EOL);
lines.shift(); // initial response line
lines.pop(); // final response line
if (retUnix) {
info = {
type: retUnix.type,
name: undefined,
target: undefined,
sticky: false,
rights: {
user: retUnix.permission.substr(0, 3).replace(RE_DASH, ''),
group: retUnix.permission.substr(3, 3).replace(RE_DASH, ''),
other: retUnix.permission.substr(6, 3).replace(RE_DASH, ''),
},
acl: (retUnix.acl === '+'),
owner: retUnix.owner,
group: retUnix.group,
size: parseInt(retUnix.size, 10),
date: undefined,
};
for (var i = 0, len = lines.length; i < len; ++i)
lines[i] = lines[i].trim();
// Check for sticky bit
const lastbit = info.rights.other.slice(-1);
// just return the raw lines for now
return lines;
};
if (lastbit === 't') {
info.rights.other = `${info.rights.other.slice(0, -1)}x`;
info.sticky = true;
} else if (lastbit === 'T') {
info.rights.other = info.rights.other.slice(0, -1);
info.sticky = true;
}
Parser.parseListEntry = function(line) {
var ret,
info,
month, day, year,
hour, mins;
if (retUnix.month1 !== undefined) {
month = parseInt(MONTHS[retUnix.month1.toLowerCase()], 10);
day = parseInt(retUnix.date1, 10);
year = (new Date()).getFullYear();
hour = parseInt(retUnix.hour, 10);
mins = parseInt(retUnix.minute, 10);
if (ret = XRegExp.exec(line, REX_LISTUNIX)) {
info = {
type: ret.type,
name: undefined,
target: undefined,
sticky: false,
rights: {
user: ret.permission.substr(0, 3).replace(RE_DASH, ''),
group: ret.permission.substr(3, 3).replace(RE_DASH, ''),
other: ret.permission.substr(6, 3).replace(RE_DASH, '')
},
acl: (ret.acl === '+'),
owner: ret.owner,
group: ret.group,
size: parseInt(ret.size, 10),
date: undefined
};
if (month < 10) month = `0${month}`;
if (day < 10) day = `0${day}`;
if (hour < 10) hour = `0${hour}`;
if (mins < 10) mins = `0${mins}`;
// check for sticky bit
var lastbit = info.rights.other.slice(-1);
if (lastbit === 't') {
info.rights.other = info.rights.other.slice(0, -1) + 'x';
info.sticky = true;
} else if (lastbit === 'T') {
info.rights.other = info.rights.other.slice(0, -1);
info.sticky = true;
}
info.date = new Date(`${year}-${month}-${day}T${hour}:${mins}`);
if (ret.month1 !== undefined) {
month = parseInt(MONTHS[ret.month1.toLowerCase()], 10);
day = parseInt(ret.date1, 10);
year = (new Date()).getFullYear();
hour = parseInt(ret.hour, 10);
mins = parseInt(ret.minute, 10);
if (month < 10)
month = '0' + month;
if (day < 10)
day = '0' + day;
if (hour < 10)
hour = '0' + hour;
if (mins < 10)
mins = '0' + mins;
info.date = new Date(year + '-'
+ month + '-'
+ day + 'T'
+ hour + ':'
+ mins);
// If the date is in the past but no more than 6 months old, year
// isn't displayed and doesn't have to be the current year.
//
// If the date is in the future (less than an hour from now), year
// isn't displayed and doesn't have to be the current year.
// That second case is much more rare than the first and less annoying.
// It's impossible to fix without knowing about the server's timezone,
// so we just don't do anything about it.
//
// If we're here with a time that is more than 28 hours into the
// future (1 hour + maximum timezone offset which is 27 hours),
// there is a problem -- we should be in the second conditional block
if (info.date.getTime() - Date.now() > 100800000) {
info.date = new Date((year - 1) + '-'
+ month + '-'
+ day + 'T'
+ hour + ':'
+ mins);
// If the date is in the past but no more than 6 months old, year
// isn't displayed and doesn't have to be the current year.
//
// If the date is in the future (less than an hour from now), year
// isn't displayed and doesn't have to be the current year.
// That second case is much more rare than the first and less annoying.
// It's impossible to fix without knowing about the server's timezone,
// so we just don't do anything about it.
//
// If we're here with a time that is more than 28 hours into the
// future (1 hour + maximum timezone offset which is 27 hours),
// there is a problem -- we should be in the second conditional block
if (info.date.getTime() - Date.now() > 100800000) {
info.date = new Date(`${year - 1}-${month}-${day}T${hour}:${mins}`);
}
// If we're here with a time that is more than 6 months old, there's
// a problem as well.
// Maybe local & remote servers aren't on the same timezone (with remote
// ahead of local)
// For instance, remote is in 2014 while local is still in 2013. In
// this case, a date like 01/01/13 02:23 could be detected instead of
// 01/01/14 02:23
// Our trigger point will be 3600*24*31*6 (since we already use 31
// as an upper bound, no need to add the 27 hours timezone offset)
if (Date.now() - info.date.getTime() > 16070400000) {
info.date = new Date(`${year - 1}-${month}-${day}T${hour}:${mins}`);
}
} else if (retUnix.month2 !== undefined) {
month = parseInt(MONTHS[retUnix.month2.toLowerCase()], 10);
day = parseInt(retUnix.date2, 10);
year = parseInt(retUnix.year, 10);
if (month < 10) month = `0${month}`;
if (day < 10) day = `0${day}`;
info.date = new Date(`${year}-${month}-${day}`);
}
// If we're here with a time that is more than 6 months old, there's
// a problem as well.
// Maybe local & remote servers aren't on the same timezone (with remote
// ahead of local)
// For instance, remote is in 2014 while local is still in 2013. In
// this case, a date like 01/01/13 02:23 could be detected instead of
// 01/01/14 02:23
// Our trigger point will be 3600*24*31*6 (since we already use 31
// as an upper bound, no need to add the 27 hours timezone offset)
if (Date.now() - info.date.getTime() > 16070400000) {
info.date = new Date((year + 1) + '-'
+ month + '-'
+ day + 'T'
+ hour + ':'
+ mins);
if (retUnix.type === 'l') {
const pos = retUnix.name.indexOf(' -> ');
info.name = retUnix.name.substring(0, pos);
info.target = retUnix.name.substring(pos + 4);
} else {
info.name = retUnix.name;
}
} else if (ret.month2 !== undefined) {
month = parseInt(MONTHS[ret.month2.toLowerCase()], 10);
day = parseInt(ret.date2, 10);
year = parseInt(ret.year, 10);
if (month < 10)
month = '0' + month;
if (day < 10)
day = '0' + day;
info.date = new Date(year + '-' + month + '-' + day);
}
if (ret.type === 'l') {
var pos = ret.name.indexOf(' -> ');
info.name = ret.name.substring(0, pos);
info.target = ret.name.substring(pos+4);
} else
info.name = ret.name;
ret = info;
} else if (ret = XRegExp.exec(line, REX_LISTMSDOS)) {
info = {
name: ret.name,
type: (ret.isdir ? 'd' : '-'),
size: (ret.isdir ? 0 : parseInt(ret.size, 10)),
date: undefined,
};
month = parseInt(ret.month, 10),
day = parseInt(ret.date, 10),
year = parseInt(ret.year, 10),
hour = parseInt(ret.hour, 10),
mins = parseInt(ret.minute, 10);
if (year < 70)
year += 2000;
else
year += 1900;
ret = info;
} else if (retMsdos) {
info = {
name: retMsdos.name,
type: (retMsdos.isdir ? 'd' : '-'),
size: (retMsdos.isdir ? 0 : parseInt(retMsdos.size, 10)),
date: undefined,
};
if (ret.ampm[0].toLowerCase() === 'p' && hour < 12)
hour += 12;
else if (ret.ampm[0].toLowerCase() === 'a' && hour === 12)
hour = 0;
month = parseInt(retMsdos.month, 10);
day = parseInt(retMsdos.date, 10);
year = parseInt(retMsdos.year, 10);
hour = parseInt(retMsdos.hour, 10);
mins = parseInt(retMsdos.minute, 10);
info.date = new Date(year, month - 1, day, hour, mins);
year += (year < 70) ? 2000 : 1900;
ret = info;
} else if (!RE_ENTRY_TOTAL.test(line))
ret = line; // could not parse, so at least give the end user a chance to
// look at the raw listing themselves
if (retMsdos.ampm[0].toLowerCase() === 'p' && hour < 12) {
hour += 12;
} else if (retMsdos.ampm[0].toLowerCase() === 'a' && hour === 12) {
hour = 0;
}
return ret;
};
info.date = new Date(year, month - 1, day, hour, mins);
Parser.parseMlsdEntry = function(entry) {
var kvs = entry.split(RE_SEP);
var obj = { name: kvs.pop().substring(1) };
kvs.forEach(function(kv) {
kv = kv.split( RE_EQ );
obj[kv[0].toLowerCase()] = kv[1];
});
ret = info;
} else if (!RE_ENTRY_TOTAL.test(line)) {
// could not parse, so at least give the end user a chance to
// look at the raw listing themselves
ret = line;
}
obj.size = parseInt(obj.size, 10);
var modify = obj.modify;
if (modify) {
var year = modify.substr(0, 4);
var month = modify.substr(4, 2);
var date = modify.substr(6, 2);
var hour = modify.substr(8, 2);
var minute = modify.substr(10, 2);
var second = modify.substr(12, 2);
obj.date = new Date(
year + '-' + month + '-' + date + 'T' + hour + ':' +minute + ':' + second
);
return ret;
}
static parseMlsdEntry(entry) {
const kvs = entry.split(RE_SEP);
const obj = { name: kvs.pop().substring(1) };
kvs.forEach((kv) => {
kv = kv.split(RE_EQ);
obj[kv[0].toLowerCase()] = kv[1];
});
obj.size = parseInt(obj.size, 10);
if (obj.modify) {
const year = obj.modify.substr(0, 4);
const month = obj.modify.substr(4, 2);
const date = obj.modify.substr(6, 2);
const hour = obj.modify.substr(8, 2);
const minute = obj.modify.substr(10, 2);
const second = obj.modify.substr(12, 2);
obj.date = new Date(`${year}-${month}-${date}T${hour}:${minute}:${second}`);
}
return obj;
};
}
}
inherits(Parser, WritableStream);
module.exports = Parser;
{
"name": "@icetee/ftp",
"version": "0.3.15",
"version": "1.0.0",
"author": "Tamás András Horváth <htomy92@gmail.com>",

@@ -11,10 +11,9 @@ "contributors": [

"engines": {
"node": ">=0.8.0"
"node": ">=6.4.0"
},
"dependencies": {
"xregexp": "2.0.0",
"readable-stream": "1.1.x"
"xregexp": "^3.2.0"
},
"scripts": {
"test": "node test/test.js"
"test": "node ./node_modules/mocha/bin/_mocha --require babel-register ./test/*.spec.js"
},

@@ -26,12 +25,18 @@ "keywords": [

],
"licenses": [
{
"type": "MIT",
"url": "http://github.com/icetee/node-ftp/raw/master/LICENSE"
}
],
"license": "MIT",
"repository": {
"type": "git",
"url": "http://github.com/icetee/node-ftp.git"
},
"devDependencies": {
"babel-register": "^6.26.0",
"chai": "^4.1.2",
"dotenv": "^4.0.0",
"eslint": "^4.10.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.8.0",
"mocha": "^5.1.1",
"sinon": "^4.0.2",
"sinon-chai": "^2.14.0"
}
}

@@ -10,3 +10,3 @@ Description

* [node.js](http://nodejs.org/) -- v0.8.0 or newer
* [node.js](http://nodejs.org/) -- v6.4.0 or newer

@@ -13,0 +13,0 @@

Sorry, the diff of this file is not supported yet

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