Add universal captcha detection
This commit is contained in:
parent
f0109aa796
commit
5c2fbec80a
@ -15,8 +15,8 @@ import java.nio.charset.Charset
|
|||||||
class AutoSolvingWebViewClient(activity: SolveCaptchaActivity,
|
class AutoSolvingWebViewClient(activity: SolveCaptchaActivity,
|
||||||
source: CaptchaCompletionVerifier,
|
source: CaptchaCompletionVerifier,
|
||||||
injectScript: String?,
|
injectScript: String?,
|
||||||
private val headers: Map<String, String>)
|
headers: Map<String, String>)
|
||||||
: BasicWebViewClient(activity, source, injectScript) {
|
: HeadersInjectingWebViewClient(activity, source, injectScript, headers) {
|
||||||
|
|
||||||
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
||||||
// Inject our custom script into the recaptcha iframes
|
// Inject our custom script into the recaptcha iframes
|
||||||
@ -32,24 +32,6 @@ class AutoSolvingWebViewClient(activity: SolveCaptchaActivity,
|
|||||||
doc.toString().byteInputStream(Charset.forName("UTF-8")).buffered()
|
doc.toString().byteInputStream(Charset.forName("UTF-8")).buffered()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if(headers.isNotEmpty()) {
|
|
||||||
val response = activity.httpClient.newCall(request.toOkHttpRequest()
|
|
||||||
.newBuilder()
|
|
||||||
.apply {
|
|
||||||
headers.forEach { (n, v) -> addHeader(n, v) }
|
|
||||||
}
|
|
||||||
.build())
|
|
||||||
.execute()
|
|
||||||
|
|
||||||
return WebResourceResponse(
|
|
||||||
response.body()?.contentType()?.let { "${it.type()}/${it.subtype()}" },
|
|
||||||
response.body()?.contentType()?.charset()?.toString(),
|
|
||||||
response.code(),
|
|
||||||
response.message(),
|
|
||||||
response.headers().toMultimap().mapValues { it.value.joinToString(",") },
|
|
||||||
response.body()?.byteStream()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return super.shouldInterceptRequest(view, request)
|
return super.shouldInterceptRequest(view, request)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package exh.ui.captcha
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.support.annotation.RequiresApi
|
||||||
|
import android.webkit.WebResourceRequest
|
||||||
|
import android.webkit.WebResourceResponse
|
||||||
|
import android.webkit.WebView
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
open class HeadersInjectingWebViewClient(activity: SolveCaptchaActivity,
|
||||||
|
source: CaptchaCompletionVerifier,
|
||||||
|
injectScript: String?,
|
||||||
|
private val headers: Map<String, String>)
|
||||||
|
: BasicWebViewClient(activity, source, injectScript) {
|
||||||
|
|
||||||
|
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
|
||||||
|
// Temp disabled as it's unreliable
|
||||||
|
/*if(headers.isNotEmpty()) {
|
||||||
|
val response = activity.httpClient.newCall(request.toOkHttpRequest()
|
||||||
|
.newBuilder()
|
||||||
|
.apply {
|
||||||
|
headers.forEach { (n, v) -> header(n, v) }
|
||||||
|
}
|
||||||
|
.build())
|
||||||
|
.execute()
|
||||||
|
|
||||||
|
return WebResourceResponse(
|
||||||
|
response.body()?.contentType()?.let { "${it.type()}/${it.subtype()}" },
|
||||||
|
response.body()?.contentType()?.charset()?.toString(),
|
||||||
|
response.code(),
|
||||||
|
response.message().nullIfBlank() ?: FALLBACK_REASON_PHRASES[response.code()] ?: "Unknown status",
|
||||||
|
response.headers().toMultimap().mapValues { it.value.joinToString(",") },
|
||||||
|
response.body()?.byteStream()
|
||||||
|
)
|
||||||
|
}*/
|
||||||
|
return super.shouldInterceptRequest(view, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val FALLBACK_REASON_PHRASES = mapOf(
|
||||||
|
100 to "Continue",
|
||||||
|
101 to "Switching Protocols",
|
||||||
|
200 to "OK",
|
||||||
|
201 to "Created",
|
||||||
|
202 to "Accepted",
|
||||||
|
203 to "Non-Authoritative Information",
|
||||||
|
204 to "No Content",
|
||||||
|
205 to "Reset Content",
|
||||||
|
206 to "Partial Content",
|
||||||
|
300 to "Multiple Choices",
|
||||||
|
301 to "Moved Permanently",
|
||||||
|
302 to "Moved Temporarily",
|
||||||
|
303 to "See Other",
|
||||||
|
304 to "Not Modified",
|
||||||
|
305 to "Use Proxy",
|
||||||
|
400 to "Bad Request",
|
||||||
|
401 to "Unauthorized",
|
||||||
|
402 to "Payment Required",
|
||||||
|
403 to "Forbidden",
|
||||||
|
404 to "Not Found",
|
||||||
|
405 to "Method Not Allowed",
|
||||||
|
406 to "Not Acceptable",
|
||||||
|
407 to "Proxy Authentication Required",
|
||||||
|
408 to "Request Time-out",
|
||||||
|
409 to "Conflict",
|
||||||
|
410 to "Gone",
|
||||||
|
411 to "Length Required",
|
||||||
|
412 to "Precondition Failed",
|
||||||
|
413 to "Request Entity Too Large",
|
||||||
|
414 to "Request-URI Too Large",
|
||||||
|
415 to "Unsupported Media Type",
|
||||||
|
500 to "Internal Server Error",
|
||||||
|
501 to "Not Implemented",
|
||||||
|
502 to "Bad Gateway",
|
||||||
|
503 to "Service Unavailable",
|
||||||
|
504 to "Gateway Time-out",
|
||||||
|
505 to "HTTP Version not supported"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -124,23 +124,26 @@ class SolveCaptchaActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
webview.webViewClient = if (preferencesHelper.eh_autoSolveCaptchas().getOrDefault()
|
webview.webViewClient = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if(preferencesHelper.eh_autoSolveCaptchas().getOrDefault()) {
|
||||||
// Fetch auto-solve credentials early for speed
|
// Fetch auto-solve credentials early for speed
|
||||||
credentialsObservable = httpClient.newCall(Request.Builder()
|
credentialsObservable = httpClient.newCall(Request.Builder()
|
||||||
// Rob demo credentials
|
// Rob demo credentials
|
||||||
.url("https://speech-to-text-demo.ng.bluemix.net/api/v1/credentials")
|
.url("https://speech-to-text-demo.ng.bluemix.net/api/v1/credentials")
|
||||||
.build())
|
.build())
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.map {
|
.map {
|
||||||
val json = jsonParser.parse(it.body()!!.string())
|
val json = jsonParser.parse(it.body()!!.string())
|
||||||
it.close()
|
it.close()
|
||||||
json["token"].string
|
json["token"].string
|
||||||
}.melt()
|
}.melt()
|
||||||
|
|
||||||
webview.addJavascriptInterface(this@SolveCaptchaActivity, "exh")
|
webview.addJavascriptInterface(this@SolveCaptchaActivity, "exh")
|
||||||
AutoSolvingWebViewClient(this, source, script, headers)
|
AutoSolvingWebViewClient(this, source, script, headers)
|
||||||
|
} else {
|
||||||
|
HeadersInjectingWebViewClient(this, source, script, headers)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
BasicWebViewClient(this, source, script)
|
BasicWebViewClient(this, source, script)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user