diff --git a/ssh2/ssh2-tests.ts b/ssh2/ssh2-tests.ts
new file mode 100644
index 000000000..1c59b1305
--- /dev/null
+++ b/ssh2/ssh2-tests.ts
@@ -0,0 +1,428 @@
+///
+
+import * as ssh2 from 'ssh2';
+
+declare var inspect: any;
+
+//
+// # Client Examples
+//
+
+// Authenticate using keys and execute uptime on a server:
+
+var Client = require('ssh2').Client;
+
+var conn = new Client();
+conn.on('ready', () => {
+ console.log('Client :: ready');
+ conn.exec('uptime', (err: Error, stream: ssh2.Channel) => {
+ if (err) throw err;
+ stream
+ .on('close', (code: any, signal: any) => {
+ console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
+ conn.end();
+ }).on('data', (data: any) => {
+ console.log('STDOUT: ' + data);
+ }).stderr.on('data', (data: any) => {
+ console.log('STDERR: ' + data);
+ });
+ });
+}).connect({
+ host: '192.168.100.100',
+ port: 22,
+ username: 'frylock',
+ privateKey: require('fs').readFileSync('/here/is/my/key')
+});
+
+// Authenticate using keys and start an interactive shell session:
+
+var Client = require('ssh2').Client;
+
+var conn = new Client();
+conn.on('ready', () => {
+ console.log('Client :: ready');
+ conn.shell( (err: Error, stream: ssh2.Channel) => {
+ if (err) throw err;
+ stream.on('close', () => {
+ console.log('Stream :: close');
+ conn.end();
+ }).on('data', (data: any) => {
+ console.log('STDOUT: ' + data);
+ }).stderr.on('data', (data: any) => {
+ console.log('STDERR: ' + data);
+ });
+ stream.end('ls -l\nexit\n');
+ });
+}).connect({
+ host: '192.168.100.100',
+ port: 22,
+ username: 'frylock',
+ privateKey: require('fs').readFileSync('/here/is/my/key')
+});
+
+// Authenticate using password and send an HTTP request to port 80 on the server:
+
+var Client = require('ssh2').Client;
+
+var conn = new Client();
+conn.on('ready', () => {
+ console.log('Client :: ready');
+ conn.forwardOut('192.168.100.102', 8000, '127.0.0.1', 80, (err: Error, stream: ssh2.Channel) => {
+ if (err) throw err;
+ stream.on('close', () => {
+ console.log('TCP :: CLOSED');
+ conn.end();
+ }).on('data', (data: any) => {
+ console.log('TCP :: DATA: ' + data);
+ }).end([
+ 'HEAD / HTTP/1.1',
+ 'User-Agent: curl/7.27.0',
+ 'Host: 127.0.0.1',
+ 'Accept: */*',
+ 'Connection: close',
+ '',
+ ''
+ ].join('\r\n'));
+ });
+}).connect({
+ host: '192.168.100.100',
+ port: 22,
+ username: 'frylock',
+ password: 'nodejsrules'
+});
+
+// Authenticate using password and forward remote connections on port 8000 to us:
+
+var Client = require('ssh2').Client;
+
+var conn = new Client();
+conn.on('ready', () => {
+ console.log('Client :: ready');
+ conn.forwardIn('127.0.0.1', 8000, (err: Error) => {
+ if (err) throw err;
+ console.log('Listening for connections on server on port 8000!');
+ });
+}).on('tcp connection', (info: any, accept: Function, reject: Function) => {
+ console.log('TCP :: INCOMING CONNECTION:');
+ console.dir(info);
+ accept().on('close', () => {
+ console.log('TCP :: CLOSED');
+ }).on('data', (data: any) => {
+ console.log('TCP :: DATA: ' + data);
+ }).end([
+ 'HTTP/1.1 404 Not Found',
+ 'Date: Thu, 15 Nov 2012 02:07:58 GMT',
+ 'Server: ForwardedConnection',
+ 'Content-Length: 0',
+ 'Connection: close',
+ '',
+ ''
+ ].join('\r\n'));
+}).connect({
+ host: '192.168.100.100',
+ port: 22,
+ username: 'frylock',
+ password: 'nodejsrules'
+});
+
+// Authenticate using password and get a directory listing via SFTP:
+
+var Client = require('ssh2').Client;
+
+var conn = new Client();
+conn.on('ready', () => {
+ console.log('Client :: ready');
+ conn.sftp( (err: Error, sftp: any) => {
+ if (err) throw err;
+ sftp.readdir('foo', (err: Error, list: any) => {
+ if (err) throw err;
+ console.dir(list);
+ conn.end();
+ });
+ });
+}).connect({
+ host: '192.168.100.100',
+ port: 22,
+ username: 'frylock',
+ password: 'nodejsrules'
+});
+
+// Connection hopping:
+
+var Client = require('ssh2').Client;
+
+var conn1 = new Client(),
+ conn2 = new Client();
+
+conn1.on('ready', () => {
+ console.log('FIRST :: connection ready');
+ conn1.exec('nc 192.168.1.2 22', (err: Error, stream: ssh2.Channel) => {
+ if (err) {
+ console.log('FIRST :: exec error: ' + err);
+ return conn1.end();
+ }
+ conn2.connect({
+ sock: stream,
+ username: 'user2',
+ password: 'password2',
+ });
+ });
+}).connect({
+ host: '192.168.1.1',
+ username: 'user1',
+ password: 'password1',
+});
+
+conn2.on('ready', () => {
+ console.log('SECOND :: connection ready');
+ conn2.exec('uptime', (err: Error, stream: ssh2.Channel) => {
+ if (err) {
+ console.log('SECOND :: exec error: ' + err);
+ return conn1.end();
+ }
+ stream.on('end', () => {
+ conn1.end(); // close parent (and this) connection
+ }).on('data', (data: any) => {
+ console.log(data.toString());
+ });
+ });
+});
+
+// Forward X11 connections (xeyes):
+
+var net = require('net'),
+ Client = require('ssh2').Client;
+
+var conn = new Client();
+
+conn.on('x11', (info: any, accept: any, reject: any) => {
+ var xserversock = new net.Socket();
+ xserversock.on('connect', () => {
+ var xclientsock = accept();
+ xclientsock.pipe(xserversock).pipe(xclientsock);
+ });
+ // connects to localhost:0.0
+ xserversock.connect(6000, 'localhost');
+});
+
+conn.on('ready', () => {
+ conn.exec('xeyes', { x11: true }, (err: Error, stream: ssh2.Channel) => {
+ if (err) throw err;
+ var code = 0;
+ stream.on('end', () => {
+ if (code !== 0)
+ console.log('Do you have X11 forwarding enabled on your SSH server?');
+ conn.end();
+ }).on('exit', (exitcode: number) => {
+ code = exitcode;
+ });
+ });
+}).connect({
+ host: '192.168.1.1',
+ username: 'foo',
+ password: 'bar'
+});
+
+// Dynamic (1:1) port forwarding using a SOCKSv5 proxy (using socksv5):
+
+var socks = require('socksv5'),
+ Client = require('ssh2').Client;
+
+var ssh_config = {
+ host: '192.168.100.1',
+ port: 22,
+ username: 'nodejs',
+ password: 'rules'
+};
+
+socks.createServer( (info: any, accept: any, deny: any) => {
+ // NOTE: you could just use one ssh2 client connection for all forwards, but
+ // you could run into server-imposed limits if you have too many forwards open
+ // at any given time
+ var conn = new Client();
+ conn.on('ready', () => {
+ conn.forwardOut(info.srcAddr,
+ info.srcPort,
+ info.dstAddr,
+ info.dstPort,
+ (err: Error, stream: ssh2.Channel) => {
+ if (err) {
+ conn.end();
+ return deny();
+ }
+
+ var clientSocket: any;
+ if (clientSocket = accept(true)) {
+ stream.pipe(clientSocket).pipe(stream).on('close', () => {
+ conn.end();
+ });
+ } else
+ conn.end();
+ });
+ }).on('error', (err: Error) => {
+ deny();
+ }).connect(ssh_config);
+}).listen(1080, 'localhost', () => {
+ console.log('SOCKSv5 proxy server started on port 1080');
+}).useAuth(socks.auth.None());
+
+// Invoke an arbitrary subsystem (netconf in this example):
+
+var Client = require('ssh2').Client,
+ xmlhello = ''+
+ ''+
+ ' '+
+ ' urn:ietf:params:netconf:base:1.0'+
+ ' '+
+ ']]>]]>';
+
+var conn = new Client();
+
+conn.on('ready', () => {
+ console.log('Client :: ready');
+ conn.subsys('netconf', (err: Error, stream: ssh2.Channel) => {
+ if (err) throw err;
+ stream.on('data', (data: any) => {
+ console.log(data);
+ }).write(xmlhello);
+ });
+}).connect({
+ host: '1.2.3.4',
+ port: 22,
+ username: 'blargh',
+ password: 'honk'
+});
+
+//
+// # Server Examples
+//
+
+// Only allow password and public key authentication and command execution:
+
+var fs = require('fs'),
+ crypto = require('crypto');
+var buffersEqual = require('buffer-equal-constant-time'),
+ //ssh2 = require('ssh2'),
+ utils = ssh2.utils;
+
+var pubKey = utils.genPublicKey(utils.parseKey(fs.readFileSync('user.pub')));
+
+new ssh2.Server({
+ privateKey: fs.readFileSync('host.key')
+}, (client: any) => {
+ console.log('Client connected!');
+
+ client.on('authentication', (ctx: any) => {
+ if (ctx.method === 'password'
+ && ctx.username === 'foo'
+ && ctx.password === 'bar')
+ ctx.accept();
+ else if (ctx.method === 'publickey'
+ && ctx.key.algo === pubKey.fulltype
+ && buffersEqual(ctx.key.data, pubKey.public)) {
+ if (ctx.signature) {
+ var verifier = crypto.createVerify(ctx.sigAlgo);
+ verifier.update(ctx.blob);
+ if (verifier.verify(pubKey.publicOrig, ctx.signature, 'binary'))
+ ctx.accept();
+ else
+ ctx.reject();
+ } else {
+ // if no signature present, that means the client is just checking
+ // the validity of the given public key
+ ctx.accept();
+ }
+ } else
+ ctx.reject();
+ }).on('ready', () => {
+ console.log('Client authenticated!');
+
+ client.on('session', (accept: any, reject: any) => {
+ var session = accept();
+ session.once('exec', (accept: any, reject: any, info: any) => {
+ console.log('Client wants to execute: ' + inspect(info.command));
+ var stream = accept();
+ stream.stderr.write('Oh no, the dreaded errors!\n');
+ stream.write('Just kidding about the errors!\n');
+ stream.exit(0);
+ stream.end();
+ });
+ });
+ }).on('end', () => {
+ console.log('Client disconnected');
+ });
+}).listen(0, '127.0.0.1', () => {
+ console.log('Listening on port ' + this.address().port);
+ });
+
+// SFTP only server:
+
+var fs = require('fs');
+//var ssh2 = require('ssh2');
+var OPEN_MODE = ssh2.SFTP_OPEN_MODE,
+ STATUS_CODE = ssh2.SFTP_STATUS_CODE;
+
+new ssh2.Server({
+ privateKey: fs.readFileSync('host.key')
+}, (client: any) => {
+ console.log('Client connected!');
+
+ client.on('authentication', (ctx: any) => {
+ if (ctx.method === 'password'
+ && ctx.username === 'foo'
+ && ctx.password === 'bar')
+ ctx.accept();
+ else
+ ctx.reject();
+ }).on('ready', () => {
+ console.log('Client authenticated!');
+
+ client.on('session', (accept: any, reject: any) => {
+ var session = accept();
+ session.on('sftp', (accept: any, reject: any) => {
+ console.log('Client SFTP session');
+ var openFiles: any = {};
+ var handleCount = 0;
+ // `sftpStream` is an `SFTPStream` instance in server mode
+ // see: https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md
+ var sftpStream = accept();
+ sftpStream.on('OPEN', (reqid: any, filename: any, flags: any, attrs: any) => {
+ // only allow opening /tmp/foo.txt for writing
+ if (filename !== '/tmp/foo.txt' || !(flags & OPEN_MODE.WRITE))
+ return sftpStream.status(reqid, STATUS_CODE.FAILURE);
+ // create a fake handle to return to the client, this could easily
+ // be a real file descriptor number for example if actually opening
+ // the file on the disk
+ var handle = new Buffer(4);
+ openFiles[handleCount] = true;
+ handle.writeUInt32BE(handleCount++, 0, true);
+ sftpStream.handle(reqid, handle);
+ console.log('Opening file for write')
+ }).on('WRITE', (reqid: any, handle: any, offset: any, data: any) => {
+ if (handle.length !== 4 || !openFiles[handle.readUInt32BE(0, true)])
+ return sftpStream.status(reqid, STATUS_CODE.FAILURE);
+ // fake the write
+ sftpStream.status(reqid, STATUS_CODE.OK);
+ var inspected = require('util').inspect(data);
+ console.log('Write to file at offset %d: %s', offset, inspected);
+ }).on('CLOSE', (reqid: any, handle: any) => {
+ var fnum: any;
+ if (handle.length !== 4 || !openFiles[(fnum = handle.readUInt32BE(0, true))])
+ return sftpStream.status(reqid, STATUS_CODE.FAILURE);
+ delete openFiles[fnum];
+ sftpStream.status(reqid, STATUS_CODE.OK);
+ console.log('Closing file');
+ });
+ });
+ });
+ }).on('end', () => {
+ console.log('Client disconnected');
+ });
+}).listen(0, '127.0.0.1', () => {
+ console.log('Listening on port ' + this.address().port);
+ });
+
+
+
+
+
diff --git a/ssh2/ssh2.d.ts b/ssh2/ssh2.d.ts
new file mode 100644
index 000000000..870104617
--- /dev/null
+++ b/ssh2/ssh2.d.ts
@@ -0,0 +1,346 @@
+// Type definitions for ssh2
+// Project: https://github.com/mscdex/ssh2
+// Definitions by: Qubo
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+///
+
+declare module "ssh2" {
+ import stream = require('stream');
+
+ namespace ssh2 {
+ interface Client {
+ Server: ServerStatic;
+ new(): Client;
+ /**
+ * SFTPStream.STATUS_CODE from ssh2-streams.
+ */
+ SFTP_STATUS_CODE: Sftp.StatusCode;
+ /**
+ * SFTPStream.OPEN_MODE from ssh2-streams.
+ */
+ SFTP_OPEN_MODE: Sftp.OpenMode;
+ //TODO: Type ssh2-streams
+ /**
+ * utility methods from ssh2-streams.
+ */
+ utils: Utils;
+
+ connect(config: ConnectConfig): void;
+ end(): void;
+ destroy(): void;
+ exec(command: string, options: ExecOption, callback: ChannelCallback): boolean;
+ exec(command: string, callback: ChannelCallback): boolean;
+ shell(window: boolean|PseudoTtySettings, options: boolean|number|X11Settings, callback: ChannelCallback): boolean;
+ shell(window: boolean|PseudoTtySettings, callback: ChannelCallback): boolean;
+ shell(callback: ChannelCallback): boolean;
+ subsys(subsystem: string, callback: ChannelCallback): boolean;
+ sftp(callback: SftpCallback): boolean;
+ forwardIn(bindAddr: string, bindPort: number, callback?: ForwardInCallback): boolean;
+ unforwardIn(bindAddr: string, bindPort: number, callback?: ErrorCallback): boolean;
+ forwardOut(srcIP: string, srcPort: number, dstIP: string, dstPort: number, callback: ChannelCallback): boolean;
+ openssh_noMoreSessions(callback?: ErrorCallback): boolean;
+ openssh_forwardInStreamLocal(socketPath: string, callback?: ErrorCallback): boolean;
+ openssh_unforwardInStreamLocal(socketPath: string, callback?: ErrorCallback): boolean;
+ openssh_forwardOutStreamLocal(socketPath: string, callback?: ChannelCallback): boolean;
+ }
+
+ interface ConnectConfig {
+ /**
+ * @description Hostname or IP address of the server.
+ * @default 'localhost'
+ */
+ host?: string;
+ /**
+ * @description Port number of the server.
+ * @default 22
+ */
+ port?: number;
+ /**
+ * @description Only connect via resolved IPv4 address for `host`.
+ * @default false
+ */
+ forceIPv4?: boolean;
+ /**
+ * @description Only connect via resolved IPv6 address for `host`.
+ * @default false
+ */
+ forceIPv6?: boolean;
+ /**
+ * @description 'md5' or 'sha1'. The host's key is hashed using this method and passed to the **hostVerifier** function.
+ * @default (none)
+ */
+ hostHash?: string;
+ /**
+ * @description Function that is passed a string hex hash of the host's key for verification purposes.
+ * Return `true` to continue with the handshake or `false` to reject and disconnect.
+ */
+ hostVerifier?: (keyHash: string) => boolean;
+ /**
+ * @description Username for authentication.
+ */
+ username?: string;
+ /**
+ * @description Password for password-based user authentication.
+ */
+ password?: string;
+ /**
+ * @description Path to ssh-agent's UNIX socket for ssh-agent-based user authentication.
+ * Windows users: set to 'pageant' for authenticating with Pageant or (actual) path to a cygwin "UNIX socket."
+ */
+ agent?: string;
+ /**
+ * @description Buffer or string that contains a private key for either key-based or hostbased user authentication (OpenSSH format).
+ */
+ privateKey?: Buffer|string;
+ /**
+ * @description For an encrypted private key, this is the passphrase used to decrypt it.
+ */
+ passphrase?: string;
+ /**
+ * @description Along with **localUsername** and **privateKey**, set this to a non-empty string for hostbased user authentication.
+ */
+ localHostname?: string;
+ /**
+ * @description Along with **localHostname** and **privateKey**, set this to a non-empty string for hostbased user authentication.
+ */
+ localUsername?: string;
+ /**
+ * @description Try keyboard-interactive user authentication if primary user authentication method fails.
+ * If you set this to `true`, you need to handle the `keyboard-interactive` event.
+ */
+ tryKeyboard: boolean;
+ /**
+ * @description How often (in milliseconds) to send SSH-level keepalive packets to the server
+ * (in a similar way as OpenSSH's ServerAliveInterval config option). Set to 0 to disable.
+ * @default 0
+ */
+ keepaliveInterval?: number;
+ /**
+ * @description How many consecutive, unanswered SSH-level keepalive packets that can be sent to the server
+ * before disconnection (similar to OpenSSH's ServerAliveCountMax config option).
+ * @default 3
+ */
+ keepaliveCountMax?: number;
+ /**
+ * @description How long (in milliseconds) to wait for the SSH handshake to complete.
+ * @default 20000
+ */
+ readyTimeout?: number;
+ /**
+ * @description Performs a strict server vendor check before sending vendor-specific requests,
+ * etc. (e.g. check for OpenSSH server when using `openssh_noMoreSessions()`)
+ * @default true
+ */
+ strictVendor?: boolean;
+ /**
+ * A ReadableStream to use for communicating with the server instead of creating and using a new TCP connection (useful for connection hopping).
+ */
+ sock?: NodeJS.ReadableStream;
+ /**
+ * @description Set to `true` to use OpenSSH agent forwarding (`auth-agent@openssh.com`) for the life of the connection. `agent` must also be set to use this feature.
+ * @default false
+ */
+ agentForward?: boolean;
+ /**
+ * @description Set this to a function that receives a single string argument to get detailed (local) debug information.
+ */
+ debug: (information: string) => any;
+ }
+
+ interface ExecOption {
+ /**
+ * @description An environment to use for the execution of the command.
+ */
+ env?: any;
+ /**
+ * @description Set to true to allocate a pseudo-tty with defaults, or an object containing specific pseudo-tty settings
+ * (see 'Pseudo-TTY settings'). Setting up a pseudo-tty can be useful when working with remote processes
+ * that expect input from an actual terminal (e.g. sudo's password prompt).
+ */
+ pty?: boolean|PseudoTtySettings;
+ /**
+ * @description Set to true to use defaults below, set to a number to specify a specific screen number,
+ * or an object.
+ */
+ x11?: boolean|number|X11Settings;
+ }
+
+ interface X11Settings {
+ /**
+ * Allow just a single connection?
+ * @default false
+ */
+ single?: boolean;
+ /**
+ * Screen number to use
+ * @default 0
+ */
+ screen?: number;
+ }
+
+ interface PseudoTtySettings {
+ /**
+ * @description * Number of rows
+ * @default 24
+ */
+ rows?: number;
+ /**
+ * @description * Number of columns
+ * @default 80
+ */
+ cols?: number;
+ /**
+ * @description * Height in pixels
+ * @default 480
+ */
+ height?: number;
+ /**
+ * @description * Width in pixels
+ * @default 640
+ */
+ width?: number;
+ /**
+ * @description The value to use for $TERM
+ * @default 'vt100'
+ */
+ term?: string;
+ }
+
+ interface ForwardInCallback {
+ (err?: Error, bindPort?: number): void;
+ }
+
+ interface ChannelCallback {
+ (err?: Error, channel?: Channel): void;
+ }
+
+ interface SftpCallback {
+ (err?: Error, sftp?: Sftp.Wrapper): void;
+ }
+
+ interface ErrorCallback {
+ (err?: Error): void;
+ }
+
+ interface Channel extends stream.Duplex {
+ new(info?: any, client?: any, options?: any): Channel;
+ eof(): boolean;
+ close(): boolean;
+ destroy(): void;
+ setWindow(rows: number, cols: number, height: number, width: number): boolean;
+ signal(signalName: string): boolean;
+ exit(name: string, coreDumped: boolean, msg: string): boolean;
+ exit(status: number): boolean;
+ stderr?: ServerStderr;
+
+ // EventEmitter overrides
+ addListener(event: string, listener: Function): Channel;
+ on(event: string, listener: Function): Channel;
+ once(event: string, listener: Function): Channel;
+ removeListener(event: string, listener: Function): Channel;
+ removeAllListeners(event?: string): Channel;
+ }
+
+ interface ServerStderr extends NodeJS.WritableStream {
+ new(channel: Channel): ServerStderr;
+ }
+
+ interface ServerStatic {
+ new(config: ServerConfig, listener?: any): Server;
+ createServer(config: ServerConfig, listener?: any): Server;
+ KEEPALIVE_INTERVAL: number;
+ KEEPALIVE_CLIENT_INTERVAL: number;
+ KEEPALIVE_CLIENT_COUNT_MAX: number;
+ }
+
+ interface Server extends NodeJS.EventEmitter {
+ listen(port: number, hostname?: string, backlog?: number, callback?: Function): Server;
+ listen(port: number, hostname?: string, callback?: Function): Server;
+ listen(path: string, callback?: Function): Server;
+ listen(handle: any, listeningListener?: Function): Server;
+ address(): { port: number; family: string; address: string; };
+ getConnections(callback: any): any; //TODO: No type
+ close(callback?: Function): Server;
+ ref(): void;
+ unref(): void;
+ }
+
+ interface ServerConfig {
+ /**
+ * @description Buffer or string that contains the host private key (OpenSSH format).
+ */
+ privateKey: Buffer|string;
+ /**
+ * @description For an encrypted host private key, this is the passphrase used to decrypt it.
+ */
+ passphrase?: string;
+ /**
+ * @description A message that is sent to clients immediately upon connection, before handshaking begins.
+ */
+ banner?: string;
+ /**
+ * @description A custom server software name/version identifier.
+ * @default 'ssh2js' + moduleVersion + 'srv'
+ */
+ indent?: string;
+ /**
+ * @description This is the highWaterMark to use for the parser stream.
+ * @default 32 * 1024
+ */
+ highWaterMark?: number;
+ /**
+ * @description Set this to a function that receives a single string argument to get detailed (local) debug information.
+ */
+ debug?: (information: string) => any;
+ }
+
+ // utility methods from ssh2-streams.
+ interface Utils {
+ iv_inc: Function;
+ isStreamCipher: Function;
+ isGCM: Function;
+ readInt: Function;
+ readString: Function;
+ parseKey: Function;
+ genPublicKey: Function;
+ convertPPKPrivate: Function;
+ verifyPPKMAC: Function;
+ decryptKey: Function;
+ }
+
+ namespace Sftp {
+ // SFTPStream.STATUS_CODE from ssh2-streams.
+ interface StatusCode {
+ OK: number;
+ EOF: number;
+ NO_SUCH_FILE: number;
+ PERMISSION_DENIED: number;
+ FAILURE: number;
+ BAD_MESSAGE: number;
+ NO_CONNECTION: number;
+ CONNECTION_LOST: number;
+ OP_UNSUPPORTED: number;
+ }
+
+ // SFTPStream.OPEN_MODE from ssh2-streams.
+ interface OpenMode {
+ READ: number;
+ WRITE: number;
+ APPEND: number;
+ CREAT: number;
+ TRUNC: number;
+ EXCL: number;
+ }
+
+ interface Wrapper extends NodeJS.EventEmitter {
+ //TODO: extends `ssh2-streams.SFTPStream`
+ }
+ }
+ }
+
+ var ssh2: ssh2.Client;
+
+ export = ssh2;
+}
+