Code Monkey home page Code Monkey logo

nodeftpd's Introduction

Simple, Extensible FTP Server in Pure JavaScript

Build Status

Introduction

This is a simple but very configurable FTP server. Notable features include:

  • Abstracts out the fs module, so you can use any implementation, even on a per-user basis. This makes it possible for each user to have his/her own virtual file system, isolated from that of the system or other users.
  • Provides hooks for handling authentication, content modification, etc.
  • Supports TLS with explicit AUTH.

Installation

npm install ftpd

Usage

See example code in test.js

FtpServer options:

host (string) - IP Address

host is a string representation of the IP address clients use to connect to the FTP server. It's imperative that this actually reflects the remote IP the clients use to access the server, as this IP will be used in the establishment of PASV data connections. If this IP is not the one clients use to connect, you will see some strange behavior from the client side (hangs).

options (object) - Configuration

See test.js for a simple example. FtpServer accepts the following options:

Path Configurations

Both these need to be set - there are no defaults.

  • getInitialCwd: Gets the initial working directory for the user. Called after user is authenticated. This path is relative to the root directory. The user may escape their initial cwd.

    • Pattern: function(username, [callback(err, path)])

    • Arguments:

      • username (string): the username to get CWD for
      • callback (function, optional):
    • Examples:

      • Simplest usage, no callback, just return:
          getInitialCwd: function(connection) {
            return "/" + connection.username;
          }
      • Usage with callback:
          getInitialCwd: function(connection, callback) {
            var userDir = '/' + connection.username;
            fs.exists(userDir, function(exists) {
              if (exists) {
                callback(null, userDir);
              } else {
                fs.mkDir(userDir, function(err) {
                  callback(err, userDir);
                });
              }
            });
          }
          // If the directory exists, callback immediately with that directory
          // If not, create the directory and callback possible error + directory
      • Typical cases where you would want/need the callback involve retrieving configurations from external datasources and suchlike.
  • getRoot: Gets the root directory for the user. This directory has the path '/' from the point of view of the user. The user is not able to escape this directory.

    • Pattern: function(connection, [callback(err, rootPath)])

    • Arguments:

      • connection (object): the connection for which to get root
      • callback (function, optional):
    • Examples:

          getRoot: function() {
            return process.cwd();
          }
          // The users will now enter at the '/' level, which is the directory passed to getInitialCwd.
      • Usage with callback:
          getRoot: function(connection, callback) {
            var rootPath = process.cwd() + '/' + connection.username;
            fs.exists(rootPath, function(exists) {
              if (exists) {
                callback(null, rootPath);
              } else {
                fs.mkDir(userDir, function(err) {
                  if (err) {
                    callback(null, '/'); // default to root
                  } else {
                    callback(err, rootPath);
                  }
                });
              }
            });
          }
          // If the subdir exists, callback immediately with relative path to that directory
          // If not, create the directory, and callback relative path to the directory
          // Stupidly, instead of failing, we apparently want 'worst case' scenario to allow relative root.
      • Typical cases where you would want/need the callback involve retrieving configurations from external datasources and suchlike.
      • Additionally, you may want to provide emulation of a path, for instance /users/(username)/ftproot.
File/handling Configurations
  • useWriteFile: (default: false)
    • If set to true, then files which the client uploads are buffered in memory and then written to disk using writeFile.
    • If false, files are written using writeStream.
  • useReadFile: (default: false)
    • If set to true, then files which the client downloads are slurped using 'readFile'.
    • If false, files are read using readStream.
  • uploadMaxSlurpSize: (default: unlimited)
    • Determines the maximum file size (in bytes) for which uploads are buffered in memory before being written to disk.
    • Has an effect only if useWriteFile is set to true.
    • If uploadMaxSlurpSize is not set, then there is no limit on buffer size.
  • hideDotFiles: (default: false)
    • Hides files beginning with a dot (UNIX hidden files) on LIST commands.
  • maxStatsAtOnce: (default: 5)
    • The maximum number of concurrent calls to fs.stat which will be made when processing a LIST request.
  • filenameSortFunc: (default: localeCompare)
  • filenameSortMap: (default: function (x) { return x.toUpperCase() })
    • A function which is applied to each filename before sorting.
    • If set to false, filenames are unaltered.
  • dontSortFilenames: (default: false)
    • If this is set, then filenames are not sorted in responses to the LIST and NLST commands.
  • noWildcards: (default: false)
    • If set to true, then LIST and NLST treat the characters ? and * as literals instead of as wildcards.
