-
-
Notifications
You must be signed in to change notification settings - Fork 214
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
96 changed files
with
2,011 additions
and
1,286 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
.gradle | ||
build/ | ||
!gradle/wrapper/gradle-wrapper.jar | ||
!**/src/main/**/build/ | ||
!**/src/test/**/build/ | ||
|
||
### IntelliJ IDEA ### | ||
.idea/modules.xml | ||
.idea/jarRepositories.xml | ||
.idea/compiler.xml | ||
.idea/libraries/ | ||
*.iws | ||
*.iml | ||
*.ipr | ||
out/ | ||
!**/src/main/**/out/ | ||
!**/src/test/**/out/ | ||
|
||
### Eclipse ### | ||
.apt_generated | ||
.classpath | ||
.factorypath | ||
.project | ||
.settings | ||
.springBeans | ||
.sts4-cache | ||
bin/ | ||
!**/src/main/**/bin/ | ||
!**/src/test/**/bin/ | ||
|
||
### NetBeans ### | ||
/nbproject/private/ | ||
/nbbuild/ | ||
/dist/ | ||
/nbdist/ | ||
/.nb-gradle/ | ||
|
||
### VS Code ### | ||
.vscode/ | ||
|
||
### Mac OS ### | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
plugins { | ||
kotlin("jvm") | ||
`maven-publish` | ||
} | ||
|
||
group = "app.revanced" | ||
|
||
dependencies { | ||
implementation("io.github.reandroid:ARSCLib:1.1.7") | ||
} | ||
|
||
java { | ||
withSourcesJar() | ||
} | ||
|
||
kotlin { | ||
jvmToolchain(11) | ||
} | ||
|
||
publishing { | ||
repositories { | ||
if (System.getenv("GITHUB_ACTOR") != null) | ||
maven { | ||
name = "GitHubPackages" | ||
url = uri("https://maven.pkg.github.com/revanced/revanced-patcher") | ||
credentials { | ||
username = System.getenv("GITHUB_ACTOR") | ||
password = System.getenv("GITHUB_TOKEN") | ||
} | ||
} | ||
else | ||
mavenLocal() | ||
} | ||
publications { | ||
register<MavenPublication>("gpr") { | ||
from(components["java"]) | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
arsclib-utils/src/main/kotlin/app/revanced/arsc/ApkException.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package app.revanced.arsc | ||
|
||
/** | ||
* An exception thrown when working with [Apk]s. | ||
* | ||
* @param message The exception message. | ||
* @param throwable The corresponding [Throwable]. | ||
*/ | ||
// TODO: this probably needs a better name but idk what to call it. | ||
sealed class ApkException(message: String, throwable: Throwable? = null) : Exception(message, throwable) { | ||
/** | ||
* An exception when decoding resources. | ||
* | ||
* @param message The exception message. | ||
* @param throwable The corresponding [Throwable]. | ||
*/ | ||
class Decode(message: String, throwable: Throwable? = null) : ApkException(message, throwable) | ||
|
||
/** | ||
* An exception when encoding resources. | ||
* | ||
* @param message The exception message. | ||
* @param throwable The corresponding [Throwable]. | ||
*/ | ||
class Encode(message: String, throwable: Throwable? = null) : ApkException(message, throwable) | ||
|
||
/** | ||
* An exception thrown when a reference could not be resolved. | ||
* | ||
* @param ref The invalid reference. | ||
* @param throwable The corresponding [Throwable]. | ||
*/ | ||
class InvalidReference(ref: String, throwable: Throwable? = null) : | ||
ApkException("Failed to resolve: $ref", throwable) { | ||
constructor(type: String, name: String, throwable: Throwable? = null) : this("@$type/$name", throwable) | ||
} | ||
|
||
/** | ||
* An exception thrown when the [Apk] does not have a resource table, but was expected to have one. | ||
*/ | ||
object MissingResourceTable : ApkException("Apk does not have a resource table.") | ||
} |
140 changes: 140 additions & 0 deletions
140
arsclib-utils/src/main/kotlin/app/revanced/arsc/archive/Archive.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package app.revanced.arsc.archive | ||
|
||
import app.revanced.arsc.ApkException | ||
import app.revanced.arsc.logging.Logger | ||
import app.revanced.arsc.resource.ResourceContainer | ||
import app.revanced.arsc.resource.ResourceFile | ||
import app.revanced.arsc.xml.LazyXMLInputSource | ||
import com.reandroid.apk.ApkModule | ||
import com.reandroid.archive.ByteInputSource | ||
import com.reandroid.archive.InputSource | ||
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock | ||
import com.reandroid.arsc.chunk.xml.ResXmlDocument | ||
import com.reandroid.xml.XMLDocument | ||
import java.io.File | ||
|
||
private fun isResXml(inputSource: InputSource) = inputSource.openStream().use { ResXmlDocument.isResXmlBlock(it) } | ||
|
||
/** | ||
* A class for reading/writing files in an [ApkModule]. | ||
* | ||
* @param module The [ApkModule] to operate on. | ||
*/ | ||
class Archive(private val module: ApkModule) { | ||
lateinit var resources: ResourceContainer | ||
|
||
/** | ||
* The result of a [read] operation. | ||
* | ||
* @param xml Whether the contents were decoded from a [ResXmlDocument]. | ||
* @param data The contents of the file. | ||
*/ | ||
class ReadResult(val xml: Boolean, val data: ByteArray) | ||
|
||
/** | ||
* The zip archive. | ||
*/ | ||
private val archive = module.apkArchive | ||
|
||
private val lockedFiles = mutableMapOf<String, ResourceFile>() | ||
|
||
/** | ||
* Lock the [ResourceFile], preventing it from being opened again until it is unlocked. | ||
*/ | ||
fun lock(file: ResourceFile) { | ||
val path = file.handle.archivePath | ||
if (lockedFiles.contains(path)) { | ||
throw ApkException.Decode("${file.handle.virtualPath} is locked. If you are a patch developer, make sure you always close files.") | ||
} | ||
lockedFiles[path] = file | ||
} | ||
|
||
/** | ||
* Unlock the [ResourceFile], allowing patches to open it again. | ||
*/ | ||
fun unlock(file: ResourceFile) { | ||
lockedFiles.remove(file.handle.archivePath) | ||
} | ||
|
||
/** | ||
* Closes all open files and encodes all XML files to binary XML. | ||
* | ||
* @param logger The [Logger] of the [app.revanced.patcher.Patcher]. | ||
*/ | ||
fun cleanup(logger: Logger?) { | ||
lockedFiles.values.toList().forEach { | ||
logger?.warn("${it.handle.virtualPath} was never closed!") | ||
it.close() | ||
} | ||
|
||
archive.listInputSources().filterIsInstance<LazyXMLInputSource>() | ||
.forEach(LazyXMLInputSource::encode) | ||
} | ||
|
||
/** | ||
* Save the archive to disk. | ||
* | ||
* @param output The file to write the updated archive to. | ||
*/ | ||
fun save(output: File) = module.writeApk(output) | ||
|
||
/** | ||
* Read an entry from the archive. | ||
* | ||
* @param path The archive path to read from. | ||
* @return A [ReadResult] containing the contents of the entry. | ||
*/ | ||
fun read(path: String) = | ||
archive.getInputSource(path)?.let { inputSource -> | ||
val xml = when { | ||
inputSource is LazyXMLInputSource -> inputSource.document | ||
isResXml(inputSource) -> module.loadResXmlDocument( | ||
inputSource | ||
).decodeToXml(resources.resourceTable.entryStore, resources.packageBlock?.id ?: 0) | ||
|
||
else -> null | ||
} | ||
|
||
ReadResult( | ||
xml != null, | ||
xml?.toText()?.toByteArray() ?: inputSource.openStream().use { it.readAllBytes() }) | ||
} | ||
|
||
/** | ||
* Reads the manifest from the archive as an [AndroidManifestBlock]. | ||
* | ||
* @return The [AndroidManifestBlock] contained in this archive. | ||
*/ | ||
fun readManifest(): AndroidManifestBlock = | ||
archive.getInputSource(AndroidManifestBlock.FILE_NAME).openStream().use { AndroidManifestBlock.load(it) } | ||
|
||
/** | ||
* Reads all dex files from the archive. | ||
* | ||
* @return A [Map] containing all the dex files. | ||
*/ | ||
fun readDexFiles() = module.listDexFiles().associate { file -> file.name to file.openStream().use { it.readAllBytes() } } | ||
|
||
/** | ||
* Write the byte array to the archive entry. | ||
* | ||
* @param path The archive path to read from. | ||
* @param content The content of the file. | ||
*/ | ||
fun writeRaw(path: String, content: ByteArray) = | ||
archive.add(ByteInputSource(content, path)) | ||
|
||
/** | ||
* Write the XML to the entry associated. | ||
* | ||
* @param path The archive path to read from. | ||
* @param document The XML document to encode. | ||
*/ | ||
fun writeXml(path: String, document: XMLDocument) = archive.add( | ||
LazyXMLInputSource( | ||
path, | ||
document, | ||
resources, | ||
) | ||
) | ||
} |
7 changes: 7 additions & 0 deletions
7
arsclib-utils/src/main/kotlin/app/revanced/arsc/logging/Logger.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package app.revanced.arsc.logging | ||
interface Logger { | ||
fun error(msg: String) | ||
fun warn(msg: String) | ||
fun info(msg: String) | ||
fun trace(msg: String) | ||
} |
Oops, something went wrong.