From 090399f61d3abd6d9bfd575a46f37527045687bf Mon Sep 17 00:00:00 2001 From: Aria Moradi Date: Thu, 9 Sep 2021 05:22:23 +0430 Subject: [PATCH] add support for installing external APK --- CHANGELOG.md | 7 +++-- buildSrc/src/main/kotlin/Constants.kt | 2 +- .../suwayomi/tachidesk/manga/MangaAPI.kt | 1 + .../manga/controller/ExtensionController.kt | 13 ++++++++ .../manga/impl/extension/Extension.kt | 30 ++++++++++++++----- .../tachidesk/manga/impl/util/PackageTools.kt | 2 +- .../tachidesk/manga/impl/util/lang/List.kt | 2 +- .../manga/model/dataclass/MangaDataClass.kt | 2 +- 8 files changed, 45 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e39e0039..8d2c4124 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ -# Server: v0.4.9-r882 + WebUI: r776 +# Server: v0.4.9-r888 + WebUI: r777 ## Tachidesk-Server ### Public API #### Non-breaking changes -- N/A +- (r888) add installing APK from external sources endpoint #### Breaking changes - (r877 #188 by @Syer10) `MangaDataClass.genre` changed type to `List` @@ -11,7 +11,7 @@ - N/A ### Private API -- N/A +- (r887) the `run` task won't call `downloadWebUI` now ## Tachidesk-WebUI @@ -21,6 +21,7 @@ - (r774 #21 by @voltrare) `ReaderNavbar.jsx`: Swap close and retract Navbar buttons - (r775 #23 by @voltrare) `yarn.lock`: Fixes version inconsistency after commit 9b866811b - (r776 #22 by @voltrare) add margin between Source and Extension cards, make the Search button look nicer +- (r777) add support for installing external APK files #### Bug fixes - N/A diff --git a/buildSrc/src/main/kotlin/Constants.kt b/buildSrc/src/main/kotlin/Constants.kt index c8a4d95e..a2311c2f 100644 --- a/buildSrc/src/main/kotlin/Constants.kt +++ b/buildSrc/src/main/kotlin/Constants.kt @@ -14,7 +14,7 @@ const val MainClass = "suwayomi.tachidesk.MainKt" // should be bumped with each stable release val tachideskVersion = System.getenv("ProductVersion") ?: "v0.4.9" -val webUIRevisionTag = System.getenv("WebUIRevision") ?: "r776" +val webUIRevisionTag = System.getenv("WebUIRevision") ?: "r777" // counts commits on the the master branch val tachideskRevision = runCatching { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/MangaAPI.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/MangaAPI.kt index 0940cfa4..c24c19e1 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/MangaAPI.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/MangaAPI.kt @@ -26,6 +26,7 @@ object MangaAPI { get("list", ExtensionController::list) get("install/:pkgName", ExtensionController::install) + post("install", ExtensionController::installFile) get("update/:pkgName", ExtensionController::update) get("uninstall/:pkgName", ExtensionController::uninstall) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/ExtensionController.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/ExtensionController.kt index e63eb265..a13fef81 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/ExtensionController.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/ExtensionController.kt @@ -33,6 +33,19 @@ object ExtensionController { ) } + /** install the uploaded apk file */ + fun installFile(ctx: Context) { + + val uploadedFile = ctx.uploadedFile("file")!! + println(uploadedFile.filename) + + ctx.json( + future { + Extension.installExternalExtension(uploadedFile.content) + } + ) + } + /** update extension identified with "pkgName" */ fun update(ctx: Context) { val pkgName = ctx.pathParam("pkgName") diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt index 87c0ac26..77d94fb0 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt @@ -17,6 +17,7 @@ import mu.KotlinLogging import okhttp3.Request import okio.buffer import okio.sink +import okio.source import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.insert import org.jetbrains.exposed.sql.select @@ -36,7 +37,6 @@ import suwayomi.tachidesk.manga.impl.util.PackageTools.dex2jar import suwayomi.tachidesk.manga.impl.util.PackageTools.getPackageInfo import suwayomi.tachidesk.manga.impl.util.PackageTools.getSignatureHash import suwayomi.tachidesk.manga.impl.util.PackageTools.loadExtensionSources -import suwayomi.tachidesk.manga.impl.util.PackageTools.trustedSignatures import suwayomi.tachidesk.manga.impl.util.network.await import suwayomi.tachidesk.manga.impl.util.storage.CachedImageResponse.getCachedImageResponse import suwayomi.tachidesk.manga.model.table.ExtensionTable @@ -68,6 +68,22 @@ object Extension { } } + suspend fun installExternalExtension(inputStream: InputStream): Int { + return installAPK { + val apkName = "apkToSave.apk" + val savePath = "${applicationDirs.extensionsRoot}/$apkName" + // download apk file + val downloadedFile = File(savePath) + downloadedFile.sink().buffer().use { sink -> + inputStream.source().use { source -> + sink.writeAll(source) + sink.flush() + } + } + savePath + } + } + suspend fun installAPK(fetcher: suspend () -> String): Int { val apkFilePath = fetcher() val apkName = File(apkFilePath).name @@ -103,12 +119,12 @@ object Extension { val signatureHash = getSignatureHash(packageInfo) - if (signatureHash == null) { - throw Exception("Package $pkgName isn't signed") - } else if (signatureHash !in trustedSignatures) { - // TODO: allow trusting keys - throw Exception("This apk is not a signed with the official tachiyomi signature") - } +// if (signatureHash == null) { +// throw Exception("Package $pkgName isn't signed") +// } else if (signatureHash !in trustedSignatures) { +// // TODO: allow trusting keys +// throw Exception("This apk is not a signed with the official tachiyomi signature") +// } val isNsfw = packageInfo.applicationInfo.metaData.getString(METADATA_NSFW) == "1" diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/PackageTools.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/PackageTools.kt index 486def72..40fab8dd 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/PackageTools.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/PackageTools.kt @@ -45,7 +45,7 @@ object PackageTools { private const val officialSignature = "7ce04da7773d41b489f4693a366c36bcd0a11fc39b547168553c285bd7348e23" // inorichi's key private const val unofficialSignature = "64feb21075ba97ebc9cc981243645b331595c111cef1b0d084236a0403b00581" // ArMor's key - var trustedSignatures = mutableSetOf() + officialSignature + unofficialSignature + val trustedSignatures = mutableSetOf() + officialSignature + unofficialSignature /** * Convert dex to jar, a wrapper for the dex2jar library diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/lang/List.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/lang/List.kt index 393d76af..712d661f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/lang/List.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/lang/List.kt @@ -1,3 +1,3 @@ package suwayomi.tachidesk.manga.impl.util.lang -fun List.trimAll() = map { it.trim() } \ No newline at end of file +fun List.trimAll() = map { it.trim() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/MangaDataClass.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/MangaDataClass.kt index 9724e583..e95d1bf0 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/MangaDataClass.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/MangaDataClass.kt @@ -41,4 +41,4 @@ data class PagedMangaListDataClass( val hasNextPage: Boolean ) -internal fun String?.toGenreList() = this?.split(",")?.trimAll().orEmpty() \ No newline at end of file +internal fun String?.toGenreList() = this?.split(",")?.trimAll().orEmpty()