Coder Social home page Coder Social logo

ftp-srv's People

Contributors

alancnet avatar almgwary avatar bartbutenaers avatar botovance avatar broofa avatar connorhu avatar dependabot[bot] avatar devotox avatar johnnyrook777 avatar jorinvo avatar lafin avatar leolabs avatar lucasantoiemma avatar matt-forster avatar medivhok avatar mikejestes avatar mortens4444 avatar ozairp avatar paulober avatar pkeuter avatar qchar avatar qiansc avatar rjonaitis avatar simultsop avatar techmunk avatar timluq avatar trs avatar vdiez avatar yassermorteza avatar zgwit 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  avatar  avatar  avatar

ftp-srv's Issues

Retrieving file with accent failing.

Hi,

If we try to retrieve a file having accent in its name, the server returns 550 ENOENT. Linux or Windows.

Here is a screen shot of the problem :

image

Best regards,

File transfer using FileZilla failed

I have used "https://github.com/trs/ftp-srv/blob/master/test/start.js" code to create an FTP Server on localhost. It shows the directory listing correctly in FileZilla. But when I try to transfer a file it fails at STOR directive by throwing Timeout error.

Am I missing anything here?

{"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":10,"msg":"[ 'STOR test.txt' ]","time":"2017-06-13T16:48:18.667Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"directive":"STOR","level":10,"command":{"directive":"STOR","arg":"test.txt","raw":"STOR test.txt"},"msg":"Handle command","time":"2017-06-13T16:48:18.668Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":20,"port":1024,"msg":"Passive connection fulfilled.","time":"2017-06-13T16:48:18.671Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":20,"msg":"Passive connection closed","time":"2017-06-13T16:48:18.677Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":20,"msg":"Passive server closed","time":"2017-06-13T16:48:18.677Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"directive":"STOR","level":50,"err":{"message":"timed out after 5000ms","name":"TimeoutError","stack":"TimeoutError: timed out after 5000ms\n at onTimeout (/Users/siddharth.mishra/GitlabRepos/analytics-api-ftp-server/node_modules/when/lib/decorators/timed.js:69:7)\n at Timeout._onTimeout (/Users/siddharth.mishra/GitlabRepos/analytics-api-ftp-server/node_modules/when/lib/decorators/timed.js:13:4)\n at ontimeout (timers.js:380:14)\n at tryOnTimeout (timers.js:244:5)\n at Timer.listOnTimeout (timers.js:214:5)"},"msg":"timed out after 5000ms","time":"2017-06-13T16:48:23.677Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":10,"port":8880,"packet":"425 No connection established","msg":"Reply","time":"2017-06-13T16:48:23.677Z","v":0}

v2.19.3 breaks TypeScript build

(Caused by 2a50134.)

When compiling TS which has a dependency to ftp-srv there are some build errors because of mismatching types. The new typed class extension to EventEmitter causes a problem as the types defined for FtpServer are incompatible to the base types.

Transpilation errors:

node_modules/ftp-srv/ftp-srv.d.ts(81,5): error TS2416: Property 'emit' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
  Type '(action: any, ...data: any[]) => void' is not assignable to type '(event: string | symbol, ...args: any[]) => boolean'.
    Type 'void' is not assignable to type 'boolean'.
node_modules/ftp-srv/ftp-srv.d.ts(97,2): error TS2416: Property 'on' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
  Type '{ (event: "login", listener: (data: { connection: FtpConnection; username: string; password: stri...' is not assignable to type '(event: string | symbol, listener: (...args: any[]) => void) => this'.
    Type 'EventEmitter' is not assignable to type 'this'.
node_modules/ftp-srv/ftp-srv.d.ts(113,2): error TS2416: Property 'on' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
  Type '{ (event: "login", listener: (data: { connection: FtpConnection; username: string; password: stri...' is not assignable to type '(event: string | symbol, listener: (...args: any[]) => void) => this'.
node_modules/ftp-srv/ftp-srv.d.ts(81,5): error TS2416: Property 'emit' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
  Type '(action: any, ...data: any[]) => void' is not assignable to type '(event: string | symbol, ...args: any[]) => boolean'.
    Type 'void' is not assignable to type 'boolean'.
node_modules/ftp-srv/ftp-srv.d.ts(97,2): error TS2416: Property 'on' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
  Type '{ (event: "login", listener: (data: { connection: FtpConnection; username: string; password: stri...' is not assignable to type '(event: string | symbol, listener: (...args: any[]) => void) => this'.
    Type 'EventEmitter' is not assignable to type 'this'.
node_modules/ftp-srv/ftp-srv.d.ts(113,2): error TS2416: Property 'on' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
  Type '{ (event: "login", listener: (data: { connection: FtpConnection; username: string; password: stri...' is not assignable to type '(event: string | symbol, listener: (...args: any[]) => void) => this'.

Concurrency issues

I'm trying to upload multiple images at once but only the first one is going through, all parallel requests throw a 530 Command requires authentication.

It works if I comment out this condition: https://github.com/trs/ftp-srv/blob/master/src/commands/index.js#L56

When uploading a single file I get:

// (command.directive, commandFlags.no_auth, this.connection.authenticated)
USER true undefined
PASS true undefined
TYPE undefined true
PASV undefined true
STOR undefined true

When uploading two files I get:

// (command.directive, commandFlags.no_auth, this.connection.authenticated)
USER true undefined
PASV undefined undefined
PASS true undefined
STOR undefined true
TYPE undefined true
PASV undefined true
STOR undefined true

I guess PASV undefined undefined is throwing the 530. Should the PASV command have a no_auth: true?

MaxListenersExceededWarning: Possible EventEmitter memory leak detected

Hi,

I'm getting this error whenever I upload a file:

(node:49079) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 connection listeners added. Use emitter.setMaxListeners() to increase limit

The upload completes just fine, but I obiously need to address this issue.

I have this in an app that is also running Hapi, but I disabled that and I still get the same error.

By way of a second question. is there an event that fire when a file has been uploaded?

Overriding FileSystem

I'm not a node expert and am struggling with how to override the filesystem. I have ftp-srv working fine using the default setup, even running in a docker container.

My application requires receiving a CSV file, converting it to JSON (potentially into a pg database) and send some data to a different REST API. My plan was to override ftp-srv file system based on a login and process the csv file stream into a json file so that I can reply to the ftp client immediately if there are any format errors. If conversion is successful I would then trigger a different process to push data to the REST API while retaining the original file and the JSON version. I may even move this to be done 100% in-memory. Unfortunately, having the third party write directly to our REST API is not an option because they only support FTP transfers. There are other ways I could do this, but there are other benefits for me in this approach that are outside of the scope of this problem.

The documentation on this is light so the best I've been able to determine is to pass a custom FileSystem object with the response from the login event (login event from your test start.js)

server.on('login', ({connection, username, password}, resolve, reject) => {
  if ((username === 'test' || username === 'testdb') && password === 'test' || username === 'anonymous') {
    if (username === 'testdb') {
      var root = '/code/data';
      var cwd = '/';
      return resolve({root: root, cwd: cwd, fs: new DbFileSystem(connection, {root: root, cwd: cwd}) });
    } else {
      return resolve({ root: '/code/data', cwd: '/' });
    }
  } else {
    reject('Bad username or password');
  }
});

First of all, is this the right approach?

I then assumed the next step is to extend the FileSystem class:

const { FileSystem } = require('ftp-srv/fs');
const csv = require('csvtojson')


class DbFileSystem extends FileSystem {
  constructor(connection, { root, cwd } = {}) {
    super(connection, root, cwd);
  }

  write(fileName, {append = false} = {}) {
    const {fsPath} = this._resolvePath(fileName);
    const stream = syncFs.createWriteStream(fsPath, {flags: !append ? 'w+' : 'a+'});
    stream.on('error', () => fs.unlink(fsPath));
    
    // conceptually, this is what I want to do while the stream is being received 
    // (I know this function is the wrong place for this code)
    csv()
    .fromStream(csvReadStream)
    .on('csv',(csvRow)=>{
      // csvRow is an array
    })
    .on('done',(error)=>{
    
    })
    
    return stream;
  }
}

module.exports = DbFileSystem;

Perhaps this is wrong, but now I don't know where to go next because write only creates a new stream.Writable and stream is handled asynchrounously in the src/commands/registration/stor.js: handler. Do I also need to override the STOR directive? ๐Ÿ˜•

Thanks

GnuTLS error -110: The TLS connection was non-properly terminated.

Using RC 3

Im adding TLS using a PFX and passphrase using the following

const pfx = fs.readFileSync(config.TLS_PFX_PATH);

ftpOptions.tls = {
   pfx: pfx,
   passphrase: config.TLS_PFX_PASSPHRASE,
 };

Then Im getting the following errors when I connect and LIST
Note, Im using FileZilla as an FTP client

