npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@akiroz/simple-ftpd

v0.0.9

Published

simple ftp server

Downloads

9

Readme

simple-ftpd

simple-ftpd is a event based ftp-server for node.js.

Features

  • Supports multiple modern ftp clients such as FileZilla, WinSCP, Transmission.
  • A real File System is not required.
  • For now it only supports basic authentication.
  • It supports passive mode only.
  • It only supports streams for writing and reading files.
  • It currently only supports a subset of FTP commands, but it should be enough for any modern FTP client.
  • It is intended to be used mainly to create local network ftp servers.

Used pyftpdlib extensively as a reference for the FTP protocol specification, as reading RFC documents is super boring :=)

Install

yarn add simple-ftpd
# or
npm install simple-ftpd --save
const ftpd = require('simple-ftpd')

API

Syntax: ftpd(opts, sessionCallback) or ftpd(host:port, sessionCallback)

Should you need more control, the ftpd function will return a net.Server instance.

Example

Simple, fs-based ftp server implementation example:

'use strict'

const ftpd = require('simple-ftpd')

ftpd({ host: '127.0.0.1', port: 1337, root: '/public/files' }, (session) => {

  session.on('pass', (username, password, cb) => {
    if (username === 'superadmin' && password === '53cr3t') {
      session.readOnly = false
      session.root = '/private/secret/files'
      cb(null, 'Welcome admin')
    } else {
      cb(null, 'Welcome guest')
    }
  })

  session.on('stat', fs.stat)
  // AKA
  // session.on('stat', (pathName, cb) => {
  //  fs.stat(pathName, cb)
  // })

  session.on('readdir', fs.readdir)
  // AKA
  // session.on('readdir', (pathName, cb) => {
  //   fs.readdir(pathName, cb)
  // })

  session.on('read', (pathName, offset, cb) => {
    cb(null, fs.createReadStream(pathName, { start: offset }))
  })

  session.on('write', (pathName, offset, cb) => {
    cb(null, fs.createWriteStream(pathName, { start: offset }))
  })

  // I'd do some checking if I were you, but hey.

  session.on('mkdir', fs.mkdir)
  session.on('unlink', fs.unlink)
  session.on('rename', fs.rename)
  session.on('remove', require('rimraf'))
})

Options

| option | | description | | --- | --- | --- | | host | required | Must be a valid ipv4 address (for now). Defaults to 127.0.0.1 | | port | required | Server port. Defaults to 1337. | | readOnly | optional | Disables client write requests. Defaults to true. Can be overridden on a connection-basis by setting the readOnly property on the session object before logging in. | | root | optional | The path passed to events will always be joined to root. Can be overridden on a connection-basis by setting the root property on the session object before logging in. The ftp client will not see root, and will think he's at /. This is simply a convenience to avoid manually joining the path you get in every event. | | maxConnections | optional | Maximum number of server connections. Defaults to 10. |

Passive connections will be initialized on an unused port assigned by the os.

Instead of options, you can pass ${host}:${port} ("192.168.1.10:1337").

Events

Every event gets some arguments and a node-style callback you must call with an Error object (if any) and results.

If you do not listen to a specific event, then that feature will become unavailable to the client. For example, if you do not listen to write events, the client will get a 502 error when trying to write files.

pass [username, password, cb]

The client wants to login with username and password. Will consider the user logged in if no error is passed to cb()

User names are always accepted, because (from pyftpdlib):

In order to prevent a malicious client from determining valid usernames on a server, it is suggested by RFC-2577 that a server always return 331 to the USER command and then reject the combination of username and password for an invalid username when PASS is provided later.

read [pathName, offset, cb]:

The client wants to read the file at pathName, starting at offset. Requires a readable stream to be passed as cb(null, readStream).

write [pathName, offset, cb]:

The client wants to write a file at pathName, starting at offset. Requires a writable stream to be passed as cb(null, writeStream).

stat [pathName, cb]:

the client wants the stats to a file or directory at pathName. Requires a fs.stat-like object to be passed as cb(null, stat).

Properties are:

{
  // fs.stat mode
  mode: 16822,
  //  size in bytes
  size: 12345,
  // lastModifiedTime as Date or number (or whatever gets parsed by moment)
  mtime: Date.now(),
  // optional, will use it for display if available, otherwise "owner"
  uname: 'kamicane',
  // optional, will use it for display if available, otherwise "group"
  gname: 'admins',
}

readdir [pathName, cb]:

The client wants a list of files in the directory pathName. requires an array of file names, relative to pathName, to be passed as cb(null, list).

mkdir [pathName, cb]:

The client wants to create a directory at pathName. Will consider the directory written if no error is passed to cb()

unlink [pathName, cb]:

The client wants to delete the file at pathName. Will consider the file deleted if no error is passed to cb()

remove [pathName, cb]:

The client wants to remove a directory, and all of its contents, at pathName. Will consider the directory and its contents removed if no error is passed to cb()

rename [fromName, toName, cb]:

The client wants to rename a file or directory, from fromName to toName. Will consider the file renamed if no error is passed to cb()

CLI

When installed globally, ftpd will provide a small cli, which will quickly create a fs-based ftp server.

You can use it like this:

ftp-server /public/files --host 192.168.0.1 --port 1234 --max-connections 10
  • --host will default to 127.0.0.1
  • --port will default to 1337
  • --max-connections will default to 10
  • --read-only will default to true
  • Unless specified, the ftp root will default to process.cwd()

The cli will accept any login, so be careful when setting --read-only to false.

License

MIT