1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-03 07:05:24 +02:00

[203500] Support encodings for SSH Sftp and FTP paths

This commit is contained in:
Martin Oberhuber 2007-09-26 22:50:53 +00:00
parent 48a344793d
commit a46672968f
5 changed files with 274 additions and 39 deletions

View file

@ -13,6 +13,7 @@
* Martin Oberhuber (Wind River) - [186773] split ISystemRegistryUI from ISystemRegistry
* Martin Oberhuber (Wind River) - [186761] make the port setting configurable
* Martin Oberhuber (Wind River) - [198790] make SSH createSession() protected
* Martin Oberhuber (Wind River) - [203500] Support encodings for SSH Sftp paths
*******************************************************************************/
package org.eclipse.rse.internal.connectorservice.ssh;
@ -61,6 +62,8 @@ public class SshConnectorService extends StandardConnectorService implements ISs
private static final int CONNECT_DEFAULT_TIMEOUT = 60; //seconds
private Session session;
private SessionLostHandler fSessionLostHandler;
/** Indicates the default string encoding on this platform */
private static String _defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding();
public SshConnectorService(IHost host) {
super(SshConnectorResources.SshConnectorService_Name, SshConnectorResources.SshConnectorService_Description, host, SSH_DEFAULT_PORT);
@ -209,6 +212,15 @@ public class SshConnectorService extends StandardConnectorService implements ISs
public Session getSession() {
return session;
}
public String getControlEncoding() {
//TODO this code should be in IHost
String encoding = getHost().getDefaultEncoding(false);
if (encoding==null) encoding = getHost().getDefaultEncoding(true);
if (encoding==null) encoding = _defaultEncoding;
//</code to be in IHost>
return encoding;
}
/**
* Handle session-lost events.

View file

@ -37,7 +37,7 @@
* Javier Montalvo Orus (Symbian) - Fixing 168120 - [ftp] root filter resolves to home dir
* Javier Montalvo Orus (Symbian) - Fixing 169680 - [ftp] FTP files subsystem and service should use passive mode
* Javier Montalvo Orus (Symbian) - Fixing 174828 - [ftp] Folders are attempted to be removed as files
* Javier Montalvo Orus (Symbian) - Fixing 176216 - [api] FTP sould provide API to allow clients register their own FTPListingParser
* Javier Montalvo Orus (Symbian) - Fixing 176216 - [api] FTP should provide API to allow clients register their own FTPListingParser
* Martin Oberhuber (Wind River) - [186128] Move IProgressMonitor last in all API
* Javier Montalvo Orus (Symbian) - improved autodetection of FTPListingParser
* Javier Montalvo Orus (Symbian) - [187096] Drag&Drop + Copy&Paste shows error message on FTP connection
@ -61,6 +61,7 @@
* Martin Oberhuber (Wind River) - [203306] Fix Deadlock comparing two files on FTP
* Martin Oberhuber (Wind River) - [204669] Fix ftp path concatenation on systems using backslash separator
* Martin Oberhuber (Wind River) - [203490] Fix NPE in FTPService.getUserHome()
* Martin Oberhuber (Wind River) - [203500] Support encodings for FTP paths
********************************************************************************/
package org.eclipse.rse.internal.services.files.ftp;
@ -74,6 +75,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
@ -96,6 +98,8 @@ import org.eclipse.rse.services.clientserver.FileTypeMatcher;
import org.eclipse.rse.services.clientserver.IMatcher;
import org.eclipse.rse.services.clientserver.NamePatternMatcher;
import org.eclipse.rse.services.clientserver.PathUtility;
import org.eclipse.rse.services.clientserver.messages.IndicatorException;
import org.eclipse.rse.services.clientserver.messages.SystemMessage;
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
import org.eclipse.rse.services.files.AbstractFileService;
import org.eclipse.rse.services.files.IFileService;
@ -117,6 +121,7 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
private transient String _userId;
private transient String _password;
private transient int _portNumber;
private transient String _controlEncoding; //Encoding to be used for file and path names
private OutputStream _ftpLoggingOutputStream;
private IPropertySet _ftpPropertySet;
@ -273,13 +278,69 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
{
_entryParserFactory = entryParserFactory;
}
/**
* Set the character encoding to be used on the FTP command channel.
* The encoding must be compatible with ASCII since FTP commands will
* be sent with the same encoding. Therefore, wide
* (16-bit) encodings are not supported.
* @param encoding Encoding to set
*/
public void setControlEncoding(String encoding)
{
_controlEncoding = encoding;
}
/**
* Check whether the given Unicode String can be properly represented with the
* specified control encoding. Throw a SystemMessageException if it turns out
* that information would be lost.
* @param s String to check
* @return the original String or a quoted or re-coded version if possible
* @throws SystemMessageException if information is lost
*/
protected String checkEncoding(String s) throws SystemMessageException {
String encoding = _controlEncoding!=null ? _controlEncoding : getFTPClient().getControlEncoding();
try {
byte[] bytes = s.getBytes(encoding);
String decoded = new String(bytes, encoding);
if (!s.equals(decoded)) {
int i=0;
int lmax = Math.min(s.length(), decoded.length());
while( (i<lmax) && (s.charAt(i)==decoded.charAt(i))) {
i++;
}
//String sbad=s.substring(Math.max(i-2,0), Math.min(i+2,lmax));
char sbad = s.charAt(i);
//FIXME Need to externalize this message in 3.0
String msg = "Cannot express character \'"+sbad+"\'(0x"+Integer.toHexString(sbad) +") with " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ "encoding \""+encoding+"\". "; //$NON-NLS-1$ //$NON-NLS-2$
msg += "Please specify a different encoding in host properties."; //$NON-NLS-1$
throw new UnsupportedEncodingException(msg);
}
return s;
} catch(UnsupportedEncodingException e) {
try {
//SystemMessage msg = new SystemMessage("RSE","F","9999",'E',e.getMessage(),"Please specify a different encoding in host properties."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
SystemMessage msg = new SystemMessage("RSE","F","9999",'E',e.getMessage(),""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
//throw new RemoteFileIOException(new SystemMessageException(msg));
throw new SystemMessageException(msg);
} catch(IndicatorException ind) {
throw new RemoteFileIOException(e);
}
}
}
public void connect() throws RemoteFileSecurityException,IOException
{
if (_ftpClient == null)
{
_ftpClient = new FTPClient();
// Encoding of control connection
if(_controlEncoding!=null) {
_ftpClient.setControlEncoding(_controlEncoding);
}
}
if(_ftpLoggingOutputStream!=null)
@ -403,6 +464,10 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
if (_ftpClient == null)
{
_ftpClient = new FTPClient();
// Encoding of control connection
if(_controlEncoding!=null) {
_ftpClient.setControlEncoding(_controlEncoding);
}
}
if(_hostName!=null)
@ -433,6 +498,7 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
FTPClient ftpClient = new FTPClient();
boolean ok=false;
try {
ftpClient.setControlEncoding(_ftpClient.getControlEncoding());
ftpClient.connect(_ftpClient.getRemoteAddress());
ftpClient.login(_userId,_password);
@ -485,6 +551,8 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
*/
protected FTPHostFile getFileInternal(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException
{
remoteParent = checkEncoding(remoteParent);
fileName = checkEncoding(fileName);
if (monitor!=null){
if (monitor.isCanceled()) {
throw new RemoteFileCancelledException();
@ -584,6 +652,7 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
*/
protected IHostFile[] internalFetch(String parentPath, String fileFilter, int fileType, IProgressMonitor monitor) throws SystemMessageException
{
parentPath = checkEncoding(parentPath);
if (monitor!=null){
if (monitor.isCanceled()) {
throw new RemoteFileCancelledException();
@ -676,6 +745,8 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
public boolean upload(File localFile, String remoteParent, String remoteFile, boolean isBinary, String srcEncoding, String hostEncoding, IProgressMonitor monitor) throws SystemMessageException
{
boolean retValue = true;
remoteParent = checkEncoding(remoteParent);
remoteFile = checkEncoding(remoteFile);
if (monitor!=null){
if (monitor.isCanceled()) {
@ -758,6 +829,8 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
public boolean upload(InputStream stream, String remoteParent, String remoteFile, boolean isBinary, String hostEncoding, IProgressMonitor monitor) throws SystemMessageException
{
boolean retValue = true;
remoteParent = checkEncoding(remoteParent);
remoteFile = checkEncoding(remoteFile);
try
{
@ -897,7 +970,6 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
return new FTPHostFile("",_userHome,true,true,0,0,true); //$NON-NLS-1$
}
/*
* (non-Javadoc)
* @see org.eclipse.rse.services.files.IFileService#getRoots(org.eclipse.core.runtime.IProgressMonitor)
@ -924,7 +996,9 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
*/
public boolean delete(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException {
boolean hasSucceeded = false;
remoteParent = checkEncoding(remoteParent);
fileName = checkEncoding(fileName);
MyProgressMonitor progressMonitor = new MyProgressMonitor(monitor);
progressMonitor.init(FTPServiceResources.FTP_File_Service_Deleting_Task+fileName, 1);
@ -980,8 +1054,10 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
* @see org.eclipse.rse.services.files.IFileService#rename(org.eclipse.core.runtime.IProgressMonitor, java.lang.String, java.lang.String, java.lang.String)
*/
public boolean rename(String remoteParent, String oldName, String newName, IProgressMonitor monitor) throws SystemMessageException {
boolean success = false;
remoteParent = checkEncoding(remoteParent);
oldName = checkEncoding(oldName);
newName = checkEncoding(newName);
if(_commandMutex.waitForLock(monitor, Long.MAX_VALUE))
{
@ -1026,8 +1102,11 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
* @see org.eclipse.rse.services.files.IFileService#move(org.eclipse.core.runtime.IProgressMonitor, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
public boolean move(String srcParent, String srcName, String tgtParent, String tgtName, IProgressMonitor monitor) throws SystemMessageException{
boolean success = false;
srcParent = checkEncoding(srcParent);
srcName = checkEncoding(srcName);
tgtParent = checkEncoding(tgtParent);
tgtName = checkEncoding(tgtName);
if(_commandMutex.waitForLock(monitor, Long.MAX_VALUE))
{
@ -1061,6 +1140,8 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
*/
public IHostFile createFolder(String remoteParent, String folderName, IProgressMonitor monitor) throws SystemMessageException
{
remoteParent = checkEncoding(remoteParent);
folderName = checkEncoding(folderName);
if(_commandMutex.waitForLock(monitor, Long.MAX_VALUE))
{
try
@ -1093,7 +1174,8 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
* @see org.eclipse.rse.services.files.IFileService#createFile(org.eclipse.core.runtime.IProgressMonitor, java.lang.String, java.lang.String)
*/
public IHostFile createFile(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException{
remoteParent = checkEncoding(remoteParent);
fileName = checkEncoding(fileName);
try {
File tempFile = File.createTempFile("ftp", "temp"); //$NON-NLS-1$ //$NON-NLS-2$
tempFile.deleteOnExit();
@ -1385,7 +1467,9 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
* @see org.eclipse.rse.services.files.AbstractFileService#getOutputStream(java.lang.String, java.lang.String, boolean, org.eclipse.core.runtime.IProgressMonitor)
*/
public OutputStream getOutputStream(String remoteParent, String remoteFile, boolean isBinary, IProgressMonitor monitor) throws SystemMessageException {
remoteParent = checkEncoding(remoteParent);
remoteFile = checkEncoding(remoteFile);
if (monitor != null && monitor.isCanceled()){
throw new RemoteFileCancelledException();
}
@ -1435,4 +1519,4 @@ public class FTPService extends AbstractFileService implements IFileService, IFT
}
}
}
}

View file

@ -12,7 +12,7 @@
* Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
*
* Contributors:
* {Name} (company) - description of contribution.
* Martin Oberhuber (Wind River) - [203500] Support encodings for SSH Sftp paths
*******************************************************************************/
package org.eclipse.rse.internal.services.ssh;
@ -26,4 +26,7 @@ public interface ISshSessionProvider
/* Inform the connectorService that a session has been lost. */
public void handleSessionLost();
/* Return the encoding to be used for file and directory names */
public String getControlEncoding();
}

View file

@ -14,6 +14,7 @@
* Martin Oberhuber (Wind River) - [199548] Avoid touching files on setReadOnly() if unnecessary
* Benjamin Muskalla (b.muskalla@gmx.net) - [174690][ssh] cannot delete symbolic links on remote systems
* Martin Oberhuber (Wind River) - [203490] Fix NPE in SftpService.getUserHome()
* Martin Oberhuber (Wind River) - [203500] Support encodings for SSH Sftp paths
*******************************************************************************/
package org.eclipse.rse.internal.services.ssh.files;
@ -26,10 +27,12 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
@ -53,6 +56,8 @@ import org.eclipse.rse.services.clientserver.FileTypeMatcher;
import org.eclipse.rse.services.clientserver.IMatcher;
import org.eclipse.rse.services.clientserver.NamePatternMatcher;
import org.eclipse.rse.services.clientserver.PathUtility;
import org.eclipse.rse.services.clientserver.messages.IndicatorException;
import org.eclipse.rse.services.clientserver.messages.SystemMessage;
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
import org.eclipse.rse.services.files.AbstractFileService;
import org.eclipse.rse.services.files.IFileService;
@ -139,7 +144,11 @@ public class SftpFileService extends AbstractFileService implements IFileService
private ChannelSftp fChannelSftp;
private String fUserHome;
private Mutex fDirChannelMutex = new Mutex();
private long fDirChannelTimeout = 5000; //max.5 seconds to obtain dir channel
private long fDirChannelTimeout = 5000; //max.5 seconds to obtain dir channel
/** Client-desired encoding for file and path names */
private String fControlEncoding = null;
/** Indicates the default string encoding on this platform */
private static String defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding();
// public SftpFileService(SshConnectorService conn) {
// fConnector = conn;
@ -149,6 +158,121 @@ public class SftpFileService extends AbstractFileService implements IFileService
fSessionProvider = sessionProvider;
}
public void setControlEncoding(String encoding) {
fControlEncoding = encoding;
}
/**
* Encode String with requested user encoding, in case it differs from Platform default encoding.
* @param s String to encode
* @return encoded String
* @throws SystemMessageException
*/
protected String recode(String s) throws SystemMessageException {
if (fControlEncoding==null) {
return s;
} else if (fControlEncoding.equals(defaultEncoding)) {
return s;
}
try {
byte[] bytes = s.getBytes(fControlEncoding); //what we want on the wire
return new String(bytes); //what we need to tell Jsch to get this on the wire
} catch(UnsupportedEncodingException e) {
throw makeSystemMessageException(e);
}
}
/**
* Recode String, and check that no information is lost.
* Throw an exception in case the desired Unicode String can not be expressed
* by the current encodings. Also enquotes result characters '?' and '*' for
* Jsch if necessary.
* @param s String to recode
* @return recoded String
* @throws SystemMessageException if information is lost
*/
protected String recodeSafe(String s) throws SystemMessageException {
try {
String recoded = recode(s);
byte[] bytes = recoded.getBytes(defaultEncoding);
String decoded = decode(new String(bytes));
if (!s.equals(decoded)) {
int i=0;
int lmax = Math.min(s.length(), decoded.length());
while( (i<lmax) && (s.charAt(i)==decoded.charAt(i))) {
i++;
}
//String sbad=s.substring(Math.max(i-2,0), Math.min(i+2,lmax));
char sbad = s.charAt(i);
String msg = "Cannot express character \'"+sbad+"\'(0x"+Integer.toHexString(sbad) +") with "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (fControlEncoding==null || fControlEncoding.equals(defaultEncoding)) {
msg += "default encoding \""+defaultEncoding+"\". "; //$NON-NLS-1$ //$NON-NLS-2$
} else {
msg += "encoding \""+fControlEncoding+"\" over local default encoding \""+defaultEncoding+"\". "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
msg += "Please specify a different encoding in host properties."; //$NON-NLS-1$
throw new UnsupportedEncodingException(msg);
}
//Quote ? and * characters for Jsch
//FIXME bug 204705: this does not work properly for commands like ls(), due to a Jsch bug
return quoteForJsch(recoded);
} catch(UnsupportedEncodingException e) {
try {
//SystemMessage msg = new SystemMessage("RSE","F","9999",'E',e.getMessage(),"Please specify a different encoding in host properties."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
SystemMessage msg = new SystemMessage("RSE","F","9999",'E',e.getMessage(),""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
//throw new RemoteFileIOException(new SystemMessageException(msg));
throw new SystemMessageException(msg);
} catch(IndicatorException ind) {
throw makeSystemMessageException(e);
}
}
}
/**
* Decode String (sftp result) with requested user encoding, in case it differs from Platform default encoding.
* @param s String to decode
* @return decoded String
* @throws SystemMessageException
*/
protected String decode(String s) throws SystemMessageException {
if (fControlEncoding==null) {
return s;
} else if (fControlEncoding.equals(defaultEncoding)) {
return s;
}
try {
byte[] bytes = s.getBytes(); //original bytes sent by SSH
return new String(bytes, fControlEncoding);
} catch(UnsupportedEncodingException e) {
throw makeSystemMessageException(e);
}
}
/** Regular expression pattern to know when Jsch needs quoting. */
private static Pattern quoteForJschPattern = Pattern.compile("[*?\\\\]"); //$NON-NLS-1$
/**
* Quote characters '?' and '*' for Jsch because it would otherwise
* use them as patterns for globbing.
* @param s String to enquote
* @return String with '?' and '*' quoted.
*/
protected String quoteForJsch(String s) {
if(quoteForJschPattern.matcher(s).find()) {
StringBuffer buf = new StringBuffer(s.length()+8);
for(int i=0; i<s.length(); i++) {
char c = s.charAt(i);
// if(c=='?' || c=='*' || c=='\\') {
if(c=='?' || c=='*') {
buf.append('\\');
}
buf.append(c);
}
s = buf.toString();
}
return s;
}
public String getName() {
return SshServiceResources.SftpFileService_Name;
}
@ -164,7 +288,8 @@ public class SftpFileService extends AbstractFileService implements IFileService
Channel channel=session.openChannel("sftp"); //$NON-NLS-1$
channel.connect();
fChannelSftp=(ChannelSftp)channel;
fUserHome = fChannelSftp.pwd();
setControlEncoding(fSessionProvider.getControlEncoding());
fUserHome = decode(fChannelSftp.pwd());
Activator.trace("SftpFileService.connected"); //$NON-NLS-1$
} catch(Exception e) {
Activator.trace("SftpFileService.connecting failed: "+e.toString()); //$NON-NLS-1$
@ -256,7 +381,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
SftpATTRS attrs = null;
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) {
try {
attrs = getChannel("SftpFileService.getFile: "+fileName).stat(remoteParent+'/'+fileName); //$NON-NLS-1$
attrs = getChannel("SftpFileService.getFile: "+fileName).stat(recodeSafe(remoteParent+'/'+fileName)); //$NON-NLS-1$
Activator.trace("SftpFileService.getFile <--"); //$NON-NLS-1$
node = makeHostFile(remoteParent, fileName, attrs);
} catch(Exception e) {
@ -304,12 +429,12 @@ public class SftpFileService extends AbstractFileService implements IFileService
List results = new ArrayList();
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) {
try {
Vector vv=getChannel("SftpFileService.internalFetch: "+parentPath).ls(parentPath); //$NON-NLS-1$
Vector vv=getChannel("SftpFileService.internalFetch: "+parentPath).ls(recodeSafe(parentPath)); //$NON-NLS-1$
for(int ii=0; ii<vv.size(); ii++) {
Object obj=vv.elementAt(ii);
if(obj instanceof ChannelSftp.LsEntry){
ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry)obj;
String fileName = lsEntry.getFilename();
String fileName = decode(lsEntry.getFilename());
if (".".equals(fileName) || "..".equals(fileName)) { //$NON-NLS-1$ //$NON-NLS-2$
//don't show the trivial names
continue;
@ -353,15 +478,15 @@ public class SftpFileService extends AbstractFileService implements IFileService
// try {
// //Note: readlink() is supported only with jsch-0.1.29 or higher.
// //By catching the exception we remain backward compatible.
// linkTarget=getChannel("makeHostFile.readlink").readlink(node.getAbsolutePath()); //$NON-NLS-1$
// linkTarget=getChannel("makeHostFile.readlink").readlink(recode(node.getAbsolutePath())); //$NON-NLS-1$
// //TODO: Classify the type of resource linked to as file, folder or broken link
// } catch(Exception e) {}
//check if the link points to a directory
try {
getChannel("makeHostFile.chdir").cd(parentPath+'/'+fileName); //$NON-NLS-1$
linkTarget=getChannel("makeHostFile.chdir").pwd(); //$NON-NLS-1$
getChannel("makeHostFile.chdir").cd(recode(parentPath+'/'+fileName)); //$NON-NLS-1$
linkTarget=decode(getChannel("makeHostFile.chdir").pwd()); //$NON-NLS-1$
if (linkTarget!=null && !linkTarget.equals(parentPath+'/'+fileName)) {
attrsTarget = getChannel("SftpFileService.getFile").stat(linkTarget); //$NON-NLS-1$
attrsTarget = getChannel("SftpFileService.getFile").stat(recode(linkTarget)); //$NON-NLS-1$
} else {
linkTarget=null;
}
@ -421,6 +546,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
}
dst += remoteFile;
}
dst = recodeSafe(dst);
getChannel("SftpFileService.upload "+remoteFile); //check the session is healthy //$NON-NLS-1$
channel=(ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$
channel.connect();
@ -439,7 +565,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
if (attr.getSize() != localFile.length()) {
//Error: file truncated? - Inform the user!!
//TODO test if this works
throw makeSystemMessageException(new IOException(NLS.bind(SshServiceResources.SftpFileService_Error_upload_size,dst)));
throw makeSystemMessageException(new IOException(NLS.bind(SshServiceResources.SftpFileService_Error_upload_size,remoteFile)));
//return false;
}
}
@ -532,7 +658,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
//localFile.createNewFile();
}
//TODO Ascii/binary?
String remotePath = remoteParent+'/'+remoteFile;
String remotePath = recode(remoteParent+'/'+remoteFile);
int mode=ChannelSftp.OVERWRITE;
MyProgressMonitor sftpMonitor = new MyProgressMonitor(monitor);
getChannel("SftpFileService.download "+remoteFile); //check the session is healthy //$NON-NLS-1$
@ -550,7 +676,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
if (attr.getSize() != localFile.length()) {
//Error: file truncated? - Inform the user!!
//TODO test if this works
throw makeSystemMessageException(new IOException(NLS.bind(SshServiceResources.SftpFileService_Error_download_size,remotePath)));
throw makeSystemMessageException(new IOException(NLS.bind(SshServiceResources.SftpFileService_Error_download_size,remoteFile)));
//return false;
}
}
@ -603,7 +729,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
IHostFile result = null;
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) {
try {
String fullPath = remoteParent + '/' + fileName;
String fullPath = recodeSafe(remoteParent + '/' + fileName);
OutputStream os = getChannel("SftpFileService.createFile").put(fullPath); //$NON-NLS-1$
//TODO workaround bug 153118: write a single space
//since jsch hangs when trying to close the stream without writing
@ -629,7 +755,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
IHostFile result = null;
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) {
try {
String fullPath = remoteParent + '/' + folderName;
String fullPath = recodeSafe(remoteParent + '/' + folderName);
getChannel("SftpFileService.createFolder").mkdir(fullPath); //$NON-NLS-1$
SftpATTRS attrs = getChannel("SftpFileService.createFolder.stat").stat(fullPath); //$NON-NLS-1$
result = makeHostFile(remoteParent, folderName, attrs);
@ -652,7 +778,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
Activator.trace("SftpFileService.delete.waitForLock"); //$NON-NLS-1$
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) {
try {
String fullPath = remoteParent + '/' + fileName;
String fullPath = recodeSafe(remoteParent + '/' + fileName);
SftpATTRS attrs = null;
try {
attrs = getChannel("SftpFileService.delete").lstat(fullPath); //$NON-NLS-1$
@ -705,7 +831,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
try {
String fullPathOld = remoteParent + '/' + oldName;
String fullPathNew = remoteParent + '/' + newName;
getChannel("SftpFileService.rename").rename(fullPathOld, fullPathNew); //$NON-NLS-1$
getChannel("SftpFileService.rename").rename(recode(fullPathOld), recodeSafe(fullPathNew)); //$NON-NLS-1$
ok=true;
Activator.trace("SftpFileService.rename ok"); //$NON-NLS-1$
} catch (Exception e) {
@ -794,8 +920,8 @@ public class SftpFileService extends AbstractFileService implements IFileService
// TODO Interpret some error messages like "command not found" (use ren instead of mv on windows)
// TODO mimic by copy if the remote does not support copying between file systems?
Activator.trace("SftpFileService.move "+srcName); //$NON-NLS-1$
String fullPathOld = PathUtility.enQuoteUnix(srcParent + '/' + srcName);
String fullPathNew = PathUtility.enQuoteUnix(tgtParent + '/' + tgtName);
String fullPathOld = PathUtility.enQuoteUnix(recode(srcParent + '/' + srcName));
String fullPathNew = PathUtility.enQuoteUnix(recodeSafe(tgtParent + '/' + tgtName));
int rv = runCommand("mv "+fullPathOld+' '+fullPathNew, monitor); //$NON-NLS-1$
return (rv==0);
}
@ -805,8 +931,8 @@ public class SftpFileService extends AbstractFileService implements IFileService
// TODO check if newer versions of sftp support copy directly
// TODO Interpret some error messages like "command not found" (use (x)copy instead of cp on windows)
Activator.trace("SftpFileService.copy "+srcName); //$NON-NLS-1$
String fullPathOld = PathUtility.enQuoteUnix(srcParent + '/' + srcName);
String fullPathNew = PathUtility.enQuoteUnix(tgtParent + '/' + tgtName);
String fullPathOld = PathUtility.enQuoteUnix(recode(srcParent + '/' + srcName));
String fullPathNew = PathUtility.enQuoteUnix(recodeSafe(tgtParent + '/' + tgtName));
int rv = runCommand("cp -Rp "+fullPathOld+' '+fullPathNew, monitor); //$NON-NLS-1$
return (rv==0);
}
@ -852,7 +978,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) {
try {
String path = parent + '/' + name;
getChannel("SftpFileService.setLastModified").setMtime(path, (int)(timestamp/1000)); //$NON-NLS-1$
getChannel("SftpFileService.setLastModified").setMtime(recode(path), (int)(timestamp/1000)); //$NON-NLS-1$
ok=true;
Activator.trace("SftpFileService.setLastModified ok"); //$NON-NLS-1$
} catch (Exception e) {
@ -871,7 +997,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) {
try {
String path = parent + '/' + name;
SftpATTRS attr = getChannel("SftpFileService.setReadOnly").stat(path); //$NON-NLS-1$
SftpATTRS attr = getChannel("SftpFileService.setReadOnly").stat(recode(path)); //$NON-NLS-1$
int permOld = attr.getPermissions();
int permNew = permOld;
if (readOnly) {
@ -882,7 +1008,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
if (permNew != permOld) {
//getChannel("SftpFileService.setReadOnly").chmod(permNew, path); //$NON-NLS-1$
attr.setPERMISSIONS(permNew);
getChannel("SftpFileService.setReadOnly").setStat(path, attr); //$NON-NLS-1$
getChannel("SftpFileService.setReadOnly").setStat(recode(path), attr); //$NON-NLS-1$
ok=true;
Activator.trace("SftpFileService.setReadOnly ok"); //$NON-NLS-1$
} else {
@ -909,7 +1035,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
InputStream stream = null;
try {
String remotePath = remoteParent + '/' + remoteFile;
String remotePath = recode(remoteParent + '/' + remoteFile);
getChannel("SftpFileService.getInputStream " + remoteFile); //check the session is healthy //$NON-NLS-1$
ChannelSftp channel = (ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$
channel.connect();
@ -954,7 +1080,7 @@ public class SftpFileService extends AbstractFileService implements IFileService
getChannel("SftpFileService.getOutputStream " + remoteFile); //check the session is healthy //$NON-NLS-1$
ChannelSftp channel = (ChannelSftp)fSessionProvider.getSession().openChannel("sftp"); //$NON-NLS-1$
channel.connect();
stream = new SftpBufferedOutputStream(channel.put(dst, sftpMonitor, mode), channel);
stream = new SftpBufferedOutputStream(channel.put(recodeSafe(dst), sftpMonitor, mode), channel);
Activator.trace("SftpFileService.getOutputStream " + remoteFile + " ok"); //$NON-NLS-1$ //$NON-NLS-2$
}
catch (Exception e) {
@ -966,4 +1092,4 @@ public class SftpFileService extends AbstractFileService implements IFileService
}
return stream;
}
}
}

View file

@ -21,6 +21,7 @@
* David Dykstal (IBM) - added RESID_FTP_SETTINGS_LABEL
* David McKnight (IBM) - [196632] [ftp] Passive mode setting does not work
* Martin Oberhuber (Wind River) - [204669] Fix ftp path concatenation on systems using backslash separator
* Martin Oberhuber (Wind River) - [203500] Support encodings for FTP paths
********************************************************************************/
package org.eclipse.rse.internal.subsystems.files.ftp.connectorservice;
@ -52,6 +53,9 @@ public class FTPConnectorService extends StandardConnectorService
{
protected FTPService _ftpService;
/** Indicates the default string encoding on this platform */
private static String _defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding();
public FTPConnectorService(IHost host, int port)
{
super(FTPSubsystemResources.RESID_FTP_CONNECTORSERVICE_NAME,FTPSubsystemResources.RESID_FTP_CONNECTORSERVICE_DESCRIPTION, host, port);
@ -105,11 +109,17 @@ public class FTPConnectorService extends StandardConnectorService
_ftpService.setLoggingStream(getLoggingStream(info.getHostname(),getPort()));
_ftpService.setPropertySet(propertySet);
_ftpService.setFTPClientConfigFactory(FTPClientConfigFactory.getParserFactory());
//TODO this code should be in IHost
String encoding = getHost().getDefaultEncoding(false);
if (encoding==null) encoding = getHost().getDefaultEncoding(true);
//TODO Here, we set the FTP default encoding same as the local encoding.
//Another alternative would be to set ISO-8859-1, which is the
//default-default internal to FTP, or keep it "null".
if (encoding==null) encoding = _defaultEncoding;
//</code to be in IHost>
_ftpService.setControlEncoding(encoding);
_ftpService.connect();
}
/* (non-Javadoc)
@ -163,4 +173,4 @@ public class FTPConnectorService extends StandardConnectorService
return (_ftpService != null && _ftpService.isConnected());
}
}
}