12:22:24 Status: Disconnected from server
12:22:24 Status: Resolving address of localhost
12:22:24 Status: Connecting to 127.0.0.1:2021...
12:22:24 Status: Connection established, waiting for welcome message...
12:22:24 Response: 220 Ready
12:22:24 Command: AUTH TLS
12:22:24 Response: 234 Honored
12:22:24 Status: Initializing TLS...
12:22:24 Status: Verifying certificate...
12:22:24 Status: TLS connection established.
12:22:24 Command: USER lingarddev
12:22:24 Response: 331 Username okay, awaiting password
12:22:24 Command: PASS **********
12:22:25 Response: 230 User logged in, proceed
12:22:25 Command: OPTS UTF8 ON
12:22:25 Response: 200 UTF8 encoding on
12:22:25 Command: PBSZ 0
12:22:25 Response: 200 OK
12:22:25 Command: PROT P
12:22:25 Response: 200 OK
12:22:25 Status: Logged in
12:22:25 Status: Retrieving directory listing...
12:22:25 Command: PWD
12:22:25 Response: 257 "/"
12:22:25 Command: TYPE I
12:22:25 Response: 200 Switch to "binary" transfer mode.
12:22:25 Command: PASV
12:22:25 Response: 227 PASV OK (localhost,203,33)
12:22:25 Command: PORT 127,0,0,1,196,177
12:22:25 Response: 200 The requested action has been successfully completed
12:22:25 Command: LIST
12:22:25 Response: 150 File status okay; about to open data connection
12:22:25 Response: 226 Closing data connection
12:22:25 Error: GnuTLS error -110: The TLS connection was non-properly terminated.
12:22:25 Status: Server did not properly shut down TLS connection
12:22:25 Error: Transfer connection interrupted: ECONNABORTED - Connection aborted
12:22:25 Error: Failed to retrieve directory listing

Any ideas or anyone else having success here?

Confusion between STAT and LIST

Hi,

It looks like the STAT command is actually doing LIST's job. According to Wikipedia

  • LIST returns information of a file or directory
  • STAT returns information about the server

Looking to your code I saw stat.js is returning FileStat and LIST returns an error when you give a file as path.

To be conform to a FTP server, STAT should return the state of the instance and LIST should accept a file as argument and do a fs.stat() on it.

on STOR, get filePath

When a user uploads a file to a dir, STOR just gives the name and not the full path, which would then require to traverse all the dirs.

It would be nice to get the full path of the file that was just uploaded

client-error event for transfert (user name undefined)

Hi Stewart,

It's really great that you added the concept of client error, I was just about to contact you about it 2 weeks ago. Without this possibility of capturing errors, the server was crashing when there were firewall issue or anormal connection breaks. Now it seems to works well. Whatever I saw that you modified a lot of code that may helped for crash issue....

While simulating connection failures I noticed that the client-error event is triggered twice. So one for the channel command and a second time for the data channel. However, the connection.userName property is valid in the channel command event, but for the data channel event it is undefined. Is this normal? I think the user name of a command channel connection should be preserved while opening the data channel connection.

Best regards,

How close ftp server

Ftp Server have a listen method, but what about close? I cannot see in documentation a close method

Typescript support

Could you please provide a .d.ts file to support Typescript with intellisense?
Anyway, thanks for your great work on this module!

`TypeError: FtpSrv is not a constructor` error when requiring FileSystem

Noticed this with the new version I installed today. (2.13.1) . The previous version I was using was 2.11.4.

This works:

const FtpSrv = require('ftp-srv');
const ftpServer = new FtpSrv(config.get('ftp').url, config.get('ftp').options);

This throws the following error:

const { FtpSrv, FileSystem } = require('ftp-srv');
const ftpServer = new FtpSrv(config.get('ftp').url, config.get('ftp').options);
const ftpServer = new FtpSrv(config.get('ftp').url, config.get('ftp').options);
                  ^
TypeError: FtpSrv is not a constructor

I also noticed in the README there are a few places where FtpSrv is referenced as FtpSvr.

Looks like ftp-srv.js is now missing when npm installed, and the package.json main points to src/index.js. ftp-srv.js is missing from the files array in the package.json. If I put ftp-srv.js back manually (I grabbed the one from 2.11.4) and change the package.json to point to it, it works again. I am sure the main value was changed for a reason, but not knowing exactly why, I am hesitant to put in a PR that in essence undoes the recent changes.

Issues with passive mode

Hi,

