From 02463e58331d60b61bacfe0d145a2410644cd9ce Mon Sep 17 00:00:00 2001 From: Koitharu Date: Fri, 10 Nov 2023 10:55:43 +0200 Subject: [PATCH] [MangaReader] Fix NetShield bypass --- .../site/mangareader/MangaReaderParser.kt | 29 ++++++++++++++----- .../parsers/site/mangareader/ar/SwaTeam.kt | 1 + .../site/mangareader/id/MangaSusuku.kt | 1 + .../site/mangareader/tr/AfroditScans.kt | 1 + .../koitharu/kotatsu/parsers/util/OkHttp.kt | 6 +++- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt index d34ad65c..0c573b3f 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt @@ -8,6 +8,7 @@ import okhttp3.Cookie import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Interceptor import okhttp3.Response +import okhttp3.internal.closeQuietly import org.json.JSONObject import org.jsoup.nodes.Document import org.koitharu.kotatsu.parsers.MangaLoaderContext @@ -33,6 +34,7 @@ internal abstract class MangaReaderParser( protected open val listUrl = "/manga" protected open val datePattern = "MMMM d, yyyy" + protected open val isNetShieldProtected = false private var tagCache: ArrayMap? = null private val mutex = Mutex() @@ -304,20 +306,31 @@ internal abstract class MangaReaderParser( override fun intercept(chain: Interceptor.Chain): Response { val response = chain.proceed(chain.request()) - if (context.cookieJar.getCookies(domain).none { it.name.contains("NetShield") }) { - val cookie = runBlocking { response.parseHtml().getNetShieldCookie() } ?: return response + if (!isNetShieldProtected) { + return response + } + val contentType = response.mimeType + if ( + contentType?.endsWith("/html") != false && + context.cookieJar.getCookies(domain).none { it.name.contains("NetShield") } + ) { + val cookie = runBlocking { response.copy().parseHtml().getNetShieldCookie() } ?: return response context.cookieJar.insertCookie(domain, cookie) - return chain.proceed(response.request.newBuilder().build()) + return chain.proceed(response.request.newBuilder().build()).also { + response.closeQuietly() + } } return response } - private suspend fun Document.getNetShieldCookie(): Cookie? { + private suspend fun Document.getNetShieldCookie(): Cookie? = runCatchingCancellable { val script = select("script").firstNotNullOfOrNull { s -> s.html().takeIf { x -> x.contains("slowAES.decrypt") } - } ?: return null + } ?: return@runCatchingCancellable null val min = webClient.httpGet("https://$domain/min.js").parseRaw() - val res = context.evaluateJs(min + "\n\n" + script.replace("document.cookie =", "return")) - return Cookie.parse(baseUri().toHttpUrl(), res ?: return null) - } + val res = context.evaluateJs(min + "\n\n" + script.replace(Regex("document.cookie\\s*=\\s*"), "return ")) + res?.let { + Cookie.parse(baseUri().toHttpUrl(), it) + } + }.getOrNull() } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/SwaTeam.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/SwaTeam.kt index 88a6c015..eb82d9f9 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/SwaTeam.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/SwaTeam.kt @@ -15,6 +15,7 @@ internal class SwaTeam(context: MangaLoaderContext) : override val datePattern = "MMMM dd, yyyy" override val selectMangaList = ".listupd .bs .bsx" override val selectMangaListImg = "img" + override val isNetShieldProtected = true override suspend fun getListPage( page: Int, diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/MangaSusuku.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/MangaSusuku.kt index ded54041..76fe6abe 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/MangaSusuku.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/MangaSusuku.kt @@ -13,4 +13,5 @@ internal class MangaSusuku(context: MangaLoaderContext) : override val listUrl = "/komik" override val datePattern = "MMM d, yyyy" override val sourceLocale: Locale = Locale.ENGLISH + override val isNetShieldProtected = true } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AfroditScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AfroditScans.kt index 469fe6b2..de9f7c3d 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AfroditScans.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AfroditScans.kt @@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser internal class AfroditScans(context: MangaLoaderContext) : MangaReaderParser(context, MangaSource.AFRODITSCANS, "afroditscans.com", pageSize = 20, searchPageSize = 10) { override val datePattern = "MMM d, yyyy" + override val isNetShieldProtected = true } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/OkHttp.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/OkHttp.kt index c4f37074..b8673cd5 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/OkHttp.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/OkHttp.kt @@ -14,7 +14,7 @@ suspend fun Call.await(): Response = suspendCancellableCoroutine { continuation } val Response.mimeType: String? - get() = body?.contentType()?.run { "$type/$subtype" } + get() = header("content-type")?.takeUnless { it.isEmpty() } val Response.contentDisposition: String? get() = header("Content-Disposition") @@ -27,3 +27,7 @@ fun Headers.Builder.mergeWith(other: Headers, replaceExisting: Boolean): Headers } return this } + +fun Response.copy() = newBuilder() + .body(peekBody(Long.MAX_VALUE)) + .build()