ManhwaLatino: Decrypt image list (#15496)

Decrypt image list
This commit is contained in:
seew3l 2023-02-27 13:34:05 -05:00 committed by GitHub
parent 4c520021b8
commit e5bcf9190f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 19 deletions

View File

@ -5,8 +5,12 @@ ext {
extName = 'Manhwa-Latino' extName = 'Manhwa-Latino'
pkgNameSuffix = 'es.manhwalatino' pkgNameSuffix = 'es.manhwalatino'
extClass = '.ManhwaLatino' extClass = '.ManhwaLatino'
extVersionCode = 22 extVersionCode = 23
isNsfw = true isNsfw = true
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"
dependencies {
implementation(project(':lib-cryptoaes'))
}

View File

@ -35,6 +35,6 @@ object MLConstants {
const val chapterLinkParser = "a" const val chapterLinkParser = "a"
const val chapterReleaseDateLinkParser = "span.chapter-release-date a" const val chapterReleaseDateLinkParser = "span.chapter-release-date a"
const val chapterReleaseDateIParser = "span.chapter-release-date i" const val chapterReleaseDateIParser = "span.chapter-release-date i"
const val pageListParseSelector = "div.read-container img" const val pageListParseSelector = "div.read-container script"
const val imageAttribute = "abs:data-src" const val imageAttribute = "abs:data-src"
} }

View File

@ -1,7 +1,9 @@
package eu.kanade.tachiyomi.extension.es.manhwalatino package eu.kanade.tachiyomi.extension.es.manhwalatino
import android.net.Uri import android.net.Uri
import android.util.Base64
import eu.kanade.tachiyomi.extension.es.manhwalatino.filters.UriFilter import eu.kanade.tachiyomi.extension.es.manhwalatino.filters.UriFilter
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
@ -10,6 +12,10 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Response import okhttp3.Response
@ -17,6 +23,7 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import org.jsoup.select.Elements import org.jsoup.select.Elements
import rx.Observable import rx.Observable
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
@ -39,6 +46,8 @@ class ManhwaLatinoSiteParser(
*/ */
private var searchType = SearchType.SEARCH_FREE private var searchType = SearchType.SEARCH_FREE
private val json by injectLazy<Json>()
/** /**
* The Latest Updates are in a Slider, this Methods get a Manga from the slide * The Latest Updates are in a Slider, this Methods get a Manga from the slide
*/ */
@ -251,12 +260,32 @@ class ManhwaLatinoSiteParser(
* @param response the response from the site. * @param response the response from the site.
*/ */
fun getPageListParse(response: Response): List<Page> { fun getPageListParse(response: Response): List<Page> {
val list = val document = response.asJsoup()
response.asJsoup().select(MLConstants.pageListParseSelector) val scripUrl = document.select(MLConstants.pageListParseSelector).attr("src")
.mapIndexed { index, imgElement -> val script = client.newCall(GET(scripUrl, headers)).execute().asJsoup().text()
Page(index, "", getImage(imgElement))
val password = script
.substringAfter("wpmangaprotectornonce='")
.substringBefore("';")
val chapterData = json.parseToJsonElement(
script
.substringAfter("chapter_data='")
.substringBefore("';")
.replace("\\/", "/"),
).jsonObject
val unsaltedCiphertext = Base64.decode(chapterData["ct"]!!.jsonPrimitive.content, Base64.DEFAULT)
val salt = chapterData["s"]!!.jsonPrimitive.content.decodeHex()
val ciphertext = SALTED + salt + unsaltedCiphertext
val rawImgArray = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), password)
val imgArrayString = json.parseToJsonElement(rawImgArray).jsonPrimitive.content
val imgArray = json.parseToJsonElement(imgArrayString).jsonArray
return imgArray.mapIndexed { idx, it ->
Page(idx, document.location(), it.jsonPrimitive.content)
} }
return list
} }
/** /**
@ -329,16 +358,15 @@ class ManhwaLatinoSiteParser(
return imageUrl return imageUrl
} }
/** private fun String.decodeHex(): ByteArray {
* Extract the Image from the Html Element check(length % 2 == 0) { "Must have an even length" }
* The website changes often the attr of the images
* data-src or src return chunked(2)
*/ .map { it.toInt(16).toByte() }
private fun getImage(element: Element): String { .toByteArray()
var imageUrl = element.attr(MLConstants.imageAttribute)
if (imageUrl.isEmpty()) {
imageUrl = element.attr("abs:src")
} }
return imageUrl
companion object {
val SALTED = "Salted__".toByteArray(Charsets.UTF_8)
} }
} }