Properly fix captchas, use the official noscript fallback method.

captchafix2
Floens 11 years ago
parent 0b5d885dff
commit 1a03c005fe
  1. 6
      Clover/app/src/main/java/org/floens/chan/chan/ChanUrls.java
  2. 53
      Clover/app/src/main/java/org/floens/chan/core/manager/ReplyManager.java
  3. 27
      docs/gcaptcha.txt

@ -43,7 +43,11 @@ public class ChanUrls {
} }
public static String getCaptchaImageUrl(String challenge) { public static String getCaptchaImageUrl(String challenge) {
return scheme + "://www.google.com/recaptcha/api/image?c=" + challenge; return scheme + "://www.google.com/recaptcha/api2/payload?c=" + challenge;
}
public static String getCaptchaFallback() {
return scheme + "://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc";
} }
public static String getImageUrl(String board, String code, String extension) { public static String getImageUrl(String board, String code, String extension) {

@ -29,6 +29,9 @@ import org.floens.chan.core.model.SavedReply;
import org.floens.chan.ui.activity.ImagePickActivity; import org.floens.chan.ui.activity.ImagePickActivity;
import org.floens.chan.utils.Logger; import org.floens.chan.utils.Logger;
import org.floens.chan.utils.Utils; import org.floens.chan.utils.Utils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -333,6 +336,37 @@ public class ReplyManager {
public String responseData = ""; public String responseData = "";
} }
private void getCaptchaHash(final CaptchaHashListener listener, String challenge, String response) {
HttpPost httpPost = new HttpPost(ChanUrls.getCaptchaFallback());
MultipartEntityBuilder entity = MultipartEntityBuilder.create();
entity.addTextBody("c", challenge, TEXT_UTF_8);
entity.addTextBody("response", response, TEXT_UTF_8);
httpPost.setEntity(entity.build());
sendHttpPost(httpPost, new HttpPostSendListener() {
@Override
public void onResponse(String responseString, HttpClient client, HttpResponse response) {
if (responseString != null) {
Document document = Jsoup.parseBodyFragment(responseString);
Elements verificationToken = document.select("div.fbc-verification-token textarea");
String hash = verificationToken.text();
if (hash.length() > 0) {
listener.onHash(hash);
return;
}
}
listener.onHash(null);
}
});
}
private interface CaptchaHashListener {
public void onHash(String hash);
}
/** /**
* Send an reply off to the server. * Send an reply off to the server.
* *
@ -343,6 +377,18 @@ public class ReplyManager {
public void sendReply(final Reply reply, final ReplyListener listener) { public void sendReply(final Reply reply, final ReplyListener listener) {
Logger.i(TAG, "Sending reply request: " + reply.board + ", " + reply.resto); Logger.i(TAG, "Sending reply request: " + reply.board + ", " + reply.resto);
CaptchaHashListener captchaHashListener = new CaptchaHashListener() {
@Override
public void onHash(String captchaHash) {
if (captchaHash == null) {
// Could not find a hash in the response html
ReplyResponse e = new ReplyResponse();
e.isUserError = true;
e.isCaptchaError = true;
listener.onResponse(e);
return;
}
HttpPost httpPost = new HttpPost(ChanUrls.getReplyUrl(reply.board)); HttpPost httpPost = new HttpPost(ChanUrls.getReplyUrl(reply.board));
MultipartEntityBuilder entity = MultipartEntityBuilder.create(); MultipartEntityBuilder entity = MultipartEntityBuilder.create();
@ -363,8 +409,7 @@ public class ReplyManager {
entity.addTextBody("spoiler", "on"); entity.addTextBody("spoiler", "on");
} }
entity.addTextBody("recaptcha_challenge_field", reply.captchaChallenge); entity.addTextBody("g-recaptcha-response", captchaHash, TEXT_UTF_8);
entity.addTextBody("g-recaptcha-response", reply.captchaResponse, TEXT_UTF_8);
entity.addTextBody("mode", "regist"); entity.addTextBody("mode", "regist");
entity.addTextBody("pwd", reply.password); entity.addTextBody("pwd", reply.password);
@ -434,6 +479,10 @@ public class ReplyManager {
} }
}); });
} }
};
getCaptchaHash(captchaHashListener, reply.captchaChallenge, reply.captchaResponse);
}
public static interface ReplyListener { public static interface ReplyListener {
public void onResponse(ReplyResponse response); public void onResponse(ReplyResponse response);

@ -1,20 +1,31 @@
4chan captcha key:
4chan key:
6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc 6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
Google supports a noscript version of the new recaptcha, described here https://developers.google.com/recaptcha/docs/faq
https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
Put this in an iframe and when the user has successfully filled in the captcha the user is told to copy paste the key into the real website field (outside the iframe, g-captcha-response)
https://www.google.com/recaptcha/api/challenge?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
contains the key 'challenge'
Clover supports the fallback method (for now) Now load the image
https://www.google.com/recaptcha/api2/payload?c=CHALLENGE
after the user has solved the image, do a POST to
Stuff
https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc
into an iframe POST:
c = CHALLENGE
response = USER_RESPONSE
You'll have to get hash inside the textarea of div.fbc-verification-token
next send off the reply to 4chan
POST:
g-captcha-response: HASH
add an input field named
g-recaptcha-response

Loading…
Cancel
Save