Tsumino: bypass email protection (#10760)

* Tsumino: bypass email protection

* Rewrite cfDecodeEmail

Use less magic, safety is kept in mind for the key and data.
Invalid key returns an empty string, invalid data is skipped.

Returns not null since the Element.text() function validates
that the input is not null -- and it's probably a useless
distincion anyways.

* further kotlin-ify cfDecodeEmails
This commit is contained in:
Vetle Ledaal 2022-02-09 11:14:22 +00:00 committed by GitHub
parent 383ba02bfc
commit 82d8a2f2ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 7 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'Tsumino' extName = 'Tsumino'
pkgNameSuffix = 'en.tsumino' pkgNameSuffix = 'en.tsumino'
extClass = '.Tsumino' extClass = '.Tsumino'
extVersionCode = 5 extVersionCode = 6
isNsfw = true isNsfw = true
} }

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.extension.en.tsumino package eu.kanade.tachiyomi.extension.en.tsumino
import eu.kanade.tachiyomi.extension.en.tsumino.TsuminoUtils.Companion.cfDecodeEmails
import eu.kanade.tachiyomi.extension.en.tsumino.TsuminoUtils.Companion.getArtists import eu.kanade.tachiyomi.extension.en.tsumino.TsuminoUtils.Companion.getArtists
import eu.kanade.tachiyomi.extension.en.tsumino.TsuminoUtils.Companion.getChapter import eu.kanade.tachiyomi.extension.en.tsumino.TsuminoUtils.Companion.getChapter
import eu.kanade.tachiyomi.extension.en.tsumino.TsuminoUtils.Companion.getCollection import eu.kanade.tachiyomi.extension.en.tsumino.TsuminoUtils.Companion.getCollection
@ -160,13 +161,13 @@ class Tsumino : HttpSource() {
val document = response.asJsoup() val document = response.asJsoup()
val infoElement = document.select("div.book-page-container") val infoElement = document.select("div.book-page-container")
return SManga.create().apply { return SManga.create().apply {
title = infoElement.select("#Title").text() title = document.select("meta[property=og:title]").first()!!.attr("content")
artist = getArtists(document) artist = getArtists(document)
author = artist author = artist
status = SManga.COMPLETED status = SManga.COMPLETED
thumbnail_url = infoElement.select("img").attr("src") thumbnail_url = infoElement.select("img").attr("src")
description = getDesc(document) description = getDesc(document)
genre = document.select("#Tag a").joinToString { it.text() } genre = document.select("#Tag a").joinToString { it.attr("data-define") }
} }
} }
@ -174,6 +175,8 @@ class Tsumino : HttpSource() {
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
val document = response.asJsoup() val document = response.asJsoup()
cfDecodeEmails(document)
val collection = document.select(".book-collection-table a") val collection = document.select(".book-collection-table a")
return if (collection.isNotEmpty()) { return if (collection.isNotEmpty()) {
getCollection(document, ".book-collection-table a") getCollection(document, ".book-collection-table a")

View File

@ -11,7 +11,7 @@ class TsuminoUtils {
val artists = document.select("#Artist a") val artists = document.select("#Artist a")
artists.forEach { artists.forEach {
stringBuilder.append(it.text()) stringBuilder.append(it.attr("data-define"))
if (it != artists.last()) if (it != artists.last())
stringBuilder.append(", ") stringBuilder.append(", ")
@ -25,7 +25,7 @@ class TsuminoUtils {
val groups = document.select("#Group a") val groups = document.select("#Group a")
groups.forEach { groups.forEach {
stringBuilder.append(it.text()) stringBuilder.append(it.attr("data-define"))
if (it != groups.last()) if (it != groups.last())
stringBuilder.append(", ") stringBuilder.append(", ")
@ -47,7 +47,7 @@ class TsuminoUtils {
stringBuilder.append("Parodies: ") stringBuilder.append("Parodies: ")
parodies.forEach { parodies.forEach {
stringBuilder.append(it.text()) stringBuilder.append(it.attr("data-define"))
if (it != parodies.last()) if (it != parodies.last())
stringBuilder.append(", ") stringBuilder.append(", ")
@ -59,7 +59,7 @@ class TsuminoUtils {
stringBuilder.append("Characters: ") stringBuilder.append("Characters: ")
characters.forEach { characters.forEach {
stringBuilder.append(it.text()) stringBuilder.append(it.attr("data-define"))
if (it != characters.last()) if (it != characters.last())
stringBuilder.append(", ") stringBuilder.append(", ")
@ -93,5 +93,26 @@ class TsuminoUtils {
chapterList.add(chapter) chapterList.add(chapter)
return chapterList return chapterList
} }
fun cfDecodeEmails(document: Document) {
document.select(".__cf_email__")!!
.map { it to cfDecodeEmail(it.attr("data-cfemail")) }
.forEach { (element, plaintext) -> element.text(plaintext) }
}
fun cfDecodeEmail(encoded: String): String {
val encodedList = encoded
.chunked(2)
.map { it.toIntOrNull(16) }
val key = encodedList
.firstOrNull()
?: return ""
return encodedList
.drop(1)
.mapNotNull { it?.xor(key)?.toChar() }
.joinToString("")
}
} }
} }