mirror of https://github.com/kurisufriend/Clover
parent
20c9623851
commit
ee7dffae7d
@ -1,45 +0,0 @@ |
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
<style type="text/css"> |
||||
#container { |
||||
width: 440px; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
#captcha-submit { |
||||
width: 100%; |
||||
height: 30px; |
||||
margin: 10px 0 0 0; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<div id="container"> |
||||
<div id="captcha-container"></div> |
||||
<input type="button" id="captcha-submit" value="Submit"> |
||||
</div> |
||||
|
||||
<script src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script> |
||||
<script type="text/javascript"> |
||||
(function() { |
||||
|
||||
var container = document.querySelector('#captcha-container'); |
||||
var submitButton = document.querySelector('#captcha-submit') |
||||
|
||||
submitButton.addEventListener('click', function() { |
||||
var challenge = document.querySelector('#recaptcha_challenge_field').value; |
||||
var response = document.querySelector('#recaptcha_response_field').value; |
||||
|
||||
CaptchaCallback.onCaptchaEnteredv1(challenge, response); |
||||
}); |
||||
|
||||
Recaptcha.create('__site_key__', container, { |
||||
theme: 'clean' |
||||
}); |
||||
|
||||
})(); |
||||
</script> |
||||
</body> |
||||
</html> |
@ -0,0 +1,40 @@ |
||||
<div id="captcha-container"> |
||||
<div id="recaptcha_image"></div> |
||||
<input type="hidden" id="recaptcha_response_field" name="recaptcha_response_field"> |
||||
</div> |
||||
|
||||
<script type="text/javascript" |
||||
src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script> |
||||
<script type="text/javascript"> |
||||
(function() { |
||||
|
||||
Recaptcha.create('__site_key__', 'captcha-container', { |
||||
'theme': 'custom' |
||||
}); |
||||
|
||||
function checkLoaded() { |
||||
var imageSource = null; |
||||
var challengeKey = null; |
||||
|
||||
var image = document.querySelector('#recaptcha_challenge_image'); |
||||
if (image) { |
||||
imageSource = image.getAttribute('src'); |
||||
} |
||||
|
||||
var challenge = document.querySelector('#recaptcha_challenge_field'); |
||||
if (challenge) { |
||||
challengeKey = challenge.getAttribute('value'); |
||||
} |
||||
|
||||
if (imageSource != null && challengeKey != null) { |
||||
CaptchaCallback.onCaptchaLoaded(imageSource, challengeKey); |
||||
} else { |
||||
setTimeout(checkLoaded, 100); |
||||
} |
||||
} |
||||
|
||||
checkLoaded(); |
||||
|
||||
})(); |
||||
|
||||
</script> |
@ -0,0 +1,7 @@ |
||||
package org.floens.chan.ui.layout; |
||||
|
||||
public interface CaptchaCallback { |
||||
void captchaLoaded(CaptchaLayoutInterface captchaLayout); |
||||
|
||||
void captchaEntered(CaptchaLayoutInterface captchaLayout, String challenge, String response); |
||||
} |
@ -0,0 +1,7 @@ |
||||
package org.floens.chan.ui.layout; |
||||
|
||||
public interface CaptchaLayoutInterface { |
||||
void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, CaptchaCallback callback); |
||||
|
||||
void reset(); |
||||
} |
@ -0,0 +1,133 @@ |
||||
package org.floens.chan.ui.layout; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.content.Context; |
||||
import android.os.Build; |
||||
import android.util.AttributeSet; |
||||
import android.view.View; |
||||
import android.webkit.JavascriptInterface; |
||||
import android.webkit.WebChromeClient; |
||||
import android.webkit.WebSettings; |
||||
import android.webkit.WebView; |
||||
import android.webkit.WebViewClient; |
||||
import android.widget.EditText; |
||||
import android.widget.ImageView; |
||||
import android.widget.LinearLayout; |
||||
|
||||
import org.floens.chan.ChanBuild; |
||||
import org.floens.chan.R; |
||||
import org.floens.chan.ui.view.FixedRatioThumbnailView; |
||||
import org.floens.chan.utils.AndroidUtils; |
||||
import org.floens.chan.utils.IOUtils; |
||||
|
||||
import static org.floens.chan.ui.theme.ThemeHelper.theme; |
||||
import static org.floens.chan.utils.AndroidUtils.setRoundItemBackground; |
||||
|
||||
public class LegacyCaptchaLayout extends LinearLayout implements CaptchaLayoutInterface, View.OnClickListener { |
||||
private FixedRatioThumbnailView image; |
||||
private EditText input; |
||||
private ImageView submit; |
||||
|
||||
private WebView internalWebView; |
||||
|
||||
private String baseUrl; |
||||
private String siteKey; |
||||
private CaptchaCallback callback; |
||||
|
||||
private String challenge; |
||||
|
||||
|
||||
public LegacyCaptchaLayout(Context context) { |
||||
super(context); |
||||
} |
||||
|
||||
public LegacyCaptchaLayout(Context context, AttributeSet attrs) { |
||||
super(context, attrs); |
||||
} |
||||
|
||||
public LegacyCaptchaLayout(Context context, AttributeSet attrs, int defStyleAttr) { |
||||
super(context, attrs, defStyleAttr); |
||||
} |
||||
|
||||
@SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"}) |
||||
@Override |
||||
protected void onFinishInflate() { |
||||
super.onFinishInflate(); |
||||
|
||||
image = (FixedRatioThumbnailView) findViewById(R.id.image); |
||||
image.setRatio(300f / 57f); |
||||
image.setOnClickListener(this); |
||||
input = (EditText) findViewById(R.id.input); |
||||
submit = (ImageView) findViewById(R.id.submit); |
||||
theme().sendDrawable.apply(submit); |
||||
setRoundItemBackground(submit); |
||||
submit.setOnClickListener(this); |
||||
|
||||
// This captcha layout uses a webview in the background
|
||||
// Because the script changed significantly we can't just load the image straight up from the challenge data anymore.
|
||||
// Now we load a skeleton page in the background, and wait until both the image and challenge key are loaded,
|
||||
// then the onCaptchaLoaded is called through the javascript interface.
|
||||
|
||||
internalWebView = new WebView(getContext()); |
||||
internalWebView.setWebChromeClient(new WebChromeClient()); |
||||
internalWebView.setWebViewClient(new WebViewClient()); |
||||
|
||||
WebSettings settings = internalWebView.getSettings(); |
||||
settings.setJavaScriptEnabled(true); |
||||
|
||||
internalWebView.addJavascriptInterface(new CaptchaInterface(this), "CaptchaCallback"); |
||||
|
||||
//noinspection PointlessBooleanExpression
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && ChanBuild.DEVELOPER_MODE) { |
||||
WebView.setWebContentsDebuggingEnabled(true); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void onClick(View v) { |
||||
if (v == submit) { |
||||
callback.captchaEntered(this, challenge, input.getText().toString()); |
||||
} else if (v == image) { |
||||
reset(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, CaptchaCallback callback) { |
||||
this.baseUrl = baseUrl; |
||||
this.siteKey = siteKey; |
||||
this.callback = callback; |
||||
} |
||||
|
||||
@Override |
||||
public void reset() { |
||||
input.setText(""); |
||||
String html = IOUtils.assetAsString(getContext(), "captcha/captcha_legacy.html"); |
||||
html = html.replace("__site_key__", siteKey); |
||||
internalWebView.loadDataWithBaseURL(baseUrl, html, "text/html", "UTF-8", null); |
||||
image.setUrl(null, 0, 0); |
||||
} |
||||
|
||||
private void onCaptchaLoaded(final String imageUrl, final String challenge) { |
||||
this.challenge = challenge; |
||||
image.setUrl(imageUrl, 300, 57); |
||||
} |
||||
|
||||
public static class CaptchaInterface { |
||||
private final LegacyCaptchaLayout layout; |
||||
|
||||
public CaptchaInterface(LegacyCaptchaLayout layout) { |
||||
this.layout = layout; |
||||
} |
||||
|
||||
@JavascriptInterface |
||||
public void onCaptchaLoaded(final String imageUrl, final String challenge) { |
||||
AndroidUtils.runOnUiThread(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
layout.onCaptchaLoaded(imageUrl, challenge); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<org.floens.chan.ui.layout.LegacyCaptchaLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:orientation="vertical"> |
||||
|
||||
<org.floens.chan.ui.view.FixedRatioThumbnailView |
||||
android:id="@+id/image" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="80dp" /> |
||||
|
||||
<LinearLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="64dp" |
||||
android:orientation="horizontal" |
||||
android:padding="8dp"> |
||||
|
||||
<EditText |
||||
android:id="@+id/input" |
||||
android:layout_width="0dp" |
||||
android:layout_height="match_parent" |
||||
android:layout_weight="1" |
||||
android:hint="@string/reply_captcha_text" |
||||
android:singleLine="true" |
||||
android:textSize="16sp" /> |
||||
|
||||
<ImageView |
||||
android:id="@+id/submit" |
||||
android:layout_width="36dp" |
||||
android:layout_height="36dp" |
||||
android:layout_gravity="center_vertical" |
||||
android:padding="6dp" /> |
||||
|
||||
</LinearLayout> |
||||
|
||||
</org.floens.chan.ui.layout.LegacyCaptchaLayout> |
Loading…
Reference in new issue