android: move unzip function to FileUtil and use SecurityException

master
PabloG02 2023-06-03 14:13:20 +07:00
parent 296ccb698d
commit 19674ec78d
2 changed files with 34 additions and 32 deletions

@ -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)

@ -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]