I'm having some issue with the passive mode for any operation that requires it (list, put, mkdir,...)

  • with node FTP client, I'm able to execute those operation but within an average of 10 seconds (and sometimes it even drop due to timeouts).
  • with a CLI ftp client (Linux default), once I'm connected:
230 User logged in, proceed
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (X,X,X,X,35,40)
ftp: connect: Invalid argument
ftp>

I tried both methods on my FTP server and they work without flaws or timeouts.

I tried to play with the pasv port range but without more success and I'm a bit dry on new idea to solve this. Did you experiment this? Have any idea?

Thank you

Allow only part of the FS to be overwritten

What would you think to let the user overwrite only a part of the FS ? Use case: I only want to implement the list() method so it would return the . folder as well.

What I would like to do:

    srv.on('login', ({connection, username, password}, resolve, reject) => {
      resolve({fs: {
        list: function(path) {...}
     });
   });

Basically, this means operating a merge here instead of an OR.

What do you think of that? If you're ok with it I can write a PR for that.

[Feature request] Support silent mode

If I started listening server always show log in command line. That would not be a problem. But if I use part of a system then it is a problem! If I set the log option to null or false, I get error.

I would like to have a 'slient' option.

FTP Timeout error on LIST Directory

Ubuntu 16.04 64 bits
Listing directory not works, this shows the console:

{"name":"ftp-srv","hostname":"vps0","pid":22478,"id":"318b90e8-1643-4b61-9290-72a5d554f7ce","ip":null,"directive":"LIST","level":50,"err":{"message":"timed out after 5000ms","name":"TimeoutError","stack":"TimeoutError: timed out after 5000ms\n    at onTimeout (/home/kodhe/projects/ftp-server/node_modules/when/lib/decorators/timed.js:69:7)\n    at Timeout._onTimeout (/home/kodhe/projects/ftp-server/node_modules/when/lib/decorators/timed.js:13:4)\n    at ontimeout (timers.js:386:11)\n    at tryOnTimeout (timers.js:250:5)\n    at Timer.listOnTimeout (timers.js:214:5)"},"msg":"timed out after 5000ms","time":"2017-12-05T05:29:00.119Z","v":0}

missing require for eprt

Looks like require('./registration/eprt'), is missing from src/commands/registry.js. Without this IPv6 connections don't seem to work.

The listen() call never rejects and always listens on 0.0.0.0

listen() never rejects

The callback to (net | tls).server.listen will not receive an error argument, but is instead attached as a callback to the "listening" event. When there is a binding error listening will never be dispatched and the promise is dead and will never reject nor resolve.

See https://nodejs.org/api/net.html#net_server_listen

listen() always listens to 0.0.0.0

No host is passed on to the net.server.listen(), as such the default 0.0.0.0 is always bound.

Typescript error: Property 'on' does not exist on type 'FtpConnection'

I am using ftp-srv in a Typescript project. When calling data.connection.on(...)
the ts compiler responds with
TS2339: Property 'on' does not exist on type 'FtpConnection'.

A working fix is to update the type declaration in ftp-srv.d.ts
from
export class FtpConnection {...}
to
export class FtpConnection extends EventEmitter {...}.
which is also how the actual implementation is defined.

Not sure if this is worth a PR, and also not sure how to add a test for this fix since ftp-srv is not a ts project. Let me know if you would prefer a PR anyway. Otherwise I suggest to incorporate this in the next patch.

Occur error when connect ftp on Chrome

I ran ftp server on Unbutu 12.04.
And I connected through chrome browser I got error.
Both firefox and ie were work fine.

Here is my server code
`const os = require('os');
const FtpSrv = require('ftp-srv');
const bunyan = require('bunyan');

const log = bunyan.createLogger({ name: '97' });
log.level('trace');

const server = new FtpSrv('ftp://168.219.244.97:21', {
anonymous: 'sillyrabbit',
log: log,
pasv_range: 8881,
greeting: ['Welcome', 'to', 'the', 'jungle!'],
tls: {
key: ${process.cwd()}/files.mysite.key,
csr: ${process.cwd()}/files.mysite.csr,
crt: ${process.cwd()}/files.mysite.crt
}
});

server.on('login', (data, resolve, reject) => {
if (data.username === 'anonymous') {

    resolve({
        root: '/home6/common/'
    });
} else {
    reject();
}

});

server.on('client-error', ({ connection, context, error }) => {
console.log(context);
console.log(error);
});

server.on('error', (err) => {
console.log(err);
});

server.on('uncaughtException', (err) => {
console.log(err);
})
server.listen();`

And followed log is error when I connect through Chrome.
{"name":"97","hostname":"VDBS1485","pid":15878,"id":"99231d2a-68a7-4bd9-b3c6-b636384702ab","ip":null,"level":10,"msg":"[ 'LIST -l' ]","time":"2017-07-05T04:35:28.656Z","v":0} {"name":"97","hostname":"VDBS1485","pid":15878,"id":"99231d2a-68a7-4bd9-b3c6-b636384702ab","ip":null,"directive":"LIST","level":10,"command":{"directive":"LIST","arg":"-l","raw":"LIST -l"},"msg":"Handle command","time":"2017-07-05T04:35:28.656Z","v":0} {"name":"97","hostname":"VDBS1485","pid":15878,"id":"99231d2a-68a7-4bd9-b3c6-b636384702ab","ip":null,"directive":"LIST","level":50,"err":{"message":"ENOENT: no such file or directory, stat '/home6/common/-l'","name":"Error","stack":"Error: ENOENT: no such file or directory, stat '/home6/common/-l'\n at Error (native)","code":"ENOENT"},"msg":"ENOENT: no such file or directory, stat '/home6/common/-l'","time":"2017-07-05T04:35:28.657Z","v":0} {"name":"97","hostname":"VDBS1485","pid":15878,"id":"99231d2a-68a7-4bd9-b3c6-b636384702ab","ip":null,"level":10,"port":21,"encoding":"utf8","packet":"451 ENOENT: no such file or directory, stat '/home6/common/-l'","msg":"Reply","time":"2017-07-05T04:35:28.657Z","v":0}

Timeout on STOR with tls enabled

I'm having issues when trying to upload some files to ftp server when TLS is enabled:

{"name":"ftp-srv","hostname":"laptop","pid":16256,"id":"-8197-4e6d-b1f8-a944121da3d8","directive":"STOR","level":50,"err":{"message":"operation timed out","name":"TimeoutError","stack":"TimeoutError: operation timed out\n    at afterTimeout (/home/jquinto/node_modules/bluebird/js/release/timers.js:46:19)\n    at Timeout.timeoutTimeout [as _onTimeout] (/home/jquinto/node_modules/bluebird/js/release/timers.js:76:13)\n    at ontimeout (timers.js:498:11)\n    at tryOnTimeout (timers.js:323:5)\n    at Timer.listOnTimeout (timers.js:290:5)"},"msg":"operation timed out","time":"2018-06-14T09:14:30.628Z","v":0}

Note: If TLS disabled that works perfectly.

My code:

const server = new FtpServer("ftps://127.0.0.1:8880", {
  logger,
  pasv_range: 8881,
  tls: {
    key: `${process.cwd()}/cert/server.key`,
    cert: `${process.cwd()}/cert/server.crt`,
    ca: `${process.cwd()}/cert/server.csr`
  },
  anonymous: true
})
server.on("login", ({ connection, username, password }, resolve, reject) => {
  if ((username === "test" && password === "test") || username === "anonymous") {
    connection.on("STOR", (error, fileName) => {
      logger.info("file stored: ", fileName)
    })
    connection.on("RETR", (error, filePath) => {
      logger.info("file downloaded: ", filePath)
    })
    resolve({ root: `${process.cwd()}/bdd/mockftp/root` })
  } else reject("Bad username or password")
})
server.on("client-error", ({ error }) => {
  logger.error(error)
})

server.listen().then(() => {
  logger.info("started FTP service.")
})

Crash when aborting download

Hi,

I connect to the server using FileZilla and then download about 100 files of (1-2K each). On half of the transfert I removed all remaining items (~50 files) from the download queue of FileZilla. After what, Filezilla seems to detect a connection break. I tried reconnecting but the server does no longer listen on that port.

netstat -anp | grep 21

Give nothing, ftp-srv crashed.

I then look on the console and then I saw this error, maybe it will help you.

Cannot read property 'write' of null","name":"TypeError","stack":"TypeError: Cannot read property 'write' of null\n    
at ReadStream.stream.on.data (/root/xxx/node_modules/ftp-srv/src/commands/registration/retr.js:18:56)\n    
at emitOne (events.js:96:13)\n    
at ReadStream.emit (events.js:188:7)\n    
at readableAddChunk (_stream_readable.js:176:18)\n    
at onread (fs.js:2018:12)\n    
at FSReqWrap.wrapper [as oncomplete] (fs.js:683:17)

I'm using the latest version : ftp-srv : 2.11.2

cli: port ignored?

Typing ftp-srv ftp://0.0.0.0:9876 --root ~/Documents will print Unhandled rejection Error: listen EACCES 127.0.0.1:21: it should listen to port 9876, not 21.

STOR events not happening for me

Is this a bug? Am I doing something wrong here?

The "this.emit('STOR', null, fileName)" line at store.js:46 is called but it never gets to my code. The file is uploaded.

  const ftpServer = new FtpSvr(

    'ftp://' + ip.address().toString() + ':3000', {
      anonymous: false,
      pasv_range: '8000-9000',
      greeting: 'xxx-FTP'
    }
  );

  ftpServer
    .listen()
    .then(() => {
      gc.log(`started FTP service ${ip.address().toString()}`);
    });

  ftpServer
    .on('login', ({
      connection, // eslint-disable-line no-unused-vars
      username, password }, resolve, reject) => {

      if (username === 'xxx' && password === 'xxxxx') 
        resolve({ root: './data/'});  
      else  
        reject({ root: './data/anonymous' });
    });

  ftpServer.on('STOR', (error, fileName) => { 
    if (error) console.log(error);
    else console.log(fileName);
  });`
`

Always have "Not a valid directory" error

When I try to do actions on the ftp server, I always get an error in the console from fs.

Here's the error (I replaced sensitive data with HIDDEN):

{"name":"ftp-srv","hostname":"HIDDEN","pid":7824,"id":"c9371611-e73c-4b70-a42b-1745957d6418","directive":"CWD","level":50,"err":{"message":"Not a valid directory","name":"FileSystemError","stack":"FileSystemError: Not a valid directory\n at fs.statAsync.tap.stat (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\ftp-srv\2.16.1\node_modules\ftp-srv\src\fs.js:58:38)\n at PassThroughHandlerContext.finallyHandler (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\finally.js:57:23)\n at PassThroughHandlerContext.tryCatcher (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\util.js:16:23)\n at Promise._settlePromiseFromHandler (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:512:31)\n at Promise._settlePromise (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:569:18)\n at Promise._settlePromise0 (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:614:10)\n at Promise._settlePromises (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:693:18)\n at Promise._fulfill (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:638:18)\n at C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\nodeback.js:42:21\n at FSReqWrap.oncomplete (fs.js:171:5)","code":400},"msg":"Not a valid directory","time":"2018-04-23T17:43:13.827Z","v":0}

Here's my code:

require('dotenv').load()
const ftpsrv = require('ftp-srv'),
    fs = require('fs')

const server = new ftpsrv(`ftp://127.0.0.1:${process.env.PORT || 7777}`)
server.on('login', (user, resolve, reject) => {
    if (user.username === 'siffrein' && user.password === 'HIDDEN') {
        resolve({ root: process.cwd() + '/public/' })
    } else reject('Bad username or password.')
})
server.listen()

The error occurs when I connect, when I manipulate files, ...
I'm on Windows 10 build 1803 with pnpm 1.40.2, npm 5.6.0, node 9.11.2 and the latest WinSCP. I tried with both pnpm and npm.
I had problems at first with node-gyp and dtrace-provider.

TLS on ftp

Can someone give me an code example how to set up tls on ftp? Do I need the node tls package?

Expose errors

Currently the errors classes from errors.js are not available for external use.

It would be great to expose them in case anyone wants to override the filesystem and use those errors as well.

GET'ing files that start with '-' (hyphen) crashes server

This happens with both the CLI and servers created via the API.

Launch the CLI:

> ftp-srv ftp://localhost:9876 --root ~/work/ftpsrv/ --username

Then try to GET any file that starts with a hyphen -

$ ftp anonymous@localhost 9876

ftp> get -foo
remote: -foo

Expected behavior: If there's a file named -foo, it should 150 File status okay; about to open data connection. If no such file exists, it should respond with 551 ENOENT: no such file or directory

Actual behavior: On the server:

Unhandled rejection TypeError: Path must be a string. Received null
    at assertPath (path.js:28:11)
    at Object.normalize (path.js:1202:5)
    at serverPath (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/fs.js:21:23)
    at FileSystem._resolvePath (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/fs.js:27:7)
    at FileSystem.get (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/fs.js:45:27)
    at FtpConnection.handler (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/commands/registration/size.js:9:36)
    at FtpCommands.handle (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/commands/index.js:65:28)
    at Promise.mapSeries.message (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/connection.js:44:65)
From previous event:
    at FtpConnection._handleData (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/connection.js:44:20)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at Socket.Readable.push (_stream_readable.js:208:10)
    at TCP.onread (net.js:607:20)

Anyone using ftp-srv with MacOS

I use this great project to run a server to test my library https://github.com/simonh1000/ftp-deploy
I've recently switched to mac and I can get the server to start and register a login, but it seems to do no more than that - no greeting is received by my client (filezilla) nor any directory listing. I'm looking for ideas on fixing this, and after reading lots of articles that MacOS rather nixed ftp with High Sierra


const homeDir =
    require("os").homedir() + "/code/sync/nodejs/ftp-deploy/test/remote/";

const FtpSrv = require("ftp-srv");

const options = {
    greeting: ["test ftp server", homeDir],
    anonymous: true
};

// Using non-standard port
const port = 2121;
const ftpServer = new FtpSrv("ftp://0.0.0.0:" + port, options);

ftpServer.on('login', (data, resolve, reject) => {
    console.log("[login] Connection by", data);
    console.log("[login] Setting home dir to:", homeDir);
    resolve({ root: homeDir });    
});

ftpServer
    .listen()
    .then(() => {
        console.log(`Serving ${homeDir} on port: ${port}`);
    })
    .catch(err => {
        console.log("[error]", err);
    });

This is the error I currently get

  username: 'anonymous',
  password: '@anonymous' }
[login] Setting home dir to: /code/sync/nodejs/ftp-deploy/test/remote/
{"name":"ftp-srv","hostname":"xxxxx.home","pid":91037,"id":"ebcbfc41-1795-4185-80a8-aed84c5f066c","directive":"LIST","level":50,"err":{"message":"operation timed out","name":"TimeoutError","stack":"TimeoutError: operation timed out\n    at afterTimeout (/code/sync/nodejs/ftp-deploy/node_modules/bluebird/js/release/timers.js:46:19)\n    at Timeout.timeoutTimeout [as _onTimeout] /code/sync/nodejs/ftp-deploy/node_modules/bluebird/js/release/timers.js:76:13)\n    at ontimeout (timers.js:425:11)\n    at tryOnTimeout (timers.js:289:5)\n    at listOnTimeout (timers.js:252:5)\n    at Timer.processTimers (timers.js:212:10)"},"msg":"operation timed out","time":"2018-12-03T20:54:19.594Z","v":0}

Fails to install within virtual machine shared folders

Hi,

I'm having issues installing this inside a virtual machine (Ubuntu server), inside a shared folder (from Windows 7).
I think this is a common issue with modules that require compiling binaries.
Something related to symlinks.

I get some ENOENT warnings tar ENOENT: no such file or directory, lstat..., then an ENOENT error.

Failed to retrieve directory listing

I'm running this code on Windows and keep getting an error
Disconnected from server: ECONNABORTED - Connection aborted
Using FileZilla

_Status:	Connecting to 127.0.0.1:21...
Status:	Connection established, waiting for welcome message...
Status:	Logged in
Status:	Retrieving directory listing...
Command:	PWD
Response:	257 "\"
Command:	TYPE I
Response:	200 Switch to "binary" transfer mode.
Command:	PASV
Error:	Disconnected from server: ECONNABORTED - Connection aborted
Error:	Failed to retrieve directory listing_
var ftp 	= require('ftp-srv');
var fs 		= require('fs')
var path 	= require('path')

var ftpd = new ftp('ftp://0.0.0.0:21', {
	root: path.join(__dirname, 'public'),
        anonymous: true
});

ftpd.on('login', (user, resolve, reject) => {
  resolve({ root: path.join(__dirname, 'public') })
});

ftpd.listen()

Is my code wrong?

dataServer EADDRINUSE Error

Hi there!

Using ftp-srv on a project and I am getting this error:

ftpServer.on('client-error', (data) => {

    // data.context
    context:"dataServer"

    // data.error
    address:"192.168.0.120"
    code:"EADDRINUSE"
    errno:"EADDRINUSE"
    port:8080
    syscall:"listen"

});

I have 2 CCTV cameras that FTP snapshots of CCTV Footage to ftp-srv every second. This is not a persistent error, it just happens every now and then, maybe once every few seconds? But every time it happens, there is a 10 second gap for ftp-srv to recover. I really can't pinpoint when or why this is happening though. Tried googling, failed.

Here is the bulk of the code, if it helps:

const ftpServer = new FtpSrv('ftp://192.168.0.120:9876', {
  pasv_range:8080
});
 
ftpServer.on('login', (data, resolve, reject) => {

  resolve({root: 'F:/path/to/ftp/root'});

  data.connection.on('STOR', (error, fileName) => {
    var filePath = data.connection.fs.cwd;
    if (error === null) {
      mainWindow.webContents.send('cctvSnapshot', {
        filePath: filePath,
        fileName: fileName
      });
    }
  });

});

Any idea how to fix this?

Setting root dir from js code

Is there a way for setting the root dir using js code? There is nothing in the documentation about this, and it appears to use to current working directory instead of the directory I set, when I start the server with node this way:

const FtpSrv = require('ftp-srv');
const path = require("path");
const root = path.join(__dirname, "ftp");
const ftpServer = new FtpSrv('ftp://0.0.0.0:9876', {root: root, anonymous: true});
ftpServer.listen();