Command configuration
  • allowedCommands: (default: undefined)
    • List of strings, the server will respond to only commands contained in this list, all other commands will result in a 502 unimplemented error.
Connectivity settings
  • tlsOptions: (default: undefined)
    • If this is set, the server will allow explicit TLS authentication.
    • Value should be a dictionary which is suitable as the options argument of tls.createServer.
  • tlsOnly: (default: false)
    • If this is set to true, and tlsOptions is also set, then the server will not allow logins over non-secure connections.
  • allowUnauthorizedTls: ?? I obviously set this to true when tlsOnly is on -someone needs to update this.
  • pasvPortRangeStart: (default: random?)
    • Integer, specifies the lower-bound port (min port) for creating PASV connections
  • pasvPortRangeEnd: (default: random?)
    • Integer, specifies the upper-bound port (max port) for creating PASV connections

Filesystem Abstraction

Filesystem abstraction makes it possible to create an FTP server which interacts directly with a database rather than the actual filesystem.

The server raises a command:pass event which is given pass, success and failure arguments. On successful login, success should be called with a username argument. It may also optionally be given a second argument, which should be an object providing an implementation of the API for Node's fs module.

The following must be implemented:

  • unlink
  • readdir
  • mkdir
  • open
  • close
  • rmdir
  • rename
  • stat
    • specific object properties: { mode, isDirectory(), size, mtime }
  • if useWriteFile option is not set or is false
    • createWriteStream: Returns a writable stream, requiring:
      • events: 'open', 'error', 'finish'
      • functions: 'write', 'end'
      • properties: 'bytesWritten'
  • if useWriteFile option is set to 'true'
    • writeFile
  • if useReadFile option is not set or is false
    • createReadStream: Returns a readable stream, requiring:
      • events: 'error', 'data', 'end'
      • functions: 'destroy'
  • if useReadFile option is set to 'true'
    • readFile

FtpServer has listen and close methods which behave as expected. It emits close and error events.

nodeftpd's People

Contributors

addrummond avatar alanszlosek avatar asylumfunk avatar billywhizz avatar britebit avatar coderbuzz avatar compulim avatar cotillion avatar ericfong avatar headconnect avatar jfromaniello avatar joshbuddy avatar mendezcode avatar mk-pmb avatar notslang avatar oleksiyk avatar phillipgreenii avatar pye2k avatar robbydaigle avatar sstur avatar thomaschaaf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nodeftpd's Issues

Issues with get client request contents etc.

Hi, First off I want to say that you've done a great job writing a simple to start up FTP server. I have a neat idea that requires me to override FTP requests so this is awesome. I've enjoyed starting it off but there are a few things that I would love if you can explain to me.

  1. How to get the name of the file being requested by the client? The original CONN object that you pass back doesn't seem to have it in there?
  2. The way that you have it set up to override the methods of the FS object before passing it back to the success function is a bit complicated. I've got it to work but it seems to be redundant due to this flow:
    a. Client performs request
    b. NodeJS intercepts and allows for custom code
    c. Custom code pulls data from data base
    d. Write data into stream

So we don't need to overwrite the ability to write the data stream, but instead have the ability to pass simply pass a different data set to be read. Does this make sense? I don't think this is a big deal but it could definitely make it easier for more novice developers to work with this.

