From c08cafc6125f53fcbcc8cc6d55fb6be8dfb429ea Mon Sep 17 00:00:00 2001 From: Chace Daniels Date: Wed, 21 May 2025 14:49:24 -0500 Subject: [PATCH 1/4] fix: encode special characters in file path --- pom.xml | 2 +- .../libs/ionfiletransferlib/IONFLTRController.kt | 4 ++-- .../helpers/IONFLTRFileHelper.kt | 14 +++++++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index ed90c4c..1506735 100644 --- a/pom.xml +++ b/pom.xml @@ -6,5 +6,5 @@ 4.0.0 io.ionic.libs ionfiletransfer-android - 0.0.1-dev-1 + 0.0.1-dev-2 \ No newline at end of file diff --git a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt index 4ab0584..af3c0fe 100644 --- a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt +++ b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt @@ -118,10 +118,10 @@ class IONFLTRController internal constructor( */ private fun prepareForDownload(options: IONFLTRDownloadOptions): Pair { // Validate inputs - inputsValidator.validateTransferInputs(options.url, options.filePath) + val normalizedFilePath = fileHelper.normalizeFilePath(options.filePath) + inputsValidator.validateTransferInputs(options.url, normalizedFilePath) // Create parent directories if needed - val normalizedFilePath = fileHelper.normalizeFilePath(options.filePath) val targetFile = File(normalizedFilePath) fileHelper.createParentDirectories(targetFile) diff --git a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt index cdcb012..3d3591d 100644 --- a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt +++ b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt @@ -12,6 +12,8 @@ import java.io.File import java.io.FileInputStream import java.io.InputStream import androidx.core.net.toUri +import java.net.URLEncoder +import java.nio.charset.StandardCharsets internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { /** @@ -23,7 +25,7 @@ internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { fun getFileToUploadInfo(filePath: String): FileToUploadInfo { return if (filePath.startsWith("content://")) { val uri = filePath.toUri() - val cursor = contentResolver.query(uri, null, null, null, null) + val cursor = contentResolver.query(uri, null, null, null, null) ?: throw IONFLTRException.FileDoesNotExist() cursor.use { val fileName = getNameForContentUri(cursor) @@ -45,16 +47,18 @@ internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { /** * Normalizes a file path by removing URI prefixes like "file://", "file:/", etc. + * and encodes special characters * * @param filePath The file path that might contain URI prefixes * @return Cleaned file path without URI prefixes */ fun normalizeFilePath(filePath: String): String { + val path = URLEncoder.encode(filePath, StandardCharsets.UTF_8.toString()) return when { - filePath.startsWith("file://") -> filePath.removePrefix("file://") - filePath.startsWith("file:/") -> filePath.removePrefix("file:/") - filePath.startsWith("file:") -> filePath.removePrefix("file:") - else -> filePath + path.startsWith("file://") -> path.removePrefix("file://") + path.startsWith("file:/") -> path.removePrefix("file:/") + path.startsWith("file:") -> path.removePrefix("file:") + else -> path } } From 1619e0433f4a35832a58fe2c346cf76934bb8619 Mon Sep 17 00:00:00 2001 From: Chace Daniels Date: Wed, 21 May 2025 15:59:33 -0500 Subject: [PATCH 2/4] fix: only encode uri when validating path --- pom.xml | 2 +- .../libs/ionfiletransferlib/IONFLTRController.kt | 4 ++-- .../ionfiletransferlib/helpers/IONFLTRFileHelper.kt | 13 +++++-------- .../helpers/IONFLTRInputsValidator.kt | 7 ++++++- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index 1506735..9b13cc0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,5 +6,5 @@ 4.0.0 io.ionic.libs ionfiletransfer-android - 0.0.1-dev-2 + 0.0.1-dev-3 \ No newline at end of file diff --git a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt index af3c0fe..4ab0584 100644 --- a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt +++ b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt @@ -118,10 +118,10 @@ class IONFLTRController internal constructor( */ private fun prepareForDownload(options: IONFLTRDownloadOptions): Pair { // Validate inputs - val normalizedFilePath = fileHelper.normalizeFilePath(options.filePath) - inputsValidator.validateTransferInputs(options.url, normalizedFilePath) + inputsValidator.validateTransferInputs(options.url, options.filePath) // Create parent directories if needed + val normalizedFilePath = fileHelper.normalizeFilePath(options.filePath) val targetFile = File(normalizedFilePath) fileHelper.createParentDirectories(targetFile) diff --git a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt index 3d3591d..53381fa 100644 --- a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt +++ b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt @@ -12,8 +12,6 @@ import java.io.File import java.io.FileInputStream import java.io.InputStream import androidx.core.net.toUri -import java.net.URLEncoder -import java.nio.charset.StandardCharsets internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { /** @@ -47,18 +45,17 @@ internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { /** * Normalizes a file path by removing URI prefixes like "file://", "file:/", etc. - * and encodes special characters + * * * @param filePath The file path that might contain URI prefixes * @return Cleaned file path without URI prefixes */ fun normalizeFilePath(filePath: String): String { - val path = URLEncoder.encode(filePath, StandardCharsets.UTF_8.toString()) return when { - path.startsWith("file://") -> path.removePrefix("file://") - path.startsWith("file:/") -> path.removePrefix("file:/") - path.startsWith("file:") -> path.removePrefix("file:") - else -> path + filePath.startsWith("file://") -> filePath.removePrefix("file://") + filePath.startsWith("file:/") -> filePath.removePrefix("file:/") + filePath.startsWith("file:") -> filePath.removePrefix("file:") + else -> filePath } } diff --git a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRInputsValidator.kt b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRInputsValidator.kt index 93faaa5..b73258b 100644 --- a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRInputsValidator.kt +++ b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRInputsValidator.kt @@ -5,6 +5,7 @@ import java.util.regex.Pattern import java.io.File import java.net.URI import java.net.URISyntaxException +import java.net.URLEncoder internal class IONFLTRInputsValidator { @@ -36,7 +37,11 @@ internal class IONFLTRInputsValidator { return try { val resolvedPath: String if (path.startsWith("file://")) { - val uri = URI(path) + val encodedPath = URLEncoder.encode( + path.replace("file://", ""), + Charsets.UTF_8.toString() + ).replace("+", "%20") + val uri = URI(encodedPath) if (uri.path == null) { return false } From 395ad7193196eed46ddcce8605b270084f445cd0 Mon Sep 17 00:00:00 2001 From: Chace Daniels Date: Wed, 21 May 2025 16:01:07 -0500 Subject: [PATCH 3/4] chore: cleanup whitespace --- .../ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt index 53381fa..cdcb012 100644 --- a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt +++ b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt @@ -23,7 +23,7 @@ internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { fun getFileToUploadInfo(filePath: String): FileToUploadInfo { return if (filePath.startsWith("content://")) { val uri = filePath.toUri() - val cursor = contentResolver.query(uri, null, null, null, null) + val cursor = contentResolver.query(uri, null, null, null, null) ?: throw IONFLTRException.FileDoesNotExist() cursor.use { val fileName = getNameForContentUri(cursor) @@ -46,7 +46,6 @@ internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { /** * Normalizes a file path by removing URI prefixes like "file://", "file:/", etc. * - * * @param filePath The file path that might contain URI prefixes * @return Cleaned file path without URI prefixes */ From 7de4435c3b43f73b11fe0eabd82d03b3df382cfa Mon Sep 17 00:00:00 2001 From: Chace Daniels Date: Thu, 22 May 2025 10:55:47 -0500 Subject: [PATCH 4/4] fix: use encoded uri for file path --- pom.xml | 2 +- .../ionfiletransferlib/IONFLTRController.kt | 7 ++++--- .../helpers/IONFLTRFileHelper.kt | 12 ++++++++++-- .../helpers/IONFLTRInputsValidator.kt | 17 ++--------------- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/pom.xml b/pom.xml index 9b13cc0..c9120b0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,5 +6,5 @@ 4.0.0 io.ionic.libs ionfiletransfer-android - 0.0.1-dev-3 + 0.0.1-dev-4 \ No newline at end of file diff --git a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt index 4ab0584..bd440f1 100644 --- a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt +++ b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/IONFLTRController.kt @@ -23,6 +23,7 @@ import java.io.BufferedOutputStream import java.io.File import java.io.FileOutputStream import java.net.HttpURLConnection +import java.net.URI /** * Entry point in IONFileTransferLib-Android @@ -118,11 +119,11 @@ class IONFLTRController internal constructor( */ private fun prepareForDownload(options: IONFLTRDownloadOptions): Pair { // Validate inputs - inputsValidator.validateTransferInputs(options.url, options.filePath) + val normalizedFilePath = fileHelper.normalizeFilePath(options.filePath) + inputsValidator.validateTransferInputs(options.url, normalizedFilePath) // Create parent directories if needed - val normalizedFilePath = fileHelper.normalizeFilePath(options.filePath) - val targetFile = File(normalizedFilePath) + val targetFile = File(URI(normalizedFilePath).path) fileHelper.createParentDirectories(targetFile) // Setup connection diff --git a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt index cdcb012..c83a83e 100644 --- a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt +++ b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRFileHelper.kt @@ -12,6 +12,9 @@ import java.io.File import java.io.FileInputStream import java.io.InputStream import androidx.core.net.toUri +import java.net.URI +import java.net.URLDecoder +import java.net.URLEncoder internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { /** @@ -35,7 +38,7 @@ internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { } } else { val cleanFilePath = normalizeFilePath(filePath) - val fileObject = File(cleanFilePath) + val fileObject = File(URI(cleanFilePath).path) if (!fileObject.exists()) { throw IONFLTRException.FileDoesNotExist() } @@ -50,12 +53,17 @@ internal class IONFLTRFileHelper(val contentResolver: ContentResolver) { * @return Cleaned file path without URI prefixes */ fun normalizeFilePath(filePath: String): String { - return when { + val path = when { filePath.startsWith("file://") -> filePath.removePrefix("file://") filePath.startsWith("file:/") -> filePath.removePrefix("file:/") filePath.startsWith("file:") -> filePath.removePrefix("file:") else -> filePath } + + return URLEncoder.encode( + URLDecoder.decode(path, Charsets.UTF_8.toString()), + Charsets.UTF_8.toString() + ).replace("+", "%20") } /** diff --git a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRInputsValidator.kt b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRInputsValidator.kt index b73258b..2adb929 100644 --- a/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRInputsValidator.kt +++ b/src/main/kotlin/io/ionic/libs/ionfiletransferlib/helpers/IONFLTRInputsValidator.kt @@ -35,21 +35,8 @@ internal class IONFLTRInputsValidator { } return try { - val resolvedPath: String - if (path.startsWith("file://")) { - val encodedPath = URLEncoder.encode( - path.replace("file://", ""), - Charsets.UTF_8.toString() - ).replace("+", "%20") - val uri = URI(encodedPath) - if (uri.path == null) { - return false - } - resolvedPath = uri.path - } else { - resolvedPath = path - } - File(resolvedPath).isAbsolute + val uri = URI(path).path + File(uri).isAbsolute } catch (e: URISyntaxException) { false }