diff --git a/app/src/main/java/com/futo/platformplayer/downloads/VideoExport.kt b/app/src/main/java/com/futo/platformplayer/downloads/VideoExport.kt index 37f1395f..81f0fb09 100644 --- a/app/src/main/java/com/futo/platformplayer/downloads/VideoExport.kt +++ b/app/src/main/java/com/futo/platformplayer/downloads/VideoExport.kt @@ -7,6 +7,7 @@ import androidx.documentfile.provider.DocumentFile import com.arthenica.ffmpegkit.* import com.futo.platformplayer.api.media.models.streams.sources.* import com.futo.platformplayer.constructs.Event1 +import com.futo.platformplayer.helpers.FileHelper.Companion.sanitizeFileName import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.states.StateApp import com.futo.platformplayer.toHumanBitrate @@ -63,7 +64,7 @@ class VideoExport { val outputFile: DocumentFile?; val downloadRoot = StateApp.instance.getExternalDownloadDirectory(context) ?: throw Exception("External download directory is not set"); if (sourceCount > 1) { - val outputFileName = toSafeFileName(videoLocal.name) + ".mp4"// + VideoDownload.videoContainerToExtension(v.container); + val outputFileName = videoLocal.name.sanitizeFileName(true) + ".mp4"// + VideoDownload.videoContainerToExtension(v.container); val f = downloadRoot.createFile("video/mp4", outputFileName) ?: throw Exception("Failed to create file in external directory."); @@ -79,7 +80,7 @@ class VideoExport { } outputFile = f; } else if (v != null) { - val outputFileName = toSafeFileName(videoLocal.name) + "." + VideoDownload.videoContainerToExtension(v.container); + val outputFileName = videoLocal.name.sanitizeFileName(true) + "." + VideoDownload.videoContainerToExtension(v.container); val f = downloadRoot.createFile(v.container, outputFileName) ?: throw Exception("Failed to create file in external directory."); @@ -91,7 +92,7 @@ class VideoExport { outputFile = f; } else if (a != null) { - val outputFileName = toSafeFileName(videoLocal.name) + "." + VideoDownload.audioContainerToExtension(a.container); + val outputFileName = videoLocal.name.sanitizeFileName(true) + "." + VideoDownload.audioContainerToExtension(a.container); val f = downloadRoot.createFile(a.container, outputFileName) ?: throw Exception("Failed to create file in external directory."); @@ -110,11 +111,6 @@ class VideoExport { return@coroutineScope outputFile; } - private fun toSafeFileName(input: String): String { - val safeCharacters = ('a'..'z') + ('A'..'Z') + ('0'..'9') + listOf('-', '_') - return input.map { if (it in safeCharacters) it else '_' }.joinToString(separator = "") - } - private suspend fun combine(inputPathAudio: String?, inputPathVideo: String?, inputPathSubtitles: String?, outputPath: String, duration: Double, onProgress: ((Double) -> Unit)? = null) = withContext(Dispatchers.IO) { suspendCancellableCoroutine { continuation -> //ffmpeg -i a.mp4 -i b.m4a -scodec mov_text -i c.vtt -map 0:v -map 1:a -map 2 -c:v copy -c:a copy -c:s mov_text output.mp4 diff --git a/app/src/main/java/com/futo/platformplayer/helpers/FileHelper.kt b/app/src/main/java/com/futo/platformplayer/helpers/FileHelper.kt index 0f8565a2..ec5b493e 100644 --- a/app/src/main/java/com/futo/platformplayer/helpers/FileHelper.kt +++ b/app/src/main/java/com/futo/platformplayer/helpers/FileHelper.kt @@ -2,11 +2,17 @@ package com.futo.platformplayer.helpers class FileHelper { companion object { - val allowedCharacters = HashSet("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz-.".toCharArray().toList()); - - - fun String.sanitizeFileName(): String { - return this.filter { allowedCharacters.contains(it) }; + fun String.sanitizeFileName(allowSpace: Boolean = false): String { + return this.filter { + (it in '0' .. '9') || + (it in 'a'..'z') || + (it in 'A'..'Z') || + (it == '-' || it == '.' || it == '_' || (it == ' ' && allowSpace)) || + (it in '丁'..'龤') || //Chinese/Kanji + (it in '\u3040'..'\u309f') || //Hiragana + (it in '\u30A0'..'\u30ff') || //Katakana + (it in '\u0600'..'\u06FF') //Arabic + }; //Chinese } } } \ No newline at end of file