diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 73a873bfa..c8f458501 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -239,6 +239,8 @@ This document generated by [dt-contributors-generator](https://github.com/vvakam * [:link:](fs-finder/fs-finder.d.ts) [fs-finder](https://github.com/sakren/node-fs-finder) by [Michael Zabka](https://github.com/misak113) * [:link:](fs-mock/fs-mock.d.ts) [fs-mock](https://github.com/sakren/node-fs-mock) by [Rogier Schouten](https://github.com/rogierschouten) * [:link:](ftdomdelegate/ftdomdelegate.d.ts) [ftdomdelegate](https://github.com/ftlabs/ftdomdelegate) by [Christian Holm Nielsen](https://github.com/dotnetnerd) +* [:link:](ftp/ftp.d.ts) [ftp](https://github.com/mscdex/node-ftp) by [Rogier Schouten](https://github.com/rogierschouten) +* [:link:](ftpd/ftpd.d.ts) [ftp](https://github.com/sstur/nodeftpd) by [Rogier Schouten](https://github.com/rogierschouten) * [:link:](fullCalendar/fullCalendar.d.ts) [FullCalendar](http://arshaw.com/fullcalendar) by [Neil Stalker](https://github.com/nestalk) * [:link:](fuse/fuse.d.ts) [Fuse.js](https://github.com/krisk/Fuse) by [Greg Smith](https://github.com/smrq) * [:link:](jquery-galleria/jquery-galleria.d.ts) [galleria.js](https://github.com/aino/galleria) by [Robert Imig](https://github.com/rimig) diff --git a/ftp/ftp-tests.ts b/ftp/ftp-tests.ts new file mode 100644 index 000000000..2e37e53f9 --- /dev/null +++ b/ftp/ftp-tests.ts @@ -0,0 +1,28 @@ +/// +/// + +import Client = require("ftp"); +import fs = require("fs"); + +var c = new Client(); +c.on('ready', (): void => { + c.get('foo.txt', function(err: Error, stream: NodeJS.ReadableStream): void { + if (err) throw err; + stream.once('close', function(): void { + c.end(); + }); + stream.pipe(fs.createWriteStream('foo.local-copy.txt')); + }); +}); +// connect to localhost:21 as anonymous +c.connect(); + +c.connect({ + host: "127.0.0.1", + port: 21, + username: "Boo", + password: "secret" +}); + + + diff --git a/ftp/ftp.d.ts b/ftp/ftp.d.ts new file mode 100644 index 000000000..764505037 --- /dev/null +++ b/ftp/ftp.d.ts @@ -0,0 +1,294 @@ +// Type definitions for ftp 0.3.8 +// Project: https://github.com/mscdex/node-ftp +// Definitions by: Rogier Schouten +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +/// + +declare module "ftp" { + + import events = require("events"); + import tls = require("tls"); + + module Client { + + /** + * Options for Client#connect() + */ + export interface Options { + /** + * The hostname or IP address of the FTP server. Default: 'localhost' + */ + host?: string; + /** + * The port of the FTP server. Default: 21 + */ + port?: number; + /** + * Set to true for both control and data connection encryption, 'control' for control connection encryption only, or 'implicit' for + * implicitly encrypted control connection (this mode is deprecated in modern times, but usually uses port 990) Default: false + */ + secure?: string|boolean; + /** + * Additional options to be passed to tls.connect(). Default: (none) + */ + secureOptions?: tls.ConnectionOptions; + /** + * Username for authentication. Default: 'anonymous' + */ + user?: string; + /** + * Password for authentication. Default: 'anonymous@' + */ + password?: string; + /** + * How long (in milliseconds) to wait for the control connection to be established. Default: 10000 + */ + connTimeout?: number; + /** + * How long (in milliseconds) to wait for a PASV data connection to be established. Default: 10000 + */ + pasvTimeout?: number; + /** + * How often (in milliseconds) to send a 'dummy' (NOOP) command to keep the connection alive. Default: 10000 + */ + keepalive?: number; + } + + /** + * Element returned by Client#list() + */ + export interface ListingElement { + /** + * A single character denoting the entry type: 'd' for directory, '-' for file (or 'l' for symlink on **\*NIX only**). + */ + "type": string; + /** + * The name of the entry + */ + name: string; + /** + * The size of the entry in bytes + */ + size: string; + /** + * The last modified date of the entry + */ + date: Date; + /** + * The various permissions for this entry **(*NIX only)** + */ + rights?: { + /** + * An empty string or any combination of 'r', 'w', 'x'. + */ + user: string; + /** + * An empty string or any combination of 'r', 'w', 'x'. + */ + group: string; + /** + * An empty string or any combination of 'r', 'w', 'x'. + */ + other: string; + }; + /** + * The user name or ID that this entry belongs to **(*NIX only)**. + */ + owner?: string; + /** + * The group name or ID that this entry belongs to **(*NIX only)**. + */ + group?: string; + /** + * For symlink entries, this is the symlink's target **(*NIX only)**. + */ + target?: string; + /** + * True if the sticky bit is set for this entry **(*NIX only)**. + */ + sticky?: boolean; + } + } + + + /** + * FTP client. + * + * Events: + * @event greeting(< string >msg) - Emitted after connection. msg is the text the server sent upon connection. + * @event ready() - Emitted when connection and authentication were sucessful. + * @event close(< boolean >hadErr) - Emitted when the connection has fully closed. + * @event end() - Emitted when the connection has ended. + * @event error(< Error >err) - Emitted when an error occurs. In case of protocol-level errors, err contains + * a 'code' property that references the related 3-digit FTP response code. + */ + class Client extends events.EventEmitter { + + /** + * Creates and returns a new FTP client instance. + */ + constructor(); + + /** + * Connects to an FTP server. + */ + connect(config?: Client.Options): void; + + /** + * Closes the connection to the server after any/all enqueued commands have been executed. + */ + end(): void; + + /** + * Closes the connection to the server immediately. + */ + destroy(): void; + + /** + * Retrieves the directory listing of path. + * @param path defaults to the current working directory. + * @param useCompression defaults to false. + */ + list(path: string, useCompression: boolean, callback: (error: Error, listing: Client.ListingElement[]) => void): void; + list(path: string, callback: (error: Error, listing: Client.ListingElement[]) => void): void; + list(useCompression: boolean, callback: (error: Error, listing: Client.ListingElement[]) => void): void; + list(callback: (error: Error, listing: Client.ListingElement[]) => void): void; + + /** + * Retrieves a file at path from the server. useCompression defaults to false + */ + get(path: string, callback: (error: Error, stream: NodeJS.ReadableStream) => void): void; + get(path: string, useCompression: boolean, callback: (error: Error, stream: NodeJS.ReadableStream) => void): void; + + /** + * Sends data to the server to be stored as destPath. + * @param input can be a ReadableStream, a Buffer, or a path to a local file. + * @param destPath + * @param useCompression defaults to false. + */ + put(input: NodeJS.ReadableStream|Buffer|string, destPath: string, useCompression: boolean, callback: (error: Error) => void): void; + put(input: NodeJS.ReadableStream|Buffer|string, destPath: string, callback: (error: Error) => void): void; + + /** + * Same as put(), except if destPath already exists, it will be appended to instead of overwritten. + * @param input can be a ReadableStream, a Buffer, or a path to a local file. + * @param destPath + * @param useCompression defaults to false. + */ + append(input: NodeJS.ReadableStream|Buffer|string, destPath: string, useCompression: boolean, callback: (error: Error) => void): void; + append(input: NodeJS.ReadableStream|Buffer|string, destPath: string, callback: (error: Error) => void): void; + + /** + * Renames oldPath to newPath on the server + */ + rename(oldPath: string, newPath: string, callback: (error: Error) => void): void; + + /** + * Logout the user from the server. + */ + logout(callback: (error: Error) => void): void; + + /** + * Delete a file on the server + */ + delete(path: string, callback: (error: Error) => void): void; + + /** + * Changes the current working directory to path. callback has 2 parameters: < Error >err, < string >currentDir. + * Note: currentDir is only given if the server replies with the path in the response text. + */ + cwd(path: string, callback: (error: Error, currentDir?: string) => void): void; + + /** + * Aborts the current data transfer (e.g. from get(), put(), or list()) + */ + abort(callback: (error: Error) => void): void; + + /** + * Sends command (e.g. 'CHMOD 755 foo', 'QUOTA') using SITE. callback has 3 parameters: + * < Error >err, < _string >responseText, < integer >responseCode. + */ + site(command: string, callback: (error: Error, responseText: string, responseCode: number) => void): void; + + /** + * Retrieves human-readable information about the server's status. + */ + status(callback: (error: Error, status: string) => void): void; + + /** + * Sets the transfer data type to ASCII. + */ + ascii(callback: (error: Error) => void): void; + + /** + * Sets the transfer data type to binary (default at time of connection). + */ + binary(callback: (error: Error) => void): void; + + /** + * Optional "standard" commands (RFC 959) + * Creates a new directory, path, on the server. recursive is for enabling a 'mkdir -p' algorithm and defaults to false + */ + mkdir(path: string, recursive: boolean, callback: (error: Error) => void): void; + mkdir(path: string, callback: (error: Error) => void): void; + + + /** + * Optional "standard" commands (RFC 959) + * Removes a directory, path, on the server. If recursive, this call will delete the contents of the directory if it is not empty + */ + rmdir(path: string, recursive: boolean, callback: (error: Error) => void): void; + rmdir(path: string, callback: (error: Error) => void): void; + + /** + * Optional "standard" commands (RFC 959) + * Changes the working directory to the parent of the current directory + */ + cdup(callback: (error: Error) => void): void; + + /** + * Optional "standard" commands (RFC 959) + * Retrieves the current working directory + */ + pwd(callback: (error: Error, path: string) => void): void; + + /** + * Optional "standard" commands (RFC 959) + * Retrieves the server's operating system. + */ + system(callback: (error: Error, OS: string) => void): void; + + /** + * Optional "standard" commands (RFC 959) + * Similar to list(), except the directory is temporarily changed to path to retrieve the directory listing. + * This is useful for servers that do not handle characters like spaces and quotes in directory names well for the LIST command. + * This function is "optional" because it relies on pwd() being available. + */ + listSafe(path: string, useCompression: boolean, callback: (error: Error, listing: Client.ListingElement[]) => void): void; + listSafe(path: string, callback: (error: Error, listing: Client.ListingElement[]) => void): void; + listSafe(useCompression: boolean, callback: (error: Error, listing: Client.ListingElement[]) => void): void; + listSafe(callback: (error: Error, listing: Client.ListingElement[]) => void): void; + + /** + * Extended commands (RFC 3659) + * Retrieves the size of path + */ + size(path: string, callback: (error: Error, size: number) => void): void; + + /** + * Extended commands (RFC 3659) + * Retrieves the last modified date and time for path + */ + lastMod(path: string, callback: (error: Error, lastMod: Date) => void): void; + + /** + * Extended commands (RFC 3659) + * Sets the file byte offset for the next file transfer action (get/put) to byteOffset + */ + restart(byteOffset: number, callback: (error: Error) => void): void; + + } + + export = Client; +} diff --git a/ftpd/ftpd-tests.ts b/ftpd/ftpd-tests.ts new file mode 100644 index 000000000..9d8485a9e --- /dev/null +++ b/ftpd/ftpd-tests.ts @@ -0,0 +1,32 @@ +/// + +import ftpd = require("ftpd"); + +var options: ftpd.FtpServerOptions = { + pasvPortRangeStart: 4000, + pasvPortRangeEnd: 5000, + getInitialCwd: function(connection: ftpd.FtpConnection, callback: (error: Error, path: string) => void): void { + callback(null, "boo"); + }, + getRoot: function(connection: ftpd.FtpConnection): string { + return '/'; + } +}; + +var host: string = '10.0.0.42'; + +var server = new ftpd.FtpServer(host, options); + +server.on('client:connected', function(conn: ftpd.FtpConnection): void { + conn.on('command:user', function(user: string, success: () => void, failure: () => void): void { + success(); + }); + conn.on('command:pass', function( + pass: string, + success: (username: string, fs?: ftpd.FtpFileSystem) => void, + failure: () => void) { + success("Rogier"); + }); +}); + +server.listen(21); diff --git a/ftpd/ftpd.d.ts b/ftpd/ftpd.d.ts new file mode 100644 index 000000000..ac0123256 --- /dev/null +++ b/ftpd/ftpd.d.ts @@ -0,0 +1,202 @@ +// Type definitions for ftpd 0.2.11 +// Project: https://github.com/sstur/nodeftpd +// Definitions by: Rogier Schouten +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +/// + +declare module "ftpd" { + + import events = require("events"); + import fs = require("fs"); + import net = require("net"); + import tls = require("tls"); + + /** + * Options for FtpServer constructor + */ + export interface FtpServerOptions { + /** + * Gets the initial working directory for the user. Called after user is authenticated + * Typical cases where you would want/need the callback involve retrieving configurations from external datasources and suchlike. + */ + getInitialCwd: (connection: FtpConnection, callback?: (error: Error, path: string) => void) => void|string; + /** + * Gets the root directory for the user relative to the CWD. Called after getInitialCwd. The user is not able to escape this directory. + * Typical cases where you would want/need the callback involve retrieving configurations from external datasources and suchlike. + */ + getRoot: (connection: FtpConnection, callback?: (error: Error, path: string) => void) => void|string; + /** + * 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. + */ + useWriteFile?: boolean; + /** + * If set to true, then files which the client uploads are slurped using 'readFile'. + * If false, files are read using readStream. + */ + useReadFile?: boolean; + /** + * 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. + */ + uploadMaxSlurpSize?: number; + /** + * The maximum number of concurrent calls to fs.stat which will be made when processing a LIST request. Default 5. + */ + maxStatsAtOnce?: number; + /** + * A function which can be used as the argument of an array's sort method. Used to sort filenames for directory listings. + * See [https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort] for more info. + */ + filenameSortFunc?: (a: string, b: string) => number; + /** + * A function which is applied to each filename before sorting. + * If set to false, filenames are unaltered. + */ + filenameSortMap?: ((a: string) => string) | boolean; + /** + * If this is set, then filenames are not sorted in responses to the LIST and NLST commands. + */ + dontSortFilenames?: boolean; + /** + * If set to true, then LIST and NLST treat the characters ? and * as literals instead of as wildcards. + */ + noWildcards?: boolean; + /** + * 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. + */ + tlsOptions?: tls.TlsOptions; + /** + * If this is set to true, and tlsOptions is also set, then the server will not allow logins over non-secure connections. + * Default false + */ + tlsOnly?: boolean; + /** + * I obviously set this to true when tlsOnly is on -someone needs to update this. + */ + allowUnauthorizedTls?: boolean; + /** + * Integer, specifies the lower-bound port (min port) for creating PASV connections + */ + pasvPortRangeStart?: number; + /** + * Integer, specifies the upper-bound port (max port) for creating PASV connections + */ + pasvPortRangeEnd?: number; + } + + /** + * Represents one Ftp connection. Incomplete type definition. + * + * @event command:user (username: string, success: () => void, failure: () => void) + * @event command:pass (password: string, success: (username: string, fs?: FtpFileSystem) => void, failure: () => void) + * 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. + */ + export class FtpConnection extends events.EventEmitter { + server: FtpServer; + socket: net.Socket; + pasv: net.Server; + dataSocket: net.Socket; // the actual data socket + mode: string; + username: string; + cwd: string; + root: string; + hasQuit: boolean; + // State for handling TLS upgrades. + secure: boolean; + pbszReceived: boolean; + } + + + /** + * Optional mock fs implementation to set in the command:pass event of FtpConnection + */ + export interface FtpFileSystem { + unlink: (path: string, callback?: (err?: NodeJS.ErrnoException) => void) => void; + readdir: (path: string, callback?: (err: NodeJS.ErrnoException, files: string[]) => void) => void; + mkdir: ((path: string, callback?: (err?: NodeJS.ErrnoException) => void) => void) + | ((path: string, mode: number, callback?: (err?: NodeJS.ErrnoException) => void) => void) + | ((path: string, mode: string, callback?: (err?: NodeJS.ErrnoException) => void) => void); + open: ((path: string, flags: string, callback?: (err: NodeJS.ErrnoException, fd: number) => any) => void) + | ((path: string, flags: string, mode: number, callback?: (err: NodeJS.ErrnoException, fd: number) => any) => void) + | ((path: string, flags: string, mode: string, callback?: (err: NodeJS.ErrnoException, fd: number) => any) => void); + close: (fd: number, callback?: (err?: NodeJS.ErrnoException) => void) => void; + rmdir: (path: string, callback?: (err?: NodeJS.ErrnoException) => void) => void; + rename: (oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void) => void; + /** + * specific object properties: { mode, isDirectory(), size, mtime } + */ + stat: (path: string, callback?: (err: NodeJS.ErrnoException, stats: fs.Stats) => any) => void; + /** + * if useReadFile option is not set or is false + */ + createReadStream?: (path: string, options?: { + flags?: string; + encoding?: string; + fd?: string; + mode?: string; + bufferSize?: number; + }) => fs.ReadStream; + /** + * if useWriteFile option is not set or is false + */ + createWriteStream?: (path: string, options?: { + flags?: string; + encoding?: string; + string?: string; + }) => fs.WriteStream; + /** + * if useReadFile option is set to 'true' + */ + readFile?: + ((filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void) => void) + | ((filename: string, options: { encoding: string; flag?: string; }, callback: (err: NodeJS.ErrnoException, data: string) => void) => void) + | ((filename: string, options: { flag?: string; }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void) => void) + | ((filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void ) => void); + /** + * if useWriteFile option is set to 'true' + */ + writeFile?: + ((filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void) => void) + | ((filename: string, data: any, options: { encoding?: string; mode?: number; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void) => void) + | ((filename: string, data: any, options: { encoding?: string; mode?: string; flag?: string; }, callback?: (err: NodeJS.ErrnoException) => void) => void); + + } + + /** + * FTP server + * + * Events: + * @event close net.Server close event + * @event error net.Server error event + * @event client:connected (connection: FtpConnection) + */ + export class FtpServer extends events.EventEmitter { + + /** + * @param host 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). + * @param options See test.js for a simple example. + */ + constructor(host: string, options: FtpServerOptions); + + /** + * Start listening, see net.Server.listen() + */ + public listen(port: number, host?: string, backlog?: number, listeningListener?: () => void): void; + + /** + * Stop listening + */ + public close(callback?: () => void): void; + } + + + +}