237 lines
7.7 KiB
Java
237 lines
7.7 KiB
Java
/*
|
|
* 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();
|
|
}
|
|
}
|