mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 22:37:56 +01:00 
			
		
		
		
	Only show Webview update prompt if CF bypass fails
This commit is contained in:
		| @@ -7,8 +7,11 @@ import android.os.Handler | ||||
| import android.os.Looper | ||||
| import android.webkit.WebSettings | ||||
| import android.webkit.WebView | ||||
| import android.widget.Toast | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.util.system.WebViewClientCompat | ||||
| import eu.kanade.tachiyomi.util.system.checkVersion | ||||
| import eu.kanade.tachiyomi.util.system.isOutdated | ||||
| import eu.kanade.tachiyomi.util.system.toast | ||||
| import okhttp3.Cookie | ||||
| import okhttp3.HttpUrl.Companion.toHttpUrl | ||||
| import okhttp3.Interceptor | ||||
| @@ -21,8 +24,6 @@ import java.util.concurrent.TimeUnit | ||||
|  | ||||
| class CloudflareInterceptor(private val context: Context) : Interceptor { | ||||
|  | ||||
|     private val serverCheck = arrayOf("cloudflare-nginx", "cloudflare") | ||||
|  | ||||
|     private val handler = Handler(Looper.getMainLooper()) | ||||
|  | ||||
|     private val networkHelper: NetworkHelper by injectLazy() | ||||
| @@ -44,36 +45,35 @@ class CloudflareInterceptor(private val context: Context) : Interceptor { | ||||
|         val response = chain.proceed(originalRequest) | ||||
|  | ||||
|         // Check if Cloudflare anti-bot is on | ||||
|         if (response.code == 503 && response.header("Server") in serverCheck) { | ||||
|             try { | ||||
|                 response.close() | ||||
|                 networkHelper.cookieManager.remove(originalRequest.url, listOf("__cfduid", "cf_clearance"), 0) | ||||
|                 val oldCookie = networkHelper.cookieManager.get(originalRequest.url) | ||||
|                         .firstOrNull { it.name == "cf_clearance" } | ||||
|                 return if (resolveWithWebView(originalRequest, oldCookie)) { | ||||
|                     chain.proceed(originalRequest) | ||||
|                 } else { | ||||
|                     throw IOException("Failed to bypass Cloudflare!") | ||||
|                 } | ||||
|             } catch (e: Exception) { | ||||
|                 // Because OkHttp's enqueue only handles IOExceptions, wrap the exception so that | ||||
|                 // we don't crash the entire app | ||||
|                 throw IOException(e) | ||||
|             } | ||||
|         if (response.code != 503 || response.header("Server") !in SERVER_CHECK) { | ||||
|             return response | ||||
|         } | ||||
|  | ||||
|         return response | ||||
|         try { | ||||
|             response.close() | ||||
|             networkHelper.cookieManager.remove(originalRequest.url, COOKIE_NAMES, 0) | ||||
|             val oldCookie = networkHelper.cookieManager.get(originalRequest.url) | ||||
|                     .firstOrNull { it.name == "cf_clearance" } | ||||
|             resolveWithWebView(originalRequest, oldCookie) | ||||
|             return chain.proceed(originalRequest) | ||||
|         } catch (e: Exception) { | ||||
|             // Because OkHttp's enqueue only handles IOExceptions, wrap the exception so that | ||||
|             // we don't crash the entire app | ||||
|             throw IOException(e) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @SuppressLint("SetJavaScriptEnabled") | ||||
|     private fun resolveWithWebView(request: Request, oldCookie: Cookie?): Boolean { | ||||
|     private fun resolveWithWebView(request: Request, oldCookie: Cookie?) { | ||||
|         // We need to lock this thread until the WebView finds the challenge solution url, because | ||||
|         // OkHttp doesn't support asynchronous interceptors. | ||||
|         val latch = CountDownLatch(1) | ||||
|  | ||||
|         var webView: WebView? = null | ||||
|  | ||||
|         var challengeFound = false | ||||
|         var cloudflareBypassed = false | ||||
|         var isWebviewOutdated = false | ||||
|  | ||||
|         val origRequestUrl = request.url.toString() | ||||
|         val headers = request.headers.toMultimap().mapValues { it.value.getOrNull(0) ?: "" } | ||||
| @@ -82,8 +82,6 @@ class CloudflareInterceptor(private val context: Context) : Interceptor { | ||||
|             val webview = WebView(context) | ||||
|             webView = webview | ||||
|  | ||||
|             webview.checkVersion() | ||||
|  | ||||
|             webview.settings.javaScriptEnabled = true | ||||
|             webview.settings.userAgentString = request.header("User-Agent") | ||||
|  | ||||
| @@ -135,10 +133,28 @@ class CloudflareInterceptor(private val context: Context) : Interceptor { | ||||
|         latch.await(12, TimeUnit.SECONDS) | ||||
|  | ||||
|         handler.post { | ||||
|             if (!cloudflareBypassed) { | ||||
|                 isWebviewOutdated = webView?.isOutdated() == true | ||||
|             } | ||||
|  | ||||
|             webView?.stopLoading() | ||||
|             webView?.destroy() | ||||
|         } | ||||
|         return cloudflareBypassed | ||||
|  | ||||
|         // Throw exception if we failed to bypass Cloudflare | ||||
|         if (!cloudflareBypassed) { | ||||
|             // Prompt user to update WebView if it seems too outdated | ||||
|             if (isWebviewOutdated) { | ||||
|                 context.toast(R.string.information_webview_outdated, Toast.LENGTH_LONG) | ||||
|             } | ||||
|  | ||||
|             throw Exception(context.getString(R.string.information_cloudflare_bypass_failure)) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|         private val SERVER_CHECK = arrayOf("cloudflare-nginx", "cloudflare") | ||||
|         private val COOKIE_NAMES = listOf("__cfduid", "cf_clearance") | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -15,7 +15,10 @@ import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.source.SourceManager | ||||
| import eu.kanade.tachiyomi.source.online.HttpSource | ||||
| import eu.kanade.tachiyomi.ui.base.activity.BaseActivity | ||||
| import eu.kanade.tachiyomi.util.system.* | ||||
| import eu.kanade.tachiyomi.util.system.WebViewClientCompat | ||||
| import eu.kanade.tachiyomi.util.system.getResourceColor | ||||
| import eu.kanade.tachiyomi.util.system.openInBrowser | ||||
| import eu.kanade.tachiyomi.util.system.toast | ||||
| import eu.kanade.tachiyomi.util.view.invisible | ||||
| import eu.kanade.tachiyomi.util.view.visible | ||||
| import kotlinx.android.synthetic.main.webview_activity.* | ||||
| @@ -53,8 +56,6 @@ class WebViewActivity : BaseActivity() { | ||||
|             val url = intent.extras!!.getString(URL_KEY) ?: return | ||||
|             val headers = source.headers.toMultimap().mapValues { it.value.getOrNull(0) ?: "" } | ||||
|  | ||||
|             webview.checkVersion() | ||||
|  | ||||
|             webview.settings.javaScriptEnabled = true | ||||
|             webview.settings.userAgentString = source.headers["User-Agent"] | ||||
|  | ||||
|   | ||||
| @@ -1,19 +1,15 @@ | ||||
| package eu.kanade.tachiyomi.util.system | ||||
|  | ||||
| import android.webkit.WebView | ||||
| import android.widget.Toast | ||||
| import eu.kanade.tachiyomi.R | ||||
|  | ||||
| private val WEBVIEW_UA_VERSION_REGEX by lazy { | ||||
|     Regex(""".*Chrome/(\d+)\..*""") | ||||
| } | ||||
|  | ||||
| private const val MINIMUM_WEBVIEW_VERSION = 72 | ||||
| private const val MINIMUM_WEBVIEW_VERSION = 70 | ||||
|  | ||||
| fun WebView.checkVersion() { | ||||
|     if (getWebviewMajorVersion(this) < MINIMUM_WEBVIEW_VERSION) { | ||||
|         this.context.toast(R.string.information_webview_outdated, Toast.LENGTH_LONG) | ||||
|     } | ||||
| fun WebView.isOutdated(): Boolean { | ||||
|     return getWebviewMajorVersion(this) < MINIMUM_WEBVIEW_VERSION | ||||
| } | ||||
|  | ||||
| // Based on https://stackoverflow.com/a/29218966 | ||||
|   | ||||
| @@ -521,6 +521,7 @@ | ||||
|     <string name="information_no_recent_manga">No recently read manga</string> | ||||
|     <string name="information_empty_library">Your library is empty, add series to your library from the catalogues.</string> | ||||
|     <string name="information_empty_category">You have no categories. Hit the plus button to create one for organizing your library.</string> | ||||
|     <string name="information_cloudflare_bypass_failure">Failed to bypass Cloudflare</string> | ||||
|     <string name="information_webview_outdated">Please update the WebView app for better compatibility</string> | ||||
|  | ||||
|     <!-- Download Notification --> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user