Skip to content

Commit

Permalink
Add handling of plus sign (+) in path name
Browse files Browse the repository at this point in the history
With test cases, with test cases to prove TeamAmaze#2964 will work.

Fixes TeamAmaze#3560, fixes TeamAmaze#3636, fixes TeamAmaze#2964
  • Loading branch information
TranceLove committed Feb 4, 2023
1 parent de85f3f commit aaee4f8
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 34 deletions.
22 changes: 11 additions & 11 deletions app/src/main/java/com/amaze/filemanager/filesystem/HybridFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ public Long execute(@NonNull SFTPClient client) throws IOException {
*/
public String getPath() {
try {
return URLDecoder.decode(path, "UTF-8");
return URLDecoder.decode(path.replace("+", "%2b"), "UTF-8");
} catch (UnsupportedEncodingException | IllegalArgumentException e) {
LOG.warn("failed to decode path {}", path, e);
return path;
Expand Down Expand Up @@ -549,7 +549,7 @@ public String getParent(Context context) {
String thisPath = path;
if (thisPath.contains("%")) {
try {
thisPath = URLDecoder.decode(path, Charsets.UTF_8.name());
thisPath = URLDecoder.decode(getPath(), Charsets.UTF_8.name());
} catch (UnsupportedEncodingException ignored) {
}
}
Expand Down Expand Up @@ -936,20 +936,20 @@ public void forEachChildrenFile(Context context, boolean isRoot, OnFileFound onF
switch (mode) {
case SFTP:
NetCopyClientUtils.INSTANCE.<SSHClient, Boolean>execute(
new SFtpClientTemplate<Boolean>(path, false) {
new SFtpClientTemplate<Boolean>(getPath(), false) {
@Override
public Boolean execute(@NonNull SFTPClient client) {
try {
for (RemoteResourceInfo info :
client.ls(NetCopyClientUtils.INSTANCE.extractRemotePathFrom(path))) {
client.ls(NetCopyClientUtils.INSTANCE.extractRemotePathFrom(getPath()))) {
boolean isDirectory = false;
try {
isDirectory = SshClientUtils.isDirectory(client, info);
} catch (IOException ifBrokenSymlink) {
LOG.warn("IOException checking isDirectory(): " + info.getPath());
continue;
}
HybridFileParcelable f = new HybridFileParcelable(path, isDirectory, info);
HybridFileParcelable f = new HybridFileParcelable(getPath(), isDirectory, info);
onFileFound.onFileFound(f);
}
} catch (IOException e) {
Expand Down Expand Up @@ -986,18 +986,18 @@ public Boolean execute(@NonNull SFTPClient client) {
}
break;
case FTP:
String thisPath = NetCopyClientUtils.INSTANCE.extractRemotePathFrom(path);
String thisPath = NetCopyClientUtils.INSTANCE.extractRemotePathFrom(getPath());
FTPFile[] ftpFiles =
NetCopyClientUtils.INSTANCE.execute(
new FtpClientTemplate<FTPFile[]>(path, false) {
new FtpClientTemplate<FTPFile[]>(getPath(), false) {
public FTPFile[] executeWithFtpClient(@NonNull FTPClient ftpClient)
throws IOException {
ftpClient.changeWorkingDirectory(thisPath);
return ftpClient.listFiles();
}
});
for (FTPFile ftpFile : ftpFiles) {
onFileFound.onFileFound(new HybridFileParcelable(path, ftpFile));
onFileFound.onFileFound(new HybridFileParcelable(getPath(), ftpFile));
}
break;
case OTG:
Expand Down Expand Up @@ -1085,11 +1085,11 @@ public InputStream getInputStream(Context context) {
case SFTP:
inputStream =
SshClientUtils.execute(
new SFtpClientTemplate<InputStream>(path, false) {
new SFtpClientTemplate<InputStream>(getPath(), false) {
@Override
public InputStream execute(@NonNull final SFTPClient client) throws IOException {
final RemoteFile rf =
client.open(NetCopyClientUtils.INSTANCE.extractRemotePathFrom(path));
client.open(NetCopyClientUtils.INSTANCE.extractRemotePathFrom(getPath()));
return rf.new RemoteFileInputStream() {
@Override
public void close() throws IOException {
Expand All @@ -1115,7 +1115,7 @@ public void close() throws IOException {
case FTP:
inputStream =
NetCopyClientUtils.INSTANCE.execute(
new FtpClientTemplate<InputStream>(path, false) {
new FtpClientTemplate<InputStream>(getPath(), false) {
public InputStream executeWithFtpClient(@NonNull FTPClient ftpClient)
throws IOException {
String parent = getParent(AppConfig.getInstance());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ class FtpServiceAndroidFileSystemIntegrationTest {
Environment.DIRECTORY_DOWNLOADS,
Environment.DIRECTORY_DCIM,
Environment.DIRECTORY_DOCUMENTS,
"1/2/3/4/5/6/7"
"1/2/3/4/5/6/7",
"lost+found"
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,37 @@ package com.amaze.filemanager.filesystem.ssh

import android.os.Environment
import androidx.test.core.app.ApplicationProvider
import com.amaze.filemanager.application.AppConfig
import com.amaze.filemanager.fileoperations.filesystem.OpenMode
import com.amaze.filemanager.filesystem.HybridFile
import com.amaze.filemanager.filesystem.HybridFileParcelable
import com.amaze.filemanager.test.randomBytes
import com.amaze.filemanager.utils.OnFileFound
import org.awaitility.Awaitility.await
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Test
import java.io.ByteArrayInputStream
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.nio.file.Files
import java.nio.file.Paths

/**
* Test listing files on SSH server.
*/
@Suppress("StringLiteralDuplication")
class ListFilesOnSshdTest : AbstractSftpServerTest() {
class FilesOnSshdTest : AbstractSftpServerTest() {

/**
* Test list directories normally
*/
@Test
fun testNormalListDirs() {
for (s in arrayOf("sysroot", "srv", "var", "tmp", "bin", "lib", "usr")) {
for (s in arrayOf("sysroot", "srv", "var", "tmp", "bin", "lib", "usr", "sysroot+v2")) {
File(Environment.getExternalStorageDirectory(), s).mkdir()
}
assertTrue(performVerify())
Expand All @@ -59,26 +62,55 @@ class ListFilesOnSshdTest : AbstractSftpServerTest() {
* Test list directories and symbolic links
*/
@Test
@Throws(Exception::class)
fun testListDirsAndSymlinks() {
createNecessaryDirsForSymlinkRelatedTests()
assertTrue(performVerify())
}

@Throws(IOException::class)
/**
* Test listing directories and files with special characters. This includes colon signs, which
* is possible - even on Windows. See #2964
*/
@Test
fun testListFilesWithSpecialChars() {
createFilesAndDirectoriesWithSpecialChars()
performVerify2()
val file = HybridFile(
OpenMode.SFTP,
"ssh://$USERNAME:$encryptedPassword@$HOST:$serverPort/sysroot%2Bv2/test%2Bfile.bin"
)
val content = file.getInputStream(AppConfig.getInstance())?.readBytes()
assertNotNull(content)
assertTrue(true == content?.isNotEmpty())
}

private fun createNecessaryDirsForSymlinkRelatedTests() {
val sysroot = File(Environment.getExternalStorageDirectory(), "sysroot")
sysroot.mkdir()
for (s in arrayOf("srv", "var", "tmp")) {
val subdir = File(sysroot, s)
subdir.mkdir()
Files.createSymbolicLink(
Paths.get(File(Environment.getExternalStorageDirectory(), s).absolutePath),
Paths.get(subdir.absolutePath)
)
Environment.getExternalStorageDirectory().let { root ->
val sysroot = File(root, "sysroot")
sysroot.mkdir()
for (s in arrayOf("srv", "var", "tmp")) {
val subdir = File(sysroot, s)
subdir.mkdir()
Files.createSymbolicLink(
Paths.get(File(root, s).absolutePath),
Paths.get(subdir.absolutePath)
)
}
for (s in arrayOf("bin", "lib", "usr")) {
File(root, s).mkdir()
}
File(root, "sysroot+v2").mkdirs()
}
for (s in arrayOf("bin", "lib", "usr")) {
File(Environment.getExternalStorageDirectory(), s).mkdir()
}

private fun createFilesAndDirectoriesWithSpecialChars() {
File(Environment.getExternalStorageDirectory(), "sysroot+v2").let {
it.mkdirs()
File(it, "D:").run {
mkdirs()
File(this, "Users").mkdirs()
}
ByteArrayInputStream(randomBytes()).copyTo(FileOutputStream(File(it, "test+file.bin")))
}
}

Expand All @@ -98,10 +130,71 @@ class ListFilesOnSshdTest : AbstractSftpServerTest() {
}
}
)
await().until { result.size == 7 }
await().until { result.size == 8 }
assertThat<List<String>>(
result,
Matchers.hasItems("sysroot", "srv", "var", "tmp", "bin", "lib", "usr", "sysroot+v2")
)
return true
}

private fun performVerify2(): Boolean {
val result: MutableList<String> = ArrayList()
var file = HybridFile(
OpenMode.SFTP,
"ssh://$USERNAME:$encryptedPassword@$HOST:$serverPort/sysroot%2Bv2"
)
file.forEachChildrenFile(
ApplicationProvider.getApplicationContext(),
false,
object : OnFileFound {
override fun onFileFound(fileFound: HybridFileParcelable) {
result.add(fileFound.name)
}
}
)
await().until { result.size == 2 }
assertThat<List<String>>(
result,
Matchers.hasItems("test+file.bin", "D:")
)
result.clear()
file = HybridFile(
OpenMode.SFTP,
"ssh://$USERNAME:$encryptedPassword@$HOST:$serverPort/sysroot%2Bv2/D:"
)
file.forEachChildrenFile(
ApplicationProvider.getApplicationContext(),
false,
object : OnFileFound {
override fun onFileFound(fileFound: HybridFileParcelable) {
result.add(fileFound.name)
}
}
)
await().until { result.size == 1 }
assertThat<List<String>>(
result,
Matchers.hasItems("Users")
)
result.clear()
file = HybridFile(
OpenMode.SFTP,
"ssh://$USERNAME:$encryptedPassword@$HOST:$serverPort/sysroot%2Bv2/D%3A"
)
file.forEachChildrenFile(
ApplicationProvider.getApplicationContext(),
false,
object : OnFileFound {
override fun onFileFound(fileFound: HybridFileParcelable) {
result.add(fileFound.name)
}
}
)
await().until { result.size == 1 }
assertThat<List<String>>(
result,
Matchers.hasItems("sysroot", "srv", "var", "tmp", "bin", "lib", "usr")
Matchers.hasItems("Users")
)
return true
}
Expand Down Expand Up @@ -153,10 +246,10 @@ class ListFilesOnSshdTest : AbstractSftpServerTest() {
}
}
)
await().until { dirs.size == 7 }
await().until { dirs.size == 8 }
assertThat<List<String>>(
dirs,
Matchers.hasItems("sysroot", "srv", "var", "tmp", "bin", "lib", "usr")
Matchers.hasItems("sysroot", "srv", "var", "tmp", "bin", "lib", "usr", "sysroot+v2")
)
assertThat<List<String>>(
files,
Expand Down Expand Up @@ -236,10 +329,10 @@ class ListFilesOnSshdTest : AbstractSftpServerTest() {
}
}
)
await().until { result2.size == 7 }
await().until { result2.size == 8 }
assertThat<List<String>>(
result2,
Matchers.hasItems("sysroot", "srv", "var", "tmp", "bin", "lib", "usr")
Matchers.hasItems("sysroot", "srv", "var", "tmp", "bin", "lib", "usr", "sysroot+v2")
)
}
}

0 comments on commit aaee4f8

Please sign in to comment.