Migrate cookies store to CookieManager backend
This commit is contained in:
1 parent
ad04681460
commit
55b3753e66
10 files changed
+81
-389
No files matched your search
@@ -37,6 +37,7 @@ import com.hippo.ehviewer.dailycheck.checkDawn
|
||||
import com.hippo.ehviewer.dao.EhDatabase
|
||||
import com.hippo.ehviewer.download.DownloadManager
|
||||
import com.hippo.ehviewer.legacy.cleanObsoleteCache
|
||||
import com.hippo.ehviewer.legacy.migrateCookies
|
||||
import com.hippo.ehviewer.okhttp.cache
|
||||
import com.hippo.ehviewer.okhttp.httpClient
|
||||
import com.hippo.ehviewer.ui.keepNoMediaFileStatus
|
||||
@@ -76,6 +77,9 @@ class EhApplication : Application(), ImageLoaderFactory {
|
||||
}
|
||||
}
|
||||
launchIO {
|
||||
launchIO {
|
||||
migrateCookies()
|
||||
}
|
||||
launchIO {
|
||||
EhTagDatabase.update()
|
||||
}
|
||||
|
||||
@@ -15,45 +15,42 @@
|
||||
*/
|
||||
package com.hippo.ehviewer.client
|
||||
|
||||
import com.hippo.ehviewer.network.CookieDatabase
|
||||
import com.hippo.ehviewer.network.CookieSet
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import android.webkit.CookieManager
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import splitties.init.appCtx
|
||||
import java.util.Collections
|
||||
import java.util.regex.Pattern
|
||||
|
||||
object EhCookieStore : CookieJar {
|
||||
private val db: CookieDatabase = CookieDatabase(appCtx)
|
||||
private val map: MutableMap<String, CookieSet> = db.allCookies
|
||||
private val manager = CookieManager.getInstance()
|
||||
fun signOut() = manager.removeAllCookies(null)
|
||||
fun contains(url: HttpUrl, name: String) = get(url).any { it.name == name }
|
||||
|
||||
fun signOut() {
|
||||
clear()
|
||||
fun get(url: HttpUrl): List<Cookie> {
|
||||
val cookies = manager.getCookie(url.toString())
|
||||
|
||||
return if (cookies != null && cookies.isNotEmpty()) {
|
||||
cookies.split(";").mapNotNull { Cookie.parse(url, it) }.filterNot { it.name == KEY_UTMP_NAME }
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
fun hasSignedIn(): Boolean {
|
||||
val url = EhUrl.HOST_E.toHttpUrl()
|
||||
return contains(url, KEY_IPB_MEMBER_ID) &&
|
||||
contains(url, KEY_IPB_PASS_HASH)
|
||||
return contains(url, KEY_IPB_MEMBER_ID) && contains(url, KEY_IPB_PASS_HASH)
|
||||
}
|
||||
|
||||
const val KEY_IPB_MEMBER_ID = "ipb_member_id"
|
||||
const val KEY_IPB_PASS_HASH = "ipb_pass_hash"
|
||||
const val KEY_IGNEOUS = "igneous"
|
||||
const val KEY_SETTINGS_PROFILE = "sp"
|
||||
const val KEY_STAR = "star"
|
||||
private const val KEY_STAR = "star"
|
||||
private const val KEY_CONTENT_WARNING = "nw"
|
||||
private const val CONTENT_WARNING_NOT_SHOW = "1"
|
||||
private val sTipsCookie: Cookie = Cookie.Builder()
|
||||
.name(KEY_CONTENT_WARNING)
|
||||
.value(CONTENT_WARNING_NOT_SHOW)
|
||||
.domain(EhUrl.DOMAIN_E)
|
||||
.path("/")
|
||||
.expiresAt(Long.MAX_VALUE)
|
||||
.build()
|
||||
private const val KEY_UTMP_NAME = "__utmp"
|
||||
private val sTipsCookie: Cookie = Cookie.Builder().name(KEY_CONTENT_WARNING).value(CONTENT_WARNING_NOT_SHOW).domain(EhUrl.DOMAIN_E).path("/").expiresAt(Long.MAX_VALUE).build()
|
||||
|
||||
fun newCookie(
|
||||
cookie: Cookie,
|
||||
@@ -87,64 +84,22 @@ object EhCookieStore : CookieJar {
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
fun copyCookie(domain: String, newDomain: String, name: String, path: String = "/") {
|
||||
val cookie = map[domain]?.get(name, domain, path)
|
||||
cookie?.let { addCookie(newCookie(it, newDomain)) }
|
||||
fun copyNecessaryCookies() {
|
||||
val cookie = get(EhUrl.HOST_E.toHttpUrl()).filter { it.name == KEY_STAR || it.name == KEY_IPB_MEMBER_ID || it.name == KEY_IPB_PASS_HASH || it.name == KEY_IGNEOUS }
|
||||
cookie.forEach { manager.setCookie(EhUrl.HOST_EX, it.toString()) }
|
||||
}
|
||||
|
||||
fun deleteCookie(url: HttpUrl, name: String) {
|
||||
val deletedCookie = Cookie.Builder()
|
||||
.name(name)
|
||||
.value("deleted")
|
||||
.domain(url.host)
|
||||
.expiresAt(0)
|
||||
.build()
|
||||
addCookie(deletedCookie)
|
||||
val deletedCookie = Cookie.Builder().name(name).value("deleted").domain(url.host).expiresAt(0).build()
|
||||
manager.setCookie(url.toString(), deletedCookie.toString())
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun addCookie(cookie: Cookie) {
|
||||
// For cookie database
|
||||
var toAdd: Cookie? = null
|
||||
var toUpdate: Cookie? = null
|
||||
var toRemove: Cookie? = null
|
||||
var set = map[cookie.domain]
|
||||
if (set == null) {
|
||||
set = CookieSet()
|
||||
map[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)
|
||||
}
|
||||
}
|
||||
if (EhUrl.DOMAIN_E in cookie.domain) manager.setCookie(EhUrl.HOST_E, cookie.toString()) else manager.setCookie(EhUrl.DOMAIN_EX, cookie.toString())
|
||||
}
|
||||
|
||||
fun getCookieHeader(url: HttpUrl): String {
|
||||
val cookies = getCookies(url)
|
||||
val cookies = get(url)
|
||||
val cookieHeader = StringBuilder()
|
||||
var i = 0
|
||||
val size = cookies.size
|
||||
@@ -159,56 +114,8 @@ object EhCookieStore : CookieJar {
|
||||
return cookieHeader.toString()
|
||||
}
|
||||
|
||||
@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[url, accepted, expired]
|
||||
}
|
||||
}
|
||||
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.
|
||||
accepted.sortWith { o1: Cookie, o2: Cookie -> o2.path.length - o1.path.length }
|
||||
return accepted
|
||||
}
|
||||
|
||||
fun contains(url: HttpUrl, name: String?): Boolean {
|
||||
for (cookie in getCookies(url)) {
|
||||
if (cookie.name == name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all cookies in this `CookieRepository`.
|
||||
*/
|
||||
@Synchronized
|
||||
fun clear() {
|
||||
map.clear()
|
||||
launchIO {
|
||||
db.clear()
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
|
||||
for (cookie in cookies) {
|
||||
// See https://github.com/Ehviewer-Overhauled/Ehviewer/issues/873
|
||||
if (cookie.name != "__utmp") {
|
||||
addCookie(cookie)
|
||||
}
|
||||
}
|
||||
}
|
||||
// See https://github.com/Ehviewer-Overhauled/Ehviewer/issues/873
|
||||
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) = cookies.filterNot { it.name == KEY_UTMP_NAME }.forEach { manager.setCookie(url.toString(), it.toString()) }
|
||||
|
||||
/**
|
||||
* Quick and dirty pattern to differentiate IP addresses from hostnames. This is an approximation
|
||||
@@ -221,8 +128,7 @@ object EhCookieStore : CookieJar {
|
||||
* 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.]+)")
|
||||
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.
|
||||
@@ -238,32 +144,19 @@ object EhCookieStore : CookieJar {
|
||||
return if (urlHost == domain) {
|
||||
true // As in 'example.com' matching 'example.com'.
|
||||
} else {
|
||||
urlHost.endsWith(domain!!) &&
|
||||
urlHost[urlHost.length - domain.length - 1] == '.' && !verifyAsIpAddress(
|
||||
urlHost,
|
||||
)
|
||||
urlHost.endsWith(domain!!) && urlHost[urlHost.length - domain.length - 1] == '.' && !verifyAsIpAddress(urlHost)
|
||||
}
|
||||
// As in 'example.com' matching 'www.example.com'.
|
||||
}
|
||||
|
||||
override fun loadForRequest(url: HttpUrl): List<Cookie> {
|
||||
val cookies = getCookies(url)
|
||||
val checkTips = domainMatch(url, EhUrl.DOMAIN_E)
|
||||
return if (checkTips) {
|
||||
val result: MutableList<Cookie> = ArrayList(cookies.size + 1)
|
||||
// Add all but skip some
|
||||
for (cookie in cookies) {
|
||||
val name = cookie.name
|
||||
if (KEY_CONTENT_WARNING == name) {
|
||||
continue
|
||||
}
|
||||
result.add(cookie)
|
||||
return get(url).run {
|
||||
if (checkTips) {
|
||||
filterNot { it.name == KEY_CONTENT_WARNING }.toMutableList().apply { add(sTipsCookie) }
|
||||
} else {
|
||||
this
|
||||
}
|
||||
// Add some
|
||||
result.add(sTipsCookie)
|
||||
Collections.unmodifiableList(result)
|
||||
} else {
|
||||
cookies
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.hippo.ehviewer.legacy
|
||||
|
||||
import arrow.fx.coroutines.release
|
||||
import arrow.fx.coroutines.resource
|
||||
import com.hippo.ehviewer.client.EhCookieStore
|
||||
import com.hippo.ehviewer.dao.Cookie
|
||||
import com.hippo.ehviewer.dao.CookiesDatabase
|
||||
import splitties.arch.room.roomDb
|
||||
import splitties.init.appCtx
|
||||
|
||||
private const val legacyCookiesDB = "okhttp3-cookie.db"
|
||||
|
||||
private fun Cookie.toOkHttp3Cookie(): okhttp3.Cookie {
|
||||
return okhttp3.Cookie.Builder().apply {
|
||||
name(name)
|
||||
value(value)
|
||||
expiresAt(expiresAt)
|
||||
if (hostOnly) hostOnlyDomain(domain) else domain(domain)
|
||||
path(path)
|
||||
if (secure) secure()
|
||||
if (httpOnly) httpOnly()
|
||||
}.build()
|
||||
}
|
||||
|
||||
suspend fun migrateCookies() {
|
||||
if (legacyCookiesDB !in appCtx.databaseList()) return
|
||||
resource {
|
||||
roomDb<CookiesDatabase>(legacyCookiesDB)
|
||||
} release {
|
||||
it.close()
|
||||
appCtx.deleteDatabase(legacyCookiesDB)
|
||||
} use { database ->
|
||||
database.cookiesDao().list().forEach {
|
||||
EhCookieStore.addCookie(it.toOkHttp3Cookie())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* 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.network
|
||||
|
||||
import android.content.Context
|
||||
import com.hippo.ehviewer.dao.Cookie
|
||||
import com.hippo.ehviewer.dao.CookiesDatabase
|
||||
import splitties.arch.room.roomDb
|
||||
import okhttp3.Cookie as OkHttpCookie
|
||||
|
||||
class CookieDatabase(context: Context) {
|
||||
private val cookiesList by lazy {
|
||||
val now = System.currentTimeMillis()
|
||||
db.cookiesDao().list().mapNotNull {
|
||||
it.takeUnless { !it.persistent || it.expiresAt <= now } ?: run {
|
||||
db.cookiesDao().delete(it)
|
||||
null
|
||||
}
|
||||
}.toMutableList()
|
||||
}
|
||||
private val db = roomDb<CookiesDatabase>("okhttp3-cookie.db")
|
||||
|
||||
val allCookies by lazy {
|
||||
hashMapOf<String, CookieSet>().also { map ->
|
||||
cookiesList.map { it.toOkHttp3Cookie() }.forEach {
|
||||
val set = map[it.domain] ?: CookieSet().apply { map[it.domain] = this }
|
||||
set.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun findCookieWithOkHttpCookies(cookie: OkHttpCookie): Cookie? {
|
||||
return cookiesList.find { it.name == cookie.name && it.domain == cookie.domain && it.value == cookie.value }
|
||||
}
|
||||
|
||||
fun add(cookie: OkHttpCookie) {
|
||||
val c = cookie.toCookie()
|
||||
c.id = db.cookiesDao().insert(c)
|
||||
cookiesList.add(c)
|
||||
}
|
||||
|
||||
fun update(from: OkHttpCookie, to: OkHttpCookie) {
|
||||
val origin = findCookieWithOkHttpCookies(from) ?: return
|
||||
val new = to.toCookie(origin.id)
|
||||
cookiesList.remove(origin)
|
||||
cookiesList.add(new)
|
||||
db.cookiesDao().update(new)
|
||||
}
|
||||
|
||||
fun remove(cookie: OkHttpCookie) {
|
||||
val origin = findCookieWithOkHttpCookies(cookie) ?: return
|
||||
db.cookiesDao().delete(origin)
|
||||
cookiesList.remove(origin)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
db.clearAllTables()
|
||||
cookiesList.clear()
|
||||
}
|
||||
}
|
||||
|
||||
fun Cookie.toOkHttp3Cookie(): OkHttpCookie {
|
||||
return OkHttpCookie.Builder().apply {
|
||||
name(name)
|
||||
value(value)
|
||||
expiresAt(expiresAt)
|
||||
if (hostOnly) hostOnlyDomain(domain) else domain(domain)
|
||||
path(path)
|
||||
if (secure) secure()
|
||||
if (httpOnly) httpOnly()
|
||||
}.build()
|
||||
}
|
||||
|
||||
private fun OkHttpCookie.toCookie(id: Long? = null): Cookie {
|
||||
return Cookie(
|
||||
name, value, expiresAt, domain, path, secure, httpOnly, persistent, hostOnly, id,
|
||||
)
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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.network
|
||||
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.HttpUrl
|
||||
|
||||
class CookieSet {
|
||||
private val map: MutableMap<Key, Cookie> = HashMap()
|
||||
|
||||
/**
|
||||
* Adds a cookie to this `CookieSet`.
|
||||
* Returns a previous cookie with
|
||||
* the same name, domain and path or `null`.
|
||||
*/
|
||||
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 `null`.
|
||||
*/
|
||||
fun remove(cookie: Cookie): Cookie? {
|
||||
return map.remove(Key(cookie))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cookies for the url. Fill `accepted` and `expired`.
|
||||
*/
|
||||
operator fun get(url: HttpUrl, accepted: MutableList<Cookie>, expired: MutableList<Cookie>) {
|
||||
val now = System.currentTimeMillis()
|
||||
val iterator = map.entries.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val cookie = iterator.next().value
|
||||
if (cookie.expiresAt <= now) {
|
||||
iterator.remove()
|
||||
expired.add(cookie)
|
||||
} else if (cookie.matches(url)) {
|
||||
accepted.add(cookie)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun get(name: String, domain: String, path: String) = map[Key(name, domain, path)]
|
||||
|
||||
internal data class Key(
|
||||
val name: String,
|
||||
val domain: String,
|
||||
val path: String,
|
||||
) {
|
||||
constructor(cookie: Cookie) : this(cookie.name, cookie.domain, cookie.path)
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ suspend fun postLogin() = coroutineScope {
|
||||
runCatching {
|
||||
// For the `star` cookie
|
||||
EhEngine.getNews(false)
|
||||
EhCookieStore.copyCookie(EhUrl.DOMAIN_E, EhUrl.DOMAIN_EX, EhCookieStore.KEY_STAR)
|
||||
EhCookieStore.copyNecessaryCookies()
|
||||
|
||||
// Sad panda check
|
||||
Settings.gallerySite = EhUrl.SITE_EX
|
||||
|
||||
@@ -21,8 +21,6 @@ import com.hippo.ehviewer.ui.SELECT_SITE_ROUTE_NAME
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@@ -34,63 +32,24 @@ fun WebviewSignInScreen() {
|
||||
val client = remember {
|
||||
object : AccompanistWebViewClient() {
|
||||
private var present = false
|
||||
fun parseCookies(url: HttpUrl?, cookieStrings: String?): List<Cookie> {
|
||||
if (cookieStrings == null) {
|
||||
return emptyList()
|
||||
}
|
||||
var cookies: MutableList<Cookie>? = null
|
||||
val pieces =
|
||||
cookieStrings.split(";".toRegex()).dropLastWhile { it.isEmpty() }
|
||||
.toTypedArray()
|
||||
for (piece in pieces) {
|
||||
val cookie = Cookie.parse(url!!, piece) ?: continue
|
||||
if (cookies == null) {
|
||||
cookies = ArrayList()
|
||||
}
|
||||
cookies.add(cookie)
|
||||
}
|
||||
return cookies ?: emptyList()
|
||||
}
|
||||
|
||||
fun addCookie(domain: String, cookie: Cookie) {
|
||||
EhCookieStore.addCookie(
|
||||
EhCookieStore.newCookie(
|
||||
cookie,
|
||||
domain,
|
||||
forcePersistent = true,
|
||||
forceLongLive = true,
|
||||
forceNotHostOnly = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPageFinished(view: WebView, url: String?) {
|
||||
if (present) {
|
||||
view.destroy()
|
||||
return
|
||||
}
|
||||
val httpUrl = url?.toHttpUrl() ?: return
|
||||
val cookieString = CookieManager.getInstance().getCookie(EhUrl.HOST_E)
|
||||
val cookies = parseCookies(httpUrl, cookieString)
|
||||
var getId = false
|
||||
var getHash = false
|
||||
for (cookie in cookies) {
|
||||
if (EhCookieStore.KEY_IPB_MEMBER_ID == cookie.name) {
|
||||
EhCookieStore.loadForRequest(EhUrl.HOST_E.toHttpUrl()).forEach {
|
||||
if (EhCookieStore.KEY_IPB_MEMBER_ID == it.name) {
|
||||
getId = true
|
||||
} else if (EhCookieStore.KEY_IPB_PASS_HASH == cookie.name) {
|
||||
} else if (EhCookieStore.KEY_IPB_PASS_HASH == it.name) {
|
||||
getHash = true
|
||||
}
|
||||
}
|
||||
if (getId && getHash) {
|
||||
present = true
|
||||
coroutineScope.launchIO {
|
||||
val canEx = withNonCancellableContext {
|
||||
cookies.forEach {
|
||||
addCookie(EhUrl.DOMAIN_EX, it)
|
||||
addCookie(EhUrl.DOMAIN_E, it)
|
||||
}
|
||||
postLogin()
|
||||
}
|
||||
val canEx = withNonCancellableContext { postLogin() }
|
||||
withUIContext { navController.navigate(if (canEx) SELECT_SITE_ROUTE_NAME else FINISH_ROUTE_NAME) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ fun EhScreen() {
|
||||
title = stringResource(id = R.string.account_name),
|
||||
summary = Settings.displayName ?: touristMode,
|
||||
) {
|
||||
val eCookies = EhCookieStore.getCookies(EhUrl.HOST_E.toHttpUrl())
|
||||
val exCookies = EhCookieStore.getCookies(EhUrl.HOST_EX.toHttpUrl())
|
||||
val eCookies = EhCookieStore.loadForRequest(EhUrl.HOST_E.toHttpUrl())
|
||||
val exCookies = EhCookieStore.loadForRequest(EhUrl.HOST_EX.toHttpUrl())
|
||||
var ipbMemberId: String? = null
|
||||
var ipbPassHash: String? = null
|
||||
var igneous: String? = null
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.hippo.ehviewer.ui.settings
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.webkit.CookieManager
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
@@ -12,16 +11,13 @@ import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.google.accompanist.web.WebView
|
||||
import com.google.accompanist.web.rememberWebViewState
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.client.EhCookieStore
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.ui.LocalNavController
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Composable
|
||||
@@ -52,16 +48,5 @@ fun MyTagsScreen() {
|
||||
}
|
||||
},
|
||||
)
|
||||
SideEffect {
|
||||
CookieManager.getInstance().apply {
|
||||
flush()
|
||||
removeAllCookies(null)
|
||||
removeSessionCookies(null)
|
||||
// Copy cookies from okhttp cookie store to CookieManager
|
||||
EhCookieStore.getCookies(url.toHttpUrl()).forEach {
|
||||
setCookie(url, it.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.hippo.ehviewer.ui.settings
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.webkit.CookieManager
|
||||
import android.webkit.WebView
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@@ -29,8 +28,6 @@ import com.hippo.ehviewer.client.EhCookieStore
|
||||
import com.hippo.ehviewer.client.EhCookieStore.KEY_SETTINGS_PROFILE
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.ui.LocalNavController
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
|
||||
private const val applyJs = "javascript:(function(){var apply = document.getElementById(\"apply\").children[0];apply.click();})();"
|
||||
@@ -81,33 +78,9 @@ fun UConfigScreen() {
|
||||
val applyTip = stringResource(id = R.string.apply_tip)
|
||||
LaunchedEffect(Unit) { snackbarHostState.showSnackbar(applyTip) }
|
||||
DisposableEffect(Unit) {
|
||||
CookieManager.getInstance().apply {
|
||||
flush()
|
||||
removeAllCookies(null)
|
||||
removeSessionCookies(null)
|
||||
// Copy cookies from okhttp cookie store to CookieManager
|
||||
EhCookieStore.getCookies(url.toHttpUrl()).forEach {
|
||||
setCookie(url, it.toString())
|
||||
}
|
||||
}
|
||||
onDispose {
|
||||
// Put cookies back to okhttp cookie store
|
||||
val cookiesString = CookieManager.getInstance().getCookie(url)
|
||||
if (cookiesString.isNotBlank()) {
|
||||
val hostUrl = EhUrl.host.toHttpUrl()
|
||||
launchIO {
|
||||
EhCookieStore.deleteCookie(hostUrl, KEY_SETTINGS_PROFILE)
|
||||
// The cookies saved in the uconfig page should not be shared between e and ex
|
||||
for (header in cookiesString.split(";".toRegex()).dropLastWhile { it.isEmpty() }) {
|
||||
Cookie.parse(hostUrl, header)?.let {
|
||||
EhCookieStore.addCookie(longLive(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EhCookieStore.deleteCookie(EhUrl.host.toHttpUrl(), KEY_SETTINGS_PROFILE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun longLive(cookie: Cookie) = Cookie.Builder().name(cookie.name).value(cookie.value).domain(cookie.domain).path(cookie.path).expiresAt(Long.MAX_VALUE).build()
|
||||
Reference in new issue
Block a user