New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

basic-ftp

Package Overview
Dependencies
Maintainers
1
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

basic-ftp - npm Package Compare versions

Comparing version 3.2.2 to 3.3.0

4

CHANGELOG.md
# Changelog
## 3.3.0
- Added: Support for leading whitespace in file and directory names.
## 3.2.2

@@ -4,0 +8,0 @@

44

dist/Client.d.ts

@@ -97,6 +97,2 @@ /// <reference types="node" />

/**
* Set the working directory.
*/
cd(path: string): Promise<FTPResponse>;
/**
* Get the current working directory.

@@ -106,6 +102,2 @@ */

/**
* Get the last modified time of a file. Not supported by every FTP server, method might throw exception.
*/
lastMod(filename: string): Promise<Date>;
/**
* Get a description of supported features.

@@ -119,5 +111,18 @@ *

/**
* Set the working directory.
*/
cd(path: string): Promise<FTPResponse>;
/**
* Switch to the parent directory of the working directory.
*/
cdup(): Promise<FTPResponse>;
/**
* Get the last modified time of a file. This is not supported by every FTP server, in which case
* calling this method will throw an exception.
*/
lastMod(path: string): Promise<Date>;
/**
* Get the size of a file.
*/
size(filename: String): Promise<number>;
size(path: string): Promise<number>;
/**

@@ -129,3 +134,3 @@ * Rename a file.

*/
rename(path: string, newPath: string): Promise<FTPResponse>;
rename(srcPath: string, destPath: string): Promise<FTPResponse>;
/**

@@ -137,3 +142,3 @@ * Remove a file from the current working directory.

*/
remove(filename: string, ignoreErrorCodes?: boolean): Promise<FTPResponse>;
remove(path: string, ignoreErrorCodes?: boolean): Promise<FTPResponse>;
/**

@@ -152,5 +157,5 @@ * Report transfer progress for any upload or download to a given handler.

* @param source The stream to read from.
* @param remoteFilename The filename of the remote file to write to.
* @param remotePath The path of the remote file to write to.
*/
upload(source: Readable, remoteFilename: string): Promise<FTPResponse>;
upload(source: Readable, remotePath: string): Promise<FTPResponse>;
/**

@@ -162,6 +167,6 @@ * Download a file with a given filename from the current working directory

* @param destination The stream to write to.
* @param remoteFilename The name of the remote file to read from.
* @param remotePath The name of the remote file to read from.
* @param startAt The offset to start at.
*/
download(destination: Writable, remoteFilename: string, startAt?: number): Promise<FTPResponse>;
download(destination: Writable, remotePath: string, startAt?: number): Promise<FTPResponse>;
/**

@@ -211,2 +216,11 @@ * List files and directories in the current working directory.

ensureDir(remoteDirPath: string): Promise<void>;
/**
* Remove an empty directory, will fail if not empty.
*/
protected removeEmptyDir(path: string): Promise<FTPResponse>;
/**
* FTP servers can't handle filenames that have leading whitespace. This method transforms
* a given path to fix that issue for most cases.
*/
protected protectWhitespace(path: string): Promise<string>;
}

@@ -164,8 +164,2 @@ "use strict";

/**
* Set the working directory.
*/
cd(path) {
return this.send("CWD " + path);
}
/**
* Get the current working directory.

@@ -184,15 +178,2 @@ */

