mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	Merge branch 'master' of https://github.com/inorichi/tachiyomi
# Conflicts: # .travis.yml # README.md # app/build.gradle # app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoController.kt # app/src/main/res/layout/manga_info_controller.xml # app/src/main/res/raw/changelog_release.xml
This commit is contained in:
		| @@ -1,10 +1,13 @@ | ||||
| package eu.kanade.tachiyomi.data.updater | ||||
|  | ||||
| import eu.kanade.tachiyomi.network.NetworkHelper | ||||
| import retrofit2.Retrofit | ||||
| import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory | ||||
| import retrofit2.converter.gson.GsonConverterFactory | ||||
| import retrofit2.http.GET | ||||
| import rx.Observable | ||||
| import uy.kohesive.injekt.Injekt | ||||
| import uy.kohesive.injekt.api.get | ||||
|  | ||||
| /** | ||||
|  * Used to connect with the Github API. | ||||
| @@ -17,6 +20,7 @@ interface GithubService { | ||||
|                     .baseUrl("https://api.github.com") | ||||
|                     .addConverterFactory(GsonConverterFactory.create()) | ||||
|                     .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) | ||||
|                     .client(Injekt.get<NetworkHelper>().client) | ||||
|                     .build() | ||||
|  | ||||
|             return restAdapter.create(GithubService::class.java) | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package eu.kanade.tachiyomi.network | ||||
|  | ||||
| import com.squareup.duktape.Duktape | ||||
| import okhttp3.CacheControl | ||||
| import okhttp3.HttpUrl | ||||
| import okhttp3.Interceptor | ||||
| import okhttp3.Request | ||||
| @@ -21,7 +22,7 @@ class CloudflareInterceptor : Interceptor { | ||||
|         val response = chain.proceed(chain.request()) | ||||
|  | ||||
|         // Check if Cloudflare anti-bot is on | ||||
|         if (response.code() == 503 && serverCheck.contains(response.header("Server"))) { | ||||
|         if (response.code() == 503 && response.header("Server") in serverCheck) { | ||||
|             return chain.proceed(resolveChallenge(response)) | ||||
|         } | ||||
|  | ||||
| @@ -43,32 +44,33 @@ class CloudflareInterceptor : Interceptor { | ||||
|             val pass = passPattern.find(content)?.groups?.get(1)?.value | ||||
|  | ||||
|             if (operation == null || challenge == null || pass == null) { | ||||
|                 throw RuntimeException("Failed resolving Cloudflare challenge") | ||||
|                 throw Exception("Failed resolving Cloudflare challenge") | ||||
|             } | ||||
|  | ||||
|             val js = operation | ||||
|                     .replace(Regex("""a\.value =(.+?) \+.*"""), "$1") | ||||
|                     .replace(Regex("""a\.value = (.+ \+ t\.length).+"""), "$1") | ||||
|                     .replace(Regex("""\s{3,}[a-z](?: = |\.).+"""), "") | ||||
|                     .replace("t.length", "${domain.length}") | ||||
|                     .replace("\n", "") | ||||
|  | ||||
|             val result = (duktape.evaluate(js) as Double).toInt() | ||||
|  | ||||
|             val answer = "${result + domain.length}" | ||||
|             val result = duktape.evaluate(js) as Double | ||||
|  | ||||
|             val cloudflareUrl = HttpUrl.parse("${url.scheme()}://$domain/cdn-cgi/l/chk_jschl")!! | ||||
|                     .newBuilder() | ||||
|                     .addQueryParameter("jschl_vc", challenge) | ||||
|                     .addQueryParameter("pass", pass) | ||||
|                     .addQueryParameter("jschl_answer", answer) | ||||
|                     .addQueryParameter("jschl_answer", "$result") | ||||
|                     .toString() | ||||
|  | ||||
|             val cloudflareHeaders = originalRequest.headers() | ||||
|                     .newBuilder() | ||||
|                     .add("Referer", url.toString()) | ||||
|                     .add("Accept", "text/html,application/xhtml+xml,application/xml") | ||||
|                     .add("Accept-Language", "en") | ||||
|                     .build() | ||||
|  | ||||
|             return GET(cloudflareUrl, cloudflareHeaders) | ||||
|             return GET(cloudflareUrl, cloudflareHeaders, cache = CacheControl.Builder().build()) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,22 @@ | ||||
| package eu.kanade.tachiyomi.network | ||||
|  | ||||
| import android.content.Context | ||||
| import android.os.Build | ||||
| import okhttp3.Cache | ||||
| import okhttp3.OkHttpClient | ||||
| import java.io.File | ||||
| import java.io.IOException | ||||
| import java.net.InetAddress | ||||
| import java.net.Socket | ||||
| import java.net.UnknownHostException | ||||
| import java.security.KeyManagementException | ||||
| import java.security.KeyStore | ||||
| import java.security.NoSuchAlgorithmException | ||||
| import javax.net.ssl.SSLContext | ||||
| import javax.net.ssl.SSLSocket | ||||
| import javax.net.ssl.SSLSocketFactory | ||||
| import javax.net.ssl.TrustManagerFactory | ||||
| import javax.net.ssl.X509TrustManager | ||||
|  | ||||
| class NetworkHelper(context: Context) { | ||||
|  | ||||
| @@ -16,6 +29,7 @@ class NetworkHelper(context: Context) { | ||||
|     val client = OkHttpClient.Builder() | ||||
|             .cookieJar(cookieManager) | ||||
|             .cache(Cache(cacheDir, cacheSize)) | ||||
|             .enableTLS12() | ||||
|             .build() | ||||
|  | ||||
|     val cloudflareClient = client.newBuilder() | ||||
| @@ -25,4 +39,75 @@ class NetworkHelper(context: Context) { | ||||
|     val cookies: PersistentCookieStore | ||||
|         get() = cookieManager.store | ||||
|  | ||||
|     private fun OkHttpClient.Builder.enableTLS12(): OkHttpClient.Builder { | ||||
|         if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { | ||||
|             return this | ||||
|         } | ||||
|  | ||||
|         val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) | ||||
|         trustManagerFactory.init(null as KeyStore?) | ||||
|         val trustManagers = trustManagerFactory.trustManagers | ||||
|         if (trustManagers.size == 1 && trustManagers[0] is X509TrustManager) { | ||||
|             class TLSSocketFactory @Throws(KeyManagementException::class, NoSuchAlgorithmException::class) | ||||
|             constructor() : SSLSocketFactory() { | ||||
|  | ||||
|                 private val internalSSLSocketFactory: SSLSocketFactory | ||||
|  | ||||
|                 init { | ||||
|                     val context = SSLContext.getInstance("TLS") | ||||
|                     context.init(null, null, null) | ||||
|                     internalSSLSocketFactory = context.socketFactory | ||||
|                 } | ||||
|  | ||||
|                 override fun getDefaultCipherSuites(): Array<String> { | ||||
|                     return internalSSLSocketFactory.defaultCipherSuites | ||||
|                 } | ||||
|  | ||||
|                 override fun getSupportedCipherSuites(): Array<String> { | ||||
|                     return internalSSLSocketFactory.supportedCipherSuites | ||||
|                 } | ||||
|  | ||||
|                 @Throws(IOException::class) | ||||
|                 override fun createSocket(): Socket? { | ||||
|                     return enableTLSOnSocket(internalSSLSocketFactory.createSocket()) | ||||
|                 } | ||||
|  | ||||
|                 @Throws(IOException::class) | ||||
|                 override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket? { | ||||
|                     return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)) | ||||
|                 } | ||||
|  | ||||
|                 @Throws(IOException::class, UnknownHostException::class) | ||||
|                 override fun createSocket(host: String, port: Int): Socket? { | ||||
|                     return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)) | ||||
|                 } | ||||
|  | ||||
|                 @Throws(IOException::class, UnknownHostException::class) | ||||
|                 override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket? { | ||||
|                     return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)) | ||||
|                 } | ||||
|  | ||||
|                 @Throws(IOException::class) | ||||
|                 override fun createSocket(host: InetAddress, port: Int): Socket? { | ||||
|                     return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)) | ||||
|                 } | ||||
|  | ||||
|                 @Throws(IOException::class) | ||||
|                 override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket? { | ||||
|                     return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)) | ||||
|                 } | ||||
|  | ||||
|                 private fun enableTLSOnSocket(socket: Socket?): Socket? { | ||||
|                     if (socket != null && socket is SSLSocket) { | ||||
|                         socket.enabledProtocols = socket.supportedProtocols | ||||
|                     } | ||||
|                     return socket | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             sslSocketFactory(TLSSocketFactory(), trustManagers[0] as X509TrustManager) | ||||
|         } | ||||
|  | ||||
|         return this | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -277,7 +277,11 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(), | ||||
|     } | ||||
|  | ||||
|     fun setLastUpdateDate(date: Date) { | ||||
|         manga_last_update?.text = DateFormat.getDateInstance(DateFormat.SHORT).format(date) | ||||
|         if (date.time != 0L) { | ||||
|             manga_last_update?.text = DateFormat.getDateInstance(DateFormat.SHORT).format(date) | ||||
|         } else { | ||||
|             manga_last_update?.text = resources?.getString(R.string.unknown) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -8,9 +8,9 @@ import com.jakewharton.rxbinding.widget.itemClicks | ||||
| import com.jakewharton.rxbinding.widget.textChanges | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.database.models.Track | ||||
| import eu.kanade.tachiyomi.data.track.model.TrackSearch | ||||
| import eu.kanade.tachiyomi.data.track.TrackManager | ||||
| import eu.kanade.tachiyomi.data.track.TrackService | ||||
| import eu.kanade.tachiyomi.data.track.model.TrackSearch | ||||
| import eu.kanade.tachiyomi.ui.base.controller.DialogController | ||||
| import eu.kanade.tachiyomi.util.plusAssign | ||||
| import kotlinx.android.synthetic.main.track_search_dialog.view.* | ||||
| @@ -114,14 +114,14 @@ class TrackSearchDialog : DialogController { | ||||
|     private fun search(query: String) { | ||||
|         val view = dialogView ?: return | ||||
|         view.progress.visibility = View.VISIBLE | ||||
|         view.track_search_list.visibility = View.GONE | ||||
|         view.track_search_list.visibility = View.INVISIBLE | ||||
|         trackController.presenter.search(query, service) | ||||
|     } | ||||
|  | ||||
|     fun onSearchResults(results: List<TrackSearch>) { | ||||
|         selectedItem = null | ||||
|         val view = dialogView ?: return | ||||
|         view.progress.visibility = View.GONE | ||||
|         view.progress.visibility = View.INVISIBLE | ||||
|         view.track_search_list.visibility = View.VISIBLE | ||||
|         adapter?.setItems(results) | ||||
|     } | ||||
| @@ -129,7 +129,7 @@ class TrackSearchDialog : DialogController { | ||||
|     fun onSearchResultsError() { | ||||
|         val view = dialogView ?: return | ||||
|         view.progress.visibility = View.VISIBLE | ||||
|         view.track_search_list.visibility = View.GONE | ||||
|         view.track_search_list.visibility = View.INVISIBLE | ||||
|         adapter?.setItems(emptyList()) | ||||
|     } | ||||
|  | ||||
| @@ -141,4 +141,4 @@ class TrackSearchDialog : DialogController { | ||||
|         const val KEY_SERVICE = "service_id" | ||||
|     } | ||||
|  | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -109,6 +109,7 @@ class SettingsAboutController : SettingsController() { | ||||
|                         } | ||||
|                     } | ||||
|                 }, { error -> | ||||
|                     activity?.toast(error.message) | ||||
|                     Timber.e(error) | ||||
|                 }) | ||||
|     } | ||||
|   | ||||
| @@ -43,7 +43,7 @@ fun Context.toast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SHORT) | ||||
|  * @param duration the duration of the toast. Defaults to short. | ||||
|  */ | ||||
| fun Context.toast(text: String?, duration: Int = Toast.LENGTH_SHORT) { | ||||
|     Toast.makeText(this, text, duration).show() | ||||
|     Toast.makeText(this, text.orEmpty(), duration).show() | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
		Reference in New Issue
	
	Block a user