/*
* Overchan Android (Meta Imageboard Client)
* Copyright (C) 2014-2016 miku-nyan <https://github.com/miku-nyan>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package nya.miku.wishmaster.http.cloudflare;
import nya.miku.wishmaster.R;
import nya.miku.wishmaster.api.HttpChanModule;
import nya.miku.wishmaster.api.interfaces.CancellableTask;
import nya.miku.wishmaster.common.Async;
import nya.miku.wishmaster.http.client.ExtendedHttpClient;
import nya.miku.wishmaster.http.interactive.InteractiveException;
import nya.miku.wishmaster.http.recaptcha.Recaptcha2;
import nya.miku.wishmaster.http.recaptcha.Recaptcha2solved;
import cz.msebera.android.httpclient.cookie.Cookie;
import java.util.Locale;
import android.app.Activity;
/**
* UI обработчик Cloudflare-исключений (статический класс)
* @author miku-nyan
*
*/
/*package*/ class CloudflareUIHandler {
private CloudflareUIHandler() {}
/**
* Обработать исключение-запрос проверки Cloudflare.
* Вызывать из фонового потока
* @param e исключение {@link CloudflareException}
* @param chan модуль чана
* @param activity активность, в которой будет создан диалог (в случае проверки с капчей),
* или в контексте которой будет создан WebView для Anti DDOS проверки с javascript.
* Используется как доступ к UI потоку ({@link Activity#runOnUiThread(Runnable)})
* @param cfTask отменяемая задача
* @param callback интерфейс {@link Callback}
*/
static void handleCloudflare(final CloudflareException e, final HttpChanModule chan, final Activity activity, final CancellableTask cfTask,
final InteractiveException.Callback callback) {
if (cfTask.isCancelled()) return;
if (!e.isRecaptcha()) { // обычная anti DDOS проверка
if (!CloudflareChecker.getInstance().isAvaibleAntiDDOS()) {
//если анти ддос проверка уже проводится другим потоком, тогда подождем завершения и объявим успех
//в случае, если проверка была по тому же ChanModule, проверка уже будет пройдена
//в противном случае на следующей попытке (закачки) cloudflare выкинет исключение снова
//и мы сможем обработать исключение для этого чана на свободном CloudflareChecker
while (!CloudflareChecker.getInstance().isAvaibleAntiDDOS()) Thread.yield();
if (!cfTask.isCancelled()) activity.runOnUiThread(new Runnable() {
@Override
public void run() {
callback.onSuccess();
}
});
return;
}
Cookie cfCookie = CloudflareChecker.getInstance().checkAntiDDOS(e, chan.getHttpClient(), cfTask, activity);
if (cfCookie != null) {
chan.saveCookie(cfCookie);
if (!cfTask.isCancelled()) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
callback.onSuccess();
}
});
}
} else if (!cfTask.isCancelled()) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
callback.onError(activity.getString(R.string.error_cloudflare_antiddos));
}
});
}
} else { // проверка с рекапчей
Recaptcha2.obtain(e.getCheckUrl(), e.getRecaptchaPublicKey(), e.getRecaptchaSecureToken(), chan.getChanName(), e.isRecaptchaFallback()).
handle(activity, cfTask, new InteractiveException.Callback() {
@Override
public void onSuccess() {
Async.runAsync(new Runnable() {
@Override
public void run() {
String url = String.format(Locale.US, e.getCheckCaptchaUrlFormat(), Recaptcha2solved.pop(e.getRecaptchaPublicKey()));
Cookie cfCookie = CloudflareChecker.getInstance().
checkRecaptcha(e, (ExtendedHttpClient) chan.getHttpClient(), cfTask, url);
if (cfCookie != null) {
chan.saveCookie(cfCookie);
if (!cfTask.isCancelled()) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
callback.onSuccess();
}
});
}
} else {
//печенька не получена (вероятно, ответ неверный, загружаем капчу еще раз)
handleCloudflare(e, chan, activity, cfTask, callback);
}
}
});
}
@Override
public void onError(String message) {
if (!cfTask.isCancelled()) callback.onError(message);
}
});
}
}
}