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