From 19674ec78d0c8b831083de3e7cf2fa29aacf9d4d Mon Sep 17 00:00:00 2001 From: PabloG02 Date: Sat, 3 Jun 2023 14:13:20 +0200 Subject: [PATCH] android: move unzip function to FileUtil and use SecurityException --- .../fragments/ImportExportSavesFragment.kt | 34 ++----------------- .../java/org/yuzu/yuzu_emu/utils/FileUtil.kt | 32 +++++++++++++++++ 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt index 5f107b37da..36e63bb9e6 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt @@ -23,17 +23,14 @@ import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.features.DocumentProvider import org.yuzu.yuzu_emu.getPublicFilesDir -import java.io.BufferedInputStream +import org.yuzu.yuzu_emu.utils.FileUtil import java.io.BufferedOutputStream import java.io.File import java.io.FileOutputStream import java.io.FilenameFilter -import java.io.IOException -import java.io.InputStream import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.zip.ZipEntry -import java.util.zip.ZipInputStream import java.util.zip.ZipOutputStream class ImportExportSavesFragment : DialogFragment() { @@ -124,33 +121,6 @@ class ImportExportSavesFragment : DialogFragment() { return true } - /** - * Extracts the save files located in the given zip file and copies them to the saves folder. - * @exception IOException if the file was being created outside of the target directory - */ - private fun unzip(zipStream: InputStream, destDir: File): Boolean { - val zis = ZipInputStream(BufferedInputStream(zipStream)) - var entry: ZipEntry? = zis.nextEntry - while (entry != null) { - val entryName = entry.name - val entryFile = File(destDir, entryName) - if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath + File.separator)) { - zis.close() - throw IOException("Entry is outside of the target dir: " + entryFile.name) - } - if (entry.isDirectory) { - entryFile.mkdirs() - } else { - entryFile.parentFile?.mkdirs() - entryFile.createNewFile() - entryFile.outputStream().use { fos -> zis.copyTo(fos) } - } - entry = zis.nextEntry - } - zis.close() - return true - } - /** * Exports the save file located in the given folder path by creating a zip file and sharing it via intent. */ @@ -204,7 +174,7 @@ class ImportExportSavesFragment : DialogFragment() { try { CoroutineScope(Dispatchers.IO).launch { - unzip(inputZip, cacheSaveDir) + FileUtil.unzip(inputZip, cacheSaveDir) cacheSaveDir.list(filterTitleId)?.forEach { savePath -> File(savesFolder, savePath).deleteRecursively() File(cacheSaveDir, savePath).copyRecursively(File(savesFolder, savePath), true) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt index 0a7b323b1c..593dad8d31 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt @@ -9,10 +9,14 @@ import android.net.Uri import android.provider.DocumentsContract import androidx.documentfile.provider.DocumentFile import org.yuzu.yuzu_emu.model.MinimalDocumentFile +import java.io.BufferedInputStream +import java.io.File import java.io.FileOutputStream import java.io.IOException import java.io.InputStream import java.net.URLDecoder +import java.util.zip.ZipEntry +import java.util.zip.ZipInputStream object FileUtil { const val PATH_TREE = "tree" @@ -276,6 +280,34 @@ object FileUtil { return false } + /** + * Extracts the given zip file into the given directory. + * @exception IOException if the file was being created outside of the target directory + */ + @Throws(SecurityException::class) + fun unzip(zipStream: InputStream, destDir: File): Boolean { + ZipInputStream(BufferedInputStream(zipStream)).use { zis -> + var entry: ZipEntry? = zis.nextEntry + while (entry != null) { + val entryName = entry.name + val entryFile = File(destDir, entryName) + if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath + File.separator)) { + throw SecurityException("Entry is outside of the target dir: " + entryFile.name) + } + if (entry.isDirectory) { + entryFile.mkdirs() + } else { + entryFile.parentFile?.mkdirs() + entryFile.createNewFile() + entryFile.outputStream().use { fos -> zis.copyTo(fos) } + } + entry = zis.nextEntry + } + } + + return true + } + fun isRootTreeUri(uri: Uri): Boolean { val paths = uri.pathSegments return paths.size == 2 && PATH_TREE == paths[0]