From e96e9a627dcdf576d14309955ece21c5700373ab Mon Sep 17 00:00:00 2001
From: az4521 <cheeze.sprinkels@gmail.com>
Date: Sun, 27 Sep 2020 13:45:55 -0400
Subject: [PATCH] japscan didnt actually work, whoops (#4447)

* fuck sizurpp

* fix japscan completely

Co-authored-by: Rani Sargees <rani.sargees@gmail.com>
Co-authored-by: az4521 <az4521@mailinator.com>
---
 .../tachiyomi/extension/fr/japscan/Japscan.kt | 64 +++++++++++++------
 1 file changed, 45 insertions(+), 19 deletions(-)

diff --git a/src/fr/japscan/src/eu/kanade/tachiyomi/extension/fr/japscan/Japscan.kt b/src/fr/japscan/src/eu/kanade/tachiyomi/extension/fr/japscan/Japscan.kt
index 60f3dfad8..75d58729e 100644
--- a/src/fr/japscan/src/eu/kanade/tachiyomi/extension/fr/japscan/Japscan.kt
+++ b/src/fr/japscan/src/eu/kanade/tachiyomi/extension/fr/japscan/Japscan.kt
@@ -10,7 +10,9 @@ import android.os.Handler
 import android.os.Looper
 import android.support.v7.preference.ListPreference
 import android.support.v7.preference.PreferenceScreen
+import android.util.Log
 import android.view.View
+import android.webkit.JavascriptInterface
 import android.webkit.WebChromeClient
 import android.webkit.WebResourceRequest
 import android.webkit.WebResourceResponse
@@ -37,6 +39,17 @@ import java.text.ParseException
 import java.text.SimpleDateFormat
 import java.util.Locale
 import java.util.concurrent.CountDownLatch
+import kotlin.collections.ArrayList
+import kotlin.collections.List
+import kotlin.collections.distinctBy
+import kotlin.collections.filter
+import kotlin.collections.first
+import kotlin.collections.forEach
+import kotlin.collections.forEachIndexed
+import kotlin.collections.map
+import kotlin.collections.mapIndexed
+import kotlin.collections.mutableListOf
+import kotlin.collections.toTypedArray
 import okhttp3.FormBody
 import okhttp3.MediaType
 import okhttp3.OkHttpClient
@@ -65,10 +78,20 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
         Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
     }
 
