kotlinize

This commit is contained in:
tarsin committed 2022-07-19 12:02:07 +08:00
1 parent ba3fe869d8
commit b84daa45c5
6 files changed
+407 -508

No files matched your search

@@ -13,225 +13,202 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.network
package com.hippo.network;
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.util.Log
import com.hippo.database.MSQLiteBuilder
import com.hippo.util.SqlUtils
import okhttp3.Cookie
/*
* Created by Hippo on 2017/9/4.
*/
internal class CookieDatabase(context: Context, name: String) {
private val cookieIdMap: MutableMap<Cookie, Long> = HashMap()
private val helper: SQLiteOpenHelper
private val db: SQLiteDatabase
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.util.Log;
val allCookies: MutableMap<String, CookieSet>
get() {
val now = System.currentTimeMillis()
val map: MutableMap<String, CookieSet> = HashMap()
val toRemove: MutableList<Long> = ArrayList()
db.rawQuery("SELECT * FROM $TABLE_COOKIE;", null).use { cursor ->
while (cursor.moveToNext()) {
val id = SqlUtils.getLong(cursor, COLUMN_ID, 0)
val cookie = getCookie(cursor, now)
if (cookie != null) {
// Save id of the cookie in db
cookieIdMap[cookie] = id
import androidx.annotation.Nullable;
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<>();
try (Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_COOKIE + ";", null)) {
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);
// Put cookie to set
var set = map[cookie.domain]
if (set == null) {
set = CookieSet()
map[cookie.domain] = set
}
set.add(cookie)
} else {
// Mark to remove the cookie
toRemove.add(id)
}
set.add(cookie);
} else {
// Mark to remove the cookie
toRemove.add(id);
}
}
}
// 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();
// Remove invalid or expired cookie
if (toRemove.isNotEmpty()) {
val statement = db.compileStatement(
"DELETE FROM $TABLE_COOKIE WHERE $COLUMN_ID = ?;"
)
db.beginTransaction()
try {
for (id in toRemove) {
statement.bindLong(1, id)
statement.executeUpdateDelete()
}
db.setTransactionSuccessful()
} finally {
db.endTransaction()
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
return map
}
return map;
private fun toContentValues(cookie: Cookie): ContentValues {
val contentValues = 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 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));
fun add(cookie: Cookie) {
val 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");
val 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");
Log.e(LOG_TAG, "An error occurred when insert a cookie")
}
}
public void update(Cookie from, Cookie to) {
Long id = cookieIdMap.get(from);
fun update(from: Cookie, to: Cookie) {
val id = cookieIdMap[from]
if (id == null) {
Log.e(LOG_TAG, "Can't get id when update the cookie");
return;
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);
val values = toContentValues(to)
val whereClause = "$COLUMN_ID = ?"
val whereArgs = arrayOf(id.toString())
val count = db.update(TABLE_COOKIE, values, whereClause, whereArgs)
if (count != 1) {
Log.e(LOG_TAG, "Bad result when update cookie: " + count);
Log.e(LOG_TAG, "Bad result when update cookie: $count")
}
// Update it in cookie-id map
cookieIdMap.remove(from);
cookieIdMap.put(to, id);
cookieIdMap.remove(from)
cookieIdMap[to] = id
}
public void remove(Cookie cookie) {
Long id = cookieIdMap.get(cookie);
fun remove(cookie: Cookie) {
val id = cookieIdMap[cookie]
if (id == null) {
Log.e(LOG_TAG, "Can't get id when remove the cookie");
return;
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);
val whereClause = "$COLUMN_ID = ?"
val whereArgs = arrayOf(id.toString())
val count = db.delete(TABLE_COOKIE, whereClause, whereArgs)
if (count != 1) {
Log.e(LOG_TAG, "Bad result when remove cookie: " + count);
Log.e(LOG_TAG, "Bad result when remove cookie: $count")
}
// Remove it from cookie-id map
cookieIdMap.remove(cookie);
cookieIdMap.remove(cookie)
}
public void clear() {
db.delete(TABLE_COOKIE, null, null);
cookieIdMap.clear();
fun clear() {
db.delete(TABLE_COOKIE, null, null)
cookieIdMap.clear()
}
public void close() {
db.close();
helper.close();
fun close() {
db.close()
helper.close()
}
}
companion object {
private val LOG_TAG = CookieDatabase::class.java.simpleName
private const val VERSION_1 = 1
private const val TABLE_COOKIE = "OK_HTTP_3_COOKIE"
private const val COLUMN_ID = "_id"
private const val COLUMN_NAME = "NAME"
private const val COLUMN_VALUE = "VALUE"
private const val COLUMN_EXPIRES_AT = "EXPIRES_AT"
private const val COLUMN_DOMAIN = "DOMAIN"
private const val COLUMN_PATH = "PATH"
private const val COLUMN_SECURE = "SECURE"
private const val COLUMN_HTTP_ONLY = "HTTP_ONLY"
private const val COLUMN_PERSISTENT = "PERSISTENT"
private const val COLUMN_HOST_ONLY = "HOST_ONLY"
private const val DB_VERSION = VERSION_1
private fun getCookie(cursor: Cursor, now: Long): Cookie? {
val name = SqlUtils.getString(cursor, COLUMN_NAME, null)
val value = SqlUtils.getString(cursor, COLUMN_VALUE, null)
val expiresAt = SqlUtils.getLong(cursor, COLUMN_EXPIRES_AT, 0)
val domain = SqlUtils.getString(cursor, COLUMN_DOMAIN, null)
val path = SqlUtils.getString(cursor, COLUMN_PATH, null)
val secure = SqlUtils.getBoolean(cursor, COLUMN_SECURE, false)
val httpOnly = SqlUtils.getBoolean(cursor, COLUMN_HTTP_ONLY, false)
val persistent = SqlUtils.getBoolean(cursor, COLUMN_PERSISTENT, false)
val 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
}
val builder = 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()
}
}
init {
helper = MSQLiteBuilder()
.version(VERSION_1)
.createTable(TABLE_COOKIE)
.insertColumn(TABLE_COOKIE, COLUMN_NAME, String::class.java)
.insertColumn(TABLE_COOKIE, COLUMN_VALUE, String::class.java)
.insertColumn(TABLE_COOKIE, COLUMN_EXPIRES_AT, Long::class.javaPrimitiveType)
.insertColumn(TABLE_COOKIE, COLUMN_DOMAIN, String::class.java)
.insertColumn(TABLE_COOKIE, COLUMN_PATH, String::class.java)
.insertColumn(TABLE_COOKIE, COLUMN_SECURE, Boolean::class.javaPrimitiveType)
.insertColumn(TABLE_COOKIE, COLUMN_HTTP_ONLY, Boolean::class.javaPrimitiveType)
.insertColumn(TABLE_COOKIE, COLUMN_PERSISTENT, Boolean::class.javaPrimitiveType)
.insertColumn(TABLE_COOKIE, COLUMN_HOST_ONLY, Boolean::class.javaPrimitiveType)
.build(context, name, DB_VERSION)
db = helper.writableDatabase
}
}
@@ -13,183 +13,169 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.network
package com.hippo.network;
import android.content.Context
import com.hippo.yorozuya.ObjectUtils
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.HttpUrl
import java.util.regex.Pattern
/*
* Created by Hippo on 2017/9/4.
*/
open class CookieRepository(context: Context, name: String) : CookieJar {
private val db: CookieDatabase
private val map: MutableMap<String, CookieSet>
import android.content.Context;
import androidx.annotation.NonNull;
import com.hippo.yorozuya.ObjectUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
public class CookieRepository implements CookieJar {
/**
* Quick and dirty pattern to differentiate IP addresses from hostnames. This is an approximation
* of Android's private InetAddress#isNumeric API.
* <p>
* 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.]+)");
private final CookieDatabase db;
private final Map<String, CookieSet> map;
public CookieRepository(Context context, String name) {
db = new CookieDatabase(context, name);
map = db.getAllCookies();
}
/**
* 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'.
}
return urlHost.endsWith(domain)
&& urlHost.charAt(urlHost.length() - domain.length() - 1) == '.'
&& !verifyAsIpAddress(urlHost); // As in 'example.com' matching 'www.example.com'.
}
public synchronized void addCookie(Cookie cookie) {
@Synchronized
fun addCookie(cookie: Cookie) {
// For cookie database
Cookie toAdd = null;
Cookie toUpdate = null;
Cookie toRemove = null;
CookieSet set = map.get(cookie.domain());
var toAdd: Cookie? = null
var toUpdate: Cookie? = null
var toRemove: Cookie? = null
var set = map[cookie.domain]
if (set == null) {
set = new CookieSet();
map.put(cookie.domain(), set);
set = CookieSet()
map[cookie.domain] = set
}
if (cookie.expiresAt() <= System.currentTimeMillis()) {
toRemove = set.remove(cookie);
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;
if (toRemove != null && !toRemove.persistent) {
toRemove = null
}
} else {
toAdd = cookie;
toUpdate = set.add(cookie);
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;
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;
toRemove = toUpdate
toUpdate = null
}
}
if (toRemove != null) {
db.remove(toRemove);
db.remove(toRemove)
}
if (toAdd != null) {
if (toUpdate != null) {
db.update(toUpdate, toAdd);
db.update(toUpdate, toAdd)
} else {
db.add(toAdd);
db.add(toAdd)
}
}
}
public String getCookieHeader(HttpUrl url) {
List<Cookie> cookies = getCookies(url);
StringBuilder cookieHeader = new StringBuilder();
for (int i = 0, size = cookies.size(); i < size; i++) {
fun getCookieHeader(url: HttpUrl): String {
val cookies = getCookies(url)
val cookieHeader = StringBuilder()
var i = 0
val size = cookies.size
while (i < size) {
if (i > 0) {
cookieHeader.append("; ");
cookieHeader.append("; ")
}
Cookie cookie = cookies.get(i);
cookieHeader.append(cookie.name()).append('=').append(cookie.value());
val cookie = cookies[i]
cookieHeader.append(cookie.name).append('=').append(cookie.value)
i++
}
return cookieHeader.toString();
return cookieHeader.toString()
}
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();
@Synchronized
fun getCookies(url: HttpUrl): List<Cookie> {
val accepted: MutableList<Cookie> = ArrayList()
val expired: MutableList<Cookie> = ArrayList()
for ((domain, cookieSet) in map) {
if (domainMatch(url, domain)) {
cookieSet.get(url, accepted, expired);
cookieSet[url, accepted, expired]
}
}
for (Cookie cookie : expired) {
if (cookie.persistent()) {
db.remove(cookie);
for (cookie in 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, (o1, o2) -> o2.path().length() - o1.path().length());
return accepted;
accepted.sortWith { o1: Cookie, o2: Cookie -> 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;
fun contains(url: HttpUrl, name: String?): Boolean {
for (cookie in getCookies(url)) {
if (ObjectUtils.equal(cookie.name, name)) {
return true
}
}
return false;
return false
}
/**
* Remove all cookies in this {@code CookieRepository}.
* Remove all cookies in this `CookieRepository`.
*/
public synchronized void clear() {
map.clear();
db.clear();
@Synchronized
fun clear() {
map.clear()
db.clear()
}
public synchronized void close() {
db.close();
@Synchronized
fun close() {
db.close()
}
@Override
public void saveFromResponse(@NonNull HttpUrl httpUrl, List<Cookie> list) {
for (Cookie cookie : list) {
addCookie(cookie);
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
for (cookie in cookies) {
addCookie(cookie)
}
}
@NonNull
@Override
public List<Cookie> loadForRequest(@NonNull HttpUrl httpUrl) {
return getCookies(httpUrl);
override fun loadForRequest(url: HttpUrl): List<Cookie> {
return getCookies(url)
}
}
companion object {
/**
* 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 val 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 fun verifyAsIpAddress(host: String): Boolean {
return VERIFY_AS_IP_ADDRESS.matcher(host).matches()
}
// okhttp3.Cookie.domainMatch(HttpUrl, String)
@JvmStatic
protected fun domainMatch(url: HttpUrl, domain: String?): Boolean {
val urlHost = url.host
return if (urlHost == domain) {
true // As in 'example.com' matching 'example.com'.
} else urlHost.endsWith(domain!!)
&& urlHost[urlHost.length - domain.length - 1] == '.' && !verifyAsIpAddress(
urlHost
)
// As in 'example.com' matching 'www.example.com'.
}
}
init {
db = CookieDatabase(context, name)
map = db.allCookies
}
}
@@ -13,94 +13,75 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.network
package com.hippo.network;
import com.hippo.util.HashCodeUtils
import com.hippo.yorozuya.ObjectUtils
import okhttp3.Cookie
import okhttp3.HttpUrl
/*
* 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 final Map<Key, Cookie> map = new HashMap<>();
internal class CookieSet {
private val map: MutableMap<Key, Cookie> = HashMap()
/**
* Adds a cookie to this {@code CookieSet}.
* Adds a cookie to this `CookieSet`.
* Returns a previous cookie with
* the same name, domain and path or {@code null}.
* the same name, domain and path or `null`.
*/
public Cookie add(Cookie cookie) {
return map.put(new Key(cookie), cookie);
fun add(cookie: Cookie): Cookie? {
return map.put(Key(cookie), cookie)
}
/**
* Removes a cookie with the same name,
* domain and path as the cookie.
* Returns the removed cookie or {@code null}.
* Returns the removed cookie or `null`.
*/
public Cookie remove(Cookie cookie) {
return map.remove(new Key(cookie));
fun remove(cookie: Cookie): Cookie? {
return map.remove(Key(cookie))
}
/**
* Get cookies for the url. Fill {@code accepted} and {@code expired}.
* Get cookies for the url. Fill `accepted` and `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();
operator fun get(url: HttpUrl?, accepted: MutableList<Cookie>, expired: MutableList<Cookie>) {
val now = System.currentTimeMillis()
val iterator: MutableIterator<Map.Entry<Key, Cookie>> = map.entries.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);
val cookie = iterator.next().value
if (cookie.expiresAt <= now) {
iterator.remove()
expired.add(cookie)
} else if (cookie.matches(url!!)) {
accepted.add(cookie)
}
}
}
static class Key {
private final String name;
private final String domain;
private final String path;
public Key(Cookie cookie) {
this.name = cookie.name();
this.domain = cookie.domain();
this.path = cookie.path();
internal class Key(cookie: Cookie) {
private val name: String
private val domain: String
private val path: String
override fun equals(other: Any?): Boolean {
if (other === this) {
return true
}
if (other is Key) {
return ObjectUtils.equal(other.name, name) &&
ObjectUtils.equal(other.domain, domain) &&
ObjectUtils.equal(other.path, path)
}
return false
}
@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 fun hashCode(): Int {
return HashCodeUtils.hashCode(name, domain, path)
}
@Override
public int hashCode() {
return HashCodeUtils.hashCode(name, domain, path);
init {
name = cookie.name
domain = cookie.domain
path = cookie.path
}
}
}
}
@@ -13,55 +13,47 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.network
package com.hippo.network;
import java.util.regex.Pattern
import java.util.regex.Matcher;
import java.util.regex.Pattern;
object InetValidator {
private const val IPV4_REGEX = "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"
private val IPV4_PATTERN = Pattern.compile(IPV4_REGEX)
public final class InetValidator {
private static final String IPV4_REGEX =
"^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
private static final Pattern IPV4_PATTERN = Pattern.compile(IPV4_REGEX);
private InetValidator() {
}
public static boolean isValidInet4Address(String inet4Address) {
@JvmStatic
fun isValidInet4Address(inet4Address: String?): Boolean {
if (null == inet4Address) {
return false;
return false
}
Matcher matcher = IPV4_PATTERN.matcher(inet4Address);
val matcher = IPV4_PATTERN.matcher(inet4Address)
if (!matcher.find()) {
return false;
return false
}
// verify that address subgroups are legal
for (int i = 1; i <= 4; i++) {
String ipSegment = matcher.group(i);
if (ipSegment == null || ipSegment.length() == 0) {
return false;
for (i in 1..4) {
val ipSegment = matcher.group(i)
if (ipSegment == null || ipSegment.isEmpty()) {
return false
}
int iIpSegment;
try {
iIpSegment = Integer.parseInt(ipSegment);
} catch (NumberFormatException e) {
return false;
val iIpSegment: Int = try {
ipSegment.toInt()
} catch (e: NumberFormatException) {
return false
}
if (iIpSegment > 255) {
return false;
return false
}
if (ipSegment.length() > 1 && ipSegment.startsWith("0")) {
return false;
if (ipSegment.length > 1 && ipSegment.startsWith("0")) {
return false
}
}
return true;
return true
}
public static boolean isValidInetPort(int inetPort) {
return inetPort >= 0 && inetPort <= 65535;
@JvmStatic
fun isValidInetPort(inetPort: Int): Boolean {
return inetPort in 0..65535
}
}
}
@@ -13,78 +13,54 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.network
package com.hippo.network;
import android.content.Context
import android.util.SparseArray
import com.hippo.ehviewer.R
import android.content.Context;
import android.content.res.Resources;
import android.util.SparseArray;
class StatusCodeException(val responseCode: Int) : Exception() {
override val message: String = ERROR_MESSAGE_ARRAY[responseCode, DEFAULT_ERROR_MESSAGE]
import com.hippo.ehviewer.R;
val isIdentifiedResponseCode: Boolean
get() = DEFAULT_ERROR_MESSAGE != message
public class StatusCodeException extends Exception {
private static final SparseArray<String> ERROR_MESSAGE_ARRAY = new SparseArray<>(24);
private static final String DEFAULT_ERROR_MESSAGE = "Error response code";
private final int mResponseCode;
private final String mMessage;
public StatusCodeException(int responseCode) {
mResponseCode = responseCode;
mMessage = ERROR_MESSAGE_ARRAY.get(responseCode, DEFAULT_ERROR_MESSAGE);
override fun getLocalizedMessage(): String {
return message
}
public StatusCodeException(int responseCode, String message) {
mResponseCode = responseCode;
mMessage = message;
companion object {
private val ERROR_MESSAGE_ARRAY = SparseArray<String>(24)
private const val DEFAULT_ERROR_MESSAGE = "Error response code"
@JvmStatic
fun initialize(context: Context) {
val resources = context.applicationContext.resources
ERROR_MESSAGE_ARRAY.append(400, resources.getString(R.string.error_status_code_400))
ERROR_MESSAGE_ARRAY.append(401, resources.getString(R.string.error_status_code_401))
ERROR_MESSAGE_ARRAY.append(402, resources.getString(R.string.error_status_code_402))
ERROR_MESSAGE_ARRAY.append(403, resources.getString(R.string.error_status_code_403))
ERROR_MESSAGE_ARRAY.append(404, resources.getString(R.string.error_status_code_404))
ERROR_MESSAGE_ARRAY.append(405, resources.getString(R.string.error_status_code_405))
ERROR_MESSAGE_ARRAY.append(406, resources.getString(R.string.error_status_code_406))
ERROR_MESSAGE_ARRAY.append(407, resources.getString(R.string.error_status_code_407))
ERROR_MESSAGE_ARRAY.append(408, resources.getString(R.string.error_status_code_408))
ERROR_MESSAGE_ARRAY.append(409, resources.getString(R.string.error_status_code_409))
ERROR_MESSAGE_ARRAY.append(410, resources.getString(R.string.error_status_code_410))
ERROR_MESSAGE_ARRAY.append(411, resources.getString(R.string.error_status_code_411))
ERROR_MESSAGE_ARRAY.append(412, resources.getString(R.string.error_status_code_412))
ERROR_MESSAGE_ARRAY.append(413, resources.getString(R.string.error_status_code_413))
ERROR_MESSAGE_ARRAY.append(414, resources.getString(R.string.error_status_code_414))
ERROR_MESSAGE_ARRAY.append(415, resources.getString(R.string.error_status_code_415))
ERROR_MESSAGE_ARRAY.append(416, resources.getString(R.string.error_status_code_416))
ERROR_MESSAGE_ARRAY.append(417, resources.getString(R.string.error_status_code_417))
ERROR_MESSAGE_ARRAY.append(500, resources.getString(R.string.error_status_code_500))
ERROR_MESSAGE_ARRAY.append(501, resources.getString(R.string.error_status_code_501))
ERROR_MESSAGE_ARRAY.append(502, resources.getString(R.string.error_status_code_502))
ERROR_MESSAGE_ARRAY.append(503, resources.getString(R.string.error_status_code_503))
ERROR_MESSAGE_ARRAY.append(504, resources.getString(R.string.error_status_code_504))
ERROR_MESSAGE_ARRAY.append(505, resources.getString(R.string.error_status_code_505))
}
}
public static void initialize(Context context) {
Resources resources = context.getApplicationContext().getResources();
ERROR_MESSAGE_ARRAY.append(400, resources.getString(R.string.error_status_code_400));
ERROR_MESSAGE_ARRAY.append(401, resources.getString(R.string.error_status_code_401));
ERROR_MESSAGE_ARRAY.append(402, resources.getString(R.string.error_status_code_402));
ERROR_MESSAGE_ARRAY.append(403, resources.getString(R.string.error_status_code_403));
ERROR_MESSAGE_ARRAY.append(404, resources.getString(R.string.error_status_code_404));
ERROR_MESSAGE_ARRAY.append(405, resources.getString(R.string.error_status_code_405));
ERROR_MESSAGE_ARRAY.append(406, resources.getString(R.string.error_status_code_406));
ERROR_MESSAGE_ARRAY.append(407, resources.getString(R.string.error_status_code_407));
ERROR_MESSAGE_ARRAY.append(408, resources.getString(R.string.error_status_code_408));
ERROR_MESSAGE_ARRAY.append(409, resources.getString(R.string.error_status_code_409));
ERROR_MESSAGE_ARRAY.append(410, resources.getString(R.string.error_status_code_410));
ERROR_MESSAGE_ARRAY.append(411, resources.getString(R.string.error_status_code_411));
ERROR_MESSAGE_ARRAY.append(412, resources.getString(R.string.error_status_code_412));
ERROR_MESSAGE_ARRAY.append(413, resources.getString(R.string.error_status_code_413));
ERROR_MESSAGE_ARRAY.append(414, resources.getString(R.string.error_status_code_414));
ERROR_MESSAGE_ARRAY.append(415, resources.getString(R.string.error_status_code_415));
ERROR_MESSAGE_ARRAY.append(416, resources.getString(R.string.error_status_code_416));
ERROR_MESSAGE_ARRAY.append(417, resources.getString(R.string.error_status_code_417));
ERROR_MESSAGE_ARRAY.append(500, resources.getString(R.string.error_status_code_500));
ERROR_MESSAGE_ARRAY.append(501, resources.getString(R.string.error_status_code_501));
ERROR_MESSAGE_ARRAY.append(502, resources.getString(R.string.error_status_code_502));
ERROR_MESSAGE_ARRAY.append(503, resources.getString(R.string.error_status_code_503));
ERROR_MESSAGE_ARRAY.append(504, resources.getString(R.string.error_status_code_504));
ERROR_MESSAGE_ARRAY.append(505, resources.getString(R.string.error_status_code_505));
}
public int getResponseCode() {
return mResponseCode;
}
public boolean isIdentifiedResponseCode() {
return !DEFAULT_ERROR_MESSAGE.equals(mMessage);
}
@Override
public String getMessage() {
return mMessage;
}
@Override
public String getLocalizedMessage() {
return getMessage();
}
}
}
@@ -13,45 +13,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.network
package com.hippo.network;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class UrlBuilder {
public String mRootUrl;
public Map<String, Object> mQueryMap = new HashMap<>();
public UrlBuilder(String rootUrl) {
mRootUrl = rootUrl;
class UrlBuilder(private var mRootUrl: String) {
private var mQueryMap: MutableMap<String, Any> = HashMap()
fun addQuery(key: String, value: Any) {
mQueryMap[key] = value
}
public void addQuery(String key, Object value) {
mQueryMap.put(key, value);
}
public String build() {
if (mQueryMap.size() == 0) {
return mRootUrl;
fun build(): String {
return if (mQueryMap.isEmpty()) {
mRootUrl
} else {
StringBuilder sb = new StringBuilder(mRootUrl);
sb.append("?");
Iterator<String> iter = mQueryMap.keySet().iterator();
val sb = StringBuilder(mRootUrl)
sb.append("?")
val iter: Iterator<String> = mQueryMap.keys.iterator()
if (iter.hasNext()) {
String key = iter.next();
Object value = mQueryMap.get(key);
sb.append(key).append("=").append(value);
val key = iter.next()
val value = mQueryMap[key]
sb.append(key).append("=").append(value)
}
while (iter.hasNext()) {
String key = iter.next();
Object value = mQueryMap.get(key);
sb.append("&").append(key).append("=").append(value);
val key = iter.next()
val value = mQueryMap[key]
sb.append("&").append(key).append("=").append(value)
}
return sb.toString();
sb.toString()
}
}
}
}