Fix the legacy recaptcha, use it as default.

multisite
Floens 10 years ago
parent 20c9623851
commit ee7dffae7d
  1. 45
      Clover/app/src/main/assets/captcha/captcha1.html
  2. 40
      Clover/app/src/main/assets/captcha/captcha_legacy.html
  3. 11
      Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java
  4. 2
      Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java
  5. 6
      Clover/app/src/main/java/org/floens/chan/ui/cell/CardPostCell.java
  6. 5
      Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java
  7. 7
      Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaCallback.java
  8. 32
      Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayout.java
  9. 7
      Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayoutInterface.java
  10. 133
      Clover/app/src/main/java/org/floens/chan/ui/layout/LegacyCaptchaLayout.java
  11. 30
      Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java
  12. 8
      Clover/app/src/main/java/org/floens/chan/ui/view/FixedRatioThumbnailView.java
  13. 36
      Clover/app/src/main/res/layout/layout_captcha_legacy.xml
  14. 2
      Clover/app/src/main/res/values-sw600dp/dimens.xml
  15. 2
      Clover/app/src/main/res/values/dimens.xml
  16. 8
      Clover/app/src/main/res/values/strings.xml

@ -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>

@ -36,7 +36,8 @@ import org.floens.chan.core.model.SavedReply;
import org.floens.chan.core.pool.LoadablePool;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.ui.helper.ImagePickDelegate;
import org.floens.chan.ui.layout.CaptchaLayout;
import org.floens.chan.ui.layout.CaptchaCallback;
import org.floens.chan.ui.layout.CaptchaLayoutInterface;
import java.io.File;
import java.nio.charset.Charset;
@ -47,7 +48,7 @@ import static org.floens.chan.utils.AndroidUtils.getReadableFileSize;
import static org.floens.chan.utils.AndroidUtils.getRes;
import static org.floens.chan.utils.AndroidUtils.getString;
public class ReplyPresenter implements ReplyManager.HttpCallback<ReplyHttpCall>, CaptchaLayout.CaptchaCallback, ImagePickDelegate.ImagePickCallback {
public class ReplyPresenter implements ReplyManager.HttpCallback<ReplyHttpCall>, CaptchaCallback, ImagePickDelegate.ImagePickCallback {
public enum Page {
INPUT,
CAPTCHA,
@ -238,11 +239,11 @@ public class ReplyPresenter implements ReplyManager.HttpCallback<ReplyHttpCall>,
}
@Override
public void captchaLoaded(CaptchaLayout captchaLayout) {
public void captchaLoaded(CaptchaLayoutInterface captchaLayout) {
}
@Override
public void captchaEntered(CaptchaLayout captchaLayout, String challenge, String response) {
public void captchaEntered(CaptchaLayoutInterface captchaLayout, String challenge, String response) {
draft.captchaChallenge = challenge;
draft.captchaResponse = response;
captchaLayout.reset();
@ -402,7 +403,7 @@ public class ReplyPresenter implements ReplyManager.HttpCallback<ReplyHttpCall>,
void setPage(Page page, boolean animate);
void initCaptcha(String baseUrl, String siteKey, CaptchaLayout.CaptchaCallback callback);
void initCaptcha(String baseUrl, String siteKey, CaptchaCallback callback);
void resetCaptcha();

@ -132,7 +132,7 @@ public class ChanSettings {
postDefaultName = new StringSetting(p, "preference_default_name", "");
postPinThread = new BooleanSetting(p, "preference_pin_on_post", false);
postNewCaptcha = new BooleanSetting(p, "preference_new_captcha", true);
postNewCaptcha = new BooleanSetting(p, "preference_new_captcha", false);
developer = new BooleanSetting(p, "preference_developer", false);

@ -33,6 +33,7 @@ import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.ui.theme.Theme;
import org.floens.chan.ui.theme.ThemeHelper;
import org.floens.chan.ui.view.FastTextView;
import org.floens.chan.ui.view.FixedRatioThumbnailView;
import org.floens.chan.ui.view.FloatingMenu;
import org.floens.chan.ui.view.FloatingMenuItem;
import org.floens.chan.ui.view.ThumbnailView;
@ -50,7 +51,7 @@ public class CardPostCell extends CardView implements PostCellInterface, View.On
private Post post;
private PostCellInterface.PostCellCallback callback;
private ThumbnailView thumbnailView;
private FixedRatioThumbnailView thumbnailView;
private TextView title;
private FastTextView comment;
private TextView replies;
@ -73,7 +74,8 @@ public class CardPostCell extends CardView implements PostCellInterface, View.On
protected void onFinishInflate() {
super.onFinishInflate();
thumbnailView = (ThumbnailView) findViewById(R.id.thumbnail);
thumbnailView = (FixedRatioThumbnailView) findViewById(R.id.thumbnail);
thumbnailView.setRatio(16f / 9f);
thumbnailView.setOnClickListener(this);
title = (TextView) findViewById(R.id.title);
comment = (FastTextView) findViewById(R.id.comment);

@ -45,6 +45,7 @@ public class AdvancedSettingsController extends SettingsController {
private boolean needRestart;
private LinkSettingView saveLocation;
private SettingView newCaptcha;
private SettingView forcePhoneLayoutSetting;
private SettingView enableReplyFab;
private SettingView postFullDate;
@ -85,7 +86,7 @@ public class AdvancedSettingsController extends SettingsController {
public void onPreferenceChange(SettingView item) {
super.onPreferenceChange(item);
if (item == forcePhoneLayoutSetting || item == enableReplyFab) {
if (item == forcePhoneLayoutSetting || item == enableReplyFab || item == newCaptcha) {
needRestart = true;
}
@ -118,7 +119,7 @@ public class AdvancedSettingsController extends SettingsController {
}));
setSaveLocationDescription();
settings.add(new BooleanSettingView(this, ChanSettings.postNewCaptcha, string(R.string.setting_use_new_captcha), string(R.string.setting_use_new_captcha_description)));
newCaptcha = settings.add(new BooleanSettingView(this, ChanSettings.postNewCaptcha, string(R.string.setting_use_new_captcha), string(R.string.setting_use_new_captcha_description)));
settings.add(new BooleanSettingView(this, ChanSettings.saveOriginalFilename, string(R.string.setting_save_original_filename), null));
settings.add(new BooleanSettingView(this, ChanSettings.shareUrl, string(R.string.setting_share_url), string(R.string.setting_share_url_description)));
settings.add(new BooleanSettingView(this, ChanSettings.networkHttps, string(R.string.setting_network_https), string(R.string.setting_network_https_description)));

@ -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);
}

@ -36,7 +36,7 @@ import org.floens.chan.ChanBuild;
import org.floens.chan.utils.AndroidUtils;
import org.floens.chan.utils.IOUtils;
public class CaptchaLayout extends WebView {
public class CaptchaLayout extends WebView implements CaptchaLayoutInterface {
private static final String TAG = "CaptchaLayout";
private CaptchaCallback callback;
@ -44,7 +44,6 @@ public class CaptchaLayout extends WebView {
private String baseUrl;
private String siteKey;
private boolean lightTheme;
private boolean useNew;
public CaptchaLayout(Context context) {
super(context);
@ -59,12 +58,11 @@ public class CaptchaLayout extends WebView {
}
@SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
public void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, boolean useNew, CaptchaCallback callback) {
public void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, CaptchaCallback callback) {
this.callback = callback;
this.baseUrl = baseUrl;
this.siteKey = siteKey;
this.lightTheme = lightTheme;
this.useNew = useNew;
WebSettings settings = getSettings();
settings.setJavaScriptEnabled(true);
@ -98,11 +96,13 @@ public class CaptchaLayout extends WebView {
}
}
public void load() {
if (!loaded) {
public void reset() {
if (loaded) {
loadUrl("javascript:grecaptcha.reset()");
} else {
loaded = true;
String html = IOUtils.assetAsString(getContext(), useNew ? "captcha/captcha.html" : "captcha/captcha1.html");
String html = IOUtils.assetAsString(getContext(), "captcha/captcha.html");
html = html.replace("__site_key__", siteKey);
html = html.replace("__theme__", lightTheme ? "light" : "dark");
@ -110,18 +110,6 @@ public class CaptchaLayout extends WebView {
}
}
public void reset() {
if (loaded) {
if (useNew) {
loadUrl("javascript:grecaptcha.reset()");
} else {
loadUrl("javascript:Recaptcha.reload()");
}
} else {
load();
}
}
private void onCaptchaLoaded() {
callback.captchaLoaded(this);
}
@ -134,12 +122,6 @@ public class CaptchaLayout extends WebView {
}
}
public interface CaptchaCallback {
void captchaLoaded(CaptchaLayout captchaLayout);
void captchaEntered(CaptchaLayout captchaLayout, String challenge, String response);
}
public static class CaptchaInterface {
private final CaptchaLayout layout;

@ -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);
}
});
}
}
}

@ -23,6 +23,7 @@ import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
@ -61,7 +62,7 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima
private ReplyLayoutCallback callback;
private View replyInputLayout;
private CaptchaLayout captchaLayout;
private CaptchaLayoutInterface captchaLayout;
private boolean openingName;
private boolean blockSelectionChange = false;
@ -161,11 +162,13 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima
@Override
public LayoutParams getLayoutParamsForView(View view) {
if (view == replyInputLayout) {
if (view == replyInputLayout || (view == captchaLayout && captchaLayout instanceof LegacyCaptchaLayout)) {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
} else if (view == captchaLayout && captchaLayout instanceof CaptchaLayout) {
return new LayoutParams(LayoutParams.MATCH_PARENT, dp(300));
} else {
// Captcha and the loadbar
return new LayoutParams(LayoutParams.MATCH_PARENT, getResources().getDimensionPixelSize(R.dimen.reply_height_loading));
// Loadbar
return new LayoutParams(LayoutParams.MATCH_PARENT, dp(100));
}
}
@ -193,6 +196,11 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima
}*/
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return true;
}
@Override
public void setPage(ReplyPresenter.Page page, boolean animate) {
setAnimateLayout(animate, true);
@ -205,10 +213,14 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima
break;
case CAPTCHA:
if (captchaLayout == null) {
captchaLayout = new CaptchaLayout(getContext());
if (ChanSettings.postNewCaptcha.get()) {
captchaLayout = new CaptchaLayout(getContext());
} else {
captchaLayout = (CaptchaLayoutInterface) LayoutInflater.from(getContext()).inflate(R.layout.layout_captcha_legacy, this, false);
}
}
setView(captchaLayout);
setView((View) captchaLayout);
AndroidUtils.hideKeyboard(this);
break;
@ -216,9 +228,9 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima
}
@Override
public void initCaptcha(String baseUrl, String siteKey, CaptchaLayout.CaptchaCallback callback) {
captchaLayout.initCaptcha(baseUrl, siteKey, ThemeHelper.getInstance().getTheme().isLightTheme, ChanSettings.postNewCaptcha.get(), callback);
captchaLayout.load();
public void initCaptcha(String baseUrl, String siteKey, CaptchaCallback callback) {
captchaLayout.initCaptcha(baseUrl, siteKey, ThemeHelper.getInstance().getTheme().isLightTheme, callback);
captchaLayout.reset();
}
@Override

@ -21,6 +21,8 @@ import android.content.Context;
import android.util.AttributeSet;
public class FixedRatioThumbnailView extends ThumbnailView {
private float ratio;
public FixedRatioThumbnailView(Context context) {
super(context);
}
@ -33,13 +35,17 @@ public class FixedRatioThumbnailView extends ThumbnailView {
super(context, attrs, defStyleAttr);
}
public void setRatio(float ratio) {
this.ratio = ratio;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY && (heightMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.AT_MOST)) {
int width = MeasureSpec.getSize(widthMeasureSpec);
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec((int) (width / 16f * 9f), MeasureSpec.EXACTLY));
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec((int) (width / ratio), MeasureSpec.EXACTLY));
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@ -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>

@ -21,7 +21,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<dimen name="grid_card_width">105dp</dimen>
<dimen name="grid_card_height">240dp</dimen>
<dimen name="reply_height_loading">400dp</dimen>
<dimen name="cell_post_thumbnail_size">100dp</dimen>
</resources>

@ -23,7 +23,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<dimen name="grid_card_width">120dp</dimen>
<dimen name="grid_card_height">200dp</dimen>
<dimen name="reply_height_loading">250dp</dimen>
<dimen name="cell_post_thumbnail_size">72dp</dimen>
</resources>

@ -237,6 +237,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<string name="reply_submit">Submit</string>
<string name="reply_error">Error posting</string>
<string name="reply_success">Post successful</string>
<string name="reply_captcha_text">Type the text</string>
<string name="delete_confirm">Delete your post?</string>
<string name="delete_wait">Deleting post&#8230;</string>
@ -332,7 +333,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<string name="setting_save_folder_error_create_folder">Error creating save folder</string>
<string name="setting_folder_pick_ok">Choose</string>
<string name="setting_use_new_captcha">Use the new captcha</string>
<string name="setting_use_new_captcha_description">Disable to fallback to the old captcha (EXPERIMENTAL).</string>
<string name="setting_use_new_captcha_description">Enable to use the newer recaptcha.</string>
<string name="setting_save_original_filename">Save original filename</string>
<string name="setting_share_url">Share url to image</string>
<string name="setting_share_url_description">Share the url to the image instead of the image itself</string>
@ -409,8 +410,3 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<string name="settings_screen_theme">Themes</string>
</resources>

Loading…
Cancel
Save