android: move unzip function to FileUtil and use SecurityException
This commit is contained in:
parent
296ccb698d
commit
19674ec78d
|
@ -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]
|
||||
|
|
Reference in New Issue