From e2320441574778e4b6402a9246aeb9ccb26942e2 Mon Sep 17 00:00:00 2001 From: Ax333l Date: Thu, 5 Oct 2023 17:36:33 +0200 Subject: [PATCH] chore: switch to revanced library and bump patcher (#1314) --- app/build.gradle.kts | 7 +- .../manager/domain/manager/KeystoreManager.kt | 62 ++++-- .../app/revanced/manager/patcher/Aligning.kt | 38 ---- .../app/revanced/manager/patcher/Session.kt | 10 +- .../manager/patcher/alignment/ZipAlign.kt | 11 - .../patcher/alignment/zip/Extensions.kt | 33 --- .../manager/patcher/alignment/zip/ZipFile.kt | 188 ----------------- .../alignment/zip/structures/ZipEndRecord.kt | 77 ------- .../alignment/zip/structures/ZipEntry.kt | 189 ------------------ .../manager/patcher/patch/PatchBundle.kt | 11 +- .../manager/patcher/patch/PatchInfo.kt | 66 +++--- .../manager/patcher/worker/PatcherWorker.kt | 13 +- .../ui/component/patches/OptionFields.kt | 7 +- .../ui/viewmodel/ImportExportViewModel.kt | 20 +- .../ui/viewmodel/PatchesSelectorViewModel.kt | 21 +- .../ui/viewmodel/VersionSelectorViewModel.kt | 4 +- .../revanced/manager/util/signing/Signer.kt | 101 ---------- .../manager/util/signing/SigningOptions.kt | 9 - gradle/libs.versions.toml | 12 +- settings.gradle.kts | 70 ++++--- 20 files changed, 171 insertions(+), 778 deletions(-) delete mode 100644 app/src/main/java/app/revanced/manager/patcher/Aligning.kt delete mode 100644 app/src/main/java/app/revanced/manager/patcher/alignment/ZipAlign.kt delete mode 100644 app/src/main/java/app/revanced/manager/patcher/alignment/zip/Extensions.kt delete mode 100644 app/src/main/java/app/revanced/manager/patcher/alignment/zip/ZipFile.kt delete mode 100644 app/src/main/java/app/revanced/manager/patcher/alignment/zip/structures/ZipEndRecord.kt delete mode 100644 app/src/main/java/app/revanced/manager/patcher/alignment/zip/structures/ZipEntry.kt delete mode 100644 app/src/main/java/app/revanced/manager/util/signing/Signer.kt delete mode 100644 app/src/main/java/app/revanced/manager/util/signing/SigningOptions.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0e7ea14e..e5c3f484 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -131,11 +131,8 @@ dependencies { ksp(libs.room.compiler) // ReVanced - implementation(libs.patcher) - - // Signing - implementation(libs.apksign) - implementation(libs.bcpkix.jdk18on) + implementation(libs.revanced.patcher) + implementation(libs.revanced.library) implementation(libs.libsu.core) implementation(libs.libsu.service) diff --git a/app/src/main/java/app/revanced/manager/domain/manager/KeystoreManager.kt b/app/src/main/java/app/revanced/manager/domain/manager/KeystoreManager.kt index 4362caa5..826d1de5 100644 --- a/app/src/main/java/app/revanced/manager/domain/manager/KeystoreManager.kt +++ b/app/src/main/java/app/revanced/manager/domain/manager/KeystoreManager.kt @@ -2,19 +2,19 @@ package app.revanced.manager.domain.manager import android.app.Application import android.content.Context -import app.revanced.manager.util.signing.Signer -import app.revanced.manager.util.signing.SigningOptions +import app.revanced.library.ApkSigner +import app.revanced.library.ApkUtils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import java.io.ByteArrayInputStream import java.io.File +import java.io.InputStream import java.io.OutputStream import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardCopyOption -import kotlin.io.path.exists +import java.security.UnrecoverableKeyException class KeystoreManager(app: Application, private val prefs: PreferencesManager) { - companion object { + companion object Constants { /** * Default alias and password for the keystore. */ @@ -22,37 +22,55 @@ class KeystoreManager(app: Application, private val prefs: PreferencesManager) { } private val keystorePath = - app.getDir("signing", Context.MODE_PRIVATE).resolve("manager.keystore").toPath() + app.getDir("signing", Context.MODE_PRIVATE).resolve("manager.keystore") private suspend fun updatePrefs(cn: String, pass: String) = prefs.edit { prefs.keystoreCommonName.value = cn prefs.keystorePass.value = pass } + private suspend fun signingOptions(path: File = keystorePath) = ApkUtils.SigningOptions( + keyStore = path, + keyStorePassword = null, + alias = prefs.keystoreCommonName.get(), + signer = prefs.keystoreCommonName.get(), + password = prefs.keystorePass.get() + ) + suspend fun sign(input: File, output: File) = withContext(Dispatchers.Default) { - Signer( - SigningOptions( - prefs.keystoreCommonName.get(), - prefs.keystorePass.get(), - keystorePath - ) - ).signApk( - input, - output - ) + ApkUtils.sign(input, output, signingOptions()) } suspend fun regenerate() = withContext(Dispatchers.Default) { - Signer(SigningOptions(DEFAULT, DEFAULT, keystorePath)).regenerateKeystore() + val ks = ApkSigner.newKeyStore( + listOf( + ApkSigner.KeyStoreEntry( + DEFAULT, DEFAULT + ) + ) + ) + keystorePath.outputStream().use { + ks.store(it, null) + } + updatePrefs(DEFAULT, DEFAULT) } - suspend fun import(cn: String, pass: String, keystore: Path): Boolean { - if (!Signer(SigningOptions(cn, pass, keystore)).canUnlock()) { + suspend fun import(cn: String, pass: String, keystore: InputStream): Boolean { + val keystoreData = keystore.readBytes() + + try { + val ks = ApkSigner.readKeyStore(ByteArrayInputStream(keystoreData), null) + + ApkSigner.readKeyCertificatePair(ks, cn, pass) + } catch (_: UnrecoverableKeyException) { + return false + } catch (_: IllegalArgumentException) { return false } + withContext(Dispatchers.IO) { - Files.copy(keystore, keystorePath, StandardCopyOption.REPLACE_EXISTING) + Files.write(keystorePath.toPath(), keystoreData) } updatePrefs(cn, pass) @@ -63,7 +81,7 @@ class KeystoreManager(app: Application, private val prefs: PreferencesManager) { suspend fun export(target: OutputStream) { withContext(Dispatchers.IO) { - Files.copy(keystorePath, target) + Files.copy(keystorePath.toPath(), target) } } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/patcher/Aligning.kt b/app/src/main/java/app/revanced/manager/patcher/Aligning.kt deleted file mode 100644 index d8a672d6..00000000 --- a/app/src/main/java/app/revanced/manager/patcher/Aligning.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.manager.patcher - -import app.revanced.manager.patcher.alignment.ZipAligner -import app.revanced.manager.patcher.alignment.zip.ZipFile -import app.revanced.manager.patcher.alignment.zip.structures.ZipEntry -import app.revanced.patcher.PatcherResult -import java.io.File - -// This is the same aligner used by the CLI. -// It will be removed eventually. -object Aligning { - fun align(result: PatcherResult, inputFile: File, outputFile: File) { - // logger.info("Aligning ${inputFile.name} to ${outputFile.name}") - - if (outputFile.exists()) outputFile.delete() - - ZipFile(outputFile).use { file -> - result.dexFiles.forEach { - file.addEntryCompressData( - ZipEntry.createWithName(it.name), - it.stream.readBytes() - ) - } - - result.resourceFile?.let { - file.copyEntriesFromFileAligned( - ZipFile(it), - ZipAligner::getEntryAlignment - ) - } - - file.copyEntriesFromFileAligned( - ZipFile(inputFile, readonly = true), - ZipAligner::getEntryAlignment - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/patcher/Session.kt b/app/src/main/java/app/revanced/manager/patcher/Session.kt index 54e028fa..2ed9ea34 100644 --- a/app/src/main/java/app/revanced/manager/patcher/Session.kt +++ b/app/src/main/java/app/revanced/manager/patcher/Session.kt @@ -1,9 +1,10 @@ package app.revanced.manager.patcher +import app.revanced.library.ApkUtils import app.revanced.manager.ui.viewmodel.ManagerLogger import app.revanced.patcher.Patcher import app.revanced.patcher.PatcherOptions -import app.revanced.patcher.patch.PatchClass +import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.PatchResult import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -13,7 +14,7 @@ import java.nio.file.Files import java.nio.file.StandardCopyOption import java.util.logging.Logger -internal typealias PatchList = List +internal typealias PatchList = List> class Session( cacheDir: String, @@ -69,7 +70,8 @@ class Session( logger.info("Writing patched files...") val result = patcher.get() - val aligned = temporary.resolve("aligned.apk").also { Aligning.align(result, input, it) } + val aligned = temporary.resolve("aligned.apk") + ApkUtils.copyAligned(input, aligned, result) logger.info("Patched apk saved to $aligned") @@ -85,7 +87,7 @@ class Session( } companion object { - operator fun PatchResult.component1() = patchName + operator fun PatchResult.component1() = patch.name operator fun PatchResult.component2() = exception } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/patcher/alignment/ZipAlign.kt b/app/src/main/java/app/revanced/manager/patcher/alignment/ZipAlign.kt deleted file mode 100644 index 4f8504c8..00000000 --- a/app/src/main/java/app/revanced/manager/patcher/alignment/ZipAlign.kt +++ /dev/null @@ -1,11 +0,0 @@ -package app.revanced.manager.patcher.alignment - -import app.revanced.manager.patcher.alignment.zip.structures.ZipEntry - -internal object ZipAligner { - private const val DEFAULT_ALIGNMENT = 4 - private const val LIBRARY_ALIGNMENT = 4096 - - fun getEntryAlignment(entry: ZipEntry): Int? = - if (entry.compression.toUInt() != 0u) null else if (entry.fileName.endsWith(".so")) LIBRARY_ALIGNMENT else DEFAULT_ALIGNMENT -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/patcher/alignment/zip/Extensions.kt b/app/src/main/java/app/revanced/manager/patcher/alignment/zip/Extensions.kt deleted file mode 100644 index c022005f..00000000 --- a/app/src/main/java/app/revanced/manager/patcher/alignment/zip/Extensions.kt +++ /dev/null @@ -1,33 +0,0 @@ -package app.revanced.manager.patcher.alignment.zip - -import java.io.DataInput -import java.io.DataOutput -import java.nio.ByteBuffer - -fun UInt.toLittleEndian() = - (((this.toInt() and 0xff000000.toInt()) shr 24) or ((this.toInt() and 0x00ff0000) shr 8) or ((this.toInt() and 0x0000ff00) shl 8) or (this.toInt() shl 24)).toUInt() - -fun UShort.toLittleEndian() = (this.toUInt() shl 16).toLittleEndian().toUShort() - -fun UInt.toBigEndian() = (((this.toInt() and 0xff) shl 24) or ((this.toInt() and 0xff00) shl 8) - or ((this.toInt() and 0x00ff0000) ushr 8) or (this.toInt() ushr 24)).toUInt() - -fun UShort.toBigEndian() = (this.toUInt() shl 16).toBigEndian().toUShort() - -fun ByteBuffer.getUShort() = this.getShort().toUShort() -fun ByteBuffer.getUInt() = this.getInt().toUInt() - -fun ByteBuffer.putUShort(ushort: UShort) = this.putShort(ushort.toShort()) -fun ByteBuffer.putUInt(uint: UInt) = this.putInt(uint.toInt()) - -fun DataInput.readUShort() = this.readShort().toUShort() -fun DataInput.readUInt() = this.readInt().toUInt() - -fun DataOutput.writeUShort(ushort: UShort) = this.writeShort(ushort.toInt()) -fun DataOutput.writeUInt(uint: UInt) = this.writeInt(uint.toInt()) - -fun DataInput.readUShortLE() = this.readUShort().toBigEndian() -fun DataInput.readUIntLE() = this.readUInt().toBigEndian() - -fun DataOutput.writeUShortLE(ushort: UShort) = this.writeUShort(ushort.toLittleEndian()) -fun DataOutput.writeUIntLE(uint: UInt) = this.writeUInt(uint.toLittleEndian()) \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/patcher/alignment/zip/ZipFile.kt b/app/src/main/java/app/revanced/manager/patcher/alignment/zip/ZipFile.kt deleted file mode 100644 index a49ffed1..00000000 --- a/app/src/main/java/app/revanced/manager/patcher/alignment/zip/ZipFile.kt +++ /dev/null @@ -1,188 +0,0 @@ -package app.revanced.manager.patcher.alignment.zip - -import app.revanced.manager.patcher.alignment.zip.structures.ZipEndRecord -import app.revanced.manager.patcher.alignment.zip.structures.ZipEntry - -import java.io.Closeable -import java.io.File -import java.io.IOException -import java.io.RandomAccessFile -import java.nio.ByteBuffer -import java.nio.channels.FileChannel -import java.util.zip.CRC32 -import java.util.zip.Deflater - -class ZipFile(file: File, private val readonly: Boolean = false) : Closeable { - var entries: MutableList = mutableListOf() - - private val filePointer: RandomAccessFile = RandomAccessFile(file, if (readonly) "r" else "rw") - private var CDNeedsRewrite = false - - private val compressionLevel = 5 - - init { - //if file isn't empty try to load entries - if (file.length() > 0) { - val endRecord = findEndRecord() - - if (endRecord.diskNumber > 0u || endRecord.totalEntries != endRecord.diskEntries) - throw IllegalArgumentException("Multi-file archives are not supported") - - entries = readEntries(endRecord).toMutableList() - } - - //seek back to start for writing - filePointer.seek(0) - } - - private fun assertWritable() { - if (readonly) throw IOException("Archive is read-only") - } - - private fun findEndRecord(): ZipEndRecord { - //look from end to start since end record is at the end - for (i in filePointer.length() - 1 downTo 0) { - filePointer.seek(i) - //possible beginning of signature - if (filePointer.readByte() == 0x50.toByte()) { - //seek back to get the full int - filePointer.seek(i) - val possibleSignature = filePointer.readUIntLE() - if (possibleSignature == ZipEndRecord.ECD_SIGNATURE) { - filePointer.seek(i) - return ZipEndRecord.fromECD(filePointer) - } - } - } - - throw Exception("Couldn't find end record") - } - - private fun readEntries(endRecord: ZipEndRecord): List { - filePointer.seek(endRecord.centralDirectoryStartOffset.toLong()) - - val numberOfEntries = endRecord.diskEntries.toInt() - - return buildList(numberOfEntries) { - for (i in 1..numberOfEntries) { - add( - ZipEntry.fromCDE(filePointer).also - { - //for some reason the local extra field can be different from the central one - it.readLocalExtra( - filePointer.channel.map( - FileChannel.MapMode.READ_ONLY, - it.localHeaderOffset.toLong() + 28, - 2 - ) - ) - }) - } - } - } - - private fun writeCD() { - val CDStart = filePointer.channel.position().toUInt() - - entries.forEach { - filePointer.channel.write(it.toCDE()) - } - - val entriesCount = entries.size.toUShort() - - val endRecord = ZipEndRecord( - 0u, - 0u, - entriesCount, - entriesCount, - filePointer.channel.position().toUInt() - CDStart, - CDStart, - "" - ) - - filePointer.channel.write(endRecord.toECD()) - } - - private fun addEntry(entry: ZipEntry, data: ByteBuffer) { - CDNeedsRewrite = true - - entry.localHeaderOffset = filePointer.channel.position().toUInt() - - filePointer.channel.write(entry.toLFH()) - filePointer.channel.write(data) - - entries.add(entry) - } - - fun addEntryCompressData(entry: ZipEntry, data: ByteArray) { - assertWritable() - - val compressor = Deflater(compressionLevel, true) - compressor.setInput(data) - compressor.finish() - - val uncompressedSize = data.size - val compressedData = - ByteArray(uncompressedSize) //i'm guessing compression won't make the data bigger - - val compressedDataLength = compressor.deflate(compressedData) - val compressedBuffer = - ByteBuffer.wrap(compressedData.take(compressedDataLength).toByteArray()) - - compressor.end() - - val crc = CRC32() - crc.update(data) - - entry.compression = 8u //deflate compression - entry.uncompressedSize = uncompressedSize.toUInt() - entry.compressedSize = compressedDataLength.toUInt() - entry.crc32 = crc.value.toUInt() - - addEntry(entry, compressedBuffer) - } - - private fun addEntryCopyData(entry: ZipEntry, data: ByteBuffer, alignment: Int? = null) { - assertWritable() - - alignment?.let { - //calculate where data would end up - val dataOffset = filePointer.filePointer + entry.LFHSize - - val mod = dataOffset % alignment - - //wrong alignment - if (mod != 0L) { - //add padding at end of extra field - entry.localExtraField = - entry.localExtraField.copyOf((entry.localExtraField.size + (alignment - mod)).toInt()) - } - } - - addEntry(entry, data) - } - - fun getDataForEntry(entry: ZipEntry): ByteBuffer { - return filePointer.channel.map( - FileChannel.MapMode.READ_ONLY, - entry.dataOffset.toLong(), - entry.compressedSize.toLong() - ) - } - - fun copyEntriesFromFileAligned(file: ZipFile, entryAlignment: (entry: ZipEntry) -> Int?) { - assertWritable() - - for (entry in file.entries) { - if (entries.any { it.fileName == entry.fileName }) continue //don't add duplicates - - val data = file.getDataForEntry(entry) - addEntryCopyData(entry, data, entryAlignment(entry)) - } - } - - override fun close() { - if (CDNeedsRewrite) writeCD() - filePointer.close() - } -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/patcher/alignment/zip/structures/ZipEndRecord.kt b/app/src/main/java/app/revanced/manager/patcher/alignment/zip/structures/ZipEndRecord.kt deleted file mode 100644 index 06555cd3..00000000 --- a/app/src/main/java/app/revanced/manager/patcher/alignment/zip/structures/ZipEndRecord.kt +++ /dev/null @@ -1,77 +0,0 @@ -package app.revanced.manager.patcher.alignment.zip.structures - -import app.revanced.manager.patcher.alignment.zip.putUInt -import app.revanced.manager.patcher.alignment.zip.putUShort -import app.revanced.manager.patcher.alignment.zip.readUIntLE -import app.revanced.manager.patcher.alignment.zip.readUShortLE -import java.io.DataInput -import java.nio.ByteBuffer -import java.nio.ByteOrder - -data class ZipEndRecord( - val diskNumber: UShort, - val startingDiskNumber: UShort, - val diskEntries: UShort, - val totalEntries: UShort, - val centralDirectorySize: UInt, - val centralDirectoryStartOffset: UInt, - val fileComment: String, -) { - - companion object { - const val ECD_HEADER_SIZE = 22 - const val ECD_SIGNATURE = 0x06054b50u - - fun fromECD(input: DataInput): ZipEndRecord { - val signature = input.readUIntLE() - - if (signature != ECD_SIGNATURE) - throw IllegalArgumentException("Input doesn't start with end record signature") - - val diskNumber = input.readUShortLE() - val startingDiskNumber = input.readUShortLE() - val diskEntries = input.readUShortLE() - val totalEntries = input.readUShortLE() - val centralDirectorySize = input.readUIntLE() - val centralDirectoryStartOffset = input.readUIntLE() - val fileCommentLength = input.readUShortLE() - var fileComment = "" - - if (fileCommentLength > 0u) { - val fileCommentBytes = ByteArray(fileCommentLength.toInt()) - input.readFully(fileCommentBytes) - fileComment = fileCommentBytes.toString(Charsets.UTF_8) - } - - return ZipEndRecord( - diskNumber, - startingDiskNumber, - diskEntries, - totalEntries, - centralDirectorySize, - centralDirectoryStartOffset, - fileComment - ) - } - } - - fun toECD(): ByteBuffer { - val commentBytes = fileComment.toByteArray(Charsets.UTF_8) - - val buffer = ByteBuffer.allocate(ECD_HEADER_SIZE + commentBytes.size).also { it.order(ByteOrder.LITTLE_ENDIAN) } - - buffer.putUInt(ECD_SIGNATURE) - buffer.putUShort(diskNumber) - buffer.putUShort(startingDiskNumber) - buffer.putUShort(diskEntries) - buffer.putUShort(totalEntries) - buffer.putUInt(centralDirectorySize) - buffer.putUInt(centralDirectoryStartOffset) - buffer.putUShort(commentBytes.size.toUShort()) - - buffer.put(commentBytes) - - buffer.flip() - return buffer - } -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/patcher/alignment/zip/structures/ZipEntry.kt b/app/src/main/java/app/revanced/manager/patcher/alignment/zip/structures/ZipEntry.kt deleted file mode 100644 index f070386c..00000000 --- a/app/src/main/java/app/revanced/manager/patcher/alignment/zip/structures/ZipEntry.kt +++ /dev/null @@ -1,189 +0,0 @@ -package app.revanced.manager.patcher.alignment.zip.structures - -import app.revanced.manager.patcher.alignment.zip.* -import java.io.DataInput -import java.nio.ByteBuffer -import java.nio.ByteOrder - -data class ZipEntry( - val version: UShort, - val versionNeeded: UShort, - val flags: UShort, - var compression: UShort, - val modificationTime: UShort, - val modificationDate: UShort, - var crc32: UInt, - var compressedSize: UInt, - var uncompressedSize: UInt, - val diskNumber: UShort, - val internalAttributes: UShort, - val externalAttributes: UInt, - var localHeaderOffset: UInt, - val fileName: String, - val extraField: ByteArray, - val fileComment: String, - var localExtraField: ByteArray = ByteArray(0), //separate for alignment -) { - val LFHSize: Int - get() = LFH_HEADER_SIZE + fileName.toByteArray(Charsets.UTF_8).size + localExtraField.size - - val dataOffset: UInt - get() = localHeaderOffset + LFHSize.toUInt() - - companion object { - const val CDE_HEADER_SIZE = 46 - const val CDE_SIGNATURE = 0x02014b50u - - const val LFH_HEADER_SIZE = 30 - const val LFH_SIGNATURE = 0x04034b50u - - fun createWithName(fileName: String): ZipEntry { - return ZipEntry( - 0x1403u, //made by unix, version 20 - 0u, - 0u, - 0u, - 0x0821u, //seems to be static time google uses, no idea - 0x0221u, //same as above - 0u, - 0u, - 0u, - 0u, - 0u, - 0u, - 0u, - fileName, - ByteArray(0), - "" - ) - } - - fun fromCDE(input: DataInput): ZipEntry { - val signature = input.readUIntLE() - - if (signature != CDE_SIGNATURE) - throw IllegalArgumentException("Input doesn't start with central directory entry signature") - - val version = input.readUShortLE() - val versionNeeded = input.readUShortLE() - var flags = input.readUShortLE() - val compression = input.readUShortLE() - val modificationTime = input.readUShortLE() - val modificationDate = input.readUShortLE() - val crc32 = input.readUIntLE() - val compressedSize = input.readUIntLE() - val uncompressedSize = input.readUIntLE() - val fileNameLength = input.readUShortLE() - var fileName = "" - val extraFieldLength = input.readUShortLE() - val extraField = ByteArray(extraFieldLength.toInt()) - val fileCommentLength = input.readUShortLE() - var fileComment = "" - val diskNumber = input.readUShortLE() - val internalAttributes = input.readUShortLE() - val externalAttributes = input.readUIntLE() - val localHeaderOffset = input.readUIntLE() - - val variableFieldsLength = - fileNameLength.toInt() + extraFieldLength.toInt() + fileCommentLength.toInt() - - if (variableFieldsLength > 0) { - val fileNameBytes = ByteArray(fileNameLength.toInt()) - input.readFully(fileNameBytes) - fileName = fileNameBytes.toString(Charsets.UTF_8) - - input.readFully(extraField) - - val fileCommentBytes = ByteArray(fileCommentLength.toInt()) - input.readFully(fileCommentBytes) - fileComment = fileCommentBytes.toString(Charsets.UTF_8) - } - - flags = (flags and 0b1000u.inv() - .toUShort()) //disable data descriptor flag as they are not used - - return ZipEntry( - version, - versionNeeded, - flags, - compression, - modificationTime, - modificationDate, - crc32, - compressedSize, - uncompressedSize, - diskNumber, - internalAttributes, - externalAttributes, - localHeaderOffset, - fileName, - extraField, - fileComment, - ) - } - } - - fun readLocalExtra(buffer: ByteBuffer) { - buffer.order(ByteOrder.LITTLE_ENDIAN) - localExtraField = ByteArray(buffer.getUShort().toInt()) - } - - fun toLFH(): ByteBuffer { - val nameBytes = fileName.toByteArray(Charsets.UTF_8) - - val buffer = ByteBuffer.allocate(LFH_HEADER_SIZE + nameBytes.size + localExtraField.size) - .also { it.order(ByteOrder.LITTLE_ENDIAN) } - - buffer.putUInt(LFH_SIGNATURE) - buffer.putUShort(versionNeeded) - buffer.putUShort(flags) - buffer.putUShort(compression) - buffer.putUShort(modificationTime) - buffer.putUShort(modificationDate) - buffer.putUInt(crc32) - buffer.putUInt(compressedSize) - buffer.putUInt(uncompressedSize) - buffer.putUShort(nameBytes.size.toUShort()) - buffer.putUShort(localExtraField.size.toUShort()) - - buffer.put(nameBytes) - buffer.put(localExtraField) - - buffer.flip() - return buffer - } - - fun toCDE(): ByteBuffer { - val nameBytes = fileName.toByteArray(Charsets.UTF_8) - val commentBytes = fileComment.toByteArray(Charsets.UTF_8) - - val buffer = - ByteBuffer.allocate(CDE_HEADER_SIZE + nameBytes.size + extraField.size + commentBytes.size) - .also { it.order(ByteOrder.LITTLE_ENDIAN) } - - buffer.putUInt(CDE_SIGNATURE) - buffer.putUShort(version) - buffer.putUShort(versionNeeded) - buffer.putUShort(flags) - buffer.putUShort(compression) - buffer.putUShort(modificationTime) - buffer.putUShort(modificationDate) - buffer.putUInt(crc32) - buffer.putUInt(compressedSize) - buffer.putUInt(uncompressedSize) - buffer.putUShort(nameBytes.size.toUShort()) - buffer.putUShort(extraField.size.toUShort()) - buffer.putUShort(commentBytes.size.toUShort()) - buffer.putUShort(diskNumber) - buffer.putUShort(internalAttributes) - buffer.putUInt(externalAttributes) - buffer.putUInt(localHeaderOffset) - - buffer.put(nameBytes) - buffer.put(extraField) - buffer.put(commentBytes) - - buffer.flip() - return buffer - } -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/patcher/patch/PatchBundle.kt b/app/src/main/java/app/revanced/manager/patcher/patch/PatchBundle.kt index 08b3c33d..7c5b2ffd 100644 --- a/app/src/main/java/app/revanced/manager/patcher/patch/PatchBundle.kt +++ b/app/src/main/java/app/revanced/manager/patcher/patch/PatchBundle.kt @@ -3,16 +3,15 @@ package app.revanced.manager.patcher.patch import android.util.Log import app.revanced.manager.util.tag import app.revanced.patcher.PatchBundleLoader -import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages -import app.revanced.patcher.patch.PatchClass +import app.revanced.patcher.patch.Patch import java.io.File -class PatchBundle(private val loader: Iterable, val integrations: File?) { +class PatchBundle(private val loader: Iterable>, val integrations: File?) { constructor(bundleJar: File, integrations: File?) : this( - object : Iterable { - private fun load(): List = PatchBundleLoader.Dex(bundleJar) + object : Iterable> { + private fun load(): Iterable> = PatchBundleLoader.Dex(bundleJar, optimizedDexDirectory = null) - override fun iterator() = load().iterator() + override fun iterator(): Iterator> = load().iterator() }, integrations ) { diff --git a/app/src/main/java/app/revanced/manager/patcher/patch/PatchInfo.kt b/app/src/main/java/app/revanced/manager/patcher/patch/PatchInfo.kt index 20d1c886..8002fa99 100644 --- a/app/src/main/java/app/revanced/manager/patcher/patch/PatchInfo.kt +++ b/app/src/main/java/app/revanced/manager/patcher/patch/PatchInfo.kt @@ -1,50 +1,70 @@ package app.revanced.manager.patcher.patch import androidx.compose.runtime.Immutable -import app.revanced.patcher.annotation.Package -import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages -import app.revanced.patcher.extensions.PatchExtensions.dependencies -import app.revanced.patcher.extensions.PatchExtensions.description -import app.revanced.patcher.extensions.PatchExtensions.include -import app.revanced.patcher.extensions.PatchExtensions.options -import app.revanced.patcher.extensions.PatchExtensions.patchName -import app.revanced.patcher.patch.PatchClass -import app.revanced.patcher.patch.PatchOption +import app.revanced.patcher.patch.Patch +import app.revanced.patcher.patch.options.PatchOption import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.ImmutableSet import kotlinx.collections.immutable.toImmutableList +import kotlinx.collections.immutable.toImmutableSet data class PatchInfo( val name: String, val description: String?, - val dependencies: ImmutableList?, val include: Boolean, val compatiblePackages: ImmutableList?, val options: ImmutableList