|
|
|
internal class PersistentCookieStore(val context: Context) : CookieStore { |
|
|
|
inner class DatedCookie(val cookie: HttpCookie, val creationDate: Date) |
|
|
|
val SP_COOKIE_STORE = "cookieStore" |
|
val SP_KEY_DELIMITER = "|" |
|
val SP_KEY_DELIMITER_REGEX = "\\" + SP_KEY_DELIMITER |
|
|
|
val cookieSharedPreferences = context.getSharedPreferences(SP_COOKIE_STORE, Context.MODE_PRIVATE) |
|
val allCookies: MutableMap<URI, MutableSet<DatedCookie>> = mutableMapOf() |
|
|
|
init { |
|
cookieSharedPreferences.all.entries.map { |
|
val uriAndName = it.key.split(Regex(SP_KEY_DELIMITER_REGEX), 2) |
|
val uri = URI(uriAndName[0]) |
|
val cookie: DatedCookie = gson.fromJson<DatedCookie?>(it.value as String)!! |
|
if (allCookies[uri] == null) { |
|
allCookies.put(uri, mutableSetOf()) |
|
} |
|
allCookies[uri]?.add(cookie) |
|
} |
|
} |
|
|
|
fun getValidCookies(uri: URI) : List<HttpCookie> { |
|
return allCookies.keys.filter { |
|
HttpCookie.domainMatches(it.host, uri.host) |
|
//checkDomainsMatch(it.host, uri.host) |
|
&& checkPathsMatch(it.path, uri.path) |
|
} .flatMap { |
|
// clean expired cookies |
|
allCookies[it].orEmpty().filter { it.cookie.maxAge > 0 && Date().time > it.creationDate.time + (it.cookie.maxAge * 1000) } |
|
.forEach { |
|
remove(uri, it.cookie) |
|
} |
|
allCookies[it].orEmpty().map { it.cookie } |
|
} |
|
} |
|
|
|
private fun checkDomainsMatch(cookieHost: String, requestHost: String): Boolean { |
|
return requestHost == cookieHost || requestHost.endsWith("." + cookieHost) |
|
} |
|
|
|
private fun checkPathsMatch(cookiePath: String, requestPath: String): Boolean { |
|
return requestPath == cookiePath || |
|
requestPath.startsWith(cookiePath) && cookiePath[cookiePath.length - 1] == '/' || |
|
requestPath.startsWith(cookiePath) && requestPath.substring(cookiePath.length)[0] == '/' |
|
} |
|
|
|
@Synchronized override fun add(uri: URI, cookie: HttpCookie) { |
|
var uri = uri |
|
|
|
uri = cookie.cookieUri(uri) |
|
var exists = allCookies[uri] |
|
if (exists == null) |
|
allCookies[uri] = HashSet<DatedCookie>() |
|
val datedCookie = DatedCookie(cookie, Date()) |
|
allCookies[uri]?.add(datedCookie) |
|
saveToPersistence(uri, datedCookie) |
|
} |
|
|
|
private inline fun HttpCookie.cookieUri(uri: URI): URI { |
|
var cookieUri = uri |
|
if (domain != null) { |
|
// Remove the starting dot character of the domain, if exists (e.g: .domain.com -> domain.com) |
|
var domain = domain |
|
if (domain[0] == '.') { |
|
domain = domain.substring(1) |
|
} |
|
try { |
|
cookieUri = URI(if (uri.scheme == null) |
|
"http" |
|
else |
|
uri.scheme, domain, |
|
if (path == null) "/" else path, null) |
|
} catch (e: URISyntaxException) { |
|
Log.w(TAG, e) |
|
} |
|
|
|
} |
|
return cookieUri |
|
} |
|
|
|
private fun saveToPersistence(uri: URI, cookie: DatedCookie) { |
|
val editor = cookieSharedPreferences.edit() |
|
editor.putString(uri.toString() + SP_KEY_DELIMITER + cookie.cookie.name,gson.toJson(cookie)) |
|
editor.apply() |
|
} |
|
|
|
|
|
@Synchronized override fun remove(uri: URI, cookie: HttpCookie): Boolean { |
|
val targetCookies = allCookies[uri] |
|
val cookieRemoved = targetCookies != null && targetCookies.remove(targetCookies.find{ it.cookie == cookie }) |
|
if (cookieRemoved) { |
|
removeFromPersistence(uri, cookie) |
|
} |
|
return cookieRemoved |
|
|
|
} |
|
|
|
private fun removeFromPersistence(uri: URI, cookieToRemove: HttpCookie) { |
|
val editor = cookieSharedPreferences.edit() |
|
editor.remove(uri.toString() + SP_KEY_DELIMITER |
|
+ cookieToRemove.name) |
|
editor.apply() |
|
} |
|
|
|
|
|
override fun removeAll(): Boolean { |
|
allCookies.clear() |
|
cookieSharedPreferences.edit().clear().apply() |
|
return true |
|
} |
|
|
|
override fun get(uri: URI?): MutableList<HttpCookie>? = getValidCookies(uri!!).toMutableList() |
|
override fun getURIs(): MutableList<URI>? = allCookies.keys.toMutableList() |
|
override fun getCookies(): MutableList<HttpCookie>? = allCookies.keys.flatMap { getValidCookies(it) }.toMutableList() |
|
} |
Hello! I'm new on app development, I'm using your class however it gives me an error on line 17, asking me for a second argument on gson.fromJson<DatedCookie?>(it.value as String)!!, do you know what can it be?