ExtensionLoader: Set read-only to private extension files (#10007)

This commit is contained in:
Ivan Iskandar 2023-10-13 10:04:40 +07:00 committed by GitHub
parent c386d375de
commit c492efcb31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 1 deletions

View File

@ -14,6 +14,7 @@ import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory
import eu.kanade.tachiyomi.util.lang.Hash
import eu.kanade.tachiyomi.util.storage.copyAndSetReadOnlyTo
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
@ -97,7 +98,8 @@ internal object ExtensionLoader {
val target = File(getPrivateExtensionDir(context), "${extension.packageName}.$PRIVATE_EXTENSION_EXTENSION")
return try {
file.copyTo(target, overwrite = true)
file.delete()
file.copyAndSetReadOnlyTo(target, overwrite = true)
if (currentExtension != null) {
ExtensionInstallReceiver.notifyReplaced(context, extension.packageName)
} else {

View File

@ -23,3 +23,41 @@ fun File.getUriCompat(context: Context): Uri {
this.toUri()
}
}
/**
* Copies this file to the given [target] file while marking the file as read-only.
*
* @see File.copyTo
*/
fun File.copyAndSetReadOnlyTo(target: File, overwrite: Boolean = false, bufferSize: Int = DEFAULT_BUFFER_SIZE): File {
if (!this.exists()) {
throw NoSuchFileException(file = this, reason = "The source file doesn't exist.")
}
if (target.exists()) {
if (!overwrite) {
throw FileAlreadyExistsException(file = this, other = target, reason = "The destination file already exists.")
} else if (!target.delete()) {
throw FileAlreadyExistsException(file = this, other = target, reason = "Tried to overwrite the destination, but failed to delete it.")
}
}
if (this.isDirectory) {
if (!target.mkdirs()) {
throw FileSystemException(file = this, other = target, reason = "Failed to create target directory.")
}
} else {
target.parentFile?.mkdirs()
this.inputStream().use { input ->
target.outputStream().use { output ->
// Set read-only
target.setReadOnly()
input.copyTo(output, bufferSize)
}
}
}
return target
}