Merge branch 'master' into Automatic_Reader_Background
This commit is contained in:
commit
c63d46a32e
6 changed files with 50 additions and 22 deletions
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
**App version:**
|
**App version:**
|
||||||
|
|
||||||
|
**Android version:**
|
||||||
|
|
||||||
**Issue/Request:**
|
**Issue/Request:**
|
||||||
|
|
||||||
**Steps to reproduce (if applicable)**
|
**Steps to reproduce (if applicable)**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
| Build | Stable | Dev | Contribute | Contact |
|
| Build | Stable | Dev | Contribute | Contact |
|
||||||
|-------|----------|---------|------------|---------|
|
|-------|----------|---------|------------|---------|
|
||||||
| [![Travis](https://img.shields.io/travis/inorichi/tachiyomi.svg)](https://travis-ci.org/inorichi/tachiyomi) | [![stable release](https://img.shields.io/github/release/inorichi/tachiyomi.svg?maxAge=3600&label=download%20(autoupdate%20included))](https://github.com/inorichi/tachiyomi/releases) | [![latest dev build](https://img.shields.io/badge/download-latest%20build-blue.svg)](http://tachiyomi.kanade.eu/latest) [![fdroid dev](https://img.shields.io/badge/autoupdate-wiki-blue.svg)](//github.com/inorichi/tachiyomi/wiki/F-Droid-for-dev-versions) | [![Translation status](https://hosted.weblate.org/widgets/tachiyomi/-/svg-badge.svg)](https://hosted.weblate.org/engage/tachiyomi/?utm_source=widget) | [![Discord](https://img.shields.io/discord/349436576037732353.svg)](https://discord.gg/tachiyomi) |
|
| [![Travis](https://img.shields.io/travis/inorichi/tachiyomi.svg)](https://travis-ci.org/inorichi/tachiyomi) | [![stable release](https://img.shields.io/github/release/inorichi/tachiyomi.svg?maxAge=3600&label=download%20(autoupdate%20included))](https://github.com/inorichi/tachiyomi/releases) | [![latest dev build](https://img.shields.io/badge/download-latest%20build-blue.svg)](http://tachiyomi.kanade.eu/latest) | [![Translation status](https://hosted.weblate.org/widgets/tachiyomi/-/svg-badge.svg)](https://hosted.weblate.org/engage/tachiyomi/?utm_source=widget) | [![Discord](https://img.shields.io/discord/349436576037732353.svg)](https://discord.gg/tachiyomi) |
|
||||||
|
|
||||||
|
|
||||||
# ![app icon](./.github/readme-images/app-icon.png)Tachiyomi
|
# ![app icon](./.github/readme-images/app-icon.png)Tachiyomi
|
||||||
|
@ -23,7 +23,7 @@ Features include:
|
||||||
## Download
|
## Download
|
||||||
Get the app from our [releases page](https://github.com/inorichi/tachiyomi/releases).
|
Get the app from our [releases page](https://github.com/inorichi/tachiyomi/releases).
|
||||||
|
|
||||||
If you want to try new features before they get to the stable release, you can download the dev version [here](http://tachiyomi.kanade.eu/latest) (auto-updates not included), or add our [F-Droid repo](https://github.com/inorichi/tachiyomi/wiki/F-Droid-for-dev-versions).
|
If you want to try new features before they get to the stable release, you can download the dev version [here](http://tachiyomi.kanade.eu/latest). (auto-updates not included)
|
||||||
|
|
||||||
## Issues, Feature Requests and Contributing
|
## Issues, Feature Requests and Contributing
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,9 @@ dependencies {
|
||||||
implementation 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0'
|
implementation 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0'
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
implementation 'eu.kanade.storio:storio:1.13.0'
|
implementation 'android.arch.persistence:db:1.0.0'
|
||||||
|
implementation 'com.github.inorichi.storio:storio-common:8be19de@aar'
|
||||||
|
implementation 'com.github.inorichi.storio:storio-sqlite:8be19de@aar'
|
||||||
implementation 'io.requery:sqlite-android:3.25.2'
|
implementation 'io.requery:sqlite-android:3.25.2'
|
||||||
|
|
||||||
// Model View Presenter
|
// Model View Presenter
|
||||||
|
|
|
@ -12,8 +12,22 @@ class CloudflareInterceptor : Interceptor {
|
||||||
|
|
||||||
private val challengePattern = Regex("""name="jschl_vc" value="(\w+)"""")
|
private val challengePattern = Regex("""name="jschl_vc" value="(\w+)"""")
|
||||||
|
|
||||||
|
private val sPattern = Regex("""name="s" value="([^"]+)""")
|
||||||
|
|
||||||
|
private val kPattern = Regex("""k\s+=\s+'([^']+)';""")
|
||||||
|
|
||||||
private val serverCheck = arrayOf("cloudflare-nginx", "cloudflare")
|
private val serverCheck = arrayOf("cloudflare-nginx", "cloudflare")
|
||||||
|
|
||||||
|
private interface IBase64 {
|
||||||
|
fun decode(input: String): String
|
||||||
|
}
|
||||||
|
|
||||||
|
private val b64: IBase64 = object : IBase64 {
|
||||||
|
override fun decode(input: String): String {
|
||||||
|
return okio.ByteString.decodeBase64(input)!!.utf8()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
val response = chain.proceed(chain.request())
|
val response = chain.proceed(chain.request())
|
||||||
|
@ -45,23 +59,36 @@ class CloudflareInterceptor : Interceptor {
|
||||||
val operation = operationPattern.find(content)?.groups?.get(1)?.value
|
val operation = operationPattern.find(content)?.groups?.get(1)?.value
|
||||||
val challenge = challengePattern.find(content)?.groups?.get(1)?.value
|
val challenge = challengePattern.find(content)?.groups?.get(1)?.value
|
||||||
val pass = passPattern.find(content)?.groups?.get(1)?.value
|
val pass = passPattern.find(content)?.groups?.get(1)?.value
|
||||||
|
val s = sPattern.find(content)?.groups?.get(1)?.value
|
||||||
|
|
||||||
if (operation == null || challenge == null || pass == null) {
|
// If `k` is null, it uses old methods.
|
||||||
|
val k = kPattern.find(content)?.groups?.get(1)?.value ?: ""
|
||||||
|
val innerHTMLValue = Regex("""<div(.*)id="$k"(.*)>(.*)</div>""")
|
||||||
|
.find(content)?.groups?.get(3)?.value ?: ""
|
||||||
|
|
||||||
|
if (operation == null || challenge == null || pass == null || s == null) {
|
||||||
throw Exception("Failed resolving Cloudflare challenge")
|
throw Exception("Failed resolving Cloudflare challenge")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Export native Base64 decode function to js object.
|
||||||
|
duktape.set("b64", IBase64::class.java, b64)
|
||||||
|
|
||||||
|
// Return simulated innerHTML when call DOM.
|
||||||
|
val simulatedDocumentJS = """var document = { getElementById: function (x) { return { innerHTML: "$innerHTMLValue" }; } }"""
|
||||||
|
|
||||||
val js = operation
|
val js = operation
|
||||||
.replace(Regex("""a\.value = (.+ \+ t\.length(\).toFixed\(10\))?).+"""), "$1")
|
.replace(Regex("""a\.value = (.+\.toFixed\(10\);).+"""), "$1")
|
||||||
.replace(Regex("""\s{3,}[a-z](?: = |\.).+"""), "")
|
.replace(Regex("""\s{3,}[a-z](?: = |\.).+"""), "")
|
||||||
.replace("t.length", "${domain.length}")
|
.replace("t.length", "${domain.length}")
|
||||||
.replace("\n", "")
|
.replace("\n", "")
|
||||||
|
|
||||||
val result = duktape.evaluate(js) as String
|
val result = duktape.evaluate("""$simulatedDocumentJS;$ATOB_JS;var t="$domain";$js""") as String
|
||||||
|
|
||||||
val cloudflareUrl = HttpUrl.parse("${url.scheme()}://$domain/cdn-cgi/l/chk_jschl")!!
|
val cloudflareUrl = HttpUrl.parse("${url.scheme()}://$domain/cdn-cgi/l/chk_jschl")!!
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.addQueryParameter("jschl_vc", challenge)
|
.addQueryParameter("jschl_vc", challenge)
|
||||||
.addQueryParameter("pass", pass)
|
.addQueryParameter("pass", pass)
|
||||||
|
.addQueryParameter("s", s)
|
||||||
.addQueryParameter("jschl_answer", result)
|
.addQueryParameter("jschl_answer", result)
|
||||||
.toString()
|
.toString()
|
||||||
|
|
||||||
|
@ -76,4 +103,8 @@ class CloudflareInterceptor : Interceptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// atob() is browser API, Using Android's own function. (java.util.Base64 can't be used because of min API level)
|
||||||
|
private const val ATOB_JS = """var atob = function (input) { return b64.decode(input) }"""
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -116,23 +116,17 @@ class ReaderProgressBar @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the aggregated visibility of this view changes. It also starts of stops the
|
* Called when the visibility of this view changes.
|
||||||
* rotation animation according to [isVisible].
|
|
||||||
*/
|
*/
|
||||||
override fun onVisibilityAggregated(isVisible: Boolean) {
|
override fun setVisibility(visibility: Int) {
|
||||||
super.onVisibilityAggregated(isVisible)
|
super.setVisibility(visibility)
|
||||||
|
val isVisible = visibility == View.VISIBLE
|
||||||
if (isVisible != aggregatedIsVisible) {
|
|
||||||
aggregatedIsVisible = isVisible
|
|
||||||
|
|
||||||
// let's be nice with the UI thread
|
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
startAnimation()
|
startAnimation()
|
||||||
} else {
|
} else {
|
||||||
stopAnimation()
|
stopAnimation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the rotation animation if needed.
|
* Starts the rotation animation if needed.
|
||||||
|
|
|
@ -22,6 +22,5 @@ allprojects {
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
jcenter()
|
jcenter()
|
||||||
maven { url "https://dl.bintray.com/inorichi/maven" }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue