Add sftpCommand config option to allow different ways of launching sftp-server

pull/64/head
Kelvin Schoofs 6 years ago
parent 0e62c9731f
commit 288f4ad845

@ -1,6 +1,7 @@
import { readFile } from 'fs';
import { Socket } from 'net';
import { Client, ConnectConfig } from 'ssh2';
import { Client, ConnectConfig, SFTPWrapper as SFTPWrapperReal } from 'ssh2';
import { SFTPStream } from 'ssh2-streams';
import * as vscode from 'vscode';
import { loadConfigs, openConfigurationEditor } from './config';
import { FileSystemConfig } from './manager';
@ -8,6 +9,10 @@ import * as proxy from './proxy';
import { getSession as getPuttySession } from './putty';
import { toPromise } from './toPromise';
// tslint:disable-next-line:variable-name
const SFTPWrapper = require('ssh2/lib/SFTPWrapper') as (new (stream: SFTPStream) => SFTPWrapperReal);
type SFTPWrapper = SFTPWrapperReal;
function replaceVariables(string?: string) {
if (typeof string !== 'string') return string;
return string.replace(/\$\w+/g, key => process.env[key.substr(1)] || '');
@ -171,3 +176,33 @@ export async function createSSH(config: FileSystemConfig, sock?: NodeJS.Readable
}
});
}
export function getSFTP(client: Client, config: FileSystemConfig): Promise<SFTPWrapper> {
return new Promise((resolve, reject) => {
if (!config.sftpCommand) {
return client.sftp((err, sftp) => {
if (err) {
client.end();
reject(err);
}
resolve(sftp);
});
}
client.exec(config.sftpCommand, (err, channel) => {
if (err) {
client.end();
return reject(err);
}
channel.once('close', () => (client.end(), reject()));
channel.once('error', () => (client.end(), reject()));
try {
const sftps = new SFTPStream();
channel.pipe(sftps).pipe(channel);
const sftp = new SFTPWrapper(sftps);
resolve(sftp);
} catch (e) {
reject(e);
}
});
});
}

@ -3,9 +3,10 @@ import { readFile } from 'fs';
import { parse as parseJsonc, ParseError } from 'jsonc-parser';
import * as path from 'path';
import { Client, ClientChannel, ConnectConfig } from 'ssh2';
import { SFTPStream } from 'ssh2-streams';
import * as vscode from 'vscode';
import { getConfig, loadConfigs, openConfigurationEditor, updateConfig } from './config';
import { createSocket, createSSH } from './connect';
import { createSocket, createSSH, getSFTP } from './connect';
import SSHFileSystem, { EMPTY_FILE_SYSTEM } from './sshFileSystem';
import { MemoryDuplex } from './streams';
import { catchingPromise, toPromise } from './toPromise';
@ -31,6 +32,7 @@ export interface FileSystemConfig extends ConnectConfig {
proxy?: ProxyConfig;
privateKeyPath?: string;
hop?: string;
sftpCommand?: string;
}
export enum ConfigStatus {
@ -194,12 +196,7 @@ export class Manager implements vscode.FileSystemProvider, vscode.TreeDataProvid
}
root = root.replace(/^~/, home.replace(/\/$/, ''));
}
client.sftp(async (err, sftp) => {
if (err) {
client.end();
return reject(err);
}
sftp.once('end', () => client.end());
const sftp = await getSFTP(client, config);
const fs = new SSHFileSystem(name, sftp, root, config!);
try {
const rootUri = vscode.Uri.parse(`ssh://${name}/`);
@ -222,7 +219,6 @@ export class Manager implements vscode.FileSystemProvider, vscode.TreeDataProvid
this.onDidChangeTreeDataEmitter.fire();
client.once('close', hadError => hadError ? this.commandReconnect(name) : (!fs.closing && this.promptReconnect(name)));
return resolve(fs);
});
}).catch((e) => {
this.onDidChangeTreeDataEmitter.fire();
if (!e) {

Loading…
Cancel
Save