kotlinize
This commit is contained in:
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user