diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyHttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/CommonReplyHttpCall.java similarity index 63% rename from Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyHttpCall.java rename to Clover/app/src/main/java/org/floens/chan/core/site/common/CommonReplyHttpCall.java index b2595830..7747145f 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyHttpCall.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/CommonReplyHttpCall.java @@ -15,14 +15,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.floens.chan.core.site.sites.chan4; - -import android.text.TextUtils; +package org.floens.chan.core.site.common; import org.floens.chan.core.site.Site; import org.floens.chan.core.site.http.HttpCall; -import org.floens.chan.core.site.http.ReplyResponse; import org.floens.chan.core.site.http.Reply; +import org.floens.chan.core.site.http.ReplyResponse; import org.jsoup.Jsoup; import java.io.IOException; @@ -30,14 +28,13 @@ import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; -import okhttp3.MediaType; +import okhttp3.HttpUrl; import okhttp3.MultipartBody; import okhttp3.Request; -import okhttp3.RequestBody; import okhttp3.Response; -public class Chan4ReplyHttpCall extends HttpCall { - private static final String TAG = "Chan4ReplyHttpCall"; +public abstract class CommonReplyHttpCall extends HttpCall { + private static final String TAG = "CommonReplyHttpCall"; private static final Random RANDOM = new Random(); private static final Pattern THREAD_NO_PATTERN = Pattern.compile(""); private static final Pattern ERROR_MESSAGE = Pattern.compile("\"errmsg\"[^>]*>(.*?)<\\/span"); @@ -46,56 +43,23 @@ public class Chan4ReplyHttpCall extends HttpCall { public final Reply reply; public final ReplyResponse replyResponse = new ReplyResponse(); - public Chan4ReplyHttpCall(Site site, Reply reply) { + public CommonReplyHttpCall(Site site, Reply reply) { super(site); this.reply = reply; } @Override public void setup(Request.Builder requestBuilder) { - boolean thread = reply.loadable.isThreadMode(); - replyResponse.password = Long.toHexString(RANDOM.nextLong()); MultipartBody.Builder formBuilder = new MultipartBody.Builder(); formBuilder.setType(MultipartBody.FORM); - formBuilder.addFormDataPart("mode", "regist"); - formBuilder.addFormDataPart("pwd", replyResponse.password); - - if (thread) { - formBuilder.addFormDataPart("resto", String.valueOf(reply.loadable.no)); - } - - formBuilder.addFormDataPart("name", reply.name); - formBuilder.addFormDataPart("email", reply.options); - - if (!thread && !TextUtils.isEmpty(reply.subject)) { - formBuilder.addFormDataPart("sub", reply.subject); - } - - formBuilder.addFormDataPart("com", reply.comment); + addParameters(formBuilder); - if (reply.captchaResponse != null) { - 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) { - formBuilder.addFormDataPart("upfile", reply.fileName, RequestBody.create( - MediaType.parse("application/octet-stream"), reply.file - )); - } - - if (reply.spoilerImage) { - formBuilder.addFormDataPart("spoiler", "on"); - } - - requestBuilder.url(site.endpoints().reply(reply.loadable)); + HttpUrl replyUrl = site.endpoints().reply(this.reply.loadable); + requestBuilder.url(replyUrl); + requestBuilder.addHeader("Referer", replyUrl.toString()); requestBuilder.post(formBuilder.build()); } @@ -120,4 +84,6 @@ public class Chan4ReplyHttpCall extends HttpCall { } } } + + public abstract void addParameters(MultipartBody.Builder builder); } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCall.java index 310eff26..2fceb22b 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCall.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCall.java @@ -28,6 +28,7 @@ import okhttp3.Call; import okhttp3.Callback; import okhttp3.Request; import okhttp3.Response; +import okhttp3.ResponseBody; /** * Http calls are an abstraction over a normal OkHttp call. @@ -55,19 +56,21 @@ public abstract class HttpCall implements Callback { @Override public void onResponse(Call call, Response response) { + ResponseBody body = response.body(); try { - if (response.isSuccessful() && response.body() != null) { - String responseString = response.body().string(); + if (response.isSuccessful() && body != null) { + String responseString = body.string(); process(response, responseString); successful = true; } else { - onFailure(call, null); + String responseString = body == null ? "no body" : body.string(); + onFailure(call, new IOException("HTTP " + response.code() + "\n\n" + responseString)); } } catch (Exception e) { exception = e; Logger.e(TAG, "IOException processing response", e); } finally { - IOUtils.closeQuietly(response.body()); + IOUtils.closeQuietly(body); } if (successful) { diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java index b0ebfb8c..01742158 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java @@ -40,6 +40,7 @@ import org.floens.chan.core.site.SiteEndpoints; import org.floens.chan.core.site.SiteIcon; import org.floens.chan.core.site.SiteRequestModifier; import org.floens.chan.core.site.common.ChanReader; +import org.floens.chan.core.site.common.CommonReplyHttpCall; import org.floens.chan.core.site.common.FutabaChanReader; import org.floens.chan.core.site.http.DeleteRequest; import org.floens.chan.core.site.http.HttpCall; @@ -408,14 +409,14 @@ public class Chan4 extends SiteBase { @Override public void post(Reply reply, final PostListener postListener) { - httpCallManager.makeHttpCall(new Chan4ReplyHttpCall(this, reply), new HttpCall.HttpCallback() { + httpCallManager.makeHttpCall(new Chan4ReplyCall(this, reply), new HttpCall.HttpCallback() { @Override - public void onHttpSuccess(Chan4ReplyHttpCall httpPost) { + public void onHttpSuccess(CommonReplyHttpCall httpPost) { postListener.onPostComplete(httpPost, httpPost.replyResponse); } @Override - public void onHttpFail(Chan4ReplyHttpCall httpPost, Exception e) { + public void onHttpFail(CommonReplyHttpCall httpPost, Exception e) { postListener.onPostError(httpPost); } }); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyCall.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyCall.java new file mode 100644 index 00000000..c5819266 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4ReplyCall.java @@ -0,0 +1,72 @@ +/* + * Clover - 4chan browser https://github.com/Floens/Clover/ + * Copyright (C) 2014 Floens + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.floens.chan.core.site.sites.chan4; + +import android.text.TextUtils; + +import org.floens.chan.core.site.Site; +import org.floens.chan.core.site.common.CommonReplyHttpCall; +import org.floens.chan.core.site.http.Reply; + +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; + +public class Chan4ReplyCall extends CommonReplyHttpCall { + public Chan4ReplyCall(Site site, Reply reply) { + super(site, reply); + } + + @Override + public void addParameters(MultipartBody.Builder formBuilder) { + formBuilder.addFormDataPart("mode", "regist"); + formBuilder.addFormDataPart("pwd", replyResponse.password); + + if (reply.loadable.isThreadMode()) { + formBuilder.addFormDataPart("resto", String.valueOf(reply.loadable.no)); + } + + formBuilder.addFormDataPart("name", reply.name); + formBuilder.addFormDataPart("email", reply.options); + + if (!reply.loadable.isThreadMode() && !TextUtils.isEmpty(reply.subject)) { + formBuilder.addFormDataPart("sub", reply.subject); + } + + formBuilder.addFormDataPart("com", reply.comment); + + if (reply.captchaResponse != null) { + 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) { + formBuilder.addFormDataPart("upfile", reply.fileName, RequestBody.create( + MediaType.parse("application/octet-stream"), reply.file + )); + } + + if (reply.spoilerImage) { + formBuilder.addFormDataPart("spoiler", "on"); + } + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java index 72b2f102..5f176799 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java @@ -33,12 +33,15 @@ import org.floens.chan.core.site.SiteEndpoints; import org.floens.chan.core.site.SiteIcon; import org.floens.chan.core.site.SiteRequestModifier; import org.floens.chan.core.site.common.ChanReader; +import org.floens.chan.core.site.common.CommonReplyHttpCall; import org.floens.chan.core.site.common.FutabaChanParser; import org.floens.chan.core.site.common.FutabaChanReader; import org.floens.chan.core.site.http.DeleteRequest; import org.floens.chan.core.site.http.HttpCall; +import org.floens.chan.core.site.http.HttpCallManager; import org.floens.chan.core.site.http.LoginRequest; import org.floens.chan.core.site.http.Reply; +import org.floens.chan.utils.Logger; import java.util.Locale; import java.util.Map; @@ -49,6 +52,8 @@ import okhttp3.Request; import static org.floens.chan.Chan.getGraph; public class Chan8 extends SiteBase { + private static final String TAG = "Chan8"; + public static final Resolvable RESOLVABLE = new Resolvable() { @Override public ResolveResult resolve(String value) { @@ -78,6 +83,11 @@ public class Chan8 extends SiteBase { .host("media.8ch.net") .build(); + private final HttpUrl sys = new HttpUrl.Builder() + .scheme("https") + .host("sys.8ch.net") + .build(); + @Override public HttpUrl catalog(Board board) { return root.newBuilder() @@ -133,7 +143,9 @@ public class Chan8 extends SiteBase { @Override public HttpUrl reply(Loadable loadable) { - return null; + return sys.newBuilder() + .addPathSegment("post.php") + .build(); } @Override @@ -182,7 +194,12 @@ public class Chan8 extends SiteBase { @Override public boolean feature(Feature feature) { - return false; + switch (feature) { + case POSTING: + return true; + default: + return false; + } } @Override @@ -231,7 +248,22 @@ public class Chan8 extends SiteBase { } @Override - public void post(Reply reply, PostListener postListener) { + public void post(Reply reply, final PostListener postListener) { + // TODO + HttpCallManager httpCallManager = getGraph().get(HttpCallManager.class); + httpCallManager.makeHttpCall(new Chan8ReplyHttpCall(this, reply), new HttpCall.HttpCallback() { + @Override + public void onHttpSuccess(CommonReplyHttpCall httpPost) { + postListener.onPostComplete(httpPost, httpPost.replyResponse); + } + + @Override + public void onHttpFail(CommonReplyHttpCall httpPost, Exception e) { + Logger.e(TAG, "post error", e); + + postListener.onPostError(httpPost); + } + }); } @Override diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8ReplyHttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8ReplyHttpCall.java new file mode 100644 index 00000000..092da71c --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8ReplyHttpCall.java @@ -0,0 +1,70 @@ +/* + * Clover - 4chan browser https://github.com/Floens/Clover/ + * Copyright (C) 2014 Floens + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.floens.chan.core.site.sites.chan8; + +import android.text.TextUtils; + +import org.floens.chan.core.site.Site; +import org.floens.chan.core.site.http.Reply; +import org.floens.chan.core.site.common.CommonReplyHttpCall; + +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; + +public class Chan8ReplyHttpCall extends CommonReplyHttpCall { + public Chan8ReplyHttpCall(Site site, Reply reply) { + super(site, reply); + } + + @Override + public void addParameters(MultipartBody.Builder formBuilder) { +// formBuilder.addFormDataPart("pwd", replyResponse.password); + + formBuilder.addFormDataPart("board", reply.loadable.board.code); + + if (reply.loadable.isThreadMode()) { + formBuilder.addFormDataPart("post", "New Reply"); + + formBuilder.addFormDataPart("thread", String.valueOf(reply.loadable.no)); + } else { + formBuilder.addFormDataPart("post", "New Thread"); + + formBuilder.addFormDataPart("page", "1"); + } + + formBuilder.addFormDataPart("name", reply.name); + formBuilder.addFormDataPart("email", reply.options); + + if (!reply.loadable.isThreadMode() && !TextUtils.isEmpty(reply.subject)) { + formBuilder.addFormDataPart("subject", reply.subject); + } + + formBuilder.addFormDataPart("body", reply.comment); + + if (reply.file != null) { + formBuilder.addFormDataPart("file", reply.fileName, RequestBody.create( + MediaType.parse("application/octet-stream"), reply.file + )); + } + + if (reply.spoilerImage) { + formBuilder.addFormDataPart("spoiler", "on"); + } + } +}