+    internal class JsObject(private val latch: CountDownLatch, var width: Int = 0, var height: Int = 0) {
+        @JavascriptInterface
+        fun passSize(widthjs: Int, ratio: Float) {
+            Log.d("japscan", "wvsc js returned $widthjs, $ratio")
+            width = widthjs
+            height = (width.toFloat() / ratio).toInt()
+            latch.countDown()
+        }
+    }
+
     @SuppressLint("SetJavaScriptEnabled")
     override val client: OkHttpClient = network.cloudflareClient.newBuilder().addInterceptor { chain ->
         val indicator = "&wvsc"
-        val cleanupjs = "var db=document.body,chl=db.children;for(db.appendChild(document.getElementsByTagName('CNV-VV')[0]);'CNV-VV'!=chl[0].tagName;)db.removeChild(chl[0]);for(var i of[].slice.call(chl[0].all_canvas)){i.style.maxWidth=(i.width+\"px\")}window.variable={w:chl[0].all_canvas[0].width,h:chl[0].all_canvas[0].height};"
+        val cleanupjs = "var checkExist=setInterval(function(){if(document.getElementsByTagName('CNV-VV').length){clearInterval(checkExist);var e=document.body,a=e.children;for(e.appendChild(document.getElementsByTagName('CNV-VV')[0]);'CNV-VV'!=a[0].tagName;)e.removeChild(a[0]);for(var t of[].slice.call(a[0].all_canvas))t.style.maxWidth='100%';window.android.passSize(a[0].all_canvas[0].width,a[0].all_canvas[0].width/a[0].all_canvas[0].height)}},100);"
         val request = chain.request()
         val url = request.url().toString()
 
@@ -83,28 +106,25 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
         var webView: WebView? = null
         var height = 0
         var width = 0
-
+        val jsinterface = JsObject(latch)
+        Log.d("japscan", "init wvsc")
         handler.post {
             val webview = WebView(Injekt.get<Application>())
             webView = webview
             webview.settings.javaScriptEnabled = true
             webview.settings.domStorageEnabled = true
             webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
-
+            webview.settings.useWideViewPort = false
+            webview.settings.loadWithOverviewMode = false
+            webview.settings.userAgentString = webview.settings.userAgentString.replace("Mobile", "eliboM").replace("Android", "diordnA")
+            webview.addJavascriptInterface(jsinterface, "android")
+            var retries = 1
             webview.webChromeClient = object : WebChromeClient() {
                 @SuppressLint("NewApi")
                 override fun onProgressChanged(view: WebView, progress: Int) {
-                    if (progress == 100) {
-                        view.evaluateJavascript(cleanupjs) {
-                            if (it.contains('{')) {
-                                val j = JsonParser().parse(it).asJsonObject
-                                width = j["w"].asInt
-                                height = j["h"].asInt
-                                latch.countDown()
-                            } else {
-                                webview.loadUrl(url.replace("&wvsc", ""))
-                            }
-                        }
+                    if (progress == 100 && retries--> 0) {
+                        Log.d("japscan", "wvsc loading finished")
+                        view.evaluateJavascript(cleanupjs) {}
                     }
                 }
             }
@@ -112,11 +132,12 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
         }
 
         latch.await()
-
+        width = jsinterface.width
+        height = jsinterface.height
         // webView!!.isDrawingCacheEnabled = true
 
-        webView!!.measure(width + 100, height + 100)
-        webView!!.layout(0, 0, width + 100, height + 100)
+        webView!!.measure(width, height)
+        webView!!.layout(0, 0, width, height)
         Thread.sleep(350)
 
         val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
@@ -126,8 +147,8 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
         // val bitmap: Bitmap = webView!!.drawingCache
         val output = ByteArrayOutputStream()
         bitmap.compress(Bitmap.CompressFormat.PNG, 100, output)
-
         val rb = ResponseBody.create(MediaType.parse("image/png"), output.toByteArray())
+        handler.post { webView!!.destroy() }
         response.newBuilder().body(rb).build()
     }.build()
 
@@ -312,13 +333,16 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
     }
 
     override fun pageListParse(document: Document): List<Page> {
-        return if (document.getElementsByTag("script").size> 12) { // scrambled images, webview screenshotting
+        return if (document.getElementsByTag("script").filter { it.attr("src").contains("ujs") }.size > 2) { // scrambled images, webview screenshotting
+            Log.d("japscan", "scrambled, loading in WVSC urls")
             document.getElementsByTag("option").mapIndexed { i, it -> Page(i, "", baseUrl + it.attr("value") + "&wvsc") }
         } else {
             // unscrambled images, check for single page
             val zjsurl = document.getElementsByTag("script").first { it.attr("src").contains("zjs", ignoreCase = true) }.attr("src")
+            Log.d("japscan", "ZJS at $zjsurl")
             val zjs = client.newCall(GET(baseUrl + zjsurl, headers)).execute().body()!!.string()
             if ((zjs.toLowerCase().split("new image").size - 1) == 1) { // single page, webview request dumping
+                Log.d("japscan", "webtoon, netdumping initiated")
                 val pagecount = document.getElementsByTag("option").size
                 val pages = ArrayList<Page>()
                 val handler = Handler(Looper.getMainLooper())
@@ -339,6 +363,7 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
                         ): WebResourceResponse? {
                             if (request.url.toString().startsWith("https://c.")) {
                                 pages.add(Page(pages.size, "", request.url.toString()))
+                                Log.d("japscan", "intercepted ${request.url}")
                                 if (pages.size == pagecount) { latch.countDown() }
                                 return WebResourceResponse("image/jpeg", "UTF-8", ByteArrayInputStream(dummystream.toByteArray()))
                             }
@@ -350,6 +375,7 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
                 latch.await()
                 return pages
             } else { // page by page, just do webview screenshotting because it's easier
+                Log.d("japscan", "unscrambled, loading WVSC urls")
                 document.getElementsByTag("option").mapIndexed { i, it -> Page(i, "", baseUrl + it.attr("value") + "&wvsc") }
             }
         }