浏览代码

Allow glide to use source's network client. Catalogue fixes

len 8 年之前
父节点
当前提交
ad6cdc9017

+ 9 - 4
app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaModelLoader.kt

@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.glide
 import android.content.Context
 import android.util.LruCache
 import com.bumptech.glide.Glide
+import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher
 import com.bumptech.glide.load.data.DataFetcher
 import com.bumptech.glide.load.model.*
 import com.bumptech.glide.load.model.stream.StreamModelLoader
@@ -89,15 +90,18 @@ class MangaModelLoader(context: Context) : StreamModelLoader<Manga> {
         }
 
         if (url.startsWith("http")) {
+            val source = sourceManager.get(manga.source) as? HttpSource
+
             // Obtain the request url and the file for this url from the LRU cache, or calculate it
             // and add them to the cache.
             val (glideUrl, file) = lruCache.get(url) ?:
-                    Pair(GlideUrl(url, getHeaders(manga)), coverCache.getCoverFile(url)).apply {
+                    Pair(GlideUrl(url, getHeaders(manga, source)), coverCache.getCoverFile(url)).apply {
                         lruCache.put(url, this)
                     }
 
             // Get the resource fetcher for this request url.
-            val networkFetcher = baseUrlLoader.getResourceFetcher(glideUrl, width, height)
+            val networkFetcher = source?.let { OkHttpStreamFetcher(it.client, glideUrl) }
+                ?: baseUrlLoader.getResourceFetcher(glideUrl, width, height)
 
             // Return an instance of the fetcher providing the needed elements.
             return MangaUrlFetcher(networkFetcher, file, manga)
@@ -118,8 +122,9 @@ class MangaModelLoader(context: Context) : StreamModelLoader<Manga> {
      *
      * @param manga the model.
      */
-    fun getHeaders(manga: Manga): Headers {
-        val source = sourceManager.get(manga.source) as? HttpSource ?: return LazyHeaders.DEFAULT
+    fun getHeaders(manga: Manga, source: HttpSource?): Headers {
+        if (source == null) return LazyHeaders.DEFAULT
+
         return cachedHeaders.getOrPut(manga.source) {
             LazyHeaders.Builder().apply {
                 val nullStr: String? = null

+ 14 - 17
app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt

@@ -6,7 +6,7 @@ import okhttp3.Interceptor
 import okhttp3.Request
 import okhttp3.Response
 
-class CloudflareInterceptor(private val cookies: PersistentCookieStore) : Interceptor {
+class CloudflareInterceptor : Interceptor {
 
     //language=RegExp
     private val operationPattern = Regex("""setTimeout\(function\(\)\{\s+(var (?:\w,)+f.+?\r?\n[\s\S]+?a\.value =.+?)\r?\n""")
@@ -17,18 +17,12 @@ class CloudflareInterceptor(private val cookies: PersistentCookieStore) : Interc
     //language=RegExp
     private val challengePattern = Regex("""name="jschl_vc" value="(\w+)"""")
 
+    @Synchronized
     override fun intercept(chain: Interceptor.Chain): Response {
         val response = chain.proceed(chain.request())
 
-        // Check if we already solved a challenge
-        if (response.code() != 503 &&
-                cookies.get(response.request().url()).any { it.name() == "cf_clearance" }) {
-            return response
-        }
-
         // Check if Cloudflare anti-bot is on
-        if ("URL=/cdn-cgi/" in response.header("Refresh", "")
-                && response.header("Server", "") == "cloudflare-nginx") {
+        if (response.code() == 503 && "cloudflare-nginx" == response.header("Server")) {
             return chain.proceed(resolveChallenge(response))
         }
 
@@ -36,10 +30,10 @@ class CloudflareInterceptor(private val cookies: PersistentCookieStore) : Interc
     }
 
     private fun resolveChallenge(response: Response): Request {
-        val duktape = Duktape.create()
-        try {
+        Duktape.create().use { duktape ->
             val originalRequest = response.request()
-            val domain = originalRequest.url().host()
+            val url = originalRequest.url()
+            val domain = url.host()
             val content = response.body().string()
 
             // CloudFlare requires waiting 4 seconds before resolving the challenge
@@ -64,16 +58,19 @@ class CloudflareInterceptor(private val cookies: PersistentCookieStore) : Interc
 
             val answer = "${result + domain.length}"
 
-            val url = HttpUrl.parse("http://$domain/cdn-cgi/l/chk_jschl").newBuilder()
+            val cloudflareUrl = HttpUrl.parse("${url.scheme()}://$domain/cdn-cgi/l/chk_jschl")
+                    .newBuilder()
                     .addQueryParameter("jschl_vc", challenge)
                     .addQueryParameter("pass", pass)
                     .addQueryParameter("jschl_answer", answer)
                     .toString()
 
-            val referer = originalRequest.url().toString()
-            return GET(url, originalRequest.headers().newBuilder().add("Referer", referer).build())
-        } finally {
-            duktape.close()
+            val cloudflareHeaders = originalRequest.headers()
+                    .newBuilder()
+                    .add("Referer", url.toString())
+                    .build()
+
+            return GET(cloudflareUrl, cloudflareHeaders)
         }
     }
 

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt

@@ -29,7 +29,7 @@ class NetworkHelper(context: Context) {
             .build()
 
     val cloudflareClient = client.newBuilder()
-            .addInterceptor(CloudflareInterceptor(cookies))
+            .addInterceptor(CloudflareInterceptor())
             .build()
 
     val cookies: PersistentCookieStore

+ 22 - 24
app/src/main/java/eu/kanade/tachiyomi/network/PersistentCookieStore.kt

@@ -28,38 +28,36 @@ class PersistentCookieStore(context: Context) {
         }
     }
 
+    @Synchronized
     fun addAll(url: HttpUrl, cookies: List<Cookie>) {
-        synchronized(this) {
-            val key = url.uri().host
+        val key = url.uri().host
 
-            // Append or replace the cookies for this domain.
-            val cookiesForDomain = cookieMap[key].orEmpty().toMutableList()
-            for (cookie in cookies) {
-                // Find a cookie with the same name. Replace it if found, otherwise add a new one.
-                val pos = cookiesForDomain.indexOfFirst { it.name() == cookie.name() }
-                if (pos == -1) {
-                    cookiesForDomain.add(cookie)
-                } else {
-                    cookiesForDomain[pos] = cookie
-                }
+        // Append or replace the cookies for this domain.
+        val cookiesForDomain = cookieMap[key].orEmpty().toMutableList()
+        for (cookie in cookies) {
+            // Find a cookie with the same name. Replace it if found, otherwise add a new one.
+            val pos = cookiesForDomain.indexOfFirst { it.name() == cookie.name() }
+            if (pos == -1) {
+                cookiesForDomain.add(cookie)
+            } else {
+                cookiesForDomain[pos] = cookie
             }
-            cookieMap.put(key, cookiesForDomain)
+        }
+        cookieMap.put(key, cookiesForDomain)
 
-            // Get cookies to be stored in disk
-            val newValues = cookiesForDomain.asSequence()
-                    .filter { it.persistent() && !it.hasExpired() }
-                    .map { it.toString() }
-                    .toSet()
+        // Get cookies to be stored in disk
+        val newValues = cookiesForDomain.asSequence()
+                .filter { it.persistent() && !it.hasExpired() }
+                .map(Cookie::toString)
+                .toSet()
 
-            prefs.edit().putStringSet(key, newValues).apply()
-        }
+        prefs.edit().putStringSet(key, newValues).apply()
     }
 
+    @Synchronized
     fun removeAll() {
-        synchronized(this) {
-            prefs.edit().clear().apply()
-            cookieMap.clear()
-        }
+        prefs.edit().clear().apply()
+        cookieMap.clear()
     }
 
     fun get(url: HttpUrl) = get(url.uri().host)

+ 0 - 9
app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt

@@ -16,7 +16,6 @@ import eu.davidea.flexibleadapter.items.IFlexible
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.source.model.FilterList
-import eu.kanade.tachiyomi.source.online.LoginSource
 import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
 import eu.kanade.tachiyomi.ui.main.MainActivity
 import eu.kanade.tachiyomi.ui.manga.MangaActivity
@@ -151,14 +150,6 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(),
     }
 
     override fun onViewCreated(view: View, savedState: Bundle?) {
-        // If the source list is empty or it only has unlogged sources, return to main screen.
-        val sources = presenter.sources
-        if (sources.isEmpty() || sources.all { it is LoginSource && !it.isLogged() }) {
-            context.toast(R.string.no_valid_sources)
-            activity.onBackPressed()
-            return
-        }
-
         // Initialize adapter, scroll listener and recycler views
         adapter = FlexibleAdapter(null, this)
         setupRecycler()

+ 4 - 18
app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt

@@ -24,7 +24,6 @@ import rx.schedulers.Schedulers
 import rx.subjects.PublishSubject
 import timber.log.Timber
 import uy.kohesive.injekt.injectLazy
-import java.util.*
 
 /**
  * Presenter of [CatalogueFragment].
@@ -118,12 +117,8 @@ open class CataloguePresenter : BasePresenter<CatalogueFragment>() {
     override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
 
-        try {
-            source = getLastUsedSource()
-            sourceFilters = source.getFilterList()
-        } catch (error: NoSuchElementException) {
-            return
-        }
+        source = getLastUsedSource()
+        sourceFilters = source.getFilterList()
 
         if (savedState != null) {
             query = savedState.getString(CataloguePresenter::query.name, "")
@@ -291,8 +286,8 @@ open class CataloguePresenter : BasePresenter<CatalogueFragment>() {
     fun getLastUsedSource(): CatalogueSource {
         val id = prefs.lastUsedCatalogueSource().get() ?: -1
         val source = sourceManager.get(id)
-        if (!isValidSource(source)) {
-            return findFirstValidSource()
+        if (!isValidSource(source) || source !in sources) {
+            return sources.first { isValidSource(it) }
         }
         return source as CatalogueSource
     }
@@ -313,15 +308,6 @@ open class CataloguePresenter : BasePresenter<CatalogueFragment>() {
         return true
     }
 
-    /**
-     * Finds the first valid source.
-     *
-     * @return the index of the first valid source.
-     */
-    fun findFirstValidSource(): CatalogueSource {
-        return sources.first { isValidSource(it) }
-    }
-
     /**
      * Returns a list of enabled sources ordered by language and name.
      */