Lines 14-19
Link Here
|
14 |
* Martin Oberhuber (Wind River) - [199548] Avoid touching files on setReadOnly() if unnecessary |
14 |
* Martin Oberhuber (Wind River) - [199548] Avoid touching files on setReadOnly() if unnecessary |
15 |
* Benjamin Muskalla (b.muskalla@gmx.net) - [174690][ssh] cannot delete symbolic links on remote systems |
15 |
* Benjamin Muskalla (b.muskalla@gmx.net) - [174690][ssh] cannot delete symbolic links on remote systems |
16 |
* Martin Oberhuber (Wind River) - [203490] Fix NPE in SftpService.getUserHome() |
16 |
* Martin Oberhuber (Wind River) - [203490] Fix NPE in SftpService.getUserHome() |
|
|
17 |
* Martin Oberhuber (Wind River) - [203500] Support encodings for SSH Sftp paths |
17 |
*******************************************************************************/ |
18 |
*******************************************************************************/ |
18 |
|
19 |
|
19 |
package org.eclipse.rse.internal.services.ssh.files; |
20 |
package org.eclipse.rse.internal.services.ssh.files; |
Lines 26-31
Link Here
|
26 |
import java.io.IOException; |
27 |
import java.io.IOException; |
27 |
import java.io.InputStream; |
28 |
import java.io.InputStream; |
28 |
import java.io.OutputStream; |
29 |
import java.io.OutputStream; |
|
|
30 |
import java.io.UnsupportedEncodingException; |
29 |
import java.text.MessageFormat; |
31 |
import java.text.MessageFormat; |
30 |
import java.util.ArrayList; |
32 |
import java.util.ArrayList; |
31 |
import java.util.List; |
33 |
import java.util.List; |
Lines 139-145
Link Here
|
139 |
private ChannelSftp fChannelSftp; |
141 |
private ChannelSftp fChannelSftp; |
140 |
private String fUserHome; |
142 |
private String fUserHome; |
141 |
private Mutex fDirChannelMutex = new Mutex(); |
143 |
private Mutex fDirChannelMutex = new Mutex(); |
142 |
private long fDirChannelTimeout = 5000; //max.5 seconds to obtain dir channel |
144 |
private long fDirChannelTimeout = 5000; //max.5 seconds to obtain dir channel |
|
|
145 |
/** Client-desired encoding for file and path names */ |
146 |
private String fControlEncoding = null; |
147 |
/** Indicates the default string encoding on this platform */ |
148 |
private static String defaultEncoding = new java.io.InputStreamReader(new java.io.ByteArrayInputStream(new byte[0])).getEncoding(); |
143 |
|
149 |
|
144 |
// public SftpFileService(SshConnectorService conn) { |
150 |
// public SftpFileService(SshConnectorService conn) { |
145 |
// fConnector = conn; |
151 |
// fConnector = conn; |
Lines 149-154
Link Here
|
149 |
fSessionProvider = sessionProvider; |
155 |
fSessionProvider = sessionProvider; |
150 |
} |
156 |
} |
151 |
|
157 |
|
|
|
158 |
public void setControlEncoding(String encoding) { |
159 |
fControlEncoding = encoding; |
160 |
} |
161 |
|
162 |
/** |
163 |
* Encode String with requested user encoding, in case it differs from Platform default encoding. |
164 |
* @param s String to encode |
165 |
* @return encoded String |
166 |
* @throws SystemMessageException |
167 |
*/ |
168 |
protected String recode(String s) throws SystemMessageException { |
169 |
if (fControlEncoding==null) { |
170 |
return s; |
171 |
} else if (fControlEncoding.equals(defaultEncoding)) { |
172 |
return s; |
173 |
} |
174 |
try { |
175 |
byte[] bytes = s.getBytes(fControlEncoding); |
176 |
return new String(bytes); |
177 |
} catch(UnsupportedEncodingException e) { |
178 |
throw makeSystemMessageException(e); |
179 |
} |
180 |
} |
181 |
|
182 |
/** |
183 |
* Decode String (sftp result) with requested user encoding, in case it differs from Platform default encoding. |
184 |
* @param s String to decode |
185 |
* @return decoded String |
186 |
* @throws SystemMessageException |
187 |
*/ |
188 |
protected String decode(String s) throws SystemMessageException { |
189 |
if (fControlEncoding==null) { |
190 |
return s; |
191 |
} else if (fControlEncoding.equals(defaultEncoding)) { |
192 |
return s; |
193 |
} |
194 |
try { |
195 |
byte[] bytes = s.getBytes(); //original bytes sent by SSH |
196 |
return new String(bytes, fControlEncoding); |
197 |
} catch(UnsupportedEncodingException e) { |
198 |
throw makeSystemMessageException(e); |
199 |
} |
200 |
} |
201 |
|
152 |
public String getName() { |
202 |
public String getName() { |
153 |
return SshServiceResources.SftpFileService_Name; |
203 |
return SshServiceResources.SftpFileService_Name; |
154 |
} |
204 |
} |
Lines 164-170
Link Here
|
164 |
Channel channel=session.openChannel("sftp"); //$NON-NLS-1$ |
214 |
Channel channel=session.openChannel("sftp"); //$NON-NLS-1$ |
165 |
channel.connect(); |
215 |
channel.connect(); |
166 |
fChannelSftp=(ChannelSftp)channel; |
216 |
fChannelSftp=(ChannelSftp)channel; |
167 |
fUserHome = fChannelSftp.pwd(); |
217 |
setControlEncoding(fSessionProvider.getControlEncoding()); |
|
|
218 |
fUserHome = decode(fChannelSftp.pwd()); |
168 |
Activator.trace("SftpFileService.connected"); //$NON-NLS-1$ |
219 |
Activator.trace("SftpFileService.connected"); //$NON-NLS-1$ |
169 |
} catch(Exception e) { |
220 |
} catch(Exception e) { |
170 |
Activator.trace("SftpFileService.connecting failed: "+e.toString()); //$NON-NLS-1$ |
221 |
Activator.trace("SftpFileService.connecting failed: "+e.toString()); //$NON-NLS-1$ |
Lines 256-262
Link Here
|
256 |
SftpATTRS attrs = null; |
307 |
SftpATTRS attrs = null; |
257 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
308 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
258 |
try { |
309 |
try { |
259 |
attrs = getChannel("SftpFileService.getFile: "+fileName).stat(remoteParent+'/'+fileName); //$NON-NLS-1$ |
310 |
attrs = getChannel("SftpFileService.getFile: "+fileName).stat(recode(remoteParent+'/'+fileName)); //$NON-NLS-1$ |
260 |
Activator.trace("SftpFileService.getFile <--"); //$NON-NLS-1$ |
311 |
Activator.trace("SftpFileService.getFile <--"); //$NON-NLS-1$ |
261 |
node = makeHostFile(remoteParent, fileName, attrs); |
312 |
node = makeHostFile(remoteParent, fileName, attrs); |
262 |
} catch(Exception e) { |
313 |
} catch(Exception e) { |
Lines 304-315
Link Here
|
304 |
List results = new ArrayList(); |
355 |
List results = new ArrayList(); |
305 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
356 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
306 |
try { |
357 |
try { |
307 |
Vector vv=getChannel("SftpFileService.internalFetch: "+parentPath).ls(parentPath); //$NON-NLS-1$ |
358 |
Vector vv=getChannel("SftpFileService.internalFetch: "+parentPath).ls(recode(parentPath)); //$NON-NLS-1$ |
308 |
for(int ii=0; ii<vv.size(); ii++) { |
359 |
for(int ii=0; ii<vv.size(); ii++) { |
309 |
Object obj=vv.elementAt(ii); |
360 |
Object obj=vv.elementAt(ii); |
310 |
if(obj instanceof ChannelSftp.LsEntry){ |
361 |
if(obj instanceof ChannelSftp.LsEntry){ |
311 |
ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry)obj; |
362 |
ChannelSftp.LsEntry lsEntry = (ChannelSftp.LsEntry)obj; |
312 |
String fileName = lsEntry.getFilename(); |
363 |
String fileName = decode(lsEntry.getFilename()); |
313 |
if (".".equals(fileName) || "..".equals(fileName)) { //$NON-NLS-1$ //$NON-NLS-2$ |
364 |
if (".".equals(fileName) || "..".equals(fileName)) { //$NON-NLS-1$ //$NON-NLS-2$ |
314 |
//don't show the trivial names |
365 |
//don't show the trivial names |
315 |
continue; |
366 |
continue; |
Lines 353-367
Link Here
|
353 |
// try { |
404 |
// try { |
354 |
// //Note: readlink() is supported only with jsch-0.1.29 or higher. |
405 |
// //Note: readlink() is supported only with jsch-0.1.29 or higher. |
355 |
// //By catching the exception we remain backward compatible. |
406 |
// //By catching the exception we remain backward compatible. |
356 |
// linkTarget=getChannel("makeHostFile.readlink").readlink(node.getAbsolutePath()); //$NON-NLS-1$ |
407 |
// linkTarget=getChannel("makeHostFile.readlink").readlink(recode(node.getAbsolutePath())); //$NON-NLS-1$ |
357 |
// //TODO: Classify the type of resource linked to as file, folder or broken link |
408 |
// //TODO: Classify the type of resource linked to as file, folder or broken link |
358 |
// } catch(Exception e) {} |
409 |
// } catch(Exception e) {} |
359 |
//check if the link points to a directory |
410 |
//check if the link points to a directory |
360 |
try { |
411 |
try { |
361 |
getChannel("makeHostFile.chdir").cd(parentPath+'/'+fileName); //$NON-NLS-1$ |
412 |
getChannel("makeHostFile.chdir").cd(recode(parentPath+'/'+fileName)); //$NON-NLS-1$ |
362 |
linkTarget=getChannel("makeHostFile.chdir").pwd(); //$NON-NLS-1$ |
413 |
linkTarget=decode(getChannel("makeHostFile.chdir").pwd()); //$NON-NLS-1$ |
363 |
if (linkTarget!=null && !linkTarget.equals(parentPath+'/'+fileName)) { |
414 |
if (linkTarget!=null && !linkTarget.equals(parentPath+'/'+fileName)) { |
364 |
attrsTarget = getChannel("SftpFileService.getFile").stat(linkTarget); //$NON-NLS-1$ |
415 |
attrsTarget = getChannel("SftpFileService.getFile").stat(recode(linkTarget)); //$NON-NLS-1$ |
365 |
} else { |
416 |
} else { |
366 |
linkTarget=null; |
417 |
linkTarget=null; |
367 |
} |
418 |
} |
Lines 601-612
Link Here
|
601 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
652 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
602 |
try { |
653 |
try { |
603 |
String fullPath = remoteParent + '/' + fileName; |
654 |
String fullPath = remoteParent + '/' + fileName; |
604 |
OutputStream os = getChannel("SftpFileService.createFile").put(fullPath); //$NON-NLS-1$ |
655 |
OutputStream os = getChannel("SftpFileService.createFile").put(recode(fullPath)); //$NON-NLS-1$ |
605 |
//TODO workaround bug 153118: write a single space |
656 |
//TODO workaround bug 153118: write a single space |
606 |
//since jsch hangs when trying to close the stream without writing |
657 |
//since jsch hangs when trying to close the stream without writing |
607 |
os.write(32); |
658 |
os.write(32); |
608 |
os.close(); |
659 |
os.close(); |
609 |
SftpATTRS attrs = getChannel("SftpFileService.createFile.stat").stat(fullPath); //$NON-NLS-1$ |
660 |
SftpATTRS attrs = getChannel("SftpFileService.createFile.stat").stat(recode(fullPath)); //$NON-NLS-1$ |
610 |
result = makeHostFile(remoteParent, fileName, attrs); |
661 |
result = makeHostFile(remoteParent, fileName, attrs); |
611 |
Activator.trace("SftpFileService.createFile ok"); //$NON-NLS-1$ |
662 |
Activator.trace("SftpFileService.createFile ok"); //$NON-NLS-1$ |
612 |
} catch (Exception e) { |
663 |
} catch (Exception e) { |
Lines 627-634
Link Here
|
627 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
678 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
628 |
try { |
679 |
try { |
629 |
String fullPath = remoteParent + '/' + folderName; |
680 |
String fullPath = remoteParent + '/' + folderName; |
630 |
getChannel("SftpFileService.createFolder").mkdir(fullPath); //$NON-NLS-1$ |
681 |
getChannel("SftpFileService.createFolder").mkdir(recode(fullPath)); //$NON-NLS-1$ |
631 |
SftpATTRS attrs = getChannel("SftpFileService.createFolder.stat").stat(fullPath); //$NON-NLS-1$ |
682 |
SftpATTRS attrs = getChannel("SftpFileService.createFolder.stat").stat(recode(fullPath)); //$NON-NLS-1$ |
632 |
result = makeHostFile(remoteParent, folderName, attrs); |
683 |
result = makeHostFile(remoteParent, folderName, attrs); |
633 |
Activator.trace("SftpFileService.createFolder ok"); //$NON-NLS-1$ |
684 |
Activator.trace("SftpFileService.createFolder ok"); //$NON-NLS-1$ |
634 |
} catch (Exception e) { |
685 |
} catch (Exception e) { |
Lines 652-663
Link Here
|
652 |
String fullPath = remoteParent + '/' + fileName; |
703 |
String fullPath = remoteParent + '/' + fileName; |
653 |
SftpATTRS attrs = null; |
704 |
SftpATTRS attrs = null; |
654 |
try { |
705 |
try { |
655 |
attrs = getChannel("SftpFileService.delete").lstat(fullPath); //$NON-NLS-1$ |
706 |
attrs = getChannel("SftpFileService.delete").lstat(recode(fullPath)); //$NON-NLS-1$ |
656 |
} catch (SftpException e) { |
707 |
} catch (SftpException e) { |
657 |
//bug 154419: test for dangling symbolic link |
708 |
//bug 154419: test for dangling symbolic link |
658 |
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { |
709 |
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { |
659 |
//simply try to delete --> if it really doesnt exist, this will throw an exception |
710 |
//simply try to delete --> if it really doesnt exist, this will throw an exception |
660 |
getChannel("SftpFileService.delete.rm").rm(fullPath); //$NON-NLS-1$ |
711 |
getChannel("SftpFileService.delete.rm").rm(recode(fullPath)); //$NON-NLS-1$ |
661 |
} else { |
712 |
} else { |
662 |
throw e; |
713 |
throw e; |
663 |
} |
714 |
} |
Lines 667-673
Link Here
|
667 |
ok=true; |
718 |
ok=true; |
668 |
} else if (attrs.isDir()) { |
719 |
} else if (attrs.isDir()) { |
669 |
try { |
720 |
try { |
670 |
getChannel("SftpFileService.delete.rmdir").rmdir(fullPath); //$NON-NLS-1$ |
721 |
getChannel("SftpFileService.delete.rmdir").rmdir(recode(fullPath)); //$NON-NLS-1$ |
671 |
ok=true; |
722 |
ok=true; |
672 |
} catch(SftpException e) { |
723 |
} catch(SftpException e) { |
673 |
if(e.id==ChannelSftp.SSH_FX_FAILURE) { |
724 |
if(e.id==ChannelSftp.SSH_FX_FAILURE) { |
Lines 681-687
Link Here
|
681 |
} |
732 |
} |
682 |
} |
733 |
} |
683 |
} else { |
734 |
} else { |
684 |
getChannel("SftpFileService.delete.rm").rm(fullPath); //$NON-NLS-1$ |
735 |
getChannel("SftpFileService.delete.rm").rm(recode(fullPath)); //$NON-NLS-1$ |
685 |
ok=true; |
736 |
ok=true; |
686 |
} |
737 |
} |
687 |
Activator.trace("SftpFileService.delete ok"); //$NON-NLS-1$ |
738 |
Activator.trace("SftpFileService.delete ok"); //$NON-NLS-1$ |
Lines 702-708
Link Here
|
702 |
try { |
753 |
try { |
703 |
String fullPathOld = remoteParent + '/' + oldName; |
754 |
String fullPathOld = remoteParent + '/' + oldName; |
704 |
String fullPathNew = remoteParent + '/' + newName; |
755 |
String fullPathNew = remoteParent + '/' + newName; |
705 |
getChannel("SftpFileService.rename").rename(fullPathOld, fullPathNew); //$NON-NLS-1$ |
756 |
getChannel("SftpFileService.rename").rename(recode(fullPathOld), recode(fullPathNew)); //$NON-NLS-1$ |
706 |
ok=true; |
757 |
ok=true; |
707 |
Activator.trace("SftpFileService.rename ok"); //$NON-NLS-1$ |
758 |
Activator.trace("SftpFileService.rename ok"); //$NON-NLS-1$ |
708 |
} catch (Exception e) { |
759 |
} catch (Exception e) { |
Lines 849-855
Link Here
|
849 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
900 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
850 |
try { |
901 |
try { |
851 |
String path = parent + '/' + name; |
902 |
String path = parent + '/' + name; |
852 |
getChannel("SftpFileService.setLastModified").setMtime(path, (int)(timestamp/1000)); //$NON-NLS-1$ |
903 |
getChannel("SftpFileService.setLastModified").setMtime(recode(path), (int)(timestamp/1000)); //$NON-NLS-1$ |
853 |
ok=true; |
904 |
ok=true; |
854 |
Activator.trace("SftpFileService.setLastModified ok"); //$NON-NLS-1$ |
905 |
Activator.trace("SftpFileService.setLastModified ok"); //$NON-NLS-1$ |
855 |
} catch (Exception e) { |
906 |
} catch (Exception e) { |
Lines 868-874
Link Here
|
868 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
919 |
if (fDirChannelMutex.waitForLock(monitor, fDirChannelTimeout)) { |
869 |
try { |
920 |
try { |
870 |
String path = parent + '/' + name; |
921 |
String path = parent + '/' + name; |
871 |
SftpATTRS attr = getChannel("SftpFileService.setReadOnly").stat(path); //$NON-NLS-1$ |
922 |
SftpATTRS attr = getChannel("SftpFileService.setReadOnly").stat(recode(path)); //$NON-NLS-1$ |
872 |
int permOld = attr.getPermissions(); |
923 |
int permOld = attr.getPermissions(); |
873 |
int permNew = permOld; |
924 |
int permNew = permOld; |
874 |
if (readOnly) { |
925 |
if (readOnly) { |
Lines 879-885
Link Here
|
879 |
if (permNew != permOld) { |
930 |
if (permNew != permOld) { |
880 |
//getChannel("SftpFileService.setReadOnly").chmod(permNew, path); //$NON-NLS-1$ |
931 |
//getChannel("SftpFileService.setReadOnly").chmod(permNew, path); //$NON-NLS-1$ |
881 |
attr.setPERMISSIONS(permNew); |
932 |
attr.setPERMISSIONS(permNew); |
882 |
getChannel("SftpFileService.setReadOnly").setStat(path, attr); //$NON-NLS-1$ |
933 |
getChannel("SftpFileService.setReadOnly").setStat(recode(path), attr); //$NON-NLS-1$ |
883 |
ok=true; |
934 |
ok=true; |
884 |
Activator.trace("SftpFileService.setReadOnly ok"); //$NON-NLS-1$ |
935 |
Activator.trace("SftpFileService.setReadOnly ok"); //$NON-NLS-1$ |
885 |
} else { |
936 |
} else { |