diff --git a/app/build.gradle b/app/build.gradle index cb367db..d3f76e4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -57,6 +57,7 @@ dependencies { compile 'com.squareup.okhttp3:okhttp:3.0.1' compile 'org.apache.commons:commons-lang3:3.1' compile 'com.squareup.picasso:picasso:2.5.2' + compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.13' compile 'com.github.chrisbanes.photoview:library:1.2.3' compile 'me.imid.swipebacklayout.lib:library:1.0.0' diff --git a/app/src/main/java/com/ecchilon/sadpanda/ExhentaiModule.java b/app/src/main/java/com/ecchilon/sadpanda/ExhentaiModule.java index 51cde5d..2a1a6b4 100644 --- a/app/src/main/java/com/ecchilon/sadpanda/ExhentaiModule.java +++ b/app/src/main/java/com/ecchilon/sadpanda/ExhentaiModule.java @@ -1,18 +1,19 @@ package com.ecchilon.sadpanda; + import android.app.Application; import android.content.Context; import com.ecchilon.sadpanda.auth.ExhentaiAuth; import com.google.inject.AbstractModule; import com.google.inject.Inject; +import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.Singleton; +import com.jakewharton.picasso.OkHttp3Downloader; import com.squareup.picasso.Picasso; import okhttp3.OkHttpClient; +import okhttp3.Request; -/** - * Created by Alex on 20-9-2014. - */ public class ExhentaiModule extends AbstractModule { @Inject @@ -26,8 +27,19 @@ public ExhentaiModule(Application application) { protected void configure() { bind(ExhentaiAuth.class).in(Singleton.class); + Provider provider = getProvider(ExhentaiAuth.class); + OkHttpClient client = new OkHttpClient.Builder() + .addInterceptor(chain -> { + Request newRequest = chain.request().newBuilder() + .addHeader("Cookie", provider.get().getSessionCookie()) + .build(); + return chain.proceed(newRequest); + }) + .build(); + Picasso.Builder builder = new Picasso.Builder(context); builder.listener(new SadPandaApp.PicassoListener()); + builder.downloader(new OkHttp3Downloader(client)); Picasso.setSingletonInstance(builder.build()); } diff --git a/app/src/main/java/com/ecchilon/sadpanda/api/DataLoader.java b/app/src/main/java/com/ecchilon/sadpanda/api/DataLoader.java index 1257aa6..099fe2f 100644 --- a/app/src/main/java/com/ecchilon/sadpanda/api/DataLoader.java +++ b/app/src/main/java/com/ecchilon/sadpanda/api/DataLoader.java @@ -29,7 +29,6 @@ import lombok.Value; import okhttp3.CacheControl; import okhttp3.FormBody; -import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -77,8 +76,6 @@ public static class GalleryIdToken { private final OkHttpClient client; private final ExhentaiAuth auth; - private String sHeader; - @Inject DataLoader(OkHttpClient client, ExhentaiAuth auth) { this.client = client; @@ -277,7 +274,7 @@ private Observable getContent(String url) { private Observable getContent(String url, boolean useCache) { return Observable.just(url).map(requestUrl -> { Request.Builder builder = new Request.Builder() - .addHeader(COOKIE, getCookieHeader()) + .addHeader(COOKIE, auth.getSessionCookie()) .url(requestUrl) .get(); if (!useCache) { @@ -465,7 +462,7 @@ private Observable updateFavorite(@NonNull String favCat, @NonNull String Request request = new Request.Builder() .url(String.format(FAVORITES_URL_EX, entry.getGalleryId(), entry.getToken())) - .addHeader(COOKIE, getCookieHeader()) + .addHeader(COOKIE, auth.getSessionCookie()) .post(body) .build(); @@ -507,12 +504,7 @@ private String getBody(Request request) { Response response = null; try { response = client.newCall(request).execute(); - if (this.sHeader == null) { - this.sHeader = getSHeader(response.headers()); - if (sHeader != null) { - return reloadWithSHeader(request); - } - } + auth.addCookies(response.headers(ExhentaiAuth.SET_COOKIE)); return response.body().string(); } catch (IOException e) { @@ -524,31 +516,4 @@ private String getBody(Request request) { } } } - - private String getSHeader(Headers headers) { - for (String header : headers.values(SET_COOKIE)) { - if (header.startsWith("s=")) { - return header.split(";")[0].substring(2); - } - } - - return null; - } - - /** - * Somehow Exhentai sends a cookie-header 's' along with its favorites. Because - */ - private String reloadWithSHeader(Request request) { - Request.Builder builder = request.newBuilder(); - builder.header(COOKIE, getCookieHeader()); - return getBody(builder.build()); - } - - private String getCookieHeader() { - String cookie = auth.getSessionCookie(); - if (sHeader != null) { - cookie += ";s=" + sHeader; - } - return cookie; - } } diff --git a/app/src/main/java/com/ecchilon/sadpanda/auth/ExhentaiAuth.java b/app/src/main/java/com/ecchilon/sadpanda/auth/ExhentaiAuth.java index 0304ade..dba623e 100644 --- a/app/src/main/java/com/ecchilon/sadpanda/auth/ExhentaiAuth.java +++ b/app/src/main/java/com/ecchilon/sadpanda/auth/ExhentaiAuth.java @@ -1,13 +1,15 @@ package com.ecchilon.sadpanda.auth; -import static com.ecchilon.sadpanda.auth.ExhentaiAuth.ExhentaiError.INCORRECT_AUTH; import static com.ecchilon.sadpanda.auth.ExhentaiAuth.ExhentaiError.UNKNOWN; import java.io.IOException; -import java.util.Collections; +import java.net.HttpCookie; +import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicReference; +import android.content.Context; import android.content.SharedPreferences; import android.text.TextUtils; import com.google.common.collect.Lists; @@ -22,6 +24,7 @@ import rx.schedulers.Schedulers; public class ExhentaiAuth { + public enum ExhentaiError { NO_USERNAME("You must enter a username"), USER_NOT_FOUND("You must already have registered for an account before you can log in"), @@ -47,14 +50,10 @@ public static class AuthException extends RuntimeException { } } - private static final String USERNAME_KEY = "pandaUserNameKey"; - public static final String MEMBER_KEY = "pandaMemberKey"; - public static final String HASH_KEY = "pandaHashKey"; - public static final String SESSION_KEY = "pandaSessionKey"; + public static final String SET_COOKIE = "Set-Cookie"; + private static final String COOKIE_PREFERENCES = "cookie_prefs"; - public static final String IPB_MEMBER_ID = "ipb_member_id"; - public static final String IPB_PASS_HASH = "ipb_pass_hash"; - public static final String IPB_SESSION_ID = "ipb_session_id"; + private static final String USERNAME_KEY = "pandaUserNameKey"; private static final String LOGIN = "https://forums.e-hentai.org/index.php?act=Login&CODE=01"; @@ -64,19 +63,16 @@ public static class AuthException extends RuntimeException { private final AtomicReference sessionCookie = new AtomicReference<>(); @Inject - public ExhentaiAuth(OkHttpClient client, SharedPreferences sharedPreferences) { + public ExhentaiAuth(OkHttpClient client, Context context) { this.client = client; - this.sharedPreferences = sharedPreferences; + this.sharedPreferences = context.getSharedPreferences(COOKIE_PREFERENCES, Context.MODE_PRIVATE); } public void logout() { sessionCookie.set(null); sharedPreferences.edit() - .remove(MEMBER_KEY) - .remove(HASH_KEY) - .remove(SESSION_KEY) - .remove(USERNAME_KEY) + .clear() .apply(); } @@ -104,7 +100,7 @@ public Observable login(final String username, String password) { .subscribeOn(Schedulers.io()) .observeOn(Schedulers.computation()) .map(response -> { - String body = null; + String body; try { body = response.body().string(); } @@ -112,42 +108,8 @@ public Observable login(final String username, String password) { throw OnErrorThrowable.from(e); } if (body.contains("You are now logged in as: ")) { - List cookies = Lists.newArrayList(); - for(String cookie : response.headers("Set-Cookie")) { - Collections.addAll(cookies, cookie.split(";")); - } - - String memberId = null, passHash = null, sessionId = null; - - for (String cookie : cookies) { - String[] kvPair = cookie.split("="); - if(kvPair.length != 2) { - continue; - } - String key = kvPair[0]; - String value = kvPair[1]; - if(IPB_MEMBER_ID.equals(key)) { - memberId = value; - } - else if(IPB_PASS_HASH.equals(key)) { - passHash = value; - } - else if(IPB_SESSION_ID.equals(key)) { - sessionId = value; - } - } - - if((memberId == null || passHash == null || sessionId == null)) { - throw OnErrorThrowable.from(new AuthException(INCORRECT_AUTH)); - } - - sharedPreferences.edit() - .putString(MEMBER_KEY, memberId) - .putString(HASH_KEY, passHash) - .putString(SESSION_KEY, sessionId) - .putString(USERNAME_KEY, username) - .apply(); - + addCookies(response.headers(SET_COOKIE)); + sharedPreferences.edit().putString(USERNAME_KEY, username).apply(); return null; } else { @@ -163,18 +125,35 @@ else if(IPB_SESSION_ID.equals(key)) { } public boolean isLoggedIn() { - return sharedPreferences.contains(SESSION_KEY); + return sharedPreferences.contains(USERNAME_KEY); } public String getUserName() { return sharedPreferences.getString(USERNAME_KEY, null); } + public void addCookies(Collection cookies) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + boolean addedCookie = false; + for (String entry : cookies) { + for (HttpCookie cookie : HttpCookie.parse(entry)) { + editor.putString(cookie.getName(), cookie.getValue()); + addedCookie = true; + } + } + + if (addedCookie) { + sessionCookie.set(null); + } + + editor.apply(); + } + public String getSessionCookie() { synchronized (sessionCookie) { String cookie = sessionCookie.get(); - if(cookie == null) { - cookie = createCookie(); + if (cookie == null) { + cookie = createSessionCookie(); sessionCookie.set(cookie); } @@ -182,18 +161,14 @@ public String getSessionCookie() { } } - private String createCookie() { - String[] cookies = new String[] { - getCookieKeyValue(IPB_MEMBER_ID, MEMBER_KEY), - getCookieKeyValue(IPB_PASS_HASH, HASH_KEY), - getCookieKeyValue(IPB_SESSION_ID, SESSION_KEY) - }; + private String createSessionCookie() { + Map cookieMap = sharedPreferences.getAll(); + List cookies = Lists.newArrayListWithExpectedSize(cookieMap.size()); + for (Map.Entry entry : cookieMap.entrySet()) { + cookies.add(entry.getKey() + "=" + entry.getValue()); + } return TextUtils.join(";", cookies); } - - private String getCookieKeyValue(String key, String preferenceKey) { - return key + "=" + sharedPreferences.getString(preferenceKey, ""); - } } diff --git a/build.gradle b/build.gradle index 449e8c5..e3e29bc 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.2.0' classpath 'me.tatarka:gradle-retrolambda:3.2.4' // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a0db497..ebf40a0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Mar 03 14:18:53 CET 2015 +#Mon Nov 28 22:29:10 CET 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip