Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e449e75219 | ||
|
|
296573ae01 | ||
|
|
be579f65d0 | ||
|
|
c440050945 | ||
|
|
ca576acf2e | ||
|
|
649d582f30 | ||
|
|
e26caad783 | ||
|
|
2470db6482 | ||
|
|
d78fae0ce6 | ||
|
|
c59e191a39 | ||
|
|
b2b1b2a0d3 | ||
|
|
81fa7fcb89 | ||
|
|
a18841d770 | ||
|
|
0dbb7f9070 |
33
README.md
33
README.md
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="https://github.com/trs/ftp-srv">
|
||||
<a href="https://github.com/autovance/ftp-srv">
|
||||
<img alt="ftp-srv" src="logo.png" width="600px" />
|
||||
</a>
|
||||
</p>
|
||||
@@ -14,8 +14,8 @@
|
||||
<img alt="npm" src="https://img.shields.io/npm/dm/ftp-srv.svg?style=for-the-badge" />
|
||||
</a>
|
||||
|
||||
<a href="https://circleci.com/gh/trs/workflows/ftp-srv/tree/master">
|
||||
<img alt="circleci" src="https://img.shields.io/circleci/project/github/trs/ftp-srv/master.svg?style=for-the-badge" />
|
||||
<a href="https://circleci.com/gh/autovance/workflows/ftp-srv/tree/master">
|
||||
<img alt="circleci" src="https://img.shields.io/circleci/project/github/autovance/ftp-srv/master.svg?style=for-the-badge" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -73,10 +73,8 @@ _Note:_ The hostname must be the external IP address to accept external connecti
|
||||
__Default:__ `"ftp://127.0.0.1:21"`
|
||||
|
||||
#### `pasv_url`
|
||||
The hostname to provide a client when attempting a passive connection (`PASV`). This defaults to the provided `url` hostname.
|
||||
|
||||
_Note:_ If set to `0.0.0.0`, this will automatically resolve to the external IP of the box.
|
||||
__Default:__ `"127.0.0.1"`
|
||||
The hostname to provide a client when attempting a passive connection (`PASV`).
|
||||
If not provided, clients can only connect using an `Active` connection.
|
||||
|
||||
#### `pasv_min`
|
||||
Tne starting port to accept passive connections.
|
||||
@@ -141,19 +139,29 @@ $ ftp-srv ftp://0.0.0.0:9876 --root ~/Documents
|
||||
```
|
||||
|
||||
#### `url`
|
||||
|
||||
Set the listening URL.
|
||||
|
||||
Defaults to `ftp://127.0.0.1:21`
|
||||
|
||||
#### `--root` / `-r`
|
||||
#### `--pasv_url`
|
||||
The hostname to provide a client when attempting a passive connection (`PASV`).
|
||||
If not provided, clients can only connect using an `Active` connection.
|
||||
|
||||
#### `--pasv_min`
|
||||
The starting port to accept passive connections.
|
||||
__Default:__ `1024`
|
||||
|
||||
#### `--pasv_max`
|
||||
The ending port to accept passive connections.
|
||||
The range is then queried for an available port to use when required.
|
||||
__Default:__ `65535`
|
||||
|
||||
#### `--root` / `-r`
|
||||
Set the default root directory for users.
|
||||
|
||||
Defaults to the current directory.
|
||||
|
||||
#### `--credentials` / `-c`
|
||||
|
||||
Set the path to a json credentials file.
|
||||
|
||||
Format:
|
||||
@@ -170,13 +178,14 @@ Format:
|
||||
```
|
||||
|
||||
#### `--username`
|
||||
|
||||
Set the username for the only user. Do not provide an argument to allow anonymous login.
|
||||
|
||||
#### `--password`
|
||||
|
||||
Set the password for the given `username`.
|
||||
|
||||
#### `--read-only`
|
||||
Disable write actions such as upload, delete, etc.
|
||||
|
||||
## Events
|
||||
|
||||
The `FtpSrv` class extends the [node net.Server](https://nodejs.org/api/net.html#net_class_net_server). Some custom events can be resolved or rejected, such as `login`.
|
||||
|
||||
15
bin/index.js
15
bin/index.js
@@ -37,19 +37,22 @@ function setupYargs() {
|
||||
boolean: true,
|
||||
default: false
|
||||
})
|
||||
.option('pasv_url', {
|
||||
.option('pasv-url', {
|
||||
describe: 'URL to provide for passive connections',
|
||||
type: 'string'
|
||||
type: 'string',
|
||||
alias: 'pasv_url'
|
||||
})
|
||||
.option('pasv_min', {
|
||||
.option('pasv-min', {
|
||||
describe: 'Starting point to use when creating passive connections',
|
||||
type: 'number',
|
||||
default: 1024
|
||||
default: 1024,
|
||||
alias: 'pasv_min'
|
||||
})
|
||||
.option('pasv_max', {
|
||||
.option('pasv-max', {
|
||||
describe: 'Ending port to use when creating passive connections',
|
||||
type: 'number',
|
||||
default: 65535
|
||||
default: 65535,
|
||||
alias: 'pasv_max'
|
||||
})
|
||||
.parse();
|
||||
}
|
||||
|
||||
7
ftp-srv.d.ts
vendored
7
ftp-srv.d.ts
vendored
@@ -112,6 +112,13 @@ export class FtpServer extends EventEmitter {
|
||||
whitelist?: Array<string>
|
||||
}) => void,
|
||||
reject: (err?: Error) => void
|
||||
) => void): this;
|
||||
|
||||
on(event: "disconnect", listener: (
|
||||
data: {
|
||||
connection: FtpConnection,
|
||||
id: string
|
||||
}
|
||||
) => void): this;
|
||||
|
||||
on(event: "client-error", listener: (
|
||||
|
||||
414
package-lock.json
generated
414
package-lock.json
generated
@@ -1094,9 +1094,9 @@
|
||||
}
|
||||
},
|
||||
"acorn": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz",
|
||||
"integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==",
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
|
||||
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-jsx": {
|
||||
@@ -2966,9 +2966,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
|
||||
"integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
|
||||
"integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"neo-async": "^2.6.0",
|
||||
@@ -3100,9 +3100,9 @@
|
||||
}
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz",
|
||||
"integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==",
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
|
||||
"integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"agent-base": "^4.3.0",
|
||||
@@ -4015,9 +4015,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
|
||||
},
|
||||
"lodash._reinterpolate": {
|
||||
"version": "3.0.0",
|
||||
@@ -4256,7 +4256,7 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"dev": true
|
||||
},
|
||||
@@ -4650,9 +4650,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"npm": {
|
||||
"version": "6.11.2",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-6.11.2.tgz",
|
||||
"integrity": "sha512-OAkXqI4bm5MUvqVvqe6rxCXmJqrln8VDlkdftpOoayHKazz8IOCJAiCuKmz0TchL224EAKeG86umuD6RYNpuEg==",
|
||||
"version": "6.14.6",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-6.14.6.tgz",
|
||||
"integrity": "sha512-axnz6iHFK6WPE0js/+mRp+4IOwpHn5tJEw5KB6FiCU764zmffrhsYHbSHi2kKqNkRBt53XasXjngZfBD3FQzrQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"JSONStream": "^1.3.5",
|
||||
@@ -4661,12 +4661,12 @@
|
||||
"ansistyles": "~0.1.3",
|
||||
"aproba": "^2.0.0",
|
||||
"archy": "~1.0.0",
|
||||
"bin-links": "^1.1.3",
|
||||
"bin-links": "^1.1.7",
|
||||
"bluebird": "^3.5.5",
|
||||
"byte-size": "^5.0.1",
|
||||
"cacache": "^12.0.3",
|
||||
"call-limit": "^1.1.1",
|
||||
"chownr": "^1.1.2",
|
||||
"chownr": "^1.1.4",
|
||||
"ci-info": "^2.0.0",
|
||||
"cli-columns": "^3.1.2",
|
||||
"cli-table3": "^0.5.1",
|
||||
@@ -4682,11 +4682,11 @@
|
||||
"find-npm-prefix": "^1.0.2",
|
||||
"fs-vacuum": "~1.2.10",
|
||||
"fs-write-stream-atomic": "~1.0.10",
|
||||
"gentle-fs": "^2.2.1",
|
||||
"glob": "^7.1.4",
|
||||
"graceful-fs": "^4.2.2",
|
||||
"gentle-fs": "^2.3.0",
|
||||
"glob": "^7.1.6",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"has-unicode": "~2.0.1",
|
||||
"hosted-git-info": "^2.8.2",
|
||||
"hosted-git-info": "^2.8.8",
|
||||
"iferr": "^1.0.2",
|
||||
"imurmurhash": "*",
|
||||
"infer-owner": "^1.0.4",
|
||||
@@ -4697,14 +4697,14 @@
|
||||
"is-cidr": "^3.0.0",
|
||||
"json-parse-better-errors": "^1.0.2",
|
||||
"lazy-property": "~1.0.0",
|
||||
"libcipm": "^4.0.3",
|
||||
"libcipm": "^4.0.7",
|
||||
"libnpm": "^3.0.1",
|
||||
"libnpmaccess": "^3.0.2",
|
||||
"libnpmhook": "^5.0.3",
|
||||
"libnpmorg": "^1.0.1",
|
||||
"libnpmsearch": "^2.0.2",
|
||||
"libnpmteam": "^1.0.2",
|
||||
"libnpx": "^10.2.0",
|
||||
"libnpx": "^10.2.2",
|
||||
"lock-verify": "^2.1.0",
|
||||
"lockfile": "^1.0.4",
|
||||
"lodash._baseindexof": "*",
|
||||
@@ -4721,41 +4721,41 @@
|
||||
"lru-cache": "^5.1.1",
|
||||
"meant": "~1.0.1",
|
||||
"mississippi": "^3.0.0",
|
||||
"mkdirp": "~0.5.1",
|
||||
"mkdirp": "^0.5.5",
|
||||
"move-concurrently": "^1.0.1",
|
||||
"node-gyp": "^5.0.3",
|
||||
"nopt": "~4.0.1",
|
||||
"node-gyp": "^5.1.0",
|
||||
"nopt": "^4.0.3",
|
||||
"normalize-package-data": "^2.5.0",
|
||||
"npm-audit-report": "^1.3.2",
|
||||
"npm-cache-filename": "~1.0.2",
|
||||
"npm-install-checks": "~3.0.0",
|
||||
"npm-lifecycle": "^3.1.3",
|
||||
"npm-install-checks": "^3.0.2",
|
||||
"npm-lifecycle": "^3.1.4",
|
||||
"npm-package-arg": "^6.1.1",
|
||||
"npm-packlist": "^1.4.4",
|
||||
"npm-pick-manifest": "^3.0.0",
|
||||
"npm-profile": "^4.0.2",
|
||||
"npm-registry-fetch": "^4.0.0",
|
||||
"npm-packlist": "^1.4.8",
|
||||
"npm-pick-manifest": "^3.0.2",
|
||||
"npm-profile": "^4.0.4",
|
||||
"npm-registry-fetch": "^4.0.5",
|
||||
"npm-user-validate": "~1.0.0",
|
||||
"npmlog": "~4.1.2",
|
||||
"once": "~1.4.0",
|
||||
"opener": "^1.5.1",
|
||||
"osenv": "^0.1.5",
|
||||
"pacote": "^9.5.8",
|
||||
"pacote": "^9.5.12",
|
||||
"path-is-inside": "~1.0.2",
|
||||
"promise-inflight": "~1.0.1",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"query-string": "^6.8.2",
|
||||
"qw": "~1.0.1",
|
||||
"read": "~1.0.7",
|
||||
"read-cmd-shim": "^1.0.3",
|
||||
"read-cmd-shim": "^1.0.5",
|
||||
"read-installed": "~4.0.3",
|
||||
"read-package-json": "^2.1.0",
|
||||
"read-package-json": "^2.1.1",
|
||||
"read-package-tree": "^5.3.1",
|
||||
"readable-stream": "^3.4.0",
|
||||
"readable-stream": "^3.6.0",
|
||||
"readdir-scoped-modules": "^1.1.0",
|
||||
"request": "^2.88.0",
|
||||
"retry": "^0.12.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"rimraf": "^2.7.1",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"semver": "^5.7.1",
|
||||
"sha": "^3.0.0",
|
||||
@@ -4763,8 +4763,8 @@
|
||||
"sorted-object": "~2.0.1",
|
||||
"sorted-union-stream": "~2.1.3",
|
||||
"ssri": "^6.0.1",
|
||||
"stringify-package": "^1.0.0",
|
||||
"tar": "^4.4.10",
|
||||
"stringify-package": "^1.0.1",
|
||||
"tar": "^4.4.13",
|
||||
"text-table": "~0.2.0",
|
||||
"tiny-relative-date": "^1.3.0",
|
||||
"uid-number": "0.0.6",
|
||||
@@ -4772,7 +4772,7 @@
|
||||
"unique-filename": "^1.1.1",
|
||||
"unpipe": "~1.0.0",
|
||||
"update-notifier": "^2.5.0",
|
||||
"uuid": "^3.3.2",
|
||||
"uuid": "^3.3.3",
|
||||
"validate-npm-package-license": "^3.0.4",
|
||||
"validate-npm-package-name": "~3.0.0",
|
||||
"which": "^1.3.1",
|
||||
@@ -4943,14 +4943,15 @@
|
||||
}
|
||||
},
|
||||
"bin-links": {
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.7",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bluebird": "^3.5.3",
|
||||
"cmd-shim": "^3.0.0",
|
||||
"gentle-fs": "^2.0.1",
|
||||
"gentle-fs": "^2.3.0",
|
||||
"graceful-fs": "^4.1.15",
|
||||
"npm-normalize-package-bin": "^1.0.0",
|
||||
"write-file-atomic": "^2.3.0"
|
||||
}
|
||||
},
|
||||
@@ -5055,7 +5056,7 @@
|
||||
}
|
||||
},
|
||||
"chownr": {
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.4",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -5361,7 +5362,7 @@
|
||||
"dev": true
|
||||
},
|
||||
"deep-extend": {
|
||||
"version": "0.5.1",
|
||||
"version": "0.6.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -5495,7 +5496,7 @@
|
||||
}
|
||||
},
|
||||
"env-paths": {
|
||||
"version": "1.0.0",
|
||||
"version": "2.2.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -5693,11 +5694,22 @@
|
||||
}
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "1.2.6",
|
||||
"version": "1.2.7",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minipass": "^2.2.1"
|
||||
"minipass": "^2.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"minipass": {
|
||||
"version": "2.9.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fs-vacuum": {
|
||||
@@ -5798,12 +5810,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"gentle-fs": {
|
||||
"version": "2.2.1",
|
||||
"version": "2.3.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aproba": "^1.1.2",
|
||||
"chownr": "^1.1.2",
|
||||
"cmd-shim": "^3.0.3",
|
||||
"fs-vacuum": "^1.2.10",
|
||||
"graceful-fs": "^4.1.11",
|
||||
"iferr": "^0.1.5",
|
||||
@@ -5827,7 +5840,7 @@
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -5848,7 +5861,7 @@
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.4",
|
||||
"version": "7.1.6",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -5894,7 +5907,7 @@
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.2",
|
||||
"version": "4.2.4",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -5936,12 +5949,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.2",
|
||||
"version": "2.8.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^5.1.1"
|
||||
}
|
||||
"dev": true
|
||||
},
|
||||
"http-cache-semantics": {
|
||||
"version": "3.8.1",
|
||||
@@ -5968,7 +5978,7 @@
|
||||
}
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "2.2.2",
|
||||
"version": "2.2.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -5998,7 +6008,7 @@
|
||||
"dev": true
|
||||
},
|
||||
"ignore-walk": {
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6055,7 +6065,7 @@
|
||||
}
|
||||
},
|
||||
"invert-kv": {
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -6075,11 +6085,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"is-ci": {
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ci-info": "^1.0.0"
|
||||
"ci-info": "^1.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ci-info": {
|
||||
@@ -6151,7 +6161,7 @@
|
||||
}
|
||||
},
|
||||
"is-retry-allowed": {
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -6244,15 +6254,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"lcid": {
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"invert-kv": "^1.0.0"
|
||||
"invert-kv": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"libcipm": {
|
||||
"version": "4.0.3",
|
||||
"version": "4.0.7",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6421,7 +6431,7 @@
|
||||
}
|
||||
},
|
||||
"libnpx": {
|
||||
"version": "10.2.0",
|
||||
"version": "10.2.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6555,7 +6565,7 @@
|
||||
}
|
||||
},
|
||||
"make-fetch-happen": {
|
||||
"version": "5.0.0",
|
||||
"version": "5.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6563,7 +6573,7 @@
|
||||
"cacache": "^12.0.0",
|
||||
"http-cache-semantics": "^3.8.1",
|
||||
"http-proxy-agent": "^2.1.0",
|
||||
"https-proxy-agent": "^2.2.1",
|
||||
"https-proxy-agent": "^2.2.3",
|
||||
"lru-cache": "^5.1.1",
|
||||
"mississippi": "^3.0.0",
|
||||
"node-fetch-npm": "^2.0.2",
|
||||
@@ -6572,17 +6582,34 @@
|
||||
"ssri": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"map-age-cleaner": {
|
||||
"version": "0.1.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-defer": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"meant": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"mem": {
|
||||
"version": "1.1.0",
|
||||
"version": "4.3.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^1.0.0"
|
||||
"map-age-cleaner": "^0.1.1",
|
||||
"mimic-fn": "^2.0.0",
|
||||
"p-is-promise": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
@@ -6598,11 +6625,6 @@
|
||||
"mime-db": "~1.35.0"
|
||||
}
|
||||
},
|
||||
"mimic-fn": {
|
||||
"version": "1.2.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
@@ -6611,35 +6633,25 @@
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.3",
|
||||
"minizlib": {
|
||||
"version": "1.3.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
"minipass": "^2.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"yallist": {
|
||||
"version": "3.0.2",
|
||||
"minipass": {
|
||||
"version": "2.9.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"minizlib": {
|
||||
"version": "1.2.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minipass": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"mississippi": {
|
||||
"version": "3.0.0",
|
||||
"bundled": true,
|
||||
@@ -6658,11 +6670,18 @@
|
||||
}
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"version": "0.5.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
"minimist": "^1.2.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"move-concurrently": {
|
||||
@@ -6695,6 +6714,11 @@
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"nice-try": {
|
||||
"version": "1.0.5",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"node-fetch-npm": {
|
||||
"version": "2.0.2",
|
||||
"bundled": true,
|
||||
@@ -6706,40 +6730,25 @@
|
||||
}
|
||||
},
|
||||
"node-gyp": {
|
||||
"version": "5.0.3",
|
||||
"version": "5.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"env-paths": "^1.0.0",
|
||||
"glob": "^7.0.3",
|
||||
"graceful-fs": "^4.1.2",
|
||||
"mkdirp": "^0.5.0",
|
||||
"nopt": "2 || 3",
|
||||
"npmlog": "0 || 1 || 2 || 3 || 4",
|
||||
"request": "^2.87.0",
|
||||
"rimraf": "2",
|
||||
"semver": "~5.3.0",
|
||||
"tar": "^4.4.8",
|
||||
"which": "1"
|
||||
},
|
||||
"dependencies": {
|
||||
"nopt": {
|
||||
"version": "3.0.6",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"abbrev": "1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.3.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
"env-paths": "^2.2.0",
|
||||
"glob": "^7.1.4",
|
||||
"graceful-fs": "^4.2.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"nopt": "^4.0.1",
|
||||
"npmlog": "^4.1.2",
|
||||
"request": "^2.88.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"semver": "^5.7.1",
|
||||
"tar": "^4.4.12",
|
||||
"which": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
"version": "4.0.1",
|
||||
"version": "4.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6778,9 +6787,12 @@
|
||||
}
|
||||
},
|
||||
"npm-bundled": {
|
||||
"version": "1.0.6",
|
||||
"version": "1.1.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"npm-normalize-package-bin": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"npm-cache-filename": {
|
||||
"version": "1.0.2",
|
||||
@@ -6788,7 +6800,7 @@
|
||||
"dev": true
|
||||
},
|
||||
"npm-install-checks": {
|
||||
"version": "3.0.0",
|
||||
"version": "3.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6796,7 +6808,7 @@
|
||||
}
|
||||
},
|
||||
"npm-lifecycle": {
|
||||
"version": "3.1.3",
|
||||
"version": "3.1.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6815,6 +6827,11 @@
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"npm-normalize-package-bin": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"npm-package-arg": {
|
||||
"version": "6.1.1",
|
||||
"bundled": true,
|
||||
@@ -6827,16 +6844,17 @@
|
||||
}
|
||||
},
|
||||
"npm-packlist": {
|
||||
"version": "1.4.4",
|
||||
"version": "1.4.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ignore-walk": "^3.0.1",
|
||||
"npm-bundled": "^1.0.1"
|
||||
"npm-bundled": "^1.0.1",
|
||||
"npm-normalize-package-bin": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"npm-pick-manifest": {
|
||||
"version": "3.0.0",
|
||||
"version": "3.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6846,7 +6864,7 @@
|
||||
}
|
||||
},
|
||||
"npm-profile": {
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6856,7 +6874,7 @@
|
||||
}
|
||||
},
|
||||
"npm-registry-fetch": {
|
||||
"version": "4.0.0",
|
||||
"version": "4.0.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -6865,7 +6883,15 @@
|
||||
"figgy-pudding": "^3.4.1",
|
||||
"lru-cache": "^5.1.1",
|
||||
"make-fetch-happen": "^5.0.0",
|
||||
"npm-package-arg": "^6.1.0"
|
||||
"npm-package-arg": "^6.1.0",
|
||||
"safe-buffer": "^5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"npm-run-path": {
|
||||
@@ -6940,13 +6966,41 @@
|
||||
"dev": true
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "2.1.0",
|
||||
"version": "3.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"execa": "^0.7.0",
|
||||
"lcid": "^1.0.0",
|
||||
"mem": "^1.1.0"
|
||||
"execa": "^1.0.0",
|
||||
"lcid": "^2.0.0",
|
||||
"mem": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-spawn": {
|
||||
"version": "6.0.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"nice-try": "^1.0.4",
|
||||
"path-key": "^2.0.1",
|
||||
"semver": "^5.5.0",
|
||||
"shebang-command": "^1.2.0",
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
"p-finally": "^1.0.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"strip-eof": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"os-tmpdir": {
|
||||
@@ -6963,11 +7017,21 @@
|
||||
"os-tmpdir": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"p-defer": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"p-is-promise": {
|
||||
"version": "2.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "1.2.0",
|
||||
"bundled": true,
|
||||
@@ -7001,7 +7065,7 @@
|
||||
}
|
||||
},
|
||||
"pacote": {
|
||||
"version": "9.5.8",
|
||||
"version": "9.5.12",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -7019,6 +7083,7 @@
|
||||
"mississippi": "^3.0.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"normalize-package-data": "^2.4.0",
|
||||
"npm-normalize-package-bin": "^1.0.0",
|
||||
"npm-package-arg": "^6.1.0",
|
||||
"npm-packlist": "^1.1.12",
|
||||
"npm-pick-manifest": "^3.0.0",
|
||||
@@ -7037,7 +7102,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"version": "2.9.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -7244,18 +7309,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"rc": {
|
||||
"version": "1.2.7",
|
||||
"version": "1.2.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"deep-extend": "^0.5.1",
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.5",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
@@ -7270,7 +7335,7 @@
|
||||
}
|
||||
},
|
||||
"read-cmd-shim": {
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -7292,7 +7357,7 @@
|
||||
}
|
||||
},
|
||||
"read-package-json": {
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -7300,7 +7365,7 @@
|
||||
"graceful-fs": "^4.1.2",
|
||||
"json-parse-better-errors": "^1.0.1",
|
||||
"normalize-package-data": "^2.0.0",
|
||||
"slash": "^1.0.0"
|
||||
"npm-normalize-package-bin": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"read-package-tree": {
|
||||
@@ -7314,7 +7379,7 @@
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.4.0",
|
||||
"version": "3.6.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -7335,7 +7400,7 @@
|
||||
}
|
||||
},
|
||||
"registry-auth-token": {
|
||||
"version": "3.3.2",
|
||||
"version": "3.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -7399,7 +7464,7 @@
|
||||
"dev": true
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.6.3",
|
||||
"version": "2.7.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -7475,28 +7540,23 @@
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"slash": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"slide": {
|
||||
"version": "1.1.6",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"smart-buffer": {
|
||||
"version": "4.0.2",
|
||||
"version": "4.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"socks": {
|
||||
"version": "2.3.2",
|
||||
"version": "2.3.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ip": "^1.1.5",
|
||||
"smart-buffer": "4.0.2"
|
||||
"ip": "1.1.5",
|
||||
"smart-buffer": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"socks-proxy-agent": {
|
||||
@@ -7588,7 +7648,7 @@
|
||||
}
|
||||
},
|
||||
"spdx-license-ids": {
|
||||
"version": "3.0.3",
|
||||
"version": "3.0.5",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -7703,15 +7763,22 @@
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
"safe-buffer": "~5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"stringify-package": {
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -7742,13 +7809,13 @@
|
||||
}
|
||||
},
|
||||
"tar": {
|
||||
"version": "4.4.10",
|
||||
"version": "4.4.13",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chownr": "^1.1.1",
|
||||
"fs-minipass": "^1.2.5",
|
||||
"minipass": "^2.3.5",
|
||||
"minipass": "^2.8.6",
|
||||
"minizlib": "^1.2.1",
|
||||
"mkdirp": "^0.5.0",
|
||||
"safe-buffer": "^5.1.2",
|
||||
@@ -7756,18 +7823,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"version": "2.9.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -7948,7 +8010,7 @@
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.2",
|
||||
"version": "3.3.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@@ -8021,7 +8083,7 @@
|
||||
}
|
||||
},
|
||||
"widest-line": {
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -8093,7 +8155,7 @@
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "11.0.0",
|
||||
"version": "11.1.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@@ -8101,7 +8163,7 @@
|
||||
"decamelize": "^1.1.1",
|
||||
"find-up": "^2.1.0",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"os-locale": "^2.0.0",
|
||||
"os-locale": "^3.1.0",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"set-blocking": "^2.0.0",
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"types": "./ftp-srv.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/trs/ftp-srv"
|
||||
"url": "https://github.com/autovance/ftp-srv"
|
||||
},
|
||||
"scripts": {
|
||||
"pre-release": "npm run verify",
|
||||
|
||||
@@ -45,25 +45,25 @@ class FtpCommands {
|
||||
log.trace({command: logCommand}, 'Handle command');
|
||||
|
||||
if (!REGISTRY.hasOwnProperty(command.directive)) {
|
||||
return this.connection.reply(402, 'Command not allowed');
|
||||
return this.connection.reply(502, `Command not allowed: ${command.directive}`);
|
||||
}
|
||||
|
||||
if (_.includes(this.blacklist, command.directive)) {
|
||||
return this.connection.reply(502, 'Command blacklisted');
|
||||
return this.connection.reply(502, `Command blacklisted: ${command.directive}`);
|
||||
}
|
||||
|
||||
if (this.whitelist.length > 0 && !_.includes(this.whitelist, command.directive)) {
|
||||
return this.connection.reply(502, 'Command not whitelisted');
|
||||
return this.connection.reply(502, `Command not whitelisted: ${command.directive}`);
|
||||
}
|
||||
|
||||
const commandRegister = REGISTRY[command.directive];
|
||||
const commandFlags = _.get(commandRegister, 'flags', {});
|
||||
if (!commandFlags.no_auth && !this.connection.authenticated) {
|
||||
return this.connection.reply(530, 'Command requires authentication');
|
||||
return this.connection.reply(530, `Command requires authentication: ${command.directive}`);
|
||||
}
|
||||
|
||||
if (!commandRegister.handler) {
|
||||
return this.connection.reply(502, 'Handler not set on command');
|
||||
return this.connection.reply(502, `Handler not set on command: ${command.directive}`);
|
||||
}
|
||||
|
||||
const handler = commandRegister.handler.bind(this.connection);
|
||||
|
||||
@@ -8,14 +8,18 @@ const FAMILY = {
|
||||
|
||||
module.exports = {
|
||||
directive: 'EPRT',
|
||||
handler: function ({command} = {}) {
|
||||
handler: function ({log, command} = {}) {
|
||||
const [, protocol, ip, port] = _.chain(command).get('arg', '').split('|').value();
|
||||
const family = FAMILY[protocol];
|
||||
if (!family) return this.reply(504, 'Unknown network protocol');
|
||||
|
||||
this.connector = new ActiveConnector(this);
|
||||
return this.connector.setupConnection(ip, port, family)
|
||||
.then(() => this.reply(200));
|
||||
.then(() => this.reply(200))
|
||||
.catch((err) => {
|
||||
log.error(err);
|
||||
return this.reply(err.code || 425, err.message);
|
||||
});
|
||||
},
|
||||
syntax: '{{cmd}} |<protocol>|<address>|<port>|',
|
||||
description: 'Specifies an address and port to which the server should connect'
|
||||
|
||||
@@ -2,13 +2,17 @@ const PassiveConnector = require('../../connector/passive');
|
||||
|
||||
module.exports = {
|
||||
directive: 'EPSV',
|
||||
handler: function () {
|
||||
handler: function ({log}) {
|
||||
this.connector = new PassiveConnector(this);
|
||||
return this.connector.setupServer()
|
||||
.then((server) => {
|
||||
const {port} = server.address();
|
||||
|
||||
return this.reply(229, `EPSV OK (|||${port}|)`);
|
||||
})
|
||||
.catch((err) => {
|
||||
log.error(err);
|
||||
return this.reply(err.code || 425, err.message);
|
||||
});
|
||||
},
|
||||
syntax: '{{cmd}} [<protocol>]',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const _ = require('lodash');
|
||||
const registry = require('../registry');
|
||||
|
||||
module.exports = {
|
||||
directive: 'FEAT',
|
||||
handler: function () {
|
||||
const registry = require('../registry');
|
||||
const features = Object.keys(registry)
|
||||
.reduce((feats, cmd) => {
|
||||
const feat = _.get(registry[cmd], 'flags.feat', null);
|
||||
|
||||
@@ -13,7 +13,7 @@ module.exports = {
|
||||
const [_option, ...args] = command.arg.split(' ');
|
||||
const option = _.toUpper(_option);
|
||||
|
||||
if (!OPTIONS.hasOwnProperty(option)) return this.reply(500);
|
||||
if (!OPTIONS.hasOwnProperty(option)) return this.reply(501, 'Unknown option command');
|
||||
return OPTIONS[option].call(this, args);
|
||||
},
|
||||
syntax: '{{cmd}}',
|
||||
|
||||
@@ -25,7 +25,7 @@ module.exports = {
|
||||
})
|
||||
.catch((err) => {
|
||||
log.error(err);
|
||||
return this.reply(425);
|
||||
return this.reply(err.code || 425, err.message);
|
||||
});
|
||||
},
|
||||
syntax: '{{cmd}}',
|
||||
|
||||
@@ -17,7 +17,7 @@ module.exports = {
|
||||
.then(() => this.reply(200))
|
||||
.catch((err) => {
|
||||
log.error(err);
|
||||
return this.reply(425);
|
||||
return this.reply(err.code || 425, err.message);
|
||||
});
|
||||
},
|
||||
syntax: '{{cmd}} <x>,<x>,<x>,<x>,<y>,<y>',
|
||||
|
||||
@@ -32,7 +32,7 @@ class FtpConnection extends EventEmitter {
|
||||
this.commandSocket.on('data', this._handleData.bind(this));
|
||||
this.commandSocket.on('timeout', () => {
|
||||
this.log.trace('Client timeout');
|
||||
this.close().catch((e) => this.log.trace(e, 'Client close error'));
|
||||
this.close();
|
||||
});
|
||||
this.commandSocket.on('close', () => {
|
||||
if (this.connector) this.connector.end();
|
||||
@@ -72,7 +72,7 @@ class FtpConnection extends EventEmitter {
|
||||
close(code = 421, message = 'Closing connection') {
|
||||
return Promise.resolve(code)
|
||||
.then((_code) => _code && this.reply(_code, message))
|
||||
.then(() => this.commandSocket && this.commandSocket.end());
|
||||
.finally(() => this.commandSocket && this.commandSocket.destroy());
|
||||
}
|
||||
|
||||
login(username, password) {
|
||||
@@ -136,7 +136,10 @@ class FtpConnection extends EventEmitter {
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
} else reject(new errors.SocketError('Socket not writable'));
|
||||
} else {
|
||||
this.log.trace({message: letter.message}, 'Could not write message');
|
||||
reject(new errors.SocketError('Socket not writable'));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
const {Socket} = require('net');
|
||||
const tls = require('tls');
|
||||
const ip = require('ip');
|
||||
const Promise = require('bluebird');
|
||||
const Connector = require('./base');
|
||||
const {SocketError} = require('../errors');
|
||||
|
||||
class Active extends Connector {
|
||||
constructor(connection) {
|
||||
@@ -27,6 +29,10 @@ class Active extends Connector {
|
||||
|
||||
return closeExistingServer()
|
||||
.then(() => {
|
||||
if (!ip.isEqual(this.connection.commandSocket.remoteAddress, host)) {
|
||||
throw new SocketError('The given address is not yours', 500);
|
||||
}
|
||||
|
||||
this.dataSocket = new Socket();
|
||||
this.dataSocket.on('error', (err) => this.server && this.server.emit('client-error', {connection: this.connection, context: 'dataSocket', error: err}));
|
||||
this.dataSocket.connect({host, port, family}, () => {
|
||||
|
||||
@@ -29,7 +29,7 @@ class Connector {
|
||||
closeSocket() {
|
||||
if (this.dataSocket) {
|
||||
const socket = this.dataSocket;
|
||||
this.dataSocket.end(() => socket.destroy());
|
||||
this.dataSocket.end(() => socket && socket.destroy());
|
||||
this.dataSocket = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,20 +40,21 @@ class FtpServer extends EventEmitter {
|
||||
_.get(this, 'options.pasv_min'),
|
||||
_.get(this, 'options.pasv_max'));
|
||||
|
||||
const timeout = Number(this.options.timeout);
|
||||
this.options.timeout = isNaN(timeout) ? 0 : Number(timeout);
|
||||
const timeout = Number(this.options.timeout);
|
||||
this.options.timeout = isNaN(timeout) ? 0 : Number(timeout);
|
||||
|
||||
const serverConnectionHandler = (socket) => {
|
||||
socket.setTimeout(this.options.timeout);
|
||||
this.options.timeout > 0 && socket.setTimeout(this.options.timeout);
|
||||
let connection = new Connection(this, {log: this.log, socket});
|
||||
this.connections[connection.id] = connection;
|
||||
|
||||
socket.on('close', () => this.disconnectClient(connection.id));
|
||||
socket.once('close', () => this.emit('disconnect', {connection, id: connection.id}));
|
||||
|
||||
const greeting = this._greeting || [];
|
||||
const features = this._features || 'Ready';
|
||||
return connection.reply(220, ...greeting, features)
|
||||
.finally(() => socket.resume());
|
||||
.finally(() => socket.resume());
|
||||
};
|
||||
const serverOptions = Object.assign({}, this.isTLS ? this.options.tls : {}, {pauseOnConnect: true});
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ describe('FtpCommands', function () {
|
||||
return commands.handle('bad')
|
||||
.then(() => {
|
||||
expect(mockConnection.reply.callCount).to.equal(1);
|
||||
expect(mockConnection.reply.args[0][0]).to.equal(402);
|
||||
expect(mockConnection.reply.args[0][0]).to.equal(502);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ describe(CMD, function () {
|
||||
});
|
||||
|
||||
it('// unsuccessful | no argument', () => {
|
||||
return cmdFn()
|
||||
return cmdFn({})
|
||||
.then(() => {
|
||||
expect(mockClient.reply.args[0][0]).to.equal(504);
|
||||
});
|
||||
|
||||
@@ -25,7 +25,7 @@ describe(CMD, function () {
|
||||
});
|
||||
|
||||
it('// successful IPv4', () => {
|
||||
return cmdFn()
|
||||
return cmdFn({})
|
||||
.then(() => {
|
||||
const [code, message] = mockClient.reply.args[0];
|
||||
expect(code).to.equal(229);
|
||||
|
||||
@@ -29,7 +29,7 @@ describe(CMD, function () {
|
||||
it('BAD // unsuccessful', () => {
|
||||
return cmdFn({command: {arg: 'BAD', directive: CMD}})
|
||||
.then(() => {
|
||||
expect(mockClient.reply.args[0][0]).to.equal(500);
|
||||
expect(mockClient.reply.args[0][0]).to.equal(501);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -13,14 +13,16 @@ describe('Connector - Active //', function () {
|
||||
let getNextPort = getNextPortFactory(host, 1024);
|
||||
let PORT;
|
||||
let active;
|
||||
let mockConnection = {};
|
||||
let mockConnection = {
|
||||
commandSocket: {
|
||||
remoteAddress: '::ffff:127.0.0.1'
|
||||
}
|
||||
};
|
||||
let sandbox;
|
||||
let server;
|
||||
|
||||
before(() => {
|
||||
active = new ActiveConnector(mockConnection);
|
||||
});
|
||||
beforeEach((done) => {
|
||||
active = new ActiveConnector(mockConnection);
|
||||
sandbox = sinon.sandbox.create().usingPromise(Promise);
|
||||
|
||||
getNextPort()
|
||||
@@ -31,9 +33,12 @@ describe('Connector - Active //', function () {
|
||||
.listen(PORT, () => done());
|
||||
});
|
||||
});
|
||||
afterEach((done) => {
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
server.close(done);
|
||||
server.close();
|
||||
active.end();
|
||||
|
||||
});
|
||||
|
||||
it('sets up a connection', function () {
|
||||
@@ -43,13 +48,27 @@ describe('Connector - Active //', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('destroys existing connection, then sets up a connection', function () {
|
||||
const destroyFnSpy = sandbox.spy(active.dataSocket, 'destroy');
|
||||
it('rejects alternative host', function () {
|
||||
return active.setupConnection('123.45.67.89', PORT)
|
||||
.catch((err) => {
|
||||
expect(err.code).to.equal(500);
|
||||
expect(err.message).to.equal('The given address is not yours');
|
||||
})
|
||||
.finally(() => {
|
||||
expect(active.dataSocket).not.to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
it('destroys existing connection, then sets up a connection', function () {
|
||||
return active.setupConnection(host, PORT)
|
||||
.then(() => {
|
||||
expect(destroyFnSpy.callCount).to.equal(1);
|
||||
expect(active.dataSocket).to.exist;
|
||||
const destroyFnSpy = sandbox.spy(active.dataSocket, 'destroy');
|
||||
|
||||
return active.setupConnection(host, PORT)
|
||||
.then(() => {
|
||||
expect(destroyFnSpy.callCount).to.equal(1);
|
||||
expect(active.dataSocket).to.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -369,6 +369,39 @@ describe('Integration', function () {
|
||||
});
|
||||
}
|
||||
|
||||
describe('Server events', function () {
|
||||
const disconnect = sinon.spy();
|
||||
const login = sinon.spy();
|
||||
|
||||
before(() => {
|
||||
server.on('login', login);
|
||||
server.on('disconnect', disconnect);
|
||||
return connectClient({
|
||||
host: server.url.hostname,
|
||||
port: server.url.port,
|
||||
user: 'test',
|
||||
password: 'test'
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
server.off('login', login);
|
||||
server.off('disconnect', disconnect);
|
||||
})
|
||||
|
||||
it('should fire a login event on connect', () => {
|
||||
expect(login.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should fire a close event on disconnect', (done) => {
|
||||
client.end();
|
||||
setTimeout(() => {
|
||||
expect(disconnect.calledOnce).to.be.true;
|
||||
done();
|
||||
}, 100)
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ASCII', function () {
|
||||
before(() => {
|
||||
return connectClient({
|
||||
|
||||
Reference in New Issue
Block a user