Skip to content

Commit 4ae62c9

Browse files
artembilanspring-builds
authored andcommitted
GH-10854: Fix remote file long name for SFTP (#10855)
* GH-10854: Fix remote file long name for SFTP Fixes: #10854 The logic in the framework is to use a long file name (preferably, the whole path) for metadata key. This was implemented via: #10162 Fix `SftpSession.doList()` not consulting with whatever `SftpClient` returns but rather using a remote dir as long name prefix unconditionally. This would make it exactly what we claim in docs and consistent with FTP * Remove blank line Signed-off-by: Artem Bilan <artem.bilan@broadcom.com> --------- Signed-off-by: Artem Bilan <artem.bilan@broadcom.com> (cherry picked from commit 0c24a46)
1 parent 1a4ffaf commit 4ae62c9

File tree

3 files changed

+17
-14
lines changed

3 files changed

+17
-14
lines changed

spring-integration-sftp/src/main/java/org/springframework/integration/sftp/session/SftpSession.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,12 @@ public Stream<SftpClient.DirEntry> doList(@Nullable String path) throws IOExcept
126126
}
127127
}
128128
remoteDir = normalizePath(remoteDir);
129-
String remoteDirToUse = remoteDir;
130-
return StreamSupport.stream(this.sftpClient.readDir(remoteDirToUse).spliterator(), false)
129+
String longNameDirPrefix = remoteDir.endsWith("/") ? remoteDir : remoteDir + '/';
130+
return StreamSupport.stream(this.sftpClient.readDir(remoteDir).spliterator(), false)
131131
.filter((entry) -> !isPattern || PatternMatchUtils.simpleMatch(remoteFile, entry.getFilename()))
132132
.map((entry) -> {
133-
String longFilename = entry.getLongFilename();
134-
if (StringUtils.hasText(longFilename)) {
135-
return entry;
136-
}
137133
String filename = entry.getFilename();
138-
return new SftpClient.DirEntry(filename, remoteDirToUse + '/' + filename, entry.getAttributes());
134+
return new SftpClient.DirEntry(filename, longNameDirPrefix + filename, entry.getAttributes());
139135
});
140136
}
141137

spring-integration-sftp/src/test/java/org/springframework/integration/sftp/SftpTestSupport.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ public static SessionFactory<SftpClient.DirEntry> sessionFactory() {
8080
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(false);
8181
factory.setHost("localhost");
8282
factory.setPort(port);
83-
factory.setUser("foo");
84-
factory.setPassword("foo");
83+
factory.setUser("user");
84+
factory.setPassword("password");
8585
factory.setAllowUnknownKeys(true);
8686
CachingSessionFactory<SftpClient.DirEntry> cachingSessionFactory = new CachingSessionFactory<>(factory);
8787
cachingSessionFactory.setTestSession(true);

spring-integration-sftp/src/test/java/org/springframework/integration/sftp/session/SftpServerTests.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import org.apache.sshd.server.SshServer;
3636
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
3737
import org.apache.sshd.sftp.client.SftpClient;
38+
import org.apache.sshd.sftp.client.SftpVersionSelector;
39+
import org.apache.sshd.sftp.common.SftpConstants;
3840
import org.apache.sshd.sftp.server.SftpSubsystemFactory;
3941
import org.junit.jupiter.api.Test;
4042

@@ -109,6 +111,8 @@ private void testKeyExchange(String pubKey, String privKey, String passphrase) t
109111
f.setPort(server.getPort());
110112
f.setUser("user");
111113
f.setAllowUnknownKeys(true);
114+
// See AbstractSftpClient.checkDirResponse() with the respective constant logic
115+
f.setSftpVersionSelector(SftpVersionSelector.fixedVersionSelector(SftpConstants.SFTP_V3));
112116
InputStream stream = new ClassPathResource(privKey).getInputStream();
113117
f.setPrivateKey(new ByteArrayResource(FileCopyUtils.copyToByteArray(stream)));
114118
f.setPrivateKeyPassphrase(passphrase);
@@ -159,13 +163,16 @@ protected void doTest(SshServer server, Session<SftpClient.DirEntry> session) th
159163
}
160164
}
161165

162-
session.write(new ByteArrayInputStream("foo".getBytes()), "bar");
166+
session.write(new ByteArrayInputStream("test data".getBytes()), "test_file");
163167
list = session.list(".");
164-
assertThat(list[1].getFilename()).isEqualTo("bar");
168+
assertThat(list[1].getFilename()).isEqualTo("test_file");
169+
// The root dir (.) becomes '/' after sftpClient.canonicalPath()
170+
// Plus with the SftpConstants.SFTP_V3 settings, we ensure here that SftpSession overrides file long name
171+
assertThat(list[1].getLongFilename()).isEqualTo("/test_file");
165172
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
166-
session.read("bar", outputStream);
167-
assertThat(new String(outputStream.toByteArray())).isEqualTo("foo");
168-
session.remove("bar");
173+
session.read("test_file", outputStream);
174+
assertThat(new String(outputStream.toByteArray())).isEqualTo("test data");
175+
session.remove("test_file");
169176
session.close();
170177
}
171178

0 commit comments

Comments
 (0)