From 64d72f6d103b1e199b27b6b0338989261b2f3624 Mon Sep 17 00:00:00 2001 From: Koen J Date: Tue, 25 Nov 2025 12:29:18 +0100 Subject: [PATCH 1/3] Implemented cookie support for httpimp. --- .../platformplayer/engine/packages/Libcurl.kt | 11 +-- .../engine/packages/PackageHttpImp.kt | 82 ++++++++----------- 2 files changed, 36 insertions(+), 57 deletions(-) diff --git a/app/src/main/java/com/futo/platformplayer/engine/packages/Libcurl.kt b/app/src/main/java/com/futo/platformplayer/engine/packages/Libcurl.kt index ed0b90bb..59c3504a 100644 --- a/app/src/main/java/com/futo/platformplayer/engine/packages/Libcurl.kt +++ b/app/src/main/java/com/futo/platformplayer/engine/packages/Libcurl.kt @@ -23,10 +23,7 @@ object Libcurl { var body: ByteArray? = null, var impersonateTarget: String = "chrome136", var useBuiltInHeaders: Boolean = true, - var timeoutMs: Int = 30_000, - var cookieJarPath: String? = null, - var sendCookies: Boolean = true, - var persistCookies: Boolean = true, + var timeoutMs: Int = 30_000 ) @Keep @@ -121,12 +118,6 @@ object Libcurl { if (slist != 0L) checkOK(ce_setopt_ptr(easy, CURLOPT.HTTPHEADER, slist)) } - if (req.sendCookies || req.persistCookies) { - val jar = (req.cookieJarPath ?: defaultCookieJarPath()) - if (req.sendCookies) checkOK(ce_setopt_str(easy, CURLOPT.COOKIEFILE, jar)) - if (req.persistCookies) checkOK(ce_setopt_str(easy, CURLOPT.COOKIEJAR, jar)) - } - val method = req.method if (!method.equals("GET", ignoreCase = true)) { checkOK(ce_setopt_str(easy, CURLOPT.CUSTOMREQUEST, method)) diff --git a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttpImp.kt b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttpImp.kt index 9dbae766..1d335918 100644 --- a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttpImp.kt +++ b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttpImp.kt @@ -1,5 +1,7 @@ package com.futo.platformplayer.engine.packages +import android.net.Uri +import androidx.core.net.toUri import com.caoccao.javet.annotations.V8Convert import com.caoccao.javet.annotations.V8Function import com.caoccao.javet.annotations.V8Property @@ -10,7 +12,9 @@ import com.caoccao.javet.values.V8Value import com.caoccao.javet.values.primitive.V8ValueString import com.caoccao.javet.values.reference.V8ValueTypedArray import com.curlbind.Libcurl +import com.futo.platformplayer.api.http.ManagedHttpClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig +import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.engine.internal.IV8Convertable @@ -43,8 +47,8 @@ class PackageHttpImp : V8Package { constructor(plugin: V8Plugin, config: IV8PluginConfig) : super(plugin) { _config = config - _packageClient = PackageHttpClient(this, withAuth = false) - _packageClientAuth = PackageHttpClient(this, withAuth = true) + _packageClient = PackageHttpClient(this, plugin.httpClient) + _packageClientAuth = PackageHttpClient(this, plugin.httpClientAuth) } fun cleanup() { @@ -95,7 +99,10 @@ class PackageHttpImp : V8Package { @V8Function fun newClient(withAuth: Boolean): PackageHttpClient { - val client = PackageHttpClient(this, withAuth) + val httpClient = if(withAuth) _plugin.httpClientAuth.clone() else _plugin.httpClient.clone(); + if(httpClient is JSHttpClient) + _plugin.registerHttpClient(httpClient); + val client = PackageHttpClient(this, httpClient) client.clientId()?.let { _clients[it] = client } return client } @@ -672,9 +679,6 @@ class PackageHttpImp : V8Package { @Transient private val _package: PackageHttpImp - @Transient - private val _withAuth: Boolean - val parentConfig: IV8PluginConfig get() = _package._config @@ -686,44 +690,21 @@ class PackageHttpImp : V8Package { @Volatile private var timeoutMs: Int = 30_000 - - @Volatile - private var sendCookies: Boolean = true - - @Volatile - private var updateCookies: Boolean = true - - @Volatile - private var allowNewCookies: Boolean = true - - @Volatile - private var cookieJarPath: String? = null - @Volatile private var impersonateTarget: String = "chrome136" @Volatile private var useBuiltInHeaders: Boolean = true + @Transient + private val _client: ManagedHttpClient; + @V8Property fun clientId(): String? = _clientId - constructor(pack: PackageHttpImp, withAuth: Boolean) : super() { + constructor(pack: PackageHttpImp, baseClient: ManagedHttpClient) : super() { _package = pack - _withAuth = withAuth - } - - private fun ensureCookieJarPath(): String { - val existing = cookieJarPath - if (existing != null) return existing - - val tmp = System.getProperty("java.io.tmpdir") ?: "/data/local/tmp" - val safeName = parentConfig.name.replace(Regex("[^a-zA-Z0-9._-]"), "_") - val fileName = - if (_withAuth) "imphttp.$safeName.auth.cookies.txt" else "imphttp.$safeName.cookies.txt" - val path = if (tmp.endsWith("/")) tmp + fileName else "$tmp/$fileName" - cookieJarPath = path - return path + _client = baseClient } @V8Function @@ -737,17 +718,18 @@ class PackageHttpImp : V8Package { @V8Function fun setDoApplyCookies(apply: Boolean) { - sendCookies = apply + if(_client is JSHttpClient) + _client.doApplyCookies = apply; } - @V8Function fun setDoUpdateCookies(update: Boolean) { - updateCookies = update + if(_client is JSHttpClient) + _client.doUpdateCookies = update; } - @V8Function fun setDoAllowNewCookies(allow: Boolean) { - allowNewCookies = allow + if(_client is JSHttpClient) + _client.doAllowNewCookies = allow; } @V8Function @@ -1060,18 +1042,23 @@ class PackageHttpImp : V8Package { private fun performCurl( method: String, url: String, - headers: Map, + hs: Map, //TODO: Why is this not a Map> bodyBytes: ByteArray?, impersonateTargetOverride: String? = null, useBuiltInHeadersOverride: Boolean? = null, timeoutMsOverride: Int? = null ): Libcurl.Response { - val jar = ensureCookieJarPath() - val finalImpersonateTarget = impersonateTargetOverride ?: this.impersonateTarget val finalUseBuiltInHeaders = useBuiltInHeadersOverride ?: this.useBuiltInHeaders val finalTimeoutMs = timeoutMsOverride ?: this.timeoutMs + val uri = url.toUri() + val headers = hs.toMutableMap() + val client = _client + if (client is JSHttpClient) { + client.applyHeaders(uri, headers, _client.isLoggedIn, true) + } + val req = Libcurl.Request( url = url, method = method, @@ -1079,12 +1066,13 @@ class PackageHttpImp : V8Package { body = bodyBytes, impersonateTarget = finalImpersonateTarget, useBuiltInHeaders = finalUseBuiltInHeaders, - timeoutMs = finalTimeoutMs, - cookieJarPath = jar, - sendCookies = sendCookies, - persistCookies = updateCookies && allowNewCookies + timeoutMs = finalTimeoutMs ) - return Libcurl.perform(req) + val resp = Libcurl.perform(req) + if (client is JSHttpClient) { + client.processRequest(method, resp.status, uri, resp.headers) + } + return resp } private fun executeRequest( From 396e9f9f4338611438fe74de86adfc77942ce8eb Mon Sep 17 00:00:00 2001 From: Koen J Date: Tue, 25 Nov 2025 12:44:57 +0100 Subject: [PATCH 2/3] Implemented support for isUrlAllowed in HttpImp. --- .../api/media/platforms/js/internal/JSHttpClient.kt | 1 + .../platformplayer/engine/packages/PackageHttpImp.kt | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt index 33f71656..f1f9d5ee 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt @@ -23,6 +23,7 @@ import java.util.UUID class JSHttpClient : ManagedHttpClient { private val _jsClient: JSClient?; private val _jsConfig: SourcePluginConfig?; + val config get() = _jsConfig private val _auth: SourceAuth?; private val _captcha: SourceCaptchaData?; diff --git a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttpImp.kt b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttpImp.kt index 1d335918..edb4ca75 100644 --- a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttpImp.kt +++ b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttpImp.kt @@ -17,6 +17,8 @@ import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.engine.V8Plugin +import com.futo.platformplayer.engine.exceptions.ScriptException +import com.futo.platformplayer.engine.exceptions.ScriptImplementationException import com.futo.platformplayer.engine.internal.IV8Convertable import com.futo.platformplayer.engine.internal.V8BindObject import com.futo.platformplayer.logging.Logger @@ -1048,13 +1050,19 @@ class PackageHttpImp : V8Package { useBuiltInHeadersOverride: Boolean? = null, timeoutMsOverride: Int? = null ): Libcurl.Response { + val client = _client + if (client is JSHttpClient) { + if (!(client.config?.isUrlAllowed(url) ?: false)) { + throw Exception( "Attempted to access non-whitelisted url: $url\nAdd it to your config"); + } + } + val finalImpersonateTarget = impersonateTargetOverride ?: this.impersonateTarget val finalUseBuiltInHeaders = useBuiltInHeadersOverride ?: this.useBuiltInHeaders val finalTimeoutMs = timeoutMsOverride ?: this.timeoutMs val uri = url.toUri() val headers = hs.toMutableMap() - val client = _client if (client is JSHttpClient) { client.applyHeaders(uri, headers, _client.isLoggedIn, true) } From b08a79b7cbf3455722487ced88354a4f9c1cd789 Mon Sep 17 00:00:00 2001 From: Koen J Date: Tue, 25 Nov 2025 14:13:06 +0100 Subject: [PATCH 3/3] Fixed plugin config missing from httpclient. --- .../platformplayer/api/media/platforms/js/JSClient.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt index 1783ed38..1718acb3 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt @@ -153,8 +153,8 @@ open class JSClient : IPlatformClient { _captcha = descriptor.getCaptchaData(); flags = descriptor.flags.toTypedArray(); - _httpClient = JSHttpClient(this, null, _captcha); - _httpClientAuth = JSHttpClient(this, _auth, _captcha); + _httpClient = JSHttpClient(this, null, _captcha, config); + _httpClientAuth = JSHttpClient(this, _auth, _captcha, config); _plugin = V8Plugin(context, descriptor.config, null, _httpClient, _httpClientAuth); _plugin.withDependency(context, "scripts/polyfil.js"); _plugin.withDependency(context, "scripts/source.js"); @@ -186,8 +186,8 @@ open class JSClient : IPlatformClient { _captcha = descriptor.getCaptchaData(); flags = descriptor.flags.toTypedArray(); - _httpClient = JSHttpClient(this, null, _captcha); - _httpClientAuth = JSHttpClient(this, _auth, _captcha); + _httpClient = JSHttpClient(this, null, _captcha, config); + _httpClientAuth = JSHttpClient(this, _auth, _captcha, config); _plugin = V8Plugin(context, descriptor.config, script, _httpClient, _httpClientAuth); _plugin.withDependency(context, "scripts/polyfil.js"); _plugin.withDependency(context, "scripts/source.js");