From 3faf39df8df82fabd827f19b184e232361b9e659 Mon Sep 17 00:00:00 2001 From: Greg Watson Date: Thu, 27 Feb 2014 18:55:49 -0500 Subject: [PATCH] [429271] Fix for special characters in directory names (master branch) Change-Id: Ib5ff490ec83dd4791cb01f6d1f85f5b0db189f77 Signed-off-by: Greg Watson --- .../core/commands/AbstractRemoteCommand.java | 200 +++++++++++------- .../jsch/core/commands/ChildInfosCommand.java | 2 +- .../jsch/core/commands/DeleteCommand.java | 52 ----- .../jsch/core/commands/PutInfoCommand.java | 5 +- 4 files changed, 130 insertions(+), 129 deletions(-) diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/AbstractRemoteCommand.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/AbstractRemoteCommand.java index 45105c2d1dc..95ec7aa0fcb 100755 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/AbstractRemoteCommand.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/AbstractRemoteCommand.java @@ -12,7 +12,9 @@ package org.eclipse.remote.internal.jsch.core.commands; import java.io.IOException; +import java.text.CharacterIterator; import java.text.MessageFormat; +import java.text.StringCharacterIterator; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -109,6 +111,78 @@ public abstract class AbstractRemoteCommand { } } + protected abstract class ExecCallable implements Callable { + private IProgressMonitor fProgressMonitor; + private ChannelExec fExecChannel; + + private Future asyncCmdInThread() throws RemoteConnectionException { + setChannel(fConnection.getExecChannel()); + return fPool.submit(this); + } + + /* + * (non-Javadoc) + * + * @see java.util.concurrent.Callable#call() + */ + @Override + public abstract T1 call() throws JSchException, IOException; + + private void finalizeCmdInThread() { + setChannel(null); + } + + public ChannelExec getChannel() { + return fExecChannel; + } + + public IProgressMonitor getProgressMonitor() { + return fProgressMonitor; + } + + /** + * Function opens exec channel and then executes the exec operation. If + * run on the main thread it executes it on a separate thread + */ + public T1 getResult(IProgressMonitor monitor) throws RemoteConnectionException { + Future future = null; + fProgressMonitor = SubMonitor.convert(monitor, 10); + try { + future = asyncCmdInThread(); + return waitCmdInThread(future); + } finally { + finalizeCmdInThread(); + } + } + + public void setChannel(ChannelExec channel) { + fExecChannel = channel; + } + + private T1 waitCmdInThread(Future future) throws RemoteConnectionException { + boolean bInterrupted = Thread.interrupted(); + while (!getProgressMonitor().isCanceled()) { + try { + return future.get(100, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + bInterrupted = true; + } catch (TimeoutException e) { + // ignore + } catch (ExecutionException e) { + getChannel().disconnect(); + throw new RemoteConnectionException(e.getMessage()); + } + getProgressMonitor().worked(1); + } + if (bInterrupted) { + Thread.currentThread().interrupt(); // set current thread flag + } + future.cancel(true); + getChannel().disconnect(); + throw new RemoteConnectionException(Messages.AbstractRemoteCommand_Operation_cancelled_by_user); + } + } + protected abstract class SftpCallable implements Callable { private IProgressMonitor fProgressMonitor; private ChannelSftp fSftpChannel; @@ -184,78 +258,6 @@ public abstract class AbstractRemoteCommand { } } - protected abstract class ExecCallable implements Callable { - private IProgressMonitor fProgressMonitor; - private ChannelExec fExecChannel; - - private Future asyncCmdInThread() throws RemoteConnectionException { - setChannel(fConnection.getExecChannel()); - return fPool.submit(this); - } - - /* - * (non-Javadoc) - * - * @see java.util.concurrent.Callable#call() - */ - @Override - public abstract T1 call() throws JSchException, IOException; - - private void finalizeCmdInThread() { - setChannel(null); - } - - public ChannelExec getChannel() { - return fExecChannel; - } - - public IProgressMonitor getProgressMonitor() { - return fProgressMonitor; - } - - /** - * Function opens exec channel and then executes the exec operation. If - * run on the main thread it executes it on a separate thread - */ - public T1 getResult(IProgressMonitor monitor) throws RemoteConnectionException { - Future future = null; - fProgressMonitor = SubMonitor.convert(monitor, 10); - try { - future = asyncCmdInThread(); - return waitCmdInThread(future); - } finally { - finalizeCmdInThread(); - } - } - - public void setChannel(ChannelExec channel) { - fExecChannel = channel; - } - - private T1 waitCmdInThread(Future future) throws RemoteConnectionException { - boolean bInterrupted = Thread.interrupted(); - while (!getProgressMonitor().isCanceled()) { - try { - return future.get(100, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - bInterrupted = true; - } catch (TimeoutException e) { - // ignore - } catch (ExecutionException e) { - getChannel().disconnect(); - throw new RemoteConnectionException(e.getMessage()); - } - getProgressMonitor().worked(1); - } - if (bInterrupted) { - Thread.currentThread().interrupt(); // set current thread flag - } - future.cancel(true); - getChannel().disconnect(); - throw new RemoteConnectionException(Messages.AbstractRemoteCommand_Operation_cancelled_by_user); - } - } - private static ExecutorService fPool = Executors.newSingleThreadExecutor(); private final JSchConnection fConnection; @@ -347,6 +349,10 @@ public abstract class AbstractRemoteCommand { return fileInfo; } + public JSchConnection getConnection() { + return fConnection; + } + public int getFinishStatus() { int code = 0; @@ -429,7 +435,53 @@ public abstract class AbstractRemoteCommand { protected abstract T getResult(IProgressMonitor monitor) throws RemoteConnectionException; - public JSchConnection getConnection() { - return fConnection; + protected String quote(String path, boolean full) { + StringBuffer buffer = new StringBuffer(); + StringCharacterIterator iter = new StringCharacterIterator(path); + for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) { + 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 ',': + case '\n': + if (full) { + buffer.append('\\'); + } + buffer.append(c); + continue; + case ' ': + buffer.append('\\'); + buffer.append(c); + continue; + default: + buffer.append(c); + continue; + } + } + return buffer.toString(); } + } \ No newline at end of file diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/ChildInfosCommand.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/ChildInfosCommand.java index 08af2d649ff..4438765ea8b 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/ChildInfosCommand.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/ChildInfosCommand.java @@ -55,7 +55,7 @@ public class ChildInfosCommand extends AbstractRemoteCommand { @SuppressWarnings("unchecked") @Override public Vector call() throws JSchException, SftpException { - return getChannel().ls(fRemotePath.toString()); + return getChannel().ls(quote(fRemotePath.toString(), true)); } }; try { diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/DeleteCommand.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/DeleteCommand.java index b788d921bd8..4183e83ff3a 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/DeleteCommand.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/DeleteCommand.java @@ -1,8 +1,5 @@ package org.eclipse.remote.internal.jsch.core.commands; -import java.text.CharacterIterator; -import java.text.StringCharacterIterator; - import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; @@ -30,53 +27,4 @@ public class DeleteCommand extends AbstractRemoteCommand { } return null; } - - private String quote(String path, boolean full) { - StringBuffer buffer = new StringBuffer(); - StringCharacterIterator iter = new StringCharacterIterator(path); - for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) { - 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 ',': - case '\n': - if (full) { - buffer.append('\\'); - } - buffer.append(c); - continue; - case ' ': - buffer.append('\\'); - buffer.append(c); - continue; - default: - buffer.append(c); - continue; - } - } - return buffer.toString(); - } } diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/PutInfoCommand.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/PutInfoCommand.java index 80092035b78..51afafe5d1b 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/PutInfoCommand.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/commands/PutInfoCommand.java @@ -38,15 +38,16 @@ public class PutInfoCommand extends AbstractRemoteCommand { final SubMonitor subMon = SubMonitor.convert(monitor, 30); FetchInfoCommand command = new FetchInfoCommand(getConnection(), fRemotePath); + String quotedPath = quote(fRemotePath.toString(), true); if ((fOptions & EFS.SET_ATTRIBUTES) != 0) { - chmod(getPermissions(fFileInfo), fRemotePath.toString(), subMon.newChild(10)); + chmod(getPermissions(fFileInfo), quotedPath, subMon.newChild(10)); } if ((fOptions & EFS.SET_LAST_MODIFIED) != 0) { IFileInfo info = command.getResult(subMon.newChild(10)); long oldMTime = info.getLastModified(); int newMTime = (int) (oldMTime / 1000); if (oldMTime != newMTime) { - setMTime(newMTime, fRemotePath.toString(), subMon.newChild(10)); + setMTime(newMTime, quotedPath, subMon.newChild(10)); } } return null;