diff --git a/Clover/app/src/main/assets/captcha/captcha.html b/Clover/app/src/main/assets/captcha/captcha.html index 8ecec8d4..5bddbcbe 100644 --- a/Clover/app/src/main/assets/captcha/captcha.html +++ b/Clover/app/src/main/assets/captcha/captcha.html @@ -1,7 +1,7 @@ - + + + +
+
+ +
+ + + + + diff --git a/Clover/app/src/main/java/org/floens/chan/core/http/ReplyHttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/http/ReplyHttpCall.java index 21f7fa8f..dadb846b 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/http/ReplyHttpCall.java +++ b/Clover/app/src/main/java/org/floens/chan/core/http/ReplyHttpCall.java @@ -79,7 +79,12 @@ public class ReplyHttpCall extends HttpCall { formBuilder.addFormDataPart("com", reply.comment); if (reply.captchaResponse != null) { - formBuilder.addFormDataPart("g-recaptcha-response", reply.captchaResponse); + if (reply.captchaChallenge != null) { + formBuilder.addFormDataPart("recaptcha_challenge_field", reply.captchaChallenge); + formBuilder.addFormDataPart("recaptcha_response_field", reply.captchaResponse); + } else { + formBuilder.addFormDataPart("g-recaptcha-response", reply.captchaResponse); + } } if (reply.file != null) { diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/Reply.java b/Clover/app/src/main/java/org/floens/chan/core/model/Reply.java index 5845e79f..400b7f52 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/model/Reply.java +++ b/Clover/app/src/main/java/org/floens/chan/core/model/Reply.java @@ -23,6 +23,14 @@ import java.io.File; * The data needed to send a reply. */ public class Reply { + /** + * Optional. Null when ReCaptcha v2 was used or a 4pass + */ + public String captchaChallenge; + + /** + * Optional. Null when a 4pass was used. + */ public String captchaResponse; public boolean usePass = false; public String board; diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java index dab385ae..91d7f7a0 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java @@ -233,7 +233,8 @@ public class ReplyPresenter implements ReplyManager.FileListener, ReplyManager.H } @Override - public void captchaEntered(CaptchaLayout captchaLayout, String response) { + public void captchaEntered(CaptchaLayout captchaLayout, String challenge, String response) { + draft.captchaChallenge = challenge; draft.captchaResponse = response; captchaLayout.reset(); makeSubmitCall(); diff --git a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java index 17b90228..a5336aa3 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java +++ b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java @@ -43,6 +43,7 @@ public class ChanSettings { public static final StringSetting postDefaultName; public static final BooleanSetting postPinThread; + public static final BooleanSetting postNewCaptcha; public static final BooleanSetting developer; @@ -87,6 +88,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); developer = new BooleanSetting(p, "preference_developer", false); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java index 38c880bb..a9af23bf 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java @@ -80,6 +80,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))); 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))); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayout.java index a897b731..d6fa9ae0 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/CaptchaLayout.java @@ -19,6 +19,8 @@ package org.floens.chan.ui.layout; import android.annotation.SuppressLint; import android.content.Context; +import android.net.Uri; +import android.os.Build; import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.AttributeSet; @@ -28,7 +30,9 @@ import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; +import android.webkit.WebViewClient; +import org.floens.chan.ChanBuild; import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.IOUtils; @@ -40,6 +44,7 @@ public class CaptchaLayout extends WebView { private String baseUrl; private String siteKey; private boolean lightTheme; + private boolean useNew; public CaptchaLayout(Context context) { super(context); @@ -54,11 +59,12 @@ public class CaptchaLayout extends WebView { } @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"}) - public void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, CaptchaCallback callback) { + public void initCaptcha(String baseUrl, String siteKey, boolean lightTheme, boolean useNew, CaptchaCallback callback) { this.callback = callback; this.baseUrl = baseUrl; this.siteKey = siteKey; this.lightTheme = lightTheme; + this.useNew = useNew; WebSettings settings = getSettings(); settings.setJavaScriptEnabled(true); @@ -70,16 +76,33 @@ public class CaptchaLayout extends WebView { return true; } }); + + setWebViewClient(new WebViewClient() { + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + if (Uri.parse(url).getHost().equals(Uri.parse(CaptchaLayout.this.baseUrl).getHost())) { + return false; + } else { + AndroidUtils.openLink(url); + return true; + } + } + }); setBackgroundColor(0x00000000); addJavascriptInterface(new CaptchaInterface(this), "CaptchaCallback"); + + //noinspection PointlessBooleanExpression + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && ChanBuild.DEVELOPER_MODE) { + setWebContentsDebuggingEnabled(true); + } } public void load() { if (!loaded) { loaded = true; - String html = IOUtils.assetAsString(getContext(), "captcha/captcha.html"); + String html = IOUtils.assetAsString(getContext(), useNew ? "captcha/captcha.html" : "captcha/captcha1.html"); html = html.replace("__site_key__", siteKey); html = html.replace("__theme__", lightTheme ? "light" : "dark"); @@ -89,7 +112,11 @@ public class CaptchaLayout extends WebView { public void reset() { if (loaded) { - loadUrl("javascript:grecaptcha.reset()"); + if (useNew) { + loadUrl("javascript:grecaptcha.reset()"); + } else { + loadUrl("javascript:Recaptcha.reload()"); + } } else { load(); } @@ -99,18 +126,18 @@ public class CaptchaLayout extends WebView { callback.captchaLoaded(this); } - private void onCaptchaEntered(String response) { + private void onCaptchaEntered(String challenge, String response) { if (TextUtils.isEmpty(response)) { reset(); } else { - callback.captchaEntered(this, response); + callback.captchaEntered(this, challenge, response); } } public interface CaptchaCallback { void captchaLoaded(CaptchaLayout captchaLayout); - void captchaEntered(CaptchaLayout captchaLayout, String response); + void captchaEntered(CaptchaLayout captchaLayout, String challenge, String response); } public static class CaptchaInterface { @@ -135,7 +162,17 @@ public class CaptchaLayout extends WebView { AndroidUtils.runOnUiThread(new Runnable() { @Override public void run() { - layout.onCaptchaEntered(response); + layout.onCaptchaEntered(null, response); + } + }); + } + + @JavascriptInterface + public void onCaptchaEnteredv1(final String challenge, final String response) { + AndroidUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + layout.onCaptchaEntered(challenge, response); } }); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java index 78efb260..bf89eba0 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java @@ -37,6 +37,7 @@ import org.floens.chan.R; import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Reply; import org.floens.chan.core.presenter.ReplyPresenter; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.ui.drawable.DropdownArrowDrawable; import org.floens.chan.ui.view.LoadView; import org.floens.chan.ui.view.SelectionListeningEditText; @@ -165,7 +166,7 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); } else { // Captcha and the loadbar - return new LayoutParams(LayoutParams.MATCH_PARENT, dp(250)); + return new LayoutParams(LayoutParams.MATCH_PARENT, getResources().getDimensionPixelSize(R.dimen.reply_height_loading)); } } @@ -217,7 +218,7 @@ 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, callback); + captchaLayout.initCaptcha(baseUrl, siteKey, ThemeHelper.getInstance().getTheme().isLightTheme, ChanSettings.postNewCaptcha.get(), callback); captchaLayout.load(); } diff --git a/Clover/app/src/main/res/values-sw600dp/dimens.xml b/Clover/app/src/main/res/values-sw600dp/dimens.xml index cbbfb63b..bc6907e6 100644 --- a/Clover/app/src/main/res/values-sw600dp/dimens.xml +++ b/Clover/app/src/main/res/values-sw600dp/dimens.xml @@ -20,4 +20,6 @@ along with this program. If not, see . 180dp 5 + + 400dp diff --git a/Clover/app/src/main/res/values/dimens.xml b/Clover/app/src/main/res/values/dimens.xml index dcc4d304..a0d0458d 100644 --- a/Clover/app/src/main/res/values/dimens.xml +++ b/Clover/app/src/main/res/values/dimens.xml @@ -22,4 +22,6 @@ along with this program. If not, see . 140dp -1 + + 250dp diff --git a/Clover/app/src/main/res/values/strings.xml b/Clover/app/src/main/res/values/strings.xml index afa2cc6f..94354df4 100644 --- a/Clover/app/src/main/res/values/strings.xml +++ b/Clover/app/src/main/res/values/strings.xml @@ -213,6 +213,8 @@ along with this program. If not, see . File save folder Error creating save folder Choose + Use the new captcha + Disable to fallback to the old captcha (EXPERIMENTAL). Save original filename Share url to image Share the url to the image instead of the image itself