diff --git a/multisrc/overrides/fmreader/heroscan/additional.gradle.kts b/multisrc/overrides/fmreader/heroscan/additional.gradle.kts deleted file mode 100644 index 10beb8157..000000000 --- a/multisrc/overrides/fmreader/heroscan/additional.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ - -dependencies { - implementation project(':lib-ratelimit') -} diff --git a/multisrc/overrides/fmreader/heroscan/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/fmreader/heroscan/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 807361f17..000000000 Binary files a/multisrc/overrides/fmreader/heroscan/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/heroscan/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/fmreader/heroscan/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 5892088bb..000000000 Binary files a/multisrc/overrides/fmreader/heroscan/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/heroscan/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/fmreader/heroscan/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 8049a51db..000000000 Binary files a/multisrc/overrides/fmreader/heroscan/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/heroscan/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/fmreader/heroscan/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 6049f5f25..000000000 Binary files a/multisrc/overrides/fmreader/heroscan/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/heroscan/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/fmreader/heroscan/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index a3033af3d..000000000 Binary files a/multisrc/overrides/fmreader/heroscan/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/heroscan/res/web_hi_res_512.png b/multisrc/overrides/fmreader/heroscan/res/web_hi_res_512.png deleted file mode 100644 index e36bee415..000000000 Binary files a/multisrc/overrides/fmreader/heroscan/res/web_hi_res_512.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/heroscan/src/HeroScan.kt b/multisrc/overrides/fmreader/heroscan/src/HeroScan.kt deleted file mode 100644 index b8ff109b7..000000000 --- a/multisrc/overrides/fmreader/heroscan/src/HeroScan.kt +++ /dev/null @@ -1,24 +0,0 @@ -package eu.kanade.tachiyomi.extension.en.heroscan - -import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor -import eu.kanade.tachiyomi.multisrc.fmreader.FMReader -import eu.kanade.tachiyomi.source.model.SChapter -import okhttp3.OkHttpClient - -class HeroScan : FMReader("HeroScan", "https://heroscan.com", "en") { - override val client: OkHttpClient = super.client.newBuilder() - .addInterceptor(RateLimitInterceptor(1)) - .addInterceptor { chain -> - val originalRequest = chain.request() - chain.proceed(originalRequest).let { response -> - if (response.code == 403 && originalRequest.url.host.contains("b-cdn")) { - response.close() - chain.proceed(originalRequest.newBuilder().removeHeader("Referer").addHeader("Referer", "https://isekaiscan.com").build()) - } else { - response - } - } - } - .build() - override fun fetchPageList(chapter: SChapter) = fetchPageListEncrypted(chapter) -} diff --git a/multisrc/overrides/fmreader/manhuascan/additional.gradle.kts b/multisrc/overrides/fmreader/manhuascan/additional.gradle.kts deleted file mode 100644 index 10beb8157..000000000 --- a/multisrc/overrides/fmreader/manhuascan/additional.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ - -dependencies { - implementation project(':lib-ratelimit') -} diff --git a/multisrc/overrides/fmreader/manhuascan/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhuascan/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index f681db5df..000000000 Binary files a/multisrc/overrides/fmreader/manhuascan/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhuascan/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhuascan/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index fe8f00294..000000000 Binary files a/multisrc/overrides/fmreader/manhuascan/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhuascan/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhuascan/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 3a3949382..000000000 Binary files a/multisrc/overrides/fmreader/manhuascan/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhuascan/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhuascan/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 97150c7b0..000000000 Binary files a/multisrc/overrides/fmreader/manhuascan/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhuascan/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhuascan/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index d70cd3dd7..000000000 Binary files a/multisrc/overrides/fmreader/manhuascan/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhuascan/res/web_hi_res_512.png b/multisrc/overrides/fmreader/manhuascan/res/web_hi_res_512.png deleted file mode 100644 index 5af1f3ca1..000000000 Binary files a/multisrc/overrides/fmreader/manhuascan/res/web_hi_res_512.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhuascan/src/ManhuaScan.kt b/multisrc/overrides/fmreader/manhuascan/src/ManhuaScan.kt deleted file mode 100644 index e254ffb84..000000000 --- a/multisrc/overrides/fmreader/manhuascan/src/ManhuaScan.kt +++ /dev/null @@ -1,15 +0,0 @@ -package eu.kanade.tachiyomi.extension.en.manhuascan - -import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor -import eu.kanade.tachiyomi.multisrc.fmreader.FMReader -import eu.kanade.tachiyomi.source.model.SChapter -import eu.kanade.tachiyomi.annotations.Nsfw -import okhttp3.OkHttpClient - -@Nsfw -class ManhuaScan : FMReader("ManhuaScan", "https://manhuascan.com", "en") { - override val client: OkHttpClient = super.client.newBuilder() - .addInterceptor(RateLimitInterceptor(1)) - .build() - override fun fetchPageList(chapter: SChapter) = fetchPageListEncrypted(chapter) -} diff --git a/multisrc/overrides/fmreader/manhwahot/additional.gradle.kts b/multisrc/overrides/fmreader/manhwahot/additional.gradle.kts deleted file mode 100644 index 10beb8157..000000000 --- a/multisrc/overrides/fmreader/manhwahot/additional.gradle.kts +++ /dev/null @@ -1,4 +0,0 @@ - -dependencies { - implementation project(':lib-ratelimit') -} diff --git a/multisrc/overrides/fmreader/manhwahot/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhwahot/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 1f083f585..000000000 Binary files a/multisrc/overrides/fmreader/manhwahot/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhwahot/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhwahot/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 0a30f1395..000000000 Binary files a/multisrc/overrides/fmreader/manhwahot/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhwahot/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhwahot/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 93d125c01..000000000 Binary files a/multisrc/overrides/fmreader/manhwahot/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhwahot/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhwahot/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 936dde5d3..000000000 Binary files a/multisrc/overrides/fmreader/manhwahot/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhwahot/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/fmreader/manhwahot/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index a946f15b4..000000000 Binary files a/multisrc/overrides/fmreader/manhwahot/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhwahot/res/web_hi_res_512.png b/multisrc/overrides/fmreader/manhwahot/res/web_hi_res_512.png deleted file mode 100644 index a273fb541..000000000 Binary files a/multisrc/overrides/fmreader/manhwahot/res/web_hi_res_512.png and /dev/null differ diff --git a/multisrc/overrides/fmreader/manhwahot/src/ManhwaHot.kt b/multisrc/overrides/fmreader/manhwahot/src/ManhwaHot.kt deleted file mode 100644 index b4de74e6f..000000000 --- a/multisrc/overrides/fmreader/manhwahot/src/ManhwaHot.kt +++ /dev/null @@ -1,15 +0,0 @@ -package eu.kanade.tachiyomi.extension.en.manhwahot - -import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor -import eu.kanade.tachiyomi.annotations.Nsfw -import eu.kanade.tachiyomi.multisrc.fmreader.FMReader -import eu.kanade.tachiyomi.source.model.SChapter -import okhttp3.OkHttpClient - -@Nsfw -class ManhwaHot : FMReader("ManhwaHot", "https://manhwahot.com", "en") { - override val client: OkHttpClient = super.client.newBuilder() - .addInterceptor(RateLimitInterceptor(1)) - .build() - override fun fetchPageList(chapter: SChapter) = fetchPageListEncrypted(chapter) -} diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/fmreader/FMReader.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/fmreader/FMReader.kt index 1d86aa297..c28bf48cd 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/fmreader/FMReader.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/fmreader/FMReader.kt @@ -1,10 +1,7 @@ package eu.kanade.tachiyomi.multisrc.fmreader import android.util.Base64 -import com.google.gson.JsonParser import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.POST -import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.MangasPage @@ -15,26 +12,14 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.util.asJsoup import okhttp3.Headers import okhttp3.HttpUrl.Companion.toHttpUrlOrNull -import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.OkHttpClient import okhttp3.Request -import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.Response -import okio.ByteString -import okio.ByteString.Companion.decodeBase64 -import okio.ByteString.Companion.decodeHex import org.jsoup.nodes.Document import org.jsoup.nodes.Element import org.jsoup.select.Elements -import rx.Observable import java.nio.charset.Charset -import java.security.MessageDigest import java.util.Calendar -import javax.crypto.BadPaddingException -import javax.crypto.Cipher -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.SecretKeySpec - /** * For sites based on the Flat-Manga CMS */ @@ -328,32 +313,6 @@ abstract class FMReader( } } - /** - * fetches the pageList by decrypting and parsing the json response of a "chapter server" - * Meant to be used by relevant subclasses to replace their implementation of fetchPageList as needed - * e.g ManhuaScan, HeroScan - */ - protected fun fetchPageListEncrypted(chapter: SChapter): Observable> { - fun stringAssignment(varname: String, script: String) = Regex("""(?:let|var)\s+$varname\s*=\s*"([^"]*)"""").find(script)?.groups?.get(1)?.value - fun pageList(s: String) = Regex("https.+?(?=https|\"$)").findAll(s).map { it.groups[0]!!.value.replace("\\/", "/") } - fun pageListRequest(id: String, server: Int = 1) = POST("$baseUrl/app/manga/controllers/cont.chapterServer$server.php", headers, "id=$id".toRequestBody("application/x-www-form-urlencoded; charset=UTF-8".toMediaTypeOrNull())) - return client.newCall(GET("$baseUrl${chapter.url}", headers)).asObservableSuccess().concatMap { htmlResponse -> - val soup = htmlResponse.asJsoup() - soup.selectFirst("head > script[type='text/javascript']")?.data()?.let { params -> - stringAssignment("chapter_id", params)?.let { chapterId -> - client.newCall(pageListRequest(chapterId)).asObservableSuccess() - .map { jsonResponse -> - try { - pageList(crypto.aes_decrypt(jsonResponse.body!!.string(), "4xje8fvkub2d3mb5cy9rv661zyjakbcn".toByteArray())) - .mapIndexed { i, imgUrl -> Page(i, "", imgUrl) }.toList() - } catch (_: BadPaddingException) { - throw RuntimeException("Decryption Failed") - } - } - } - } ?: Observable.just(emptyList()) - } - } override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used") @@ -513,74 +472,4 @@ abstract class FMReader( Genre("Zombies") ) - companion object { - interface Crypto { - fun md5(s: String): String; - fun aes_decrypt(context: String, key: ByteArray): String; - } - - /* cryptography utilities leveraged by fetchPageListEncrypted */ - val crypto = object : Crypto { - private fun parseCryptoCT(s: String): Map { - // https://cryptojs.gitbook.io/docs/ - val jsonObj = JsonParser.parseString(s).asJsonObject - val cipherParams = mutableMapOf("ciphertext" to jsonObj["ct"].asString.decodeBase64()!!) - jsonObj["iv"]?.let { cipherParams.put("iv", it.asString.decodeHex()) } - jsonObj["s"]?.let { cipherParams.put("salt", it.asString.decodeHex()) } - return cipherParams - } - - private fun decryptAES(encrypted: ByteString, password: ByteArray, iv: ByteString, salt: ByteString): String { - // https://stackoverflow.com/questions/29151211/29152379#29152379 - val (key, _iv) = EvpKDF(password, 256, 128, salt.toByteArray(), 1, "MD5") - val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") - cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(_iv)) - return String(cipher.doFinal(encrypted.toByteArray()), Charset.forName("UTF-8")) - } - - private fun EvpKDF(password: ByteArray, _keySize: Int, _ivSize: Int, salt: ByteArray, iterations: Int, hashAlgorithm: String): Pair { - // Key Derivation Function - val keySize = _keySize / 32 - val ivSize = _ivSize / 32 - val targetKeySize = keySize + ivSize - val derivedBytes = ByteArray(targetKeySize * 4) - var numberOfDerivedWords = 0 - var block = ByteArray(0) - val hasher = MessageDigest.getInstance(hashAlgorithm) - val key = ByteArray(keySize * 4) - val iv = ByteArray(ivSize * 4) - while (numberOfDerivedWords < targetKeySize) { - if (block != null) { - hasher.update(block) - } - hasher.update(password) - block = hasher.digest(salt) - hasher.reset() - - // Iterations - for (i in 1 until iterations) { - block = hasher.digest(block) - hasher.reset() - } - - System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4, - block.size.coerceAtMost((targetKeySize - numberOfDerivedWords) * 4)) - - numberOfDerivedWords += block.size / 4 - } - - System.arraycopy(derivedBytes, 0, key, 0, key.size) - System.arraycopy(derivedBytes, key.size, iv, 0, iv.size) - - return key to iv // key + iv - } - - override fun md5(s: String): String = MessageDigest.getInstance("MD5").digest(s.toByteArray()).joinToString("") { String.format("%02x", it) } - - override fun aes_decrypt(context: String, key: ByteArray): String { - val cipherParams = parseCryptoCT(JsonParser.parseString(context).asJsonObject["content"].asString) - return decryptAES(cipherParams["ciphertext"]!!, key, cipherParams["iv"]!!, cipherParams["salt"]!!) - } - } - } } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/fmreader/FMReaderGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/fmreader/FMReaderGenerator.kt index 08d8fa476..22c6ca8fb 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/fmreader/FMReaderGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/fmreader/FMReaderGenerator.kt @@ -17,17 +17,14 @@ class FMReaderGenerator : ThemeSourceGenerator { override val sources = listOf( SingleLang("Epik Manga", "https://www.epikmanga.com", "tr"), - SingleLang("HeroScan", "https://heroscan.com", "en", overrideVersionCode = 2), SingleLang("KissLove", "https://kissaway.net", "ja"), SingleLang("LHTranslation", "https://lhtranslation.net", "en", overrideVersionCode = 1), SingleLang("Manga-TR", "https://manga-tr.com", "tr", className = "MangaTR"), - SingleLang("ManhuaScan", "https://manhuascan.com", "en", isNsfw = true, overrideVersionCode = 3), SingleLang("Manhwa18", "https://manhwa18.com", "en", isNsfw = true), MultiLang("Manhwa18.net", "https://manhwa18.net", listOf("en", "ko"), className = "Manhwa18NetFactory", isNsfw = true), SingleLang("RawLH", "https://lovehug.net", "ja"), SingleLang("Say Truyen", "https://saytruyen.com", "vi"), SingleLang("KSGroupScans", "https://ksgroupscans.com", "en"), - SingleLang("ManhwaHot", "https://manhwahot.com", "en", isNsfw = true, overrideVersionCode=1), // Sites that went down //SingleLang("18LHPlus", "https://18lhplus.com", "en", className = "EighteenLHPlus"), //SingleLang("HanaScan (RawQQ)", "https://hanascan.com", "ja", className = "HanaScanRawQQ"),