Problem with outside visibility

I'm using this ftp server on my android box using Termux.
Using the LAN, my ftp server works great. But when I'm accessing from outside of my LAN it doesn't work. I got the message Socket couldn't write, but all my permissions of files and directories are 777, and I think that I got an 5000ms timeout error once in the past.
One thing to note is that my ls it is not on /bin/ls but it is on /data/data/com.termux/files/usr/bin/ls.
So here it is my program:

process.chdir(__dirname);

const FtpSvr = require('ftp-srv');
const ftpServer = new FtpSvr('ftp://0.0.0.0:3000', {anonymous: true, pasv_range: 8000});

ftpServer.on('login', ({connection, username, password}, resolve, reject) => {
	if(username === 'daniel' && password === 'ola') {
		resolve({root: './data/'});
	} else {
		resolve({root: './data/anonymous'});
	}
});

ftpServer.listen();

and here is an image of an outside test of my server using https://ftptest.net/:
deepinscreenshot_chromium_20171020151739
Can someone help me?

Uncaught TypeError: types.isModuleNamespaceObject is not a function

Uncaught TypeError: types.isModuleNamespaceObject is not a function
at formatValue (util.js:664:22)
at Object.inspect (util.js:328:10)
at Logger.addStream (C:\Users\123\bpnex\node_modules\bunyan\lib\bunyan.js:581:62)
at new Logger (C:\Users\123\bpnex\node_modules\bunyan\lib\bunyan.js:490:18)
at Function.createLogger (C:\Users\123\bpnex\node_modules\bunyan\lib\bunyan.js:1618:12)
at new FtpServer (C:\Users\123\bpnex\node_modules\ftp-srv\src\index.js:17:18)

STOR operation attempts to destroy stream instead of socket

In the stor.js file, line 33:

  .finally(() => when.try(stream.destroy.bind(stream)));

This line attempts to call destroy on the writable stream (the class stream.Writable has no destroy method) returned from the FileSystem.write method. I suspect this should be against the data socket like so:

  .finally(() => when.try(dataSocket.destroy.bind(dataSocket)));

Edit: To clarify I'm using a Duplex PassThrough stream for which destroy is not defined. I see now that the Writable stream has a non-public destroy method. It doesn't look like the Duplex stream implements that until an update added in May (not in the version I have).

If this is intended to called be on the writable stream, I can shim it for the time being.

CLI version?

I'd like to run $ ftp-srv as I run http-server, from CLI. Is that possible? I could work on this if it makes sense. Let me know.

Setting root folder problem (Windows)

Hi,

I'm having problem setting the ftp root folder on Windows. Here is what I did :

const ftp_srv = require('ftp-srv');
const f = new ftp_srv("127.0.0.1:21", {});
f.on('login', ({ username, password }, resolveLogin, rejectLogin) => {
return resolveLogin({
                root: "d:\\ftp_root",
                cwd: "/"
            });
)};
f.listen();

When the client is getting the file (LIST) the here is what I'm getting in fs.js

class FileSystem {
  constructor(connection, {
    root = '/',
    cwd = '/'
  } = {}) {
    this.connection = connection;
    this.cwd = nodePath.resolve(cwd);              // "/" = "d:/"
    this.root = nodePath.resolve(root);            // "d:\\ftp_root" = "d:\ftp_root"
  }

Now in the list function :

  list(path = '.') {
    path = this._resolvePath(path);                // path = "d:\ftp_rootd:\"
    return fs.readdir(path)
    .then(fileNames => {

Thus, d:\ftp_rootd:\ is not a valid folder on my host. Why the cmd and the root folder are merge together ? Why not use only the root argument ?

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.