I'd appreciate answers and I hope that once I get my hands dirty, I will be able to contribute back.

Thanks!

Unable to connect using SSL/TLS

Is anyone else hosting their app over SSL/TLS ?

I have an SSL cert specifically for "ftp.mydomain.com" which is pointed at my application running nodeftp but have had no luck getting it to work.

The output of my error is as follows:

FTPD listening on port 21
Client connected from xx.xx.xxx.xxx
Establishing secure connection...
Secure socket not authorized: [Error: UNABLE_TO_GET_ISSUER_CERT]

I've tried loading the intermediaries into one .pem file as suggested here as well as just passing them individually in the ca array - but to no avail.

Here's the code. In this example my app uses a Comodo PositiveSSL cert.

//For SSL/TLS:
var tlsOptions = {
  key: fs.readFileSync('ftp_mydomain_com.key'),
  cert: fs.readFileSync('ftp_mydomain_com.crt'),
  ca : [
    fs.readFileSync('ftp_mydomain_com.crt'),  
    fs.readFileSync('COMODORSADomainValidationSecureServerCA.crt'),
    fs.readFileSync('COMODORSAAddTrustCA.crt'), 
    fs.readFileSync('AddTrustExternalCARoot.crt')
  ],
  rejectUnauthorized: true
}

var options = {
  tlsOptions: tlsOptions,
  allowUnauthorizedTls: false,
  tlsOnly: true,
  getInitialCwd: function(connection, initialCwdCallback) {
  //and so forth

The user can connect if if you set "allowUnauthorizedTls".
Also, if you disable "tlsOnly" plain FTP works fine too.

Let the active port number configurable

Currently the active port number is hard-coded to 20.

With just 2 line of code, this can be made configurable.

In FtpServer.js,
On line 32, add self.activePort = options.activePort || 20;
On line 72, change to dataPort: this.activePort,

Update NPM Package

Update NPM - the last update was over a year ago and breaking changes from Node V7 has rendered ftpd inoperable for many users. Thank you.

Error when using TLS

<::ffff:177.206.84.50> << LIST
<::ffff:177.206.84.50> FTP command: LIST
<::ffff:177.206.84.50> Directory has 3 files
<::ffff:177.206.84.50> >> 150 Here comes the directory listing
<::ffff:177.206.84.50> Sending file list
<::ffff:177.206.84.50> >> -rw-r--r-- 1 ftp ftp 480 Jan 31 15:01 doc1.txt
<::ffff:177.206.84.50> >> -rw-r--r-- 1 ftp ftp 725 Jan 31 13:51 doc2.txt
<::ffff:177.206.84.50> >> drwxr-xr-x 1 ftp ftp 4096 Jan 31 13:52 Nova pasta
<::ffff:177.206.84.50> >> 226 Transfer OK
ERROR: <::ffff:177.206.84.50> Data connection error: { Error: read ECONNRESET
at exports._errnoException (util.js:1026:11)
at TCP.onread (net.js:563:26) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
Trace: Trace follows
at FtpServer._logIf (/wanas03/shared_config/ftpNodejs/node_modules/ftpd/lib/FtpServer.js:141:13)
at FtpConnection._logIf (/wanas03/shared_config/ftpNodejs/node_modules/ftpd/lib/FtpConnection.js:43:22)
at Socket. (/wanas03/shared_config/ftpNodejs/node_modules/ftpd/lib/FtpConnection.js:200:10)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at emitErrorNT (net.js:1272:8)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)

When i connect using simple FTP (unsecure) it connects and list files OK, but when i use the option use TLS if possible the connection goes ok but i do not receive the file list and got the error above.

The super constructor to "inherits" must not ' +

I am getting below error while compiling test.js

`util.js:965
throw new TypeError('The super constructor to "inherits" must not ' +
^

TypeError: The super constructor to "inherits" must not be null or undefined
at Object.exports.inherits (util.js:965:11)
at Object. (D:\Personal\examples\node_modules\ft
pd\lib\ftpd.js:67:6)
at Module._compile (module.js:573:32)
at Object.Module._extensions..js (module.js:582:10)
at Module.load (module.js:490:32)
at tryModuleLoad (module.js:449:12)
at Function.Module._load (module.js:441:3)
at Module.require (module.js:500:17)
at require (internal/module.js:20:19)
at Object. (D:\Personal\examples\test.js:1:74)`

If there are less files in the directory than maxStatsAtOnce, a call to LIST returns duplicates of files

Thanks for the cool library. It's extremely useful. 👍

In glob.statList, there is a for loop that runs CONC times. If there are less files than concurrent stats, it calls the finished callback more than once, which makes the server send more than one 150 Here comes the directory listing with the same data and also never finishes the call properly.

To reproduce, list a directory with one file and maxStatsAtOnce = 10.

Examples of using FS abstraction

This supports Filesystem Abstraction. Are there any examples of this which can be used to build out integration with SMB or S3?

npm version out of date

The version downloaded by 'npm install ftpd' seems to be quite out of date. I can't actually find the commit that it references. This came as a bit of a surprise, I'd spent a bit of time browsing the code here, and inserting console.logs all over my code, trying to figure out why options.allowedCommands wasn't working.

Stack overflow when listing a directory that has many files

It's because of the following code:

FtpServer.js:

self.getUsernameFromUid = options.getUsernameFromUid || function(uid, c) {
    c(null, 'ftp');
  };
  self.getGroupFromGid = options.getGroupFromGid || function(gid, c) {
    c(null, 'ftp');
  };

FtpConnection.js:

    function handleFile(ii) {
      if (i >= files.length) {
        return i === files.length + j ? finished() : null;
      }

      self.server.getUsernameFromUid(files[ii].stats.uid, function(e1, uname) {
        self.server.getGroupFromGid(files[ii].stats.gid, function(e2, gname) {
          if (e1 || e2) {
            self._logIf(LOG.WARN, 'Error getting user/group name for file: ' + util.inspect(e1 || e2));
            fileInfos.push({
              file: files[ii],
              uname: null,
              gname: null,
            });
          } else {
            fileInfos.push({
              file: files[ii],
              uname: uname,
              gname: gname,
            });
          }
          handleFile(++i);
        });
      });
    }

You can see why -- it recurses on the file list.

process.nextTick() can solve this. (I've added process.nextTick on the 2 get...() function. But since I'm using the previous version, the source cannot be merged to the master.)

Rely on `close` event and not on `finish` for WriteStream

https://github.com/sstur/nodeftpd/blob/master/lib/ftpd.js#L1397

I know that close event is not documented but the problem with finish event is that it is emitted before the stream has actually closed its descriptors and finished cleanup:

https://github.com/nodejs/node/blob/master/lib/fs.js#L1924

For custom filesystem that implements fs module functionality it means it has no chance to do final commits to whatever backend it uses before file:store event is emitted or even before Ftp client receives 226 Closing data connection.

Use same port as an Express server?

Can this be used on the same host and port as an Express server?

I would like to attach this to an Express app that I'm running on Heroku, but Heroku only allows each app access to a single port.

Is it possible to have an Express app listen to HTTP requests as usual but also act as an FTP server using this module?

Delete operation failed

So the scenario.

I start minecraft server with world name "Somethingwithutf8lettersilkečęšįėų". Then I login via ftp and I can't delete this dir(Keep in mind that it's renamed to "Somethingwithutf8letters???????"). But I can rename to something like "randomname" and delete that dir.

RETR sending 150 when file isn't found

I'm struggling with a situation where my ftp client is trying to download a file using RETR and it sees the 150 mark response, but there is no file contents. Upon digging into the code, it looks like in both _RETR_usingCreateReadStream and _RETR_usingReadFile a 150 is send and then the 550 is send. I thought perhaps there was a bug in the client I was using, but to verify I tried to find the FTP spec. The best I found was this: http://cr.yp.to/ftp/retr.html which says

The server may reject the RETR request without first responding with a mark. In this case the
server does not touch the data connection. RFC 959 allows code 550 for file-does-not-exist,
permission-denied, etc., and code 450 for out-of-memory, disk-failure, etc.

So, should the 150 not be sent? or is the client wrong for not checking for 550 after 150?

npm install ftpd hangs

As of today I cannot npm install ftpd anymore.

> mkdir temp
> cd temp
> npm init
(keep pressing enter until this exits)
> npm install ftpd
(hangs)

Runtime error after migration to Node 7

This occurred after upgrade to Node 7:

util.js:965
    throw new TypeError('The super constructor to "inherits" must not ' +
    ^

TypeError: The super constructor to "inherits" must not be null or undefined
    at Object.exports.inherits (util.js:965:11)
    at Object.<anonymous> (/Users/den/ShHarbor/videoMonitoring/NVRConnector/node_modules/ftpd/lib/ftpd.js:67:6)
    at Module._compile (module.js:573:32)
    at Object.Module._extensions..js (module.js:582:10)
    at Module.load (module.js:490:32)
    at tryModuleLoad (module.js:449:12)
    at Function.Module._load (module.js:441:3)
    at Module.require (module.js:500:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> ({require directive in my code})

The code used to work before node upgrade.

bug in example in README.md

The getRoot() function appears to get a complete connection object, not just a username, other than README.md suggests.

Listing files error, datasocket undefined

When i connect to the FTP server, using the ip, it list the files with no problems, but when i use the domain name it says:
"Currently no data connection; expecting client to connect to pasv server shortly..."
Its alrealdy configured to connect in passive mode and etc... but even if i connect in auto mode, it doesnt show the file list.

Connection
FTP command: USER walter
FTP command: PASS ***
FTP command: PWD
FTP command: TYPE I
FTP command: PASV
Setting up listener for passive connections
Passive data connection beginning to listen
Passive data connection listening on port 1030
FTP command: LIST
Directory has 5 files
Currently no data connection; expecting client to connect to pasv server shortly...

Debugging the code i see that in line 715 of ftpd.js in lib, it never change the status to ready, the datasocket is undefined in "FtpConnection.prototype._whenDataReady" line 299

handleUpload called before 150 Ok in _STOR_usingCreateWriteStream

This seems to be a regression as the prior (fork) version has correct logic.

Regardless of whether an "open" is emitted on storeStream, 150 Ok should be sent before _whenDataReady is called.

Correct logic:

self.respond("150 Ok to send data", function() {
  self._whenDataReady(handleUpload);
});

The data connection could not be established: ECONNREFUSED - Connection refused by server

Using the test.js example and attempting to connect to the server from Filezilla I am getting the response:

Error: The data connection could not be established: ECONNREFUSED - Connection refused by server

After the LIST command is issued. On the server it looks like this:

FTP command: LIST
Directory has 0 files
Currently no data connection; expecting client to connect to pasv server shortly...

What would be causing this?

publish the latest to npm

there is a bunch of changes in master that aren't showing up in npm. Most notably is the bug fixes. Can we get a more up-to-date version in npm?

Ftpd leaks sockets

Currently there is no way to close the server and be sure all sockets are closed. The close() method only closes the main listening socket but not the data sockets. Is there any way around that?

Factor our PASV component

The logic for the PASV listener/server adds too much complexity to the FtpConnection component and should be abstracted into it's own library. Ideally FtpConnection doesn't need to care how the data connection is established (active or passive) it just needs to be able to read/write, open/close and subscribe to events.

I'm in the process of doing this refactor however I'm wondering about a few things related to passive connections and the FTP spec.

Assumptions I'm making (are these safe to assume?):

  • There will be no more than one data connection per control connection.
  • The data connection will originate from the same host (IP address) as the control connection.
  • After server sends 227 Entered Passive Mode with an address/port, I can expect a connection from the expected host (within a certain time) and once that connection is received (or the timeout happens) then I can free the listener again (either close it or put it back into a pool of available listeners).
  • If I get an unexpected connection on a listener I can reject it.
  • I might have more clients than available listening ports. I can use the same listener for multiple clients as long as those clients have different host addresses because I will know which incoming connection belongs to which control connection based on IP.
  • If client(s) on the same host (or behind the same NAT device) open concurrent control connections, several of which send PASV command at or around the same time, then I will need to reply with different ports. If there are no more available listener ports, I assume I can leave them waiting until one becomes available. Or Is there a busy/retry response I can send?

Is there anything in the spec I'm mis-understanding or overlooking? Is this how other FTP servers are implemented?

Any thoughts @asylumfunk, @oleksiyk, @mk-pmb, @joshbuddy, @addrummond, @pye2k, @phillipgreenii, @coderbuzz?

Concerning Error upload

Hi,

When a (big) file is 100% uploaded, it's then moved correctly to the target folder. Thats fine.

But if I try to upload a bigger file and I f.x. crash it while uploading, then the partly uploaded file is moved to the target folder. It would be best to remove the partly uploaded file on any network error.

Is it possible for you to fix this?

Thanks.

Commands starting with "X" i.e. XRMD not supported

Hi,
I am using ftpd for quite some time and most of ftp commands were working just fine. Recently it started breaking when connecting using ftp CLI from windows. After some analysis it seems that server is getting command prefixed with X for example in case for rmdir server get XRMD which is not supported in FTPD implementation. I am not sure why this is happening but do we have any plan to support such cases as well in FTPD.

Does not support korean character in LIST command.

I uploaded file has Korean character(KR UTF-8)using filezila. Howerver, the filename is not printed properly. Also 'delete' and 'rename' operations do not work.
I checked file list using 'ls' command in the root folder on the linux server, the file has the right name.
I suppose that this problem could be in LIST command part.

I attached full log from ftpd .

Passive data event: connect
FTP command: STOR Google 행아웃.lnk (filename is recognized correctly)
A data connection exists
File opened/created: /Google 행아웃.lnk
Told client ok to send file data
Passive data event: end
Passive data event: close
FTP command: CWD /
FTP command: PWD
FTP command: TYPE A
FTP command: PASV
Telling client that they can connect now
Passive data event: connect
FTP command: LIST
Directory has 14 files
A data connection exists
Sending file list
Passive data event: end
Passive data event: close
FTP command: CWD /
FTP command: PWD
FTP command: TYPE A
FTP command: PASV
Telling client that they can connect now
Passive data event: connect
FTP command: LIST
Directory has 14 files
A data connection exists
Sending file list
Passive data event: end
Passive data event: close
FTP command: DELE Google ?Dnlnk (filename is not recognized)
Error deleting file: /Google ?Dnlnk, Error: ENOENT, unlink '/stg/ftp_root/Google ?Dnlnk'

Problem with back-pressure 'STOR' code

Its hard to replicate but sometimes storeStream fails with error 'write after end'. That .end() is called here: https://github.com/sstur/nodeftpd/blob/master/lib/FtpConnection.js#L1214

I guess it happens when the peer has finished writing all the data but the dataSocket was paused. The 'drain' event of the storeStream in this case has two handlers: https://github.com/sstur/nodeftpd/blob/master/lib/FtpConnection.js#L1201
and
https://github.com/sstur/nodeftpd/blob/master/lib/FtpConnection.js#L1201
The first handler calls resume() on a dataSocket but the second handler closes the storeStream with end().

Maybe someone has some quick fix idea?

Additional event hooks

I need some additional event hooks, and some record keeping of a client's actions so that those actions can be syncronized elsewhere via function callbacks

I'm proposing "client:disconnected" event, and several others, like "file:put", "file:rename", "file:delete"

filename with äöü

it is not possible to store files with name öüäbla.txt

it is uploaded but after that it disappear in the ftp list.

PWD on windows gives bad path

The PWD is possibly giving an undesirable path. Seems like the user should see "/" as his root

Also running in Windows seems to give issues with pathing due to backslash versus slash.

Or, the problem is process.cwd() returning "C:\path\to\somewhere" and not using unix style "C:/path/to/somewhere"

C: PWD
S: 257 "\C:\path\to\user" is current directory

'download' instead of 'upload' in Readme

In the Readme:

Instead of

useReadFile: (default: false)
If set to true, then files which the client uploads are slurped using 'readFile'.

shouldn't it be:

useReadFile: (default: false)
If set to true, then files which the client downloads are slurped using 'readFile'.

?

unable to cwd when there is space in directory name

server comes with an error when we try to change working directory whose name contains space

for example

ftp> ls
200 OK
150 Here comes the directory listing
drwxrwxr-x 1 ftp ftp 4096 Jul 14 13:41 a
-rw-rw-r-- 1 ftp ftp 13 Jul 09 14:42 hello.txt
-rw-rw-r-- 1 ftp ftp 775702 Jul 14 11:02 Jellyfish.jpg
drwxrwxr-x 1 ftp ftp 4096 Jul 14 18:45 new folder
226 Transfer OK
ftp> cd new folder

550 Directory not found.

the issue may be here

https://github.com/sstur/nodeftpd/blob/master/lib/ftpd.js#L510

'pathRequest' does not contain full path .the characters after 'space' are missing

Remove console logging

I keep getting these 'Client connection closed' messages in the console. This is annoying because I use ftpd for unittests and it mixes with the test output. Is there any way I can turn that off?

Refactor to use ES6 (ES2015)

This is a good time to bring this codebase into 2016. Modern JS doesn't need us to write var self = this; and Foo.prototype.thing = function() { ... } all over the place.

I've done this in a branch called refactor and I'm using babel to build it to ES5 for Node versions before v5.

This feature is a prerequisite to #80 in which I will do more refactoring in an effort to make FtpConnection shorter and more readable/understandable by factoring out pieces (like PASV) where applicable.

UTF8 support

Are you interested in UTF8 support? I have it running for a year already without any problems. I can prepare a PR.

when the number of files exceeds 3170, the LIST command crashes

when the number of files exceeds 3170, the LIST command generates the following exception:

FTP command: LIST
Directory has 3170 files
/home/sesame/lumipark/node_modules/ftpd/lib/ftpd.js:677
return x.localeCompare(y);
^
RangeError: Maximum call stack size exceeded
at String.localeCompare (native)
at sf (/home/sesame/lumipark/node_modules/ftpd/lib/ftpd.js:677:24)
at /home/sesame/lumipark/node_modules/ftpd/lib/ftpd.js:681:20
at Array.sort (native)
at finished (/home/sesame/lumipark/node_modules/ftpd/lib/ftpd.js:679:31)
at handleFile (/home/sesame/lumipark/node_modules/ftpd/lib/ftpd.js:643:40)
at /home/sesame/lumipark/node_modules/ftpd/lib/ftpd.js:658:11
at FtpServer.self.getGroupFromGid (/home/sesame/lumipark/node_modules/ftpd/lib/ftpd.js:99:5)
at /home/sesame/lumipark/node_modules/ftpd/lib/ftpd.js:646:21
at FtpServer.self.getUsernameFromUid (/home/sesame/lumipark/node_modules/ftpd/lib/ftpd.js:96:5)
[nodemon] app crashed - waiting for file changes before starting...

Configurable list of allowed verbs

I think of FTP generally as a legacy compatibility layer. Most of the time I find that the full array of verbs aren't necessary. Would it be useful to have the ability to turn off certain verbs altogether? E.g. block DELE or RMD (say, for an upload-only server that expects to be a data-sink)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.