From d07a8f28bf10f44efb94718761c075b7eec1ce94 Mon Sep 17 00:00:00 2001 From: Claudemirovsky <63046606+Claudemirovsky@users.noreply.github.com> Date: Sat, 6 May 2023 09:50:45 -0300 Subject: [PATCH] [skip ci]refactor(lib): General refactoration (#1579) --- .../CloudflareInterceptor.kt | 3 -- .../tachiyomi/lib/cryptoaes/CryptoAES.kt | 38 ++++++++++------- .../lib/dataimage/DataImageInterceptor.kt | 24 +++++------ .../lib/doodextractor/DoodExtractor.kt | 24 +++++------ lib/fembed-extractor/build.gradle.kts | 1 - .../lib/fembedextractor/FembedExtractor.kt | 38 ++++++++++------- .../lib/fembedextractor/FembedExtractorDto.kt | 6 +-- lib/mixdrop-extractor/build.gradle.kts | 1 - lib/okru-extractor/build.gradle.kts | 2 +- .../lib/okruextractor/OkruExtractor.kt | 22 ++++++---- .../streamsbextractor/StreamSBExtractor.kt | 42 +++++++++---------- .../streamsbextractor/StreamSBExtractorDto.kt | 6 +-- .../StreamTapeExtractor.kt | 2 +- .../tachiyomi/lib/synchrony/Deobfuscator.kt | 18 ++++---- .../YourUploadExtractor.kt | 2 +- .../tachiyomi/multisrc/dooplay/DooPlay.kt | 13 +++--- 16 files changed, 124 insertions(+), 118 deletions(-) diff --git a/lib/cloudflare-interceptor/src/main/java/eu/kanade/tachiyomi/lib/cloudflareinterceptor/CloudflareInterceptor.kt b/lib/cloudflare-interceptor/src/main/java/eu/kanade/tachiyomi/lib/cloudflareinterceptor/CloudflareInterceptor.kt index 1093a9a83..22eef2430 100644 --- a/lib/cloudflare-interceptor/src/main/java/eu/kanade/tachiyomi/lib/cloudflareinterceptor/CloudflareInterceptor.kt +++ b/lib/cloudflare-interceptor/src/main/java/eu/kanade/tachiyomi/lib/cloudflareinterceptor/CloudflareInterceptor.kt @@ -8,7 +8,6 @@ import android.webkit.CookieManager import android.webkit.JavascriptInterface import android.webkit.WebView import android.webkit.WebViewClient -import eu.kanade.tachiyomi.network.NetworkHelper import okhttp3.Cookie import okhttp3.HttpUrl import okhttp3.Interceptor @@ -22,7 +21,6 @@ import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit class CloudflareInterceptor(private val client: OkHttpClient) : Interceptor { - private val network: NetworkHelper by injectLazy() private val context: Application by injectLazy() private val handler by lazy { Handler(Looper.getMainLooper()) } @@ -141,7 +139,6 @@ class CloudflareInterceptor(private val client: OkHttpClient) : Interceptor { companion object { private val ERROR_CODES = listOf(403, 503) private val SERVER_CHECK = arrayOf("cloudflare-nginx", "cloudflare") - private val COOKIE_NAMES = listOf("cf_clearance") // ref: https://github.com/vvanglro/cf-clearance/blob/0d3455b5b4f299b131f357dd6e0a27316cf26f9a/cf_clearance/retry.py#L15 private val CHECK_SCRIPT by lazy { diff --git a/lib/cryptoaes/src/main/java/eu/kanade/tachiyomi/lib/cryptoaes/CryptoAES.kt b/lib/cryptoaes/src/main/java/eu/kanade/tachiyomi/lib/cryptoaes/CryptoAES.kt index 69b0221c8..5859d3efe 100644 --- a/lib/cryptoaes/src/main/java/eu/kanade/tachiyomi/lib/cryptoaes/CryptoAES.kt +++ b/lib/cryptoaes/src/main/java/eu/kanade/tachiyomi/lib/cryptoaes/CryptoAES.kt @@ -23,8 +23,9 @@ import javax.crypto.spec.SecretKeySpec @Suppress("unused") object CryptoAES { - private const val KEY_SIZE = 256 - private const val IV_SIZE = 128 + private const val KEY_SIZE = 32 // 256 bits + private const val IV_SIZE = 16 // 128 bits + private const val SALT_SIZE = 8 // 64 bits private const val HASH_CIPHER = "AES/CBC/PKCS7PADDING" private const val HASH_CIPHER_FALLBACK = "AES/CBC/PKCS5PADDING" private const val AES = "AES" @@ -41,14 +42,14 @@ object CryptoAES { fun decrypt(cipherText: String, password: String): String { return try { val ctBytes = Base64.decode(cipherText, Base64.DEFAULT) - val saltBytes = Arrays.copyOfRange(ctBytes, 8, 16) - val cipherTextBytes = Arrays.copyOfRange(ctBytes, 16, ctBytes.size) - val md5: MessageDigest = MessageDigest.getInstance("MD5") - val keyAndIV = generateKeyAndIV(32, 16, 1, saltBytes, password.toByteArray(Charsets.UTF_8), md5) + val saltBytes = Arrays.copyOfRange(ctBytes, SALT_SIZE, IV_SIZE) + val cipherTextBytes = Arrays.copyOfRange(ctBytes, IV_SIZE, ctBytes.size) + val md5 = MessageDigest.getInstance("MD5") + val keyAndIV = generateKeyAndIV(KEY_SIZE, IV_SIZE, 1, saltBytes, password.toByteArray(Charsets.UTF_8), md5) decryptAES( cipherTextBytes, - keyAndIV?.get(0) ?: ByteArray(32), - keyAndIV?.get(1) ?: ByteArray(16), + keyAndIV?.get(0) ?: ByteArray(KEY_SIZE), + keyAndIV?.get(1) ?: ByteArray(IV_SIZE), ) } catch (e: Exception) { "" @@ -60,17 +61,17 @@ object CryptoAES { val ctBytes = Base64.decode(cipherText, Base64.DEFAULT) val md5: MessageDigest = MessageDigest.getInstance("MD5") val keyAndIV = generateKeyAndIV( - 32, - 16, + KEY_SIZE, + IV_SIZE, 1, salt.decodeHex(), password.toByteArray(Charsets.UTF_8), - md5 + md5, ) decryptAES( ctBytes, - keyAndIV?.get(0) ?: ByteArray(32), - keyAndIV?.get(1) ?: ByteArray(16), + keyAndIV?.get(0) ?: ByteArray(KEY_SIZE), + keyAndIV?.get(1) ?: ByteArray(IV_SIZE), ) } catch (e: Exception) { "" @@ -129,7 +130,14 @@ object CryptoAES { * @param md the message digest algorithm to use * @return an two-element array with the generated key and IV */ - private fun generateKeyAndIV(keyLength: Int, ivLength: Int, iterations: Int, salt: ByteArray, password: ByteArray, md: MessageDigest): Array? { + private fun generateKeyAndIV( + keyLength: Int, + ivLength: Int, + iterations: Int, + salt: ByteArray, + password: ByteArray, + md: MessageDigest, + ): Array? { val digestLength = md.digestLength val requiredLength = (keyLength + ivLength + digestLength - 1) / digestLength * digestLength val generatedData = ByteArray(requiredLength) @@ -142,7 +150,7 @@ object CryptoAES { // Digest data (last digest if available, password data, salt if available) if (generatedLength > 0) md.update(generatedData, generatedLength - digestLength, digestLength) md.update(password) - md.update(salt, 0, 8) + md.update(salt, 0, SALT_SIZE) md.digest(generatedData, generatedLength, digestLength) // additional rounds diff --git a/lib/dataimage/src/main/java/eu/kanade/tachiyomi/lib/dataimage/DataImageInterceptor.kt b/lib/dataimage/src/main/java/eu/kanade/tachiyomi/lib/dataimage/DataImageInterceptor.kt index 3599a8910..6df21c6e6 100644 --- a/lib/dataimage/src/main/java/eu/kanade/tachiyomi/lib/dataimage/DataImageInterceptor.kt +++ b/lib/dataimage/src/main/java/eu/kanade/tachiyomi/lib/dataimage/DataImageInterceptor.kt @@ -13,26 +13,22 @@ import org.jsoup.nodes.Element */ /** - * Use if the attribute tag could have a data:image string or URL - * Transforms data:image in to a fake URL that OkHttp won't die on + * Use if the attribute tag has a data:image string but real URLs are on a different attribute */ -fun Element.dataImageAsUrl(attr: String): String { - return if (this.attr(attr).startsWith("data")) { - "https://127.0.0.1/?" + this.attr(attr).substringAfter(":") +fun Element.dataImageAsUrlOrNull(attr: String): String? { + return if (attr(attr).startsWith("data")) { + "https://127.0.0.1/?" + attr(attr).substringAfter(":") } else { - this.attr("abs:$attr") + null } } /** - * Use if the attribute tag has a data:image string but real URLs are on a different attribute + * Use if the attribute tag could have a data:image string or URL + * Transforms data:image in to a fake URL that OkHttp won't die on */ -fun Element.dataImageAsUrlOrNull(attr: String): String? { - return if (this.attr(attr).startsWith("data")) { - "https://127.0.0.1/?" + this.attr(attr).substringAfter(":") - } else { - null - } +fun Element.dataImageAsUrl(attr: String): String { + return dataImageAsUrlOrNull(attr) ?: attr("abs:$attr") } /** @@ -51,7 +47,7 @@ class DataImageInterceptor : Interceptor { } else { dataString.substringAfter(",").toByteArray() } - val mediaType = mediaTypePattern.find(dataString)!!.value.toMediaTypeOrNull() + val mediaType = mediaTypePattern.find(dataString)?.value?.toMediaTypeOrNull() Response.Builder().body(byteArray.toResponseBody(mediaType)) .request(chain.request()) .protocol(Protocol.HTTP_1_0) diff --git a/lib/dood-extractor/src/main/java/eu/kanade/tachiyomi/lib/doodextractor/DoodExtractor.kt b/lib/dood-extractor/src/main/java/eu/kanade/tachiyomi/lib/doodextractor/DoodExtractor.kt index 3b1da2bf1..e7ebecd34 100644 --- a/lib/dood-extractor/src/main/java/eu/kanade/tachiyomi/lib/doodextractor/DoodExtractor.kt +++ b/lib/dood-extractor/src/main/java/eu/kanade/tachiyomi/lib/doodextractor/DoodExtractor.kt @@ -10,14 +10,14 @@ class DoodExtractor(private val client: OkHttpClient) { fun videoFromUrl( url: String, quality: String? = null, - redirect: Boolean = true + redirect: Boolean = true, ): Video? { - val newQuality = quality ?: "Doodstream" + if(redirect) " mirror" else "" - - return try { + val newQuality = quality ?: "Doodstream" + if (redirect) " mirror" else "" + + return runCatching { val response = client.newCall(GET(url)).execute() - val newUrl = if(redirect) response.request.url.toString() else url - + val newUrl = if (redirect) response.request.url.toString() else url + val doodTld = newUrl.substringAfter("https://dood.").substringBefore("/") val content = response.body.string() if (!content.contains("'/pass_md5/")) return null @@ -28,23 +28,21 @@ class DoodExtractor(private val client: OkHttpClient) { val videoUrlStart = client.newCall( GET( "https://dood.$doodTld/pass_md5/$md5", - Headers.headersOf("referer", newUrl) - ) + Headers.headersOf("referer", newUrl), + ), ).execute().body.string() val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry" Video(newUrl, newQuality, videoUrl, headers = doodHeaders(doodTld)) - } catch (e: Exception) { - null - } + }.getOrNull() } fun videosFromUrl( url: String, quality: String? = null, - redirect: Boolean = true + redirect: Boolean = true, ): List