/**
* Get the last modified time of a file. Not supported by every FTP server, method might throw exception.
*/
async lastMod(filename) {
const res = await this.send("MDTM " + filename);
// Message contains response code and modified time in the format: YYYYMMDDHHMMSS[.sss]
// For example `213 19991005213102` or `213 19980615100045.014`.
const msg = res.message;
const date = new Date();
date.setUTCFullYear(+msg.slice(4, 8), +msg.slice(8, 10) - 1, +msg.slice(10, 12));
date.setUTCHours(+msg.slice(12, 14), +msg.slice(14, 16), +msg.slice(16, 18), +msg.slice(19, 22));
return date;
}
/**
* Get a description of supported features.

@@ -220,6 +201,36 @@ *

/**
* Set the working directory.
*/
async cd(path) {
const validPath = await this.protectWhitespace(path);
return this.send("CWD " + validPath);
}
/**
* Switch to the parent directory of the working directory.
*/
async cdup() {
return this.send("CDUP");
}
/**
* Get the last modified time of a file. This is not supported by every FTP server, in which case
* calling this method will throw an exception.
*/
async lastMod(path) {
const validPath = await this.protectWhitespace(path);
const res = await this.send(`MDTM ${validPath}`);
// Message contains response code and modified time in the format: YYYYMMDDHHMMSS[.sss]
// For example `213 19991005213102` or `213 19980615100045.014`.
const msg = res.message;
const date = new Date();
date.setUTCFullYear(+msg.slice(4, 8), +msg.slice(8, 10) - 1, +msg.slice(10, 12));
date.setUTCHours(+msg.slice(12, 14), +msg.slice(14, 16), +msg.slice(16, 18), +msg.slice(19, 22));
return date;
}
/**
* Get the size of a file.
*/
async size(filename) {
const res = await this.send("SIZE " + filename);
async size(path) {
const validPath = await this.protectWhitespace(path);
const command = `SIZE ${validPath}`;
const res = await this.send(command);
// The size is part of the response message, for example: "213 555555". It's

@@ -229,3 +240,3 @@ // possible that there is a commmentary appended like "213 5555, some commentary".

if (Number.isNaN(size)) {
throw new Error(`Can't parse response to command 'SIZE ${filename}' as a numerical value: ${res.message}`);
throw new Error(`Can't parse response to command '${command}' as a numerical value: ${res.message}`);
}

@@ -240,5 +251,7 @@ return size;

*/
async rename(path, newPath) {
await this.send("RNFR " + path);
return this.send("RNTO " + newPath);
async rename(srcPath, destPath) {
const validSrc = await this.protectWhitespace(srcPath);
const validDest = await this.protectWhitespace(destPath);
await this.send("RNFR " + validSrc);
return this.send("RNTO " + validDest);
}

@@ -251,4 +264,5 @@ /**

*/
remove(filename, ignoreErrorCodes = false) {
return this.send("DELE " + filename, ignoreErrorCodes);
async remove(path, ignoreErrorCodes = false) {
const validPath = await this.protectWhitespace(path);
return this.send(`DELE ${validPath}`, ignoreErrorCodes);
}

@@ -271,7 +285,8 @@ /**

* @param source The stream to read from.
* @param remoteFilename The filename of the remote file to write to.
* @param remotePath The path of the remote file to write to.
*/
async upload(source, remoteFilename) {
async upload(source, remotePath) {
const validPath = await this.protectWhitespace(remotePath);
await this.prepareTransfer(this);
return upload(this.ftp, this.progressTracker, source, remoteFilename);
return upload(this.ftp, this.progressTracker, source, validPath);
}

@@ -284,9 +299,10 @@ /**

* @param destination The stream to write to.
* @param remoteFilename The name of the remote file to read from.
* @param remotePath The name of the remote file to read from.
* @param startAt The offset to start at.
*/
async download(destination, remoteFilename, startAt = 0) {
async download(destination, remotePath, startAt = 0) {
const validPath = await this.protectWhitespace(remotePath);
await this.prepareTransfer(this);
const command = startAt > 0 ? `REST ${startAt}` : `RETR ${remoteFilename}`;
return download(this.ftp, this.progressTracker, destination, command, remoteFilename);
const command = startAt > 0 ? `REST ${startAt}` : `RETR ${validPath}`;
return download(this.ftp, this.progressTracker, destination, command, validPath);
}

@@ -323,4 +339,4 @@ /**

if (workingDir !== "/") {
await this.send("CDUP");
await this.send("RMD " + remoteDirPath);
await this.cdup();
await this.removeEmptyDir(remoteDirPath);
}

@@ -337,7 +353,7 @@ }

await this.clearWorkingDir();
await this.send("CDUP");
await this.send("RMD " + file.name);
await this.cdup();
await this.removeEmptyDir(file.name);
}
else {
await this.send("DELE " + file.name);
await this.remove(file.name);
}

@@ -367,3 +383,3 @@ }

if (remoteDirName !== undefined) {
await this.send("CDUP");
await this.cdup();
}

@@ -383,3 +399,3 @@ }

await this.downloadDir(localPath);
await this.send("CDUP");
await this.cdup();
}

@@ -406,2 +422,23 @@ else {

}
/**
* Remove an empty directory, will fail if not empty.
*/
async removeEmptyDir(path) {
const validPath = await this.protectWhitespace(path);
return this.send(`RMD ${validPath}`);
}
/**
* FTP servers can't handle filenames that have leading whitespace. This method transforms
* a given path to fix that issue for most cases.
*/
async protectWhitespace(path) {
if (!path.startsWith(" ")) {
return path;
}
// Handle leading whitespace by prepending the absolute path:
// " test.txt" while being in the root directory becomes "/ test.txt".
const pwd = await this.pwd();
const absolutePathPrefix = pwd.endsWith("/") ? pwd : pwd + "/";
return absolutePathPrefix + path;
}
}

@@ -812,3 +849,3 @@ exports.Client = Client;

await uploadDirContents(client, fullPath);
await client.send("CDUP");
await client.cdup();
}

@@ -815,0 +852,0 @@ }

@@ -30,3 +30,3 @@ "use strict";

* + file has extended security attributes (e.g. ACL)
* Note: local listings on MacOSX also use '@';
* Note: local listings on MacOSX also use '@'
* this is not allowed for here as does not appear to be shown by FTP servers

@@ -70,3 +70,2 @@ * {@code @} file has extended attributes

exports.testLine = testLine;
;
function parseLine(line) {

@@ -76,3 +75,3 @@ const groups = line.match(RE_LINE);

// Ignore parent directory links
const name = groups[21].trim();
const name = groups[21];
if (name === "." || name === "..") {

@@ -129,3 +128,2 @@ return undefined;

exports.parseLine = parseLine;
;
function parseMode(r, w, x) {

@@ -132,0 +130,0 @@ let value = 0;

{
"name": "basic-ftp",
"version": "3.2.2",
"version": "3.3.0",
"description": "FTP client for Node.js, supports explicit FTPS over TLS, IPv6, Async/Await, and Typescript.",

@@ -5,0 +5,0 @@ "main": "dist/index",

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