Add recaptcha
This commit is contained in:
1 parent
550d3735c7
commit
2c3fa31e91
29 files changed
+1591
-519
No files matched your search
@@ -55,6 +55,7 @@ dependencies {
|
||||
compile "com.android.support:appcompat-v7:$supportLibrary"
|
||||
compile "com.android.support:design:$supportLibrary"
|
||||
compile 'com.github.amlcurran.showcaseview:library:5.4.3'
|
||||
compile 'com.github.seven332:android-recaptcha:2bbb3459a8'
|
||||
compile 'com.github.seven332:animator:0.1.0'
|
||||
compile 'com.github.seven332:beerbelly:0.1.4'
|
||||
compile 'com.github.seven332:conaco:0.1.5-eh'
|
||||
@@ -79,4 +80,6 @@ dependencies {
|
||||
compile 'org.greenrobot:greendao:2.2.0'
|
||||
compile 'org.jsoup:jsoup:1.9.2'
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.robolectric:robolectric:3.4'
|
||||
testCompile 'org.jooq:joor:0.9.6'
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.database;
|
||||
|
||||
/*
|
||||
* Created by Hippo on 2017/9/3.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.SparseArray;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MSQLiteBuilder {
|
||||
|
||||
public static final String COLUMN_ID = "_id";
|
||||
|
||||
private static final Map<Class, String> JAVA_TYPE_TO_SQLITE_TYPE = new HashMap<>();
|
||||
|
||||
static {
|
||||
JAVA_TYPE_TO_SQLITE_TYPE.put(boolean.class, "INTEGER NOT NULL DEFAULT 0");
|
||||
JAVA_TYPE_TO_SQLITE_TYPE.put(byte.class, "INTEGER NOT NULL DEFAULT 0");
|
||||
JAVA_TYPE_TO_SQLITE_TYPE.put(short.class, "INTEGER NOT NULL DEFAULT 0");
|
||||
JAVA_TYPE_TO_SQLITE_TYPE.put(int.class, "INTEGER NOT NULL DEFAULT 0");
|
||||
JAVA_TYPE_TO_SQLITE_TYPE.put(long.class, "INTEGER NOT NULL DEFAULT 0");
|
||||
JAVA_TYPE_TO_SQLITE_TYPE.put(float.class, "REAL NOT NULL DEFAULT 0");
|
||||
JAVA_TYPE_TO_SQLITE_TYPE.put(double.class, "REAL NOT NULL DEFAULT 0");
|
||||
JAVA_TYPE_TO_SQLITE_TYPE.put(String.class, "TEXT");
|
||||
}
|
||||
|
||||
private static String javaTypeToSQLiteType(Class clazz) {
|
||||
String type = JAVA_TYPE_TO_SQLITE_TYPE.get(clazz);
|
||||
if (type == null) {
|
||||
throw new IllegalStateException("Unknown type: " + clazz);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private int version = 0;
|
||||
private List<String> statements;
|
||||
private SparseArray<List<String>> statementsMap = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* Bump database version.
|
||||
*/
|
||||
public MSQLiteBuilder version(int version) {
|
||||
if (version <= this.version) {
|
||||
throw new IllegalStateException("New version must be bigger than current version. "
|
||||
+ "current version: " + this.version + ", new version: " + version + ".");
|
||||
}
|
||||
this.version = version;
|
||||
this.statements = new ArrayList<>();
|
||||
this.statementsMap.put(version, this.statements);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a table with int {@link #COLUMN_ID} primary key.
|
||||
*/
|
||||
public MSQLiteBuilder createTable(String table) {
|
||||
return createTable(table, COLUMN_ID, int.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a table.
|
||||
*/
|
||||
public MSQLiteBuilder createTable(String table, String column, Class clazz) {
|
||||
return statement("CREATE TABLE " + table + " (" + column + " " + javaTypeToSQLiteType(clazz) + " PRIMARY KEY);");
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops a table.
|
||||
*/
|
||||
public MSQLiteBuilder dropTable(String table) {
|
||||
return statement("DROP TABLE " + table + ";");
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a column to the table.
|
||||
*/
|
||||
public MSQLiteBuilder insertColumn(String table, String column, Class clazz) {
|
||||
return statement("ALTER TABLE " + table + " ADD COLUMN " + column + " " + javaTypeToSQLiteType(clazz) + ";");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a statement.
|
||||
*/
|
||||
public MSQLiteBuilder statement(String statement) {
|
||||
if (version == 0 || statements == null) {
|
||||
throw new IllegalStateException("Call version() first!");
|
||||
}
|
||||
statements.add(statement);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a SQLiteOpenHelper from it.
|
||||
*/
|
||||
public SQLiteOpenHelper build(Context context, String name, int version) {
|
||||
return new MSQLiteOpenHelper(context, name, version, this);
|
||||
}
|
||||
|
||||
List<String> getStatements(int oldVersion, int newVersion) {
|
||||
List<String> result = new ArrayList<>();
|
||||
for (int i = oldVersion + 1; i <= newVersion; ++i) {
|
||||
List<String> list = statementsMap.get(i);
|
||||
if (list != null) {
|
||||
result.addAll(list);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.database;
|
||||
|
||||
/*
|
||||
* Created by Hippo on 2017/9/4.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import com.hippo.util.SqlUtils;
|
||||
|
||||
class MSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
private final int version;
|
||||
private final MSQLiteBuilder builder;
|
||||
|
||||
public MSQLiteOpenHelper(Context context, String name, int version, MSQLiteBuilder builder) {
|
||||
super(context, name, null, version);
|
||||
this.version = version;
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
onUpgrade(db, 0, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
for (String command : builder.getStatements(oldVersion, newVersion)) {
|
||||
db.execSQL(command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
SqlUtils.dropAllTable(db);
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.drawable;
|
||||
|
||||
/*
|
||||
* Created by Hippo on 2017/9/6.
|
||||
*/
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.IntRange;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class TextDrawable extends Drawable {
|
||||
|
||||
private static final float STANDARD_TEXT_SIZE = 1000.0f;
|
||||
private static final Paint STANDARD_PAINT = new Paint();
|
||||
|
||||
static {
|
||||
STANDARD_PAINT.setTextSize(STANDARD_TEXT_SIZE);
|
||||
}
|
||||
|
||||
private String text;
|
||||
private float contentPercent;
|
||||
|
||||
private Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
private int textColor = Color.BLACK;
|
||||
private int backgroundColor = Color.BLACK;
|
||||
|
||||
private float x = 0.0f;
|
||||
private float y = 0.0f;
|
||||
private boolean textSizeDirty = false;
|
||||
private Rect textBounds = new Rect();
|
||||
|
||||
public TextDrawable(String text, float contentPercent) {
|
||||
this.text = text;
|
||||
this.contentPercent = contentPercent;
|
||||
STANDARD_PAINT.getTextBounds(text, 0, text.length(), textBounds);
|
||||
}
|
||||
|
||||
public int getTextColor() {
|
||||
return textColor;
|
||||
}
|
||||
|
||||
public void setTextColor(int textColor) {
|
||||
if (this.textColor != textColor) {
|
||||
this.textColor = textColor;
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
public int getBackgroundColor() {
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
public void setBackgroundColor(int backgroundColor) {
|
||||
if (this.backgroundColor != backgroundColor) {
|
||||
this.backgroundColor = backgroundColor;
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
super.onBoundsChange(bounds);
|
||||
textSizeDirty = true;
|
||||
}
|
||||
|
||||
private void updateTextSizeIfDirty(Rect bounds) {
|
||||
if (!textSizeDirty) {
|
||||
return;
|
||||
}
|
||||
textSizeDirty = false;
|
||||
|
||||
int contentWidth = (int) (bounds.width() * contentPercent);
|
||||
int contentHeight = (int) (bounds.height() * contentPercent);
|
||||
float widthRatio = (float) contentWidth / (float) textBounds.width();
|
||||
float heightRatio = (float) contentHeight / (float) textBounds.height();
|
||||
float ratio = Math.min(widthRatio, heightRatio);
|
||||
float textSize = STANDARD_TEXT_SIZE * ratio;
|
||||
textPaint.setTextSize(textSize);
|
||||
x = (bounds.width() - textBounds.width() * ratio) / 2 - textBounds.left * ratio;
|
||||
y = (bounds.height() - textBounds.height() * ratio) / 2 - textBounds.top * ratio;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
Rect bounds = getBounds();
|
||||
if (!bounds.isEmpty()) {
|
||||
// Draw background
|
||||
backgroundPaint.setColor(backgroundColor);
|
||||
canvas.drawRect(bounds, backgroundPaint);
|
||||
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
// Draw text
|
||||
updateTextSizeIfDirty(bounds);
|
||||
textPaint.setColor(textColor);
|
||||
canvas.drawText(text, x, y, textPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
backgroundPaint.setColorFilter(colorFilter);
|
||||
textPaint.setColorFilter(colorFilter);
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,6 @@ import com.hippo.conaco.Conaco;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.client.EhCookieStore;
|
||||
import com.hippo.ehviewer.client.EhEngine;
|
||||
import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.data.GalleryDetail;
|
||||
import com.hippo.ehviewer.download.DownloadManager;
|
||||
import com.hippo.ehviewer.spider.SpiderDen;
|
||||
@@ -40,7 +39,6 @@ import com.hippo.ehviewer.ui.CommonOperations;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.image.ImageBitmap;
|
||||
import com.hippo.network.StatusCodeException;
|
||||
import com.hippo.okhttp.CookieDB;
|
||||
import com.hippo.scene.SceneApplication;
|
||||
import com.hippo.text.Html;
|
||||
import com.hippo.unifile.UniFile;
|
||||
@@ -58,8 +56,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
public class EhApplication extends SceneApplication implements Thread.UncaughtExceptionHandler {
|
||||
@@ -97,7 +93,6 @@ public class EhApplication extends SceneApplication implements Thread.UncaughtEx
|
||||
super.onCreate();
|
||||
|
||||
GetText.initialize(this);
|
||||
CookieDB.initialize(this);
|
||||
StatusCodeException.initialize(this);
|
||||
Settings.initialize(this);
|
||||
ReadableTime.initialize(this);
|
||||
@@ -159,29 +154,6 @@ public class EhApplication extends SceneApplication implements Thread.UncaughtEx
|
||||
if (version < 52) {
|
||||
Settings.putGuideGallery(true);
|
||||
}
|
||||
if (version < 56) { // Make cookie long live
|
||||
HttpUrl eUrl = HttpUrl.parse(EhUrl.HOST_E);
|
||||
HttpUrl exUrl = HttpUrl.parse(EhUrl.HOST_EX);
|
||||
EhCookieStore cookieStore = getEhCookieStore(this);
|
||||
|
||||
Cookie c;
|
||||
c = cookieStore.get(eUrl, EhCookieStore.KEY_IPD_MEMBER_ID);
|
||||
if (null != c) {
|
||||
cookieStore.add(EhCookieStore.newCookie(c, c.domain(), true, true, true));
|
||||
}
|
||||
c = cookieStore.get(eUrl, EhCookieStore.KEY_IPD_PASS_HASH);
|
||||
if (null != c) {
|
||||
cookieStore.add(EhCookieStore.newCookie(c, c.domain(), true, true, true));
|
||||
}
|
||||
c = cookieStore.get(exUrl, EhCookieStore.KEY_IPD_MEMBER_ID);
|
||||
if (null != c) {
|
||||
cookieStore.add(EhCookieStore.newCookie(c, c.domain(), true, true, true));
|
||||
}
|
||||
c = cookieStore.get(exUrl, EhCookieStore.KEY_IPD_PASS_HASH);
|
||||
if (null != c) {
|
||||
cookieStore.add(EhCookieStore.newCookie(c, c.domain(), true, true, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearMemoryCache() {
|
||||
@@ -243,7 +215,7 @@ public class EhApplication extends SceneApplication implements Thread.UncaughtEx
|
||||
public static EhCookieStore getEhCookieStore(@NonNull Context context) {
|
||||
EhApplication application = ((EhApplication) context.getApplicationContext());
|
||||
if (application.mEhCookieStore == null) {
|
||||
application.mEhCookieStore = new EhCookieStore();
|
||||
application.mEhCookieStore = new EhCookieStore(context);
|
||||
}
|
||||
return application.mEhCookieStore;
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public class EhClient {
|
||||
try {
|
||||
switch (mMethod) {
|
||||
case METHOD_SIGN_IN:
|
||||
return EhEngine.signIn(this, mOkHttpClient, (String) params[0], (String) params[1]);
|
||||
return EhEngine.signIn(this, mOkHttpClient, (String) params[0], (String) params[1], (String) params[2], (String) params[3]);
|
||||
case METHOD_GET_GALLERY_LIST:
|
||||
return EhEngine.getGalleryList(this, mOkHttpClient, (String) params[0]);
|
||||
case METHOD_FILL_GALLERY_LIST_BY_API:
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import com.hippo.okhttp.CookieDBStore;
|
||||
import android.content.Context;
|
||||
|
||||
import com.hippo.network.CookieRepository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -26,7 +28,7 @@ import okhttp3.Cookie;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class EhCookieStore extends CookieDBStore {
|
||||
public class EhCookieStore extends CookieRepository {
|
||||
|
||||
public static final String KEY_IPD_MEMBER_ID = "ipb_member_id";
|
||||
public static final String KEY_IPD_PASS_HASH = "ipb_pass_hash";
|
||||
@@ -41,13 +43,18 @@ public class EhCookieStore extends CookieDBStore {
|
||||
.expiresAt(Long.MAX_VALUE)
|
||||
.build();
|
||||
|
||||
public EhCookieStore(Context context) {
|
||||
super(context, "okhttp3-cookie.db");
|
||||
}
|
||||
|
||||
public void signOut() {
|
||||
removeAll();
|
||||
clear();
|
||||
}
|
||||
|
||||
public boolean hasSignedIn() {
|
||||
return contain(EhUrl.DOMAIN_EX, KEY_IPD_MEMBER_ID) &&
|
||||
contain(EhUrl.DOMAIN_EX, KEY_IPD_PASS_HASH);
|
||||
HttpUrl url = HttpUrl.parse(EhUrl.HOST_E);
|
||||
return contains(url, KEY_IPD_MEMBER_ID) &&
|
||||
contains(url, KEY_IPD_PASS_HASH);
|
||||
}
|
||||
|
||||
public static Cookie newCookie(Cookie cookie, String newDomain, boolean forcePersistent,
|
||||
@@ -82,10 +89,9 @@ public class EhCookieStore extends CookieDBStore {
|
||||
public List<Cookie> loadForRequest(HttpUrl url, Request request) {
|
||||
List<Cookie> cookies = super.loadForRequest(url, request);
|
||||
Object tag = request.tag();
|
||||
String host = url.host();
|
||||
|
||||
boolean checkTips = domainMatch(host, EhUrl.DOMAIN_E);
|
||||
boolean checkUconfig = (domainMatch(host, EhUrl.DOMAIN_E) || domainMatch(host, EhUrl.DOMAIN_EX)) && tag instanceof EhConfig;
|
||||
boolean checkTips = domainMatch(url, EhUrl.DOMAIN_E);
|
||||
boolean checkUconfig = (domainMatch(url, EhUrl.DOMAIN_E) || domainMatch(url, EhUrl.DOMAIN_EX)) && tag instanceof EhConfig;
|
||||
|
||||
if (checkTips || checkUconfig) {
|
||||
List<Cookie> result = new ArrayList<>(cookies.size() + 1);
|
||||
@@ -109,7 +115,7 @@ public class EhCookieStore extends CookieDBStore {
|
||||
Cookie uconfigCookie = new Cookie.Builder()
|
||||
.name(EhConfig.KEY_UCONFIG)
|
||||
.value(ehConfig.uconfig())
|
||||
.domain(host)
|
||||
.domain(url.host())
|
||||
.path("/")
|
||||
.expiresAt(Long.MAX_VALUE)
|
||||
.build();
|
||||
@@ -120,26 +126,4 @@ public class EhCookieStore extends CookieDBStore {
|
||||
return cookies;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
List<Cookie> result = new ArrayList<>(cookies.size() + 2);
|
||||
|
||||
for (Cookie cookie: cookies) {
|
||||
if (EhUrl.DOMAIN_E.equals(cookie.domain())) {
|
||||
// Save id and hash for exhentai
|
||||
if (KEY_IPD_MEMBER_ID.equals(cookie.name()) ||
|
||||
KEY_IPD_PASS_HASH.equals(cookie.name()) ||
|
||||
KEY_IGNEOUS.equals(cookie.name())) {
|
||||
result.add(newCookie(cookie, EhUrl.DOMAIN_E, true, true, true));
|
||||
result.add(newCookie(cookie, EhUrl.DOMAIN_EX, true, true, true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.add(cookie);
|
||||
}
|
||||
|
||||
super.saveFromResponse(url, Collections.unmodifiableList(result));
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
@@ -120,13 +121,17 @@ public class EhEngine {
|
||||
}
|
||||
|
||||
public static String signIn(@Nullable EhClient.Task task, OkHttpClient okHttpClient,
|
||||
String username, String password) throws Exception {
|
||||
String username, String password, String recaptchaChallenge, String recaptchaResponse) throws Exception {
|
||||
FormBody.Builder builder = new FormBody.Builder()
|
||||
.add("UserName", username)
|
||||
.add("PassWord", password)
|
||||
.add("submit", "Log me in")
|
||||
.add("CookieDate", "1")
|
||||
.add("temporary_https", "off");
|
||||
if (!TextUtils.isEmpty(recaptchaChallenge) && !TextUtils.isEmpty(recaptchaResponse)) {
|
||||
builder.add("recaptcha_challenge_field", recaptchaChallenge);
|
||||
builder.add("recaptcha_response_field", recaptchaResponse);
|
||||
}
|
||||
String url = EhUrl.API_SIGN_IN;
|
||||
Log.d(TAG, url);
|
||||
Request request = new EhRequestBuilder(url, null != task ? task.getEhConfig() : Settings.getEhConfig())
|
||||
|
||||
@@ -30,16 +30,13 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhCookieStore;
|
||||
import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.yorozuya.ViewUtils;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
|
||||
public class CookieSignInScene extends SolidScene implements EditText.OnEditorActionListener,
|
||||
@@ -241,11 +238,11 @@ public class CookieSignInScene extends SolidScene implements EditText.OnEditorAc
|
||||
EhUtils.signOut(context);
|
||||
|
||||
EhCookieStore store = EhApplication.getEhCookieStore(context);
|
||||
store.add(newCookie(EhCookieStore.KEY_IPD_MEMBER_ID, id, EhUrl.DOMAIN_E));
|
||||
store.add(newCookie(EhCookieStore.KEY_IPD_MEMBER_ID, id, EhUrl.DOMAIN_EX));
|
||||
store.add(newCookie(EhCookieStore.KEY_IPD_PASS_HASH, hash, EhUrl.DOMAIN_E));
|
||||
store.add(newCookie(EhCookieStore.KEY_IPD_PASS_HASH, hash, EhUrl.DOMAIN_EX));
|
||||
store.add(newCookie(EhCookieStore.KEY_IGNEOUS, igneous, EhUrl.DOMAIN_E));
|
||||
store.add(newCookie(EhCookieStore.KEY_IGNEOUS, igneous, EhUrl.DOMAIN_EX));
|
||||
store.addCookie(newCookie(EhCookieStore.KEY_IPD_MEMBER_ID, id, EhUrl.DOMAIN_E));
|
||||
store.addCookie(newCookie(EhCookieStore.KEY_IPD_MEMBER_ID, id, EhUrl.DOMAIN_EX));
|
||||
store.addCookie(newCookie(EhCookieStore.KEY_IPD_PASS_HASH, hash, EhUrl.DOMAIN_E));
|
||||
store.addCookie(newCookie(EhCookieStore.KEY_IPD_PASS_HASH, hash, EhUrl.DOMAIN_EX));
|
||||
store.addCookie(newCookie(EhCookieStore.KEY_IGNEOUS, igneous, EhUrl.DOMAIN_E));
|
||||
store.addCookie(newCookie(EhCookieStore.KEY_IGNEOUS, igneous, EhUrl.DOMAIN_EX));
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
import com.hippo.ehviewer.client.parser.ProfileParser;
|
||||
import com.hippo.ehviewer.ui.MainActivity;
|
||||
import com.hippo.ehviewer.widget.RecaptchaView;
|
||||
import com.hippo.scene.Announcer;
|
||||
import com.hippo.scene.SceneFragment;
|
||||
import com.hippo.yorozuya.IntIdGenerator;
|
||||
@@ -68,6 +69,8 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
|
||||
private EditText mUsername;
|
||||
@Nullable
|
||||
private EditText mPassword;
|
||||
private EditText mRecaptcha;
|
||||
private RecaptchaView mRecaptchaView;
|
||||
@Nullable
|
||||
private View mRegister;
|
||||
@Nullable
|
||||
@@ -125,6 +128,8 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
|
||||
mPasswordLayout = (TextInputLayout) ViewUtils.$$(loginForm, R.id.password_layout);
|
||||
mPassword = mPasswordLayout.getEditText();
|
||||
Assert.assertNotNull(mPassword);
|
||||
mRecaptcha = (EditText) ViewUtils.$$(loginForm, R.id.recaptcha);
|
||||
mRecaptchaView = (RecaptchaView) ViewUtils.$$(loginForm, R.id.recaptcha_image);
|
||||
mRegister = ViewUtils.$$(loginForm, R.id.register);
|
||||
mSignIn = ViewUtils.$$(loginForm, R.id.sign_in);
|
||||
mSignInViaWebView = (TextView) ViewUtils.$$(loginForm, R.id.sign_in_via_webview);
|
||||
@@ -280,12 +285,15 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
|
||||
// Clean up for sign in
|
||||
EhUtils.signOut(context);
|
||||
|
||||
String challenge = mRecaptchaView.getChallenge();
|
||||
String response = mRecaptcha.getText().toString();
|
||||
|
||||
EhCallback callback = new SignInListener(context,
|
||||
activity.getStageId(), getTag());
|
||||
mRequestId = ((EhApplication) context.getApplicationContext()).putGlobalStuff(callback);
|
||||
EhRequest request = new EhRequest()
|
||||
.setMethod(EhClient.METHOD_SIGN_IN)
|
||||
.setArgs(username, password)
|
||||
.setArgs(username, password, challenge, response)
|
||||
.setCallback(callback);
|
||||
EhApplication.getEhClient(context).execute(request);
|
||||
|
||||
|
||||
@@ -28,18 +28,14 @@ import android.webkit.CookieManager;
|
||||
import android.webkit.CookieSyncManager;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import com.hippo.ehviewer.EhApplication;
|
||||
import com.hippo.ehviewer.client.EhCookieStore;
|
||||
import com.hippo.ehviewer.client.EhUrl;
|
||||
import com.hippo.ehviewer.client.EhUtils;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
@@ -122,7 +118,7 @@ public class WebViewSignInScene extends SolidScene {
|
||||
}
|
||||
|
||||
private void addCookie(Context context, String domain, Cookie cookie) {
|
||||
EhApplication.getEhCookieStore(context).add(EhCookieStore.newCookie(cookie, domain, true, true, true));
|
||||
EhApplication.getEhCookieStore(context).addCookie(EhCookieStore.newCookie(cookie, domain, true, true, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,6 +145,9 @@ public class WebViewSignInScene extends SolidScene {
|
||||
getHash = true;
|
||||
addCookie(context, EhUrl.DOMAIN_EX, cookie);
|
||||
addCookie(context, EhUrl.DOMAIN_E, cookie);
|
||||
} else if (EhCookieStore.KEY_IGNEOUS.equals(cookie.name())) {
|
||||
addCookie(context, EhUrl.DOMAIN_EX, cookie);
|
||||
addCookie(context, EhUrl.DOMAIN_E, cookie);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
/*
|
||||
* Created by Hippo on 2017/8/20.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import com.hippo.android.recaptcha.RecaptchaV1;
|
||||
import com.hippo.drawable.TextDrawable;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.widget.LoadImageView;
|
||||
import com.hippo.yorozuya.SimpleHandler;
|
||||
|
||||
public class RecaptchaView extends LoadImageView implements RecaptchaV1.RecaptchaCallback, View.OnClickListener {
|
||||
|
||||
private static final String CHALLENGE = "6LdtfgYAAAAAALjIPPiCgPJJah8MhAUpnHcKF8u_";
|
||||
|
||||
private boolean loading = false;
|
||||
private String challenge;
|
||||
private String image;
|
||||
|
||||
private TextDrawable waitingDrawable;
|
||||
private TextDrawable loadingDrawable;
|
||||
private TextDrawable failureDrawable;
|
||||
|
||||
public RecaptchaView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public RecaptchaView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setOnClickListener(this);
|
||||
if (waitingDrawable == null) {
|
||||
waitingDrawable = new TextDrawable(getContext().getString(R.string.recaptcha_none), 0.6f);
|
||||
waitingDrawable.setBackgroundColor(Color.GRAY);
|
||||
waitingDrawable.setTextColor(Color.WHITE);
|
||||
}
|
||||
load(waitingDrawable);
|
||||
}
|
||||
|
||||
public String getChallenge() {
|
||||
return challenge;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
loading = false;
|
||||
challenge = null;
|
||||
image = null;
|
||||
|
||||
if (loadingDrawable == null) {
|
||||
loadingDrawable = new TextDrawable(getContext().getString(R.string.recaptcha_loading), 0.6f);
|
||||
loadingDrawable.setBackgroundColor(Color.GRAY);
|
||||
loadingDrawable.setTextColor(Color.WHITE);
|
||||
}
|
||||
load(loadingDrawable);
|
||||
|
||||
RecaptchaV1.recaptcha(getContext(), CHALLENGE, SimpleHandler.getInstance(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(@NonNull View v) {
|
||||
load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(@NonNull String challenge, @NonNull String image) {
|
||||
this.loading = false;
|
||||
this.challenge = challenge;
|
||||
this.image = image;
|
||||
|
||||
load(image, image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure() {
|
||||
this.loading = false;
|
||||
this.challenge = null;
|
||||
this.image = null;
|
||||
|
||||
if (failureDrawable == null) {
|
||||
failureDrawable = new TextDrawable(getContext().getString(R.string.recaptcha_failure), 0.6f);
|
||||
failureDrawable.setBackgroundColor(Color.GRAY);
|
||||
failureDrawable.setTextColor(Color.WHITE);
|
||||
}
|
||||
load(failureDrawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
SavedState ss = new SavedState(super.onSaveInstanceState());
|
||||
ss.loading = loading;
|
||||
ss.challenge = challenge;
|
||||
ss.image = image;
|
||||
return ss;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
if (!(state instanceof SavedState)) {
|
||||
super.onRestoreInstanceState(state);
|
||||
return;
|
||||
}
|
||||
|
||||
SavedState ss = (SavedState) state;
|
||||
super.onRestoreInstanceState(ss.getSuperState());
|
||||
|
||||
if (ss.loading) {
|
||||
load();
|
||||
} else if (!TextUtils.isEmpty(ss.challenge) && !TextUtils.isEmpty(ss.image)) {
|
||||
onSuccess(ss.challenge, ss.image);
|
||||
}
|
||||
}
|
||||
|
||||
private static class SavedState extends BaseSavedState {
|
||||
|
||||
private boolean loading;
|
||||
private String challenge;
|
||||
private String image;
|
||||
|
||||
public SavedState(Parcelable superState) {
|
||||
super(superState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeByte(loading ? (byte) 1 : (byte) 0);
|
||||
out.writeString(challenge);
|
||||
out.writeString(image);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<SavedState> CREATOR
|
||||
= new Parcelable.Creator<SavedState>() {
|
||||
@Override
|
||||
public SavedState createFromParcel(Parcel in) {
|
||||
return new SavedState(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavedState[] newArray(int size) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
|
||||
public SavedState(Parcel source) {
|
||||
super(source);
|
||||
loading = source.readByte() != 0;
|
||||
challenge = source.readString();
|
||||
image = source.readString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.network;
|
||||
|
||||
/*
|
||||
* Created by Hippo on 2017/9/4.
|
||||
*/
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import com.hippo.database.MSQLiteBuilder;
|
||||
import com.hippo.util.SqlUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import okhttp3.Cookie;
|
||||
|
||||
class CookieDatabase {
|
||||
|
||||
private static final String LOG_TAG = CookieDatabase.class.getSimpleName();
|
||||
|
||||
private static final int VERSION_1 = 1;
|
||||
private static final String TABLE_COOKIE = "OK_HTTP_3_COOKIE";
|
||||
private static final String COLUMN_ID = "_id";
|
||||
private static final String COLUMN_NAME = "NAME";
|
||||
private static final String COLUMN_VALUE = "VALUE";
|
||||
private static final String COLUMN_EXPIRES_AT = "EXPIRES_AT";
|
||||
private static final String COLUMN_DOMAIN = "DOMAIN";
|
||||
private static final String COLUMN_PATH = "PATH";
|
||||
private static final String COLUMN_SECURE = "SECURE";
|
||||
private static final String COLUMN_HTTP_ONLY = "HTTP_ONLY";
|
||||
private static final String COLUMN_PERSISTENT = "PERSISTENT";
|
||||
private static final String COLUMN_HOST_ONLY = "HOST_ONLY";
|
||||
|
||||
private static final int DB_VERSION = VERSION_1;
|
||||
|
||||
private final Map<Cookie, Long> cookieIdMap = new HashMap<>();
|
||||
private final SQLiteOpenHelper helper;
|
||||
private final SQLiteDatabase db;
|
||||
|
||||
public CookieDatabase(Context context, String name) {
|
||||
helper = new MSQLiteBuilder()
|
||||
.version(VERSION_1)
|
||||
.createTable(TABLE_COOKIE)
|
||||
.insertColumn(TABLE_COOKIE, COLUMN_NAME, String.class)
|
||||
.insertColumn(TABLE_COOKIE, COLUMN_VALUE, String.class)
|
||||
.insertColumn(TABLE_COOKIE, COLUMN_EXPIRES_AT, long.class)
|
||||
.insertColumn(TABLE_COOKIE, COLUMN_DOMAIN, String.class)
|
||||
.insertColumn(TABLE_COOKIE, COLUMN_PATH, String.class)
|
||||
.insertColumn(TABLE_COOKIE, COLUMN_SECURE, boolean.class)
|
||||
.insertColumn(TABLE_COOKIE, COLUMN_HTTP_ONLY, boolean.class)
|
||||
.insertColumn(TABLE_COOKIE, COLUMN_PERSISTENT, boolean.class)
|
||||
.insertColumn(TABLE_COOKIE, COLUMN_HOST_ONLY, boolean.class)
|
||||
.build(context, name, DB_VERSION);
|
||||
db = helper.getWritableDatabase();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Cookie getCookie(Cursor cursor, long now) {
|
||||
String name = SqlUtils.getString(cursor, COLUMN_NAME, null);
|
||||
String value = SqlUtils.getString(cursor, COLUMN_VALUE, null);
|
||||
long expiresAt = SqlUtils.getLong(cursor, COLUMN_EXPIRES_AT, 0);
|
||||
String domain = SqlUtils.getString(cursor, COLUMN_DOMAIN, null);
|
||||
String path = SqlUtils.getString(cursor, COLUMN_PATH, null);
|
||||
boolean secure = SqlUtils.getBoolean(cursor, COLUMN_SECURE, false);
|
||||
boolean httpOnly = SqlUtils.getBoolean(cursor, COLUMN_HTTP_ONLY, false);
|
||||
boolean persistent = SqlUtils.getBoolean(cursor, COLUMN_PERSISTENT, false);
|
||||
boolean hostOnly = SqlUtils.getBoolean(cursor, COLUMN_HOST_ONLY, false);
|
||||
|
||||
if (name == null || domain == null || path == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check non-persistent or expired
|
||||
if (!persistent || expiresAt <= now) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Cookie.Builder builder = new Cookie.Builder();
|
||||
builder.name(name);
|
||||
builder.value(value);
|
||||
if (hostOnly) {
|
||||
builder.hostOnlyDomain(domain);
|
||||
} else {
|
||||
builder.domain(domain);
|
||||
}
|
||||
builder.path(path);
|
||||
builder.expiresAt(expiresAt);
|
||||
if (secure) builder.secure();
|
||||
if (httpOnly) builder.httpOnly();
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public Map<String, CookieSet> getAllCookies() {
|
||||
long now = System.currentTimeMillis();
|
||||
Map<String, CookieSet> map = new HashMap<>();
|
||||
List<Long> toRemove = new ArrayList<>();
|
||||
|
||||
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_COOKIE + ";", null);
|
||||
try {
|
||||
while (cursor.moveToNext()) {
|
||||
long id = SqlUtils.getLong(cursor, COLUMN_ID, 0);
|
||||
Cookie cookie = getCookie(cursor, now);
|
||||
|
||||
if (cookie != null) {
|
||||
// Save id of the cookie in db
|
||||
cookieIdMap.put(cookie, id);
|
||||
|
||||
// Put cookie to set
|
||||
CookieSet set = map.get(cookie.domain());
|
||||
if (set == null) {
|
||||
set = new CookieSet();
|
||||
map.put(cookie.domain(), set);
|
||||
}
|
||||
set.add(cookie);
|
||||
} else {
|
||||
// Mark to remove the cookie
|
||||
toRemove.add(id);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
// Remove invalid or expired cookie
|
||||
if (!toRemove.isEmpty()) {
|
||||
SQLiteStatement statement = db.compileStatement(
|
||||
"DELETE FROM " + TABLE_COOKIE + " WHERE " + COLUMN_ID + " = ?;");
|
||||
db.beginTransaction();
|
||||
try {
|
||||
for (long id : toRemove) {
|
||||
statement.bindLong(1, id);
|
||||
statement.executeUpdateDelete();
|
||||
}
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public ContentValues toContentValues(Cookie cookie) {
|
||||
ContentValues contentValues = new ContentValues(9);
|
||||
contentValues.put(COLUMN_NAME, cookie.name());
|
||||
contentValues.put(COLUMN_VALUE, cookie.value());
|
||||
contentValues.put(COLUMN_EXPIRES_AT, cookie.expiresAt());
|
||||
contentValues.put(COLUMN_DOMAIN, cookie.domain());
|
||||
contentValues.put(COLUMN_PATH, cookie.path());
|
||||
contentValues.put(COLUMN_SECURE, cookie.secure());
|
||||
contentValues.put(COLUMN_HTTP_ONLY, cookie.httpOnly());
|
||||
contentValues.put(COLUMN_PERSISTENT, cookie.persistent());
|
||||
contentValues.put(COLUMN_HOST_ONLY, cookie.hostOnly());
|
||||
return contentValues;
|
||||
}
|
||||
|
||||
public void add(Cookie cookie) {
|
||||
long id = db.insert(TABLE_COOKIE, null, toContentValues(cookie));
|
||||
if (id != -1L) {
|
||||
Long oldId = cookieIdMap.put(cookie, id);
|
||||
if (oldId != null) Log.e(LOG_TAG, "Add a duplicate cookie");
|
||||
} else {
|
||||
Log.e(LOG_TAG, "An error occurred when insert a cookie");
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Cookie from, Cookie to) {
|
||||
Long id = cookieIdMap.get(from);
|
||||
if (id == null) {
|
||||
Log.e(LOG_TAG, "Can't get id when update the cookie");
|
||||
return;
|
||||
}
|
||||
|
||||
ContentValues values = toContentValues(to);
|
||||
String whereClause = COLUMN_ID + " = ?";
|
||||
String[] whereArgs = { id.toString() };
|
||||
int count = db.update(TABLE_COOKIE, values, whereClause, whereArgs);
|
||||
if (count != 1) {
|
||||
Log.e(LOG_TAG, "Bad result when update cookie: " + count);
|
||||
}
|
||||
|
||||
// Update it in cookie-id map
|
||||
cookieIdMap.remove(from);
|
||||
cookieIdMap.put(to, id);
|
||||
}
|
||||
|
||||
public void remove(Cookie cookie) {
|
||||
Long id = cookieIdMap.get(cookie);
|
||||
if (id == null) {
|
||||
Log.e(LOG_TAG, "Can't get id when remove the cookie");
|
||||
return;
|
||||
}
|
||||
|
||||
String whereClause = COLUMN_ID + " = ?";
|
||||
String[] whereArgs = { id.toString() };
|
||||
int count = db.delete(TABLE_COOKIE, whereClause, whereArgs);
|
||||
if (count != 1) {
|
||||
Log.e(LOG_TAG, "Bad result when remove cookie: " + count);
|
||||
}
|
||||
|
||||
// Remove it from cookie-id map
|
||||
cookieIdMap.remove(cookie);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
db.delete(TABLE_COOKIE, null, null);
|
||||
cookieIdMap.clear();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
db.close();
|
||||
helper.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.network;
|
||||
|
||||
/*
|
||||
* Created by Hippo on 2017/9/4.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import com.hippo.yorozuya.ObjectUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class CookieRepository implements CookieJar {
|
||||
|
||||
private CookieDatabase db;
|
||||
private Map<String, CookieSet> map;
|
||||
|
||||
public CookieRepository(Context context, String name) {
|
||||
db = new CookieDatabase(context, name);
|
||||
map = db.getAllCookies();
|
||||
}
|
||||
|
||||
public synchronized void addCookie(Cookie cookie) {
|
||||
// For cookie database
|
||||
Cookie toAdd = null;
|
||||
Cookie toUpdate = null;
|
||||
Cookie toRemove = null;
|
||||
|
||||
CookieSet set = map.get(cookie.domain());
|
||||
if (set == null) {
|
||||
set = new CookieSet();
|
||||
map.put(cookie.domain(), set);
|
||||
}
|
||||
|
||||
if (cookie.expiresAt() <= System.currentTimeMillis()) {
|
||||
toRemove = set.remove(cookie);
|
||||
// If the cookie is not persistent, it's not in database
|
||||
if (toRemove != null && !toRemove.persistent()) {
|
||||
toRemove = null;
|
||||
}
|
||||
} else {
|
||||
toAdd = cookie;
|
||||
toUpdate = set.add(cookie);
|
||||
// If the cookie is not persistent, it's not in database
|
||||
if (!toAdd.persistent()) toAdd = null;
|
||||
if (toUpdate != null && !toUpdate.persistent()) toUpdate = null;
|
||||
// Remove the cookie if it updates to null
|
||||
if (toAdd == null && toUpdate != null) {
|
||||
toRemove = toUpdate;
|
||||
toUpdate = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (toRemove != null) {
|
||||
db.remove(toRemove);
|
||||
}
|
||||
if (toAdd != null) {
|
||||
if (toUpdate != null) {
|
||||
db.update(toUpdate, toAdd);
|
||||
} else {
|
||||
db.add(toAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized List<Cookie> getCookies(HttpUrl url) {
|
||||
List<Cookie> accepted = new ArrayList<>();
|
||||
List<Cookie> expired = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<String, CookieSet> entry : map.entrySet()) {
|
||||
String domain = entry.getKey();
|
||||
CookieSet cookieSet = entry.getValue();
|
||||
if (domainMatch(url, domain)) {
|
||||
cookieSet.get(url, accepted, expired);
|
||||
}
|
||||
}
|
||||
|
||||
for (Cookie cookie : expired) {
|
||||
if (cookie.persistent()) {
|
||||
db.remove(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
// RFC 6265 Section-5.4 step 2, sort the cookie-list
|
||||
// Cookies with longer paths are listed before cookies with shorter paths.
|
||||
// Ignore creation-time, we don't store them.
|
||||
Collections.sort(accepted, new Comparator<Cookie>() {
|
||||
@Override
|
||||
public int compare(Cookie o1, Cookie o2) {
|
||||
return o2.path().length() - o1.path().length();
|
||||
}
|
||||
});
|
||||
|
||||
return accepted;
|
||||
}
|
||||
|
||||
public boolean contains(HttpUrl url, String name) {
|
||||
for (Cookie cookie : getCookies(url)) {
|
||||
if (ObjectUtils.equal(cookie.name(), name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all cookies in this {@code CookieRepository}.
|
||||
*/
|
||||
public synchronized void clear() {
|
||||
map.clear();
|
||||
db.clear();
|
||||
}
|
||||
|
||||
public synchronized void close() {
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
|
||||
for (Cookie cookie : list) {
|
||||
addCookie(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cookie> loadForRequest(HttpUrl httpUrl, Request request) {
|
||||
return getCookies(httpUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick and dirty pattern to differentiate IP addresses from hostnames. This is an approximation
|
||||
* of Android's private InetAddress#isNumeric API.
|
||||
*
|
||||
* This matches IPv6 addresses as a hex string containing at least one colon, and possibly
|
||||
* including dots after the first colon. It matches IPv4 addresses as strings containing only
|
||||
* decimal digits and dots. This pattern matches strings like "a:.23" and "54" that are neither IP
|
||||
* addresses nor hostnames; they will be verified as IP addresses (which is a more strict
|
||||
* verification).
|
||||
*/
|
||||
private static final Pattern VERIFY_AS_IP_ADDRESS = Pattern.compile("([0-9a-fA-F]*:[0-9a-fA-F:.]*)|([\\d.]+)");
|
||||
|
||||
/**
|
||||
* Returns true if `host` is not a host name and might be an IP address.
|
||||
*/
|
||||
private static boolean verifyAsIpAddress(String host) {
|
||||
return VERIFY_AS_IP_ADDRESS.matcher(host).matches();
|
||||
}
|
||||
|
||||
// okhttp3.Cookie.domainMatch(HttpUrl, String)
|
||||
protected static boolean domainMatch(HttpUrl url, String domain) {
|
||||
String urlHost = url.host();
|
||||
|
||||
if (urlHost.equals(domain)) {
|
||||
return true; // As in 'example.com' matching 'example.com'.
|
||||
}
|
||||
|
||||
if (urlHost.endsWith(domain)
|
||||
&& urlHost.charAt(urlHost.length() - domain.length() - 1) == '.'
|
||||
&& !verifyAsIpAddress(urlHost)) {
|
||||
return true; // As in 'example.com' matching 'www.example.com'.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.network;
|
||||
|
||||
/*
|
||||
* Created by Hippo on 2017/9/4.
|
||||
*/
|
||||
|
||||
import com.hippo.util.HashCodeUtils;
|
||||
import com.hippo.yorozuya.ObjectUtils;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
class CookieSet {
|
||||
|
||||
private Map<Key, Cookie> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Adds a cookie to this {@code CookieSet}.
|
||||
* Returns a previous cookie with
|
||||
* the same name, domain and path or {@code null}.
|
||||
*/
|
||||
public Cookie add(Cookie cookie) {
|
||||
return map.put(new Key(cookie), cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a cookie with the same name,
|
||||
* domain and path as the cookie.
|
||||
* Returns the removed cookie or {@code null}.
|
||||
*/
|
||||
public Cookie remove(Cookie cookie) {
|
||||
return map.remove(new Key(cookie));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cookies for the url. Fill {@code accepted} and {@code expired}.
|
||||
*/
|
||||
public void get(HttpUrl url, List<Cookie> accepted, List<Cookie> expired) {
|
||||
long now = System.currentTimeMillis();
|
||||
Iterator<Map.Entry<Key, Cookie>> iterator = map.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Cookie cookie = iterator.next().getValue();
|
||||
if (cookie.expiresAt() <= now) {
|
||||
iterator.remove();
|
||||
expired.add(cookie);
|
||||
} else if (cookie.matches(url)) {
|
||||
accepted.add(cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Key {
|
||||
|
||||
private String name;
|
||||
private String domain;
|
||||
private String path;
|
||||
|
||||
public Key(Cookie cookie) {
|
||||
this.name = cookie.name();
|
||||
this.domain = cookie.domain();
|
||||
this.path = cookie.path();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj instanceof Key) {
|
||||
Key key = (Key) obj;
|
||||
return ObjectUtils.equal(key.name, this.name) &&
|
||||
ObjectUtils.equal(key.domain, this.domain) &&
|
||||
ObjectUtils.equal(key.path, this.path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeUtils.hashCode(name, domain, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.okhttp;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import com.hippo.okhttp.dao.DaoMaster;
|
||||
import com.hippo.okhttp.dao.DaoSession;
|
||||
import com.hippo.okhttp.dao.OkHttp3CookieDao;
|
||||
import com.hippo.okhttp.dao.OkHttp3CookieRaw;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
|
||||
public class CookieDB {
|
||||
|
||||
private static DaoSession sDaoSession;
|
||||
|
||||
private static class DBOpenHelper extends DaoMaster.OpenHelper {
|
||||
|
||||
public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
|
||||
super(context, name, factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void initialize(Context context) {
|
||||
DBOpenHelper helper = new DBOpenHelper(
|
||||
context.getApplicationContext(), "okhttp3-cookie.db", null);
|
||||
|
||||
SQLiteDatabase db = helper.getWritableDatabase();
|
||||
DaoMaster daoMaster = new DaoMaster(db);
|
||||
|
||||
sDaoSession = daoMaster.newSession();
|
||||
}
|
||||
|
||||
static Map<String, List<CookieWithID>> getAllCookies() {
|
||||
OkHttp3CookieDao dao = sDaoSession.getOkHttp3CookieDao();
|
||||
List<OkHttp3CookieRaw> list = dao.queryBuilder().list();
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
Map<String, List<CookieWithID>> result = new HashMap<>();
|
||||
for (OkHttp3CookieRaw raw : list) {
|
||||
// Check expired
|
||||
if (!raw.getPersistent() || raw.getExpiresAt() <= now) {
|
||||
dao.delete(raw);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Avoid null error
|
||||
String name = raw.getName();
|
||||
String value = raw.getValue();
|
||||
String domain = raw.getDomain();
|
||||
if (name == null || value == null || domain == null) {
|
||||
dao.delete(raw);
|
||||
continue;
|
||||
}
|
||||
|
||||
Cookie.Builder builder = new Cookie.Builder();
|
||||
builder.name(name);
|
||||
builder.value(value);
|
||||
builder.expiresAt(raw.getExpiresAt());
|
||||
if (raw.getHostOnly()) {
|
||||
builder.hostOnlyDomain(domain);
|
||||
} else {
|
||||
builder.domain(raw.getDomain());
|
||||
}
|
||||
builder.path(raw.getPath());
|
||||
if (raw.getSecure()) {
|
||||
builder.secure();
|
||||
}
|
||||
if (raw.getHttpOnly()) {
|
||||
builder.httpOnly();
|
||||
}
|
||||
|
||||
List<CookieWithID> cookies = result.get(domain);
|
||||
if (cookies == null) {
|
||||
cookies = new ArrayList<>();
|
||||
result.put(domain, cookies);
|
||||
}
|
||||
|
||||
cookies.add(new CookieWithID(raw.getId(), builder.build()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void removeCookie(long id) {
|
||||
sDaoSession.getOkHttp3CookieDao().deleteByKey(id);
|
||||
}
|
||||
|
||||
static void removeAllCookies() {
|
||||
sDaoSession.getOkHttp3CookieDao().deleteAll();
|
||||
}
|
||||
|
||||
static long addCookie(Cookie cookie) {
|
||||
OkHttp3CookieDao dao = sDaoSession.getOkHttp3CookieDao();
|
||||
|
||||
OkHttp3CookieRaw raw = new OkHttp3CookieRaw();
|
||||
raw.setName(cookie.name());
|
||||
raw.setValue(cookie.value());
|
||||
raw.setExpiresAt(cookie.expiresAt());
|
||||
raw.setDomain(cookie.domain());
|
||||
raw.setPath(cookie.path());
|
||||
raw.setSecure(cookie.secure());
|
||||
raw.setHttpOnly(cookie.httpOnly());
|
||||
raw.setPersistent(cookie.persistent());
|
||||
raw.setHostOnly(cookie.hostOnly());
|
||||
|
||||
return dao.insert(raw);
|
||||
}
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.okhttp;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class CookieDBStore implements CookieJar {
|
||||
|
||||
private final Map<String, List<CookieWithID>> map;
|
||||
|
||||
public CookieDBStore() {
|
||||
map = CookieDB.getAllCookies();
|
||||
}
|
||||
|
||||
private static boolean hasExpired(Cookie cookie) {
|
||||
return cookie.expiresAt() < System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private static boolean domainMatch(Cookie cookie, String urlHost) {
|
||||
return cookie.hostOnly()
|
||||
? urlHost.equals(cookie.domain())
|
||||
: domainMatch(urlHost, cookie.domain());
|
||||
}
|
||||
|
||||
public static boolean domainMatch(String urlHost, String cookieDomain) {
|
||||
if (urlHost.equals(cookieDomain)) {
|
||||
return true; // As in 'example.com' matching 'example.com'.
|
||||
}
|
||||
|
||||
return urlHost.endsWith(cookieDomain)
|
||||
&& urlHost.charAt(urlHost.length() - cookieDomain.length() - 1) == '.';
|
||||
}
|
||||
|
||||
private static CookieWithID removeCookie(List<CookieWithID> list, String name) {
|
||||
for (int i = 0, n = list.size(); i < n; i++) {
|
||||
CookieWithID cwi = list.get(i);
|
||||
if (cwi.cookie.name().equals(name)) {
|
||||
list.remove(i);
|
||||
return cwi;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean containInternal(String host, String name, List<CookieWithID> cookies) {
|
||||
for (int i = 0, n = cookies.size(); i < n; i++) {
|
||||
Cookie cookie = cookies.get(i).cookie;
|
||||
if (domainMatch(cookie, host) && cookie.name().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized boolean contain(String host, String name) {
|
||||
for (String key : map.keySet()) {
|
||||
if (domainMatch(host, key)) {
|
||||
List<CookieWithID> cookies = map.get(key);
|
||||
// cookies can not be null
|
||||
if (containInternal(host, name, cookies)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private synchronized void removeInternal(Cookie cookie) {
|
||||
String domain = cookie.domain();
|
||||
List<CookieWithID> cookies = map.get(domain);
|
||||
if (cookies != null) {
|
||||
// Remove from list
|
||||
CookieWithID cwi = removeCookie(cookies, cookie.name());
|
||||
if (cwi != null) {
|
||||
// Remove from DB
|
||||
CookieDB.removeCookie(cwi.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeInternal(String host, List<CookieWithID> cookies) {
|
||||
for (Iterator<CookieWithID> i = cookies.iterator(); i.hasNext();) {
|
||||
CookieWithID cwi = i.next();
|
||||
Cookie cookie = cwi.cookie;
|
||||
// Check match host or has expired
|
||||
if (domainMatch(cookie, host) || hasExpired(cookie)) {
|
||||
// Remove from list
|
||||
i.remove();
|
||||
// Remove from DB
|
||||
CookieDB.removeCookie(cwi.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void remove(String host) {
|
||||
for (String key : map.keySet()) {
|
||||
if (domainMatch(host, key)) {
|
||||
List<CookieWithID> cookies = map.get(key);
|
||||
// cookies can not be null
|
||||
removeInternal(host, cookies);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void removeAll() {
|
||||
map.clear();
|
||||
CookieDB.removeAllCookies();
|
||||
}
|
||||
|
||||
public synchronized void add(Cookie cookie) {
|
||||
String domain = cookie.domain();
|
||||
|
||||
// Check expired
|
||||
if (hasExpired(cookie)) {
|
||||
removeInternal(cookie);
|
||||
return;
|
||||
}
|
||||
|
||||
List<CookieWithID> cookies = map.get(domain);
|
||||
if (cookies == null) {
|
||||
cookies = new ArrayList<>();
|
||||
map.put(domain, cookies);
|
||||
} else {
|
||||
// Remove old cookie
|
||||
// Remove from list
|
||||
CookieWithID cwi = removeCookie(cookies, cookie.name());
|
||||
if (cwi != null) {
|
||||
// Remove from DB
|
||||
CookieDB.removeCookie(cwi.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Add to DB
|
||||
long id = CookieDB.addCookie(cookie);
|
||||
// Add to list
|
||||
cookies.add(new CookieWithID(id, cookie));
|
||||
}
|
||||
|
||||
private void getInternal(HttpUrl url, List<CookieWithID> cookies, List<Cookie> result) {
|
||||
for (Iterator<CookieWithID> i = cookies.iterator(); i.hasNext();) {
|
||||
CookieWithID cwi = i.next();
|
||||
Cookie cookie = cwi.cookie;
|
||||
// Check expired
|
||||
if (hasExpired(cookie)) {
|
||||
// Remove from list
|
||||
i.remove();
|
||||
// Remove from DB
|
||||
CookieDB.removeCookie(cwi.id);
|
||||
} else if (cookie.matches(url)) {
|
||||
result.add(cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Cookie getInternal(HttpUrl url, String name, List<CookieWithID> cookies) {
|
||||
for (Iterator<CookieWithID> i = cookies.iterator(); i.hasNext();) {
|
||||
CookieWithID cwi = i.next();
|
||||
Cookie cookie = cwi.cookie;
|
||||
// Check expired
|
||||
if (hasExpired(cookie)) {
|
||||
// Remove from list
|
||||
i.remove();
|
||||
// Remove from DB
|
||||
CookieDB.removeCookie(cwi.id);
|
||||
} else if (cookie.name().equals(name) && cookie.matches(url)) {
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public synchronized Cookie get(HttpUrl url, String name) {
|
||||
String host = url.host();
|
||||
for (String key : map.keySet()) {
|
||||
if (domainMatch(host, key)) {
|
||||
List<CookieWithID> cookies = map.get(key);
|
||||
return getInternal(url, name, cookies);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized List<Cookie> get(HttpUrl url) {
|
||||
List<Cookie> result = new ArrayList<>();
|
||||
|
||||
String host = url.host();
|
||||
for (String key : map.keySet()) {
|
||||
if (domainMatch(host, key)) {
|
||||
List<CookieWithID> cookies = map.get(key);
|
||||
// cookies can not be null
|
||||
getInternal(url, cookies, result);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
for (Cookie cookie: cookies) {
|
||||
add(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cookie> loadForRequest(HttpUrl url, Request request) {
|
||||
return get(url);
|
||||
}
|
||||
}
|
||||
+22
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,17 +14,29 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.okhttp;
|
||||
package com.hippo.util;
|
||||
/*
|
||||
* Created by Hippo on 2017/9/4.
|
||||
*/
|
||||
|
||||
import okhttp3.Cookie;
|
||||
public class HashCodeUtils {
|
||||
|
||||
public class CookieWithID {
|
||||
private static final int X = 31;
|
||||
|
||||
public long id;
|
||||
public Cookie cookie;
|
||||
|
||||
public CookieWithID(long id, Cookie cookie) {
|
||||
this.id = id;
|
||||
this.cookie = cookie;
|
||||
/**
|
||||
* <pre>{@code
|
||||
* args[0].hashCode()*31^(n-1) + args[1].hashCode()*31^(n-2) + ... + args[n-1].hashCode()
|
||||
* }</pre>
|
||||
* Returns 0 if {@code args == null}.
|
||||
*/
|
||||
public static int hashCode(Object... args) {
|
||||
if (args == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = 0;
|
||||
for (Object o: args) {
|
||||
hash = X * hash + (o != null ? o.hashCode() : 0);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
@@ -69,4 +69,54 @@ public class SqlUtils {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static boolean getBoolean(Cursor cursor, String column, boolean defValue) {
|
||||
try {
|
||||
int index = cursor.getColumnIndex(column);
|
||||
if (index != -1) {
|
||||
return cursor.getInt(index) != 0;
|
||||
}
|
||||
} catch (Throwable e) { /* Ignore */ }
|
||||
return defValue;
|
||||
}
|
||||
|
||||
public static int getInt(Cursor cursor, String column, int defValue) {
|
||||
try {
|
||||
int index = cursor.getColumnIndex(column);
|
||||
if (index != -1) {
|
||||
return cursor.getInt(index);
|
||||
}
|
||||
} catch (Throwable e) { /* Ignore */ }
|
||||
return defValue;
|
||||
}
|
||||
|
||||
public static long getLong(Cursor cursor, String column, long defValue) {
|
||||
try {
|
||||
int index = cursor.getColumnIndex(column);
|
||||
if (index != -1) {
|
||||
return cursor.getLong(index);
|
||||
}
|
||||
} catch (Throwable e) { /* Ignore */ }
|
||||
return defValue;
|
||||
}
|
||||
|
||||
public static float getFloat(Cursor cursor, String column, float defValue) {
|
||||
try {
|
||||
int index = cursor.getColumnIndex(column);
|
||||
if (index != -1) {
|
||||
return cursor.getFloat(index);
|
||||
}
|
||||
} catch (Throwable e) { /* Ignore */ }
|
||||
return defValue;
|
||||
}
|
||||
|
||||
public static String getString(Cursor cursor, String column, String defValue) {
|
||||
try {
|
||||
int index = cursor.getColumnIndex(column);
|
||||
if (index != -1) {
|
||||
return cursor.getString(index);
|
||||
}
|
||||
} catch (Throwable e) { /* Ignore */ }
|
||||
return defValue;
|
||||
}
|
||||
}
|
||||
@@ -71,13 +71,40 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/password"
|
||||
android:imeOptions="actionDone"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textPassword"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/recaptcha_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:minWidth="@dimen/single_max_width">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/recaptcha"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/recaptcha"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<com.hippo.ehviewer.widget.RecaptchaView
|
||||
android:id="@+id/recaptcha_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:minWidth="@dimen/single_max_width"
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
<android.support.v4.widget.Space
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
|
||||
<string name="username">用户名</string>
|
||||
<string name="password">密码</string>
|
||||
<string name="recaptcha">验证码(非必需)</string>
|
||||
|
||||
<string name="recaptcha_none">点我</string>
|
||||
<string name="recaptcha_loading">加载中…</string>
|
||||
<string name="recaptcha_failure">失败</string>
|
||||
|
||||
<string name="sign_in">登录</string>
|
||||
<string name="register">注册</string>
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
|
||||
<string name="username">用户名</string>
|
||||
<string name="password">密碼</string>
|
||||
<string name="recaptcha">驗證碼(非必需)</string>
|
||||
|
||||
<string name="recaptcha_none">點我</string>
|
||||
<string name="recaptcha_loading">加載中…</string>
|
||||
<string name="recaptcha_failure">失敗</string>
|
||||
|
||||
<string name="sign_in">登錄</string>
|
||||
<string name="register">註冊</string>
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
|
||||
<string name="username">使用者名稱</string>
|
||||
<string name="password">密碼</string>
|
||||
<string name="recaptcha">驗證碼(非必需)</string>
|
||||
|
||||
<string name="recaptcha_none">點我</string>
|
||||
<string name="recaptcha_loading">載入中…</string>
|
||||
<string name="recaptcha_failure">失敗</string>
|
||||
|
||||
<string name="sign_in">登入</string>
|
||||
<string name="register">註冊</string>
|
||||
|
||||
@@ -44,6 +44,11 @@
|
||||
|
||||
<string name="username">Username</string>
|
||||
<string name="password">Password</string>
|
||||
<string name="recaptcha">Recaptcha (Not required)</string>
|
||||
|
||||
<string name="recaptcha_none">Click me</string>
|
||||
<string name="recaptcha_loading">Loading…</string>
|
||||
<string name="recaptcha_failure">Failed</string>
|
||||
|
||||
<string name="sign_in">Sign in</string>
|
||||
<string name="register">Register</string>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.database;
|
||||
|
||||
/*
|
||||
* Created by Hippo on 2017/9/4.
|
||||
*/
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@Config(manifest = Config.NONE)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class MSQLiteBuilderTest {
|
||||
|
||||
@Test
|
||||
public void testGetStatements() {
|
||||
MSQLiteBuilder builder = new MSQLiteBuilder()
|
||||
.version(1)
|
||||
.statement("11")
|
||||
.statement("12")
|
||||
.version(3)
|
||||
.statement("31")
|
||||
.statement("32");
|
||||
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("31");
|
||||
list.add("32");
|
||||
assertEquals(list, builder.getStatements(1, 3));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright 2017 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.network;
|
||||
|
||||
/*
|
||||
* Created by Hippo on 2017/9/4.
|
||||
*/
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.HttpUrl;
|
||||
import org.joor.Reflect;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@Config(manifest = Config.NONE)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class CookieRepositoryTest {
|
||||
|
||||
private void equals(CookieSet cookieSet, List<Cookie> cookies) {
|
||||
assertNotNull(cookieSet);
|
||||
assertNotNull(cookies);
|
||||
|
||||
Map<CookieSet.Key, Cookie> map = Reflect.on(cookieSet).field("map").get();
|
||||
assertEquals(cookies.size(), map.size());
|
||||
for (Cookie cookie: cookies) {
|
||||
assertEquals(cookie, map.get(new CookieSet.Key(cookie)));
|
||||
}
|
||||
}
|
||||
|
||||
private void equals(List<Cookie> cookies1, List<Cookie> cookies2) {
|
||||
assertNotNull(cookies1);
|
||||
assertNotNull(cookies2);
|
||||
|
||||
assertEquals(cookies1.size(), cookies2.size());
|
||||
for (Cookie cookie: cookies1) {
|
||||
assertTrue(cookies2.contains(cookie));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPersistent() {
|
||||
Context app = RuntimeEnvironment.application;
|
||||
|
||||
HttpUrl urlEh = HttpUrl.parse("http://www.ehviewer.com/");
|
||||
Cookie cookieEh1 = new Cookie.Builder()
|
||||
.name("user")
|
||||
.value("1234567890")
|
||||
.domain("ehviewer.com")
|
||||
.path("/")
|
||||
.build();
|
||||
Cookie cookieEh2 = new Cookie.Builder()
|
||||
.name("level")
|
||||
.value("999")
|
||||
.domain("www.ehviewer.com")
|
||||
.path("/")
|
||||
.expiresAt(System.currentTimeMillis() + 100000)
|
||||
.build();
|
||||
Cookie cookieEh3 = new Cookie.Builder()
|
||||
.name("speed")
|
||||
.value("10")
|
||||
.domain("www.ehviewer.com")
|
||||
.path("/")
|
||||
.expiresAt(System.currentTimeMillis() + 100000)
|
||||
.build();
|
||||
|
||||
HttpUrl urlNMB = HttpUrl.parse("http://h.nimingban.com/");
|
||||
Cookie cookieNMB = new Cookie.Builder()
|
||||
.name("hash")
|
||||
.value("0987654321")
|
||||
.domain("nimingban.com")
|
||||
.expiresAt(System.currentTimeMillis() + 100000)
|
||||
.path("/")
|
||||
.build();
|
||||
|
||||
CookieRepository repository = new CookieRepository(app, "cookie.db");
|
||||
repository.saveFromResponse(urlEh, Arrays.asList(cookieEh1, cookieEh2, cookieEh3));
|
||||
repository.saveFromResponse(urlNMB, Collections.singletonList(cookieNMB));
|
||||
|
||||
Map<String, CookieSet> map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(3, map.size());
|
||||
equals(map.get("ehviewer.com"), Collections.singletonList(cookieEh1));
|
||||
equals(map.get("www.ehviewer.com"), Arrays.asList(cookieEh2, cookieEh3));
|
||||
equals(map.get("nimingban.com"), Collections.singletonList(cookieNMB));
|
||||
repository.close();
|
||||
|
||||
repository = new CookieRepository(app, "cookie.db");
|
||||
map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(2, map.size());
|
||||
equals(map.get("www.ehviewer.com"), Arrays.asList(cookieEh2, cookieEh3));
|
||||
equals(map.get("nimingban.com"), Collections.singletonList(cookieNMB));
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
Context app = RuntimeEnvironment.application;
|
||||
|
||||
HttpUrl urlEh = HttpUrl.parse("http://www.ehviewer.com/");
|
||||
Cookie cookieEh1 = new Cookie.Builder()
|
||||
.name("level")
|
||||
.value("999")
|
||||
.domain("www.ehviewer.com")
|
||||
.path("/")
|
||||
.expiresAt(System.currentTimeMillis() + 100000)
|
||||
.build();
|
||||
Cookie cookieEh2 = new Cookie.Builder()
|
||||
.name("level")
|
||||
.value("0")
|
||||
.domain("www.ehviewer.com")
|
||||
.path("/")
|
||||
.expiresAt(System.currentTimeMillis() + 100000)
|
||||
.build();
|
||||
|
||||
CookieRepository repository = new CookieRepository(app, "cookie.db");
|
||||
repository.saveFromResponse(urlEh, Collections.singletonList(cookieEh1));
|
||||
repository.saveFromResponse(urlEh, Collections.singletonList(cookieEh2));
|
||||
Map<String, CookieSet> map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(1, map.size());
|
||||
equals(map.get("www.ehviewer.com"), Collections.singletonList(cookieEh2));
|
||||
repository.close();
|
||||
|
||||
repository = new CookieRepository(app, "cookie.db");
|
||||
map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(1, map.size());
|
||||
equals(map.get("www.ehviewer.com"), Collections.singletonList(cookieEh2));
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveByExpired() {
|
||||
Context app = RuntimeEnvironment.application;
|
||||
|
||||
HttpUrl urlEh = HttpUrl.parse("http://www.ehviewer.com/");
|
||||
Cookie cookieEh1 = new Cookie.Builder()
|
||||
.name("level")
|
||||
.value("999")
|
||||
.domain("www.ehviewer.com")
|
||||
.path("/")
|
||||
.expiresAt(System.currentTimeMillis() + 100000)
|
||||
.build();
|
||||
Cookie cookieEh2 = new Cookie.Builder()
|
||||
.name("level")
|
||||
.value("0")
|
||||
.domain("www.ehviewer.com")
|
||||
.path("/")
|
||||
.expiresAt(System.currentTimeMillis() - 100000)
|
||||
.build();
|
||||
|
||||
CookieRepository repository = new CookieRepository(app, "cookie.db");
|
||||
repository.saveFromResponse(urlEh, Collections.singletonList(cookieEh1));
|
||||
repository.saveFromResponse(urlEh, Collections.singletonList(cookieEh2));
|
||||
Map<String, CookieSet> map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(1, map.size());
|
||||
equals(map.get("www.ehviewer.com"), Collections.<Cookie>emptyList());
|
||||
repository.close();
|
||||
|
||||
repository = new CookieRepository(app, "cookie.db");
|
||||
map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(0, map.size());
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveByNonPersistent() {
|
||||
Context app = RuntimeEnvironment.application;
|
||||
|
||||
HttpUrl urlEh = HttpUrl.parse("http://www.ehviewer.com/");
|
||||
Cookie cookieEh1 = new Cookie.Builder()
|
||||
.name("level")
|
||||
.value("999")
|
||||
.domain("www.ehviewer.com")
|
||||
.path("/")
|
||||
.expiresAt(System.currentTimeMillis() + 100000)
|
||||
.build();
|
||||
Cookie cookieEh2 = new Cookie.Builder()
|
||||
.name("level")
|
||||
.value("0")
|
||||
.domain("www.ehviewer.com")
|
||||
.path("/")
|
||||
.build();
|
||||
|
||||
CookieRepository repository = new CookieRepository(app, "cookie.db");
|
||||
repository.saveFromResponse(urlEh, Collections.singletonList(cookieEh1));
|
||||
repository.saveFromResponse(urlEh, Collections.singletonList(cookieEh2));
|
||||
Map<String, CookieSet> map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(1, map.size());
|
||||
equals(map.get("www.ehviewer.com"), Collections.singletonList(cookieEh2));
|
||||
repository.close();
|
||||
|
||||
|
||||
repository = new CookieRepository(app, "cookie.db");
|
||||
map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(0, map.size());
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet() throws InterruptedException {
|
||||
Context app = RuntimeEnvironment.application;
|
||||
|
||||
HttpUrl urlEh1 = HttpUrl.parse("http://www.ehviewer.com/");
|
||||
HttpUrl urlEh2 = HttpUrl.parse("http://ehviewer.com/");
|
||||
Cookie cookieEh1 = new Cookie.Builder()
|
||||
.name("user")
|
||||
.value("1234567890")
|
||||
.domain("ehviewer.com")
|
||||
.path("/")
|
||||
.expiresAt(System.currentTimeMillis() + 3000)
|
||||
.build();
|
||||
Cookie cookieEh2 = new Cookie.Builder()
|
||||
.name("level")
|
||||
.value("999")
|
||||
.domain("www.ehviewer.com")
|
||||
.path("/")
|
||||
.build();
|
||||
Cookie cookieEh3 = new Cookie.Builder()
|
||||
.name("speed")
|
||||
.value("10")
|
||||
.domain("ehviewer.com")
|
||||
.path("/")
|
||||
.build();
|
||||
|
||||
HttpUrl urlNMB = HttpUrl.parse("http://h.nimingban.com/");
|
||||
Cookie cookieNMB = new Cookie.Builder()
|
||||
.name("hash")
|
||||
.value("0987654321")
|
||||
.domain("nimingban.com")
|
||||
.path("/")
|
||||
.build();
|
||||
|
||||
CookieRepository repository = new CookieRepository(app, "cookie.db");
|
||||
repository.saveFromResponse(urlEh1, Arrays.asList(cookieEh1, cookieEh2));
|
||||
repository.saveFromResponse(urlEh1, Collections.singletonList(cookieEh3));
|
||||
repository.saveFromResponse(urlNMB, Collections.singletonList(cookieNMB));
|
||||
equals(Arrays.asList(cookieEh1, cookieEh3), repository.loadForRequest(urlEh2, null));
|
||||
Thread.sleep(3000);
|
||||
equals(Collections.singletonList(cookieEh3), repository.loadForRequest(urlEh2, null));
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClear() {
|
||||
Context app = RuntimeEnvironment.application;
|
||||
|
||||
HttpUrl url = HttpUrl.parse("http://www.ehviewer.com/");
|
||||
Cookie cookie = new Cookie.Builder()
|
||||
.name("user")
|
||||
.value("1234567890")
|
||||
.domain("ehviewer.com")
|
||||
.path("/")
|
||||
.expiresAt(System.currentTimeMillis() + 3000)
|
||||
.build();
|
||||
|
||||
CookieRepository repository = new CookieRepository(app, "cookie.db");
|
||||
repository.saveFromResponse(url, Collections.singletonList(cookie));
|
||||
Map<String, CookieSet> map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(1, map.size());
|
||||
equals(map.get("ehviewer.com"), Collections.singletonList(cookie));
|
||||
repository.clear();
|
||||
map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(0, map.size());
|
||||
repository.close();
|
||||
|
||||
repository = new CookieRepository(app, "cookie.db");
|
||||
map = Reflect.on(repository).field("map").get();
|
||||
assertEquals(0, map.size());
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSort() {
|
||||
Context app = RuntimeEnvironment.application;
|
||||
|
||||
HttpUrl url = HttpUrl.parse("http://www.ehviewer.com/long/long/long/");
|
||||
Cookie cookie1 = new Cookie.Builder()
|
||||
.name("user")
|
||||
.value("1234567890")
|
||||
.domain("ehviewer.com")
|
||||
.path("/")
|
||||
.build();
|
||||
Cookie cookie2 = new Cookie.Builder()
|
||||
.name("supersuperme")
|
||||
.value("99999")
|
||||
.domain("ehviewer.com")
|
||||
.path("/long/")
|
||||
.build();
|
||||
Cookie cookie3 = new Cookie.Builder()
|
||||
.name("a")
|
||||
.value("b")
|
||||
.domain("ehviewer.com")
|
||||
.path("/long/long/long/")
|
||||
.build();
|
||||
Cookie cookie4 = new Cookie.Builder()
|
||||
.name("speed")
|
||||
.value("100")
|
||||
.domain("ehviewer.com")
|
||||
.path("/long/long/")
|
||||
.build();
|
||||
|
||||
CookieRepository repository = new CookieRepository(app, "cookie.db");
|
||||
repository.saveFromResponse(url, Arrays.asList(cookie1, cookie2, cookie3, cookie4));
|
||||
List<Cookie> list = repository.loadForRequest(url, null);
|
||||
List<Cookie> expected = Arrays.asList(cookie3, cookie4, cookie2, cookie1);
|
||||
assertEquals(expected.size(), list.size());
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
assertEquals(expected.get(i), list.get(i));
|
||||
}
|
||||
repository.close();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -6,7 +6,7 @@ buildscript {
|
||||
maven { url "https://jitpack.io" }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.2'
|
||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
||||
classpath 'com.github.seven332:android-chinese-string-gradle-plugin:0.1.0'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.daogenerator;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import de.greenrobot.daogenerator.DaoGenerator;
|
||||
import de.greenrobot.daogenerator.Entity;
|
||||
import de.greenrobot.daogenerator.Schema;
|
||||
|
||||
public class CookieDaoGenerator {
|
||||
|
||||
private static final String PACKAGE = "com.hippo.okhttp.dao";
|
||||
private static final String OUT_DIR = "../app/src/main/java-gen";
|
||||
private static final String DELETE_DIR = "../app/src/main/java-gen/com/hippo/okhttp/dao";
|
||||
|
||||
public static void generate() throws Exception {
|
||||
Utilities.deleteContents(new File(DELETE_DIR));
|
||||
File outDir = new File(OUT_DIR);
|
||||
outDir.delete();
|
||||
outDir.mkdirs();
|
||||
|
||||
Schema schema = new Schema(1, PACKAGE);
|
||||
addOkHttp3Cookie(schema);
|
||||
new DaoGenerator().generateAll(schema, OUT_DIR);
|
||||
}
|
||||
|
||||
private static void addOkHttp3Cookie(Schema schema) {
|
||||
Entity entity = schema.addEntity("OkHttp3CookieRaw");
|
||||
entity.setTableName("OK_HTTP_3_COOKIE");
|
||||
entity.setClassNameDao("OkHttp3CookieDao");
|
||||
|
||||
entity.addIdProperty();
|
||||
entity.addStringProperty("name");
|
||||
entity.addStringProperty("value");
|
||||
entity.addLongProperty("expiresAt");
|
||||
entity.addStringProperty("domain");
|
||||
entity.addStringProperty("path");
|
||||
entity.addBooleanProperty("secure");
|
||||
entity.addBooleanProperty("httpOnly");
|
||||
entity.addBooleanProperty("persistent");
|
||||
entity.addBooleanProperty("hostOnly");
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package com.hippo.ehviewer.daogenerator;
|
||||
public class Main {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
CookieDaoGenerator.generate();
|
||||
EhDaoGenerator.generate();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user