mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 10:16:03 +02:00
Bug 345329 - Add SSH proxy
Allows to connect over any ssh server as gateway or over any other proxy by executing a local or remote command (such as netcat, corkscrew, ...). Change-Id: I413c22cb588d8560d8db9ac877fb04f8331456aa
This commit is contained in:
parent
5ee4fa818a
commit
c563ea3f0e
10 changed files with 893 additions and 15 deletions
|
@ -0,0 +1,367 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.jsch.core;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.StringCharacterIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utilitiy class for managing command line arguments.
|
||||
*
|
||||
*/
|
||||
public class ArgumentParser {
|
||||
private static List<String> parseCommandline(String commandline) {
|
||||
ArrayList<String> result = new ArrayList<String>();
|
||||
StringCharacterIterator iterator = new StringCharacterIterator(commandline);
|
||||
|
||||
for (iterator.first(); iterator.current() != CharacterIterator.DONE; iterator.next()) {
|
||||
|
||||
// Restart to skip white space
|
||||
if (Character.isWhitespace(iterator.current())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Read token
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
token_reader: for (; iterator.current() != CharacterIterator.DONE; iterator.next()) {
|
||||
char tokenChar = iterator.current();
|
||||
|
||||
// A white space terminates the token
|
||||
if (Character.isWhitespace(tokenChar)) {
|
||||
break token_reader;
|
||||
}
|
||||
|
||||
// Handle character that composes the token
|
||||
switch (tokenChar) {
|
||||
case '"': {
|
||||
/*
|
||||
* Read all text within double quotes or until end of
|
||||
* string. Allows escaping.
|
||||
*/
|
||||
iterator.next(); // Skip quote
|
||||
quoted_reader: while ((iterator.current() != CharacterIterator.DONE) && (iterator.current() != '"')) {
|
||||
char innerChar = iterator.current();
|
||||
switch (innerChar) {
|
||||
case '\\':
|
||||
char nextChar = iterator.next();
|
||||
switch (nextChar) {
|
||||
case CharacterIterator.DONE:
|
||||
break quoted_reader;
|
||||
case '"':
|
||||
// Add the character, but remove the escape
|
||||
buffer.append(nextChar);
|
||||
iterator.next();
|
||||
continue quoted_reader;
|
||||
default:
|
||||
// Add the character and keep escape
|
||||
buffer.append(innerChar);
|
||||
buffer.append(nextChar);
|
||||
iterator.next();
|
||||
continue quoted_reader;
|
||||
}
|
||||
default:
|
||||
buffer.append(innerChar);
|
||||
iterator.next();
|
||||
continue quoted_reader;
|
||||
}
|
||||
}
|
||||
continue token_reader;
|
||||
}
|
||||
case '\'': {
|
||||
/*
|
||||
* Read all text within single quotes or until end of
|
||||
* string. No escaping.
|
||||
*/
|
||||
iterator.next(); // Skip the quote
|
||||
while ((iterator.current() != CharacterIterator.DONE) && (iterator.current() != '\'')) {
|
||||
buffer.append(iterator.current());
|
||||
iterator.next();
|
||||
}
|
||||
continue token_reader;
|
||||
}
|
||||
case '\\': {
|
||||
/*
|
||||
* Read escaped char.
|
||||
*/
|
||||
char nextChar = iterator.next();
|
||||
switch (nextChar) {
|
||||
case CharacterIterator.DONE:
|
||||
break token_reader;
|
||||
case '\n':
|
||||
// Ignore newline. Both lines are concatenated.
|
||||
continue token_reader;
|
||||
default:
|
||||
// Add the character, but remove the escape
|
||||
buffer.append(nextChar);
|
||||
continue token_reader;
|
||||
}
|
||||
}
|
||||
default:
|
||||
/*
|
||||
* Any other char, add to the buffer.
|
||||
*/
|
||||
buffer.append(tokenChar);
|
||||
continue token_reader;
|
||||
}
|
||||
}
|
||||
result.add(buffer.toString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private final List<String> tokens;
|
||||
|
||||
/**
|
||||
* Create a command line representation from an array of strings. The first
|
||||
* element of the list is assumed to be the command, the remaining, the
|
||||
* arguments. The elements are not parsed not (un)escaped., but taked as the
|
||||
* are.
|
||||
*
|
||||
*/
|
||||
public ArgumentParser(List<String> tokenList) {
|
||||
this.tokens = new ArrayList<String>(tokenList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a command line representation from the string with a shell command
|
||||
* line. The command line is parsed and split on spaces. Quoted or escaped
|
||||
* spaces are preserved..
|
||||
*
|
||||
*/
|
||||
public ArgumentParser(String commandline) {
|
||||
this.tokens = parseCommandline(commandline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a command line representation from an array of strings. The first
|
||||
* element of the array is assumed to be the command, the remaining, the
|
||||
* arguments. The elements are not parsed not (un)escaped., but taked as the
|
||||
* are.
|
||||
*
|
||||
*/
|
||||
public ArgumentParser(String tokenArray[]) {
|
||||
this(Arrays.asList(tokenArray));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a command line representation from the command and an list of
|
||||
* parameters. The elements are not parsed not (un)escaped., but taked as
|
||||
* the are.
|
||||
*
|
||||
*/
|
||||
public ArgumentParser(String command, List<String> parameterList) {
|
||||
this.tokens = new ArrayList<String>();
|
||||
this.tokens.add(command);
|
||||
this.tokens.addAll(parameterList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a command line representation from the command and an array of
|
||||
* parameters. The elements are not parsed not (un)escaped., but taked as
|
||||
* the are.
|
||||
*
|
||||
*/
|
||||
public ArgumentParser(String command, String parameterArray[]) {
|
||||
this(command, Arrays.asList(parameterArray));
|
||||
}
|
||||
|
||||
private StringBuffer escapeToken(String token, boolean fullEscape) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringCharacterIterator iter = new StringCharacterIterator(token);
|
||||
for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) {
|
||||
if (Character.isWhitespace(c)) {
|
||||
buffer.append('\\');
|
||||
buffer.append(c);
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case '(':
|
||||
case ')':
|
||||
case '[':
|
||||
case ']':
|
||||
case '{':
|
||||
case '}':
|
||||
case '|':
|
||||
case '\\':
|
||||
case '*':
|
||||
case '&':
|
||||
case '^':
|
||||
case '%':
|
||||
case '$':
|
||||
case '#':
|
||||
case '@':
|
||||
case '!':
|
||||
case '~':
|
||||
case '`':
|
||||
case '\'':
|
||||
case '"':
|
||||
case ':':
|
||||
case ';':
|
||||
case '?':
|
||||
case '>':
|
||||
case '<':
|
||||
case '\n':
|
||||
if (fullEscape) {
|
||||
buffer.append('\\');
|
||||
}
|
||||
buffer.append(c);
|
||||
continue;
|
||||
case ' ':
|
||||
buffer.append('\\');
|
||||
buffer.append(c);
|
||||
continue;
|
||||
default:
|
||||
buffer.append(c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the command of the command line, assuming that the first entry is
|
||||
* always the command.
|
||||
*
|
||||
* @return The command or null if the command lines has no command nor
|
||||
* arguments.
|
||||
*/
|
||||
public String getCommand() {
|
||||
if (this.tokens.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return this.tokens.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert all tokens in a full command line that can be executed in a
|
||||
* shell.
|
||||
*
|
||||
* @param fullEscape
|
||||
* If every special character shall be escaped. If false, only
|
||||
* white spaces are escaped and the shell will interpret the
|
||||
* special chars. If true, then all special chars are quoted.
|
||||
*/
|
||||
public String getCommandLine(boolean fullEscape) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
Iterator<String> iterator = this.tokens.iterator();
|
||||
boolean first = true;
|
||||
while (iterator.hasNext()) {
|
||||
String token = iterator.next();
|
||||
if (!first) {
|
||||
buffer.append(' ');
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
buffer.append(escapeToken(token, fullEscape));
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the command of the command line, assuming that the first entry is
|
||||
* always the command.
|
||||
*
|
||||
* @return The command or null if the command lines has no command nor
|
||||
* arguments.
|
||||
* @param fullEscape
|
||||
* If every special character shall be escaped. If false, only
|
||||
* white spaces are escaped and the shell will interpret the
|
||||
* special chars. If true, then all special chars are quoted.
|
||||
*/
|
||||
public String getEscapedCommand(boolean fullEscalpe) {
|
||||
if (this.tokens.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return escapeToken(this.tokens.get(0), fullEscalpe).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all arguments, assuming that the first entry is the
|
||||
* command name.
|
||||
*
|
||||
* @return The Array or null if the command lines has no command nor
|
||||
* arguments.
|
||||
*/
|
||||
public String[] getParameterArray() {
|
||||
if (this.tokens.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return this.tokens.subList(1, this.tokens.size()).toArray(new String[this.tokens.size() - 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all arguments, assuming that the first entry is the
|
||||
* command name.
|
||||
*
|
||||
* @return The List or null if the command lines has no command nor
|
||||
* arguments.
|
||||
*/
|
||||
public List<String> getParameterList() {
|
||||
if (this.tokens.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return new ArrayList<String>(this.tokens.subList(1, this.tokens.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of entries.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getSize() {
|
||||
return this.tokens.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List of all entries of the command line.
|
||||
*
|
||||
* @return The Array
|
||||
*/
|
||||
public String[] getTokenArray() {
|
||||
return this.tokens.toArray(new String[this.tokens.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List of all entries of the command line.
|
||||
*
|
||||
* @return The List
|
||||
*/
|
||||
public List<String> getTokenList() {
|
||||
return new ArrayList<String>(this.tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a representation of the command line for debug purposes.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("<"); //$NON-NLS-1$
|
||||
Iterator<String> iterator = this.tokens.iterator();
|
||||
boolean first = true;
|
||||
while (iterator.hasNext()) {
|
||||
String token = iterator.next();
|
||||
if (!first) {
|
||||
buffer.append('\n');
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
buffer.append(token);
|
||||
}
|
||||
buffer.append(">"); //$NON-NLS-1$
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
|
@ -27,18 +27,21 @@ import org.eclipse.osgi.util.NLS;
|
|||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteConnectionChangeEvent;
|
||||
import org.eclipse.remote.core.IRemoteConnectionChangeListener;
|
||||
import org.eclipse.remote.core.IRemoteConnectionManager;
|
||||
import org.eclipse.remote.core.IRemoteConnectionWorkingCopy;
|
||||
import org.eclipse.remote.core.IRemoteFileManager;
|
||||
import org.eclipse.remote.core.IRemoteProcess;
|
||||
import org.eclipse.remote.core.IRemoteProcessBuilder;
|
||||
import org.eclipse.remote.core.IRemoteServices;
|
||||
import org.eclipse.remote.core.IUserAuthenticator;
|
||||
import org.eclipse.remote.core.RemoteServices;
|
||||
import org.eclipse.remote.core.exception.AddressInUseException;
|
||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||
import org.eclipse.remote.core.exception.UnableToForwardPortException;
|
||||
import org.eclipse.remote.internal.jsch.core.commands.ExecCommand;
|
||||
import org.eclipse.remote.internal.jsch.core.messages.Messages;
|
||||
|
||||
import com.jcraft.jsch.Channel;
|
||||
import com.jcraft.jsch.ChannelExec;
|
||||
import com.jcraft.jsch.ChannelSftp;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
|
@ -388,7 +391,7 @@ public class JSchConnection implements IRemoteConnection {
|
|||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.core.IRemoteConnection#forwardRemotePort(java. lang.String, int,
|
||||
* @see org.eclipse.remote.core.IRemoteConnection#forwardRemotePort(java.lang.String, int,
|
||||
* org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
|
@ -581,6 +584,38 @@ public class JSchConnection implements IRemoteConnection {
|
|||
return fProperties.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the proxy command. For no proxy command an empty string is returned.
|
||||
*
|
||||
* @return proxy command
|
||||
*/
|
||||
public String getProxyCommand() {
|
||||
return fAttributes.getAttribute(JSchConnectionAttributes.PROXYCOMMAND_ATTR, EMPTY_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the proxy connection. If no proxy is used it returns a local connection.
|
||||
*
|
||||
* @return proxy connection
|
||||
*/
|
||||
public IRemoteConnection getProxyConnection() {
|
||||
String proxyConnectionName = getProxyConnectionName();
|
||||
if (proxyConnectionName.equals(EMPTY_STRING)) {
|
||||
return RemoteServices.getLocalServices().getConnectionManager().getConnection(
|
||||
IRemoteConnectionManager.LOCAL_CONNECTION_NAME);
|
||||
}
|
||||
return fManager.getConnection(proxyConnectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the proxy connection name
|
||||
*
|
||||
* @return proxy connection name
|
||||
*/
|
||||
public String getProxyConnectionName() {
|
||||
return fAttributes.getAttribute(JSchConnectionAttributes.PROXYCONNECTION_ATTR, EMPTY_STRING);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -612,6 +647,22 @@ public class JSchConnection implements IRemoteConnection {
|
|||
return fSftpChannel;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Session#getStreamForwarder(java.lang.String, int)
|
||||
*/
|
||||
public Channel getStreamForwarder(String host, int port) throws RemoteConnectionException
|
||||
{
|
||||
try {
|
||||
Channel channel = fSessions.get(0).getStreamForwarder(host, port);
|
||||
channel.connect();
|
||||
return channel;
|
||||
} catch (JSchException e) {
|
||||
throw new RemoteConnectionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
return fAttributes.getInt(JSchConnectionAttributes.TIMEOUT_ATTR, DEFAULT_TIMEOUT);
|
||||
}
|
||||
|
@ -792,7 +843,19 @@ public class JSchConnection implements IRemoteConnection {
|
|||
if (isPasswordAuth()) {
|
||||
session.setPassword(getPassword());
|
||||
}
|
||||
fJSchService.connect(session, getTimeout() * 1000, progress.newChild(10));
|
||||
if (getProxyCommand().equals(EMPTY_STRING) && getProxyConnectionName().equals(EMPTY_STRING)) {
|
||||
fJSchService.connect(session, getTimeout() * 1000, progress.newChild(10)); // connect without proxy
|
||||
} else {
|
||||
if (getProxyCommand().equals(EMPTY_STRING)) {
|
||||
session.setProxy(JSchConnectionProxyFactory.createForwardProxy(getProxyConnection(),
|
||||
progress.newChild(10)));
|
||||
fJSchService.connect(session, getTimeout() * 1000, progress.newChild(10));
|
||||
} else {
|
||||
session.setProxy(JSchConnectionProxyFactory.createCommandProxy(getProxyConnection(), getProxyCommand(),
|
||||
progress.newChild(10)));
|
||||
session.connect(getTimeout() * 1000); // the fJSchService doesn't pass the timeout correctly
|
||||
}
|
||||
}
|
||||
if (!progress.isCanceled()) {
|
||||
fSessions.add(session);
|
||||
return session;
|
||||
|
|
|
@ -31,6 +31,8 @@ public class JSchConnectionAttributes {
|
|||
public static final String USERNAME_ATTR = "JSCH_USERNAME_ATTR"; //$NON-NLS-1$
|
||||
public static final String PASSWORD_ATTR = "JSCH_PASSWORD_ATTR"; //$NON-NLS-1$
|
||||
public static final String PORT_ATTR = "JSCH_PORT_ATTR"; //$NON-NLS-1$
|
||||
public static final String PROXYCONNECTION_ATTR = "JSCH_PROXYCONNECTION_ATTR"; //$NON-NLS-1$
|
||||
public static final String PROXYCOMMAND_ATTR = "JSCH_PROXYCOMMAND_ATTR"; //$NON-NLS-1$
|
||||
public static final String IS_PASSWORD_ATTR = "JSCH_IS_PASSWORD_ATTR"; //$NON-NLS-1$
|
||||
public static final String PASSPHRASE_ATTR = "JSCH_PASSPHRASE_ATTR"; //$NON-NLS-1$
|
||||
public static final String KEYFILE_ATTR = "JSCH_KEYFILE_ATTR"; //$NON-NLS-1$
|
||||
|
|
|
@ -0,0 +1,311 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2014 University of Tennessee and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* University of Tennessee (Roland Schulz) - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.remote.internal.jsch.core;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.ILog;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteProcess;
|
||||
import org.eclipse.remote.core.IRemoteProcessBuilder;
|
||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||
import org.eclipse.remote.internal.jsch.core.messages.Messages;
|
||||
|
||||
import com.jcraft.jsch.Channel;
|
||||
import com.jcraft.jsch.Proxy;
|
||||
import com.jcraft.jsch.SocketFactory;
|
||||
|
||||
/**
|
||||
* Creates a JSch Proxy. Supports both command proxies, as well as the ssh build-in
|
||||
* stream forwarding.
|
||||
*
|
||||
* @author rschulz
|
||||
*
|
||||
*/
|
||||
public class JSchConnectionProxyFactory {
|
||||
private static class CommandProxy implements Proxy {
|
||||
private String command;
|
||||
private IRemoteProcess process;
|
||||
private IRemoteConnection connection;
|
||||
private IProgressMonitor monitor;
|
||||
|
||||
private CommandProxy(IRemoteConnection connection, String command, IProgressMonitor monitor) {
|
||||
if (command == null || connection == null || monitor == null)
|
||||
throw new IllegalArgumentException();
|
||||
this.command = command;
|
||||
this.connection = connection;
|
||||
this.monitor = monitor;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#close()
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
process.destroy();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#connect(com.jcraft.jsch.SocketFactory, java.lang.String, int, int)
|
||||
*/
|
||||
@Override
|
||||
public void connect(SocketFactory socket_factory, String host,
|
||||
int port, int timeout) throws IOException {
|
||||
assert connection != null : "connect should only be called once"; //$NON-NLS-1$
|
||||
try {
|
||||
if (timeout == 0) {
|
||||
timeout = 10000; // default to 10s
|
||||
}
|
||||
final int waitTime = 50;
|
||||
final int waitSteps = timeout / waitTime;
|
||||
SubMonitor subMon;
|
||||
|
||||
// Open connection if it isn't already opened
|
||||
if (!connection.isOpen()) {
|
||||
subMon = SubMonitor.convert(monitor, waitSteps * 2);
|
||||
try {
|
||||
connection.open(subMon.newChild(waitSteps));
|
||||
} catch (RemoteConnectionException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
} else {
|
||||
subMon = SubMonitor.convert(monitor, waitSteps);
|
||||
}
|
||||
|
||||
// Start command
|
||||
command = command.replace("%h", host); //$NON-NLS-1$
|
||||
command = command.replace("%p", Integer.toString(port)); //$NON-NLS-1$
|
||||
List<String> cmd = new ArgumentParser(command).getTokenList();
|
||||
IRemoteProcessBuilder pb = connection.getProcessBuilder(cmd);
|
||||
process = pb.start();
|
||||
|
||||
// Wait on command to produce stdout output
|
||||
long endTime = System.currentTimeMillis() + timeout;
|
||||
boolean bOutputAvailable, bProcessComplete, bTimedOut, bCanceled;
|
||||
do {
|
||||
try {
|
||||
Thread.sleep(waitTime);
|
||||
subMon.worked(1);
|
||||
} catch (InterruptedException e) {
|
||||
/* ignore */
|
||||
}
|
||||
bOutputAvailable = (getInputStream().available() != 0);
|
||||
bProcessComplete = process.isCompleted();
|
||||
bTimedOut = System.currentTimeMillis() > endTime;
|
||||
bCanceled = subMon.isCanceled();
|
||||
} while (!bOutputAvailable && !bProcessComplete && !bTimedOut && !bCanceled);
|
||||
|
||||
// If no output was produced before process died, throw an exception with the stderr output
|
||||
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
if (getInputStream().available() == 0 || process.isCompleted()) {
|
||||
String msg = ""; //$NON-NLS-1$
|
||||
while (bufferedReader.ready()) {
|
||||
msg += (char) bufferedReader.read();
|
||||
}
|
||||
msg = msg.trim();
|
||||
|
||||
if (!process.isCompleted()) {
|
||||
process.destroy();
|
||||
}
|
||||
|
||||
String cause = Messages.JSchConnectionProxyFactory_failed;
|
||||
if (bTimedOut) {
|
||||
cause = Messages.JSchConnectionProxyFactory_timedOut;
|
||||
} else if (bCanceled) {
|
||||
cause = Messages.JSchConnectionProxyFactory_wasCanceled;
|
||||
}
|
||||
throw new IOException(MessageFormat.format(Messages.JSchConnectionProxyFactory_ProxyCommandFailed,
|
||||
command, cause, msg));
|
||||
}
|
||||
|
||||
// Dump the stderr to log
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ILog log = Activator.getDefault().getLog();
|
||||
String line;
|
||||
try {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
log.log(new Status(IStatus.INFO, Activator.getUniqueIdentifier(),
|
||||
IStatus.OK, line, null));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Activator.log(e);
|
||||
}
|
||||
};
|
||||
}.start();
|
||||
} finally {
|
||||
// Not valid to call connect again or for any other command to access these variables. Setting to null to ensure.
|
||||
connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#getInputStream()
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return process.getInputStream();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#getOutputStream()
|
||||
*/
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
return process.getOutputStream();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#getSocket()
|
||||
*/
|
||||
@Override
|
||||
public Socket getSocket() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class SSHForwardProxy implements Proxy {
|
||||
private Channel channel;
|
||||
private JSchConnection connection;
|
||||
private IProgressMonitor monitor;
|
||||
|
||||
private SSHForwardProxy(IRemoteConnection proxyConnection, IProgressMonitor monitor) {
|
||||
if (proxyConnection == null || monitor == null)
|
||||
throw new IllegalArgumentException();
|
||||
this.connection = (JSchConnection) proxyConnection; // only JSch supported for ForwardProxy
|
||||
this.monitor = monitor;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#close()
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
channel.disconnect();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#connect(com.jcraft.jsch.SocketFactory, java.lang.String, int, int)
|
||||
*/
|
||||
@Override
|
||||
public void connect(SocketFactory socket_factory, String host, int port,
|
||||
int timeout) throws Exception {
|
||||
assert connection != null : "connect should only be called once"; //$NON-NLS-1$
|
||||
try {
|
||||
if (!connection.isOpen()) {
|
||||
try {
|
||||
connection.open(monitor);
|
||||
} catch (RemoteConnectionException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
channel = connection.getStreamForwarder(host, port);
|
||||
} finally {
|
||||
// Not valid to call connect again or for any other command to access these variables. Setting to null to ensure.
|
||||
connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#getInputStream()
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
try {
|
||||
return channel.getInputStream();
|
||||
} catch (IOException e) {
|
||||
Activator.log(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#getOutputStream()
|
||||
*/
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
try {
|
||||
return channel.getOutputStream();
|
||||
} catch (IOException e) {
|
||||
Activator.log(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.jcraft.jsch.Proxy#getSocket()
|
||||
*/
|
||||
@Override
|
||||
public Socket getSocket() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a (local or remote) command proxy.
|
||||
*
|
||||
* @param connection
|
||||
* Any (local or remote) connection. Cannot be null.
|
||||
* @param command
|
||||
* A valid proxy command. Cannot be null or empty.
|
||||
* @param monitor
|
||||
* A valid progress monitor. Cannot be null.
|
||||
* @return ssh proxy
|
||||
*/
|
||||
public static Proxy createCommandProxy(IRemoteConnection connection, String command, IProgressMonitor monitor) {
|
||||
return new CommandProxy(connection, command, monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ssh forward proxy.
|
||||
*
|
||||
* @param proxyConnection
|
||||
* The Jsch proxy connection. Cannot be null.
|
||||
* @param monitor
|
||||
* A valid progress monitor. Cannot be null.
|
||||
* @return ssh proxy
|
||||
*/
|
||||
public static Proxy createForwardProxy(IRemoteConnection proxyConnection, IProgressMonitor monitor) {
|
||||
return new SSHForwardProxy(proxyConnection, monitor);
|
||||
}
|
||||
}
|
|
@ -107,6 +107,26 @@ public class JSchConnectionWorkingCopy extends JSchConnection implements IRemote
|
|||
return fWorkingAttributes.getInt(JSchConnectionAttributes.PORT_ATTR, DEFAULT_PORT);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.internal.jsch.core.JSchConnection#getProxyCommand()
|
||||
*/
|
||||
@Override
|
||||
public String getProxyCommand() {
|
||||
return fWorkingAttributes.getAttribute(JSchConnectionAttributes.PROXYCOMMAND_ATTR, EMPTY_STRING);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.remote.internal.jsch.core.JSchConnection#getProxyConnectionName()
|
||||
*/
|
||||
@Override
|
||||
public String getProxyConnectionName() {
|
||||
return fWorkingAttributes.getAttribute(JSchConnectionAttributes.PROXYCONNECTION_ATTR, EMPTY_STRING);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -255,6 +275,28 @@ public class JSchConnectionWorkingCopy extends JSchConnection implements IRemote
|
|||
fWorkingAttributes.setAttribute(JSchConnectionAttributes.PORT_ATTR, Integer.toString(port));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the proxy command. Set to empty string for no command
|
||||
*
|
||||
* @param proxyCommand
|
||||
* proxy command
|
||||
*/
|
||||
public void setProxyCommand(String proxyCommand) {
|
||||
fIsDirty = true;
|
||||
fWorkingAttributes.setAttribute(JSchConnectionAttributes.PROXYCOMMAND_ATTR, proxyCommand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the proxy connection name. Set to empty string for no proxy connection
|
||||
*
|
||||
* @param proxyCommand
|
||||
* proxy connection name
|
||||
*/
|
||||
public void setProxyConnectionName(String proxyConnectionName) {
|
||||
fIsDirty = true;
|
||||
fWorkingAttributes.setAttribute(JSchConnectionAttributes.PROXYCONNECTION_ATTR, proxyConnectionName);
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
fIsDirty = true;
|
||||
fWorkingAttributes.setAttribute(JSchConnectionAttributes.TIMEOUT_ATTR, Integer.toString(timeout));
|
||||
|
|
|
@ -38,6 +38,10 @@ public class Messages extends NLS {
|
|||
public static String JSchConnectionManager_connection_with_name_exists;
|
||||
public static String JSchConnectionManager_cannotRemoveOpenConnection;
|
||||
public static String JSchConnectionManager_invalidConnectionType;
|
||||
public static String JSchConnectionProxyFactory_failed;
|
||||
public static String JSchConnectionProxyFactory_ProxyCommandFailed;
|
||||
public static String JSchConnectionProxyFactory_timedOut;
|
||||
public static String JSchConnectionProxyFactory_wasCanceled;
|
||||
public static String JSchProcessBuilder_Connection_is_not_open;
|
||||
public static String JschFileStore_Connection_is_not_open;
|
||||
public static String JschFileStore_File_doesnt_exist;
|
||||
|
|
|
@ -28,6 +28,10 @@ JSchConnection_username_must_be_set=Username must be set before opening connecti
|
|||
JSchConnectionManager_connection_with_name_exists=A connection with name \"{0}\" already exists
|
||||
JSchConnectionManager_cannotRemoveOpenConnection=Cannot remove an open connection
|
||||
JSchConnectionManager_invalidConnectionType=Invalid connection type
|
||||
JSchConnectionProxyFactory_failed=failed
|
||||
JSchConnectionProxyFactory_ProxyCommandFailed=Proxy command "{0}" {1} and printed message "{2}"
|
||||
JSchConnectionProxyFactory_timedOut=timed out
|
||||
JSchConnectionProxyFactory_wasCanceled=was canceled
|
||||
JSchProcessBuilder_Connection_is_not_open=Connection is not open
|
||||
JschFileStore_Connection_is_not_open=Connection is not open
|
||||
JschFileStore_File_doesnt_exist=File {0} doesn't exist
|
||||
|
|
|
@ -25,6 +25,12 @@ public class Messages extends NLS {
|
|||
public static String JSchConnectionPage_Edit_Connection;
|
||||
public static String JSchConnectionPage_Edit_properties_of_an_existing_connection;
|
||||
public static String JSchConnectionPage_Please_enter_name_for_connection;
|
||||
public static String JSchConnectionPage_Proxy;
|
||||
public static String JSchConnectionPage_Help;
|
||||
public static String JSchConnectionPage_SelectCommand;
|
||||
public static String JSchConnectionPage_SelectConnection;
|
||||
public static String JSchConnectionPage_Settings0;
|
||||
public static String JSchConnectionPage_selectProxyConnection;
|
||||
public static String JSchFileSystemContributor_0;
|
||||
public static String JSchNewConnectionPage_Advanced;
|
||||
public static String JSchNewConnectionPage_Connection_name;
|
||||
|
|
|
@ -12,6 +12,12 @@ JSchConnectionPage_A_connection_with_that_name_already_exists=A connection with
|
|||
JSchConnectionPage_Edit_Connection=Edit Connection
|
||||
JSchConnectionPage_Edit_properties_of_an_existing_connection=Edit properties of an existing connection
|
||||
JSchConnectionPage_Please_enter_name_for_connection=Please enter a name for the connection
|
||||
JSchConnectionPage_Proxy=SSH Proxy Settings
|
||||
JSchConnectionPage_Help=If 'Local' is selected and proxy command is empty, no proxy is used.\nSee <a href=\"org.eclipse.ui.net.NetPreferences\">Network Connections</a> for SOCKS and HTTP proxy options.
|
||||
JSchConnectionPage_SelectCommand=Enter a local or remote command such as 'nc %h %p'. Can be empty for an ssh gateway.
|
||||
JSchConnectionPage_SelectConnection=Select 'Remote' for an ssh gateway or a remote proxy command.
|
||||
JSchConnectionPage_Settings0=Connection Settings
|
||||
JSchConnectionPage_selectProxyConnection=Please select a proxy connection
|
||||
JSchFileSystemContributor_0=Browse File System
|
||||
JSchNewConnectionPage_Advanced=Advanced
|
||||
JSchNewConnectionPage_Connection_name=Connection name:
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jface.wizard.WizardPage;
|
||||
import org.eclipse.remote.core.IRemoteConnection;
|
||||
import org.eclipse.remote.core.IRemoteConnectionManager;
|
||||
import org.eclipse.remote.core.RemoteServices;
|
||||
import org.eclipse.remote.core.exception.RemoteConnectionException;
|
||||
|
@ -25,6 +26,7 @@ import org.eclipse.remote.internal.jsch.core.JSchConnection;
|
|||
import org.eclipse.remote.internal.jsch.core.JSchConnectionAttributes;
|
||||
import org.eclipse.remote.internal.jsch.core.JSchConnectionWorkingCopy;
|
||||
import org.eclipse.remote.internal.jsch.ui.messages.Messages;
|
||||
import org.eclipse.remote.ui.widgets.RemoteConnectionWidget;
|
||||
import org.eclipse.remote.ui.widgets.RemoteFileWidget;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.ModifyEvent;
|
||||
|
@ -41,6 +43,7 @@ import org.eclipse.swt.widgets.Composite;
|
|||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Group;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Link;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.ui.forms.events.ExpansionEvent;
|
||||
import org.eclipse.ui.forms.events.IExpansionListener;
|
||||
|
@ -74,6 +77,8 @@ public class JSchConnectionPage extends WizardPage {
|
|||
private final IRemoteConnectionManager fConnectionManager;
|
||||
|
||||
private final DataModifyListener fDataModifyListener = new DataModifyListener();
|
||||
private RemoteConnectionWidget fProxyConnectionWidget;
|
||||
private Text fProxyCommandText;
|
||||
|
||||
public JSchConnectionPage(IRemoteConnectionManager connMgr) {
|
||||
super(Messages.JSchNewConnectionPage_New_Connection);
|
||||
|
@ -82,7 +87,7 @@ public class JSchConnectionPage extends WizardPage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create controls for the bottom (hideable) composite
|
||||
* Create controls for the bottom (hideable) advanced composite
|
||||
*
|
||||
* @param mold
|
||||
*
|
||||
|
@ -96,13 +101,15 @@ public class JSchConnectionPage extends WizardPage {
|
|||
|
||||
@Override
|
||||
public void expansionStateChanged(ExpansionEvent e) {
|
||||
Point newSize = parent.computeSize(SWT.DEFAULT, SWT.DEFAULT);
|
||||
Point currentSize = parent.getSize();
|
||||
int deltaY = newSize.y - currentSize.y;
|
||||
Point shellSize = getShell().getSize();
|
||||
shellSize.y += deltaY;
|
||||
getShell().setSize(shellSize);
|
||||
getShell().layout(true, true);
|
||||
for (int i = 0; i < 2; i++) { // sometimes the size compute isn't correct on first try
|
||||
Point newSize = parent.computeSize(SWT.DEFAULT, SWT.DEFAULT);
|
||||
Point currentSize = parent.getSize();
|
||||
int deltaY = newSize.y - currentSize.y;
|
||||
Point shellSize = getShell().getSize();
|
||||
shellSize.y += deltaY;
|
||||
getShell().setSize(shellSize);
|
||||
getShell().layout(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -112,25 +119,36 @@ public class JSchConnectionPage extends WizardPage {
|
|||
});
|
||||
|
||||
Composite advancedComp = new Composite(expComp, SWT.NONE);
|
||||
advancedComp.setLayout(new GridLayout(2, false));
|
||||
advancedComp.setLayout(new GridLayout(1, false));
|
||||
advancedComp.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
|
||||
|
||||
Label portLabel = new Label(advancedComp, SWT.NONE);
|
||||
Group settingsComp = new Group(advancedComp, SWT.NONE);
|
||||
settingsComp.setText(Messages.JSchConnectionPage_Settings0);
|
||||
settingsComp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
|
||||
settingsComp.setLayout(new GridLayout(2, false));
|
||||
|
||||
Label portLabel = new Label(settingsComp, SWT.NONE);
|
||||
portLabel.setText(Messages.JSchNewConnectionPage_Port);
|
||||
portLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
|
||||
fPortText = new Text(advancedComp, SWT.BORDER | SWT.SINGLE);
|
||||
fPortText = new Text(settingsComp, SWT.BORDER | SWT.SINGLE);
|
||||
fPortText.setText(Integer.toString(JSchConnection.DEFAULT_PORT));
|
||||
fPortText.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
|
||||
setTextFieldWidthInChars(fPortText, 5);
|
||||
|
||||
Label timeoutLabel = new Label(advancedComp, SWT.NONE);
|
||||
Label timeoutLabel = new Label(settingsComp, SWT.NONE);
|
||||
timeoutLabel.setText(Messages.JSchNewConnectionPage_Timeout);
|
||||
timeoutLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
|
||||
fTimeoutText = new Text(advancedComp, SWT.BORDER | SWT.SINGLE);
|
||||
fTimeoutText = new Text(settingsComp, SWT.BORDER | SWT.SINGLE);
|
||||
fTimeoutText.setText(Integer.toString(JSchConnection.DEFAULT_TIMEOUT));
|
||||
fTimeoutText.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
|
||||
setTextFieldWidthInChars(fTimeoutText, 5);
|
||||
|
||||
Group proxyComp = new Group(advancedComp, SWT.NONE);
|
||||
proxyComp.setText(Messages.JSchConnectionPage_Proxy);
|
||||
proxyComp.setLayout(new GridLayout(1, false));
|
||||
proxyComp.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
|
||||
createProxyControls(proxyComp);
|
||||
|
||||
expComp.setClient(advancedComp);
|
||||
}
|
||||
|
||||
|
@ -248,6 +266,33 @@ public class JSchConnectionPage extends WizardPage {
|
|||
updateEnablement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create controls for the bottom (hideable) proxy composite
|
||||
*
|
||||
* @param mold
|
||||
*
|
||||
*/
|
||||
private void createProxyControls(final Composite proxyComp) {
|
||||
Label lblConnection = new Label(proxyComp, SWT.WRAP);
|
||||
lblConnection.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
lblConnection.setText(Messages.JSchConnectionPage_SelectConnection);
|
||||
|
||||
fProxyConnectionWidget = new RemoteConnectionWidget(proxyComp, SWT.NONE, null, 0, null);
|
||||
|
||||
Label lblCommand = new Label(proxyComp, SWT.WRAP);
|
||||
lblCommand.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
lblCommand.setText(Messages.JSchConnectionPage_SelectCommand);
|
||||
|
||||
fProxyCommandText = new Text(proxyComp, SWT.BORDER);
|
||||
fProxyCommandText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
|
||||
Link link = new Link(proxyComp, SWT.WRAP);
|
||||
final GridData linkLayoutData = new GridData(GridData.FILL_HORIZONTAL);
|
||||
link.setLayoutData(linkLayoutData);
|
||||
linkLayoutData.widthHint = 400;
|
||||
link.setText(Messages.JSchConnectionPage_Help);
|
||||
}
|
||||
|
||||
public JSchConnectionWorkingCopy getConnection() {
|
||||
return fConnection;
|
||||
}
|
||||
|
@ -285,6 +330,9 @@ public class JSchConnectionPage extends WizardPage {
|
|||
fPassphraseText.setText(fConnection.getPassphrase());
|
||||
fFileWidget.setLocationPath(fConnection.getKeyFile());
|
||||
}
|
||||
fProxyCommandText.setText(fConnection.getProxyCommand());
|
||||
|
||||
fProxyConnectionWidget.setConnection(fConnection.getProxyConnection());
|
||||
} else {
|
||||
fConnectionName.setText(fInitialName);
|
||||
String host = fInitialAttributes.get(JSchConnectionAttributes.ADDRESS_ATTR);
|
||||
|
@ -319,6 +367,8 @@ public class JSchConnectionPage extends WizardPage {
|
|||
if (file != null) {
|
||||
fFileWidget.setLocationPath(file);
|
||||
}
|
||||
fProxyConnectionWidget.setConnection(RemoteServices.getLocalServices().getConnectionManager().getConnection(
|
||||
IRemoteConnectionManager.LOCAL_CONNECTION_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,6 +381,14 @@ public class JSchConnectionPage extends WizardPage {
|
|||
fPassphraseText.addModifyListener(fDataModifyListener);
|
||||
fPortText.addModifyListener(fDataModifyListener);
|
||||
fTimeoutText.addModifyListener(fDataModifyListener);
|
||||
fProxyCommandText.addModifyListener(fDataModifyListener);
|
||||
fProxyConnectionWidget.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
validateFields();
|
||||
getContainer().updateButtons();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
|
@ -420,6 +478,17 @@ public class JSchConnectionPage extends WizardPage {
|
|||
if (fConnection.getPort() != port) {
|
||||
fConnection.setPort(port);
|
||||
}
|
||||
if (!fConnection.getProxyCommand().equals(fProxyCommandText.getText().trim())) {
|
||||
fConnection.setProxyCommand(fProxyCommandText.getText().trim());
|
||||
}
|
||||
IRemoteConnection proxyConnection = fProxyConnectionWidget.getConnection();
|
||||
String proxyConnectionName = ""; //$NON-NLS-1$
|
||||
if (proxyConnection != null && proxyConnection.getRemoteServices() != RemoteServices.getLocalServices()) {
|
||||
proxyConnectionName = proxyConnection.getName();
|
||||
}
|
||||
if (!fConnection.getProxyConnectionName().equals(proxyConnectionName)) {
|
||||
fConnection.setProxyConnectionName(proxyConnectionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,9 +530,13 @@ public class JSchConnectionPage extends WizardPage {
|
|||
if (message == null) {
|
||||
message = validatePasskey();
|
||||
}
|
||||
if (message == null && fProxyConnectionWidget.getConnection() == null) {
|
||||
message = Messages.JSchConnectionPage_selectProxyConnection;
|
||||
}
|
||||
if (message == null) {
|
||||
message = validateAdvanced();
|
||||
}
|
||||
|
||||
setErrorMessage(message);
|
||||
setPageComplete(message == null);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue